java.lang.AssertionError: org.jetbrains.uast.java.JavaUParameter@10ed5906:class org.jetbrains.uast.j

277 views
Skip to first unread message

Niklas Baudy

unread,
Nov 12, 2017, 7:08:11 AM11/12/17
to lint-dev
I'm in the process of migrating from PSI to UAST and yesterday I've seen that there is the following function, that I assume will also work better within the IDE (just like the Timber method comparison check).

context.evaluator.getAllAnnotations


Unfortunately when I use it on this test case:

fun testOverrideComesFirstOnParameters() {
@Language("java") val source = """
package foo;

public class MyTest {
public void myTest(@Test @Override int something) { }
}""".trimMargin()

assertThat(lintProject(java(source))).startsWith("""src/foo/MyTest.java:4: Warning: Annotations are in wrong order. Should be @Override @Test [WrongAnnotationOrder]
| public void myTest(@Test @Override int something) { }
| ~~~~~~~~~
|0 errors, 1 warnings""".trimMargin())
}

It fails with:

java.lang.RuntimeException: java.lang.AssertionError: org.jetbrains.uast.java.JavaUParameter@10ed5906:class org.jetbrains.uast.java.JavaUParameter not found among parameters: [PsiParameter:something]. parameterList' parent: PsiMethod:myTest; parameter.isValid()=true; parameterList.isValid()= true; parameterList stub: null;  parameter stub: ---; suspect: PsiParameter:something (index=0); class com.intellij.psi.impl.source.PsiParameterImpl suspect stub: null; parameter.equals(suspect) = false;  parameter.getNode() == suspect.getNode():  true; .
	at com.android.tools.lint.checks.infrastructure.LintDetectorTest$TestLintClient.log(LintDetectorTest.java:990)
	at com.android.tools.lint.client.api.LintDriver$LintClientWrapper.log(LintDriver.kt:2173)
	at com.android.tools.lint.client.api.LintDriver$Companion.handleDetectorError(LintDriver.kt:2772)
	at com.android.tools.lint.client.api.LintDriver.analyze(LintDriver.kt:394)
	at com.android.tools.lint.checks.infrastructure.LintDetectorTest$TestLintClient.analyze(LintDetectorTest.java:1225)
	at com.android.tools.lint.checks.infrastructure.LintDetectorTest.checkLint(LintDetectorTest.java:292)
	at com.android.tools.lint.checks.infrastructure.LintDetectorTest.checkLint(LintDetectorTest.java:265)
	at com.android.tools.lint.checks.infrastructure.LintDetectorTest.lintProject(LintDetectorTest.java:422)
	at com.vanniktech.lintrules.android.AnnotationOrderDetectorTest.testOverrideComesFirstOnParameters(AnnotationOrderDetectorTest.kt:60)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at junit.framework.TestCase.runTest(TestCase.java:176)
	at junit.framework.TestCase.runBare(TestCase.java:141)
	at junit.framework.TestResult$1.protect(TestResult.java:122)
	at junit.framework.TestResult.runProtected(TestResult.java:142)
	at junit.framework.TestResult.run(TestResult.java:125)
	at junit.framework.TestCase.run(TestCase.java:129)
	at junit.framework.TestSuite.runTest(TestSuite.java:252)
	at junit.framework.TestSuite.run(TestSuite.java:247)
	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
	at com.sun.proxy.$Proxy1.processTestClass(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:108)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.AssertionError: org.jetbrains.uast.java.JavaUParameter@10ed5906:class org.jetbrains.uast.java.JavaUParameter not found among parameters: [PsiParameter:something]. parameterList' parent: PsiMethod:myTest; parameter.isValid()=true; parameterList.isValid()= true; parameterList stub: null;  parameter stub: ---; suspect: PsiParameter:something (index=0); class com.intellij.psi.impl.source.PsiParameterImpl suspect stub: null; parameter.equals(suspect) = false;  parameter.getNode() == suspect.getNode():  true; .
	at com.intellij.openapi.diagnostic.DefaultLogger.error(DefaultLogger.java:77)
	at com.intellij.openapi.diagnostic.Logger.error(Logger.java:132)
	at com.intellij.psi.impl.PsiImplUtil.getParameterIndex(PsiImplUtil.java:162)
	at com.intellij.psi.impl.source.PsiParameterListImpl.getParameterIndex(PsiParameterListImpl.java:51)
	at com.intellij.codeInsight.AnnotationUtil.getAllAnnotations(AnnotationUtil.java:455)
	at com.android.tools.lint.helpers.DefaultJavaEvaluator.getAllAnnotations(DefaultJavaEvaluator.kt:96)
	at com.vanniktech.lintrules.android.AnnotationOrderDetector$AnnotationOrderVisitor.processAnnotations(AnnotationOrderDetector.kt:159)
	at com.vanniktech.lintrules.android.AnnotationOrderDetector$AnnotationOrderVisitor.visitVariable(AnnotationOrderDetector.kt:149)
	at com.android.tools.lint.client.api.UElementVisitor$DispatchPsiVisitor.visitVariable(UElementVisitor.java:1084)
	at org.jetbrains.uast.visitor.UastVisitor$DefaultImpls.visitParameter(UastVisitor.kt:29)
	at org.jetbrains.uast.visitor.AbstractUastVisitor.visitParameter(UastVisitor.kt:129)
	at com.android.tools.lint.client.api.UElementVisitor$DispatchPsiVisitor.visitParameter(UElementVisitor.java:909)
	at org.jetbrains.uast.UParameter$DefaultImpls.accept(UVariable.kt:72)
	at org.jetbrains.uast.java.JavaUParameter.accept(JavaUVariable.kt:58)
	at org.jetbrains.uast.internal.ImplementationUtilsKt.acceptList(implementationUtils.kt:23)
	at org.jetbrains.uast.UMethod$DefaultImpls.accept(UMethod.kt:52)
	at org.jetbrains.uast.java.JavaUMethod.accept(JavaUMethod.kt:25)
	at org.jetbrains.uast.internal.ImplementationUtilsKt.acceptList(implementationUtils.kt:23)
	at org.jetbrains.uast.UClass$DefaultImpls.accept(UClass.kt:63)
	at org.jetbrains.uast.java.AbstractJavaUClass.accept(JavaUClass.kt:26)
	at org.jetbrains.uast.internal.ImplementationUtilsKt.acceptList(implementationUtils.kt:23)
	at org.jetbrains.uast.UFile$DefaultImpls.accept(UFile.kt:87)
	at org.jetbrains.uast.java.JavaUFile.accept(JavaUFile.kt:27)
	at com.android.tools.lint.client.api.UElementVisitor.lambda$visitFile$7(UElementVisitor.java:299)
	at com.android.tools.lint.client.api.LintClient.runReadAction(LintClient.kt:1482)
	at com.android.tools.lint.client.api.LintDriver$LintClientWrapper.runReadAction(LintDriver.kt:2111)
	at com.android.tools.lint.client.api.UElementVisitor.visitFile(UElementVisitor.java:296)
	at com.android.tools.lint.client.api.LintDriver$visitJavaFiles$1.run(LintDriver.kt:1533)
	at com.android.tools.lint.client.api.LintClient.runReadAction(LintClient.kt:1482)
	at com.android.tools.lint.client.api.LintDriver$LintClientWrapper.runReadAction(LintDriver.kt:2111)
	at com.android.tools.lint.client.api.LintDriver.visitJavaFiles(LintDriver.kt:1533)
	at com.android.tools.lint.client.api.LintDriver.visitJavaFiles(LintDriver.kt:1494)
	at com.android.tools.lint.client.api.LintDriver.checkJava(LintDriver.kt:1472)
	at com.android.tools.lint.client.api.LintDriver.runFileDetectors(LintDriver.kt:1025)
	at com.android.tools.lint.client.api.LintDriver.checkProject(LintDriver.kt:882)
	at com.android.tools.lint.client.api.LintDriver.analyze(LintDriver.kt:385)
	... 47 more
