Fixed several bugs in Android lint ApiDetector (KT-15002, KT-12024, KT-14737, KT-14825, KT-12023, KT-15018)
Merged IntelliJApiDetector to ApiDetector #KT-15002 Fixed #KT-12024 Fixed #KT-14737 Fixed #KT-14825 Fixed #KT-12023 Fixed #KT-15018 Fixed (cherry picked from commit e830e8b55fa2e354303a6c604b3905285a05b9db)
This commit is contained in:
+178
-18
@@ -4,6 +4,7 @@
|
||||
// INSPECTION_CLASS3: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintOverrideInspection
|
||||
|
||||
import android.animation.RectEvaluator
|
||||
import android.annotation.SuppressLint
|
||||
import android.annotation.TargetApi
|
||||
import org.w3c.dom.DOMError
|
||||
import org.w3c.dom.DOMErrorHandler
|
||||
@@ -14,6 +15,7 @@ import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams
|
||||
import android.app.Activity
|
||||
import android.app.ApplicationErrorReport
|
||||
import android.graphics.drawable.VectorDrawable
|
||||
import android.graphics.Path
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.Rect
|
||||
@@ -22,7 +24,7 @@ import android.widget.*
|
||||
import dalvik.bytecode.OpcodeInfo
|
||||
|
||||
import android.os.Build.VERSION
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import <warning descr="Field requires API level 4 (current min is 1): `android.os.Build.VERSION#SDK_INT`">android.os.Build.VERSION.SDK_INT</warning>
|
||||
import android.os.Build.VERSION_CODES
|
||||
import android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH
|
||||
import android.os.Build.VERSION_CODES.JELLY_BEAN
|
||||
@@ -30,7 +32,7 @@ import android.os.Bundle
|
||||
import android.system.ErrnoException
|
||||
import android.widget.TextView
|
||||
|
||||
@Suppress("SENSELESS_COMPARISON", "UNUSED_EXPRESSION", "UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION")
|
||||
@Suppress("SENSELESS_COMPARISON", "UNUSED_EXPRESSION", "UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION", "USELESS_CAST")
|
||||
class ApiCallTest: Activity() {
|
||||
|
||||
fun method(chronometer: Chronometer, locator: DOMLocator) {
|
||||
@@ -39,8 +41,7 @@ class ApiCallTest: Activity() {
|
||||
// Ok
|
||||
Bundle().getInt("")
|
||||
|
||||
// Ok, this constant is inlined
|
||||
View.<warning descr="Field requires API level 16 (current min is 1): android.view.View#SYSTEM_UI_FLAG_FULLSCREEN">SYSTEM_UI_FLAG_FULLSCREEN</warning>
|
||||
View.<warning descr="Field requires API level 16 (current min is 1): `android.view.View#SYSTEM_UI_FLAG_FULLSCREEN`">SYSTEM_UI_FLAG_FULLSCREEN</warning>
|
||||
|
||||
// Virtual call
|
||||
<error descr="Call requires API level 11 (current min is 1): android.app.Activity#getActionBar">getActionBar</error>() // API 11
|
||||
@@ -48,7 +49,7 @@ class ApiCallTest: Activity() {
|
||||
|
||||
// Class references (no call or field access)
|
||||
val error: DOMError? = null // API 8
|
||||
val clz = DOMErrorHandler::class // API 8
|
||||
val clz = <error descr="Class requires API level 8 (current min is 1): org.w3c.dom.DOMErrorHandler">DOMErrorHandler::class</error> // API 8
|
||||
|
||||
// Method call
|
||||
chronometer.<error descr="Call requires API level 3 (current min is 1): android.widget.Chronometer#getOnChronometerTickListener">onChronometerTickListener</error> // API 3
|
||||
@@ -56,21 +57,21 @@ class ApiCallTest: Activity() {
|
||||
// Inherited method call (from TextView
|
||||
chronometer.<error descr="Call requires API level 11 (current min is 1): android.widget.TextView#setTextIsSelectable">setTextIsSelectable</error>(true) // API 11
|
||||
|
||||
GridLayout::class
|
||||
<error descr="Class requires API level 14 (current min is 1): android.widget.GridLayout">GridLayout::class</error>
|
||||
|
||||
// Field access
|
||||
val field = OpcodeInfo.<warning descr="Field requires API level 11 (current min is 1): dalvik.bytecode.OpcodeInfo#MAXIMUM_VALUE">MAXIMUM_VALUE</warning> // API 11
|
||||
val field = OpcodeInfo.<warning descr="Field requires API level 11 (current min is 1): `dalvik.bytecode.OpcodeInfo#MAXIMUM_VALUE`">MAXIMUM_VALUE</warning> // API 11
|
||||
|
||||
|
||||
val fillParent = LayoutParams.FILL_PARENT // API 1
|
||||
// This is a final int, which means it gets inlined
|
||||
val matchParent = LayoutParams.MATCH_PARENT // API 8
|
||||
// Field access: non final
|
||||
val batteryInfo = report!!.<error descr="Field requires API level 14 (current min is 1): android.app.ApplicationErrorReport#batteryInfo">batteryInfo</error>
|
||||
val batteryInfo = report!!.<error descr="Field requires API level 14 (current min is 1): `android.app.ApplicationErrorReport#batteryInfo`">batteryInfo</error>
|
||||
|
||||
// Enum access
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
|
||||
val mode = PorterDuff.Mode.<error descr="Field requires API level 11 (current min is 1): android.graphics.PorterDuff.Mode#OVERLAY">OVERLAY</error> // API 11
|
||||
val mode = PorterDuff.Mode.<error descr="Field requires API level 11 (current min is 1): `android.graphics.PorterDuff.Mode#OVERLAY`">OVERLAY</error> // API 11
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,12 +116,6 @@ class ApiCallTest: Activity() {
|
||||
}
|
||||
|
||||
fun test(priority: Boolean, layout: ViewGroup) {
|
||||
if (layout is LinearLayout) {}
|
||||
layout as? LinearLayout
|
||||
|
||||
if (layout is GridLayout) {}
|
||||
layout as? GridLayout
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
GridLayout(null).getOrientation(); // Not flagged
|
||||
} else {
|
||||
@@ -250,14 +245,22 @@ class ApiCallTest: Activity() {
|
||||
//ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT >= JELLY_BEAN && textView.<error descr="Call requires API level 14 (current min is 1): android.widget.TextView#isSuggestionsEnabled">isSuggestionsEnabled</error>()) {
|
||||
if (SDK_INT >= JELLY_BEAN && textView.isSuggestionsEnabled()) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT >= JELLY_BEAN && textView.<error descr="Call requires API level 14 (current min is 1): android.widget.TextView#isSuggestionsEnabled">isSuggestionsEnabled</error>) {
|
||||
if (SDK_INT >= JELLY_BEAN && textView.isSuggestionsEnabled) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT >= JELLY_BEAN && (textView.text != "" || textView.isSuggestionsEnabled)) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT < JELLY_BEAN && (textView.text != "" || textView.<error descr="Call requires API level 14 (current min is 1): android.widget.TextView#isSuggestionsEnabled">isSuggestionsEnabled</error>)) {
|
||||
//ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT < JELLY_BEAN && textView.<error descr="Call requires API level 14 (current min is 1): android.widget.TextView#isSuggestionsEnabled">isSuggestionsEnabled</error>()) {
|
||||
//ERROR
|
||||
}
|
||||
@@ -265,10 +268,108 @@ class ApiCallTest: Activity() {
|
||||
if (SDK_INT < JELLY_BEAN && textView.<error descr="Call requires API level 14 (current min is 1): android.widget.TextView#isSuggestionsEnabled">isSuggestionsEnabled</error>) {
|
||||
//ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT < JELLY_BEAN || textView.isSuggestionsEnabled) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT > JELLY_BEAN || textView.<error descr="Call requires API level 14 (current min is 1): android.widget.TextView#isSuggestionsEnabled">isSuggestionsEnabled</error>) {
|
||||
//ERROR
|
||||
}
|
||||
|
||||
|
||||
// getActionBar() API 11
|
||||
if (SDK_INT <= 10 || getActionBar() == null) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT < 10 || <error descr="Call requires API level 11 (current min is 1): android.app.Activity#getActionBar">getActionBar</error>() == null) {
|
||||
//ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT < 11 || getActionBar() == null) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT != 11 || getActionBar() == null) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT != 12 || <error descr="Call requires API level 11 (current min is 1): android.app.Activity#getActionBar">getActionBar</error>() == null) {
|
||||
//ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT <= 11 || getActionBar() == null) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT < 12 || getActionBar() == null) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT <= 12 || getActionBar() == null) {
|
||||
//NO ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT < 9 || <error descr="Call requires API level 11 (current min is 1): android.app.Activity#getActionBar">getActionBar</error>() == null) {
|
||||
//ERROR
|
||||
}
|
||||
|
||||
if (SDK_INT <= 9 || <error descr="Call requires API level 11 (current min is 1): android.app.Activity#getActionBar">getActionBar</error>() == null) {
|
||||
//ERROR
|
||||
}
|
||||
}
|
||||
|
||||
fun testReturn() {
|
||||
if (SDK_INT < 11) {
|
||||
return
|
||||
}
|
||||
|
||||
// No Error
|
||||
val actionBar = getActionBar()
|
||||
}
|
||||
|
||||
fun testThrow() {
|
||||
if (SDK_INT < 11) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
// No Error
|
||||
val actionBar = getActionBar()
|
||||
}
|
||||
|
||||
fun testError() {
|
||||
if (SDK_INT < 11) {
|
||||
error("Api")
|
||||
}
|
||||
|
||||
// No Error
|
||||
val actionBar = getActionBar()
|
||||
}
|
||||
|
||||
fun testWithoutAnnotation(textView: TextView) {
|
||||
if (textView.<error descr="Call requires API level 14 (current min is 1): android.widget.TextView#isSuggestionsEnabled">isSuggestionsEnabled</error>()) {
|
||||
|
||||
}
|
||||
|
||||
if (textView.<error descr="Call requires API level 14 (current min is 1): android.widget.TextView#isSuggestionsEnabled">isSuggestionsEnabled</error>) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(JELLY_BEAN)
|
||||
fun testWithAnnotation(textView: TextView) {
|
||||
fun testWithTargetApiAnnotation(textView: TextView) {
|
||||
if (textView.isSuggestionsEnabled()) {
|
||||
//NO ERROR, annotation
|
||||
}
|
||||
|
||||
if (textView.isSuggestionsEnabled) {
|
||||
//NO ERROR, annotation
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
fun testWithSuppressLintAnnotation(textView: TextView) {
|
||||
if (textView.isSuggestionsEnabled()) {
|
||||
//NO ERROR, annotation
|
||||
}
|
||||
@@ -291,6 +392,59 @@ class ApiCallTest: Activity() {
|
||||
Path().<error descr="Call requires API level 21 (current min is 1): android.graphics.Path#addOval">addOval</error>(0f, 0f, 0f, 0f, Path.Direction.CW)
|
||||
}
|
||||
|
||||
// KT-14737 False error with short-circuit evaluation
|
||||
fun testShortCircuitEvaluation() {
|
||||
<error descr="Call requires API level 21 (current min is 1): android.content.Context#getDrawable">getDrawable</error>(0) // error here as expected
|
||||
if(Build.VERSION.SDK_INT >= 23
|
||||
&& null == getDrawable(0)) // error here should not occur
|
||||
{
|
||||
getDrawable(0) // no error here as expected
|
||||
}
|
||||
}
|
||||
|
||||
// KT-1482 Kotlin Lint: "Calling new methods on older versions" does not report call on receiver in extension function
|
||||
private fun Bundle.caseE1a() { <error descr="Call requires API level 18 (current min is 1): android.os.Bundle#getBinder">getBinder</error>("") }
|
||||
|
||||
private fun Bundle.caseE1c() { this.<error descr="Call requires API level 18 (current min is 1): android.os.Bundle#getBinder">getBinder</error>("") }
|
||||
|
||||
private fun caseE1b(bundle: Bundle) { bundle.<error descr="Call requires API level 18 (current min is 1): android.os.Bundle#getBinder">getBinder</error>("") }
|
||||
|
||||
// KT-12023 Kotlin Lint: Cast doesn't trigger minSdk error
|
||||
fun testCast(layout: ViewGroup) {
|
||||
if (layout is LinearLayout) {} // OK API 1
|
||||
layout as? LinearLayout // OK API 1
|
||||
layout as LinearLayout // OK API 1
|
||||
|
||||
if (layout !is GridLayout) {} // TODO: should be error, fixed in uast > 1.0.8
|
||||
layout as? GridLayout // TODO: should be error, fixed in uast > 1.0.8
|
||||
layout as GridLayout // TODO: should be error, fixed in uast > 1.0.8
|
||||
|
||||
val grid = layout as? GridLayout // TODO: should be error, fixed in uast > 1.0.8
|
||||
val linear = layout as LinearLayout // OK API 1
|
||||
}
|
||||
|
||||
// TODO: should be error
|
||||
class ErrorVectorDravable : VectorDrawable()
|
||||
|
||||
@TargetApi(21)
|
||||
class MyVectorDravable : VectorDrawable()
|
||||
|
||||
fun testTypes() {
|
||||
<error descr="Call requires API level 14 (current min is 1): android.widget.GridLayout#GridLayout">GridLayout</error>(this)
|
||||
val c = <error descr="Class requires API level 21 (current min is 1): android.graphics.drawable.VectorDrawable">VectorDrawable::class</error>.java
|
||||
}
|
||||
|
||||
fun testCallWithApiAnnotation(textView: TextView) {
|
||||
<error descr="Call requires API level 21 (current min is 1): ApiCallTest.MyVectorDravable#MyVectorDravable">MyVectorDravable</error>()
|
||||
<error descr="Call requires API level 16 (current min is 1): ApiCallTest#testWithTargetApiAnnotation">testWithTargetApiAnnotation</error>(textView)
|
||||
}
|
||||
|
||||
companion object : Activity() {
|
||||
fun test() {
|
||||
<error descr="Call requires API level 21 (current min is 1): android.content.Context#getDrawable">getDrawable</error>(0)
|
||||
}
|
||||
}
|
||||
|
||||
// Return type
|
||||
internal // API 14
|
||||
val gridLayout: GridLayout?
|
||||
@@ -298,4 +452,10 @@ class ApiCallTest: Activity() {
|
||||
|
||||
private val report: ApplicationErrorReport?
|
||||
get() = null
|
||||
}
|
||||
|
||||
object O: Activity() {
|
||||
fun test() {
|
||||
<error descr="Call requires API level 21 (current min is 1): android.content.Context#getDrawable">getDrawable</error>(0)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user