Status Update
Comments
ls...@google.com <ls...@google.com>
tn...@google.com <tn...@google.com> #2
I can't reproduce this. Can you attach a project where you see it?
su...@twofortyfouram.com <su...@twofortyfouram.com> #3
It contains one additional commit with an empty kt file in a library project. The CI job shows the lint failure by running the task `./gradlew lint`.
js...@google.com <js...@google.com> #4
The error raised from here:
But, assuming there is no script file, the only case ULC fails to create a facade light class is here:
js...@google.com <js...@google.com> #5
Not trivial to reproduce the case in upstream Kotiln/IntelliJ repo.
There is a similar input: KotlinAsJavaSupport
, not CliKotlinAsJavaSupport
, is used, which has a quite different way of creating a facade light class (in short, decompilation):
tn...@google.com <tn...@google.com> #6
I tried to to fix ^H^H^H work around this issue -- by just having lint skip empty files since there's no good reason to analyze them anyway:
diff --git a/lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt b/lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt
index 27ae062dd78..7a1af09b48b 100644
--- a/lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt
+++ b/lint/libs/lint-api/src/main/java/com/android/tools/lint/helpers/DefaultUastParser.kt
@@ -121,6 +121,11 @@ open class DefaultUastParser(
StandardFileSystems.local().findFileByPath(absPath) ?: return null
}
+ // Workaround for b/233355652
+ if (virtualFile.length == 0L) {
+ return null
+ }
+
val psiFile = PsiManager.getInstance(ideaProject).findFile(virtualFile) ?: return null
if (psiFile.language == Language.ANY && file.path.endsWith(DOT_KT)) {
But while that "fixes" the immediate exception shown in repro project (thank you very much for that repro project by the way, very helpful!), it just shifts the problem, because the mere presence of that file no the class path causes the PSI environment to look it up on its own later and fail -- for example from this code path:
kotlin.UninitializedPropertyAccessException: lateinit property module has not been initialized
at org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder.getModule(CliTrace.kt:25)
at org.jetbrains.kotlin.cli.jvm.compiler.CliKotlinAsJavaSupport.findClassOrObjectDeclarations(CliKotlinAsJavaSupport.kt:119)
at org.jetbrains.kotlin.asJava.finder.JavaElementFinder.findClassesAndObjects(JavaElementFinder.kt:62)
at org.jetbrains.kotlin.asJava.finder.JavaElementFinder.findClasses(JavaElementFinder.kt:47)
at org.jetbrains.kotlin.asJava.finder.JavaElementFinder.findClass(JavaElementFinder.kt:36)
at com.intellij.psi.impl.JavaPsiFacadeImpl.doFindClass(JavaPsiFacadeImpl.java:91)
at com.intellij.psi.impl.JavaPsiFacadeImpl.findClass(JavaPsiFacadeImpl.java:69)
at com.android.tools.lint.helpers.DefaultJavaEvaluator.findClass(DefaultJavaEvaluator.kt:99)
So we'll need to get to the bottom of it properly.
al...@google.com <al...@google.com> #7
We are hitting the lateinit
exception in AndroidX in
au...@google.com <au...@google.com> #8
We started hitting androidx failure after upgrading to AGP 7.4.0-alpha04 from AGP 7.4.0-alpha01.
This is bad enough for us to revert back to alpha01
tn...@google.com <tn...@google.com> #9
Do you have empty .kt files?
js...@google.com <js...@google.com> #11
Last time I was able to detach to the repro project build, I saw the facade light class "EmptyKt" for "empty.kt" is created properly. Rather, what triggered the whole exception trace was "Build_gradleKt", which I guess came from "build_gradle.kt" somewhere. Does anyone notice about this? Anyway, then I lost the control; let me try again today.
Regarding the revert, sorry to hear that. But, there wasn't any major UAST drops since 7.4.0-alpha01. Well, from upstream UAST. On the platform side, everything is updated to IJ 221 recently?
js...@google.com <js...@google.com> #12
Finally, I got to the bottom of this, and was able to reproduce it in Android Lint testing infra, which is surprisingly simple:
@Test
fun testEmptyKtWithGradleKts() {
TestLintTask.lint().files(
kts(
"""
plugins {
id("com.android.application")
}
""".trimIndent()
),
kotlin(
"src/some/pkg/Empty.kt",
""
)
)
.allowMissingSdk()
.issues(UastImplementationDetector.ISSUE) // Any detector that triggers FILE-level UAST visit
.run()
.expectClean()
}
Any detector that needs to visit UFile
triggers collecting facade light classes in that file. Under the hood, such collection is package name-based lookup. As an empty file, its package name is <root>
for now. build.gradle.kts
, as a script file, has <root>
package too.
At
But, assuming there is no script file, the only case ULC fails to create a facade light class is here:
https://cs.android.com/android-studio/kotlin/+/master:compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt;l=71?q=createUltraLightClassForFacade
Well, there is script file :( and thus null
is returned just a couple lines below:
That is, upstream U/LC has an incomplete condition check
it just shifts the problem, because the mere presence of that file no the class path causes the PSI environment to look it up on its own later and fail
Yeah, but it's not just an empty .kt file; any .kt files without specific package names could have triggered the issue. So... I'm still not sure a nice workaround on Android Lint side.
js...@google.com <js...@google.com> #14
Regarding workaround, it's too deep in U/LC facade creation, and like I said, this could be triggered by any root-level file:
@Test
fun testNonEmptyRootPackageKtWithGradleKts() {
TestLintTask.lint().files(
kts(
"""
plugins {
id("com.android.application")
}
""".trimIndent()
),
kotlin(
"src/NonEmpty.kt",
"val p = 42"
)
)
.allowMissingSdk()
.issues(UastImplementationDetector.ISSUE) // Any detector that triggers FILE-level UAST visit
.run()
.expectClean()
}
An upstream fix should be simple, so I'd rather patch that directly to Lint's bundled PSI artifacts.
js...@google.com <js...@google.com> #15
Re:
I've tried the same workaround:
+ // Workaround for b/233355652
+ if (virtualFile.length == 0L) {
+ return null
+ }
to see if I'd see the same lateinit
exception, but the lintDebug task failed differently:
.../secant-android-wallet/test-lib/src/main/AndroidManifest.xml:6: Error: android.permission.WAKE_LOCK is a reserved permission [ReservedSystemPermission]
<permission android:name="android.permission.WAKE_LOCK"/>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Explanation for issues of type "ReservedSystemPermission":
This check looks for custom permission declarations whose names are
reserved values for system or Android SDK permissions.
Please double check the permission name you have supplied. Attempting to
redeclare a system or Android SDK permission will be ignored.
which seems like
So, I'm curious what the full stack trace was, because one from
kotlin.UninitializedPropertyAccessException: lateinit property module has not been initialized
at org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder.getModule(CliTrace.kt:25)
at org.jetbrains.kotlin.cli.jvm.compiler.CliKotlinAsJavaSupport.findClassOrObjectDeclarations(CliKotlinAsJavaSupport.kt:119)
at org.jetbrains.kotlin.asJava.finder.JavaElementFinder.findClassesAndObjects(JavaElementFinder.kt:62)
at org.jetbrains.kotlin.asJava.finder.JavaElementFinder.findClasses(JavaElementFinder.kt:47)
at org.jetbrains.kotlin.asJava.finder.JavaElementFinder.findClass(JavaElementFinder.kt:36)
at com.intellij.psi.impl.JavaPsiFacadeImpl.doFindClass(JavaPsiFacadeImpl.java:91)
at com.intellij.psi.impl.JavaPsiFacadeImpl.findClass(JavaPsiFacadeImpl.java:69)
at com.android.tools.lint.helpers.DefaultJavaEvaluator.findClass(DefaultJavaEvaluator.kt:99)
at com.android.tools.lint.checks.PermissionErrorDetector$Companion.computePlatformPermissions(PermissionErrorDetector.kt:463)
at com.android.tools.lint.checks.PermissionErrorDetector$Companion.getPlatformPermissions(PermissionErrorDetector.kt:453)
at com.android.tools.lint.checks.PermissionErrorDetector$Companion.findAlmostPlatformPermission(PermissionErrorDetector.kt:342)
at com.android.tools.lint.checks.PermissionErrorDetector.reportPermissionUsageIncidents(PermissionErrorDetector.kt:191)
at com.android.tools.lint.checks.PermissionErrorDetector.checkDocument$reportOrAddPermissionUsages(PermissionErrorDetector.kt:78)
at com.android.tools.lint.checks.PermissionErrorDetector.checkDocument(PermissionErrorDetector.kt:91)
at com.android.tools.lint.checks.PermissionErrorDetector.checkMergedProject(PermissionErrorDetector.kt:58)
at com.android.tools.lint.client.api.LintDriver.processMergedProjects(LintDriver.kt:676)
at com.android.tools.lint.LintCliClient.mergeState(LintCliClient.kt:616)
at com.android.tools.lint.client.api.LintDriver$LintClientWrapper.mergeState(LintDriver.kt:2952)
at com.android.tools.lint.client.api.LintDriver$mergeOnly$1.invoke(LintDriver.kt:483)
at com.android.tools.lint.client.api.LintDriver$mergeOnly$1.invoke(LintDriver.kt:478)
at com.android.tools.lint.client.api.LintDriver.doAnalyze$default(LintDriver.kt:493)
at com.android.tools.lint.client.api.LintDriver.mergeOnly(LintDriver.kt:478)
at com.android.tools.lint.LintCliClient$mergeOnly$1.invoke(LintCliClient.kt:262)
at com.android.tools.lint.LintCliClient$mergeOnly$1.invoke(LintCliClient.kt:260)
at com.android.tools.lint.LintCliClient.mergeOnly(LintCliClient.kt:260)
Note that that detector, PermissionErrorDetector
, and functions involved in the stacktrace were indeed changed recently: module
variable in CliTraceHolder
.
au...@google.com <au...@google.com> #16
js...@google.com <js...@google.com> #17
au...@google.com <au...@google.com> #18
Created
js...@google.com <js...@google.com> #19
Upstream issue (
au...@google.com <au...@google.com> #20
Thanks for the fix!
al...@gmail.com <al...@gmail.com> #22
aaltafgopang86 @gmail com
be...@gmail.com <be...@gmail.com> #23
If it can help others, I also get this issue if the Kotlin file is missing a package
declaration. Adding it fixes the issue.
js...@google.com <js...@google.com> #24
I'm not sure what version of AS you're using, but assuming a stable version, maybe Dolphin?
It'll be available at the next canary (AS EE / AGP 7.4 canary 7?).
Like I mentioned, a patch is added and available in EE, and its stable version will be out very soon.
Description
Lint crashes when a project contains an empty .kt file
STEPS TO REPRODUCE:
1. Configure an Android project with AGP 7.2.0
2. Create a .kt file in the main source set where the kt file is empty
3. ./gradlew lintRelease
Results
java.lang.IllegalStateException: () -> kotlin.String
at org.jetbrains.kotlin.asJava.classes.KtLightClassForFacadeImpl$Companion.createForFacadeNoCache(KtLightClassForFacadeImpl.kt:272)
at org.jetbrains.kotlin.asJava.classes.FacadeCache$FacadeCacheData$cache$1.createValue(FacadeCache.kt:30)
at org.jetbrains.kotlin.asJava.classes.FacadeCache$FacadeCacheData$cache$1.createValue(FacadeCache.kt:28)
at com.intellij.util.containers.SLRUCache.get(SLRUCache.java:47)
at org.jetbrains.kotlin.asJava.classes.FacadeCache.get(FacadeCache.kt:47)
at org.jetbrains.kotlin.asJava.classes.KtLightClassForFacadeImpl$Companion.createForFacade(KtLightClassForFacadeImpl.kt:282)
at org.jetbrains.kotlin.cli.jvm.compiler.CliKotlinAsJavaSupport.getFacadeClassesInPackage(CliKotlinAsJavaSupport.kt:40)
at org.jetbrains.kotlin.asJava.LightClassUtilsKt.findFacadeClass(lightClassUtils.kt:58)
at org.jetbrains.uast.kotlin.KotlinUFile$classes$2.invoke(KotlinUFile.kt:57)
at org.jetbrains.uast.kotlin.KotlinUFile$classes$2.invoke(KotlinUFile.kt:56)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at org.jetbrains.uast.kotlin.KotlinUFile.getClasses(KotlinUFile.kt:56)
at org.jetbrains.uast.UFile$DefaultImpls.accept(UFile.kt:87)
at org.jetbrains.uast.kotlin.KotlinUFile.accept(KotlinUFile.kt:14)
at com.android.tools.lint.detector.api.UastLintUtilsKt.acceptSourceFile(UastLintUtils.kt:537)
at com.android.tools.lint.client.api.UElementVisitor$visitFile$2.run(UElementVisitor.kt:267)
at com.android.tools.lint.client.api.LintClient.runReadAction(LintClient.kt:1795)
at com.android.tools.lint.client.api.LintDriver$LintClientWrapper.runReadAction(LintDriver.kt:2766)
at com.android.tools.lint.client.api.UElementVisitor.visitFile(UElementVisitor.kt:265)
at com.android.tools.lint.client.api.LintDriver$visitUastDetectors$1.run(LintDriver.kt:2083)
at com.android.tools.lint.client.api.LintClient.runReadAction(LintClient.kt:1795)
at com.android.tools.lint.client.api.LintDriver$LintClientWrapper.runReadAction(LintDriver.kt:2766)
at com.android.tools.lint.client.api.LintDriver.visitUastDetectors(LintDriver.kt:2083)
at com.android.tools.lint.client.api.LintDriver.visitUast(LintDriver.kt:2042)
at com.android.tools.lint.client.api.LintDriver.runFileDetectors(LintDriver.kt:1417)
at com.android.tools.lint.client.api.LintDriver.checkProject(LintDriver.kt:1181)
at com.android.tools.lint.client.api.LintDriver.checkProjectRoot(LintDriver.kt:644)
at com.android.tools.lint.client.api.LintDriver.access$checkProjectRoot(LintDriver.kt:159)
at com.android.tools.lint.client.api.LintDriver$analyzeOnly$1.invoke(LintDriver.kt:458)
at com.android.tools.lint.client.api.LintDriver$analyzeOnly$1.invoke(LintDriver.kt:451)
at com.android.tools.lint.client.api.LintDriver.doAnalyze(LintDriver.kt:518)
at com.android.tools.lint.client.api.LintDriver.analyzeOnly(LintDriver.kt:451)
at com.android.tools.lint.LintCliClient$analyzeOnly$1.invoke(LintCliClient.kt:243)
at com.android.tools.lint.LintCliClient$analyzeOnly$1.invoke(LintCliClient.kt:243)
at com.android.tools.lint.LintCliClient.run(LintCliClient.kt:285)
at com.android.tools.lint.LintCliClient.run$default(LintCliClient.kt:268)
at com.android.tools.lint.LintCliClient.analyzeOnly(LintCliClient.kt:243)
at com.android.tools.lint.Main.run(Main.java:1661)
at com.android.tools.lint.Main.run(Main.java:275)
at jdk.internal.reflect.GeneratedMethodAccessor799.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at com.android.build.gradle.internal.lint.AndroidLintWorkAction.invokeLintMainRunMethod(AndroidLintWorkAction.kt:93)
at com.android.build.gradle.internal.lint.AndroidLintWorkAction.runLint(AndroidLintWorkAction.kt:82)
at com.android.build.gradle.internal.lint.AndroidLintWorkAction.execute(AndroidLintWorkAction.kt:64)
at org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:63)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:66)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1$1.create(NoIsolationWorkerFactory.java:62)
at org.gradle.internal.classloader.ClassLoaderUtils.executeInClassloader(ClassLoaderUtils.java:97)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.lambda$execute$0(NoIsolationWorkerFactory.java:62)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:44)
at org.gradle.workers.internal.AbstractWorker$1.call(AbstractWorker.java:41)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
at org.gradle.workers.internal.AbstractWorker.executeWrappedInBuildOperation(AbstractWorker.java:41)
at org.gradle.workers.internal.NoIsolationWorkerFactory$1.execute(NoIsolationWorkerFactory.java:59)
at org.gradle.workers.internal.DefaultWorkerExecutor.lambda$submitWork$2(DefaultWorkerExecutor.java:205)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:187)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.access$700(DefaultConditionalExecutionQueue.java:120)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner$1.run(DefaultConditionalExecutionQueue.java:162)
at org.gradle.internal.Factories$1.create(Factories.java:31)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:270)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:119)
at org.gradle.internal.work.DefaultWorkerLeaseService.runAsWorkerThread(DefaultWorkerLeaseService.java:124)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:157)
at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:126)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:833)
------------------
Studio Build:
Version of Gradle Plugin: 7.2.0
Version of Gradle: 7.4.2
Version of Java: 17
OS: macOS 12.4