From 07bd4346647122c57616f94f6b4476f6c07206c3 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Thu, 27 Feb 2025 10:34:00 -0800 Subject: [PATCH 01/38] CI: Update release branch to 1.0.32 --- .github/workflows/auto-merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 8aa94ede06..08721d5751 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v2 with: fetch-depth: 0 - ref: 1.0.31-release + ref: 1.0.32-release - name: merge commits from main to release branch run: | From 8dd6826067711fdb33db7de944c911b5f8accc14 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Tue, 4 Mar 2025 15:11:10 -0800 Subject: [PATCH 02/38] KSValueArgumentImpl: compute value lazily --- .../devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt index ed72a9930d..0be29b14ce 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueArgumentImpl.kt @@ -40,7 +40,9 @@ class KSValueArgumentImpl private constructor( override val isSpread: Boolean = false - override val value: Any? = namedAnnotationValue.expression.toValue() + override val value: Any? by lazy { + namedAnnotationValue.expression.toValue() + } override val annotations: Sequence = emptySequence() From 1957ba08adb2a6d28184da69faeff6872c47b918 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 5 Mar 2025 10:11:34 -0800 Subject: [PATCH 03/38] Update actions/cache to v4. --- .github/workflows/auto-merge.yml | 4 ++-- .github/workflows/main.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 08721d5751..b8b21b7841 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -50,7 +50,7 @@ jobs: # Build cache - name: Cache Gradle Cache - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}-${{ hashFiles('**/gradle.properties') }} @@ -58,7 +58,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Cache gradle wrapper - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c935d14e52..fefda10032 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,7 +46,7 @@ jobs: # Build cache - name: Cache Gradle Cache - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}-${{ hashFiles('**/gradle.properties') }} @@ -54,7 +54,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Cache gradle wrapper - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3cd0deef4a..1319c6b512 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: # Build cache - name: Cache Gradle Cache - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}-${{ hashFiles('**/gradle.properties') }} @@ -33,7 +33,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Cache gradle wrapper - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} From 5b2fd3c79b60f99ca643f362e564659176d900ac Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Mon, 3 Mar 2025 14:34:04 -0800 Subject: [PATCH 04/38] Replace createSearchScopeByLibraryRoots by LibraryRootsSearchScope --- .../ksp/impl/KotlinSymbolProcessing.kt | 4 +- .../ksp/standalone/KspLibraryModuleBuilder.kt | 86 +++++++++++++++++-- .../testData/annotationWithDefault.kt | 4 +- .../testData/annotationWithDefaultValues.kt | 4 +- 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt index f3e6715b5d..3fd372ed67 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt @@ -37,6 +37,7 @@ import com.google.devtools.ksp.standalone.IncrementalKotlinDeclarationProviderFa import com.google.devtools.ksp.standalone.IncrementalKotlinPackageProviderFactory import com.google.devtools.ksp.standalone.KspStandaloneDirectInheritorsProvider import com.google.devtools.ksp.standalone.buildKspLibraryModule +import com.google.devtools.ksp.standalone.buildKspSdkModule import com.google.devtools.ksp.standalone.buildKspSourceModule import com.google.devtools.ksp.symbol.KSFile import com.google.devtools.ksp.symbol.KSNode @@ -89,7 +90,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLSealedInheritorsProvider import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleBuilder import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleProviderBuilder -import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtSdkModule import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreApplicationEnvironmentMode import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment @@ -200,7 +200,7 @@ class KotlinSymbolProcessing( ) compilerConfig.get(JVMConfigurationKeys.JDK_HOME)?.let { jdkHome -> addRegularDependency( - buildKtSdkModule { + buildKspSdkModule { this.platform = platform addBinaryRootsFromJdkHome(jdkHome.toPath(), isJre = false) libraryName = "JDK for $moduleName" diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspLibraryModuleBuilder.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspLibraryModuleBuilder.kt index 862e9a7d0c..5deb4f9694 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspLibraryModuleBuilder.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspLibraryModuleBuilder.kt @@ -18,30 +18,42 @@ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") package com.google.devtools.ksp.standalone -import com.intellij.psi.search.ProjectScope +import com.intellij.openapi.module.Module +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analysis.api.KaExperimentalApi +import org.jetbrains.kotlin.analysis.api.KaImplementationDetail +import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils import org.jetbrains.kotlin.analysis.api.projectStructure.KaLibraryModule import org.jetbrains.kotlin.analysis.api.projectStructure.KaLibrarySourceModule +import org.jetbrains.kotlin.analysis.api.standalone.base.projectStructure.StandaloneProjectFactory import org.jetbrains.kotlin.analysis.project.structure.builder.KtBinaryModuleBuilder import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleBuilderDsl import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleProviderBuilder import org.jetbrains.kotlin.analysis.project.structure.impl.KaLibraryModuleImpl import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment +import java.nio.file.Path import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract @KtModuleBuilderDsl -class KspLibraryModuleBuilder( +open class KspLibraryModuleBuilder( private val kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment ) : KtBinaryModuleBuilder() { public lateinit var libraryName: String public var librarySources: KaLibrarySourceModule? = null + override fun build(): KaLibraryModule = build(isSdk = false) + @OptIn(KaExperimentalApi::class) - override fun build(): KaLibraryModule { + fun build(isSdk: Boolean): KaLibraryModule { val binaryRoots = getBinaryRoots() - val contentScope = ProjectScope.getLibrariesScope(kotlinCoreProjectEnvironment.project) + val binaryVirtualFiles = getBinaryVirtualFiles() + val contentScope = LibraryRootsSearchScope( + StandaloneProjectFactory.getVirtualFilesForLibraryRoots(binaryRoots, kotlinCoreProjectEnvironment) + + binaryVirtualFiles + ) return KaLibraryModuleImpl( directRegularDependencies, directDependsOnDependencies, @@ -50,10 +62,10 @@ class KspLibraryModuleBuilder( platform, kotlinCoreProjectEnvironment.project, binaryRoots, - emptyList(), + binaryVirtualFiles, libraryName, librarySources, - false + isSdk ) } } @@ -65,3 +77,65 @@ inline fun KtModuleProviderBuilder.buildKspLibraryModule(init: KspLibraryModuleB } return KspLibraryModuleBuilder(kotlinCoreProjectEnvironment).apply(init).build() } + +internal class SimpleTrie(paths: List) { + class TrieNode { + var isTerminal: Boolean = false + } + + val root = TrieNode() + + private val m = mutableMapOf, TrieNode>().apply { + paths.forEach { path -> + var p = root + for (d in path.trim('/').split('/')) { + p = getOrPut(Pair(p, d)) { TrieNode() } + } + p.isTerminal = true + } + } + + fun contains(s: String): Boolean { + var p = root + for (d in s.trim('/').split('/')) { + p = m.get(Pair(p, d))?.also { + if (it.isTerminal) + return true + } ?: return false + } + return false + } +} + +internal class LibraryRootsSearchScope(roots: List) : GlobalSearchScope() { + val trie: SimpleTrie = SimpleTrie(roots.map { it.path }) + + override fun contains(file: VirtualFile): Boolean { + return trie.contains(file.path) + } + + override fun isSearchInModuleContent(aModule: Module): Boolean = false + + override fun isSearchInLibraries(): Boolean = true +} + +@KtModuleBuilderDsl +public class KspSdkModuleBuilder( + kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment +) : KspLibraryModuleBuilder(kotlinCoreProjectEnvironment) { + @OptIn(KaImplementationDetail::class) + public fun addBinaryRootsFromJdkHome(jdkHome: Path, isJre: Boolean) { + val jdkRoots = LibraryUtils.findClassesFromJdkHome(jdkHome, isJre) + addBinaryRoots(jdkRoots) + } + + override fun build(): KaLibraryModule = build(isSdk = true) +} + +@OptIn(ExperimentalContracts::class) +public inline fun KtModuleProviderBuilder.buildKspSdkModule(init: KspSdkModuleBuilder.() -> Unit): KaLibraryModule { + contract { + callsInPlace(init, InvocationKind.EXACTLY_ONCE) + } + return KspSdkModuleBuilder(kotlinCoreProjectEnvironment).apply(init).build() +} diff --git a/kotlin-analysis-api/testData/annotationWithDefault.kt b/kotlin-analysis-api/testData/annotationWithDefault.kt index aed1f0e5cd..5d4d6624c8 100644 --- a/kotlin-analysis-api/testData/annotationWithDefault.kt +++ b/kotlin-analysis-api/testData/annotationWithDefault.kt @@ -22,8 +22,8 @@ // JavaAnnotation2 -> y:y-kotlin:false,x:x-kotlin:false,z:z-default:true // KotlinAnnotation2 -> y:y-kotlin:false,x:x-kotlin:false,z:z-default:true,kotlinEnumVal:KotlinEnum.VALUE_1:true // KotlinAnnotationLib -> a:debugLibKt:false,b:defaultInLib:true,kClassValue:OtherKotlinAnnotation:true,topLevelProp:bar:true -// JavaAnnotationWithDefaults -> stringVal:foo:true,stringArrayVal:[x, y]:true,typeVal:HashMap<(Any..Any?), (Any..Any?)>:true,typeArrayVal:[LinkedHashMap<(Any..Any?), (Any..Any?)>]:true,intVal:3:true,intArrayVal:[1, 3, 5]:true,enumVal:JavaEnum.DEFAULT:true,enumArrayVal:[JavaEnum.VAL1, JavaEnum.VAL2]:true,localEnumVal:LocalEnum.LOCAL1:true,otherAnnotationVal:@OtherAnnotation:true,otherAnnotationArrayVal:[@OtherAnnotation]:true,kotlinAnnotationLibVal:@OtherKotlinAnnotation:true -// KotlinAnnotationWithDefaults -> stringVal:foo:false,stringArrayVal:[x, y]:true,typeVal:HashMap<(Any..Any?), (Any..Any?)>:true,typeArrayVal:[LinkedHashMap<(Any..Any?), (Any..Any?)>]:true,intVal:3:true,intArrayVal:[1, 3, 5]:true,enumVal:JavaEnum.DEFAULT:true,enumArrayVal:[JavaEnum.VAL1, JavaEnum.VAL2]:true,otherAnnotationVal:@OtherAnnotation:true,otherAnnotationArrayVal:[@OtherAnnotation]:true,kotlinAnnotationLibVal:@OtherKotlinAnnotation:true +// JavaAnnotationWithDefaults -> stringVal:foo:true,stringArrayVal:[x, y]:true,typeVal:HashMap<*, *>:true,typeArrayVal:[LinkedHashMap<*, *>]:true,intVal:3:true,intArrayVal:[1, 3, 5]:true,enumVal:JavaEnum.DEFAULT:true,enumArrayVal:[JavaEnum.VAL1, JavaEnum.VAL2]:true,localEnumVal:LocalEnum.LOCAL1:true,otherAnnotationVal:@OtherAnnotation:true,otherAnnotationArrayVal:[@OtherAnnotation]:true,kotlinAnnotationLibVal:@OtherKotlinAnnotation:true +// KotlinAnnotationWithDefaults -> stringVal:foo:false,stringArrayVal:[x, y]:true,typeVal:HashMap<*, *>:true,typeArrayVal:[LinkedHashMap<*, *>]:true,intVal:3:true,intArrayVal:[1, 3, 5]:true,enumVal:JavaEnum.DEFAULT:true,enumArrayVal:[JavaEnum.VAL1, JavaEnum.VAL2]:true,otherAnnotationVal:@OtherAnnotation:true,otherAnnotationArrayVal:[@OtherAnnotation]:true,kotlinAnnotationLibVal:@OtherKotlinAnnotation:true // KotlinAnnotation -> a:debugKt:false,b:default:true,kClassValue:Array>:true,topLevelProp:foo:true,companionProp:companion:true // JavaAnnotation -> debug:debugJava2:false,withDefaultValue:OK:true,nested:@Nested:true // JavaAnnotation2 -> y:y-java:false,x:x-java:false,z:z-default:true diff --git a/kotlin-analysis-api/testData/annotationWithDefaultValues.kt b/kotlin-analysis-api/testData/annotationWithDefaultValues.kt index 5dfabedbe3..0f76a9aacf 100644 --- a/kotlin-analysis-api/testData/annotationWithDefaultValues.kt +++ b/kotlin-analysis-api/testData/annotationWithDefaultValues.kt @@ -22,8 +22,8 @@ // JavaAnnotation2 -> x:x-default,y:y-default,z:z-default // KotlinAnnotation2 -> y:y-default,z:z-default,kotlinEnumVal:KotlinEnum.VALUE_1 // KotlinAnnotationLib -> b:defaultInLib,kClassValue:OtherKotlinAnnotation,topLevelProp:bar -// JavaAnnotationWithDefaults -> stringVal:foo,stringArrayVal:[x, y],typeVal:HashMap<(Any..Any?), (Any..Any?)>,typeArrayVal:[LinkedHashMap<(Any..Any?), (Any..Any?)>],intVal:3,intArrayVal:[1, 3, 5],enumVal:JavaEnum.DEFAULT,enumArrayVal:[JavaEnum.VAL1, JavaEnum.VAL2],localEnumVal:LocalEnum.LOCAL1,otherAnnotationVal:@OtherAnnotation,otherAnnotationArrayVal:[@OtherAnnotation],kotlinAnnotationLibVal:@OtherKotlinAnnotation -// KotlinAnnotationWithDefaults -> stringVal:foo,stringArrayVal:[x, y],typeVal:HashMap<(Any..Any?), (Any..Any?)>,typeArrayVal:[LinkedHashMap<(Any..Any?), (Any..Any?)>],intVal:3,intArrayVal:[1, 3, 5],enumVal:JavaEnum.DEFAULT,enumArrayVal:[JavaEnum.VAL1, JavaEnum.VAL2],otherAnnotationVal:@OtherAnnotation,otherAnnotationArrayVal:[@OtherAnnotation],kotlinAnnotationLibVal:@OtherKotlinAnnotation +// JavaAnnotationWithDefaults -> stringVal:foo,stringArrayVal:[x, y],typeVal:HashMap<*, *>,typeArrayVal:[LinkedHashMap<*, *>],intVal:3,intArrayVal:[1, 3, 5],enumVal:JavaEnum.DEFAULT,enumArrayVal:[JavaEnum.VAL1, JavaEnum.VAL2],localEnumVal:LocalEnum.LOCAL1,otherAnnotationVal:@OtherAnnotation,otherAnnotationArrayVal:[@OtherAnnotation],kotlinAnnotationLibVal:@OtherKotlinAnnotation +// KotlinAnnotationWithDefaults -> stringVal:foo,stringArrayVal:[x, y],typeVal:HashMap<*, *>,typeArrayVal:[LinkedHashMap<*, *>],intVal:3,intArrayVal:[1, 3, 5],enumVal:JavaEnum.DEFAULT,enumArrayVal:[JavaEnum.VAL1, JavaEnum.VAL2],otherAnnotationVal:@OtherAnnotation,otherAnnotationArrayVal:[@OtherAnnotation],kotlinAnnotationLibVal:@OtherKotlinAnnotation // KotlinAnnotation -> b:default,kClassValue:Array>,topLevelProp:foo,companionProp:companion // JavaAnnotation -> withDefaultValue:OK,stringArrayParam:[3, 5, 7],typeVal:HashMap<*, *>,nested:@Nested // JavaAnnotation2 -> x:x-default,y:y-default,z:z-default From 88e9e6221af7007962177be9069541834f73434c Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 5 Mar 2025 14:20:05 -0800 Subject: [PATCH 05/38] Update github actions permissions for auto-merger which was switched to read-only recently. --- .github/workflows/auto-merge.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index b8b21b7841..88896c493d 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -14,6 +14,9 @@ jobs: # The type of runner that the job will run on runs-on: ubuntu-latest + permissions: + contents: write + steps: # Checkout - uses: actions/checkout@v2 From fb6f7bfac014e2e459fedb63922b7fd46b27f289 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 5 Mar 2025 15:16:22 -0800 Subject: [PATCH 06/38] KSFileJavaImpl: compuate packageName and location lazily They are expensive according to the profiler. --- .../devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt index a46934e983..fd75d633b2 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt @@ -34,7 +34,9 @@ class KSFileJavaImpl private constructor(val psi: PsiJavaFile) : KSFile, Deferra fun getCached(psi: PsiJavaFile) = cache.getOrPut(psi) { KSFileJavaImpl(psi) } } - override val packageName: KSName = KSNameImpl.getCached(psi.packageName) + override val packageName: KSName by lazy { + KSNameImpl.getCached(psi.packageName) + } override val fileName: String = psi.name @@ -50,7 +52,9 @@ class KSFileJavaImpl private constructor(val psi: PsiJavaFile) : KSFile, Deferra override val origin: Origin = Origin.JAVA - override val location: Location = psi.toLocation() + override val location: Location by lazy { + psi.toLocation() + } override val parent: KSNode? = null From 124675863859f2451339df5d7d87c50ba6cd6fcb Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 5 Mar 2025 15:16:58 -0800 Subject: [PATCH 07/38] Simplify KSTypeImpl.getCached --- .../google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt index 84b985354d..a3444b9b3b 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeImpl.kt @@ -17,7 +17,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin -import com.google.devtools.ksp.common.IdKeyPair +import com.google.devtools.ksp.common.IdKey import com.google.devtools.ksp.common.KSObjectCache import com.google.devtools.ksp.common.errorTypeOnInconsistentArguments import com.google.devtools.ksp.impl.ResolverAAImpl @@ -31,14 +31,13 @@ import com.google.devtools.ksp.symbol.KSType import com.google.devtools.ksp.symbol.KSTypeArgument import com.google.devtools.ksp.symbol.Nullability import org.jetbrains.kotlin.analysis.api.KaImplementationDetail -import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotationList import org.jetbrains.kotlin.analysis.api.impl.base.types.KaBaseStarTypeProjection import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.types.* class KSTypeImpl private constructor(internal val type: KaType) : KSType { - companion object : KSObjectCache, KSTypeImpl>() { - fun getCached(type: KaType): KSTypeImpl = cache.getOrPut(IdKeyPair(type, type.annotations)) { + companion object : KSObjectCache, KSTypeImpl>() { + fun getCached(type: KaType): KSTypeImpl = cache.getOrPut(IdKey(type)) { KSTypeImpl(type) } } From 93bceadd1dc55d0c55b3532324d2557e9415854c Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 5 Mar 2025 15:35:51 -0800 Subject: [PATCH 08/38] SymbolCollector: do not skip private declarations Computing visibility is expensive in KSP2. The extra entries won't affect dirty set calculation. --- .../com/google/devtools/ksp/common/IncrementalContextBase.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/common/IncrementalContextBase.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/common/IncrementalContextBase.kt index f94d7b5661..83fde1db14 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/common/IncrementalContextBase.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/common/IncrementalContextBase.kt @@ -17,7 +17,6 @@ package com.google.devtools.ksp.common -import com.google.devtools.ksp.isPrivate import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSDeclaration import com.google.devtools.ksp.symbol.KSDeclarationContainer @@ -35,9 +34,6 @@ object SymbolCollector : KSDefaultVisitor<(LookupSymbolWrapper) -> Unit, Unit>() override fun defaultHandler(node: KSNode, data: (LookupSymbolWrapper) -> Unit) = Unit override fun visitDeclaration(declaration: KSDeclaration, data: (LookupSymbolWrapper) -> Unit) { - if (declaration.isPrivate()) - return - val name = declaration.simpleName.asString() val scope = declaration.qualifiedName?.asString()?.let { it.substring(0, Math.max(it.length - name.length - 1, 0)) } From 1e8492b7f7237a8bfcb0d5be9b68424906b5dc65 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Thu, 6 Mar 2025 15:02:06 -0800 Subject: [PATCH 09/38] Fix validity check of annotations on properties Annotations on properties may come from corresponding parameters if they are declared in constructors. They may not be valid on properties and need to be filtered out. The previous implementation incorrectly excludes all annotations with @Target(AnnotationTarget.VALUE_PARAMETER), while what should be excluded are the ones with @Target and without @Target(AnnotationTarget.PROPERTY). --- .../ksp/test/KSPCompilerPluginTest.kt | 6 +++ .../kotlin/KSPropertyDeclarationImpl.kt | 26 ++++++------ .../com/google/devtools/ksp/test/KSPAATest.kt | 6 +++ .../processor/AnnotationTargetsProcessor.kt | 39 ++++++++++++++++++ test-utils/testData/api/annotationTargets.kt | 40 +++++++++++++++++++ 5 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 test-utils/src/main/kotlin/com/google/devtools/ksp/processor/AnnotationTargetsProcessor.kt create mode 100644 test-utils/testData/api/annotationTargets.kt diff --git a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt index c8794fbff5..6a7a1df319 100644 --- a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt +++ b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/KSPCompilerPluginTest.kt @@ -80,6 +80,12 @@ class KSPCompilerPluginTest : AbstractKSPCompilerPluginTest() { runTest("../test-utils/testData/api/annotationsRepeatable.kt") } + @TestMetadata("annotationTargets.kt") + @Test + fun testAnnotationTargets() { + runTest("../test-utils/testData/api/annotationTargets.kt") + } + @TestMetadata("annotationWithArbitraryClassValue.kt") @Test fun testAnnotationWithArbitraryClassValue() { diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyDeclarationImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyDeclarationImpl.kt index f0a58865e8..00e44a8dbf 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyDeclarationImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyDeclarationImpl.kt @@ -64,21 +64,13 @@ class KSPropertyDeclarationImpl private constructor(internal val ktPropertySymbo .map { KSAnnotationResolvedImpl.getCached(it, this) } .plus( if (ktPropertySymbol.isFromPrimaryConstructor) { - (parentDeclaration as? KSClassDeclaration)?.primaryConstructor?.parameters - ?.singleOrNull { it.name == simpleName }?.annotations ?: emptySequence() + (parentDeclaration as? KSClassDeclaration)?.primaryConstructor?.parameters?.singleOrNull { + it.name == simpleName + }?.annotations?.filter { it.isValidOnProperty() } ?: emptySequence() } else { emptySequence() } - ).filterNot { valueParameterAnnotation -> - 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? KSClassDeclaration)?.qualifiedName - ?.asString() == "kotlin.annotation.AnnotationTarget.VALUE_PARAMETER" - } ?: false - } - }.plus( + ).plus( // TODO: optimize for psi ktPropertySymbol.backingFieldSymbol?.annotations ?.map { KSAnnotationResolvedImpl.getCached(it, this@KSPropertyDeclarationImpl) } ?: emptyList() @@ -203,6 +195,7 @@ internal fun KaAnnotation.isUseSiteTargetAnnotation(): Boolean { it == AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER } ?: false } + internal fun KtAnnotationEntry.isUseSiteTargetAnnotation(): Boolean { return this.useSiteTarget?.getAnnotationUseSiteTarget()?.let { it == AnnotationUseSiteTarget.PROPERTY_GETTER || @@ -212,6 +205,7 @@ internal fun KtAnnotationEntry.isUseSiteTargetAnnotation(): Boolean { it == AnnotationUseSiteTarget.FIELD } ?: false } + internal fun KaPropertySymbol.toModifiers(): Set { val result = mutableSetOf() if (visibility != KaSymbolVisibility.PACKAGE_PRIVATE) { @@ -239,3 +233,11 @@ internal fun KaPropertySymbol.toModifiers(): Set { } return result } + +internal fun KSAnnotation.isValidOnProperty(): Boolean = + annotationType.resolve().declaration.annotations.none { metaAnnotation -> + metaAnnotation.annotationType.resolve().declaration.qualifiedName?.asString() == "kotlin.annotation.Target" && + (metaAnnotation.arguments.singleOrNull()?.value as? ArrayList<*>)?.none { + (it as? KSClassDeclaration)?.qualifiedName?.asString() == "kotlin.annotation.AnnotationTarget.PROPERTY" + } ?: false + } diff --git a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt index 84ed95c61a..fbf1507c0e 100644 --- a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt +++ b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt @@ -88,6 +88,12 @@ class KSPAATest : AbstractKSPAATest() { runTest("../kotlin-analysis-api/testData/annotationsRepeatable.kt") } + @TestMetadata("annotationTargets.kt") + @Test + fun testAnnotationTargets() { + runTest("../test-utils/testData/api/annotationTargets.kt") + } + @TestMetadata("annotationWithArbitraryClassValue.kt") @Test fun testAnnotationWithArbitraryClassValue() { diff --git a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/AnnotationTargetsProcessor.kt b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/AnnotationTargetsProcessor.kt new file mode 100644 index 0000000000..2d035bc3a8 --- /dev/null +++ b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/AnnotationTargetsProcessor.kt @@ -0,0 +1,39 @@ +/* + * 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.processor + +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.symbol.* + +class AnnotationTargetsProcessor : AbstractTestProcessor() { + val results = mutableListOf() + + override fun process(resolver: Resolver): List { + val myClassName = resolver.getKSNameFromString("com.example.MyClass") + val myClass: KSClassDeclaration = resolver.getClassDeclarationByName(myClassName)!! + val propForLib = myClass.getAllProperties().single { it.simpleName.asString() == "propForLib" } + val propForSrc = myClass.getAllProperties().single { it.simpleName.asString() == "propForSrc" } + results.add("$propForLib: ${propForLib.annotations.map { it.shortName.asString() }.toList()}") + results.add("$propForSrc: ${propForSrc.annotations.map { it.shortName.asString() }.toList()}") + return emptyList() + } + + override fun toResult(): List { + return results + } +} diff --git a/test-utils/testData/api/annotationTargets.kt b/test-utils/testData/api/annotationTargets.kt new file mode 100644 index 0000000000..99ccb4e710 --- /dev/null +++ b/test-utils/testData/api/annotationTargets.kt @@ -0,0 +1,40 @@ +/* + * 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. + */ + +// TEST PROCESSOR: AnnotationTargetsProcessor +// EXPECTED: +// propForLib: [MyAnnotationInLib] +// propForSrc: [MyAnnotationInSrc] +// END +// MODULE: Anno +// FILE: com/example/MyAnnotation.kt +package com.example + +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER) +public annotation class MyAnnotationInLib + +// MODULE: main(Anno) +// FILE: com/exampel/MyClass.kt +package com.example + +@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER) +public annotation class MyAnnotationInSrc + +class MyClass { + @MyAnnotationInLib lateinit var propForLib: String + @MyAnnotationInSrc lateinit var propForSrc: String +} From f2be649306383551857d30899764d4a55cfbc7f1 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Fri, 7 Mar 2025 15:06:18 -0800 Subject: [PATCH 10/38] Store collected symbols by annotations Previous implementation needs to scan through all symbols with annotations each time getSymbolsWithAnnotation is called. Let's just store the symbols in a map and index by annotations. --- .../visitor/CollectAnnotatedSymbolsVisitor.kt | 3 +- .../devtools/ksp/impl/ResolverAAImpl.kt | 39 ++++++++++++------- kotlin-analysis-api/testData/locations.kt | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/common-util/src/main/kotlin/com/google/devtools/ksp/common/visitor/CollectAnnotatedSymbolsVisitor.kt b/common-util/src/main/kotlin/com/google/devtools/ksp/common/visitor/CollectAnnotatedSymbolsVisitor.kt index 9cb3ec5b98..f9063b08db 100644 --- a/common-util/src/main/kotlin/com/google/devtools/ksp/common/visitor/CollectAnnotatedSymbolsVisitor.kt +++ b/common-util/src/main/kotlin/com/google/devtools/ksp/common/visitor/CollectAnnotatedSymbolsVisitor.kt @@ -44,8 +44,7 @@ class CollectAnnotatedSymbolsVisitor(private val inDepth: Boolean) : KSVisitorVo } override fun visitTypeAlias(typeAlias: KSTypeAlias, data: Unit) { - if (typeAlias.annotations.any()) - symbols.add(typeAlias) + visitAnnotated(typeAlias, data) } override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) { diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt index 29772cc156..20801f4023 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt @@ -544,15 +544,10 @@ class ResolverAAImpl( } val realAnnotationName = expandedIfAlias ?: annotationName - fun checkAnnotated(annotated: KSAnnotated): Boolean { - return annotated.annotations.any { - val kaType = (it.annotationType.resolve() as? KSTypeImpl)?.type ?: return@any false - kaType.fullyExpand().symbol?.classId?.asFqNameString() == realAnnotationName - } - } - - val newSymbols = if (inDepth) newAnnotatedSymbolsWithLocals else newAnnotatedSymbols - return (newSymbols + deferredSymbolsRestored).asSequence().filter(::checkAnnotated) + return if (inDepth) + annotationToSymbolsMapWithLocals[realAnnotationName]?.asSequence() ?: emptySequence() + else + annotationToSymbolsMap[realAnnotationName]?.asSequence() ?: emptySequence() } private fun collectAnnotatedSymbols(inDepth: Boolean): Collection { @@ -565,16 +560,30 @@ class ResolverAAImpl( return visitor.symbols } - private val deferredSymbolsRestored: Set by lazy { - deferredSymbols.values.flatten().mapNotNull { it.restore() }.toSet() + private val annotationToSymbolsMap: Map> by lazy { + mapAnnotatedSymbols(false) + } + + private val annotationToSymbolsMapWithLocals: Map> by lazy { + mapAnnotatedSymbols(true) } - private val newAnnotatedSymbols: Collection by lazy { - collectAnnotatedSymbols(false) + private fun mapAnnotatedSymbols(inDepth: Boolean): Map> { + val newSymbols = collectAnnotatedSymbols(inDepth) + val withDeferred = newSymbols + deferredSymbolsRestored + return mutableMapOf>().apply { + withDeferred.forEach { annotated -> + for (annotation in annotated.annotations) { + val kaType = (annotation.annotationType.resolve() as? KSTypeImpl)?.type ?: continue + val annotationFqN = kaType.fullyExpand().symbol?.classId?.asFqNameString() ?: continue + getOrPut(annotationFqN, ::mutableSetOf).add(annotated) + } + } + } } - private val newAnnotatedSymbolsWithLocals: Collection by lazy { - collectAnnotatedSymbols(true) + private val deferredSymbolsRestored: Set by lazy { + deferredSymbols.values.flatten().mapNotNull { it.restore() }.toSet() } override fun getTypeArgument(typeRef: KSTypeReference, variance: Variance): KSTypeArgument { diff --git a/kotlin-analysis-api/testData/locations.kt b/kotlin-analysis-api/testData/locations.kt index 20bc8af3fe..76bf6608fa 100644 --- a/kotlin-analysis-api/testData/locations.kt +++ b/kotlin-analysis-api/testData/locations.kt @@ -24,7 +24,6 @@ // T:J.java:73 // T:J.java:73 // T:K.kt:54 -// T:K.kt:54 // f1:J.java:77 // f1:K.kt:61 // p1:K.kt:56 @@ -39,6 +38,7 @@ // v3:J.java:82 // END + // FILE: Location.kt annotation class Location From e7fc197e2361d054b19cc702389aeda200f31655 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Fri, 7 Mar 2025 16:57:05 -0800 Subject: [PATCH 11/38] Replace lazy Sequences by lazyMemoizedSequence where the intermediate functions applied on the sequence are pure and cost effective. Unlike simple lazy values, intermediate functions applied in lazy properties of Sequence types are computed repeatedly. For example, square() is called each time x is read. val x: Sequence by lazy { listOf(1, 2, 3).map { square(it) } } lazyMemoizedSequence caches the values of the sequence. Also replaced the stateful implementation of KSClassDeclarationImpl.declarations by a stateless one. --- .../google/devtools/ksp/common/PsiUtils.kt | 8 +++++ .../devtools/ksp/impl/ResolverAAImpl.kt | 4 +-- .../kotlin/AbstractKSDeclarationImpl.kt | 8 ++--- .../kotlin/KSClassDeclarationEnumEntryImpl.kt | 6 ++-- .../symbol/kotlin/KSClassDeclarationImpl.kt | 35 +++++++------------ .../ksp/impl/symbol/kotlin/KSFileImpl.kt | 5 +-- .../ksp/impl/symbol/kotlin/KSFileJavaImpl.kt | 3 +- .../kotlin/KSFunctionDeclarationImpl.kt | 10 +++--- .../symbol/kotlin/KSPropertyAccessorImpl.kt | 9 ++--- .../kotlin/KSPropertyDeclarationImpl.kt | 3 +- .../impl/symbol/kotlin/KSTypeReferenceImpl.kt | 3 +- .../symbol/kotlin/KSValueParameterImpl.kt | 3 +- .../resolved/KSTypeArgumentResolvedImpl.kt | 3 +- .../resolved/KSTypeReferenceResolvedImpl.kt | 3 +- .../devtools/ksp/impl/symbol/kotlin/util.kt | 3 +- 15 files changed, 55 insertions(+), 51 deletions(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/common/PsiUtils.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/common/PsiUtils.kt index a760f3340d..347f391239 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/common/PsiUtils.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/common/PsiUtils.kt @@ -94,3 +94,11 @@ inline fun PsiElement.findParentOfType(): T? { } fun Sequence.memoized() = MemoizedSequence(this) + +inline fun lazyMemoizedSequence(crossinline initializer: () -> Sequence): Lazy> = lazy { + val value = initializer() + if (value is MemoizedSequence) + value + else + value.memoized() +} diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt index 20801f4023..e947617f06 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/ResolverAAImpl.kt @@ -89,8 +89,8 @@ class ResolverAAImpl( lateinit var functionAsMemberOfCache: MutableMap, KSFunction> val javaFileManager = project.getService(JavaFileManager::class.java) as KotlinCliJavaFileManagerImpl private val classBinaryCache = ClsKotlinBinaryClassCache() - private val packageInfoFiles by lazy { - allKSFiles.filter { it.fileName == "package-info.java" }.asSequence().memoized() + private val packageInfoFiles by lazyMemoizedSequence { + allKSFiles.filter { it.fileName == "package-info.java" }.asSequence() } // TODO: fix in upstream for builtin types. diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/AbstractKSDeclarationImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/AbstractKSDeclarationImpl.kt index cbfb6a8e3d..527fadaaeb 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/AbstractKSDeclarationImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/AbstractKSDeclarationImpl.kt @@ -17,6 +17,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.impl.KSNameImpl +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.common.toKSModifiers import com.google.devtools.ksp.impl.symbol.java.KSAnnotationJavaImpl import com.google.devtools.ksp.impl.symbol.util.toKSModifiers @@ -52,9 +53,8 @@ abstract class AbstractKSDeclarationImpl(val ktDeclarationSymbol: KaDeclarationS KSNameImpl.getCached((ktDeclarationSymbol as? KaNamedSymbol)?.name?.asString() ?: "") } - override val annotations: Sequence by lazy { - originalAnnotations - } + override val annotations: Sequence + get() = originalAnnotations override val modifiers: Set by lazy { if (origin == Origin.JAVA_LIB || origin == Origin.KOTLIN_LIB || origin == Origin.SYNTHETIC) { @@ -122,7 +122,7 @@ abstract class AbstractKSDeclarationImpl(val ktDeclarationSymbol: KaDeclarationS override val docString: String? get() = ktDeclarationSymbol.toDocString() - internal open val originalAnnotations: Sequence by lazy { + internal open val originalAnnotations: Sequence by lazyMemoizedSequence { if (ktDeclarationSymbol.psi is KtAnnotated) { (ktDeclarationSymbol.psi as KtAnnotated).annotations(ktDeclarationSymbol, this) } else if (ktDeclarationSymbol.origin == KaSymbolOrigin.JAVA_SOURCE && ktDeclarationSymbol.psi != null) { diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationEnumEntryImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationEnumEntryImpl.kt index d9ef961c95..d9b4441675 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationEnumEntryImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationEnumEntryImpl.kt @@ -112,10 +112,8 @@ class KSClassDeclarationEnumEntryImpl private constructor(private val ktEnumEntr return visitor.visitClassDeclaration(this, data) } - override val declarations: Sequence by lazy { - // TODO: fix after .getDeclaredMemberScope() works for enum entry with no initializer. - emptySequence() - } + // TODO: fix after .getDeclaredMemberScope() works for enum entry with no initializer. + override val declarations: Sequence = emptySequence() override fun toString(): String { return "$parent.${simpleName.asString()}" diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationImpl.kt index 5d6b4da8a0..a55a89ec29 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSClassDeclarationImpl.kt @@ -21,6 +21,7 @@ import com.google.devtools.ksp.common.KSObjectCache import com.google.devtools.ksp.common.errorTypeOnInconsistentArguments import com.google.devtools.ksp.common.impl.KSNameImpl import com.google.devtools.ksp.common.impl.KSTypeReferenceSyntheticImpl +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.ResolverAAImpl import com.google.devtools.ksp.impl.recordGetSealedSubclasses import com.google.devtools.ksp.impl.recordLookup @@ -70,7 +71,7 @@ class KSClassDeclarationImpl private constructor(internal val ktClassOrObjectSym } } - override val superTypes: Sequence by lazy { + override val superTypes: Sequence by lazyMemoizedSequence { (ktClassOrObjectSymbol.psiIfSource() as? KtClassOrObject)?.let { classOrObject -> if (classKind == ClassKind.ANNOTATION_CLASS || classKind == ClassKind.ENUM_CLASS) { null @@ -178,31 +179,21 @@ class KSClassDeclarationImpl private constructor(internal val ktClassOrObjectSym return visitor.visitClassDeclaration(this, data) } - override val declarations: Sequence by lazy { + override val declarations: Sequence by lazyMemoizedSequence { val decls = ktClassOrObjectSymbol.declarations() if (origin == Origin.JAVA && classKind != ClassKind.ANNOTATION_CLASS) { - buildList { - decls.forEach { decl -> - if (decl is KSPropertyDeclarationImpl && decl.ktPropertySymbol is KaSyntheticJavaPropertySymbol) { - decl.getter?.let { - add( - KSFunctionDeclarationImpl.getCached( - (it as KSPropertyAccessorImpl).ktPropertyAccessorSymbol - ) - ) - } - decl.setter?.let { - add( - KSFunctionDeclarationImpl.getCached( - (it as KSPropertyAccessorImpl).ktPropertyAccessorSymbol - ) - ) - } - } else { - add(decl) + decls.flatMap { decl -> + if (decl is KSPropertyDeclarationImpl && decl.ktPropertySymbol is KaSyntheticJavaPropertySymbol) { + sequenceOf(decl.getter, decl.setter).mapNotNull { accessor -> + KSFunctionDeclarationImpl.getCached( + (accessor as? KSPropertyAccessorImpl)?.ktPropertyAccessorSymbol + ?: return@mapNotNull null + ) } + } else { + sequenceOf(decl) } - }.asSequence() + } } else decls } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileImpl.kt index 67bf356696..8b5235d363 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileImpl.kt @@ -19,6 +19,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.KSObjectCache import com.google.devtools.ksp.common.impl.KSNameImpl +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.symbol.KSAnnotation import com.google.devtools.ksp.symbol.KSDeclaration import com.google.devtools.ksp.symbol.KSFile @@ -58,7 +59,7 @@ class KSFileImpl private constructor(internal val ktFileSymbol: KaFileSymbol) : psi.virtualFile.path } - override val declarations: Sequence by lazy { + override val declarations: Sequence by lazyMemoizedSequence { analyze { ktFileSymbol.fileScope.declarations.map { when (it) { @@ -84,7 +85,7 @@ class KSFileImpl private constructor(internal val ktFileSymbol: KaFileSymbol) : return visitor.visitFile(this, data) } - override val annotations: Sequence by lazy { + override val annotations: Sequence by lazyMemoizedSequence { (ktFileSymbol.psi as? KtFile)?.annotations(ktFileSymbol) ?: ktFileSymbol.annotations(this) } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt index fd75d633b2..f58808cdfe 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFileJavaImpl.kt @@ -19,6 +19,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.KSObjectCache import com.google.devtools.ksp.common.impl.KSNameImpl +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.symbol.KSAnnotation import com.google.devtools.ksp.symbol.KSDeclaration import com.google.devtools.ksp.symbol.KSFile @@ -42,7 +43,7 @@ class KSFileJavaImpl private constructor(val psi: PsiJavaFile) : KSFile, Deferra override val filePath: String = psi.virtualFile.path - override val declarations: Sequence by lazy { + override val declarations: Sequence by lazyMemoizedSequence { psi.classes.asSequence().mapNotNull { psi -> analyze { psi.namedClassSymbol?.let { KSClassDeclarationImpl.getCached(it) } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFunctionDeclarationImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFunctionDeclarationImpl.kt index 6c35287b76..a2078aaec9 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFunctionDeclarationImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSFunctionDeclarationImpl.kt @@ -20,6 +20,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.* import com.google.devtools.ksp.common.KSObjectCache import com.google.devtools.ksp.common.impl.KSNameImpl +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.ResolverAAImpl import com.google.devtools.ksp.impl.recordLookupForPropertyOrMethod import com.google.devtools.ksp.impl.recordLookupWithSupertypes @@ -146,8 +147,8 @@ class KSFunctionDeclarationImpl private constructor(internal val ktFunctionSymbo return visitor.visitFunctionDeclaration(this, data) } - override val declarations: Sequence by lazy { - val psi = ktFunctionSymbol.psi as? KtFunction ?: return@lazy emptySequence() + override val declarations: Sequence by lazyMemoizedSequence { + val psi = ktFunctionSymbol.psi as? KtFunction ?: return@lazyMemoizedSequence emptySequence() if (!psi.hasBlockBody()) { emptySequence() } else { @@ -178,13 +179,12 @@ class KSFunctionDeclarationImpl private constructor(internal val ktFunctionSymbo ) } - override val annotations: Sequence by lazy { - if (isSyntheticConstructor()) { + override val annotations: Sequence + get() = if (isSyntheticConstructor()) { emptySequence() } else { super.annotations } - } override fun toString(): String { // TODO: fix origin for implicit Java constructor in AA diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyAccessorImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyAccessorImpl.kt index 0edd57cdcf..5a8be449c1 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyAccessorImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyAccessorImpl.kt @@ -18,6 +18,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.KSObjectCache +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.symbol.kotlin.resolved.KSAnnotationResolvedImpl import com.google.devtools.ksp.impl.symbol.kotlin.resolved.KSTypeReferenceResolvedImpl import com.google.devtools.ksp.impl.symbol.util.toKSModifiers @@ -37,7 +38,7 @@ abstract class KSPropertyAccessorImpl( override val receiver: KSPropertyDeclaration ) : KSPropertyAccessor, Deferrable { - override val annotations: Sequence by lazy { + override val annotations: Sequence by lazyMemoizedSequence { // (ktPropertyAccessorSymbol.psi as? KtPropertyAccessor)?.annotations(ktPropertyAccessorSymbol, this) ?: ktPropertyAccessorSymbol.annotations.asSequence() .filter { it.useSiteTarget != AnnotationUseSiteTarget.SETTER_PARAMETER } @@ -45,7 +46,7 @@ abstract class KSPropertyAccessorImpl( .plus(findAnnotationFromUseSiteTarget()) } - internal val originalAnnotations: Sequence by lazy { + internal val originalAnnotations: Sequence by lazyMemoizedSequence { // (ktPropertyAccessorSymbol.psi as? KtPropertyAccessor)?.annotations(ktPropertyAccessorSymbol, this) ?: ktPropertyAccessorSymbol.annotations(this) } @@ -84,8 +85,8 @@ abstract class KSPropertyAccessorImpl( override val parent: KSNode? get() = ktPropertyAccessorSymbol.getContainingKSSymbol() - override val declarations: Sequence by lazy { - val psi = ktPropertyAccessorSymbol.psi as? KtPropertyAccessor ?: return@lazy emptySequence() + override val declarations: Sequence by lazyMemoizedSequence { + val psi = ktPropertyAccessorSymbol.psi as? KtPropertyAccessor ?: return@lazyMemoizedSequence emptySequence() if (!psi.hasBlockBody()) { emptySequence() } else { diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyDeclarationImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyDeclarationImpl.kt index 00e44a8dbf..5cab393671 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyDeclarationImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSPropertyDeclarationImpl.kt @@ -22,6 +22,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.closestClassDeclaration import com.google.devtools.ksp.common.KSObjectCache import com.google.devtools.ksp.common.impl.KSNameImpl +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.ResolverAAImpl import com.google.devtools.ksp.impl.recordLookupForPropertyOrMethod import com.google.devtools.ksp.impl.recordLookupWithSupertypes @@ -58,7 +59,7 @@ class KSPropertyDeclarationImpl private constructor(internal val ktPropertySymbo override val originalAnnotations: Sequence get() = annotations - override val annotations: Sequence by lazy { + override val annotations: Sequence by lazyMemoizedSequence { ktPropertySymbol.annotations.asSequence() .filter { !it.isUseSiteTargetAnnotation() } .map { KSAnnotationResolvedImpl.getCached(it, this) } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeReferenceImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeReferenceImpl.kt index 6eebc92e07..588bc1ba4f 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeReferenceImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSTypeReferenceImpl.kt @@ -18,6 +18,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.IdKeyPair import com.google.devtools.ksp.common.KSObjectCache +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.recordLookup import com.google.devtools.ksp.impl.symbol.util.toKSModifiers import com.google.devtools.ksp.symbol.KSAnnotation @@ -76,7 +77,7 @@ class KSTypeReferenceImpl( return KSTypeImpl.getCached(ktType) } - override val annotations: Sequence by lazy { + override val annotations: Sequence by lazyMemoizedSequence { val innerAnnotations = mutableListOf>() visitNullableType { innerAnnotations.add(it.annotationEntries.asSequence()) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt index 53a318d7ed..e7f05be992 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt @@ -20,6 +20,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.common.KSObjectCache import com.google.devtools.ksp.common.impl.KSNameImpl +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.symbol.kotlin.resolved.KSTypeReferenceResolvedImpl import com.google.devtools.ksp.symbol.* import org.jetbrains.kotlin.analysis.api.fir.symbols.KaFirValueParameterSymbol @@ -86,7 +87,7 @@ class KSValueParameterImpl private constructor( ktValueParameterSymbol.hasDefaultValue } - override val annotations: Sequence by lazy { + override val annotations: Sequence by lazyMemoizedSequence { ktValueParameterSymbol.annotations(this).plus(findAnnotationFromUseSiteTarget()) } override val origin: Origin by lazy { diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeArgumentResolvedImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeArgumentResolvedImpl.kt index d5b240957f..b2bb1a32c5 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeArgumentResolvedImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeArgumentResolvedImpl.kt @@ -19,6 +19,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin.resolved import com.google.devtools.ksp.common.IdKeyPair import com.google.devtools.ksp.common.KSObjectCache +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.symbol.kotlin.Deferrable import com.google.devtools.ksp.impl.symbol.kotlin.Restorable import com.google.devtools.ksp.impl.symbol.kotlin.annotations @@ -59,7 +60,7 @@ class KSTypeArgumentResolvedImpl private constructor( kaType?.let { KSTypeReferenceResolvedImpl.getCached(it, this@KSTypeArgumentResolvedImpl) } } - override val annotations: Sequence by lazy { + override val annotations: Sequence by lazyMemoizedSequence { kaType?.annotations(this) ?: emptySequence() } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt index cfca2e837a..9f6914cd26 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt @@ -19,6 +19,7 @@ package com.google.devtools.ksp.impl.symbol.kotlin.resolved import com.google.devtools.ksp.common.IdKeyTriple import com.google.devtools.ksp.common.KSObjectCache +import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.recordLookup import com.google.devtools.ksp.impl.symbol.kotlin.Deferrable import com.google.devtools.ksp.impl.symbol.kotlin.KSClassDeclarationImpl @@ -71,7 +72,7 @@ class KSTypeReferenceResolvedImpl private constructor( return KSTypeImpl.getCached(ktType) } - override val annotations: Sequence by lazy { + override val annotations: Sequence by lazyMemoizedSequence { ktType.annotations(this) + additionalAnnotations.asSequence().map { KSAnnotationResolvedImpl.getCached(it, this) } } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt index cf45dfd07e..9e84125012 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/util.kt @@ -21,7 +21,6 @@ package com.google.devtools.ksp.impl.symbol.kotlin import com.google.devtools.ksp.ExceptionMessage import com.google.devtools.ksp.common.impl.KSNameImpl -import com.google.devtools.ksp.common.memoized import com.google.devtools.ksp.impl.KSPCoreEnvironment import com.google.devtools.ksp.impl.ResolverAAImpl import com.google.devtools.ksp.impl.symbol.kotlin.resolved.KSAnnotationResolvedImpl @@ -264,7 +263,7 @@ internal fun KaDeclarationContainerSymbol.declarations(): Sequence KSPropertyDeclarationJavaImpl.getCached(symbol) else -> throw IllegalStateException() } - }.memoized() + } } } From 2c019f166b7a65341dafb4462783faed5745e3b3 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Thu, 13 Feb 2025 12:26:00 -0800 Subject: [PATCH 12/38] UPDATE_KOTLIN_VERSION: 2.2.0-dev-2474 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 0017c6ddc9..d4dec2e354 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Copied from kotlinc org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx4096m -Dfile.encoding=UTF-8 -kotlinBaseVersion=2.2.0-dev-745 +kotlinBaseVersion=2.2.0-dev-2474 agpBaseVersion=8.10.0-alpha03 intellijVersion=241.19416.19 junitVersion=4.13.1 From fff3bab76ff1cf01a3c51e4031a40ccaebe64b90 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Thu, 13 Feb 2025 12:26:11 -0800 Subject: [PATCH 13/38] UPDATE_AA_VERSION: 2.2.0-dev-2474 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d4dec2e354..31888c36a2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ junit5Version=5.8.2 junitPlatformVersion=1.8.2 googleTruthVersion=1.1 -aaKotlinBaseVersion=2.2.0-dev-745 +aaKotlinBaseVersion=2.2.0-dev-2474 aaIntellijVersion=241.19416.19 aaGuavaVersion=33.2.0-jre aaAsmVersion=9.0 From e2adbad0bbb945207020afbf0f80945a1567e091 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Thu, 13 Feb 2025 12:26:46 -0800 Subject: [PATCH 14/38] UPDATE_KOTLIN_VERSION: 2.2.0-dev-4719 --- .../google/devtools/ksp/gradle/KspAATask.kt | 18 ++++++++++++++---- gradle.properties | 2 +- .../google/devtools/ksp/test/PlaygroundIT.kt | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt index 3b4c0be83a..3a9c0751f7 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt @@ -38,6 +38,7 @@ import org.gradle.work.NormalizeLineEndings import org.gradle.workers.WorkAction import org.gradle.workers.WorkParameters import org.gradle.workers.WorkerExecutor +import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType @@ -276,11 +277,20 @@ abstract class KspAATask @Inject constructor( cfg.jdkVersion.value(it.toInt()) } - val jvmDefaultMode = compilerOptions.freeCompilerArgs + val oldJvmDefaultMode = compilerOptions.freeCompilerArgs .map { args -> args.filter { it.startsWith("-Xjvm-default=") } } - .map { it.lastOrNull()?.substringAfter("=") ?: "disable" } - - cfg.jvmDefaultMode.value(jvmDefaultMode) + .map { it.lastOrNull()?.substringAfter("=") ?: "undefined" } + + cfg.jvmDefaultMode.value( + project.provider { + when (oldJvmDefaultMode.get()) { + "all" -> "no-compatibility" + "all-compatibility" -> "enable" + "disable" -> "disable" + else -> compilerOptions.jvmDefault.getOrElse(JvmDefaultMode.ENABLE).compilerArgument + } + } + ) cfg.jvmTarget.value(compilerOptions.jvmTarget.map { it.target }) diff --git a/gradle.properties b/gradle.properties index 31888c36a2..a9597a0f0a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Copied from kotlinc org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx4096m -Dfile.encoding=UTF-8 -kotlinBaseVersion=2.2.0-dev-2474 +kotlinBaseVersion=2.2.0-dev-4719 agpBaseVersion=8.10.0-alpha03 intellijVersion=241.19416.19 junitVersion=4.13.1 diff --git a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt index d775a049c2..26add07ff3 100644 --- a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt +++ b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt @@ -310,7 +310,7 @@ class PlaygroundIT(val useKSP2: Boolean) { val gradleRunner = GradleRunner.create().withProjectDir(project.root) gradleRunner.buildAndCheck("clean", "build") { result -> Assert.assertTrue(result.output.contains("platform: JVM")) - Assert.assertTrue(result.output.contains("jvm default mode: all")) + Assert.assertTrue(result.output.contains("jvm default mode: no-compatibility")) } project.restore(buildFile.path) } From 06cc2230ec66351288df3bb0f54a531c39db2c5a Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Thu, 13 Feb 2025 12:26:57 -0800 Subject: [PATCH 15/38] UPDATE_AA_VERSION: 2.2.0-dev-4719 --- gradle.properties | 2 +- .../devtools/ksp/standalone/IncrementalJavaFileManager.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index a9597a0f0a..07e13c8ded 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ junit5Version=5.8.2 junitPlatformVersion=1.8.2 googleTruthVersion=1.1 -aaKotlinBaseVersion=2.2.0-dev-2474 +aaKotlinBaseVersion=2.2.0-dev-4719 aaIntellijVersion=241.19416.19 aaGuavaVersion=33.2.0-jre aaAsmVersion=9.0 diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalJavaFileManager.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalJavaFileManager.kt index e8d5d08066..f073cbfb75 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalJavaFileManager.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalJavaFileManager.kt @@ -87,7 +87,7 @@ class IncrementalJavaFileManager(val environment: KotlinCoreProjectEnvironment) rootsIndex, packagePartProviders, SingleJavaFileRootsIndex(singleJavaFileRoots), - true + true, null ) } @@ -130,7 +130,7 @@ class IncrementalJavaFileManager(val environment: KotlinCoreProjectEnvironment) rootsIndex, packagePartProviders, SingleJavaFileRootsIndex(singleJavaFileRoots), - true + true, null ) } } From e65b7bf1cc64fdf682a50991532c230474e79059 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 12 Mar 2025 10:39:47 -0700 Subject: [PATCH 16/38] Decouple AGP tests with other integration tests and update CI to use check instead of test. --- .github/workflows/auto-merge.yml | 2 +- .github/workflows/main.yml | 6 +----- .github/workflows/release.yml | 2 +- integration-tests/build.gradle.kts | 8 ++++++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 88896c493d..bd80a0e7d4 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -72,7 +72,7 @@ jobs: # Run ksp generated tests - name: test - run: ./gradlew --stacktrace --info test + run: ./gradlew --stacktrace --info check - name: push to release branch if: success() diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fefda10032..3912274d8f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -58,10 +58,6 @@ jobs: with: path: ~/.gradle/wrapper key: ${{ runner.os }}-gradle-wrapper-${{ hashFiles('gradle/wrapper/gradle-wrapper.properties') }} - # Run ktlint - - name: lint - if: matrix.os == 'ubuntu-latest' - run: ./gradlew ktlint # Check API compatibility - name: API compatibility check @@ -71,7 +67,7 @@ jobs: # Run tests - name: test shell: bash - run: ./gradlew --stacktrace --info test + run: ./gradlew --stacktrace --info check - name: Upload test results if: always() uses: actions/upload-artifact@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1319c6b512..f27481097c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,7 +41,7 @@ jobs: # Run tests - name: test shell: bash - run: ./gradlew --stacktrace --info test + run: ./gradlew --stacktrace --info check - name: Upload test results if: always() uses: actions/upload-artifact@v4 diff --git a/integration-tests/build.gradle.kts b/integration-tests/build.gradle.kts index 58be3b0802..762eeb790c 100644 --- a/integration-tests/build.gradle.kts +++ b/integration-tests/build.gradle.kts @@ -58,7 +58,7 @@ val agpCompatibilityTest by tasks.registering(Test::class) { configureCommonSettings() } -tasks.named("test") { +tasks.test { maxParallelForks = max(1, Runtime.getRuntime().availableProcessors() / 2) // Exclude test classes from agpCompatibilityTest @@ -67,7 +67,11 @@ tasks.named("test") { // Apply common settings configureCommonSettings() - // Ensure that 'test' depends on 'compatibilityTest' + // Ensure that 'test' runs after 'compatibilityTest' + mustRunAfter(agpCompatibilityTest) +} + +tasks.check { dependsOn(agpCompatibilityTest) } From a3541e40fef2bb00a9715010404f1efeb86a73ae Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 12 Mar 2025 11:13:11 -0700 Subject: [PATCH 17/38] ApiCheck: handle out-of-project libraries --- buildSrc/src/main/kotlin/com/google/devtools/ksp/ApiCheck.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/com/google/devtools/ksp/ApiCheck.kt b/buildSrc/src/main/kotlin/com/google/devtools/ksp/ApiCheck.kt index c0053cee98..767809caba 100644 --- a/buildSrc/src/main/kotlin/com/google/devtools/ksp/ApiCheck.kt +++ b/buildSrc/src/main/kotlin/com/google/devtools/ksp/ApiCheck.kt @@ -87,8 +87,7 @@ private fun JavaExec.configureCommonMetalavaArgs( private fun Project.getCompileClasspath(): String = configurations.findByName("compileClasspath")!!.files - .map { it.toRelativeString(projectDir) } - .joinToString(File.pathSeparator) + .joinToString(File.pathSeparator) { it.relativeToOrSelf(projectDir).path } private fun Project.getMetalavaConfiguration(): Configuration { return configurations.findByName("metalava") ?: configurations.create("metalava") { From 2217b97fca7a50e4f6c03c3330f44a92218bd75b Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Mon, 10 Mar 2025 15:43:24 -0700 Subject: [PATCH 18/38] UPDATE_AA_VERSION: 2.2.0-dev-7255 --- gradle.properties | 2 +- .../ksp/impl/KotlinSymbolProcessing.kt | 8 ++++--- .../standalone/IncrementalJavaFileManager.kt | 2 +- .../ksp/standalone/KspLibraryModuleBuilder.kt | 23 +++++++++++-------- .../ksp/standalone/KspSourceModuleBuilder.kt | 15 ++++++------ 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/gradle.properties b/gradle.properties index 07e13c8ded..a7b0a43fae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ junit5Version=5.8.2 junitPlatformVersion=1.8.2 googleTruthVersion=1.1 -aaKotlinBaseVersion=2.2.0-dev-4719 +aaKotlinBaseVersion=2.2.0-dev-7255 aaIntellijVersion=241.19416.19 aaGuavaVersion=33.2.0-jre aaAsmVersion=9.0 diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt index 3fd372ed67..52e3ad6a8e 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt @@ -172,7 +172,9 @@ class KotlinSymbolProcessing( ) // replaces buildKtModuleProviderByCompilerConfiguration(compilerConfiguration) - val projectStructureProvider = KtModuleProviderBuilder(kotlinCoreProjectEnvironment).apply { + val projectStructureProvider = KtModuleProviderBuilder( + kotlinCoreProjectEnvironment.environment, project + ).apply { val compilerConfig = compilerConfiguration val platform = when (kspConfig) { is KSPJvmConfig -> { @@ -238,7 +240,7 @@ class KotlinSymbolProcessing( projectStructureProvider, ) val ktFiles = allSourceFiles.filterIsInstance() - val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots(modules, kotlinCoreProjectEnvironment) + val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots(modules, kotlinCoreProjectEnvironment.environment) val createPackagePartProvider = StandaloneProjectFactory.createPackagePartsProvider( libraryRoots, @@ -687,9 +689,9 @@ internal val DEAR_SHADOW_JAR_PLEASE_DO_NOT_REMOVE_THESE = listOf( org.jetbrains.kotlin.analysis.low.level.api.fir.services.LLRealFirElementByPsiElementChooser::class.java, org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionInvalidationService::class.java, org.jetbrains.kotlin.analysis.low.level.api.fir.symbolProviders.factories.LLStubOriginLibrarySymbolProviderFactory::class.java, + org.jetbrains.kotlin.analysis.api.impl.base.java.KaBaseJavaModuleResolver::class.java, org.jetbrains.kotlin.analysis.api.impl.base.permissions.KaBaseAnalysisPermissionChecker::class.java, org.jetbrains.kotlin.analysis.api.impl.base.permissions.KaBaseAnalysisPermissionRegistry::class.java, - org.jetbrains.kotlin.analysis.api.impl.base.symbols.pointers.KaBasePsiSymbolPointerCreator::class.java, org.jetbrains.kotlin.analysis.api.permissions.KaAnalysisPermissionRegistry::class.java, org.jetbrains.kotlin.analysis.api.platform.KotlinProjectMessageBusProvider::class.java, org.jetbrains.kotlin.analysis.api.platform.permissions.KaAnalysisPermissionChecker::class.java, diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalJavaFileManager.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalJavaFileManager.kt index f073cbfb75..4c87b137ed 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalJavaFileManager.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalJavaFileManager.kt @@ -38,7 +38,7 @@ class IncrementalJavaFileManager(val environment: KotlinCoreProjectEnvironment) val javaModuleGraph = JavaModuleGraph(javaModuleFinder) val allSourceFileRoots = sourceFiles.map { JavaRoot(it.virtualFile, JavaRoot.RootType.SOURCE) } val jdkRoots = getDefaultJdkModuleRoots(javaModuleFinder, javaModuleGraph) - val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots(modules, environment) + val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots(modules, environment.environment) val rootsWithSingleJavaFileRoots = buildList { addAll(libraryRoots) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspLibraryModuleBuilder.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspLibraryModuleBuilder.kt index 5deb4f9694..d01f8fb875 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspLibraryModuleBuilder.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspLibraryModuleBuilder.kt @@ -18,7 +18,9 @@ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") package com.google.devtools.ksp.standalone +import com.intellij.core.CoreApplicationEnvironment import com.intellij.openapi.module.Module +import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analysis.api.KaExperimentalApi @@ -31,7 +33,6 @@ import org.jetbrains.kotlin.analysis.project.structure.builder.KtBinaryModuleBui import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleBuilderDsl import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleProviderBuilder import org.jetbrains.kotlin.analysis.project.structure.impl.KaLibraryModuleImpl -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment import java.nio.file.Path import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind @@ -39,7 +40,8 @@ import kotlin.contracts.contract @KtModuleBuilderDsl open class KspLibraryModuleBuilder( - private val kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment + private val coreApplicationEnvironment: CoreApplicationEnvironment, + private val project: Project, ) : KtBinaryModuleBuilder() { public lateinit var libraryName: String public var librarySources: KaLibrarySourceModule? = null @@ -51,8 +53,10 @@ open class KspLibraryModuleBuilder( val binaryRoots = getBinaryRoots() val binaryVirtualFiles = getBinaryVirtualFiles() val contentScope = LibraryRootsSearchScope( - StandaloneProjectFactory.getVirtualFilesForLibraryRoots(binaryRoots, kotlinCoreProjectEnvironment) + - binaryVirtualFiles + StandaloneProjectFactory.getVirtualFilesForLibraryRoots( + binaryRoots, + coreApplicationEnvironment, + ) + binaryVirtualFiles ) return KaLibraryModuleImpl( directRegularDependencies, @@ -60,7 +64,7 @@ open class KspLibraryModuleBuilder( directFriendDependencies, contentScope, platform, - kotlinCoreProjectEnvironment.project, + project, binaryRoots, binaryVirtualFiles, libraryName, @@ -75,7 +79,7 @@ inline fun KtModuleProviderBuilder.buildKspLibraryModule(init: KspLibraryModuleB contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) } - return KspLibraryModuleBuilder(kotlinCoreProjectEnvironment).apply(init).build() + return KspLibraryModuleBuilder(coreApplicationEnvironment, project).apply(init).build() } internal class SimpleTrie(paths: List) { @@ -121,8 +125,9 @@ internal class LibraryRootsSearchScope(roots: List) : GlobalSearchS @KtModuleBuilderDsl public class KspSdkModuleBuilder( - kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment -) : KspLibraryModuleBuilder(kotlinCoreProjectEnvironment) { + coreApplicationEnvironment: CoreApplicationEnvironment, + project: Project, +) : KspLibraryModuleBuilder(coreApplicationEnvironment, project) { @OptIn(KaImplementationDetail::class) public fun addBinaryRootsFromJdkHome(jdkHome: Path, isJre: Boolean) { val jdkRoots = LibraryUtils.findClassesFromJdkHome(jdkHome, isJre) @@ -137,5 +142,5 @@ public inline fun KtModuleProviderBuilder.buildKspSdkModule(init: KspSdkModuleBu contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) } - return KspSdkModuleBuilder(kotlinCoreProjectEnvironment).apply(init).build() + return KspSdkModuleBuilder(coreApplicationEnvironment, project).apply(init).build() } diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspSourceModuleBuilder.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspSourceModuleBuilder.kt index 77d1c4c1b7..a79067f677 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspSourceModuleBuilder.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/KspSourceModuleBuilder.kt @@ -18,6 +18,7 @@ @file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") package com.google.devtools.ksp.standalone +import com.intellij.core.CoreApplicationEnvironment import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.VirtualFile @@ -28,7 +29,6 @@ import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleBuilder import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleBuilderDsl import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleProviderBuilder import org.jetbrains.kotlin.analysis.project.structure.impl.KaSourceModuleImpl -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersionSettings @@ -40,7 +40,8 @@ import kotlin.contracts.contract @KtModuleBuilderDsl class KspModuleBuilder( - private val kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment, + private val coreApplicationEnvironment: CoreApplicationEnvironment, + private val project: Project ) : KtModuleBuilder() { public lateinit var moduleName: String public var languageVersionSettings: LanguageVersionSettings = @@ -58,16 +59,16 @@ class KspModuleBuilder( override fun build(): KaSourceModule { val virtualFiles = collectVirtualFilesByRoots() - val psiManager = PsiManager.getInstance(kotlinCoreProjectEnvironment.project) + val psiManager = PsiManager.getInstance(project) val psiFiles = virtualFiles.mapNotNull { psiManager.findFile(it) } - val contentScope = IncrementalGlobalSearchScope(kotlinCoreProjectEnvironment.project, virtualFiles) + val contentScope = IncrementalGlobalSearchScope(project, virtualFiles) return KaSourceModuleImpl( directRegularDependencies, directDependsOnDependencies, directFriendDependencies, contentScope, platform, - kotlinCoreProjectEnvironment.project, + project, moduleName, languageVersionSettings, psiFiles, @@ -77,7 +78,7 @@ class KspModuleBuilder( val analyzableExtensions = setOf("kt", "java", "kts") private fun collectVirtualFilesByRoots(): Set { - val localFileSystem = kotlinCoreProjectEnvironment.environment.localFileSystem + val localFileSystem = coreApplicationEnvironment.localFileSystem return buildSet { for (root in sourceRoots) { val files = root.toFile().walk().filter { @@ -115,5 +116,5 @@ public inline fun KtModuleProviderBuilder.buildKspSourceModule( contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) } - return KspModuleBuilder(kotlinCoreProjectEnvironment).apply(init).build() + return KspModuleBuilder(coreApplicationEnvironment, project).apply(init).build() } From aa09421c0d434abd7efb7b9db43a749947f4dc03 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Tue, 11 Mar 2025 10:11:30 -0700 Subject: [PATCH 19/38] UPDATE_KOTLIN_VERSION: 2.2.0-dev-7255 --- .../google/devtools/ksp/gradle/AndroidPluginIntegration.kt | 2 +- .../kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt | 4 ++-- gradle.properties | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt index 345978a9c6..c9fab8e1c4 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt @@ -86,7 +86,7 @@ object AndroidPluginIntegration { } when (task) { is KspTaskJvm -> { - task.setSource(filteredSources) + task.source(filteredSources) task.dependsOn(filteredSources) } diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt index 99b5832aee..71a6bfc7d3 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt @@ -351,7 +351,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool fun setSource(source: FileCollection) { // kspTask.setSource(source) would create circular dependency. // Therefore we need to manually extract input deps, filter them, and tell kspTask. - kspTask.setSource(project.provider { source.files }) + kspTask.source(project.provider { source.files }) kspTask.dependsOn(project.provider { source.nonSelfDeps(kspTaskName) }) } @@ -371,7 +371,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool val filteredTasks = kspExtension.excludedSources.buildDependencies.getDependencies(null).map { it.name } kotlinCompilation.allKotlinSourceSetsObservable.forAll { sourceSet -> - kspTask.setSource( + kspTask.source( sourceSet.kotlin.srcDirs.filter { !kotlinOutputDir.isParentOf(it) && !javaOutputDir.isParentOf(it) && it !in kspExtension.excludedSources diff --git a/gradle.properties b/gradle.properties index a7b0a43fae..a0c52ab08b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # Copied from kotlinc org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx4096m -Dfile.encoding=UTF-8 -kotlinBaseVersion=2.2.0-dev-4719 +kotlinBaseVersion=2.2.0-dev-7255 agpBaseVersion=8.10.0-alpha03 intellijVersion=241.19416.19 junitVersion=4.13.1 From e33e4abbdecaba5daa9eab82b1a44c93b6f461a4 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Tue, 11 Mar 2025 17:06:39 -0700 Subject: [PATCH 20/38] Update integration tests for newer Kotlin versions --- .../devtools/ksp/test/AndroidIncrementalIT.kt | 5 ----- .../com/google/devtools/ksp/test/PlaygroundIT.kt | 15 ++++++++++----- .../playground/workload/build.gradle.kts | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/AndroidIncrementalIT.kt b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/AndroidIncrementalIT.kt index 8fec8c7064..c7cdb0af86 100644 --- a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/AndroidIncrementalIT.kt +++ b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/AndroidIncrementalIT.kt @@ -69,11 +69,6 @@ class AndroidIncrementalIT(useKSP2: Boolean) { testWithExtraFlags() } - @Test - fun testPlaygroundAndroidUseClasspathSnapshotFalse() { - testWithExtraFlags("-Pkotlin.incremental.useClasspathSnapshot=false") - } - companion object { @JvmStatic @Parameterized.Parameters(name = "KSP2={0}") diff --git a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt index 26add07ff3..3b3877ad3d 100644 --- a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt +++ b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt @@ -250,7 +250,7 @@ class PlaygroundIT(val useKSP2: Boolean) { """ kotlin { compilerOptions { - apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_6) + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_8) languageVersion.set(compilerOptions.apiVersion) } } @@ -260,8 +260,8 @@ class PlaygroundIT(val useKSP2: Boolean) { val kotlinVersion = System.getProperty("kotlinVersion").split('-').first() val gradleRunner = GradleRunner.create().withProjectDir(project.root) gradleRunner.buildAndCheck("clean", "build") { result -> - Assert.assertTrue(result.output.contains("language version: 1.6")) - Assert.assertTrue(result.output.contains("api version: 1.6")) + Assert.assertTrue(result.output.contains("language version: 1.8")) + Assert.assertTrue(result.output.contains("api version: 1.8")) if (!useKSP2) { // In case KSP 1 and KSP 2 uses different compiler versions, ignore this test for KSP 2 for now. Assert.assertTrue(result.output.contains("compiler version: $kotlinVersion")) @@ -352,14 +352,19 @@ class PlaygroundIT(val useKSP2: Boolean) { """ kotlin { compilerOptions { - allWarningsAsErrors.value(true) progressiveMode.value(true) } } """.trimIndent() ) val gradleRunner = GradleRunner.create().withProjectDir(project.root).withGradleVersion("8.0") - gradleRunner.withArguments("clean", "build").build() + gradleRunner.withArguments("clean", "build").build().let { + Assert.assertFalse( + it.output.contains( + "'-progressive' is meaningful only for the latest language version" + ) + ) + } project.restore(buildFile.path) } diff --git a/integration-tests/src/test/resources/playground/workload/build.gradle.kts b/integration-tests/src/test/resources/playground/workload/build.gradle.kts index baa316f8a2..57cf9bcae9 100644 --- a/integration-tests/src/test/resources/playground/workload/build.gradle.kts +++ b/integration-tests/src/test/resources/playground/workload/build.gradle.kts @@ -32,5 +32,5 @@ tasks.register("copyG") { into(layout.buildDirectory.file("generatedSources")) }.let { // Magic. `map` creates a provider to propagate task dependency. - compileKotlin.setSource(it.map { it.destinationDir }) + compileKotlin.source(it.map { it.destinationDir }) } From a8a204f5e0a499b0107e3b9dff838710b06579b8 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Thu, 13 Mar 2025 21:09:46 -0700 Subject: [PATCH 21/38] KSP2: fix KSValueParameter.isVal and isVar for symbols from libraries. --- .../symbol/kotlin/KSValueParameterImpl.kt | 23 +++++++++- .../ksp/processor/ValueParameterProcessor.kt | 23 ++++++++++ .../com/google/devtools/ksp/test/KSPAATest.kt | 6 +++ .../testData/valueParameter.kt | 45 +++++++++++++++++++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/processor/ValueParameterProcessor.kt create mode 100644 kotlin-analysis-api/testData/valueParameter.kt diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt index e7f05be992..7848d165df 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt @@ -24,6 +24,10 @@ import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.symbol.kotlin.resolved.KSTypeReferenceResolvedImpl import com.google.devtools.ksp.symbol.* import org.jetbrains.kotlin.analysis.api.fir.symbols.KaFirValueParameterSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaConstructorSymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaPropertySymbol +import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolOrigin import org.jetbrains.kotlin.analysis.api.symbols.KaValueParameterSymbol import org.jetbrains.kotlin.analysis.api.types.abbreviationOrSelf import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack @@ -77,11 +81,26 @@ class KSValueParameterImpl private constructor( override val isCrossInline: Boolean get() = ktValueParameterSymbol.isCrossinline + private val KaValueParameterSymbol.primaryConstructorProperty: KaPropertySymbol? by lazy { + when (ktValueParameterSymbol.origin) { + // ktValueParameterSymbol.generatedPrimaryConstructorProperty is always null in libraries. + // TODO: fix in AA + KaSymbolOrigin.LIBRARY, KaSymbolOrigin.JAVA_LIBRARY -> analyze { + val cstr = ktValueParameterSymbol.containingDeclaration as? KaConstructorSymbol + val cls = cstr?.containingDeclaration as? KaClassSymbol + cls?.declaredMemberScope?.declarations?.filterIsInstance() + ?.firstOrNull { it.name == ktValueParameterSymbol.name } + } + + else -> ktValueParameterSymbol.generatedPrimaryConstructorProperty + } + } + override val isVal: Boolean - get() = (ktValueParameterSymbol.psi as? KtParameter)?.let { it.hasValOrVar() && !it.isMutable } ?: false + get() = ktValueParameterSymbol.primaryConstructorProperty?.isVal == true override val isVar: Boolean - get() = (ktValueParameterSymbol.psi as? KtParameter)?.let { it.hasValOrVar() && it.isMutable } ?: false + get() = ktValueParameterSymbol.primaryConstructorProperty?.isVal == false override val hasDefault: Boolean by lazy { ktValueParameterSymbol.hasDefaultValue diff --git a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/processor/ValueParameterProcessor.kt b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/processor/ValueParameterProcessor.kt new file mode 100644 index 0000000000..315056fe40 --- /dev/null +++ b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/processor/ValueParameterProcessor.kt @@ -0,0 +1,23 @@ +package com.google.devtools.ksp.processor + +import com.google.devtools.ksp.getClassDeclarationByName +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.symbol.KSAnnotated + +class ValueParameterProcessor : AbstractTestProcessor() { + val results = mutableListOf() + + override fun toResult(): List { + return results + } + + override fun process(resolver: Resolver): List { + for (clsName in listOf("MyClassSrc", "MyClassLib")) { + val clsDecl = resolver.getClassDeclarationByName(clsName)!! + clsDecl.primaryConstructor!!.parameters.sortedBy { it.name!!.asString() }.forEach { + results.add("$clsName.${it.name!!.asString()}: isVal: ${it.isVal}, isVar: ${it.isVar}") + } + } + return emptyList() + } +} diff --git a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt index fbf1507c0e..41a14d4567 100644 --- a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt +++ b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt @@ -684,6 +684,12 @@ class KSPAATest : AbstractKSPAATest() { runTest("../kotlin-analysis-api/testData/typeParameterVariance.kt") } + @TestMetadata("valueParameter.kt") + @Test + fun testValueParameter() { + runTest("../kotlin-analysis-api/testData/valueParameter.kt") + } + @TestMetadata("varianceTypeCheck.kt") @Test fun testVarianceTypeCheck() { diff --git a/kotlin-analysis-api/testData/valueParameter.kt b/kotlin-analysis-api/testData/valueParameter.kt new file mode 100644 index 0000000000..1f62f67a3f --- /dev/null +++ b/kotlin-analysis-api/testData/valueParameter.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2025 Google LLC + * Copyright 2010-2025 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. + */ + +// TEST PROCESSOR: ValueParameterProcessor +// EXPECTED: +// MyClassSrc.field: isVal: false, isVar: false +// MyClassSrc.valField: isVal: true, isVar: false +// MyClassSrc.varField: isVal: false, isVar: true +// MyClassLib.field: isVal: false, isVar: false +// MyClassLib.valField: isVal: true, isVar: false +// MyClassLib.varField: isVal: false, isVar: true +// END + +// MODULE: lib +// FILE: lib.kt + +class MyClassLib( + field: String, + val valField: String, + var varField: String, +) + +// MODULE: main(lib) +// FILE: main.kt + +class MyClassSrc( + field: String, + val valField: String, + var varField: String, +) + From 2a60e287c5a996c52615507ac2581f133ad2e3fe Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 19 Mar 2025 15:35:35 -0700 Subject: [PATCH 22/38] Update github actions permissions for release --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f27481097c..8310d0e089 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,9 @@ jobs: # The type of runner that the job will run on runs-on: ubuntu-latest + permissions: + contents: write + steps: - name: Setup Java 17 uses: actions/setup-java@v1.4.3 From 2a935515e739674b6530a9539006a7d3fb79f4fe Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 19 Mar 2025 11:04:57 -0700 Subject: [PATCH 23/38] KSP2: fix the type of vararg for Kotlin sources Previously, KSValueParameter.type was an array when it is from Kotlin sources, while it is the declared type for Java and libraries. For example, the KSValueParameter.type of strings is now consistently String. fun (vararg strings: String) The equivalentJavaWildcards test is updated due to a toString() change. --- .../symbol/kotlin/KSValueParameterImpl.kt | 27 +++------ .../com/google/devtools/ksp/test/KSPAATest.kt | 6 ++ .../testData/equivalentJavaWildcards.kt | 2 +- .../devtools/ksp/processor/VarargProcessor.kt | 28 ++++++++++ test-utils/testData/api/vararg.kt | 55 +++++++++++++++++++ 5 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 test-utils/src/main/kotlin/com/google/devtools/ksp/processor/VarargProcessor.kt create mode 100644 test-utils/testData/api/vararg.kt diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt index 7848d165df..a374d74477 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/KSValueParameterImpl.kt @@ -23,18 +23,13 @@ import com.google.devtools.ksp.common.impl.KSNameImpl import com.google.devtools.ksp.common.lazyMemoizedSequence import com.google.devtools.ksp.impl.symbol.kotlin.resolved.KSTypeReferenceResolvedImpl import com.google.devtools.ksp.symbol.* -import org.jetbrains.kotlin.analysis.api.fir.symbols.KaFirValueParameterSymbol import org.jetbrains.kotlin.analysis.api.symbols.KaClassSymbol import org.jetbrains.kotlin.analysis.api.symbols.KaConstructorSymbol import org.jetbrains.kotlin.analysis.api.symbols.KaPropertySymbol import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolOrigin import org.jetbrains.kotlin.analysis.api.symbols.KaValueParameterSymbol import org.jetbrains.kotlin.analysis.api.types.abbreviationOrSelf -import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack -import org.jetbrains.kotlin.fir.java.declarations.FirJavaValueParameter -import org.jetbrains.kotlin.fir.java.resolveIfJavaType import org.jetbrains.kotlin.fir.symbols.SymbolInternals -import org.jetbrains.kotlin.psi.KtParameter class KSValueParameterImpl private constructor( private val ktValueParameterSymbol: KaValueParameterSymbol, @@ -55,20 +50,14 @@ class KSValueParameterImpl private constructor( @OptIn(SymbolInternals::class) override val type: KSTypeReference by lazy { - // FIXME: temporary workaround before upstream fixes java type refs. - if (origin == Origin.JAVA || origin == Origin.JAVA_LIB) { - ((ktValueParameterSymbol as KaFirValueParameterSymbol).firSymbol.fir as? FirJavaValueParameter)?.let { - // can't get containing class for FirJavaValueParameter, using empty stack for now. - it.returnTypeRef = - it.returnTypeRef.resolveIfJavaType(it.moduleData.session, JavaTypeParameterStack.EMPTY, null) - } - } - (ktValueParameterSymbol.psiIfSource() as? KtParameter)?.typeReference - ?.let { KSTypeReferenceImpl.getCached(it, this) } - ?: KSTypeReferenceResolvedImpl.getCached( - ktValueParameterSymbol.returnType.abbreviationOrSelf, - this@KSValueParameterImpl - ) + // TODO: avoid eager resolution by using PSI. + // KaFirValueParameterSymbol extracts and returns the element type of a vararg. + // That logic needs to be replicated if we resolve the PSI via + // analyze { KtTypeReference.type }. + KSTypeReferenceResolvedImpl.getCached( + ktValueParameterSymbol.returnType.abbreviationOrSelf, + this@KSValueParameterImpl + ) } override val isVararg: Boolean by lazy { diff --git a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt index 41a14d4567..c272082993 100644 --- a/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt +++ b/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPAATest.kt @@ -702,6 +702,12 @@ class KSPAATest : AbstractKSPAATest() { runTest("../test-utils/testData/api/validateTypes.kt") } + @TestMetadata("vararg.kt") + @Test + fun testVararg() { + runTest("../test-utils/testData/api/vararg.kt") + } + @TestMetadata("visibilities.kt") @Test fun testVisibilities() { diff --git a/kotlin-analysis-api/testData/equivalentJavaWildcards.kt b/kotlin-analysis-api/testData/equivalentJavaWildcards.kt index 793e423850..267414f8a7 100644 --- a/kotlin-analysis-api/testData/equivalentJavaWildcards.kt +++ b/kotlin-analysis-api/testData/equivalentJavaWildcards.kt @@ -81,7 +81,7 @@ // - COVARIANT X : X -> X // v7 : B<*> -> B // v8 : B> -> B> -// - INVARIANT A : A -> A +// - INVARIANT A : A -> A // - - INVARIANT X : X -> X // - - COVARIANT Y : Y -> Y // foo : Unit -> Unit diff --git a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/VarargProcessor.kt b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/VarargProcessor.kt new file mode 100644 index 0000000000..5554e57d98 --- /dev/null +++ b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/VarargProcessor.kt @@ -0,0 +1,28 @@ +package com.google.devtools.ksp.processor + +import com.google.devtools.ksp.getClassDeclarationByName +import com.google.devtools.ksp.getDeclaredFunctions +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.symbol.KSAnnotated + +class VarargProcessor : AbstractTestProcessor() { + val results = mutableListOf() + + override fun toResult(): List { + return results + } + + override fun process(resolver: Resolver): List { + for (clsName in listOf("s.K", "s.J", "l.K", "l.J")) { + val clsDecl = resolver.getClassDeclarationByName(clsName)!! + val func = clsDecl.getDeclaredFunctions().single { it.simpleName.asString() == "foo" } + val funcName = func.qualifiedName!!.asString() + val param = func.parameters.single() + val paramName = param.name!!.asString() + val paramType = param.type.resolve() + val isVararg = if (param.isVararg) "vararg " else "" + results.add("$funcName($isVararg$paramName: $paramType)") + } + return emptyList() + } +} diff --git a/test-utils/testData/api/vararg.kt b/test-utils/testData/api/vararg.kt new file mode 100644 index 0000000000..385c0accea --- /dev/null +++ b/test-utils/testData/api/vararg.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2025 Google LLC + * Copyright 2010-2025 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. + */ + +// TEST PROCESSOR: VarargProcessor +// EXPECTED: +// s.K.foo(vararg strings: String) +// s.J.foo(vararg strings: (String..String?)) +// l.K.foo(vararg strings: String) +// l.J.foo(vararg p0: (String..String?)) +// END + +// MODULE: lib +// FILE: l/K.kt +package l +class K { + fun foo(vararg strings: String) = 0 +} + +// FILE: l/J.java +package l; +public class J { + int foo(String... strings) { + return 0; + } +} + +// MODULE: main(lib) +// FILE: s/K.kt +package s +class K { + fun foo(vararg strings: String) = 0 +} + +// FILE: s/J.java +package s; +public class J { + int foo(String... strings) { + return 0; + } +} + From d7cc8a3547a4807e466ae6d87859e8bee9faff32 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 19 Mar 2025 11:20:19 -0700 Subject: [PATCH 24/38] Update ksp2api.md to clarify the change of vararg --- docs/ksp2api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ksp2api.md b/docs/ksp2api.md index 7b0606d80a..3cdb4110ea 100644 --- a/docs/ksp2api.md +++ b/docs/ksp2api.md @@ -83,8 +83,8 @@ class OverrideOrder2 : BaseInterface2, GrandBaseInterface1 { * KSP2: Type annotations on a type argument now present in the resolved type as well ##### vararg parameters -* KSP1: Considered as an `Array` type -* KSP2: Not considered as an `Array` type +* KSP1: Considered as an `Array` type when it is from Java sources. +* KSP2: Not considered as an `Array` type. KSValueParameter returns the declared type consistently. ##### Synthesized members of Enums * KSP1: `values` and `valueOf` are missing if the enum is defined in Kotlin sources From 9068bda24fa459919646a7fe550e77a7f0e9d140 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Tue, 25 Mar 2025 11:50:38 -0700 Subject: [PATCH 25/38] Register KotlinStandalonePackageProviderFactory to project Disposable It has to be done manually because it is wrapped by IncrementalPackageProviderFactory. --- .../com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt | 7 ++++++- .../standalone/IncrementalKotlinPackageProviderFactory.kt | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt index 52e3ad6a8e..ea70ef8895 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt @@ -259,6 +259,7 @@ class KotlinSymbolProcessing( kotlinCoreProjectEnvironment, ktFiles, createPackagePartProvider, + projectDisposable ) CoreApplicationEnvironment.registerExtensionPoint( @@ -295,6 +296,7 @@ class KotlinSymbolProcessing( kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment, ktFiles: List, packagePartProvider: (GlobalSearchScope) -> PackagePartProvider, + projectDisposable: Disposable, ) { val project = kotlinCoreProjectEnvironment.project project.apply { @@ -343,7 +345,10 @@ class KotlinSymbolProcessing( KotlinDeclarationProviderMerger::class.java, KotlinStandaloneDeclarationProviderMerger(this) ) - registerService(KotlinPackageProviderFactory::class.java, IncrementalKotlinPackageProviderFactory(project)) + registerService( + KotlinPackageProviderFactory::class.java, + IncrementalKotlinPackageProviderFactory(project, projectDisposable) + ) registerService( SealedClassInheritorsProvider::class.java, diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalKotlinPackageProviderFactory.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalKotlinPackageProviderFactory.kt index 935a8c3db1..1fae50c4c1 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalKotlinPackageProviderFactory.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalKotlinPackageProviderFactory.kt @@ -1,6 +1,8 @@ package com.google.devtools.ksp.standalone +import com.intellij.openapi.Disposable import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Disposer import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analysis.api.platform.packages.KotlinCompositePackageProvider import org.jetbrains.kotlin.analysis.api.platform.packages.KotlinPackageProvider @@ -10,6 +12,7 @@ import org.jetbrains.kotlin.psi.KtFile class IncrementalKotlinPackageProviderFactory( private val project: Project, + private val projectDisposable: Disposable, ) : KotlinPackageProviderFactory { private val staticFactories: MutableList = mutableListOf() @@ -20,6 +23,7 @@ class IncrementalKotlinPackageProviderFactory( fun update(files: Collection) { val staticFactory = KotlinStandalonePackageProviderFactory(project, files) + Disposer.register(projectDisposable, staticFactory) staticFactories.add(staticFactory) } } From dc5ba2e6a5e7bc4ec0ca184d630597e18f28acea Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Tue, 25 Mar 2025 13:08:17 -0700 Subject: [PATCH 26/38] Dispose KotlinStandalonePackageProviderFactor via IncrementalKotlinPackageProviderFactory --- .../google/devtools/ksp/impl/KotlinSymbolProcessing.kt | 7 +------ .../standalone/IncrementalKotlinPackageProviderFactory.kt | 8 +++++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt index ea70ef8895..52e3ad6a8e 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt @@ -259,7 +259,6 @@ class KotlinSymbolProcessing( kotlinCoreProjectEnvironment, ktFiles, createPackagePartProvider, - projectDisposable ) CoreApplicationEnvironment.registerExtensionPoint( @@ -296,7 +295,6 @@ class KotlinSymbolProcessing( kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment, ktFiles: List, packagePartProvider: (GlobalSearchScope) -> PackagePartProvider, - projectDisposable: Disposable, ) { val project = kotlinCoreProjectEnvironment.project project.apply { @@ -345,10 +343,7 @@ class KotlinSymbolProcessing( KotlinDeclarationProviderMerger::class.java, KotlinStandaloneDeclarationProviderMerger(this) ) - registerService( - KotlinPackageProviderFactory::class.java, - IncrementalKotlinPackageProviderFactory(project, projectDisposable) - ) + registerService(KotlinPackageProviderFactory::class.java, IncrementalKotlinPackageProviderFactory(project)) registerService( SealedClassInheritorsProvider::class.java, diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalKotlinPackageProviderFactory.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalKotlinPackageProviderFactory.kt index 1fae50c4c1..f81a692a52 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalKotlinPackageProviderFactory.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/standalone/IncrementalKotlinPackageProviderFactory.kt @@ -12,8 +12,7 @@ import org.jetbrains.kotlin.psi.KtFile class IncrementalKotlinPackageProviderFactory( private val project: Project, - private val projectDisposable: Disposable, -) : KotlinPackageProviderFactory { +) : KotlinPackageProviderFactory, Disposable { private val staticFactories: MutableList = mutableListOf() override fun createPackageProvider(searchScope: GlobalSearchScope): KotlinPackageProvider { @@ -23,7 +22,10 @@ class IncrementalKotlinPackageProviderFactory( fun update(files: Collection) { val staticFactory = KotlinStandalonePackageProviderFactory(project, files) - Disposer.register(projectDisposable, staticFactory) + Disposer.register(this, staticFactory) staticFactories.add(staticFactory) } + + override fun dispose() { + } } From 30a7e0d0c3f6f0b68fe6f0a44c1efeda529b972f Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 26 Mar 2025 10:09:00 -0700 Subject: [PATCH 27/38] CI: Update release branch to 2.0.0 (cherry picked from commit de1ebbc4156c9b30884b9b812d8336418ecc8bb0) --- .github/workflows/auto-merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index bd80a0e7d4..bf280e51c9 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v2 with: fetch-depth: 0 - ref: 1.0.32-release + ref: 2.0.0-release - name: merge commits from main to release branch run: | From cd4acbad64d388999f67c7a7fec60ca209afd1fc Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 26 Mar 2025 10:05:15 -0700 Subject: [PATCH 28/38] Downgrade to Kotlin 2.1.20 --- .../ksp/KotlinSymbolProcessingExtension.kt | 26 ++----------------- .../devtools/ksp/test/AbstractKSPTest.kt | 7 +++-- .../google/devtools/ksp/gradle/KspAATask.kt | 18 +++---------- gradle.properties | 6 ++--- .../google/devtools/ksp/test/PlaygroundIT.kt | 2 +- 5 files changed, 13 insertions(+), 46 deletions(-) diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingExtension.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingExtension.kt index a0888f7daf..2c044d6752 100644 --- a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingExtension.kt +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingExtension.kt @@ -46,8 +46,6 @@ import com.google.devtools.ksp.symbol.Visibility import com.google.devtools.ksp.symbol.impl.java.KSFileJavaImpl import com.google.devtools.ksp.symbol.impl.kotlin.KSFileImpl import com.intellij.openapi.Disposable -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.StandardFileSystems @@ -55,7 +53,6 @@ import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager import com.intellij.psi.impl.file.impl.JavaFileManager -import com.intellij.util.ui.EDT import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl @@ -167,10 +164,8 @@ abstract class AbstractKotlinSymbolProcessingExtension( logger.logging("round $rounds of processing") val psiManager = PsiManager.getInstance(project) if (initialized) { - maybeRunInWriteAction { - psiManager.dropPsiCaches() - psiManager.dropResolveCaches() - } + psiManager.dropPsiCaches() + psiManager.dropResolveCaches() invalidateKotlinCliJavaFileManagerCache(project) } else { // In case of broken builds. @@ -534,20 +529,3 @@ private fun invalidateKotlinCliJavaFileManagerCache(project: Project): Boolean { (privateCacheField.get(javaFileManager) as? MutableMap<*, *>)?.clear() ?: return false return true } - -private fun maybeRunInWriteAction(f: () -> R) { - synchronized(EDT::class.java) { - if (!EDT.isCurrentThreadEdt()) { - val edt = EDT::class.java.getDeclaredField("myEventDispatchThread") - edt.isAccessible = true - edt.set(null, Thread.currentThread()) - } - if (ApplicationManager.getApplication() != null) { - runWriteAction { - f() - } - } else { - f() - } - } -} diff --git a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/AbstractKSPTest.kt b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/AbstractKSPTest.kt index 7faa9ccfaf..6e65f4dc9c 100644 --- a/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/AbstractKSPTest.kt +++ b/compiler-plugin/src/test/kotlin/com/google/devtools/ksp/test/AbstractKSPTest.kt @@ -24,7 +24,6 @@ import com.intellij.openapi.util.Disposer import com.intellij.testFramework.TestDataFile import org.jetbrains.kotlin.analysis.test.framework.services.TargetPlatformDirectives import org.jetbrains.kotlin.analysis.test.framework.services.TargetPlatformProviderForAnalysisApiTests -import org.jetbrains.kotlin.cli.common.disposeRootInWriteAction import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoot @@ -61,13 +60,13 @@ abstract class DisposableTest { protected val disposable: Disposable get() = _disposable!! @BeforeEach - fun initDisposable(testInfo: TestInfo) { + private fun initDisposable(testInfo: TestInfo) { _disposable = Disposer.newDisposable("disposable for ${testInfo.displayName}") } @AfterEach - fun disposeDisposable() { - _disposable?.let { disposeRootInWriteAction(it) } + private fun disposeDisposable() { + _disposable?.let { Disposer.dispose(it) } _disposable = null } } diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt index 3a9c0751f7..3b4c0be83a 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt @@ -38,7 +38,6 @@ import org.gradle.work.NormalizeLineEndings import org.gradle.workers.WorkAction import org.gradle.workers.WorkParameters import org.gradle.workers.WorkerExecutor -import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType @@ -277,20 +276,11 @@ abstract class KspAATask @Inject constructor( cfg.jdkVersion.value(it.toInt()) } - val oldJvmDefaultMode = compilerOptions.freeCompilerArgs + val jvmDefaultMode = compilerOptions.freeCompilerArgs .map { args -> args.filter { it.startsWith("-Xjvm-default=") } } - .map { it.lastOrNull()?.substringAfter("=") ?: "undefined" } - - cfg.jvmDefaultMode.value( - project.provider { - when (oldJvmDefaultMode.get()) { - "all" -> "no-compatibility" - "all-compatibility" -> "enable" - "disable" -> "disable" - else -> compilerOptions.jvmDefault.getOrElse(JvmDefaultMode.ENABLE).compilerArgument - } - } - ) + .map { it.lastOrNull()?.substringAfter("=") ?: "disable" } + + cfg.jvmDefaultMode.value(jvmDefaultMode) cfg.jvmTarget.value(compilerOptions.jvmTarget.map { it.target }) diff --git a/gradle.properties b/gradle.properties index a0c52ab08b..632f6e109d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,9 @@ # Copied from kotlinc org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx4096m -Dfile.encoding=UTF-8 -kotlinBaseVersion=2.2.0-dev-7255 +kotlinBaseVersion=2.1.20 agpBaseVersion=8.10.0-alpha03 -intellijVersion=241.19416.19 +intellijVersion=233.13135.128 junitVersion=4.13.1 junit5Version=5.8.2 junitPlatformVersion=1.8.2 @@ -25,4 +25,4 @@ kotlin.jvm.target.validation.mode=warning # Build or runtime dependencies of this project buildKotlinVersion=2.0.20 -buildKspVersion=2.0.20-1.0.25 \ No newline at end of file +buildKspVersion=2.0.20-1.0.25 diff --git a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt index 3b3877ad3d..956c9a4245 100644 --- a/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt +++ b/integration-tests/src/test/kotlin/com/google/devtools/ksp/test/PlaygroundIT.kt @@ -310,7 +310,7 @@ class PlaygroundIT(val useKSP2: Boolean) { val gradleRunner = GradleRunner.create().withProjectDir(project.root) gradleRunner.buildAndCheck("clean", "build") { result -> Assert.assertTrue(result.output.contains("platform: JVM")) - Assert.assertTrue(result.output.contains("jvm default mode: no-compatibility")) + Assert.assertTrue(result.output.contains("jvm default mode: all")) } project.restore(buildFile.path) } From bd1a8fddbb1424e90096559b8f024c04860c2916 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Wed, 26 Mar 2025 11:46:56 -0700 Subject: [PATCH 29/38] Enable KSP2 by default (cherry picked from commit 39cd86cb1333794299d44c2729d7e4701c98bd63) --- .../main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt | 2 +- .../main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt index 96f62d0627..17ac4b2e11 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt @@ -28,7 +28,7 @@ import javax.inject.Inject abstract class KspExtension @Inject constructor(project: Project) { /** - * Enables or disables KSP 2, defaults to the `ksp.useKsp2` gradle property or `false` if that's not set. + * Enables or disables KSP 2, defaults to the `ksp.useKSP2` gradle property or `true` if that's not set. * * This API is temporary and will be removed once KSP1 is removed. */ diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt index 71a6bfc7d3..857ef87758 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt @@ -214,7 +214,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool target.providers .gradleProperty("ksp.useKSP2") .map { it.toBoolean() } - .orElse(false) + .orElse(true) ) kspConfigurations = KspConfigurations(target) registry.register(KspModelBuilder()) From afc6825309f476fdbd6df974cf497367bad51f25 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Sat, 29 Mar 2025 10:14:30 -0700 Subject: [PATCH 30/38] KSTypeReferenceResolvedImpl.toString(): render unexpanded (cherry picked from commit 549040231f205176d646ca71e6f9a159a50157e2) --- .../impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt index 9f6914cd26..6f01f8fd94 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/symbol/kotlin/resolved/KSTypeReferenceResolvedImpl.kt @@ -116,7 +116,7 @@ class KSTypeReferenceResolvedImpl private constructor( } override fun toString(): String { - return ktType.render() + return ktType.abbreviationOrSelf.render() } override fun defer(): Restorable? { From 924efc3c06390d45dceb420cfa18ed45f9523bfa Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Tue, 1 Apr 2025 18:27:24 -0700 Subject: [PATCH 31/38] No-op blockOtherCompilerPlugins This has been deprecated and has been messaged to be unsupported since KSP 1.0.8 (cherry picked from commit ab470cfa337a9d6b9ee6c39947c73ccd4ec6db90) --- .../devtools/ksp/gradle/KspExtension.kt | 2 +- .../devtools/ksp/gradle/KspSubplugin.kt | 22 ++++++------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt index 17ac4b2e11..400e457bbd 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspExtension.kt @@ -65,7 +65,7 @@ abstract class KspExtension @Inject constructor(project: Project) { commandLineArgumentProviders.add(arg) } - @Deprecated("KSP will stop supporting other compiler plugins in KSP's Gradle tasks after 1.0.8.") + @Deprecated("No-op. KSP no longer reads this property") open var blockOtherCompilerPlugins: Boolean = true // Instruct KSP to pickup sources from compile tasks, instead of source sets. diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt index 857ef87758..a9802bae9d 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt @@ -405,11 +405,9 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool (kspTask as? AbstractKotlinCompile<*>)?.incremental = false } - fun maybeBlockOtherPlugins(kspTask: BaseKotlinCompile) { - if (kspExtension.blockOtherCompilerPlugins) { - kspTask.pluginClasspath.setFrom(kspClasspathCfg) - kspTask.pluginOptions.set(emptyList()) - } + fun blockOtherPlugins(kspTask: BaseKotlinCompile) { + kspTask.pluginClasspath.setFrom(kspClasspathCfg) + kspTask.pluginOptions.set(emptyList()) } fun configurePluginOptions(kspTask: BaseKotlinCompile) { @@ -474,7 +472,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool KotlinFactories.registerKotlinJvmCompileTask(project, kspTaskName, kotlinCompilation).also { it.configure { kspTask -> val kotlinCompileTask = kotlinCompileProvider.get() as KotlinCompile - maybeBlockOtherPlugins(kspTask as BaseKotlinCompile) + blockOtherPlugins(kspTask as BaseKotlinCompile) configureAsKspTask(kspTask, isIncremental) configureAsAbstractKotlinCompileTool(kspTask as AbstractKotlinCompileTool<*>) configurePluginOptions(kspTask) @@ -509,7 +507,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool KotlinPlatformType.js, KotlinPlatformType.wasm -> { KotlinFactories.registerKotlinJSCompileTask(project, kspTaskName, kotlinCompilation).also { it.configure { kspTask -> - maybeBlockOtherPlugins(kspTask as BaseKotlinCompile) + blockOtherPlugins(kspTask as BaseKotlinCompile) configureAsKspTask(kspTask, isIncremental) configureAsAbstractKotlinCompileTool(kspTask as AbstractKotlinCompileTool<*>) configurePluginOptions(kspTask) @@ -532,7 +530,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool KotlinPlatformType.common -> { KotlinFactories.registerKotlinMetadataCompileTask(project, kspTaskName, kotlinCompilation).also { it.configure { kspTask -> - maybeBlockOtherPlugins(kspTask as BaseKotlinCompile) + blockOtherPlugins(kspTask as BaseKotlinCompile) configureAsKspTask(kspTask, isIncremental) configureAsAbstractKotlinCompileTool(kspTask as AbstractKotlinCompileTool<*>) configurePluginOptions(kspTask) @@ -570,13 +568,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool kspClasspathCfgNonEmbeddable } // KotlinNativeCompile computes -Xplugin=... from compilerPluginClasspath. - if (kspExtension.blockOtherCompilerPlugins) { - kspTask.compilerPluginClasspath = classpathCfg - } else { - kspTask.compilerPluginClasspath = - classpathCfg + kotlinCompileTask.compilerPluginClasspath!! - kspTask.compilerPluginOptions.addPluginArgument(kotlinCompileTask.compilerPluginOptions) - } + kspTask.compilerPluginClasspath = classpathCfg kspTask.commonSources.from(kotlinCompileTask.commonSources) kspTask.options.add( FileCollectionSubpluginOption.create( From c990a634b8abf996492db09b95c5f6954a6e2bd5 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Fri, 4 Apr 2025 12:54:20 -0700 Subject: [PATCH 32/38] Update BUILD Kotlin and KSP versions. (cherry picked from commit 04fcbf891b63e0858c0866e36ab7eee5d8923d51) --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 632f6e109d..b4e4462c47 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,5 +24,5 @@ compilerTestEnabled=false kotlin.jvm.target.validation.mode=warning # Build or runtime dependencies of this project -buildKotlinVersion=2.0.20 -buildKspVersion=2.0.20-1.0.25 +buildKotlinVersion=2.1.20 +buildKspVersion=2.1.20-1.0.32 From 5e3581b592b238e17d14dd98414b0747c9dc1ff0 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Fri, 4 Apr 2025 10:53:24 -0700 Subject: [PATCH 33/38] UPDATE_AA_VERSION: 2.2.0-dev-9278 (cherry picked from commit 69cb7b464f55cdba0eccded29deb9490e09076e7) --- gradle.properties | 2 +- .../ksp/impl/KotlinSymbolProcessing.kt | 27 +++++++++---------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/gradle.properties b/gradle.properties index b4e4462c47..955d983da6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ junit5Version=5.8.2 junitPlatformVersion=1.8.2 googleTruthVersion=1.1 -aaKotlinBaseVersion=2.2.0-dev-7255 +aaKotlinBaseVersion=2.2.0-dev-9278 aaIntellijVersion=241.19416.19 aaGuavaVersion=33.2.0-jre aaAsmVersion=9.0 diff --git a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt index 52e3ad6a8e..bffc6d1210 100644 --- a/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt +++ b/kotlin-analysis-api/src/main/kotlin/com/google/devtools/ksp/impl/KotlinSymbolProcessing.kt @@ -58,6 +58,7 @@ import com.intellij.psi.PsiTreeChangeListener import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.ui.EDT import org.jetbrains.kotlin.analysis.api.KaExperimentalApi +import org.jetbrains.kotlin.analysis.api.KaIdeApi import org.jetbrains.kotlin.analysis.api.KaImplementationDetail import org.jetbrains.kotlin.analysis.api.platform.KotlinMessageBusProvider import org.jetbrains.kotlin.analysis.api.platform.KotlinPlatformSettings @@ -65,13 +66,12 @@ import org.jetbrains.kotlin.analysis.api.platform.KotlinProjectMessageBusProvide import org.jetbrains.kotlin.analysis.api.platform.declarations.* import org.jetbrains.kotlin.analysis.api.platform.lifetime.KotlinAlwaysAccessibleLifetimeTokenFactory import org.jetbrains.kotlin.analysis.api.platform.lifetime.KotlinLifetimeTokenFactory -import org.jetbrains.kotlin.analysis.api.platform.modification.KotlinGlobalModificationService import org.jetbrains.kotlin.analysis.api.platform.modification.KotlinModificationTrackerFactory +import org.jetbrains.kotlin.analysis.api.platform.modification.publishGlobalModuleStateModificationEvent import org.jetbrains.kotlin.analysis.api.platform.packages.KotlinPackagePartProviderFactory import org.jetbrains.kotlin.analysis.api.platform.packages.KotlinPackageProviderFactory import org.jetbrains.kotlin.analysis.api.platform.permissions.KotlinAnalysisPermissionOptions -import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinByModulesResolutionScopeProvider -import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinResolutionScopeProvider +import org.jetbrains.kotlin.analysis.api.platform.resolution.KaResolutionActivityTracker import org.jetbrains.kotlin.analysis.api.projectStructure.KaModule import org.jetbrains.kotlin.analysis.api.projectStructure.KaSourceModule import org.jetbrains.kotlin.analysis.api.resolve.extensions.KaResolveExtensionProvider @@ -81,12 +81,12 @@ import org.jetbrains.kotlin.analysis.api.standalone.StandaloneAnalysisAPISession import org.jetbrains.kotlin.analysis.api.standalone.base.KotlinStandalonePlatformSettings import org.jetbrains.kotlin.analysis.api.standalone.base.declarations.KotlinStandaloneAnnotationsResolverFactory import org.jetbrains.kotlin.analysis.api.standalone.base.declarations.KotlinStandaloneDeclarationProviderMerger -import org.jetbrains.kotlin.analysis.api.standalone.base.modification.KotlinStandaloneGlobalModificationService import org.jetbrains.kotlin.analysis.api.standalone.base.modification.KotlinStandaloneModificationTrackerFactory import org.jetbrains.kotlin.analysis.api.standalone.base.permissions.KotlinStandaloneAnalysisPermissionOptions import org.jetbrains.kotlin.analysis.api.standalone.base.projectStructure.FirStandaloneServiceRegistrar import org.jetbrains.kotlin.analysis.api.standalone.base.projectStructure.StandaloneProjectFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession +import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirResolutionActivityTracker import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLSealedInheritorsProvider import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleBuilder import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleProviderBuilder @@ -150,7 +150,7 @@ class KotlinSymbolProcessing( setupIdeaStandaloneExecution() } - @OptIn(KaExperimentalApi::class, KaImplementationDetail::class) + @OptIn(KaExperimentalApi::class, KaImplementationDetail::class, KaIdeApi::class) private fun createAASession( compilerConfiguration: CompilerConfiguration, projectDisposable: Disposable, @@ -254,6 +254,10 @@ class KotlinSymbolProcessing( KotlinAnalysisPermissionOptions::class.java, KotlinStandaloneAnalysisPermissionOptions::class.java ) + kotlinCoreProjectEnvironment.registerApplicationServices( + KaResolutionActivityTracker::class.java, + LLFirResolutionActivityTracker::class.java + ) registerProjectServices( kotlinCoreProjectEnvironment, @@ -313,10 +317,6 @@ class KotlinSymbolProcessing( KotlinModificationTrackerFactory::class.java, KotlinStandaloneModificationTrackerFactory::class.java ) - registerService( - KotlinGlobalModificationService::class.java, - KotlinStandaloneGlobalModificationService::class.java - ) registerService( KotlinLifetimeTokenFactory::class.java, KotlinAlwaysAccessibleLifetimeTokenFactory::class.java @@ -327,10 +327,6 @@ class KotlinSymbolProcessing( KotlinAnnotationsResolverFactory::class.java, KotlinStandaloneAnnotationsResolverFactory(project, ktFiles) ) - registerService( - KotlinResolutionScopeProvider::class.java, - KotlinByModulesResolutionScopeProvider::class.java - ) registerService( KotlinDeclarationProviderFactory::class.java, IncrementalKotlinDeclarationProviderFactory(this) @@ -545,7 +541,7 @@ class KotlinSymbolProcessing( fun dropCaches() { maybeRunInWriteAction { - KotlinGlobalModificationService.getInstance(project).publishGlobalSourceModuleStateModification() + project.publishGlobalModuleStateModificationEvent() KaSessionProvider.getInstance(project).clearCaches() psiManager.dropResolveCaches() psiManager.dropPsiCaches() @@ -690,8 +686,11 @@ internal val DEAR_SHADOW_JAR_PLEASE_DO_NOT_REMOVE_THESE = listOf( org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSessionInvalidationService::class.java, org.jetbrains.kotlin.analysis.low.level.api.fir.symbolProviders.factories.LLStubOriginLibrarySymbolProviderFactory::class.java, org.jetbrains.kotlin.analysis.api.impl.base.java.KaBaseJavaModuleResolver::class.java, + org.jetbrains.kotlin.analysis.api.impl.base.java.KaBaseKotlinJavaPsiFacade::class.java, org.jetbrains.kotlin.analysis.api.impl.base.permissions.KaBaseAnalysisPermissionChecker::class.java, org.jetbrains.kotlin.analysis.api.impl.base.permissions.KaBaseAnalysisPermissionRegistry::class.java, + org.jetbrains.kotlin.analysis.api.impl.base.projectStructure.KaBaseContentScopeProvider::class.java, + org.jetbrains.kotlin.analysis.api.impl.base.projectStructure.KaBaseResolutionScopeProvider::class.java, org.jetbrains.kotlin.analysis.api.permissions.KaAnalysisPermissionRegistry::class.java, org.jetbrains.kotlin.analysis.api.platform.KotlinProjectMessageBusProvider::class.java, org.jetbrains.kotlin.analysis.api.platform.permissions.KaAnalysisPermissionChecker::class.java, From cabc47c5452f2ab4a2352076ac1b188b29348503 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Fri, 4 Apr 2025 13:03:12 -0700 Subject: [PATCH 34/38] UPDATE_AA_VERSION: 2.2.0-dev-10059 (cherry picked from commit ec276a17738f9d2229f0012793624db2eb31da6e) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 955d983da6..f05c1a22a9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ junit5Version=5.8.2 junitPlatformVersion=1.8.2 googleTruthVersion=1.1 -aaKotlinBaseVersion=2.2.0-dev-9278 +aaKotlinBaseVersion=2.2.0-dev-10059 aaIntellijVersion=241.19416.19 aaGuavaVersion=33.2.0-jre aaAsmVersion=9.0 From cc81cfc437df17cef10088402c2776c57add8985 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Fri, 4 Apr 2025 13:29:25 -0700 Subject: [PATCH 35/38] UPDATE_AA_VERSION: 2.2.0-dev-12451 (cherry picked from commit 60df3d5d4cd94a3a40daf0dce74e281278713fbb) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f05c1a22a9..5aa35f3e75 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ junit5Version=5.8.2 junitPlatformVersion=1.8.2 googleTruthVersion=1.1 -aaKotlinBaseVersion=2.2.0-dev-10059 +aaKotlinBaseVersion=2.2.0-dev-12451 aaIntellijVersion=241.19416.19 aaGuavaVersion=33.2.0-jre aaAsmVersion=9.0 From 5cef44f4ac3ec669e2ca7dbd3ae75770569f6252 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Fri, 4 Apr 2025 13:29:52 -0700 Subject: [PATCH 36/38] UPDATE_AA_VERSION: 2.2.0-dev-12941 (cherry picked from commit ffd955fce5aef2b6fb1b029bafbcc0910d5b3e95) --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 5aa35f3e75..c81d26c3f7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ junit5Version=5.8.2 junitPlatformVersion=1.8.2 googleTruthVersion=1.1 -aaKotlinBaseVersion=2.2.0-dev-12451 +aaKotlinBaseVersion=2.2.0-dev-12941 aaIntellijVersion=241.19416.19 aaGuavaVersion=33.2.0-jre aaAsmVersion=9.0 From 524fb6a6b2e33831f0e54130737572f0e6c53c84 Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Mon, 7 Apr 2025 15:47:35 -0700 Subject: [PATCH 37/38] Exclude KAPT outputs from classpath snapshots. (cherry picked from commit a73350529ece3e8c08350b8c35391987e5f4f91d) --- .../kotlin/com/google/devtools/ksp/gradle/KspAATask.kt | 2 ++ .../com/google/devtools/ksp/gradle/KspSubplugin.kt | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt index 3b4c0be83a..a007dba6c7 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt @@ -191,12 +191,14 @@ abstract class KspAATask @Inject constructor( if (kotlinCompilation is KotlinJvmAndroidCompilation) { // Workaround of a dependency resolution issue of AGP. // FIXME: figure out how to filter or set variant attributes correctly. + val kaptGeneratedClassesDir = getKaptGeneratedClassesDir(project, sourceSetName) val kspOutputDir = KspGradleSubplugin.getKspOutputDir(project, sourceSetName, target) cfg.libraries.from( project.files( Callable { kotlinCompileProvider.get().libraries.filter { !kspOutputDir.isParentOf(it) && + !kaptGeneratedClassesDir.isParentOf(it) && !(it.isDirectory && it.listFiles()?.isEmpty() == true) } } diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt index a9802bae9d..2e05036502 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspSubplugin.kt @@ -42,6 +42,7 @@ import org.gradle.work.InputChanges import org.jetbrains.kotlin.buildtools.api.SourcesChanges import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.gradle.dsl.KotlinVersion +import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin import org.jetbrains.kotlin.gradle.internal.kapt.incremental.CLASS_STRUCTURE_ARTIFACT_TYPE import org.jetbrains.kotlin.gradle.internal.kapt.incremental.ClasspathSnapshot import org.jetbrains.kotlin.gradle.internal.kapt.incremental.KaptClasspathChanges @@ -383,6 +384,7 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool if (kotlinCompilation is KotlinJvmAndroidCompilation) { // Workaround of a dependency resolution issue of AGP. + val kaptGeneratedClassesDir = getKaptGeneratedClassesDir(project, sourceSetName) kspTask.libraries.setFrom( project.files( Callable { @@ -390,7 +392,9 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool // manually exclude KAPT generated class folder from class path snapshot. // TODO: remove in 1.9.0. - !kspOutputDir.isParentOf(it) && !(it.isDirectory && it.listFiles()?.isEmpty() == true) + !kspOutputDir.isParentOf(it) && + !kaptGeneratedClassesDir.isParentOf(it) && + !(it.isDirectory && it.listFiles()?.isEmpty() == true) } } ) @@ -924,3 +928,6 @@ internal fun FileCollection.nonSelfDeps(selfTaskName: String): List = buildDependencies.getDependencies(null).filterNot { it.name == selfTaskName } + +internal fun getKaptGeneratedClassesDir(project: Project, sourceSetName: String) = + Kapt3GradleSubplugin.getKaptGeneratedClassesDir(project, sourceSetName) From b541b46d43cfa9fd397f8511a97f0ca5fff5e9db Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Mon, 7 Apr 2025 15:48:52 -0700 Subject: [PATCH 38/38] KSP2: include KotlinPlatformType.androidJvm in incremental libs (cherry picked from commit f244bfca23cc7201af82f87115c91e97e9132b8b) --- .../google/devtools/ksp/gradle/KspAATask.kt | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt index a007dba6c7..c925081c20 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/KspAATask.kt @@ -91,27 +91,30 @@ abstract class KspAATask @Inject constructor( } val changedClasses = if (kspConfig.incremental.get()) { - if (kspConfig.platformType.get() == KotlinPlatformType.jvm) { - getCPChanges( - inputChanges, - listOf( - kspConfig.sourceRoots, - kspConfig.javaSourceRoots, - kspConfig.commonSourceRoots, + when (kspConfig.platformType.get()) { + KotlinPlatformType.jvm, KotlinPlatformType.androidJvm -> { + getCPChanges( + inputChanges, + listOf( + kspConfig.sourceRoots, + kspConfig.javaSourceRoots, + kspConfig.commonSourceRoots, + kspConfig.classpathStructure, + ), + kspConfig.cachesDir.asFile.get(), kspConfig.classpathStructure, - ), - kspConfig.cachesDir.asFile.get(), - kspConfig.classpathStructure, - kspConfig.libraries, - kspConfig.processorClasspath, - ) - } else { - if ( - !inputChanges.isIncremental || - inputChanges.getFileChanges(kspConfig.nonJvmLibraries).iterator().hasNext() - ) - kspConfig.cachesDir.get().asFile.deleteRecursively() - emptyList() + kspConfig.libraries, + kspConfig.processorClasspath, + ) + } + else -> { + if ( + !inputChanges.isIncremental || + inputChanges.getFileChanges(kspConfig.nonJvmLibraries).iterator().hasNext() + ) + kspConfig.cachesDir.get().asFile.deleteRecursively() + emptyList() + } } } else { kspConfig.cachesDir.get().asFile.deleteRecursively()