Exception() resolved as <init>()?

102 views
Skip to first unread message

John Rodriguez

unread,
Aug 8, 2021, 5:15:26 PM8/8/21
to lint-dev
I'm updating some broken Timber lints to work better with Kotlin consumers and noticed an interesting phenomenon when running the "usingAndroidLogWithThreeArguments" test on this Kotlin source:

package foo
import android.util.Log
class Example {
  fun log() {
    Log.d("TAG", "msg", Exception())
  }
}

Expected quickfix suggestion:

|Fix for src/foo/Example.kt line 5: Replace with Timber.d(Exception(), "msg"):
|@@ -5 +5
|- Log.d("TAG", "msg", Exception())
|+ Timber.d(Exception(), "msg")

Actual quickfix suggestion:

|Fix for src/foo/Example.kt line 5: Replace with Timber.d(<init>(), "msg"):
|@@ -5 +5
|- Log.d("TAG", "msg", <init>())
|+ Timber.d(<init>(), "msg")

The issue goes away if I use an Exception overload (i.e., Exception(String) or Exception(Throwable)).

Any idea why the empty constructor overload of Exception would resolve to <init>()?

John Rodriguez

unread,
Aug 8, 2021, 5:19:43 PM8/8/21
to lint-dev
Oops, I was mistaken about the overloads.  Those seem to fail as well:

Did not find "Log.d("TAG", "msg", <init>("foo"))" in "Log.d("TAG", "msg", Exception("foo"))" as suggested in the quickfix. Consider calling ReplaceStringBuilder#range() to set a larger range to search than the default highlight range.

Tor Norbye

unread,
Aug 8, 2021, 5:26:31 PM8/8/21
to John Rodriguez, lint-dev
This is the corresponding code which constructs the lintfix, right?

I think the problem is that you're using element.asSourceString() here -- use element.sourcePsi?.text instead. 

--
You received this message because you are subscribed to the Google Groups "lint-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lint-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lint-dev/f4ab4d60-4bf4-4fe5-a0ca-a2866e811eb9n%40googlegroups.com.

John Rodriguez

unread,
Aug 8, 2021, 5:36:45 PM8/8/21
to lint-dev
Yes, that's the corresponding code.

And updating to element.sourcePsi?.text in those call sites and the following logCall call site (https://github.com/JakeWharton/timber/blob/01aee4b914e7a17fba9feafb2610b876dacaa8dc/timber-lint/src/main/java/timber/lint/WrongTimberUsageDetector.java#L678) worked!

Thanks!

By the way, is that the general recommendation, to use element.sourcePsi?.text instead of asSourceString()?

Tor Norbye

unread,
Aug 8, 2021, 5:46:25 PM8/8/21
to John Rodriguez, lint-dev
On Sun, Aug 8, 2021 at 2:36 PM 'John Rodriguez' via lint-dev <lint...@googlegroups.com> wrote:
Yes, that's the corresponding code.

And updating to element.sourcePsi?.text in those call sites and the following logCall call site (https://github.com/JakeWharton/timber/blob/01aee4b914e7a17fba9feafb2610b876dacaa8dc/timber-lint/src/main/java/timber/lint/WrongTimberUsageDetector.java#L678) worked!

Thanks!

By the way, is that the general recommendation, to use element.sourcePsi?.text instead of asSourceString()?

asSourceString doesn't seem to be very well supported in UAST; you can think of it a bit like a decompiler -- it takes the AST and attempts to compute source back from it, but in some cases that source doesn't look the same way as the original (since multiple different forms can map to the same AST representation), and in some cases, you end up with some strange source. If what you're trying to do is pick up exactly what the source is, always use sourcePsi?.text. If source psi is null, that tells you that this is a synthetic element which doesn't have source (for example, if you have a Kotlin file that has a top level function, the "class" that UAST will put those methods inside will have null sourcePsi).

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