aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eclipse/dictionary.txt1
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java45
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/SharedPrefsDetector.java9
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SharedPrefsDetectorTest.java36
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest2.java.txt19
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest3.java.txt15
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest4.java.txt15
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java73
8 files changed, 210 insertions, 3 deletions
diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt
index af3d835..c4d9089 100644
--- a/eclipse/dictionary.txt
+++ b/eclipse/dictionary.txt
@@ -341,6 +341,7 @@ wakelocks
wallpaper
webtools
whilst
+wildcard
workflow
xdpi
xhdpi
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
index 514d91e..fe659cd 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
@@ -47,6 +47,8 @@ import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
+import lombok.ast.ImportDeclaration;
+
/**
* Useful utility methods related to lint.
@@ -707,4 +709,47 @@ public class LintUtils {
return locale;
}
+
+ /**
+ * Returns true if the given class (specified by a fully qualified class
+ * name) name is imported in the given compilation unit either through a fully qualified
+ * import or by a wildcard import.
+ *
+ * @param compilationUnit the compilation unit
+ * @param fullyQualifiedName the fully qualified class name
+ * @return true if the given imported name refers to the given fully
+ * qualified name
+ */
+ public static boolean isImported(
+ @NonNull lombok.ast.Node compilationUnit,
+ @NonNull String fullyQualifiedName) {
+ int dotIndex = fullyQualifiedName.lastIndexOf('.');
+ int dotLength = fullyQualifiedName.length() - dotIndex;
+
+ boolean imported = false;
+ for (lombok.ast.Node rootNode : compilationUnit.getChildren()) {
+ if (rootNode instanceof ImportDeclaration) {
+ ImportDeclaration importDeclaration = (ImportDeclaration) rootNode;
+ String fqn = importDeclaration.asFullyQualifiedName();
+ if (fqn.equals(fullyQualifiedName)) {
+ return true;
+ } else if (fullyQualifiedName.regionMatches(dotIndex, fqn,
+ fqn.length() - dotLength, dotLength)) {
+ // This import is importing the class name using some other prefix, so there
+ // fully qualified class name cannot be imported under that name
+ return false;
+ } else if (importDeclaration.astStarImport()
+ && fqn.regionMatches(0, fqn, 0, dotIndex + 1)) {
+ imported = true;
+ // but don't break -- keep searching in case there's a non-wildcard
+ // import of the specific class name, e.g. if we're looking for
+ // android.content.SharedPreferences.Editor, don't match on the following:
+ // import android.content.SharedPreferences.*;
+ // import foo.bar.Editor;
+ }
+ }
+ }
+
+ return imported;
+ }
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/SharedPrefsDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/SharedPrefsDetector.java
index 685d9cf..5db301b 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/SharedPrefsDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/SharedPrefsDetector.java
@@ -23,6 +23,7 @@ import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Detector;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.JavaContext;
+import com.android.tools.lint.detector.api.LintUtils;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
@@ -109,8 +110,12 @@ public class SharedPrefsDetector extends Detector implements Detector.JavaScanne
}
VariableDefinition definition = (VariableDefinition) node.getParent().getParent();
String type = definition.astTypeReference().toString();
- if (!type.endsWith("SharedPreferences.Editor")) { //$NON-NLS-1$
- return;
+ if (!type.endsWith("SharedPreferences.Editor")) { //$NON-NLS-1$
+ if (!type.equals("Editor") || //$NON-NLS-1$
+ !LintUtils.isImported(context.compilationUnit,
+ "android.content.SharedPreferences.Editor")) { //$NON-NLS-1$
+ return;
+ }
}
Node method = findSurroundingMethod(node.getParent());
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SharedPrefsDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SharedPrefsDetectorTest.java
index b77f3bd..964232c 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SharedPrefsDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/SharedPrefsDetectorTest.java
@@ -39,4 +39,40 @@ public class SharedPrefsDetectorTest extends AbstractCheckTest {
lintProject("src/test/pkg/SharedPrefsTest.java.txt=>" +
"src/test/pkg/SharedPrefsTest.java"));
}
+
+ public void test2() throws Exception {
+ // Regression test 1 for http://code.google.com/p/android/issues/detail?id=34322
+ assertEquals(
+ "src/test/pkg/SharedPrefsTest2.java:13: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " SharedPreferences.Editor editor = preferences.edit();\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "src/test/pkg/SharedPrefsTest2.java:17: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " Editor editor = preferences.edit();\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 2 warnings\n",
+
+ lintProject("src/test/pkg/SharedPrefsTest2.java.txt=>" +
+ "src/test/pkg/SharedPrefsTest2.java"));
+ }
+
+ public void test3() throws Exception {
+ // Regression test 2 for http://code.google.com/p/android/issues/detail?id=34322
+ assertEquals(
+ "src/test/pkg/SharedPrefsTest3.java:13: Warning: SharedPreferences.edit() without a corresponding commit() or apply() call [CommitPrefEdits]\n" +
+ " Editor editor = preferences.edit();\n" +
+ " ~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n",
+
+ lintProject("src/test/pkg/SharedPrefsTest3.java.txt=>" +
+ "src/test/pkg/SharedPrefsTest3.java"));
+ }
+
+ public void test4() throws Exception {
+ // Regression test 3 for http://code.google.com/p/android/issues/detail?id=34322
+ assertEquals(
+ "No warnings.",
+
+ lintProject("src/test/pkg/SharedPrefsTest4.java.txt=>" +
+ "src/test/pkg/SharedPrefsTest4.java"));
+ }
}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest2.java.txt b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest2.java.txt
new file mode 100644
index 0000000..20c3a21
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest2.java.txt
@@ -0,0 +1,19 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+
+@SuppressWarnings("unused")
+public class SharedPrefsTest2 extends Activity {
+ public void test1(SharedPreferences preferences) {
+ SharedPreferences.Editor editor = preferences.edit();
+ }
+
+ public void test2(SharedPreferences preferences) {
+ Editor editor = preferences.edit();
+ }
+}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest3.java.txt b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest3.java.txt
new file mode 100644
index 0000000..e5baa00
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest3.java.txt
@@ -0,0 +1,15 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.*;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+
+@SuppressWarnings("unused")
+public class SharedPrefsTest3 extends Activity {
+ public void test(SharedPreferences preferences) {
+ Editor editor = preferences.edit();
+ }
+}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest4.java.txt b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest4.java.txt
new file mode 100644
index 0000000..28de959
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/src/test/pkg/SharedPrefsTest4.java.txt
@@ -0,0 +1,15 @@
+package test.pkg;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import foo.bar.Editor;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+
+@SuppressWarnings("unused")
+public class SharedPrefsTest4 extends Activity {
+ public void test(SharedPreferences preferences) {
+ Editor editor = preferences.edit();
+ }
+}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java
index 0ce3815..7dfa260 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java
@@ -17,9 +17,15 @@
package com.android.tools.lint.detector.api;
import static com.android.tools.lint.detector.api.LintUtils.getLocaleAndRegion;
+import static com.android.tools.lint.detector.api.LintUtils.isImported;
import static com.android.tools.lint.detector.api.LintUtils.splitPath;
+import com.android.annotations.Nullable;
+import com.android.tools.lint.LombokParser;
import com.android.tools.lint.Main;
+import com.android.tools.lint.checks.BuiltinIssueRegistry;
+import com.android.tools.lint.client.api.IJavaParser;
+import com.android.tools.lint.client.api.LintDriver;
import com.google.common.collect.Iterables;
import java.io.BufferedOutputStream;
@@ -29,6 +35,7 @@ import java.io.OutputStreamWriter;
import java.util.Arrays;
import junit.framework.TestCase;
+import lombok.ast.Node;
@SuppressWarnings("javadoc")
public class LintUtilsTest extends TestCase {
@@ -285,4 +292,68 @@ public class LintUtilsTest extends TestCase {
assertEquals("zh-rCN", getLocaleAndRegion("values-zh-rCN-keyshidden"));
assertEquals("ms", getLocaleAndRegion("values-ms-keyshidden"));
}
-} \ No newline at end of file
+
+ public void testIsImported() throws Exception {
+ assertFalse(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+
+ assertTrue(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "import foo.bar.*;\n" +
+ "import android.app.Activity;\n" +
+ "import foo.bar.Baz;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+
+ assertTrue(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "import android.app.Activity;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+
+ assertTrue(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "import android.app.*;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+
+ assertFalse(isImported(getCompilationUnit(
+ "package foo.bar;\n" +
+ "import android.app.*;\n" +
+ "import foo.bar.Activity;\n" +
+ "class Foo {\n" +
+ "}\n"),
+ "android.app.Activity"));
+ }
+
+ private Node getCompilationUnit(String javaSource) {
+ IJavaParser parser = new LombokParser();
+ TestContext context = new TestContext(javaSource, new File("test"));
+ Node compilationUnit = parser.parseJava(context);
+ assertNotNull(javaSource, compilationUnit);
+ return compilationUnit;
+ }
+
+ private class TestContext extends JavaContext {
+ private final String mJavaSource;
+ public TestContext(String javaSource, File file) {
+ super(new LintDriver(new BuiltinIssueRegistry(),
+ new Main()), new Main().getProject(new File("dummy"), new File("dummy")),
+ null, file);
+
+ mJavaSource = javaSource;
+ }
+
+ @Override
+ @Nullable
+ public String getContents() {
+ return mJavaSource;
+ }
+ }
+}