Caused by: java.lang.Throwable
	... 82 more

I also tested 26.1.0-alpha03 and there it's failing too. My calling code looks like this:

class AnnotationOrderVisitor(private val context: JavaContext) : UElementHandler() {
override fun visitVariable(variable: UVariable) {
processAnnotations(variable, variable)
}

override fun visitMethod(method: UMethod) {
processAnnotations(method, method)
}

private fun processAnnotations(element: UElement, modifierListOwner: PsiModifierListOwner) {
val annotations = context.evaluator.getAllAnnotations(modifierListOwner, true).mapNotNull { it.qualifiedName?.split(".")?.lastOrNull() }
...
}

I've also got a link to a PR where I'm trying to use the method here - https://github.com/vanniktech/lint-rules/pull/102

Any help is appreciated.

Tor Norbye

unread,
Nov 12, 2017, 5:33:12 PM11/12/17
to lint-dev
This is a bug in the evaluator.

I'll fix it. In the meantime you can work around this by changing your call
processAnnotations(variable, variable)
to
processAnnotations(variable, variable.psi)

Also, instead of implementing both visitMethod and visitVariable here  you can instead just visit UDeclaration (assuming you're looking for all elements with modifier lists, which for example would also include classes which is a UDeclaration but not a UMethod or UVariable.)

-- Tor

Niklas Baudy

unread,
Nov 14, 2017, 9:37:44 AM11/14/17
to lint-dev
Oh that works. Thank you very much. There's no visitDeclaration. At least I can't find it which one are you refering to?

Tor Norbye

unread,
Nov 17, 2017, 8:19:08 PM11/17/17
to lint-dev
Oh -- you're right, there isn't one in UAST. That's unfortunate. I guess that means you need to add an explicit visit handler for each of UDeclaration's sub-interfaces:
  • UClassInitializer (org.jetbrains.uast)
  • UMethod (org.jetbrains.uast)
  • UClass (org.jetbrains.uast)
  • UVariable (org.jetbrains.uast)
-- Tor

Niklas Baudy

unread,
Nov 18, 2017, 12:33:59 PM11/18/17
to lint-dev
Would it be possible to add the visitDeclaration method?

Tor Norbye

unread,
Nov 29, 2017, 10:35:57 AM11/29/17
to lint-dev
On Saturday, November 18, 2017 at 9:33:59 AM UTC-8, Niklas Baudy wrote:
Would it be possible to add the visitDeclaration method?

I can certainly add it on the UElementHandler. But right now that UHandler *exactly* mirrors the structure of a UastVisitor, so it would probably better if UAST's own visitors offered this. I'll bring that up.

(You might wonder why there is a UElementHandler at all, instead of lint just asking you to create a visitor. In the old lint Java API (the lombok one, and then the PSI one) that's exactly how it worked - you returned a subclass of the general Lombok/PSI visitor. But the purpose of this handler is to have a "shared iteration" of the AST -- you tell lint exactly which node types you're interested in, lint keeps track of that, lint visits the full AST, and invokes the detectors only on the AST nodes they're interested in.  When the callback here was a visitor, it was very tempting/confusing for developers to be implementing a visitor, and NOT calling super.visitWhatever. But if you invoke the super on a recursive visitor, now you're visiting all the nodes in the subtree! So instead, now there's a dedicated handler interface which just asks you to handle that specific node; there's no super implementation and there's no recursive handling of children, so it should be unambiguous and less error prone.)

-- Tor

Niklas Baudy

unread,
Dec 1, 2017, 12:16:11 PM12/1/17
to lint-dev
Thank you. Should I file a bit or do you have it somewhere?

Oh that makes so much sense. Definitely sounds like the current API is better now.

Tor Norbye

unread,
Dec 5, 2017, 10:18:17 AM12/5/17
to lint-dev
I haven't filed it yet, so go for it -- file it on https://youtrack.jetbrains.com/ as a feature request for UAST (I'd include UAST as a prefix of the summary.)

-- Tor

Niklas Baudy

unread,
Dec 6, 2017, 5:33:53 PM12/6/17
to lint-dev
Alright cool. I created it. https://youtrack.jetbrains.com/issue/IDEA-183377 Also I'll mark this as complete. Thanks once again :)

Niklas Baudy

unread,
Jan 20, 2018, 8:47:32 AM1/20/18
to lint-dev
Seems like this was fixed in IntelliJ 2018.1 and can be mirrored soon.

Tor Norbye

unread,
Feb 14, 2018, 9:38:16 AM2/14/18
to lint-dev
Great. We plan to pick up 2018.1 in Studio 3.2.

-- Tor
Reply all
Reply to author
Forward
0 new messages