aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java45
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java23
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/AnnotationDetector.java22
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java5
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ButtonDetector.java2
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/FieldGetterDetector.java3
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/JavaPerformanceDetector.java1
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/LocaleDetector.java9
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/MathDetector.java2
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/OverrideDetector.java3
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ViewTagDetector.java2
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/WakelockDetector.java7
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AnnotationDetectorTest.java14
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java18
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.databin0 -> 732 bytes
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.java.txt19
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt16
17 files changed, 157 insertions, 34 deletions
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
index 7f6c0ee..fc9487d 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
@@ -60,8 +60,10 @@ import com.google.common.io.Closeables;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import org.w3c.dom.Attr;
@@ -1800,27 +1802,62 @@ public class LintDriver {
// pointers, so we have to have multiple methods which pass in each type
// of node (class, method, field) to be checked.
- // TODO: The Quickfix should look for lint warnings placed *inside* warnings
- // and warn that they won't apply to checks that are bytecode oriented!
-
/**
* Returns whether the given issue is suppressed in the given method.
*
* @param issue the issue to be checked, or null to just check for "all"
+ * @param classNode the class containing the issue
* @param method the method containing the issue
+ * @param instruction the instruction within the method, if any
* @return true if there is a suppress annotation covering the specific
* issue on this method
*/
- public boolean isSuppressed(@Nullable Issue issue, @NonNull MethodNode method) {
+ public boolean isSuppressed(
+ @Nullable Issue issue,
+ @NonNull ClassNode classNode,
+ @NonNull MethodNode method,
+ @Nullable AbstractInsnNode instruction) {
if (method.invisibleAnnotations != null) {
@SuppressWarnings("unchecked")
List<AnnotationNode> annotations = method.invisibleAnnotations;
return isSuppressed(issue, annotations);
}
+ // Initializations of fields end up placed in generated methods (<init>
+ // for members and <clinit> for static fields).
+ if (instruction != null && method.name.charAt(0) == '<') {
+ AbstractInsnNode next = LintUtils.getNextInstruction(instruction);
+ if (next != null && next.getType() == AbstractInsnNode.FIELD_INSN) {
+ FieldInsnNode fieldRef = (FieldInsnNode) next;
+ FieldNode field = findField(classNode, fieldRef.owner, fieldRef.name);
+ if (field != null && isSuppressed(issue, field)) {
+ return true;
+ }
+ }
+ }
+
return false;
}
+ @Nullable
+ private FieldNode findField(ClassNode classNode, String owner, String name) {
+ while (classNode != null) {
+ if (owner.equals(classNode.name)) {
+ @SuppressWarnings("rawtypes") // ASM API
+ List fieldList = classNode.fields;
+ for (Object f : fieldList) {
+ FieldNode field = (FieldNode) f;
+ if (field.name.equals(name)) {
+ return field;
+ }
+ }
+ return null;
+ }
+ classNode = getOuterClassNode(classNode);
+ }
+ return null;
+ }
+
/**
* Returns whether the given issue is suppressed for the given field.
*
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java
index 68c25d9..159180d 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/ClassContext.java
@@ -280,7 +280,7 @@ public class ClassContext extends Context {
* Detectors should only call this method if an error applies to the whole class
* scope and there is no specific method or field that applies to the error.
* If so, use
- * {@link #report(Issue, MethodNode, Location, String, Object)} or
+ * {@link #report(Issue, MethodNode, AbstractInsnNode, Location, String, Object)} or
* {@link #report(Issue, FieldNode, Location, String, Object)}, such that
* suppress annotations are checked.
*
@@ -313,7 +313,8 @@ public class ClassContext extends Context {
// Found the outer method for this anonymous class; continue
// reporting on it (which will also work its way up the parent
// class hierarchy)
- if (method != null && mDriver.isSuppressed(issue, method)) {
+ if (method != null && mDriver.isSuppressed(issue, mClassNode, method,
+ null)) {
return;
}
break;
@@ -337,9 +338,18 @@ public class ClassContext extends Context {
* Reports an issue applicable to a given method node.
*
* @param issue the issue to report
- * @param method the method scope the error applies to. The lint infrastructure
- * will check whether there are suppress annotations on this method (or its enclosing
- * class) and if so suppress the warning without involving the client.
+ * @param method the method scope the error applies to. The lint
+ * infrastructure will check whether there are suppress
+ * annotations on this method (or its enclosing class) and if so
+ * suppress the warning without involving the client.
+ * @param instruction the instruction within the method the error applies
+ * to. You cannot place annotations on individual method
+ * instructions (for example, annotations on local variables are
+ * allowed, but are not kept in the .class file). However, this
+ * instruction is needed to handle suppressing errors on field
+ * initializations; in that case, the errors may be reported in
+ * the {@code <clinit>} method, but the annotation is found not
+ * on that method but for the {@link FieldNode}'s.
* @param location the location of the issue, or null if not known
* @param message the message for this warning
* @param data any associated data, or null
@@ -347,10 +357,11 @@ public class ClassContext extends Context {
public void report(
@NonNull Issue issue,
@Nullable MethodNode method,
+ @Nullable AbstractInsnNode instruction,
@Nullable Location location,
@NonNull String message,
@Nullable Object data) {
- if (method != null && mDriver.isSuppressed(issue, method)) {
+ if (method != null && mDriver.isSuppressed(issue, mClassNode, method, instruction)) {
return;
}
report(issue, location, message, data); // also checks the class node
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/AnnotationDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/AnnotationDetector.java
index 7543def..9982f18 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/AnnotationDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/AnnotationDetector.java
@@ -40,12 +40,16 @@ import lombok.ast.AnnotationElement;
import lombok.ast.AnnotationValue;
import lombok.ast.ArrayInitializer;
import lombok.ast.AstVisitor;
+import lombok.ast.Block;
+import lombok.ast.ConstructorDeclaration;
import lombok.ast.Expression;
import lombok.ast.ForwardingAstVisitor;
+import lombok.ast.MethodDeclaration;
import lombok.ast.Modifiers;
import lombok.ast.Node;
import lombok.ast.StrictListAccessor;
import lombok.ast.StringLiteral;
+import lombok.ast.TypeBody;
import lombok.ast.VariableDefinition;
/**
@@ -153,11 +157,27 @@ public class AnnotationDetector extends Detector implements Detector.JavaScanner
IssueRegistry registry = mContext.getDriver().getRegistry();
Issue issue = registry.getIssue(id);
if (issue != null && !issue.getScope().contains(Scope.JAVA_FILE)) {
+ // Ensure that this isn't a field
+ Node parent = node.getParent();
+ while (parent != null) {
+ if (parent instanceof MethodDeclaration
+ || parent instanceof ConstructorDeclaration
+ || parent instanceof Block) {
+ break;
+ } else if (parent instanceof TypeBody) { // It's a field
+ return true;
+ }
+ parent = parent.getParent();
+ if (parent == null) {
+ return true;
+ }
+ }
+
// This issue doesn't have AST access: annotations are not
// available for local variables or parameters
mContext.report(ISSUE,mContext.getLocation(node), String.format(
"The @SuppresLint annotation cannot be used on a local" +
- " variable with the lint check '%1$s': move out to the " +
+ " variable with the lint check '%1$s': move out to the " +
"surrounding method", id),
null);
return false;
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java
index 5e1a687..26ff804 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiDetector.java
@@ -683,7 +683,8 @@ public class ApiDetector extends ResourceXmlDetector implements Detector.ClassSc
}
}
- Location location = context.getLocationForLine(lineNumber, patternStart, patternEnd, hints);
- context.report(UNSUPPORTED, method, location, message, null);
+ Location location = context.getLocationForLine(lineNumber, patternStart, patternEnd,
+ hints);
+ context.report(UNSUPPORTED, method, node, location, message, null);
}
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ButtonDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ButtonDetector.java
index 251a65e..da274f6 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ButtonDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ButtonDetector.java
@@ -302,7 +302,7 @@ public class ButtonDetector extends ResourceXmlDetector {
reportOkPosition(context, element);
}
} else {
- assert BACK_LABEL.equalsIgnoreCase(label);
+ assert BACK_LABEL.equalsIgnoreCase(label) : label + ':' + context.file;
Location location = context.getLocation(element);
if (context.isEnabled(BACKBUTTON)) {
context.report(BACKBUTTON, element, location,
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/FieldGetterDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/FieldGetterDetector.java
index a1fd9fa..a74b8ec 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/FieldGetterDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/FieldGetterDetector.java
@@ -165,7 +165,8 @@ public class FieldGetterDetector extends Detector implements Detector.ClassScann
if (fieldName == null) {
fieldName = "";
}
- context.report(ISSUE, entry.method, location, String.format(
+ context.report(ISSUE, entry.method, entry.call, location,
+ String.format(
"Calling getter method %1$s() on self is " +
"slower than field access (%2$s)", getter, fieldName), fieldName);
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/JavaPerformanceDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/JavaPerformanceDetector.java
index 34a697c..6ee9b1b 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/JavaPerformanceDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/JavaPerformanceDetector.java
@@ -180,7 +180,6 @@ public class JavaPerformanceDetector extends Detector implements Detector.JavaSc
mCheckAllocations = context.isEnabled(PAINT_ALLOC);
mCheckMaps = context.isEnabled(USE_SPARSEARRAY);
mCheckValueOf = context.isEnabled(USE_VALUEOF);
- assert mCheckAllocations || mCheckMaps || mCheckValueOf; // enforced by infrastructure
}
@Override
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/LocaleDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/LocaleDetector.java
index 43e9ea0..6a6ed9a 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/LocaleDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/LocaleDetector.java
@@ -96,7 +96,7 @@ public class LocaleDetector extends Detector implements ClassScanner {
6,
Severity.WARNING,
LocaleDetector.class,
- EnumSet.of(Scope.ALL_RESOURCE_FILES, Scope.CLASS_FILE)).setMoreInfo(
+ Scope.CLASS_FILE_SCOPE).setMoreInfo(
"http://developer.android.com/reference/java/text/SimpleDateFormat.html"); //$NON-NLS-1$
private static final String DATE_FORMAT_OWNER = "java/text/SimpleDateFormat"; //$NON-NLS-1$
@@ -147,8 +147,9 @@ public class LocaleDetector extends Detector implements ClassScanner {
"To get local formatting use getDateInstance(), getDateTimeInstance(), " +
"or getTimeInstance(), or use new SimpleDateFormat(String template, " +
"Locale locale) with for example Locale.US for ASCII dates.", name);
- context.report(DATE_FORMAT, method, location, message, null);
+ context.report(DATE_FORMAT, method, call, location, message, null);
}
+ return;
} else if (!owner.equals(STRING_OWNER)) {
return;
}
@@ -186,7 +187,7 @@ public class LocaleDetector extends Detector implements ClassScanner {
String message =
"Implicitly using the default locale is a common source of bugs: " +
"Use String.format(Locale, ...) instead";
- context.report(STRING_LOCALE, method, location, message, null);
+ context.report(STRING_LOCALE, method, call, location, message, null);
}
}
} catch (AnalyzerException e) {
@@ -198,7 +199,7 @@ public class LocaleDetector extends Detector implements ClassScanner {
String message = String.format(
"Implicitly using the default locale is a common source of bugs: " +
"Use %1$s(Locale) instead", name);
- context.report(STRING_LOCALE, method, location, message, null);
+ context.report(STRING_LOCALE, method, call, location, message, null);
}
}
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/MathDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/MathDetector.java
index 65eff86..000b139 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/MathDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/MathDetector.java
@@ -90,7 +90,7 @@ public class MathDetector extends Detector implements Detector.ClassScanner {
String message = String.format(
"Use java.lang.Math#%1$s instead of android.util.FloatMath#%1$s() " +
"since it is faster as of API 8", call.name);
- context.report(ISSUE, method, context.getLocation(call), message, null /*data*/);
+ context.report(ISSUE, method, call, context.getLocation(call), message, null /*data*/);
}
}
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/OverrideDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/OverrideDetector.java
index 137bc21..041536f 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/OverrideDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/OverrideDetector.java
@@ -251,7 +251,8 @@ public class OverrideDetector extends Detector implements ClassScanner {
String signature = method.name + method.desc;
if (methods.containsKey(signature)){
- if (method != null && context.getDriver().isSuppressed(ISSUE, method)) {
+ if (method != null && context.getDriver().isSuppressed(ISSUE, classNode,
+ method, null)) {
Map<String, String> errors = mErrors.get(classNode.name);
if (errors != null) {
errors.remove(signature);
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ViewTagDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ViewTagDetector.java
index e944427..3590f83 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ViewTagDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ViewTagDetector.java
@@ -164,7 +164,7 @@ public class ViewTagDetector extends Detector implements ClassScanner {
String message = String.format("Avoid setting %1$s as values for setTag: " +
"Can lead to memory leaks in versions older than Android 4.0",
objectType);
- context.report(ISSUE, method, location, message, null);
+ context.report(ISSUE, method, call, location, message, null);
}
} catch (AnalyzerException e) {
context.log(e, null);
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/WakelockDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/WakelockDetector.java
index ccf8d73..bddee0f 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/WakelockDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/WakelockDetector.java
@@ -117,7 +117,7 @@ public class WakelockDetector extends Detector implements ClassScanner {
if (context.getDriver().getPhase() == 2) {
assert !mHasRelease;
- context.report(ISSUE, method, context.getLocation(call),
+ context.report(ISSUE, method, call, context.getLocation(call),
"Found a wakelock acquire() but no release() calls anywhere",
null);
} else {
@@ -136,7 +136,7 @@ public class WakelockDetector extends Detector implements ClassScanner {
if ("onDestroy".equals(method.name) //$NON-NLS-1$
&& context.getDriver().isSubclassOf(
classNode, ANDROID_APP_ACTIVITY)) {
- context.report(ISSUE, method, context.getLocation(call),
+ context.report(ISSUE, method, call, context.getLocation(call),
"Wakelocks should be released in onPause, not onDestroy",
null);
}
@@ -191,7 +191,8 @@ public class WakelockDetector extends Detector implements ClassScanner {
message = "The release() call is not always reached";
}
- context.report(ISSUE, method, context.getLocation(release), message, null);
+ context.report(ISSUE, method, acquire,
+ context.getLocation(release), message, null);
}
} catch (AnalyzerException e) {
context.log(e, null);
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AnnotationDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AnnotationDetectorTest.java
index 4c9d34d..becca80 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AnnotationDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AnnotationDetectorTest.java
@@ -25,20 +25,22 @@ import java.util.List;
public class AnnotationDetectorTest extends AbstractCheckTest {
public void test() throws Exception {
assertEquals(
- "src/test/pkg/WrongAnnotation.java:8: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ "src/test/pkg/WrongAnnotation.java:9: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
" public static void foobar(View view, @SuppressLint(\"NewApi\") int foo) { // Invalid: class-file check\n" +
" ~~~~~~~~~~~~~~~~~~~~~~~\n" +
- "src/test/pkg/WrongAnnotation.java:9: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ "src/test/pkg/WrongAnnotation.java:10: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
" @SuppressLint(\"NewApi\") // Invalid\n" +
" ~~~~~~~~~~~~~~~~~~~~~~~\n" +
- "src/test/pkg/WrongAnnotation.java:11: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ "src/test/pkg/WrongAnnotation.java:12: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
" @SuppressLint({\"SdCardPath\", \"NewApi\"}) // Invalid: class-file based check on local variable\n" +
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
- "src/test/pkg/WrongAnnotation.java:13: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ "src/test/pkg/WrongAnnotation.java:14: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
" @android.annotation.SuppressLint({\"SdCardPath\", \"NewApi\"}) // Invalid (FQN)\n" +
" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
- "4 errors, 0 warnings\n" +
- "",
+ "src/test/pkg/WrongAnnotation.java:28: Error: The @SuppresLint annotation cannot be used on a local variable with the lint check 'NewApi': move out to the surrounding method [LocalSuppress]\n" +
+ " @SuppressLint(\"NewApi\")\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "5 errors, 0 warnings\n",
lintProject(
"src/test/pkg/WrongAnnotation.java.txt=>src/test/pkg/WrongAnnotation.java"
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java
index 576c0fe..af7c3d5 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiDetectorTest.java
@@ -639,4 +639,22 @@ public class ApiDetectorTest extends AbstractCheckTest {
));
}
+ public void testSuppressFieldAnnotations() throws Exception {
+ // See http://code.google.com/p/android/issues/detail?id=38626
+ assertEquals(
+ "src/test/pkg/ApiCallTest9.java:9: Error: Call requires API level 14 (current min is 4): new android.widget.GridLayout [NewApi]\n" +
+ " private GridLayout field1 = new GridLayout(null);\n" +
+ " ~~~~~~~~~~\n" +
+ "src/test/pkg/ApiCallTest9.java:12: Error: Call requires API level 14 (current min is 4): new android.widget.GridLayout [NewApi]\n" +
+ " private static GridLayout field2 = new GridLayout(null);\n" +
+ " ~~~~~~~~~~\n" +
+ "2 errors, 0 warnings\n",
+
+ lintProject(
+ "apicheck/classpath=>.classpath",
+ "apicheck/minsdk4.xml=>AndroidManifest.xml",
+ "apicheck/ApiCallTest9.java.txt=>src/test/pkg/ApiCallTest9.java",
+ "apicheck/ApiCallTest9.class.data=>bin/classes/test/pkg/ApiCallTest9.class"
+ ));
+ }
}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.data b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.data
new file mode 100644
index 0000000..f50ebab
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.class.data
Binary files differ
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.java.txt b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.java.txt
new file mode 100644
index 0000000..199231e
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/apicheck/ApiCallTest9.java.txt
@@ -0,0 +1,19 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.widget.GridLayout;
+
+/** Test suppress on fields */
+public class ApiCallTest9 {
+ // Actual initialization code lives in the synthetic method <init>
+ private GridLayout field1 = new GridLayout(null);
+
+ // Actual initialization code lives in the synthetic method <clinit>
+ private static GridLayout field2 = new GridLayout(null);
+
+ @SuppressLint("NewApi")
+ private GridLayout field3 = new GridLayout(null);
+
+ @SuppressLint("NewApi")
+ private static GridLayout field4 = new GridLayout(null);
+}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt
index 9256055..6fef833 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/WrongAnnotation.java.txt
@@ -1,6 +1,7 @@
-package com.example.test2;
+package test.pkg;
import android.annotation.SuppressLint;
+import android.view.View;
public class WrongAnnotation {
@Override
@@ -15,5 +16,16 @@ public class WrongAnnotation {
@SuppressLint("SdCardPath") // Valid: AST-based check
boolean d;
}
-}
+ @SuppressLint("NewApi")
+ private int field1;
+
+ @SuppressLint("NewApi")
+ private int field2 = 5;
+
+ static {
+ // Local variable outside method: invalid
+ @SuppressLint("NewApi")
+ int localvar = 5;
+ }
+}