From eb28ce3007a570aa45609a239a034eca2b8a0853 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Mon, 3 Dec 2018 22:37:41 +0900 Subject: [PATCH] Fix Android Lint tests (182 bunch only) --- idea/testData/android/lint/apiCheck.kt | 18 +- idea/testData/android/lint/closeCursor.kt | 2 +- idea/testData/android/lint/commitFragment.kt | 2 +- idea/testData/android/lint/javaPerformance.kt | 4 +- .../android/lint/javaPerformance.kt.181 | 193 ++++++++++++++++++ 5 files changed, 206 insertions(+), 13 deletions(-) create mode 100644 idea/testData/android/lint/javaPerformance.kt.181 diff --git a/idea/testData/android/lint/apiCheck.kt b/idea/testData/android/lint/apiCheck.kt index af027213faf..cc9ffdc4dc6 100644 --- a/idea/testData/android/lint/apiCheck.kt +++ b/idea/testData/android/lint/apiCheck.kt @@ -50,7 +50,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 = DOMErrorHandler::class // API 8 // Method call chronometer.onChronometerTickListener // API 3 @@ -58,7 +58,7 @@ class ApiCallTest: Activity() { // Inherited method call (from TextView chronometer.setTextIsSelectable(true) // API 11 - GridLayout::class + GridLayout::class // Field access val field = OpcodeInfo.MAXIMUM_VALUE // API 11 @@ -292,7 +292,7 @@ class ApiCallTest: Activity() { //NO ERROR } - if (SDK_INT != 11 || getActionBar() == null) { + if (SDK_INT != 11 || getActionBar() == null) { //NO ERROR } @@ -336,7 +336,7 @@ class ApiCallTest: Activity() { } // No Error - val actionBar = getActionBar() + val actionBar = getActionBar() } fun testError() { @@ -345,7 +345,7 @@ class ApiCallTest: Activity() { } // No Error - val actionBar = getActionBar() + val actionBar = getActionBar() } fun testWithoutAnnotation(textView: TextView) { @@ -431,12 +431,12 @@ class ApiCallTest: Activity() { fun testTypes() { GridLayout(this) - val c = VectorDrawable::class.java + val c = VectorDrawable::class.java } fun testCallWithApiAnnotation(textView: TextView) { - MyVectorDravable() - testWithTargetApiAnnotation(textView) + MyVectorDravable() + testWithTargetApiAnnotation(textView) } companion object : Activity() { @@ -472,7 +472,7 @@ fun testJava8() { } // Error, Api 24, Java8 - mapOf(1 to 2).forEach { key, value -> key + value } + mapOf(1 to 2).forEach { key, value -> key + value } // Ok, Kotlin mapOf(1 to 2).forEach { (key, value) -> key + value } diff --git a/idea/testData/android/lint/closeCursor.kt b/idea/testData/android/lint/closeCursor.kt index 82a01cd75cf..a9046c86ed4 100644 --- a/idea/testData/android/lint/closeCursor.kt +++ b/idea/testData/android/lint/closeCursor.kt @@ -13,7 +13,7 @@ class MainActivity : Activity() { val cursor = contentResolver.query(null, null, null, null, null) // WARNING - contentResolver.query(null, null, null, null, null) + contentResolver.query(null, null, null, null, null) // OK, closed in chained call contentResolver.query(null, null, null, null, null).close() diff --git a/idea/testData/android/lint/commitFragment.kt b/idea/testData/android/lint/commitFragment.kt index 25ad12e680c..00470e0cdb0 100644 --- a/idea/testData/android/lint/commitFragment.kt +++ b/idea/testData/android/lint/commitFragment.kt @@ -36,6 +36,6 @@ class MainActivity : Activity() { // KT-14780: Kotlin Lint: "Missing commit() calls" false positive when the result of `commit()` is assigned or used as receiver fun testResultOfCommit(fm: FragmentManager) { val r1 = fm.beginTransaction().hide(fm.findFragmentByTag("aTag")).commit() - val r2 = fm.beginTransaction().hide(fm.findFragmentByTag("aTag")).commit().toString() + val r2 = fm.beginTransaction().hide(fm.findFragmentByTag("aTag")).commit().toString() } } diff --git a/idea/testData/android/lint/javaPerformance.kt b/idea/testData/android/lint/javaPerformance.kt index 0bf3b5f0957..cd2f66d551f 100644 --- a/idea/testData/android/lint/javaPerformance.kt +++ b/idea/testData/android/lint/javaPerformance.kt @@ -73,7 +73,7 @@ class JavaPerformanceTest(context: Context, attrs: AttributeSet, defStyle: Int) // This one should not be reported: @SuppressLint("UseSparseArrays") - val myOtherMap = HashMap() + val myOtherMap = HashMap() } protected fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int, @@ -113,7 +113,7 @@ class JavaPerformanceTest(context: Context, attrs: AttributeSet, defStyle: Int) BitmapFactory.decodeFile(null) val canvas: Canvas? = null canvas!!.getClipBounds() // allocates on your behalf - canvas.clipBounds // allocates on your behalf + canvas.clipBounds // allocates on your behalf canvas.getClipBounds(null) // NOT an error val layoutWidth = width diff --git a/idea/testData/android/lint/javaPerformance.kt.181 b/idea/testData/android/lint/javaPerformance.kt.181 new file mode 100644 index 00000000000..0bf3b5f0957 --- /dev/null +++ b/idea/testData/android/lint/javaPerformance.kt.181 @@ -0,0 +1,193 @@ +// INSPECTION_CLASS: com.android.tools.idea.lint.AndroidLintDrawAllocationInspection +// INSPECTION_CLASS2: com.android.tools.idea.lint.AndroidLintUseSparseArraysInspection +// INSPECTION_CLASS3: com.android.tools.idea.lint.AndroidLintUseValueOfInspection + +import android.annotation.SuppressLint +import java.util.HashMap +import android.content.Context +import android.graphics.* +import android.util.AttributeSet +import android.util.SparseArray +import android.widget.Button + +@SuppressWarnings("unused") +@Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") +class JavaPerformanceTest(context: Context, attrs: AttributeSet, defStyle: Int) : Button(context, attrs, defStyle) { + + private var cachedRect: Rect? = null + private var shader: LinearGradient? = null + private var lastHeight: Int = 0 + private var lastWidth: Int = 0 + + override fun onDraw(canvas: android.graphics.Canvas) { + super.onDraw(canvas) + + // Various allocations: + java.lang.String("foo") + val s = java.lang.String("bar") + + // This one should not be reported: + @SuppressLint("DrawAllocation") + val i = 5 + + // Cached object initialized lazily: should not complain about these + if (cachedRect == null) { + cachedRect = Rect(0, 0, 100, 100) + } + if (cachedRect == null || cachedRect!!.width() != 50) { + cachedRect = Rect(0, 0, 50, 100) + } + + val b = java.lang.Boolean.valueOf(true)!! // auto-boxing + dummy(1, 2) + + // Non-allocations + super.animate() + dummy2(1, 2) + + // This will involve allocations, but we don't track + // inter-procedural stuff here + someOtherMethod() + } + + internal fun dummy(foo: Int?, bar: Int) { + dummy2(foo!!, bar) + } + + internal fun dummy2(foo: Int, bar: Int) { + } + + internal fun someOtherMethod() { + // Allocations are okay here + java.lang.String("foo") + val s = java.lang.String("bar") + val b = java.lang.Boolean.valueOf(true)!! // auto-boxing + + + // Sparse array candidates + val myMap = HashMap() + // Should use SparseBooleanArray + val myBoolMap = HashMap() + // Should use SparseIntArray + val myIntMap = java.util.HashMap() + + // This one should not be reported: + @SuppressLint("UseSparseArrays") + val myOtherMap = HashMap() + } + + protected fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int, + x: Boolean) { + // wrong signature + java.lang.String("not an error") + } + + protected fun onMeasure(widthMeasureSpec: Int) { + // wrong signature + java.lang.String("not an error") + } + + protected fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, + bottom: Int, wrong: Int) { + // wrong signature + java.lang.String("not an error") + } + + protected fun onLayout(changed: Boolean, left: Int, top: Int, right: Int) { + // wrong signature + java.lang.String("not an error") + } + + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, + bottom: Int) { + java.lang.String("flag me") + } + + @SuppressWarnings("null") // not real code + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + java.lang.String("flag me") + + // Forbidden factory methods: + Bitmap.createBitmap(100, 100, null) + android.graphics.Bitmap.createScaledBitmap(null, 100, 100, false) + BitmapFactory.decodeFile(null) + val canvas: Canvas? = null + canvas!!.getClipBounds() // allocates on your behalf + canvas.clipBounds // allocates on your behalf + canvas.getClipBounds(null) // NOT an error + + val layoutWidth = width + val layoutHeight = height + if (mAllowCrop && (mOverlay == null || mOverlay!!.width != layoutWidth || + mOverlay!!.height != layoutHeight)) { + mOverlay = Bitmap.createBitmap(layoutWidth, layoutHeight, Bitmap.Config.ARGB_8888) + mOverlayCanvas = Canvas(mOverlay!!) + } + + if (widthMeasureSpec == 42) { + throw IllegalStateException("Test") // NOT an allocation + } + + // More lazy init tests + var initialized = false + if (!initialized) { + java.lang.String("foo") + initialized = true + } + + // NOT lazy initialization + if (!initialized || mOverlay == null) { + java.lang.String("foo") + } + } + + internal fun factories() { + val i1 = 42 + val l1 = 42L + val b1 = true + val c1 = 'c' + val f1 = 1.0f + val d1 = 1.0 + + // The following should not generate errors: + val i3 = Integer.valueOf(42) + } + + private val mAllowCrop: Boolean = false + private var mOverlayCanvas: Canvas? = null + private var mOverlay: Bitmap? = null + + override fun layout(l: Int, t: Int, r: Int, b: Int) { + // Using "this." to reference fields + if (this.shader == null) + this.shader = LinearGradient(0f, 0f, width.toFloat(), 0f, intArrayOf(0), null, + Shader.TileMode.REPEAT) + + val width = width + val height = height + + if (shader == null || lastWidth != width || lastHeight != height) { + lastWidth = width + lastHeight = height + + shader = LinearGradient(0f, 0f, width.toFloat(), 0f, intArrayOf(0), null, Shader.TileMode.REPEAT) + } + } + + fun inefficientSparseArray() { + SparseArray() // Use SparseIntArray instead + SparseArray() // Use SparseLongArray instead + SparseArray() // Use SparseBooleanArray instead + SparseArray() // OK + } + + fun longSparseArray() { + // but only minSdkVersion >= 17 or if has v4 support lib + val myStringMap = HashMap() + } + + fun byteSparseArray() { + // bytes easily apply to ints + val myByteMap = HashMap() + } +}