diff options
Diffstat (limited to 'lint/cli')
-rw-r--r-- | lint/cli/.classpath | 10 | ||||
-rw-r--r-- | lint/cli/src/test/.classpath | 8 | ||||
-rw-r--r-- | lint/cli/src/test/java/com/android/tools/lint/checks/RecycleDetectorTest.java | 76 | ||||
-rw-r--r-- | lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/RecycleTest.class.data | bin | 0 -> 4321 bytes | |||
-rw-r--r-- | lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/RecycleTest.java.txt | 159 |
5 files changed, 244 insertions, 9 deletions
diff --git a/lint/cli/.classpath b/lint/cli/.classpath index ade4f41..3278842 100644 --- a/lint/cli/.classpath +++ b/lint/cli/.classpath @@ -5,11 +5,11 @@ <classpathentry combineaccessrules="false" kind="src" path="/common"/> <classpathentry combineaccessrules="false" kind="src" path="/lint-api"/> <classpathentry combineaccessrules="false" kind="src" path="/lint-checks"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-tree-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-analysis-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-13.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src-4.0.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-tree-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src-4.0.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-analysis-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src-4.0.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-13.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src-4.0.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src-4.0.zip"/> <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/lint/cli/src/test/.classpath b/lint/cli/src/test/.classpath index 178cd8c..e79b65f 100644 --- a/lint/cli/src/test/.classpath +++ b/lint/cli/src/test/.classpath @@ -7,10 +7,10 @@ <classpathentry combineaccessrules="false" kind="src" path="/lint-api"/> <classpathentry combineaccessrules="false" kind="src" path="/lint-checks"/> <classpathentry combineaccessrules="false" kind="src" path="/lint-cli"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-tree-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-13.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src.zip"/> - <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src-4.0.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-tree-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src-4.0.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-13.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src-4.0.zip"/> + <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/lombok-ast/lombok-ast-0.2.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/lombok-ast/src-4.0.zip"/> <classpathentry combineaccessrules="false" kind="src" path="/layoutlib_api"/> <classpathentry combineaccessrules="false" kind="src" path="/common"/> <classpathentry combineaccessrules="false" kind="src" path="/testutils"/> diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/RecycleDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/RecycleDetectorTest.java new file mode 100644 index 0000000..ebef046 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/RecycleDetectorTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.tools.lint.checks; + +import com.android.tools.lint.detector.api.Detector; + +@SuppressWarnings("javadoc") +public class RecycleDetectorTest extends AbstractCheckTest { + @Override + protected Detector getDetector() { + return new RecycleDetector(); + } + + public void test() throws Exception { + assertEquals( + "src/test/pkg/RecycleTest.java:56: Warning: This TypedArray should be recycled after use with #recycle() [Recycle]\n" + + " final TypedArray a = getContext().obtainStyledAttributes(attrs,\n" + + " ~~~~~~~~~~~~~~~~~~~~~~\n" + + "src/test/pkg/RecycleTest.java:63: Warning: This TypedArray should be recycled after use with #recycle() [Recycle]\n" + + " final TypedArray a = getContext().obtainStyledAttributes(new int[0]);\n" + + " ~~~~~~~~~~~~~~~~~~~~~~\n" + + "src/test/pkg/RecycleTest.java:79: Warning: This VelocityTracker should be recycled after use with #recycle() [Recycle]\n" + + " VelocityTracker tracker = VelocityTracker.obtain();\n" + + " ~~~~~~\n" + + "src/test/pkg/RecycleTest.java:85: Warning: This Message should be recycled after use with #recycle() [Recycle]\n" + + " Message message1 = getHandler().obtainMessage();\n" + + " ~~~~~~~~~~~~~\n" + + "src/test/pkg/RecycleTest.java:86: Warning: This Message should be recycled after use with #recycle() [Recycle]\n" + + " Message message2 = Message.obtain();\n" + + " ~~~~~~\n" + + "src/test/pkg/RecycleTest.java:92: Warning: This MotionEvent should be recycled after use with #recycle() [Recycle]\n" + + " MotionEvent event1 = MotionEvent.obtain(null);\n" + + " ~~~~~~\n" + + "src/test/pkg/RecycleTest.java:93: Warning: This MotionEvent should be recycled after use with #recycle() [Recycle]\n" + + " MotionEvent event2 = MotionEvent.obtainNoHistory(null);\n" + + " ~~~~~~~~~~~~~~~\n" + + "src/test/pkg/RecycleTest.java:98: Warning: This MotionEvent should be recycled after use with #recycle() [Recycle]\n" + + " MotionEvent event2 = MotionEvent.obtainNoHistory(null); // Not recycled\n" + + " ~~~~~~~~~~~~~~~\n" + + "src/test/pkg/RecycleTest.java:103: Warning: This MotionEvent should be recycled after use with #recycle() [Recycle]\n" + + " MotionEvent event1 = MotionEvent.obtain(null); // Not recycled\n" + + " ~~~~~~\n" + + "src/test/pkg/RecycleTest.java:113: Warning: This MotionEvent has already been recycled [Recycle]\n" + + " int contents2 = event1.describeContents(); // BAD, after recycle\n" + + " ~~~~~~~~~~~~~~~~\n" + + "src/test/pkg/RecycleTest.java:117: Warning: This TypedArray has already been recycled [Recycle]\n" + + " example = a.getString(R.styleable.MyView_exampleString); // BAD, after recycle\n" + + " ~~~~~~~~~\n" + + "src/test/pkg/RecycleTest.java:129: Warning: This Parcel should be recycled after use with #recycle() [Recycle]\n" + + " Parcel myparcel = Parcel.obtain();\n" + + " ~~~~~~\n" + + "0 errors, 12 warnings\n", + + lintProject( + "apicheck/classpath=>.classpath", + "apicheck/minsdk4.xml=>AndroidManifest.xml", + "project.properties1=>project.properties", + "bytecode/RecycleTest.java.txt=>src/test/pkg/RecycleTest.java", + "bytecode/RecycleTest.class.data=>bin/classes/test/pkg/RecycleTest.class" + )); + } +} diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/RecycleTest.class.data b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/RecycleTest.class.data Binary files differnew file mode 100644 index 0000000..3bdc829 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/RecycleTest.class.data diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/RecycleTest.java.txt b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/RecycleTest.java.txt new file mode 100644 index 0000000..2a026f2 --- /dev/null +++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/bytecode/RecycleTest.java.txt @@ -0,0 +1,159 @@ +package test.pkg; + +import com.unit.test.R; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Message; +import android.os.Parcel; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; + +@SuppressWarnings("unused") +public class RecycleTest extends View { + // ---- Check recycling TypedArrays ---- + + public RecycleTest(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void ok1(AttributeSet attrs, int defStyle) { + final TypedArray a = getContext().obtainStyledAttributes(attrs, + R.styleable.MyView, defStyle, 0); + String example = a.getString(R.styleable.MyView_exampleString); + a.recycle(); + } + + public void ok2(AttributeSet attrs, int defStyle) { + final TypedArray a = getContext().obtainStyledAttributes(attrs, + R.styleable.MyView, defStyle, 0); + String example = a.getString(R.styleable.MyView_exampleString); + // If there's complicated logic, don't flag + if (something()) { + a.recycle(); + } + } + + public TypedArray ok3(AttributeSet attrs, int defStyle) { + // Value passes out of method: don't flag, caller might be recycling + return getContext().obtainStyledAttributes(attrs, R.styleable.MyView, + defStyle, 0); + } + + private TypedArray myref; + + public void ok4(AttributeSet attrs, int defStyle) { + // Value stored in a field: might be recycled later + TypedArray ref = getContext().obtainStyledAttributes(attrs, + R.styleable.MyView, defStyle, 0); + myref = ref; + } + + public void wrong1(AttributeSet attrs, int defStyle) { + final TypedArray a = getContext().obtainStyledAttributes(attrs, + R.styleable.MyView, defStyle, 0); + String example = a.getString(R.styleable.MyView_exampleString); + // a.recycle(); + } + + public void wrong2(AttributeSet attrs, int defStyle) { + final TypedArray a = getContext().obtainStyledAttributes(new int[0]); + // a.recycle(); + } + + public void unknown(AttributeSet attrs, int defStyle) { + final TypedArray a = getContext().obtainStyledAttributes(attrs, + R.styleable.MyView, defStyle, 0); + // We don't know what this method is (usually it will be in a different + // class) + // so don't flag it; it might recycle + handle(a); + } + + // ---- Check recycling VelocityTracker ---- + + public void tracker() { + VelocityTracker tracker = VelocityTracker.obtain(); + } + + // ---- Check recycling Message ---- + + public void message() { + Message message1 = getHandler().obtainMessage(); + Message message2 = Message.obtain(); + } + + // ---- Check recycling MotionEvent ---- + + public void motionEvent() { + MotionEvent event1 = MotionEvent.obtain(null); + MotionEvent event2 = MotionEvent.obtainNoHistory(null); + } + + public void motionEvent2() { + MotionEvent event1 = MotionEvent.obtain(null); // OK + MotionEvent event2 = MotionEvent.obtainNoHistory(null); // Not recycled + event1.recycle(); + } + + public void motionEvent3() { + MotionEvent event1 = MotionEvent.obtain(null); // Not recycled + MotionEvent event2 = MotionEvent.obtain(event1); + event2.recycle(); + } + + // ---- Using recycled objects ---- + + public void recycled() { + MotionEvent event1 = MotionEvent.obtain(null); // Not recycled + event1.recycle(); + int contents2 = event1.describeContents(); // BAD, after recycle + final TypedArray a = getContext().obtainStyledAttributes(new int[0]); + String example = a.getString(R.styleable.MyView_exampleString); // OK + a.recycle(); + example = a.getString(R.styleable.MyView_exampleString); // BAD, after recycle + } + + // ---- Check recycling Parcel ---- + + public void parcelOk() { + Parcel myparcel = Parcel.obtain(); + myparcel.createBinderArray(); + myparcel.recycle(); + } + + public void parcelMissing() { + Parcel myparcel = Parcel.obtain(); + myparcel.createBinderArray(); + } + + + // ---- Check suppress ---- + + @SuppressLint("Recycle") + public void recycledSuppress() { + MotionEvent event1 = MotionEvent.obtain(null); // Not recycled + event1.recycle(); + int contents2 = event1.describeContents(); // BAD, after recycle + final TypedArray a = getContext().obtainStyledAttributes(new int[0]); + String example = a.getString(R.styleable.MyView_exampleString); // OK + } + + // ---- Stubs ---- + + static void handle(TypedArray a) { + // Unknown method + } + + protected boolean something() { + return true; + } + + public android.content.res.TypedArray obtainStyledAttributes( + AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { + return null; + } +} |