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:
Vyacheslav Gerasimov
2017-01-24 13:38:06 +03:00
parent d0f1b81bfa
commit 4fe040eeb9
4 changed files with 531 additions and 2052 deletions
+178 -18
View File
@@ -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)
}
}