diff options
5 files changed, 109 insertions, 53 deletions
diff --git a/common/src/com/android/util/PositionXmlParser.java b/common/src/com/android/util/PositionXmlParser.java index a72ad95..22ea4c1 100644 --- a/common/src/com/android/util/PositionXmlParser.java +++ b/common/src/com/android/util/PositionXmlParser.java @@ -458,63 +458,67 @@ public class PositionXmlParser { @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - flushText(); - Element element = mDocument.createElement(qName); - for (int i = 0; i < attributes.getLength(); i++) { - if (attributes.getURI(i) != null && attributes.getURI(i).length() > 0) { - Attr attr = mDocument.createAttributeNS(attributes.getURI(i), - attributes.getQName(i)); - attr.setValue(attributes.getValue(i)); - element.setAttributeNodeNS(attr); - assert attr.getOwnerElement() == element; - } else { - Attr attr = mDocument.createAttribute(attributes.getQName(i)); - attr.setValue(attributes.getValue(i)); - element.setAttributeNode(attr); - assert attr.getOwnerElement() == element; + try { + flushText(); + Element element = mDocument.createElement(qName); + for (int i = 0; i < attributes.getLength(); i++) { + if (attributes.getURI(i) != null && attributes.getURI(i).length() > 0) { + Attr attr = mDocument.createAttributeNS(attributes.getURI(i), + attributes.getQName(i)); + attr.setValue(attributes.getValue(i)); + element.setAttributeNodeNS(attr); + assert attr.getOwnerElement() == element; + } else { + Attr attr = mDocument.createAttribute(attributes.getQName(i)); + attr.setValue(attributes.getValue(i)); + element.setAttributeNode(attr); + assert attr.getOwnerElement() == element; + } } - } - 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. - // We have to scan backwards to find the real beginning. We'll do that - // by scanning backwards. - // -1: Make sure that when we have <foo></foo> we don't consider </foo> - // the beginning since pos.offset will typically point to the first character - // AFTER the element open tag, which could be a closing tag or a child open - // tag - - for (int offset = pos.getOffset() - 1; offset >= 0; offset--) { - char c = mXml.charAt(offset); - // < cannot appear in attribute values or anywhere else within - // an element open tag, so we know the first occurrence is the real - // element start - if (c == '<') { - // Adjust line position - int line = pos.getLine(); - for (int i = offset, n = pos.getOffset(); i < n; i++) { - if (mXml.charAt(i) == '\n') { - line--; + 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. + // We have to scan backwards to find the real beginning. We'll do that + // by scanning backwards. + // -1: Make sure that when we have <foo></foo> we don't consider </foo> + // the beginning since pos.offset will typically point to the first character + // AFTER the element open tag, which could be a closing tag or a child open + // tag + + for (int offset = pos.getOffset() - 1; offset >= 0; offset--) { + char c = mXml.charAt(offset); + // < cannot appear in attribute values or anywhere else within + // an element open tag, so we know the first occurrence is the real + // element start + if (c == '<') { + // Adjust line position + int line = pos.getLine(); + for (int i = offset, n = pos.getOffset(); i < n; i++) { + if (mXml.charAt(i) == '\n') { + line--; + } } - } - // Compute new column position - int column = 0; - for (int i = offset; i >= 0; i--, column++) { - if (mXml.charAt(i) == '\n') { - break; + // Compute new column position + int column = 0; + for (int i = offset; i >= 0; i--, column++) { + if (mXml.charAt(i) == '\n') { + break; + } } - } - pos = createPosition(line, column, offset); - break; + pos = createPosition(line, column, offset); + break; + } } - } - element.setUserData(POS_KEY, pos, null); - mStack.add(element); + element.setUserData(POS_KEY, pos, null); + mStack.add(element); + } catch (Exception t) { + throw new SAXException(t); + } } @Override @@ -547,9 +551,10 @@ public class PositionXmlParser { // Compute offset incrementally now that we have the new line and column // numbers - while (mCurrentLine < line) { + int xmlLength = mXml.length(); + while (mCurrentLine < line && mCurrentOffset < xmlLength) { char c = mXml.charAt(mCurrentOffset); - if (c == '\r' && mCurrentOffset < mXml.length() - 1) { + if (c == '\r' && mCurrentOffset < xmlLength - 1) { if (mXml.charAt(mCurrentOffset + 1) != '\n') { mCurrentLine++; mCurrentColumn = 0; @@ -564,6 +569,11 @@ public class PositionXmlParser { } mCurrentOffset += column - mCurrentColumn; + if (mCurrentOffset >= xmlLength) { + // The parser sometimes passes wrong column numbers at the + // end of the file: Ensure that the offset remains valid. + mCurrentOffset = xmlLength; + } mCurrentColumn = column; return createPosition(mCurrentLine, mCurrentColumn, mCurrentOffset); 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 59e29f4..0ad4be5 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 @@ -786,6 +786,11 @@ public class EclipseLintClient extends LintClient implements IDomParser { // Don't analyze files containing errors List<ParseProblem> problems = source.getProblems(); if (problems != null && problems.size() > 0) { + /* Silently ignore the errors. There are still some bugs in Lombok/Parboiled + * (triggered if you run lint on the AOSP framework directory for example), + * and having these show up as fatal errors when it's really a tool bug + * is bad. To make matters worse, the error messages aren't clear: + * http://code.google.com/p/projectlombok/issues/detail?id=313 for (ParseProblem problem : problems) { lombok.ast.Position position = problem.getPosition(); Location location = Location.create(context.file, @@ -797,6 +802,7 @@ public class EclipseLintClient extends LintClient implements IDomParser { null); } + */ return null; } diff --git a/lint/cli/src/com/android/tools/lint/LombokParser.java b/lint/cli/src/com/android/tools/lint/LombokParser.java index 6d77462..0282781 100644 --- a/lint/cli/src/com/android/tools/lint/LombokParser.java +++ b/lint/cli/src/com/android/tools/lint/LombokParser.java @@ -73,11 +73,17 @@ public class LombokParser implements IJavaParser { } return null; } catch (Throwable e) { + /* Silently ignore the errors. There are still some bugs in Lombok/Parboiled + * (triggered if you run lint on the AOSP framework directory for example), + * and having these show up as fatal errors when it's really a tool bug + * is bad. To make matters worse, the error messages aren't clear: + * http://code.google.com/p/projectlombok/issues/detail?id=313 context.report( IssueRegistry.PARSER_ERROR, Location.create(context.file), e.getCause() != null ? e.getCause().getLocalizedMessage() : e.getLocalizedMessage(), null); + */ return null; } diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ExtraTextDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ExtraTextDetector.java index cf5d2e6..a14c7d0 100644 --- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ExtraTextDetector.java +++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ExtraTextDetector.java @@ -18,7 +18,10 @@ package com.android.tools.lint.checks; import com.android.resources.ResourceFolderType; import com.android.tools.lint.detector.api.Category; +import com.android.tools.lint.detector.api.DefaultPosition; import com.android.tools.lint.detector.api.Issue; +import com.android.tools.lint.detector.api.Location; +import com.android.tools.lint.detector.api.Position; import com.android.tools.lint.detector.api.ResourceXmlDetector; import com.android.tools.lint.detector.api.Scope; import com.android.tools.lint.detector.api.Severity; @@ -88,7 +91,38 @@ public class ExtraTextDetector extends ResourceXmlDetector { if (snippet.length() > maxLength) { snippet = snippet.substring(0, maxLength) + "..."; } - context.report(ISSUE, context.getLocation(node), + Location location = context.getLocation(node); + if (i > 0) { + // Adjust the error position to point to the beginning of + // the text rather than the beginning of the text node + // (which is often the newline at the end of the previous + // line and the indentation) + Position start = location.getStart(); + if (start != null) { + int line = start.getLine(); + int column = start.getColumn(); + int offset = start.getOffset(); + + for (int j = 0; j < i; j++) { + offset++; + + if (text.charAt(j) == '\n') { + if (line != -1) { + line++; + } + if (column != -1) { + column = 0; + } + } else if (column != -1) { + column++; + } + } + + start = new DefaultPosition(line, column, offset); + location = Location.create(context.file, start, location.getEnd()); + } + } + context.report(ISSUE, location, String.format("Unexpected text found in layout file: \"%1$s\"", snippet), null); mFoundText = true; diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ExtraTextDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ExtraTextDetectorTest.java index 35c38ac..5016828 100644 --- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ExtraTextDetectorTest.java +++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ExtraTextDetectorTest.java @@ -27,7 +27,7 @@ public class ExtraTextDetectorTest extends AbstractCheckTest { public void testBroken() throws Exception { assertEquals( - "broken.xml:5: Warning: Unexpected text found in layout file: \"ImageButton " + + "broken.xml:6: Warning: Unexpected text found in layout file: \"ImageButton " + "android:id=\"@+id/android_logo2\" android:layout_width=\"wrap_content\"" + " android:layout_heigh...\"", lintProject("res/layout/broken.xml")); |