aboutsummaryrefslogtreecommitdiffstats
path: root/lint/cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'lint/cli/src')
-rw-r--r--lint/cli/src/com/android/tools/lint/HtmlReporter.java85
-rw-r--r--lint/cli/src/com/android/tools/lint/Main.java248
-rw-r--r--lint/cli/src/com/android/tools/lint/PositionXmlParser.java24
-rw-r--r--lint/cli/src/com/android/tools/lint/Warning.java14
-rw-r--r--lint/cli/src/com/android/tools/lint/XmlReporter.java107
5 files changed, 359 insertions, 119 deletions
diff --git a/lint/cli/src/com/android/tools/lint/HtmlReporter.java b/lint/cli/src/com/android/tools/lint/HtmlReporter.java
index 0d8335e..c4b8602 100644
--- a/lint/cli/src/com/android/tools/lint/HtmlReporter.java
+++ b/lint/cli/src/com/android/tools/lint/HtmlReporter.java
@@ -16,6 +16,7 @@
package com.android.tools.lint;
+import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Severity;
@@ -66,6 +67,11 @@ class HtmlReporter extends Reporter {
" font-weight: bold;\n" + //$NON-NLS-1$
" margin: 5px 0px 5px 0px;\n" + //$NON-NLS-1$
"}\n" + //$NON-NLS-1$
+ ".category {\n" + //$NON-NLS-1$
+ " font-size: 18pt;\n" + //$NON-NLS-1$
+ " font-weight: bold;\n" + //$NON-NLS-1$
+ " margin: 10px 0px 5px 0px;\n" + //$NON-NLS-1$
+ "}\n" + //$NON-NLS-1$
// The issue summary line
//".summary {\n" + //$NON-NLS-1$
//" font-weight: bold;\n" + //$NON-NLS-1$
@@ -93,6 +99,9 @@ class HtmlReporter extends Reporter {
" max-width: 200px;\n" + //$NON-NLS-1$
" max-height: 200px;\n" + //$NON-NLS-1$
"}\n" + //$NON-NLS-1$
+ // Image labels
+ "th { font-weight: normal; }\n" + //$NON-NLS-1$
+ "table { border: none; }\n" + //$NON-NLS-1$
// The Priority/Category section
".metadata { }\n" + //$NON-NLS-1$
// Each error message
@@ -132,28 +141,59 @@ class HtmlReporter extends Reporter {
mWriter.write(String.format("Check performed at %1$s.",
new Date().toString()));
- mWriter.write("<br/>"); //$NON-NLS-1$
+ mWriter.write("<br/><br/>"); //$NON-NLS-1$
mWriter.write(String.format("%1$d errors and %2$d warnings found:",
errorCount, warningCount));
mWriter.write("<br/>"); //$NON-NLS-1$
// Write issue id summary
mWriter.write("<ul>\n"); //$NON-NLS-1$
+ Category previousCategory = null;
for (List<Warning> warnings : related) {
- mWriter.write("<li> <a href=\"#" //$NON-NLS-1$
- + warnings.get(0).issue.getId()
- +"\">"); //$NON-NLS-1$
+ Issue issue = warnings.get(0).issue;
+
+ if (issue.getCategory() != previousCategory) {
+ if (previousCategory != null) {
+ mWriter.write("</ul>\n"); //$NON-NLS-1$
+ }
+ previousCategory = issue.getCategory();
+ String categoryName = issue.getCategory().getFullName();
+ mWriter.write("<li> <a href=\"#"); //$NON-NLS-1$
+ mWriter.write(categoryName);
+ mWriter.write("\">"); //$NON-NLS-1$
+ mWriter.write(categoryName);
+ mWriter.write("</a>\n"); //$NON-NLS-1$
+ mWriter.write("\n<ul>\n"); //$NON-NLS-1$
+ }
+
+ mWriter.write("<li> <a href=\"#"); //$NON-NLS-1$
+ mWriter.write(issue.getId());
+ mWriter.write("\">"); //$NON-NLS-1$
mWriter.write(String.format("%1$3d %2$s", //$NON-NLS-1$
- warnings.size(), warnings.get(0).issue.getId()));
+ warnings.size(), issue.getId()));
mWriter.write("</a>\n"); //$NON-NLS-1$
}
+ if (previousCategory != null) {
+ mWriter.write("</ul>\n"); //$NON-NLS-1$
+ }
mWriter.write("</ul>\n"); //$NON-NLS-1$
mWriter.write("<br/>"); //$NON-NLS-1$
+ previousCategory = null;
for (List<Warning> warnings : related) {
Warning first = warnings.get(0);
Issue issue = first.issue;
+ if (issue.getCategory() != previousCategory) {
+ previousCategory = issue.getCategory();
+ mWriter.write("\n<a name=\""); //$NON-NLS-1$
+ mWriter.write(issue.getCategory().getFullName());
+ mWriter.write("\">\n"); //$NON-NLS-1$
+ mWriter.write("<div class=\"category\">"); //$NON-NLS-1$
+ mWriter.write(issue.getCategory().getFullName());
+ mWriter.write("</div>\n"); //$NON-NLS-1$
+ }
+
mWriter.write("<a name=\"" + issue.getId() + "\">\n"); //$NON-NLS-1$ //$NON-NLS-2$
mWriter.write("<div class=\"issue\">\n"); //$NON-NLS-1$
@@ -225,7 +265,7 @@ class HtmlReporter extends Reporter {
mWriter.write(issue.getPriority());
mWriter.write("<br/>\n"); //$NON-NLS-1$
mWriter.write("Category: ");
- mWriter.write(issue.getCategory());
+ mWriter.write(issue.getCategory().getFullName());
mWriter.write("</div>\n"); //$NON-NLS-1$
mWriter.write("Severity: ");
@@ -300,7 +340,22 @@ class HtmlReporter extends Reporter {
return getDpiRank(s1) - getDpiRank(s2);
}
});
- mWriter.write("<table normal\" border=\"0\"><tr>"); //$NON-NLS-1$
+ mWriter.write("<table>"); //$NON-NLS-1$
+ mWriter.write("<tr>"); //$NON-NLS-1$
+ for (String linkedUrl : urls) {
+ // Image series: align top
+ mWriter.write("<td>"); //$NON-NLS-1$
+ mWriter.write("<a href=\""); //$NON-NLS-1$
+ mWriter.write(linkedUrl);
+ mWriter.write("\">"); //$NON-NLS-1$
+ mWriter.write("<img border=\"0\" align=\"top\" src=\""); //$NON-NLS-1$
+ mWriter.write(linkedUrl);
+ mWriter.write("\" /></a>\n"); //$NON-NLS-1$
+ mWriter.write("</td>"); //$NON-NLS-1$
+ }
+ mWriter.write("</tr>"); //$NON-NLS-1$
+
+ mWriter.write("<tr>"); //$NON-NLS-1$
for (String linkedUrl : urls) {
mWriter.write("<th>"); //$NON-NLS-1$
int index = linkedUrl.lastIndexOf("drawable-"); //$NON-NLS-1$
@@ -313,19 +368,9 @@ class HtmlReporter extends Reporter {
}
mWriter.write("</th>"); //$NON-NLS-1$
}
- mWriter.write("</tr>\n<tr>"); //$NON-NLS-1$
- for (String linkedUrl : urls) {
- // Image series: align top
- mWriter.write("<td>"); //$NON-NLS-1$
- mWriter.write("<a href=\""); //$NON-NLS-1$
- mWriter.write(linkedUrl);
- mWriter.write("\">"); //$NON-NLS-1$
- mWriter.write("<img border=\"0\" align=\"top\" src=\""); //$NON-NLS-1$
- mWriter.write(linkedUrl);
- mWriter.write("\" /></a>\n"); //$NON-NLS-1$
- mWriter.write("</td>"); //$NON-NLS-1$
- }
- mWriter.write("</tr></table>"); //$NON-NLS-1$
+ mWriter.write("</tr>\n"); //$NON-NLS-1$
+
+ mWriter.write("</table>\n"); //$NON-NLS-1$
}
} else {
// Just this image: float to the right
diff --git a/lint/cli/src/com/android/tools/lint/Main.java b/lint/cli/src/com/android/tools/lint/Main.java
index 11d2af1..0fe1fcb 100644
--- a/lint/cli/src/com/android/tools/lint/Main.java
+++ b/lint/cli/src/com/android/tools/lint/Main.java
@@ -16,15 +16,20 @@
package com.android.tools.lint;
-import com.android.tools.lint.api.DetectorRegistry;
-import com.android.tools.lint.api.IDomParser;
-import com.android.tools.lint.api.Lint;
-import com.android.tools.lint.api.ToolContext;
-import com.android.tools.lint.checks.BuiltinDetectorRegistry;
+import com.android.tools.lint.checks.BuiltinIssueRegistry;
+import com.android.tools.lint.client.api.Configuration;
+import com.android.tools.lint.client.api.DefaultConfiguration;
+import com.android.tools.lint.client.api.IDomParser;
+import com.android.tools.lint.client.api.IssueRegistry;
+import com.android.tools.lint.client.api.Lint;
+import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.client.api.LintListener;
+import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Position;
+import com.android.tools.lint.detector.api.Project;
import com.android.tools.lint.detector.api.Severity;
import java.io.BufferedReader;
@@ -51,20 +56,21 @@ import java.util.Set;
* <li>Offer suppressing violations
* </ul>
*/
-public class Main extends ToolContext {
+public class Main extends LintClient {
private static final int MAX_LINE_WIDTH = 70;
private static final String ARG_ENABLE = "--enable"; //$NON-NLS-1$
private static final String ARG_DISABLE = "--disable"; //$NON-NLS-1$
private static final String ARG_CHECK = "--check"; //$NON-NLS-1$
- private static final String ARG_SUPPRESS = "--suppress"; //$NON-NLS-1$
private static final String ARG_IGNORE = "--ignore"; //$NON-NLS-1$
private static final String ARG_LISTIDS = "--list"; //$NON-NLS-1$
private static final String ARG_SHOW = "--show"; //$NON-NLS-1$
+ private static final String ARG_QUIET = "--quiet"; //$NON-NLS-1$
private static final String ARG_FULLPATH = "--fullpath"; //$NON-NLS-1$
private static final String ARG_HELP = "--help"; //$NON-NLS-1$
private static final String ARG_NOLINES = "--nolines"; //$NON-NLS-1$
private static final String ARG_HTML = "--html"; //$NON-NLS-1$
- private static final String ARG_URL = "--url"; //$NON-NLS-1$
+ private static final String ARG_XML = "--xml"; //$NON-NLS-1$
+ private static final String ARG_URL = "--url"; //$NON-NLS-1$
private static final int ERRNO_ERRORS = -1;
private static final int ERRNO_USAGE = -2;
private static final int ERRNO_EXISTS = -3;
@@ -82,6 +88,7 @@ public class Main extends ToolContext {
private int mWarningCount;
private boolean mShowLines = true;
private Reporter mReporter;
+ private boolean mQuiet;
/** Creates a CLI driver */
public Main() {
@@ -107,7 +114,7 @@ public class Main extends ToolContext {
System.exit(ERRNO_USAGE);
}
- DetectorRegistry registry = new BuiltinDetectorRegistry();
+ IssueRegistry registry = new BuiltinIssueRegistry();
// Mapping from file path prefix to URL. Applies only to HTML reports
String urlMap = null;
@@ -141,6 +148,8 @@ public class Main extends ToolContext {
} else if (arg.equals(ARG_FULLPATH)
|| arg.equals(ARG_FULLPATH + "s")) { // allow "--fullpaths" too
mFullPath = true;
+ } else if (arg.equals(ARG_QUIET) || arg.equals("-q")) {
+ mQuiet = true;
} else if (arg.equals(ARG_NOLINES)) {
mShowLines = false;
} else if (arg.equals(ARG_URL)) {
@@ -178,21 +187,44 @@ public class Main extends ToolContext {
log(e, null);
System.exit(ERRNO_INVALIDARGS);
}
- } else if (arg.equals(ARG_SUPPRESS) || arg.equals(ARG_DISABLE)
- || arg.equals(ARG_IGNORE)) {
+ } else if (arg.equals(ARG_XML)) {
+ if (index == args.length - 1) {
+ System.err.println("Missing XML output file name");
+ System.exit(ERRNO_INVALIDARGS);
+ }
+ File output = new File(args[++index]);
+ if (output.exists()) {
+ boolean delete = output.delete();
+ if (!delete) {
+ System.err.println("Could not delete old " + output);
+ System.exit(ERRNO_EXISTS);
+ }
+ }
+ if (output.canWrite()) {
+ System.err.println("Cannot write XML output file " + output);
+ System.exit(ERRNO_EXISTS);
+ }
+ try {
+ mReporter = new XmlReporter(output);
+ } catch (IOException e) {
+ log(e, null);
+ System.exit(ERRNO_INVALIDARGS);
+ }
+ } else if (arg.equals(ARG_DISABLE) || arg.equals(ARG_IGNORE)) {
if (index == args.length - 1) {
System.err.println("Missing categories or id's to disable");
System.exit(ERRNO_INVALIDARGS);
}
String[] ids = args[++index].split(",");
for (String id : ids) {
- if (registry.isCategory(id)) {
+ if (registry.isCategoryName(id)) {
// Suppress all issues with the given category
String category = id;
for (Issue issue : registry.getIssues()) {
// Check prefix such that filtering on the "Usability" category
// will match issue category "Usability:Icons" etc.
- if (category.startsWith(issue.getCategory())) {
+ if (issue.getCategory().getName().startsWith(category) ||
+ issue.getCategory().getFullName().startsWith(category)) {
mSuppress.add(issue.getId());
}
}
@@ -211,11 +243,12 @@ public class Main extends ToolContext {
}
String[] ids = args[++index].split(",");
for (String id : ids) {
- if (registry.isCategory(id)) {
+ if (registry.isCategoryName(id)) {
// Enable all issues with the given category
String category = id;
for (Issue issue : registry.getIssues()) {
- if (category.startsWith(issue.getCategory())) {
+ if (issue.getCategory().getName().startsWith(category) ||
+ issue.getCategory().getFullName().startsWith(category)) {
mEnabled.add(issue.getId());
}
}
@@ -235,13 +268,14 @@ public class Main extends ToolContext {
mCheck = new HashSet<String>();
String[] ids = args[++index].split(",");
for (String id : ids) {
- if (registry.isCategory(id)) {
+ if (registry.isCategoryName(id)) {
// Suppress all issues with the given category
String category = id;
for (Issue issue : registry.getIssues()) {
// Check prefix such that filtering on the "Usability" category
// will match issue category "Usability:Icons" etc.
- if (category.startsWith(issue.getCategory())) {
+ if (issue.getCategory().getName().startsWith(category) ||
+ issue.getCategory().getFullName().startsWith(category)) {
mCheck.add(issue.getId());
}
}
@@ -302,8 +336,13 @@ public class Main extends ToolContext {
((HtmlReporter) mReporter).setUrlMap(map);
}
- Lint analyzer = new Lint(new BuiltinDetectorRegistry(), this, null);
- analyzer.analyze(files);
+ Lint analyzer = new Lint(registry, this);
+
+ if (!mQuiet) {
+ analyzer.addLintListener(new ProgressPrinter());
+ }
+
+ analyzer.analyze(files, null /* scope */);
Collections.sort(mWarnings);
@@ -317,11 +356,11 @@ public class Main extends ToolContext {
System.exit(mFatal ? ERRNO_ERRORS : 0);
}
- private void displayValidIds(DetectorRegistry registry, PrintStream out) {
- List<String> categories = registry.getCategories();
+ private void displayValidIds(IssueRegistry registry, PrintStream out) {
+ List<Category> categories = registry.getCategories();
out.println("Valid issue categories:");
- for (String category : categories) {
- out.println(" " + category);
+ for (Category category : categories) {
+ out.println(" " + category.getFullName());
}
out.println();
List<Issue> issues = registry.getIssues();
@@ -331,7 +370,7 @@ public class Main extends ToolContext {
}
}
- private void showIssues(DetectorRegistry registry) {
+ private void showIssues(IssueRegistry registry) {
List<Issue> issues = registry.getIssues();
List<Issue> sorted = new ArrayList<Issue>(issues);
Collections.sort(sorted, new Comparator<Issue>() {
@@ -350,12 +389,13 @@ public class Main extends ToolContext {
});
System.out.println("Available issues:\n");
- String previousCategory = null;
+ Category previousCategory = null;
for (Issue issue : sorted) {
- String category = issue.getCategory();
+ Category category = issue.getCategory();
if (!category.equals(previousCategory)) {
- System.out.println(category);
- for (int i = 0, n = category.length(); i < n; i++) {
+ String name = category.getFullName();
+ System.out.println(name);
+ for (int i = 0, n = name.length(); i < n; i++) {
System.out.print('=');
}
System.out.println('\n');
@@ -393,11 +433,17 @@ public class Main extends ToolContext {
}
}
+ static String wrapArg(String explanation) {
+ // Wrap arguments such that the wrapped lines are not showing up in the left column
+ return wrap(explanation, MAX_LINE_WIDTH, " ");
+ }
+
+
static String wrap(String explanation) {
- return wrap(explanation, MAX_LINE_WIDTH);
+ return wrap(explanation, MAX_LINE_WIDTH, "");
}
- static String wrap(String explanation, int max) {
+ static String wrap(String explanation, int lineWidth, String hangingIndent) {
int explanationLength = explanation.length();
StringBuilder sb = new StringBuilder(explanationLength * 2);
int index = 0;
@@ -406,12 +452,12 @@ public class Main extends ToolContext {
int lineEnd = explanation.indexOf('\n', index);
int next;
- if (lineEnd != -1 && (lineEnd - index) < max) {
+ if (lineEnd != -1 && (lineEnd - index) < lineWidth) {
next = lineEnd + 1;
} else {
// Line is longer than available width; grab as much as we can
- lineEnd = Math.min(index + max, explanationLength);
- if (lineEnd - index < max) {
+ lineEnd = Math.min(index + lineWidth, explanationLength);
+ if (lineEnd - index < lineWidth) {
next = explanationLength;
} else {
// then back up to the last space
@@ -427,6 +473,12 @@ public class Main extends ToolContext {
}
}
+ if (sb.length() > 0) {
+ sb.append(hangingIndent);
+ } else {
+ lineWidth -= hangingIndent.length();
+ }
+
sb.append(explanation.substring(index, lineEnd));
sb.append('\n');
index = next;
@@ -441,19 +493,31 @@ public class Main extends ToolContext {
out.println("Usage: " + command + " [flags] <project directories>\n");
out.println("Flags:");
- out.println(ARG_SUPPRESS + " <list>: Suppress a list of categories or specific issue id's");
- out.println(ARG_CHECK + " <list>: Only check the specific list of issues (categories or id's)");
- out.println(ARG_DISABLE + " <list>: Disable the list of categories or specific issue id's");
- out.println(ARG_ENABLE + " <list>: Enable the specific list of issues (plus default enabled)");
- out.println(ARG_FULLPATH + " : Use full paths in the error output");
- out.println(ARG_NOLINES + " : Do not include the source file lines with errors in the output");
- out.println(ARG_HTML + " <filename>: Create an HTML report instead");
- out.println(ARG_URL + " filepath=url: Add links to HTML report, replacing local path prefixes with url prefix");
+ out.print(wrapArg(ARG_HELP + ": This message."));
+ out.print(wrapArg(ARG_DISABLE + " <list>: Disable the list of categories or " +
+ "specific issue id's. The list should be a comma-separated list of issue " +
+ "id's or categories."));
+ out.print(wrapArg(ARG_ENABLE + " <list>: Enable the specific list of issues. " +
+ "This checks all the default issues plus the specifically enabled issues. The " +
+ "list should be a comma-separated list of issue id's or categories."));
+ out.print(wrapArg(ARG_CHECK + " <list>: Only check the specific list of issues. " +
+ "This will disable everything and re-enable the given list of issues. " +
+ "The list should be a comma-separated list of issue id's or categories."));
+ out.print(wrapArg(ARG_FULLPATH + " : Use full paths in the error output."));
+ out.print(wrapArg(ARG_NOLINES + " : Do not include the source file lines with errors " +
+ "in the output. By default, the error output includes snippets of source code " +
+ "on the line containing the error, but this flag turns it off."));
+ out.print(wrapArg(ARG_HTML + " <filename>: Create an HTML report instead."));
+ out.print(wrapArg(ARG_URL + " filepath=url: Add links to HTML report, replacing local " +
+ "path prefixes with url prefix. The mapping can be a comma-separated list of " +
+ "path prefixes to corresponding URL prefixes, such as " +
+ "C:\\temp\\Proj1=http://buildserver/sources/temp/Proj1"));
+ out.print(wrapArg(ARG_XML + " <filename>: Create an XML report instead."));
out.println();
- out.println(ARG_LISTIDS + ": List the available issue id's and exit.");
- out.println(ARG_SHOW + ": List available issues along with full explanations");
- out.println(ARG_SHOW + " <ids>: Show full explanations for the given list of issue id's");
- out.println("Id lists should be comma separated with no spaces. ");
+ out.print(wrapArg(ARG_LISTIDS + ": List the available issue id's and exit."));
+ out.print(wrapArg(ARG_SHOW + ": List available issues along with full explanations."));
+ out.print(wrapArg(ARG_SHOW + " <ids>: Show full explanations for the given list of issue id's."));
+ out.print(wrapArg(ARG_QUIET + ": Don't show progress."));
}
@Override
@@ -472,31 +536,16 @@ public class Main extends ToolContext {
}
@Override
- public boolean isEnabled(Issue issue) {
- String id = issue.getId();
- if (mSuppress.contains(id)) {
- return false;
- }
-
- if (mEnabled.contains(id)) {
- return true;
- }
-
- if (mCheck != null) {
- return mCheck.contains(id);
- }
-
- return issue.isEnabledByDefault();
+ public Configuration getConfiguration(Project project) {
+ return new CliConfiguration(null, project);
}
@Override
public void report(Context context, Issue issue, Location location, String message,
Object data) {
- if (!isEnabled(issue)) {
- return;
- }
+ assert context.configuration.isEnabled(issue);
- Severity severity = getSeverity(issue);
+ Severity severity = context.configuration.getSeverity(issue);
if (severity == Severity.IGNORE) {
return;
}
@@ -533,7 +582,7 @@ public class Main extends ToolContext {
warning.line = line;
warning.offset = startPosition.getOffset();
if (line >= 0) {
- warning.fileContents = context.toolContext.readFile(location.getFile());
+ warning.fileContents = context.client.readFile(location.getFile());
if (mShowLines) {
// Compute error line contents
@@ -595,18 +644,6 @@ public class Main extends ToolContext {
}
@Override
- public boolean isSuppressed(Context context, Issue issue, Location range, String message,
- Severity severity, Object data) {
- // Not yet supported
- return false;
- }
-
- @Override
- public Severity getSeverity(Issue issue) {
- return issue.getDefaultSeverity();
- }
-
- @Override
public String readFile(File file) {
BufferedReader reader = null;
try {
@@ -634,4 +671,61 @@ public class Main extends ToolContext {
return ""; //$NON-NLS-1$
}
+
+ /**
+ * Consult the lint.xml file, but override with the --enable and --disable
+ * flags supplied on the command line
+ */
+ private class CliConfiguration extends DefaultConfiguration {
+ CliConfiguration(Configuration parent, Project project) {
+ super(Main.this, project, parent);
+ }
+
+ @Override
+ public Severity getSeverity(Issue issue) {
+ Severity severity = super.getSeverity(issue);
+
+ String id = issue.getId();
+ if (mSuppress.contains(id)) {
+ return Severity.IGNORE;
+ }
+
+ if (mEnabled.contains(id) || (mCheck != null && mCheck.contains(id))) {
+ // Overriding default
+ // Detectors shouldn't be returning ignore as a default severity,
+ // but in case they do, force it up to warning here to ensure that
+ // it's run
+ if (severity == Severity.IGNORE) {
+ return Severity.WARNING;
+ } else {
+ return severity;
+ }
+ }
+
+ if (mCheck != null) {
+ return Severity.IGNORE;
+ }
+
+ return severity;
+ }
+ }
+
+ private class ProgressPrinter implements LintListener {
+ public void update(EventType type, Context context) {
+ switch (type) {
+ case SCANNING_PROJECT:
+ System.out.print(String.format(
+ "Scanning %1$s: ",
+ context.project.getDir().getName()));
+ break;
+ case SCANNING_FILE:
+ System.out.print('.');
+ break;
+ case CANCELED:
+ case COMPLETED:
+ System.out.println();
+ break;
+ }
+ }
+ }
}
diff --git a/lint/cli/src/com/android/tools/lint/PositionXmlParser.java b/lint/cli/src/com/android/tools/lint/PositionXmlParser.java
index 06c195b..aa7f9c9 100644
--- a/lint/cli/src/com/android/tools/lint/PositionXmlParser.java
+++ b/lint/cli/src/com/android/tools/lint/PositionXmlParser.java
@@ -16,13 +16,11 @@
package com.android.tools.lint;
-import com.android.tools.lint.api.IDomParser;
+import com.android.tools.lint.client.api.IDomParser;
+import com.android.tools.lint.client.api.IssueRegistry;
import com.android.tools.lint.detector.api.Context;
-import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Position;
-import com.android.tools.lint.detector.api.Scope;
-import com.android.tools.lint.detector.api.Severity;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
@@ -36,7 +34,6 @@ import org.xml.sax.helpers.DefaultHandler;
import java.io.StringReader;
import java.util.ArrayList;
-import java.util.EnumSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -74,25 +71,19 @@ public class PositionXmlParser implements IDomParser {
parser.parse(input, handler);
return handler.getDocument();
} catch (ParserConfigurationException e) {
- context.toolContext.log(e, null);
+ context.client.log(e, null);
} catch (SAXException e) {
- context.toolContext.report(
+ context.client.report(
context,
// Must provide an issue since API guarantees that the issue parameter
// is valid
- Issue.create("fatal", "", "", "", 10, Severity.ERROR, //$NON-NLS-1$
- EnumSet.noneOf(Scope.class)),
+ IssueRegistry.PARSER_ERROR,
new Location(context.file, null, null),
e.getCause() != null ? e.getCause().getLocalizedMessage() :
e.getLocalizedMessage(),
null);
-
- context.toolContext.log(null, String.format("Failed parsing %1$s: %2$s",
- context.file.getName(),
- e.getCause() != null ? e.getCause().getLocalizedMessage() :
- e.getLocalizedMessage()));
} catch (Throwable t) {
- context.toolContext.log(t, null);
+ context.client.log(t, null);
}
return null;
}
@@ -378,4 +369,7 @@ public class PositionXmlParser implements IDomParser {
return mColumn;
}
}
+
+ public void dispose(Context context) {
+ }
}
diff --git a/lint/cli/src/com/android/tools/lint/Warning.java b/lint/cli/src/com/android/tools/lint/Warning.java
index 0cc3d81..e6ca111 100644
--- a/lint/cli/src/com/android/tools/lint/Warning.java
+++ b/lint/cli/src/com/android/tools/lint/Warning.java
@@ -16,7 +16,7 @@
package com.android.tools.lint;
-import com.android.tools.lint.api.ToolContext;
+import com.android.tools.lint.client.api.LintClient;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Severity;
@@ -24,7 +24,7 @@ import com.android.tools.lint.detector.api.Severity;
import java.io.File;
/**
- * A {@link Warning} represents a specific warning that a {@link ToolContext}
+ * A {@link Warning} represents a specific warning that a {@link LintClient}
* has been told about. The context stores these as they are reported into a
* list of warnings such that it can sort them all before presenting them all at
* the end.
@@ -52,7 +52,7 @@ class Warning implements Comparable<Warning> {
// ---- Implements Comparable<Warning> ----
public int compareTo(Warning other) {
- // Sort by priority, then by category, then by id,
+ // Sort by category, then by priority, then by id,
// then by file, then by line
String id1 = issue.getId();
String id2 = other.issue.getId();
@@ -60,15 +60,15 @@ class Warning implements Comparable<Warning> {
return file.getName().compareTo(
other.file.getName());
}
+ int categoryDelta = issue.getCategory().compareTo(other.issue.getCategory());
+ if (categoryDelta != 0) {
+ return categoryDelta;
+ }
// DECREASING priority order
int priorityDelta = other.issue.getPriority() - issue.getPriority();
if (priorityDelta != 0) {
return priorityDelta;
}
- int categoryDelta = issue.getCategory().compareTo(other.issue.getCategory());
- if (categoryDelta != 0) {
- return categoryDelta;
- }
int idDelta = id1.compareTo(id2);
if (idDelta != -1) {
return idDelta;
diff --git a/lint/cli/src/com/android/tools/lint/XmlReporter.java b/lint/cli/src/com/android/tools/lint/XmlReporter.java
new file mode 100644
index 0000000..39044eb
--- /dev/null
+++ b/lint/cli/src/com/android/tools/lint/XmlReporter.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 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;
+
+import com.android.tools.lint.detector.api.Position;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+
+/**
+ * A reporter which emits lint results into an XML report.
+ */
+class XmlReporter extends Reporter {
+ private final File mOutput;
+
+ XmlReporter(File output) throws IOException {
+ super(new BufferedWriter(new FileWriter(output)));
+ mOutput = output;
+ }
+
+ @Override
+ void write(int errorCount, int warningCount, List<Warning> issues) throws IOException {
+ mWriter.write(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //$NON-NLS-1$
+ "<issues>\n"); //$NON-NLS-1$
+
+ if (issues.size() > 0) {
+ for (Warning warning : issues) {
+ mWriter.write("\n <issue");
+ writeAttribute(mWriter, "id", warning.issue.getId()); //$NON-NLS-1$
+ writeAttribute(mWriter, "severity", warning.severity.getDescription()); //$NON-NLS-1$
+ writeAttribute(mWriter, "message", warning.issue.getId()); //$NON-NLS-1$
+ if (warning.file != null) {
+ writeAttribute(mWriter, "file", warning.file.getPath()); //$NON-NLS-1$
+ if (warning.location != null) {
+ Position start = warning.location.getStart();
+ if (start != null) {
+ int line = start.getLine();
+ int column = start.getColumn();
+ if (line >= 0) {
+ writeAttribute(mWriter, "line", Integer.toString(line)); //$NON-NLS-1$
+ if (column >= 0) {
+ writeAttribute(mWriter, "column", Integer.toString(column)); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+ }
+ mWriter.write("\n />\n");
+ }
+ }
+
+ mWriter.write(
+ "\n</issues>\n"); //$NON-NLS-1$
+ mWriter.close();
+
+ String path = mOutput.getAbsolutePath();
+ System.out.println(String.format("Wrote HTML report to %1$s", path));
+ }
+
+ private static void writeAttribute(Writer writer, String name, String value)
+ throws IOException {
+ writer.write("\n "); //$NON-NLS-1$
+ writer.write(name);
+ writer.write('=');
+ writer.write('"');
+ for (int i = 0, n = value.length(); i < n; i++) {
+ char c = value.charAt(i);
+ switch (c) {
+ case '"':
+ writer.write("&quot;"); //$NON-NLS-1$
+ break;
+ case '\'':
+ writer.write("&apos;"); //$NON-NLS-1$
+ break;
+ case '&':
+ writer.write("&amp;"); //$NON-NLS-1$
+ break;
+ case '<':
+ writer.write("&lt;"); //$NON-NLS-1$
+ break;
+ default:
+ writer.write(c);
+ break;
+ }
+ }
+ writer.write('"');
+ }
+} \ No newline at end of file