// INSPECTION_CLASS: com.android.tools.idea.lint.AndroidLintLogConditionalInspection // INSPECTION_CLASS2: com.android.tools.idea.lint.AndroidLintLogTagMismatchInspection // INSPECTION_CLASS3: com.android.tools.idea.lint.AndroidLintLongLogTagInspection import android.annotation.SuppressLint import android.util.Log import android.util.Log.DEBUG @SuppressWarnings("UnusedDeclaration") @Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") class LogTest { fun checkConditional(m: String) { Log.d(TAG1, "message") // ok: unconditional, but not performing computation Log.d(TAG1, m) // ok: unconditional, but not performing computation Log.d(TAG1, "a" + "b") // ok: unconditional, but not performing non-constant computation Log.d(TAG1, Constants.MY_MESSAGE) // ok: unconditional, but constant string Log.i(TAG1, "message" + m) // error: unconditional w/ computation Log.i(TAG1, toString()) // error: unconditional w/ computation Log.e(TAG1, toString()) // ok: only flagging debug/info messages Log.w(TAG1, toString()) // ok: only flagging debug/info messages Log.wtf(TAG1, toString()) // ok: only flagging debug/info messages if (Log.isLoggable(TAG1, 0)) { Log.d(TAG1, toString()) // ok: conditional } } fun checkWrongTag(tag: String) { if (Log.isLoggable(TAG1, Log.DEBUG)) { Log.d(TAG2, "message") // warn: mismatched tags! } if (Log.isLoggable("my_tag", Log.DEBUG)) { Log.d("other_tag", "message") // warn: mismatched tags! } if (Log.isLoggable("my_tag", Log.DEBUG)) { Log.d("my_tag", "message") // ok: strings equal } if (Log.isLoggable(tag, Log.DEBUG)) { Log.d(tag, "message") // ok: same variable } } fun checkLongTag(shouldLog: Boolean) { if (shouldLog) { // String literal tags Log.d("short_tag", "message") // ok: short Log.d("really_really_really_really_really_long_tag", "message") // error: too long // Resolved field tags Log.d(TAG1, "message") // ok: short Log.d(TAG22, "message") // ok: short Log.d(TAG23, "message") // ok: threshold Log.d(TAG24, "message") // error: too long Log.d(LONG_TAG, "message") // error: way too long // Locally defined variable tags val LOCAL_TAG = "MyReallyReallyReallyReallyReallyLongTag" Log.d(LOCAL_TAG, "message") // error: too long // Concatenated tags Log.d(TAG22 + TAG1, "message") // error: too long Log.d(TAG22 + "MyTag", "message") // error: too long } } fun checkWrongLevel(tag: String) { if (Log.isLoggable(TAG1, Log.DEBUG)) { Log.d(TAG1, "message") // ok: right level } if (Log.isLoggable(TAG1, Log.INFO)) { Log.i(TAG1, "message") // ok: right level } if (Log.isLoggable(TAG1, Log.DEBUG)) { Log.v(TAG1, "message") // warn: wrong level } if (Log.isLoggable(TAG1, DEBUG)) { // static import of level Log.v(TAG1, "message") // warn: wrong level } if (Log.isLoggable(TAG1, Log.VERBOSE)) { Log.d(TAG1, "message") // warn? verbose is a lower logging level, which includes debug } if (Log.isLoggable(TAG1, Constants.MY_LEVEL)) { Log.d(TAG1, "message") // ok: unknown level alias } } @SuppressLint("all") fun suppressed1() { Log.d(TAG1, "message") // ok: suppressed } @SuppressLint("LogConditional") fun suppressed2() { Log.d(TAG1, "message") // ok: suppressed } private object Constants { val MY_MESSAGE = "My Message" val MY_LEVEL = 5 } companion object { private val TAG1 = "MyTag1" private val TAG2 = "MyTag2" private val TAG22 = "1234567890123456789012" private val TAG23 = "12345678901234567890123" private val TAG24 = "123456789012345678901234" private val LONG_TAG = "MyReallyReallyReallyReallyReallyLongTag" } }