diff options
19 files changed, 269 insertions, 53 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java index 0480cda..53b8f49 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoring.java @@ -56,6 +56,7 @@ import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.ReplaceEdit; import org.eclipse.text.edits.TextEdit; import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; +import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.w3c.dom.Attr; import org.w3c.dom.Document; @@ -283,6 +284,17 @@ public class UseCompoundDrawableRefactoring extends VisualRefactoring { setAndroidAttribute(newTextElement, androidNsPrefix, drawableAttribute, src); + // If the removed LinearLayout is the root container, transfer its namespace + // declaration to the TextView + if (layout.getParentNode() instanceof Document) { + List<Attr> declarations = findNamespaceAttributes(layout); + for (Attr attribute : declarations) { + if (attribute instanceof IndexedRegion) { + newTextElement.setAttribute(attribute.getName(), attribute.getValue()); + } + } + } + // Update any layout references to the layout to point to the text view String layoutId = getId(layout); if (layoutId.length() > 0) { diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java index 04b9b1a..c1a5ca4 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/UseCompoundDrawableRefactoringTest.java @@ -57,6 +57,11 @@ public class UseCompoundDrawableRefactoringTest extends RefactoringTest { checkRefactoring("refactoring/usecompound/compound_all.xml", "@+id/layout3"); } + public void test7() throws Exception { + // Test converting where a namespace needs to be migrated + checkRefactoring("refactoring/usecompound/compound5.xml", "@+id/layout"); + } + private void checkRefactoring(String basename, String id) throws Exception { IFile file = getLayoutFile(getProject(), basename); TestContext info = setupTestContext(file, basename); diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5-expected-7.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5-expected-7.xml new file mode 100644 index 0000000..e909811 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5-expected-7.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/TextView1" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:drawableBottom="@drawable/ic_launcher" + android:text="Hello World" > + +</TextView>
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.info b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.info new file mode 100644 index 0000000..8eb5c4b --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.info @@ -0,0 +1,3 @@ +android.widget.LinearLayout [0,74,480,800] <LinearLayout> + android.widget.TextView [0,0,107,26] <TextView> + android.widget.ImageView [0,26,72,98] <ImageView> diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.xml new file mode 100644 index 0000000..49c0594 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/refactoring/usecompound/compound5.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:id="@+id/layout" + android:orientation="vertical" > + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Hello World" /> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:src="@drawable/ic_launcher" /> + +</LinearLayout> diff --git a/lint/cli/src/com/android/tools/lint/HtmlReporter.java b/lint/cli/src/com/android/tools/lint/HtmlReporter.java index 9cc9c6f..8b3e99e 100644 --- a/lint/cli/src/com/android/tools/lint/HtmlReporter.java +++ b/lint/cli/src/com/android/tools/lint/HtmlReporter.java @@ -28,6 +28,7 @@ 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 com.google.common.annotations.Beta; import com.google.common.base.Charsets; import com.google.common.collect.Maps; import com.google.common.io.ByteStreams; @@ -51,8 +52,12 @@ import java.util.Set; /** * A reporter which emits lint results into an HTML report. + * <p> + * <b>NOTE: This is not a public or final API; if you rely on this be prepared + * to adjust your code for the next tools release.</b> */ -class HtmlReporter extends Reporter { +@Beta +public class HtmlReporter extends Reporter { private static boolean USE_HOLO_STYLE = true; private static final String CSS = USE_HOLO_STYLE ? "hololike.css" : "default.css"; //$NON-NLS-1$ //$NON-NLS-2$ @@ -72,13 +77,20 @@ class HtmlReporter extends Reporter { private String mStripPrefix; private String mFixUrl; - HtmlReporter(Main client, File output) throws IOException { + /** + * Creates a new {@link HtmlReporter} + * + * @param client the associated client + * @param output the output file + * @throws IOException if an error occurs + */ + public HtmlReporter(Main client, File output) throws IOException { super(client, output); mWriter = new BufferedWriter(new FileWriter(output)); } @Override - void write(int errorCount, int warningCount, List<Warning> issues) throws IOException { + public void write(int errorCount, int warningCount, List<Warning> issues) throws IOException { Map<Issue, String> missing = computeMissingIssues(issues); mWriter.write( @@ -406,7 +418,7 @@ class HtmlReporter extends Reporter { continue; } - if (!issue.isEnabledByDefault()) { + if (!issue.isEnabledByDefault() && !mClient.isAllEnabled()) { map.put(issue, "Default"); continue; } diff --git a/lint/cli/src/com/android/tools/lint/Main.java b/lint/cli/src/com/android/tools/lint/Main.java index 1f2191b..6a40cb3 100644 --- a/lint/cli/src/com/android/tools/lint/Main.java +++ b/lint/cli/src/com/android/tools/lint/Main.java @@ -78,6 +78,7 @@ public class Main extends LintClient { private static final String ARG_CONFIG = "--config"; //$NON-NLS-1$ private static final String ARG_URL = "--url"; //$NON-NLS-1$ private static final String ARG_VERSION = "--version"; //$NON-NLS-1$ + private static final String ARG_EXITCODE = "--exitcode"; //$NON-NLS-1$ private static final String ARG_NOWARN2 = "--nowarn"; //$NON-NLS-1$ // GCC style flag names for options @@ -100,7 +101,8 @@ public class Main extends LintClient { private Set<String> mEnabled = new HashSet<String>(); /** If non-null, only run the specified checks (possibly modified by enable/disables) */ private Set<String> mCheck = null; - private boolean mFatal; + private boolean mHasErrors; + private boolean mSetExitCode; private boolean mFullPath; private int mErrorCount; private int mWarningCount; @@ -228,6 +230,8 @@ public class Main extends LintClient { mQuiet = true; } else if (arg.equals(ARG_NOLINES)) { mShowLines = false; + } else if (arg.equals(ARG_EXITCODE)) { + mSetExitCode = true; } else if (arg.equals(ARG_VERSION)) { printVersion(); System.exit(0); @@ -489,7 +493,7 @@ public class Main extends LintClient { System.exit(ERRNO_INVALIDARGS); } - System.exit(mFatal ? ERRNO_ERRORS : 0); + System.exit(mSetExitCode ? (mHasErrors ? ERRNO_ERRORS : 0) : 0); } /** @@ -805,8 +809,10 @@ public class Main extends LintClient { ARG_HELP + " <topic>", "Help on the given topic, such as \"suppress\".", ARG_LISTIDS, "List the available issue id's and exit.", ARG_VERSION, "Output version information and exit.", + ARG_EXITCODE, "Set the exit code to " + ERRNO_ERRORS + " if errors are found.", ARG_SHOW, "List available issues along with full explanations.", ARG_SHOW + " <ids>", "Show full explanations for the given list of issue id's.", + "", "\nEnabled Checks:", ARG_DISABLE + " <list>", "Disable the list of categories or " + "specific issue id's. The list should be a comma-separated list of issue " + @@ -823,7 +829,9 @@ public class Main extends LintClient { ARG_CONFIG + " <filename>", "Use the given configuration file to " + "determine whether issues are enabled or disabled. If a project contains " + "a lint.xml file, then this config file will be used as a fallback.", - "", "\nOutput Options:", + + + "", "\nOutput Options:", ARG_QUIET, "Don't show progress.", ARG_FULLPATH, "Use full paths in the error output.", ARG_SHOWALL, "Do not truncate long messages, lists of alternate locations, etc.", @@ -840,15 +848,14 @@ public class Main extends LintClient { "to files, use " + ARG_URL + " " + VALUE_NONE, ARG_SIMPLEHTML + " <filename>", "Create a simple HTML report", ARG_XML + " <filename>", "Create an XML report instead.", - }); - out.println("\nExit Status:"); - printUsage(out, new String[] { - Integer.toString(ERRNO_ERRORS), "Lint errors detected.", - Integer.toString(ERRNO_USAGE), "Lint usage.", - Integer.toString(ERRNO_EXISTS), "Cannot clobber existing file.", - Integer.toString(ERRNO_HELP), "Lint help.", - Integer.toString(ERRNO_INVALIDARGS), "Invalid command-line argument.", + "", "\nExit Status:", + "0", "Success.", + Integer.toString(ERRNO_ERRORS), "Lint errors detected.", + Integer.toString(ERRNO_USAGE), "Lint usage.", + Integer.toString(ERRNO_EXISTS), "Cannot clobber existing file.", + Integer.toString(ERRNO_HELP), "Lint help.", + Integer.toString(ERRNO_INVALIDARGS), "Invalid command-line argument.", }); } @@ -936,12 +943,12 @@ public class Main extends LintClient { } if (severity == Severity.FATAL) { - mFatal = true; // From here on, treat the fatal error as an error such that we don't display // both "Fatal:" and "Error:" etc in the error output. severity = Severity.ERROR; } if (severity == Severity.ERROR) { + mHasErrors = true; mErrorCount++; } else { mWarningCount++; @@ -1096,11 +1103,14 @@ public class Main extends LintClient { // 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 && severity == issue.getDefaultSeverity()) { - return Severity.WARNING; - } else { - return severity; + if (severity == Severity.IGNORE) { + severity = issue.getDefaultSeverity(); + if (severity == Severity.IGNORE) { + severity = Severity.WARNING; + } } + + return severity; } if (mCheck != null && issue != LINT_ERROR && issue != PARSER_ERROR) { @@ -1162,6 +1172,11 @@ public class Main extends LintClient { return path; } + /** Returns whether all warnings are enabled, including those disabled by default */ + boolean isAllEnabled() { + return mWarnAll; + } + /** Returns the issue registry used by this client */ IssueRegistry getRegistry() { return mRegistry; diff --git a/lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java b/lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java index db7b4fb..d039edc 100644 --- a/lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java +++ b/lint/cli/src/com/android/tools/lint/MultiProjectHtmlReporter.java @@ -37,17 +37,17 @@ import java.util.Set; * "Multiplexing" reporter which allows output to be split up into a separate * report for each separate project. It also adds an overview index. */ -class MultiProjectHtmlReporter extends HtmlReporter { +public class MultiProjectHtmlReporter extends HtmlReporter { private static final String INDEX_NAME = "index.html"; //$NON-NLS-1$ private final File mDir; - MultiProjectHtmlReporter(Main client, File dir) throws IOException { + public MultiProjectHtmlReporter(Main client, File dir) throws IOException { super(client, new File(dir, INDEX_NAME)); mDir = dir; } @Override - void write(int errorCount, int warningCount, List<Warning> allIssues) throws IOException { + public void write(int errorCount, int warningCount, List<Warning> allIssues) throws IOException { Map<Project, List<Warning>> projectToWarnings = new HashMap<Project, List<Warning>>(); for (Warning warning : allIssues) { List<Warning> list = projectToWarnings.get(warning.project); diff --git a/lint/cli/src/com/android/tools/lint/Reporter.java b/lint/cli/src/com/android/tools/lint/Reporter.java index bee0eb4..2c86635 100644 --- a/lint/cli/src/com/android/tools/lint/Reporter.java +++ b/lint/cli/src/com/android/tools/lint/Reporter.java @@ -20,6 +20,7 @@ import static com.android.tools.lint.detector.api.LintConstants.DOT_9PNG; import static com.android.tools.lint.detector.api.LintConstants.DOT_PNG; import static com.android.tools.lint.detector.api.LintUtils.endsWith; +import com.google.common.annotations.Beta; import com.google.common.io.ByteStreams; import com.google.common.io.Closeables; import com.google.common.io.Files; @@ -35,8 +36,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -/** A reporter is an output generator for lint warnings */ -abstract class Reporter { +/** A reporter is an output generator for lint warnings + * <p> + * <b>NOTE: This is not a public or final API; if you rely on this be prepared + * to adjust your code for the next tools release.</b> + */ +@Beta +public abstract class Reporter { protected final Main mClient; protected final File mOutput; protected String mTitle = "Lint Report"; @@ -47,7 +53,16 @@ abstract class Reporter { protected Map<File, String> mResourceUrl = new HashMap<File, String>(); protected Map<String, File> mNameToFile = new HashMap<String, File>(); - abstract void write(int errorCount, int warningCount, List<Warning> issues) throws IOException; + /** + * Write the given warnings into the report + * + * @param errorCount the number of errors + * @param warningCount the number of warnings + * @param issues the issues to be reported + * @throws IOException if an error occurs + */ + public abstract void write(int errorCount, int warningCount, List<Warning> issues) + throws IOException; protected Reporter(Main client, File output) { mClient = client; @@ -59,12 +74,12 @@ abstract class Reporter { * * @param title the title of the report */ - void setTitle(String title) { + public void setTitle(String title) { mTitle = title; } /** @return the title of the report */ - String getTitle() { + public String getTitle() { return mTitle; } @@ -75,7 +90,7 @@ abstract class Reporter { * @param bundleResources if true, copy images into a directory relative to * the report */ - void setBundleResources(boolean bundleResources) { + public void setBundleResources(boolean bundleResources) { mBundleResources = bundleResources; mSimpleFormat = false; } @@ -86,7 +101,7 @@ abstract class Reporter { * * @param simpleFormat whether the formatting should be simple */ - void setSimpleFormat(boolean simpleFormat) { + public void setSimpleFormat(boolean simpleFormat) { mSimpleFormat = simpleFormat; } @@ -96,7 +111,7 @@ abstract class Reporter { * * @return whether the report should use simple formatting */ - boolean isSimpleFormat() { + public boolean isSimpleFormat() { return mSimpleFormat; } diff --git a/lint/cli/src/com/android/tools/lint/TextReporter.java b/lint/cli/src/com/android/tools/lint/TextReporter.java index 47202d1..63ee857 100644 --- a/lint/cli/src/com/android/tools/lint/TextReporter.java +++ b/lint/cli/src/com/android/tools/lint/TextReporter.java @@ -18,22 +18,35 @@ package com.android.tools.lint; import com.android.tools.lint.detector.api.Location; import com.android.tools.lint.detector.api.Position; +import com.google.common.annotations.Beta; import java.io.IOException; import java.io.Writer; import java.util.List; -/** A reporter which emits lint warnings as plain text strings */ -class TextReporter extends Reporter { +/** + * A reporter which emits lint warnings as plain text strings + * <p> + * <b>NOTE: This is not a public or final API; if you rely on this be prepared + * to adjust your code for the next tools release.</b> + */ +@Beta +public class TextReporter extends Reporter { private final Writer mWriter; - TextReporter(Main client, Writer writer) { + /** + * Constructs a new {@link TextReporter} + * + * @param client the client + * @param writer the writer to write into + */ + public TextReporter(Main client, Writer writer) { super(client, null); mWriter = writer; } @Override - void write(int errorCount, int warningCount, List<Warning> issues) throws IOException { + public void write(int errorCount, int warningCount, List<Warning> issues) throws IOException { boolean abbreviate = mClient.getDriver().isAbbreviating(); StringBuilder output = new StringBuilder(issues.size() * 200); diff --git a/lint/cli/src/com/android/tools/lint/XmlReporter.java b/lint/cli/src/com/android/tools/lint/XmlReporter.java index 4de1dd7..03fc937 100644 --- a/lint/cli/src/com/android/tools/lint/XmlReporter.java +++ b/lint/cli/src/com/android/tools/lint/XmlReporter.java @@ -18,6 +18,7 @@ package com.android.tools.lint; import com.android.tools.lint.detector.api.Location; import com.android.tools.lint.detector.api.Position; +import com.google.common.annotations.Beta; import com.google.common.base.Charsets; import com.google.common.io.Files; @@ -29,17 +30,28 @@ import java.util.List; /** * A reporter which emits lint results into an XML report. + * <p> + * <b>NOTE: This is not a public or final API; if you rely on this be prepared + * to adjust your code for the next tools release.</b> */ -class XmlReporter extends Reporter { +@Beta +public class XmlReporter extends Reporter { private final Writer mWriter; - XmlReporter(Main client, File output) throws IOException { + /** + * Constructs a new {@link XmlReporter} + * + * @param client the client + * @param output the output file + * @throws IOException if an error occurs + */ + public XmlReporter(Main client, File output) throws IOException { super(client, output); mWriter = new BufferedWriter(Files.newWriter(output, Charsets.UTF_8)); } @Override - void write(int errorCount, int warningCount, List<Warning> issues) throws IOException { + public 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$ diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java index 7223670..8c35b74 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiClass.java @@ -172,6 +172,17 @@ public class ApiClass { } public void addMethod(String name, int since) { + // Strip off the method type at the end to ensure that the code which + // produces inherited methods doesn't get confused and end up multiple entries. + // For example, java/nio/Buffer has the method "array()Ljava/lang/Object;", + // and the subclass java/nio/ByteBuffer has the method "array()[B". We want + // the lookup on mMethods to associate the ByteBuffer array method to be + // considered overriding the Buffer method. + int index = name.indexOf(')'); + if (index != -1) { + name = name.substring(0, index + 1); + } + Integer i = mMethods.get(name); if (i == null || i.intValue() > since) { mMethods.put(name, Integer.valueOf(since)); @@ -204,23 +215,47 @@ public class ApiClass { } /** - * Returns the set of all members (method and fields), including inherited + * Returns the set of all methods, including inherited * ones. * * @param info the api to look up super classes from - * @return a set containing all the members (methods and fields) + * @return a set containing all the members fields */ - public Set<String> getAllMembers(Api info) { + public Set<String> getAllMethods(Api info) { Set<String> members = new HashSet<String>(100); - addAllMembers(info, members); + addAllMethods(info, members); return members; } - private void addAllMembers(Api info, Set<String> set) { + private void addAllMethods(Api info, Set<String> set) { for (String method : mMethods.keySet()) { set.add(method); } + for (Pair<String, Integer> superClass : mSuperClasses) { + ApiClass clz = info.getClass(superClass.getFirst()); + assert clz != null : superClass.getSecond(); + if (clz != null) { + clz.addAllMethods(info, set); + } + } + } + + /** + * Returns the set of all fields, including inherited + * ones. + * + * @param info the api to look up super classes from + * @return a set containing all the fields + */ + public Set<String> getAllFields(Api info) { + Set<String> members = new HashSet<String>(100); + addAllFields(info, members); + + return members; + } + + private void addAllFields(Api info, Set<String> set) { for (String field : mFields.keySet()) { set.add(field); } @@ -228,8 +263,9 @@ public class ApiClass { ApiClass clz = info.getClass(superClass.getFirst()); assert clz != null : superClass.getSecond(); if (clz != null) { - clz.addAllMembers(info, set); + clz.addAllFields(info, set); } } } + } diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java index 5f9a1e3..306e6a2 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ApiLookup.java @@ -73,7 +73,7 @@ public class ApiLookup { /** Relative path to the api-versions.xml database file within the Lint installation */ private static final String XML_FILE_PATH = "platform-tools/api/api-versions.xml"; //$NON-NLS-1$ private static final String FILE_HEADER = "API database used by Android lint\000"; - private static final int BINARY_FORMAT_VERSION = 1; + private static final int BINARY_FORMAT_VERSION = 2; private static final boolean DEBUG_FORCE_REGENERATE_BINARY = false; private static final boolean DEBUG_SEARCH = false; private static final boolean WRITE_STATS = false; @@ -336,7 +336,8 @@ public class ApiLookup { String className = entry.getKey(); ApiClass apiClass = entry.getValue(); - Set<String> allMembers = apiClass.getAllMembers(info); + Set<String> allMethods = apiClass.getAllMethods(info); + Set<String> allFields = apiClass.getAllFields(info); // Strip out all members that have been supported since version 1. // This makes the database *much* leaner (down from about 4M to about @@ -345,14 +346,27 @@ public class ApiLookup { // requires a version *higher* than the minimum. If in the future the // database needs to answer queries about whether a method is public // or not, then we'd need to put this data back in. - List<String> members = new ArrayList<String>(allMembers.size()); - for (String member : allMembers) { - Integer since; - if (member.indexOf('(') != -1) { - since = apiClass.getMethod(member, info); - } else { - since = apiClass.getField(member, info); + List<String> members = new ArrayList<String>(allMethods.size() + allFields.size()); + for (String member : allMethods) { + Integer since = apiClass.getMethod(member, info); + assert since != null : className + ':' + member; + if (since == null) { + since = 1; + } + if (since != 1) { + members.add(member); } + } + + // Strip out all members that have been supported since version 1. + // This makes the database *much* leaner (down from about 4M to about + // 1.7M), and this just fills the table with entries that ultimately + // don't help the API checker since it just needs to know if something + // requires a version *higher* than the minimum. If in the future the + // database needs to answer queries about whether a method is public + // or not, then we'd need to put this data back in. + for (String member : allFields) { + Integer since = apiClass.getField(member, info); assert since != null : className + ':' + member; if (since == null) { since = 1; diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java index 4dd7eb1..dc65f26 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/InefficientWeightDetector.java @@ -157,6 +157,7 @@ public class InefficientWeightDetector extends LayoutDetector { } if (allChildrenAreLayouts) { context.report(BASELINE_WEIGHTS, + element, context.getLocation(element), "Set android:baselineAligned=\"false\" on this element for better performance", null); @@ -178,6 +179,7 @@ public class InefficientWeightDetector extends LayoutDetector { "Use a %1$s of 0dip instead of %2$s for better performance", dimension, size); context.report(INEFFICIENT_WEIGHT, + element, context.getLocation(sizeNode != null ? sizeNode : weightChild), msg, null); } diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java index bda828d..c5a9302 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypographyDetector.java @@ -178,6 +178,9 @@ public class TypographyDetector extends ResourceXmlDetector { private static final String FRACTION_MESSAGE = "Use fraction character %1$c (%2$s) instead of %3$s ?"; + private static final String FRACTION_MESSAGE_PATTERN = + "Use fraction character (.+) \\((.+)\\) instead of (.+) \\?"; + private boolean mCheckDashes; private boolean mCheckQuotes; private boolean mCheckFractions; @@ -477,6 +480,17 @@ public class TypographyDetector extends ResourceXmlDetector { edits.add(new ReplaceEdit(endOffset, 1, "\u2019")); //$NON-NLS-1$ } } + } else { + Matcher matcher = Pattern.compile(FRACTION_MESSAGE_PATTERN).matcher(message); + if (matcher.find()) { + // "Use fraction character %1$c (%2$s) instead of %3$s ?"; + String replace = matcher.group(3); + int offset = text.indexOf(replace); + if (offset != -1) { + String replaceWith = matcher.group(2); + edits.add(new ReplaceEdit(offset, replace.length(), replaceWith)); + } + } } return edits; diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java index 8ded0e6..540a0f1 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/UseCompoundDrawableDetector.java @@ -17,6 +17,7 @@ package com.android.tools.lint.checks; import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI; +import static com.android.tools.lint.detector.api.LintConstants.ATTR_BACKGROUND; import static com.android.tools.lint.detector.api.LintConstants.ATTR_LAYOUT_WEIGHT; import static com.android.tools.lint.detector.api.LintConstants.IMAGE_VIEW; import static com.android.tools.lint.detector.api.LintConstants.LINEAR_LAYOUT; @@ -86,6 +87,12 @@ public class UseCompoundDrawableDetector extends LayoutDetector { ((second.getTagName().equals(IMAGE_VIEW) && first.getTagName().equals(TEXT_VIEW) && !second.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_WEIGHT)))) { + // If the layout has a background, ignore since it would disappear from + // the TextView + if (element.hasAttributeNS(ANDROID_URI, ATTR_BACKGROUND)) { + return; + } + context.report(ISSUE, element, context.getLocation(element), "This tag and its children can be replaced by one <TextView/> and " + "a compound drawable", null); diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java index a7c2de9..044778f 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ApiLookupTest.java @@ -57,6 +57,11 @@ public class ApiLookupTest extends AbstractCheckTest { assertTrue(mDb.getCallVersion("java/lang/Object", "getClass", "()") <= 1); } + public void testIssue26467() { + assertTrue(mDb.getCallVersion("java/nio/ByteBuffer", "array", "()") <= 1); + assertEquals(9, mDb.getCallVersion("java/nio/Buffer", "array", "()")); + } + @Override protected Detector getDetector() { fail("This is not used in the ApiDatabase test"); diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java index 16aee19..6abfa71 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/UseCompoundDrawableDetectorTest.java @@ -31,4 +31,11 @@ public class UseCompoundDrawableDetectorTest extends AbstractCheckTest { "<TextView/> and a compound drawable", lintFiles("res/layout/compound.xml")); } + + public void testCompound2() throws Exception { + // Ignore layouts that set a custom background + assertEquals( + "No warnings.", + lintFiles("res/layout/compound2.xml")); + } } diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/compound2.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/compound2.xml new file mode 100644 index 0000000..24f45dc --- /dev/null +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/compound2.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:background="@android:drawable/ic_dialog_alert" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + +</LinearLayout> |