aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-01-05 15:47:09 -0800
committerTor Norbye <tnorbye@google.com>2012-01-05 21:25:47 -0800
commit581ca2e75fd638f6e95570ac54ff9e6b7b7cde84 (patch)
tree130b1ad476c0230db414fdd03cfe4efaac7dadbc
parentc000db8d112f4143249fa79a24c6ddb2ffc122f3 (diff)
downloadsdk-581ca2e75fd638f6e95570ac54ff9e6b7b7cde84.zip
sdk-581ca2e75fd638f6e95570ac54ff9e6b7b7cde84.tar.gz
sdk-581ca2e75fd638f6e95570ac54ff9e6b7b7cde84.tar.bz2
Extract positional XML parser into common and fix encoding issues
The XML DOM parser used by the lint CLI driver (which tracks positions) is needed outside of lint, so pull it out of the lint/cli project, and refactor it such that it does not directly reference the lint Position APIs (but can utilize them when subclassed in lint). In addition, handle non-UTF-8 file encodings. XML files can be encoded in other character sets, and can specify this via the encoding attribute in the XML prologue. Until now, the CLI lint runner would just read the XML file contents in using the default encoding and parse this. Now there's a new utility method which takes a byte[] and infers the desired encoding and uses that to convert the byte[] into a string using the correct encoding. (We can't just pass an InputStream and let the SAX parser handle this on its own because the XML parser needs to access the character stream in order to assign correct node offsets.) This code now also handles the byte order mark more cleanly. There are some new unit tests too to check the new encoding, BOM and offset handling. Change-Id: Ib0badbbe72172e3408c6d5af2413be51280a7724
-rw-r--r--common/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--common/.settings/org.eclipse.jdt.core.prefs93
-rw-r--r--common/.settings/org.moreunit.prefs5
-rw-r--r--common/src/com/android/io/FileWrapper.java7
-rw-r--r--common/src/com/android/io/FolderWrapper.java8
-rw-r--r--common/src/com/android/resources/Density.java5
-rw-r--r--common/src/com/android/resources/Keyboard.java5
-rw-r--r--common/src/com/android/resources/KeyboardState.java5
-rw-r--r--common/src/com/android/resources/Navigation.java5
-rw-r--r--common/src/com/android/resources/NavigationState.java5
-rw-r--r--common/src/com/android/resources/NightMode.java5
-rw-r--r--common/src/com/android/resources/ScreenOrientation.java5
-rw-r--r--common/src/com/android/resources/ScreenRatio.java5
-rw-r--r--common/src/com/android/resources/ScreenSize.java5
-rw-r--r--common/src/com/android/resources/TouchScreen.java5
-rw-r--r--common/src/com/android/resources/UiMode.java5
-rw-r--r--common/src/com/android/util/PositionXmlParser.java (renamed from lint/cli/src/com/android/tools/lint/PositionXmlParser.java)389
-rw-r--r--common/tests/.classpath1
-rw-r--r--common/tests/src/com/android/util/PositionXmlParserTest.java243
-rw-r--r--eclipse/dictionary.txt1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java31
-rw-r--r--lint/cli/.classpath1
-rw-r--r--lint/cli/Android.mk1
-rw-r--r--lint/cli/etc/manifest.txt2
-rw-r--r--lint/cli/src/com/android/tools/lint/LintCliXmlParser.java174
-rw-r--r--lint/cli/src/com/android/tools/lint/Main.java35
-rw-r--r--lint/libs/lint_checks/tests/.classpath2
-rw-r--r--lint/libs/lint_checks/tests/Android.mk2
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/LintCliXmlParserTest.java (renamed from lint/libs/lint_checks/tests/src/com/android/tools/lint/PositionXmlParserTest.java)29
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java19
30 files changed, 925 insertions, 176 deletions
diff --git a/common/.settings/org.eclipse.core.resources.prefs b/common/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..d8a1f3c
--- /dev/null
+++ b/common/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Thu Jan 05 21:13:52 PST 2012
+eclipse.preferences.version=1
+encoding//tests/src/com/android/util/PositionXmlParserTest.java=UTF-8
diff --git a/common/.settings/org.eclipse.jdt.core.prefs b/common/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..5381a0e
--- /dev/null
+++ b/common/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,93 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled
+org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/common/.settings/org.moreunit.prefs b/common/.settings/org.moreunit.prefs
new file mode 100644
index 0000000..c0ed4c1
--- /dev/null
+++ b/common/.settings/org.moreunit.prefs
@@ -0,0 +1,5 @@
+#Thu Jan 05 10:46:32 PST 2012
+eclipse.preferences.version=1
+org.moreunit.prefixes=
+org.moreunit.unitsourcefolder=common\:src\:common-tests\:src
+org.moreunit.useprojectsettings=true
diff --git a/common/src/com/android/io/FileWrapper.java b/common/src/com/android/io/FileWrapper.java
index 2859c0d..84a1f3e 100644
--- a/common/src/com/android/io/FileWrapper.java
+++ b/common/src/com/android/io/FileWrapper.java
@@ -85,6 +85,7 @@ public class FileWrapper extends File implements IAbstractFile {
super(uri);
}
+ @Override
public InputStream getContents() throws StreamException {
try {
return new FileInputStream(this);
@@ -93,6 +94,7 @@ public class FileWrapper extends File implements IAbstractFile {
}
}
+ @Override
public void setContents(InputStream source) throws StreamException {
FileOutputStream fos = null;
try {
@@ -116,6 +118,7 @@ public class FileWrapper extends File implements IAbstractFile {
}
}
+ @Override
public OutputStream getOutputStream() throws StreamException {
try {
return new FileOutputStream(this);
@@ -124,10 +127,12 @@ public class FileWrapper extends File implements IAbstractFile {
}
}
+ @Override
public PreferredWriteMode getPreferredWriteMode() {
return PreferredWriteMode.OUTPUTSTREAM;
}
+ @Override
public String getOsLocation() {
return getAbsolutePath();
}
@@ -137,10 +142,12 @@ public class FileWrapper extends File implements IAbstractFile {
return isFile();
}
+ @Override
public long getModificationStamp() {
return lastModified();
}
+ @Override
public IAbstractFolder getParentFolder() {
String p = this.getParent();
if (p == null) {
diff --git a/common/src/com/android/io/FolderWrapper.java b/common/src/com/android/io/FolderWrapper.java
index 26ed9cf..c29c934 100644
--- a/common/src/com/android/io/FolderWrapper.java
+++ b/common/src/com/android/io/FolderWrapper.java
@@ -81,6 +81,7 @@ public class FolderWrapper extends File implements IAbstractFolder {
super(file.getAbsolutePath());
}
+ @Override
public IAbstractResource[] listMembers() {
File[] files = listFiles();
final int count = files == null ? 0 : files.length;
@@ -100,8 +101,10 @@ public class FolderWrapper extends File implements IAbstractFolder {
return afiles;
}
+ @Override
public boolean hasFile(final String name) {
String[] match = list(new FilenameFilter() {
+ @Override
public boolean accept(IAbstractFolder dir, String filename) {
return name.equals(filename);
}
@@ -110,14 +113,17 @@ public class FolderWrapper extends File implements IAbstractFolder {
return match.length > 0;
}
+ @Override
public IAbstractFile getFile(String name) {
return new FileWrapper(this, name);
}
+ @Override
public IAbstractFolder getFolder(String name) {
return new FolderWrapper(this, name);
}
+ @Override
public IAbstractFolder getParentFolder() {
String p = this.getParent();
if (p == null) {
@@ -126,6 +132,7 @@ public class FolderWrapper extends File implements IAbstractFolder {
return new FolderWrapper(p);
}
+ @Override
public String getOsLocation() {
return getAbsolutePath();
}
@@ -135,6 +142,7 @@ public class FolderWrapper extends File implements IAbstractFolder {
return isDirectory();
}
+ @Override
public String[] list(FilenameFilter filter) {
File[] files = listFiles();
if (files != null && files.length > 0) {
diff --git a/common/src/com/android/resources/Density.java b/common/src/com/android/resources/Density.java
index f838de4..610789a 100644
--- a/common/src/com/android/resources/Density.java
+++ b/common/src/com/android/resources/Density.java
@@ -72,6 +72,7 @@ public enum Density implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
@@ -88,10 +89,12 @@ public enum Density implements ResourceEnum {
return "";
}
+ @Override
public String getShortDisplayValue() {
return mDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mDisplayValue;
}
@@ -120,10 +123,12 @@ public enum Density implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return this != NODPI; // nodpi is not a valid config for devices.
}
diff --git a/common/src/com/android/resources/Keyboard.java b/common/src/com/android/resources/Keyboard.java
index eb99f9b..d6bc80a 100644
--- a/common/src/com/android/resources/Keyboard.java
+++ b/common/src/com/android/resources/Keyboard.java
@@ -53,14 +53,17 @@ public enum Keyboard implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -89,10 +92,12 @@ public enum Keyboard implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/KeyboardState.java b/common/src/com/android/resources/KeyboardState.java
index e3333f5..2eb7e00 100644
--- a/common/src/com/android/resources/KeyboardState.java
+++ b/common/src/com/android/resources/KeyboardState.java
@@ -50,14 +50,17 @@ public enum KeyboardState implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -86,10 +89,12 @@ public enum KeyboardState implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/Navigation.java b/common/src/com/android/resources/Navigation.java
index d5d9541..f857e5f 100644
--- a/common/src/com/android/resources/Navigation.java
+++ b/common/src/com/android/resources/Navigation.java
@@ -51,14 +51,17 @@ public enum Navigation implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -87,10 +90,12 @@ public enum Navigation implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/NavigationState.java b/common/src/com/android/resources/NavigationState.java
index 266d9da..63b8fea 100644
--- a/common/src/com/android/resources/NavigationState.java
+++ b/common/src/com/android/resources/NavigationState.java
@@ -49,14 +49,17 @@ public enum NavigationState implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -85,10 +88,12 @@ public enum NavigationState implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/NightMode.java b/common/src/com/android/resources/NightMode.java
index 2d64316..8fe1dd9 100644
--- a/common/src/com/android/resources/NightMode.java
+++ b/common/src/com/android/resources/NightMode.java
@@ -49,14 +49,17 @@ public enum NightMode implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -85,10 +88,12 @@ public enum NightMode implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/ScreenOrientation.java b/common/src/com/android/resources/ScreenOrientation.java
index 56f907b..b18753d 100644
--- a/common/src/com/android/resources/ScreenOrientation.java
+++ b/common/src/com/android/resources/ScreenOrientation.java
@@ -50,14 +50,17 @@ public enum ScreenOrientation implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -87,10 +90,12 @@ public enum ScreenOrientation implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/ScreenRatio.java b/common/src/com/android/resources/ScreenRatio.java
index 2794b6e..bb575b0 100644
--- a/common/src/com/android/resources/ScreenRatio.java
+++ b/common/src/com/android/resources/ScreenRatio.java
@@ -49,14 +49,17 @@ public enum ScreenRatio implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -86,10 +89,12 @@ public enum ScreenRatio implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/ScreenSize.java b/common/src/com/android/resources/ScreenSize.java
index b6ffc50..4def540 100644
--- a/common/src/com/android/resources/ScreenSize.java
+++ b/common/src/com/android/resources/ScreenSize.java
@@ -51,14 +51,17 @@ public enum ScreenSize implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -88,10 +91,12 @@ public enum ScreenSize implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/TouchScreen.java b/common/src/com/android/resources/TouchScreen.java
index 7ee1f0f..7eeeb08 100644
--- a/common/src/com/android/resources/TouchScreen.java
+++ b/common/src/com/android/resources/TouchScreen.java
@@ -50,14 +50,17 @@ public enum TouchScreen implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mShortDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mLongDisplayValue;
}
@@ -87,10 +90,12 @@ public enum TouchScreen implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return false;
}
+ @Override
public boolean isValidValueForDevice() {
return true;
}
diff --git a/common/src/com/android/resources/UiMode.java b/common/src/com/android/resources/UiMode.java
index 36c903b..d1ddbc8 100644
--- a/common/src/com/android/resources/UiMode.java
+++ b/common/src/com/android/resources/UiMode.java
@@ -49,14 +49,17 @@ public enum UiMode implements ResourceEnum {
return null;
}
+ @Override
public String getResourceValue() {
return mValue;
}
+ @Override
public String getShortDisplayValue() {
return mDisplayValue;
}
+ @Override
public String getLongDisplayValue() {
return mDisplayValue;
}
@@ -85,10 +88,12 @@ public enum UiMode implements ResourceEnum {
return null;
}
+ @Override
public boolean isFakeValue() {
return this == NORMAL; // NORMAL is not a real enum. it's used for internal state only.
}
+ @Override
public boolean isValidValueForDevice() {
return this != NORMAL;
}
diff --git a/lint/cli/src/com/android/tools/lint/PositionXmlParser.java b/common/src/com/android/util/PositionXmlParser.java
index b4af282..bfe8075 100644
--- a/lint/cli/src/com/android/tools/lint/PositionXmlParser.java
+++ b/common/src/com/android/util/PositionXmlParser.java
@@ -14,15 +14,10 @@
* limitations under the License.
*/
-package com.android.tools.lint;
+package com.android.util;
-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.Location;
-import com.android.tools.lint.detector.api.Location.Handle;
-import com.android.tools.lint.detector.api.Position;
-import com.android.tools.lint.detector.api.XmlContext;
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
@@ -35,8 +30,11 @@ import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
-import java.io.File;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
@@ -52,56 +50,242 @@ import javax.xml.parsers.SAXParserFactory;
* A simple DOM XML parser which can retrieve exact beginning and end offsets
* (and line and column numbers) for element nodes as well as attribute nodes.
*/
-public class PositionXmlParser implements IDomParser {
- private static final String CONTENT_KEY = "contents"; //$NON-NLS-1$
- private final static String POS_KEY = "offsets"; //$NON-NLS-1$
+public class PositionXmlParser {
+ private static final String UTF_8 = "UTF-8"; //$NON-NLS-1$
+ private static final String UTF_16 = "UTF_16"; //$NON-NLS-1$
+ private static final String UTF_16LE = "UTF_16LE"; //$NON-NLS-1$
+ private static final String CONTENT_KEY = "contents"; //$NON-NLS-1$
+ private final static String POS_KEY = "offsets"; //$NON-NLS-1$
private static final String NAMESPACE_PREFIX_FEATURE =
- "http://xml.org/sax/features/namespace-prefixes"; //$NON-NLS-1$
+ "http://xml.org/sax/features/namespace-prefixes"; //$NON-NLS-1$
private static final String NAMESPACE_FEATURE =
- "http://xml.org/sax/features/namespaces"; //$NON-NLS-1$
+ "http://xml.org/sax/features/namespaces"; //$NON-NLS-1$
+ /** See http://www.w3.org/TR/REC-xml/#NT-EncodingDecl */
+ private static final Pattern ENCODING_PATTERN =
+ Pattern.compile("encoding=['\"](\\S*)['\"]");//$NON-NLS-1$
- // ---- Implements IDomParser ----
+ /**
+ * Parses the XML content from the given input stream.
+ *
+ * @param input the input stream containing the XML to be parsed
+ * @return the corresponding document
+ * @throws ParserConfigurationException if a SAX parser is not available
+ * @throws SAXException if the document contains a parsing error
+ * @throws IOException if something is seriously wrong. This should not
+ * happen since the input source is known to be constructed from
+ * a string.
+ */
+ @Nullable
+ public Document parse(@NonNull InputStream input)
+ throws ParserConfigurationException, SAXException, IOException {
+ // Read in all the data
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ while (true) {
+ int r = input.read(buf);
+ if (r == -1) {
+ break;
+ }
+ out.write(buf, 0, r);
+ }
+ input.close();
+ return parse(out.toByteArray());
+ }
+
+ /**
+ * Parses the XML content from the given byte array
+ *
+ * @param data the raw XML data (with unknown encoding)
+ * @return the corresponding document
+ * @throws ParserConfigurationException if a SAX parser is not available
+ * @throws SAXException if the document contains a parsing error
+ * @throws IOException if something is seriously wrong. This should not
+ * happen since the input source is known to be constructed from
+ * a string.
+ */
+ @Nullable
+ public Document parse(@NonNull byte[] data)
+ throws ParserConfigurationException, SAXException, IOException {
+ String xml = getXmlString(data);
+ return parse(xml, new InputSource(new StringReader(xml)), true);
+ }
- @Override
- public Document parseXml(XmlContext context) {
- return parse(context, context.getContents(), true);
+ /**
+ * Parses the given XML content.
+ *
+ * @param xml the XML string to be parsed. This must be in the correct
+ * encoding already.
+ * @return the corresponding document
+ * @throws ParserConfigurationException if a SAX parser is not available
+ * @throws SAXException if the document contains a parsing error
+ * @throws IOException if something is seriously wrong. This should not
+ * happen since the input source is known to be constructed from
+ * a string.
+ */
+ @Nullable
+ public Document parse(@NonNull String xml)
+ throws ParserConfigurationException, SAXException, IOException {
+ return parse(xml, new InputSource(new StringReader(xml)), true);
}
- private Document parse(Context context, String xml, boolean checkBom) {
+ @NonNull
+ private Document parse(@NonNull String xml, @NonNull InputSource input, boolean checkBom)
+ throws ParserConfigurationException, SAXException, IOException {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature(NAMESPACE_FEATURE, true);
factory.setFeature(NAMESPACE_PREFIX_FEATURE, true);
SAXParser parser = factory.newSAXParser();
-
- InputSource input = new InputSource(new StringReader(xml));
DomBuilder handler = new DomBuilder(xml);
parser.parse(input, handler);
return handler.getDocument();
- } catch (ParserConfigurationException e) {
- context.log(e, null);
} catch (SAXException e) {
if (checkBom && e.getMessage().contains("Content is not allowed in prolog")) {
// Byte order mark in the string? Skip it. There are many markers
// (see http://en.wikipedia.org/wiki/Byte_order_mark) so here we'll
// just skip those up to the XML prolog beginning character, <
xml = xml.replaceFirst("^([\\W]+)<","<"); //$NON-NLS-1$ //$NON-NLS-2$
- return parse(context, xml, false);
+ return parse(xml, null, false);
}
- context.report(
- // Must provide an issue since API guarantees that the issue parameter
- // is valid
- IssueRegistry.PARSER_ERROR, Location.create(context.file),
- e.getCause() != null ? e.getCause().getLocalizedMessage() :
- e.getLocalizedMessage(),
- null);
- } catch (Throwable t) {
- context.log(t, null);
+ throw e;
}
- return null;
}
- static Position getPositions(Node node) {
+ /**
+ * Returns the String corresponding to the given byte array of XML data
+ * (with unknown encoding). This method attempts to guess the encoding based
+ * on the XML prologue.
+ * @param data the XML data to be decoded into a string
+ * @return a string corresponding to the XML data
+ */
+ public static String getXmlString(byte[] data) {
+ int offset = 0;
+
+ String defaultCharset = UTF_8;
+ String charset = null;
+ // Look for the byte order mark, to see if we need to remove bytes from
+ // the input stream (and to determine whether files are big endian or little endian) etc
+ // for files which do not specify the encoding.
+ // See http://unicode.org/faq/utf_bom.html#BOM for more.
+ if (data.length > 4) {
+ if (data[0] == (byte)0xef && data[1] == (byte)0xbb && data[2] == (byte)0xbf) {
+ // UTF-8
+ defaultCharset = charset = UTF_8;
+ offset += 3;
+ } else if (data[0] == (byte)0xfe && data[1] == (byte)0xff) {
+ // UTF-16, big-endian
+ defaultCharset = charset = UTF_16;
+ offset += 2;
+ } else if (data[0] == (byte)0x0 && data[1] == (byte)0x0
+ && data[2] == (byte)0xfe && data[3] == (byte)0xff) {
+ // UTF-32, big-endian
+ defaultCharset = charset = "UTF_32"; //$NON-NLS-1$
+ offset += 4;
+ } else if (data[0] == (byte)0xff && data[1] == (byte)0xfe
+ && data[2] == (byte)0x0 && data[3] == (byte)0x0) {
+ // UTF-32, little-endian. We must check for this *before* looking for
+ // UTF_16LE since UTF_32LE has the same prefix!
+ defaultCharset = charset = "UTF_32LE"; //$NON-NLS-1$
+ offset += 4;
+ } else if (data[0] == (byte)0xff && data[1] == (byte)0xfe) {
+ // UTF-16, little-endian
+ defaultCharset = charset = UTF_16LE;
+ offset += 2;
+ }
+ }
+ int length = data.length - offset;
+
+ // Guess encoding by searching for an encoding= entry in the first line.
+ // The prologue, and the encoding names, will always be in ASCII - which means
+ // we don't need to worry about strange character encodings for the prologue characters.
+ // However, one wrinkle is that the whole file may be encoded in something like UTF-16
+ // where there are two bytes per character, so we can't just look for
+ // ['e','n','c','o','d','i','n','g'] etc in the byte array since there could be
+ // multiple bytes for each character. However, since again the prologue is in ASCII,
+ // we can just drop the zeroes.
+ boolean seenOddZero = false;
+ boolean seenEvenZero = false;
+ int prologueStart = -1;
+ for (int lineEnd = offset; lineEnd < data.length; lineEnd++) {
+ if (data[lineEnd] == 0) {
+ if ((lineEnd - offset) % 1 == 0) {
+ seenEvenZero = true;
+ } else {
+ seenOddZero = true;
+ }
+ } else if (data[lineEnd] == '\n') {
+ break;
+ } else if (data[lineEnd] == '<') {
+ prologueStart = lineEnd;
+ } else if (data[lineEnd] == '>') {
+ // End of prologue. Quick check to see if this is a utf-8 file since that's
+ // common
+ for (int i = lineEnd - 4; i >= 0; i--) {
+ if ((data[i] == 'u' || data[i] == 'U')
+ && (data[i + 1] == 't' || data[i + 1] == 'T')
+ && (data[i + 2] == 'f' || data[i + 2] == 'F')
+ && (data[i + 3] == '-' || data[i + 3] == '_')
+ && (data[i + 4] == '8')
+ ) {
+ charset = UTF_8;
+ break;
+ }
+ }
+
+ if (charset == null) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = prologueStart; i <= lineEnd; i++) {
+ if (data[i] != 0) {
+ sb.append((char) data[i]);
+ }
+ }
+ String prologue = sb.toString();
+ int encodingIndex = prologue.indexOf("encoding"); //$NON-NLS-1$
+ if (encodingIndex != -1) {
+ Matcher matcher = ENCODING_PATTERN.matcher(prologue);
+ if (matcher.find(encodingIndex)) {
+ charset = matcher.group(1);
+ }
+ }
+ }
+
+ break;
+ }
+ }
+
+ // No prologue on the first line, and no byte order mark: Assume UTF-8/16
+ if (charset == null) {
+ charset = seenOddZero ? UTF_16 : seenEvenZero ? UTF_16LE : UTF_8;
+ }
+
+ String xml = null;
+ try {
+ xml = new String(data, offset, length, charset);
+ } catch (UnsupportedEncodingException e) {
+ try {
+ if (charset != defaultCharset) {
+ xml = new String(data, offset, length, defaultCharset);
+ }
+ } catch (UnsupportedEncodingException u) {
+ // Just use the default encoding below
+ }
+ }
+ if (xml == null) {
+ xml = new String(data, offset, length);
+ }
+ return xml;
+ }
+
+ /**
+ * Returns the position for the given node. This is the start position. The
+ * end position can be obtained via {@link Position#getEnd()}.
+ *
+ * @param node the node to look up position for
+ * @return the position, or null if the node type is not supported for
+ * position info
+ */
+ @Nullable
+ public Position getPosition(@NonNull Node node) {
// Look up the position information stored while parsing for the given node.
// Note however that we only store position information for elements (because
// there is no SAX callback for individual attributes).
@@ -113,10 +297,10 @@ public class PositionXmlParser implements IDomParser {
// and if found uses that as the exact node offsets instead.
if (node instanceof Attr) {
Attr attr = (Attr) node;
- OffsetPosition pos = (OffsetPosition) attr.getOwnerElement().getUserData(POS_KEY);
+ Position pos = (Position) attr.getOwnerElement().getUserData(POS_KEY);
if (pos != null) {
int startOffset = pos.getOffset();
- int endOffset = pos.next.getOffset();
+ int endOffset = pos.getEnd().getOffset();
// Find attribute in the text
String contents = (String) node.getOwnerDocument().getUserData(CONTENT_KEY);
@@ -145,9 +329,9 @@ public class PositionXmlParser implements IDomParser {
}
}
- OffsetPosition attributePosition = new OffsetPosition(line, column, index);
+ Position attributePosition = createPosition(line, column, index);
// Also set end range for retrieval in getLocation
- attributePosition.next = new OffsetPosition(line, column, matcher.end());
+ attributePosition.setEnd(createPosition(line, column, matcher.end()));
return attributePosition;
} else {
// No regexp match either: just fall back to element position
@@ -156,17 +340,17 @@ public class PositionXmlParser implements IDomParser {
}
} else if (node instanceof Text) {
// Position of parent element, if any
- OffsetPosition pos = null;
+ Position pos = null;
if (node.getPreviousSibling() != null) {
- pos = (OffsetPosition) node.getPreviousSibling().getUserData(POS_KEY);
+ pos = (Position) node.getPreviousSibling().getUserData(POS_KEY);
}
if (pos == null) {
- pos = (OffsetPosition) node.getParentNode().getUserData(POS_KEY);
+ pos = (Position) node.getParentNode().getUserData(POS_KEY);
}
if (pos != null) {
// Attempt to point forward to the actual text node
int startOffset = pos.getOffset();
- int endOffset = pos.next.getOffset();
+ int endOffset = pos.getEnd().getOffset();
int line = pos.getLine();
int column = pos.getColumn();
@@ -212,11 +396,11 @@ public class PositionXmlParser implements IDomParser {
column = newColumn;
}
- OffsetPosition attributePosition = new OffsetPosition(line, column,
+ Position attributePosition = createPosition(line, column,
offset);
// Also set end range for retrieval in getLocation
- attributePosition.next = new OffsetPosition(line, column,
- offset + textLength);
+ attributePosition.setEnd(createPosition(line, column,
+ offset + textLength));
return attributePosition;
} else if (c == '"') {
inAttribute = !inAttribute;
@@ -231,22 +415,7 @@ public class PositionXmlParser implements IDomParser {
}
}
- return (OffsetPosition) node.getUserData(POS_KEY);
- }
-
- @Override
- public Location getLocation(XmlContext context, Node node) {
- OffsetPosition pos = (OffsetPosition) getPositions(node);
- if (pos != null) {
- return Location.create(context.file, pos, pos.next);
- }
-
- return null;
- }
-
- @Override
- public Handle createLocationHandle(XmlContext context, Node node) {
- return new LocationHandle(context.file, node);
+ return (Position) node.getUserData(POS_KEY);
}
/**
@@ -255,7 +424,7 @@ public class PositionXmlParser implements IDomParser {
* information is attached to the DOM nodes by setting user data with the
* {@link POS_KEY} key.
*/
- private static final class DomBuilder extends DefaultHandler {
+ private final class DomBuilder extends DefaultHandler {
private final String mXml;
private final Document mDocument;
private Locator mLocator;
@@ -306,7 +475,7 @@ public class PositionXmlParser implements IDomParser {
}
}
- OffsetPosition pos = getCurrentPosition();
+ Position pos = getCurrentPosition();
// The starting position reported to us by SAX is really the END of the
// open tag in an element, when all the attributes have been processed.
@@ -339,7 +508,7 @@ public class PositionXmlParser implements IDomParser {
}
}
- pos = new OffsetPosition(line, column, offset);
+ pos = createPosition(line, column, offset);
break;
}
}
@@ -353,9 +522,9 @@ public class PositionXmlParser implements IDomParser {
flushText();
Element element = mStack.remove(mStack.size() - 1);
- OffsetPosition pos = (OffsetPosition) element.getUserData(POS_KEY);
+ Position pos = (Position) element.getUserData(POS_KEY);
assert pos != null;
- pos.next = getCurrentPosition();
+ pos.setEnd(getCurrentPosition());
if (mStack.isEmpty()) {
mDocument.appendChild(element);
@@ -372,7 +541,7 @@ public class PositionXmlParser implements IDomParser {
* number and column position of the XML parser, counting characters as
* it goes along.
*/
- private OffsetPosition getCurrentPosition() {
+ private Position getCurrentPosition() {
int line = mLocator.getLineNumber() - 1;
int column = mLocator.getColumnNumber() - 1;
@@ -397,7 +566,7 @@ public class PositionXmlParser implements IDomParser {
mCurrentOffset += column - mCurrentColumn;
mCurrentColumn = column;
- return new OffsetPosition(mCurrentLine, mCurrentColumn, mCurrentOffset);
+ return createPosition(mCurrentLine, mCurrentColumn, mCurrentOffset);
}
@Override
@@ -415,24 +584,55 @@ public class PositionXmlParser implements IDomParser {
}
}
- private static class OffsetPosition extends Position {
- /** The line number (0-based where the first line is line 0) */
- private final int mLine;
+ /**
+ * Creates a position while constructing the DOM document. This method
+ * allows a subclass to create a custom implementation of the position
+ * class.
+ *
+ * @param line the line number for the position
+ * @param column the column number for the position
+ * @param offset the character offset
+ * @return a new position
+ */
+ @NonNull
+ protected Position createPosition(int line, int column, int offset) {
+ return new DefaultPosition(line, column, offset);
+ }
+ protected interface Position {
/**
- * The column number (where the first character on the line is 0), or -1 if
- * unknown
+ * Linked position: for a begin position this will point to the
+ * corresponding end position. For an end position this will be null.
+ *
+ * @return the end position, or null
*/
- private final int mColumn;
-
- /** The character offset */
- private final int mOffset;
+ @Nullable
+ public Position getEnd();
/**
- * Linked position: for a begin offset this will point to the end
- * offset, and for an end offset this will be null
+ * Linked position: for a begin position this will point to the
+ * corresponding end position. For an end position this will be null.
+ *
+ * @param end the end position
*/
- public OffsetPosition next;
+ public void setEnd(@NonNull Position end);
+
+ /** @return the line number, 0-based */
+ public int getLine();
+
+ /** @return the offset number, 0-based */
+ public int getOffset();
+
+ /** @return the column number, 0-based, and -1 if the column number if not known */
+ public int getColumn();
+ }
+
+ protected static class DefaultPosition implements Position {
+ /** The line number (0-based where the first line is line 0) */
+ private final int mLine;
+ private final int mColumn;
+ private final int mOffset;
+ private Position mEnd;
/**
* Creates a new {@link Position}
@@ -441,7 +641,7 @@ public class PositionXmlParser implements IDomParser {
* @param column the 0-based column number, or -1 if unknown
* @param offset the offset, or -1 if unknown
*/
- public OffsetPosition(int line, int column, int offset) {
+ public DefaultPosition(int line, int column, int offset) {
this.mLine = line;
this.mColumn = column;
this.mOffset = offset;
@@ -461,30 +661,15 @@ public class PositionXmlParser implements IDomParser {
public int getColumn() {
return mColumn;
}
- }
-
- @Override
- public void dispose(XmlContext context, Document document) {
- }
-
- /* Handle for creating DOM positions cheaply and returning full fledged locations later */
- private class LocationHandle implements Handle {
- private File mFile;
- private Node mNode;
- public LocationHandle(File file, Node node) {
- mFile = file;
- mNode = node;
+ @Override
+ public Position getEnd() {
+ return mEnd;
}
@Override
- public Location resolve() {
- OffsetPosition pos = (OffsetPosition) getPositions(mNode);
- if (pos != null) {
- return Location.create(mFile, pos, pos.next);
- }
-
- return null;
+ public void setEnd(Position end) {
+ mEnd = end;
}
}
}
diff --git a/common/tests/.classpath b/common/tests/.classpath
index b793adc..15b6472 100644
--- a/common/tests/.classpath
+++ b/common/tests/.classpath
@@ -4,5 +4,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
<classpathentry combineaccessrules="false" kind="src" path="/common"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-10.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src.zip"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/common/tests/src/com/android/util/PositionXmlParserTest.java b/common/tests/src/com/android/util/PositionXmlParserTest.java
new file mode 100644
index 0000000..9f87252
--- /dev/null
+++ b/common/tests/src/com/android/util/PositionXmlParserTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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.util;
+
+import com.android.util.PositionXmlParser.Position;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("javadoc")
+public class PositionXmlParserTest extends TestCase {
+ public void test() throws Exception {
+ String xml =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
+ " android:layout_width=\"match_parent\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:orientation=\"vertical\" >\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button1\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:text=\"Button\" />\n" +
+ "\n" +
+ " <Button\n" +
+ " android:id=\"@+id/button2\"\n" +
+ " android:layout_width=\"wrap_content\"\n" +
+ " android:layout_height=\"wrap_content\"\n" +
+ " android:text=\"Button\" />\n" +
+ "\n" +
+ "</LinearLayout>\n";
+ PositionXmlParser parser = new PositionXmlParser();
+ File file = File.createTempFile("parsertest", ".xml");
+ Writer fw = new BufferedWriter(new FileWriter(file));
+ fw.write(xml);
+ fw.close();
+ Document document = parser.parse(new FileInputStream(file));
+ assertNotNull(document);
+
+ // Basic parsing heart beat tests
+ Element linearLayout = (Element) document.getElementsByTagName("LinearLayout").item(0);
+ assertNotNull(linearLayout);
+ NodeList buttons = document.getElementsByTagName("Button");
+ assertEquals(2, buttons.getLength());
+ final String ANDROID_URI = "http://schemas.android.com/apk/res/android";
+ assertEquals("wrap_content",
+ linearLayout.getAttributeNS(ANDROID_URI, "layout_height"));
+
+ // Check attribute positions
+ Attr attr = linearLayout.getAttributeNodeNS(ANDROID_URI, "layout_width");
+ assertNotNull(attr);
+ Position start = parser.getPosition(attr);
+ Position end = start.getEnd();
+ assertEquals(2, start.getLine());
+ assertEquals(xml.indexOf("android:layout_width"), start.getOffset());
+ assertEquals(2, end.getLine());
+ String target = "android:layout_width=\"match_parent\"";
+ assertEquals(xml.indexOf(target) + target.length(), end.getOffset());
+
+ // Check element positions
+ Element button = (Element) buttons.item(0);
+ start = parser.getPosition(button);
+ end = start.getEnd();
+ assertNull(end.getEnd());
+ assertEquals(6, start.getLine());
+ assertEquals(xml.indexOf("<Button"), start.getOffset());
+ assertEquals(xml.indexOf("/>") + 2, end.getOffset());
+ assertEquals(10, end.getLine());
+ int button1End = end.getOffset();
+
+ Element button2 = (Element) buttons.item(1);
+ start = parser.getPosition(button2);
+ end = start.getEnd();
+ assertEquals(12, start.getLine());
+ assertEquals(xml.indexOf("<Button", button1End), start.getOffset());
+ assertEquals(xml.indexOf("/>", start.getOffset()) + 2, end.getOffset());
+ assertEquals(16, end.getLine());
+
+ file.delete();
+ }
+
+ public void testLineEndings() throws Exception {
+ // Test for http://code.google.com/p/android/issues/detail?id=22925
+ String xml =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
+ "<LinearLayout>\r\n" +
+ "\r" +
+ "<LinearLayout></LinearLayout>\r\n" +
+ "</LinearLayout>\r\n";
+ PositionXmlParser parser = new PositionXmlParser();
+ File file = File.createTempFile("parsertest2", ".xml");
+ Writer fw = new BufferedWriter(new FileWriter(file));
+ fw.write(xml);
+ fw.close();
+ Document document = parser.parse(new FileInputStream(file));
+ assertNotNull(document);
+
+ file.delete();
+ }
+
+ private static void checkEncoding(String encoding, boolean writeBom, boolean writeEncoding)
+ throws Exception {
+ String value = "¾¿Œ";
+ StringBuilder sb = new StringBuilder();
+
+ sb.append("<?xml version=\"1.0\"");
+ if (writeEncoding) {
+ sb.append(" encoding=\"");
+ sb.append(encoding);
+ sb.append("\"");
+ }
+ sb.append("?>\n" +
+ "<!-- This is a \n" +
+ " multiline comment\n" +
+ "-->\n" +
+ "<foo ");
+ int startAttrOffset = sb.length();
+ sb.append("attr=\"");
+ sb.append(value);
+ sb.append("\"");
+ sb.append(">\n" +
+ "\n" +
+ "<bar></bar>\n" +
+ "</foo>\n");
+ PositionXmlParser parser = new PositionXmlParser();
+ File file = File.createTempFile("parsertest" + encoding + writeBom + writeEncoding,
+ ".xml");
+ BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
+ OutputStreamWriter writer = new OutputStreamWriter(stream, encoding);
+
+ if (writeBom) {
+ String normalized = encoding.toLowerCase().replace("-", "_");
+ if (normalized.equals("utf_8")) {
+ stream.write(0xef);
+ stream.write(0xbb);
+ stream.write(0xbf);
+ } else if (normalized.equals("utf_16")) {
+ stream.write(0xfe);
+ stream.write(0xff);
+ } else if (normalized.equals("utf_16le")) {
+ stream.write(0xff);
+ stream.write(0xfe);
+ } else if (normalized.equals("utf_32")) {
+ stream.write(0x0);
+ stream.write(0x0);
+ stream.write(0xfe);
+ stream.write(0xff);
+ } else if (normalized.equals("utf_32le")) {
+ stream.write(0xff);
+ stream.write(0xfe);
+ stream.write(0x0);
+ stream.write(0x0);
+ } else {
+ fail("Can't write BOM for encoding " + encoding);
+ }
+ }
+
+ writer.write(sb.toString());
+ writer.close();
+
+ Document document = parser.parse(new FileInputStream(file));
+ assertNotNull(document);
+ Element root = document.getDocumentElement();
+ assertEquals(file.getPath(), value, root.getAttribute("attr"));
+ assertEquals(4, parser.getPosition(root).getLine());
+
+ Attr attribute = root.getAttributeNode("attr");
+ assertNotNull(attribute);
+ Position position = parser.getPosition(attribute);
+ assertNotNull(position);
+ assertEquals(4, position.getLine());
+ assertEquals(startAttrOffset, position.getOffset());
+
+ file.delete();
+ }
+
+ public void testEncoding() throws Exception {
+ checkEncoding("utf-8", false /*bom*/, true /*encoding*/);
+ checkEncoding("UTF-8", false /*bom*/, true /*encoding*/);
+ checkEncoding("UTF_16", false /*bom*/, true /*encoding*/);
+ checkEncoding("UTF-16", false /*bom*/, true /*encoding*/);
+ checkEncoding("UTF_16LE", false /*bom*/, true /*encoding*/);
+ checkEncoding("UTF_32", false /*bom*/, true /*encoding*/);
+ checkEncoding("UTF_32LE", false /*bom*/, true /*encoding*/);
+ checkEncoding("windows-1252", false /*bom*/, true /*encoding*/);
+ checkEncoding("MacRoman", false /*bom*/, true /*encoding*/);
+ checkEncoding("ISO-8859-1", false /*bom*/, true /*encoding*/);
+ checkEncoding("iso-8859-1", false /*bom*/, true /*encoding*/);
+
+ // Try BOM's (with no encoding specified)
+ checkEncoding("utf-8", true /*bom*/, false /*encoding*/);
+ checkEncoding("UTF-8", true /*bom*/, false /*encoding*/);
+ checkEncoding("UTF_16", true /*bom*/, false /*encoding*/);
+ checkEncoding("UTF-16", true /*bom*/, false /*encoding*/);
+ checkEncoding("UTF_16LE", true /*bom*/, false /*encoding*/);
+ checkEncoding("UTF_32", true /*bom*/, false /*encoding*/);
+ checkEncoding("UTF_32LE", true /*bom*/, false /*encoding*/);
+
+ // Try default encodings (only defined for utf-8 and utf-16)
+ checkEncoding("utf-8", false /*bom*/, false /*encoding*/);
+ checkEncoding("UTF-8", false /*bom*/, false /*encoding*/);
+ checkEncoding("UTF_16", false /*bom*/, false /*encoding*/);
+ checkEncoding("UTF-16", false /*bom*/, false /*encoding*/);
+ checkEncoding("UTF_16LE", false /*bom*/, false /*encoding*/);
+
+ // Try BOM's (with explicit encoding specified)
+ checkEncoding("utf-8", true /*bom*/, true /*encoding*/);
+ checkEncoding("UTF-8", true /*bom*/, true /*encoding*/);
+ checkEncoding("UTF_16", true /*bom*/, true /*encoding*/);
+ checkEncoding("UTF-16", true /*bom*/, true /*encoding*/);
+ checkEncoding("UTF_16LE", true /*bom*/, true /*encoding*/);
+ checkEncoding("UTF_32", true /*bom*/, true /*encoding*/);
+ checkEncoding("UTF_32LE", true /*bom*/, true /*encoding*/);
+ }
+}
diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt
index c7e5331..601d9eb 100644
--- a/eclipse/dictionary.txt
+++ b/eclipse/dictionary.txt
@@ -85,6 +85,7 @@ drawables
dropdown
ed
editable
+endian
endpoint
enum
enums
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java
index d105867..ba5b63e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/EclipseLintClient.java
@@ -38,6 +38,8 @@ import com.android.tools.lint.detector.api.Project;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.XmlContext;
import com.android.util.Pair;
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
@@ -64,9 +66,7 @@ import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
import java.io.IOException;
/**
@@ -502,33 +502,12 @@ public class EclipseLintClient extends LintClient implements IDomParser {
return readPlainFile(f);
}
- private String readPlainFile(File f) {
- // TODO: Connect to document and read live contents
- BufferedReader reader = null;
+ private String readPlainFile(File file) {
try {
- reader = new BufferedReader(new FileReader(f));
- StringBuilder sb = new StringBuilder((int) f.length());
- while (true) {
- int c = reader.read();
- if (c == -1) {
- return sb.toString();
- } else {
- sb.append((char)c);
- }
- }
+ return Files.toString(file, Charsets.UTF_8);
} catch (IOException e) {
- // pass -- ignore files we can't read
- } finally {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException e) {
- log(e, null);
- }
+ return ""; //$NON-NLS-1$
}
-
- return ""; //$NON-NLS-1$
}
@Override
diff --git a/lint/cli/.classpath b/lint/cli/.classpath
index 267ebe8..362d028 100644
--- a/lint/cli/.classpath
+++ b/lint/cli/.classpath
@@ -2,6 +2,7 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/common"/>
<classpathentry combineaccessrules="false" kind="src" path="/lint-api"/>
<classpathentry combineaccessrules="false" kind="src" path="/lint-checks"/>
<classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/asm-tools/src.zip"/>
diff --git a/lint/cli/Android.mk b/lint/cli/Android.mk
index 3aec3e2..a78a9fe 100644
--- a/lint/cli/Android.mk
+++ b/lint/cli/Android.mk
@@ -10,6 +10,7 @@ LOCAL_JAR_MANIFEST := etc/manifest.txt
# If the dependency list is changed, etc/manifest.txt
LOCAL_JAVA_LIBRARIES := \
+ common \
lint_api \
lint_checks
LOCAL_STATIC_JAVA_LIBRARIES := \
diff --git a/lint/cli/etc/manifest.txt b/lint/cli/etc/manifest.txt
index a60c7ca..242c7f4 100644
--- a/lint/cli/etc/manifest.txt
+++ b/lint/cli/etc/manifest.txt
@@ -1,2 +1,2 @@
Main-Class: com.android.tools.lint.Main
-Class-Path: lint_api.jar lint_checks.jar asm-4.0.jar asm-tree-4.0.jar guava-10.0.1.jar
+Class-Path: common.jar lint_api.jar lint_checks.jar asm-4.0.jar asm-tree-4.0.jar guava-10.0.1.jar
diff --git a/lint/cli/src/com/android/tools/lint/LintCliXmlParser.java b/lint/cli/src/com/android/tools/lint/LintCliXmlParser.java
new file mode 100644
index 0000000..1c7b13a
--- /dev/null
+++ b/lint/cli/src/com/android/tools/lint/LintCliXmlParser.java
@@ -0,0 +1,174 @@
+/*
+ * 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.client.api.IDomParser;
+import com.android.tools.lint.client.api.IssueRegistry;
+import com.android.tools.lint.detector.api.Location;
+import com.android.tools.lint.detector.api.Location.Handle;
+import com.android.tools.lint.detector.api.XmlContext;
+import com.android.util.PositionXmlParser;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * A customization of the {@link PositionXmlParser} which creates position
+ * objects that directly extend the lint
+ * {@link com.android.tools.lint.detector.api.Position} class.
+ * <p>
+ * It also catches and reports parser errors as lint errors.
+ */
+public class LintCliXmlParser extends PositionXmlParser implements IDomParser {
+ @Override
+ public Document parseXml(XmlContext context) {
+ try {
+ // Do we need to provide an input stream for encoding?
+ String xml = context.getContents();
+ if (xml != null) {
+ return super.parse(xml);
+ }
+ } catch (UnsupportedEncodingException e) {
+ context.report(
+ // Must provide an issue since API guarantees that the issue parameter
+ // is valid
+ IssueRegistry.PARSER_ERROR, Location.create(context.file),
+ e.getCause() != null ? e.getCause().getLocalizedMessage() :
+ e.getLocalizedMessage(),
+ null);
+ } catch (SAXException e) {
+ context.report(
+ // Must provide an issue since API guarantees that the issue parameter
+ // is valid
+ IssueRegistry.PARSER_ERROR, Location.create(context.file),
+ e.getCause() != null ? e.getCause().getLocalizedMessage() :
+ e.getLocalizedMessage(),
+ null);
+ } catch (Throwable t) {
+ context.log(t, null);
+ }
+ return null;
+ }
+
+ @Override
+ public Location getLocation(XmlContext context, Node node) {
+ OffsetPosition pos = (OffsetPosition) getPosition(node);
+ if (pos != null) {
+ return Location.create(context.file, pos, (OffsetPosition) pos.getEnd());
+ }
+
+ return null;
+ }
+
+ @Override
+ public Handle createLocationHandle(XmlContext context, Node node) {
+ return new LocationHandle(context.file, node);
+ }
+
+ @Override
+ protected OffsetPosition createPosition(int line, int column, int offset) {
+ return new OffsetPosition(line, column, offset);
+ }
+
+ private static class OffsetPosition extends com.android.tools.lint.detector.api.Position
+ implements PositionXmlParser.Position {
+ /** The line number (0-based where the first line is line 0) */
+ private final int mLine;
+
+ /**
+ * The column number (where the first character on the line is 0), or -1 if
+ * unknown
+ */
+ private final int mColumn;
+
+ /** The character offset */
+ private final int mOffset;
+
+ /**
+ * Linked position: for a begin offset this will point to the end
+ * offset, and for an end offset this will be null
+ */
+ private com.android.util.PositionXmlParser.Position mEnd;
+
+ /**
+ * Creates a new {@link OffsetPosition}
+ *
+ * @param line the 0-based line number, or -1 if unknown
+ * @param column the 0-based column number, or -1 if unknown
+ * @param offset the offset, or -1 if unknown
+ */
+ public OffsetPosition(int line, int column, int offset) {
+ this.mLine = line;
+ this.mColumn = column;
+ this.mOffset = offset;
+ }
+
+ @Override
+ public int getLine() {
+ return mLine;
+ }
+
+ @Override
+ public int getOffset() {
+ return mOffset;
+ }
+
+ @Override
+ public int getColumn() {
+ return mColumn;
+ }
+
+ @Override
+ public com.android.util.PositionXmlParser.Position getEnd() {
+ return mEnd;
+ }
+
+ @Override
+ public void setEnd(com.android.util.PositionXmlParser.Position end) {
+ mEnd = end;
+ }
+ }
+
+ @Override
+ public void dispose(XmlContext context, Document document) {
+ }
+
+ /* Handle for creating DOM positions cheaply and returning full fledged locations later */
+ private class LocationHandle implements Handle {
+ private File mFile;
+ private Node mNode;
+
+ public LocationHandle(File file, Node node) {
+ mFile = file;
+ mNode = node;
+ }
+
+ @Override
+ public Location resolve() {
+ OffsetPosition pos = (OffsetPosition) getPosition(mNode);
+ if (pos != null) {
+ return Location.create(mFile, pos, (OffsetPosition) pos.getEnd());
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/lint/cli/src/com/android/tools/lint/Main.java b/lint/cli/src/com/android/tools/lint/Main.java
index 489ac81..e37f9c4 100644
--- a/lint/cli/src/com/android/tools/lint/Main.java
+++ b/lint/cli/src/com/android/tools/lint/Main.java
@@ -34,10 +34,11 @@ 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.android.util.PositionXmlParser;
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
@@ -661,7 +662,7 @@ public class Main extends LintClient {
@Override
public IDomParser getDomParser() {
- return new PositionXmlParser();
+ return new LintCliXmlParser();
}
@Override
@@ -790,31 +791,17 @@ public class Main extends LintClient {
@Override
public String readFile(File file) {
- BufferedReader reader = null;
try {
- reader = new BufferedReader(new FileReader(file));
- StringBuilder sb = new StringBuilder((int) file.length());
- while (true) {
- int c = reader.read();
- if (c == -1) {
- return sb.toString();
- } else {
- sb.append((char)c);
- }
+ // For XML files, apply special logic to pick up encoding information within the file
+ if (endsWith(file.getName(), DOT_XML)) {
+ byte[] data = Files.toByteArray(file);
+ return PositionXmlParser.getXmlString(data);
}
+
+ return Files.toString(file, Charsets.UTF_8);
} catch (IOException e) {
- // pass -- ignore files we can't read
- } finally {
- try {
- if (reader != null) {
- reader.close();
- }
- } catch (IOException e) {
- log(e, null);
- }
+ return ""; //$NON-NLS-1$
}
-
- return ""; //$NON-NLS-1$
}
/**
diff --git a/lint/libs/lint_checks/tests/.classpath b/lint/libs/lint_checks/tests/.classpath
index 73067c0..7e1e017 100644
--- a/lint/libs/lint_checks/tests/.classpath
+++ b/lint/libs/lint_checks/tests/.classpath
@@ -7,5 +7,7 @@
<classpathentry combineaccessrules="false" kind="src" path="/lint-api"/>
<classpathentry combineaccessrules="false" kind="src" path="/lint-checks"/>
<classpathentry combineaccessrules="false" kind="src" path="/lint-cli"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/common"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/guava-tools/guava-10.0.1.jar" sourcepath="/ANDROID_SRC/prebuilts/tools/common/guava-tools/src.zip"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/lint/libs/lint_checks/tests/Android.mk b/lint/libs/lint_checks/tests/Android.mk
index fda6d7f..a0d9bd0 100644
--- a/lint/libs/lint_checks/tests/Android.mk
+++ b/lint/libs/lint_checks/tests/Android.mk
@@ -22,7 +22,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE := lint_checks-tests
LOCAL_MODULE_TAGS := optional
-LOCAL_JAVA_LIBRARIES := lint_api lint_checks lint junit easymock
+LOCAL_JAVA_LIBRARIES := common lint_api lint_checks lint junit easymock
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/PositionXmlParserTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/LintCliXmlParserTest.java
index 1c78c44..212b01e 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/PositionXmlParserTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/LintCliXmlParserTest.java
@@ -16,6 +16,9 @@
package com.android.tools.lint;
+import com.android.tools.lint.client.api.LintClient;
+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.Location.Handle;
import com.android.tools.lint.detector.api.Position;
@@ -37,7 +40,7 @@ import java.util.EnumSet;
import junit.framework.TestCase;
@SuppressWarnings("javadoc")
-public class PositionXmlParserTest extends TestCase {
+public class LintCliXmlParserTest extends TestCase {
public void test() throws Exception {
String xml =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
@@ -59,13 +62,15 @@ public class PositionXmlParserTest extends TestCase {
" android:text=\"Button\" />\n" +
"\n" +
"</LinearLayout>\n";
- PositionXmlParser parser = new PositionXmlParser();
+ LintCliXmlParser parser = new LintCliXmlParser();
File file = File.createTempFile("parsertest", ".xml");
Writer fw = new BufferedWriter(new FileWriter(file));
fw.write(xml);
fw.close();
- Project project = new Project(null, file.getParentFile(), file.getParentFile());
- XmlContext context = new XmlContext(new Main(), project, file,
+ LintClient client = new TestClient();
+ Project project = new Project(client, file.getParentFile(), file.getParentFile());
+ project.setConfiguration(client.getConfiguration(project));
+ XmlContext context = new XmlContext(client, project, file,
EnumSet.of(Scope.RESOURCE_FILE));
Document document = parser.parseXml(context);
assertNotNull(document);
@@ -132,17 +137,27 @@ public class PositionXmlParserTest extends TestCase {
"\r" +
"<LinearLayout></LinearLayout>\r\n" +
"</LinearLayout>\r\n";
- PositionXmlParser parser = new PositionXmlParser();
+ LintCliXmlParser parser = new LintCliXmlParser();
File file = File.createTempFile("parsertest2", ".xml");
Writer fw = new BufferedWriter(new FileWriter(file));
fw.write(xml);
fw.close();
- Project project = new Project(null, file.getParentFile(), file.getParentFile());
- XmlContext context = new XmlContext(new Main(), project, file,
+ LintClient client = new TestClient();
+ Project project = new Project(client, file.getParentFile(), file.getParentFile());
+ project.setConfiguration(client.getConfiguration(project));
+ XmlContext context = new XmlContext(client, project, file,
EnumSet.of(Scope.RESOURCE_FILE));
Document document = parser.parseXml(context);
assertNotNull(document);
file.delete();
}
+
+ private static class TestClient extends Main {
+ @Override
+ public void report(Context context, Issue issue, Location location, String message,
+ Object data) {
+ System.out.println(location + ":" + message);
+ }
+ }
}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java
index 58f1045..dd18ffa 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java
@@ -16,12 +16,12 @@
package com.android.tools.lint.checks;
-import com.android.tools.lint.PositionXmlParser;
+import com.android.tools.lint.LintCliXmlParser;
+import com.android.tools.lint.Main;
import com.android.tools.lint.client.api.Configuration;
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.detector.api.Context;
import com.android.tools.lint.detector.api.Detector;
import com.android.tools.lint.detector.api.Issue;
@@ -33,7 +33,6 @@ import com.android.tools.lint.detector.api.Severity;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
@@ -253,7 +252,7 @@ abstract class AbstractCheckTest extends TestCase {
return false;
}
- private class TestLintClient extends LintClient {
+ private class TestLintClient extends Main {
private List<String> mErrors = new ArrayList<String>();
public List<String> getErrors() {
@@ -344,17 +343,7 @@ abstract class AbstractCheckTest extends TestCase {
@Override
public IDomParser getDomParser() {
- return new PositionXmlParser();
- }
-
- @Override
- public String readFile(File file) {
- try {
- return AbstractCheckTest.readFile(new FileReader(file));
- } catch (Throwable e) {
- fail(e.toString());
- }
- return null;
+ return new LintCliXmlParser();
}
@Override