aboutsummaryrefslogtreecommitdiffstats
path: root/lint
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-02-20 08:57:56 -0800
committerTor Norbye <tnorbye@google.com>2012-02-21 09:17:02 -0800
commite0281950ddcd517c9ef4c6ed118f33a9fd063cec (patch)
tree3d2d09a32bf479ae34d5263de15c7f4f1904ae68 /lint
parent556b907792f0658a6c3f676e23469b83175e3431 (diff)
downloadsdk-e0281950ddcd517c9ef4c6ed118f33a9fd063cec.zip
sdk-e0281950ddcd517c9ef4c6ed118f33a9fd063cec.tar.gz
sdk-e0281950ddcd517c9ef4c6ed118f33a9fd063cec.tar.bz2
Use lint error mechanism for config issues like no classes found
If Lint cannot find the .class files for a project, it cannot run any of the class-file based checks (such as the NewApi check). This changeset adds a new category and issue id, "Lint Error", for these types of issues. In HTML reports, these errors are listed at the top. The issue explanation states that these errors don't represent bugs in the user's code, but that lint was not able to check certain things for the reasons given. In the case of no .class files found, it asks whether the project needs to be built first. It also uses these lint errors to emit errors in processing lint.xml configuration files. (Note that if you don't want to see these types of errors, you can suppress it via --disable LintError.) Change-Id: Ifc2f55566f3a0cd20189d43e4205201bc21ee280
Diffstat (limited to 'lint')
-rw-r--r--lint/cli/src/com/android/tools/lint/Main.java7
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultConfiguration.java19
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java22
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java10
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java3
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java18
6 files changed, 66 insertions, 13 deletions
diff --git a/lint/cli/src/com/android/tools/lint/Main.java b/lint/cli/src/com/android/tools/lint/Main.java
index 1484a1d..629c932 100644
--- a/lint/cli/src/com/android/tools/lint/Main.java
+++ b/lint/cli/src/com/android/tools/lint/Main.java
@@ -16,6 +16,8 @@
package com.android.tools.lint;
+import static com.android.tools.lint.client.api.IssueRegistry.LINT_ERROR;
+import static com.android.tools.lint.client.api.IssueRegistry.PARSER_ERROR;
import static com.android.tools.lint.detector.api.LintConstants.DOT_XML;
import static com.android.tools.lint.detector.api.LintUtils.endsWith;
@@ -1030,7 +1032,7 @@ public class Main extends LintClient {
}
}
- if (mCheck != null) {
+ if (mCheck != null && issue != LINT_ERROR && issue != PARSER_ERROR) {
return Severity.IGNORE;
}
@@ -1081,6 +1083,9 @@ public class Main extends LintClient {
chop++;
}
path = path.substring(chop);
+ if (path.length() == 0) {
+ path = file.getName();
+ }
}
return path;
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultConfiguration.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultConfiguration.java
index 1281987..56cee8e 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultConfiguration.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/DefaultConfiguration.java
@@ -31,6 +31,7 @@ import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
+import org.xml.sax.SAXParseException;
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
@@ -196,6 +197,15 @@ public class DefaultConfiguration extends Configuration {
}
}
+ private void formatError(String message, Object... args) {
+ if (args != null && args.length > 0) {
+ message = String.format(message, args);
+ }
+ message = "Failed to parse lint.xml configuration file: " + message;
+ mClient.report(new Context(null, mProject, mProject, mConfigFile),
+ IssueRegistry.LINT_ERROR, Location.create(mConfigFile), message, null);
+ }
+
private void readConfig() {
mSuppressed = new HashMap<String, List<String>>();
mSeverity = new HashMap<String, Severity>();
@@ -218,8 +228,7 @@ public class DefaultConfiguration extends Configuration {
Element element = (Element) node;
String id = element.getAttribute(ATTR_ID);
if (id.length() == 0) {
- mClient.log(null,
- "Invalid lint config file: Missing required issue id attribute");
+ formatError("Invalid lint config file: Missing required issue id attribute");
continue;
}
@@ -238,7 +247,7 @@ public class DefaultConfiguration extends Configuration {
}
}
} else {
- mClient.log(null, "Unexpected attribute %1$s", name);
+ formatError("Unexpected attribute \"%1$s\"", name);
}
}
@@ -251,7 +260,7 @@ public class DefaultConfiguration extends Configuration {
Element ignore = (Element) child;
String path = ignore.getAttribute(ATTR_PATH);
if (path.length() == 0) {
- mClient.log(null, "Missing required %1$s attribute under %2$s",
+ formatError("Missing required %1$s attribute under %2$s",
ATTR_PATH, id);
} else {
List<String> paths = mSuppressed.get(id);
@@ -265,6 +274,8 @@ public class DefaultConfiguration extends Configuration {
}
}
}
+ } catch (SAXParseException e) {
+ formatError(e.getMessage());
} catch (Exception e) {
mClient.log(e, null);
}
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java
index a809841..7d9471d 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/IssueRegistry.java
@@ -61,6 +61,27 @@ public abstract class IssueRegistry {
Scope.RESOURCE_FILE_SCOPE);
/**
+ * Issue reported by lint for various other issues which prevents lint from
+ * running normally when it's not necessarily an error in the user's code base.
+ */
+ @NonNull
+ public static final Issue LINT_ERROR = Issue.create(
+ "LintError", //$NON-NLS-1$
+ "Isues related to running lint itself, such as failure to read files, etc",
+ "This issue type represents a problem running lint itself. Examples include " +
+ "failure to find bytecode for source files (which means certain detectors " +
+ "could not be run), parsing errors in lint configuration files, etc." +
+ "\n" +
+ "These errors are not errors in your own code, but they are shown to make " +
+ "it clear that some checks were not completed.",
+
+ Category.LINT,
+ 10,
+ Severity.ERROR,
+ null,
+ Scope.RESOURCE_FILE_SCOPE);
+
+ /**
* Returns the list of issues that can be found by all known detectors.
*
* @return the list of issues to be checked (including those that may be
@@ -213,6 +234,7 @@ public abstract class IssueRegistry {
}
sIdToIssue.put(PARSER_ERROR.getId(), PARSER_ERROR);
+ sIdToIssue.put(LINT_ERROR.getId(), LINT_ERROR);
}
return sIdToIssue.get(id);
}
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 31622eb..4ebc9ed 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
@@ -830,8 +830,12 @@ public class LintDriver {
List<File> classFolders = project.getJavaClassFolders();
List<ClassEntry> classEntries;
if (classFolders.size() == 0) {
- //mClient.log(null, "Warning: Class-file checks are enabled, but no " +
- // "output folders found. Does the project need to be built first?");
+ String message = String.format("No .class files were found in project \"%1$s\", "
+ + "so none of the classfile based checks could be run. "
+ + "Does the project need to be built first?", project.getName());
+ Location location = Location.create(project.getDir());
+ mClient.report(new Context(this, project, main, project.getDir()),
+ IssueRegistry.LINT_ERROR, location, message, null);
classEntries = Collections.emptyList();
} else {
classEntries = new ArrayList<ClassEntry>(64);
@@ -1247,7 +1251,7 @@ public class LintDriver {
@Nullable Object data) {
Configuration configuration = context.getConfiguration();
if (!configuration.isEnabled(issue)) {
- if (issue != IssueRegistry.PARSER_ERROR) {
+ if (issue != IssueRegistry.PARSER_ERROR && issue != IssueRegistry.LINT_ERROR) {
mDelegate.log(null, "Incorrect detector reported disabled issue %1$s",
issue.toString());
}
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java
index 75aaa0b..6978ef0 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java
@@ -136,6 +136,9 @@ public final class Category implements Comparable<Category> {
return other.mPriority - mPriority;
}
+ /** Issues related to running lint itself */
+ public static final Category LINT = Category.create("Lint", 110);
+
/** Issues related to correctness */
public static final Category CORRECTNESS = Category.create("Correctness", 100);
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java
index 97cb5f6..95ca8b9 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ManifestOrderDetector.java
@@ -125,7 +125,7 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann
@Override
public void afterCheckFile(Context context) {
- if (mSeenUsesSdk == 0) {
+ if (mSeenUsesSdk == 0 && context.isEnabled(USES_SDK)) {
context.report(USES_SDK, Location.create(context.file),
"Manifest should specify a minimum API level with " +
"<uses-sdk android:minSdkVersion=\"?\" />; if it really supports " +
@@ -175,34 +175,42 @@ public class ManifestOrderDetector extends Detector implements Detector.XmlScann
}
location.setSecondary(secondary);
- context.report(MULTIPLE_USES_SDK, element, location,
+ if (context.isEnabled(MULTIPLE_USES_SDK)) {
+ context.report(MULTIPLE_USES_SDK, element, location,
"There should only be a single <uses-sdk> element in the manifest:" +
" merge these together", null);
+ }
return;
}
if (!element.hasAttributeNS(ANDROID_URI, ATTR_MIN_SDK_VERSION)) {
- context.report(USES_SDK, element, context.getLocation(element),
+ if (context.isEnabled(USES_SDK)) {
+ context.report(USES_SDK, element, context.getLocation(element),
"<uses-sdk> tag should specify a minimum API level with " +
"android:minSdkVersion=\"?\"", null);
+ }
} else if (context.getProject().getMinSdk() <= 9
&& !element.hasAttributeNS(ANDROID_URI, ATTR_TARGET_SDK_VERSION)) {
// Warn if not setting target SDK -- but only if the min SDK is somewhat
// old so there's some compatibility stuff kicking in (such as the menu
// button etc)
- context.report(USES_SDK, element, context.getLocation(element),
+ if (context.isEnabled(USES_SDK)) {
+ context.report(USES_SDK, element, context.getLocation(element),
"<uses-sdk> tag should specify a target API level (the " +
"highest verified version; when running on later versions, " +
"compatibility behaviors may be enabled) with " +
"android:targetSdkVersion=\"?\"", null);
+ }
}
}
if (tag.equals(TAG_APPLICATION)) {
mSeenApplication = true;
} else if (mSeenApplication) {
- context.report(ORDER, element, context.getLocation(element),
+ if (context.isEnabled(ORDER)) {
+ context.report(ORDER, element, context.getLocation(element),
String.format("<%1$s> tag appears after <application> tag", tag), null);
+ }
// Don't complain for *every* element following the <application> tag
mSeenApplication = false;