com.android.tools.lint.detector.api.XmlContext Java Examples

The following examples show how to use com.android.tools.lint.detector.api.XmlContext. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: RegistrationDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    String fqcn = getFqcn(context, element);
    String tag = element.getTagName();
    String frameworkClass = tagToClass(tag);
    if (frameworkClass != null) {
        String signature = ClassContext.getInternalName(fqcn);
        if (mManifestRegistrations == null) {
            mManifestRegistrations = ArrayListMultimap.create(4, 8);
        }
        mManifestRegistrations.put(frameworkClass, signature);
        if (signature.indexOf('$') != -1) {
            // The internal name contains a $ which means it's an inner class.
            // The conversion from fqcn to internal name is a bit ambiguous:
            // "a.b.C.D" usually means "inner class D in class C in package a.b".
            // However, it can (see issue 31592) also mean class D in package "a.b.C".
            // Place *both* of these possibilities in the registered map, since this
            // is only used to check that an activity is registered, not the other way
            // (so it's okay to have entries there that do not correspond to real classes).
            signature = signature.replace('$', '/');
            mManifestRegistrations.put(frameworkClass, signature);
        }
    }
}
 
Example #2
Source File: AppIndexingApiDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private static String replaceUrlWithValue(@NonNull XmlContext context,
        @NonNull String str) {
    Project project = context.getProject();
    LintClient client = context.getClient();
    if (!client.supportsProjectResources()) {
        return str;
    }
    ResourceUrl style = ResourceUrl.parse(str);
    if (style == null || style.type != ResourceType.STRING || style.framework) {
        return str;
    }
    AbstractResourceRepository resources = client.getProjectResources(project, true);
    if (resources == null) {
        return str;
    }
    List<ResourceItem> items = resources.getResourceItem(ResourceType.STRING, style.name);
    if (items == null || items.isEmpty()) {
        return str;
    }
    ResourceValue resourceValue = items.get(0).getResourceValue(false);
    if (resourceValue == null) {
        return str;
    }
    return resourceValue.getValue() == null ? str : resourceValue.getValue();
}
 
Example #3
Source File: ManifestDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private static void checkMipmapIcon(@NonNull XmlContext context, @NonNull Element element) {
    Attr attribute = element.getAttributeNodeNS(ANDROID_URI, ATTR_ICON);
    if (attribute == null) {
        return;
    }
    String icon = attribute.getValue();
    if (icon.startsWith(DRAWABLE_PREFIX)) {
        if (TAG_ACTIVITY.equals(element.getTagName()) && !isLaunchableActivity(element)) {
            return;
        }

        if (context.isEnabled(MIPMAP)
                // Only complain if this app is skipping some densities
                && context.getProject().getApplicableDensities() != null) {
            context.report(MIPMAP, element, context.getLocation(attribute),
                    "Should use `@mipmap` instead of `@drawable` for launcher icons");
        }
    }
}
 
Example #4
Source File: LintCliXmlParser.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
@NonNull
public Location getValueLocation(@NonNull XmlContext context, @NonNull Attr node) {
    Location location = getLocation(context, node);
    Position start = location.getStart();
    Position end = location.getEnd();
    if (start == null || end == null) {
        return location;
    }
    int totalLength = end.getOffset() - start.getOffset();
    int length = node.getValue().length();
    int delta = totalLength - 1 - length;
    int startOffset = start.getOffset() + delta;
    int startColumn = start.getColumn() + delta;
    return Location.create(location.getFile(),
            new DefaultPosition(start.getLine(), startColumn, startOffset),
            new DefaultPosition(end.getLine(), startColumn + length, startOffset + length));
}
 
Example #5
Source File: LabelForDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    // NOTE: This should NOT be checking *minSdkVersion*, but *targetSdkVersion*
    // or even buildTarget instead. However, there's a risk that this will flag
    // way too much and make the rule annoying until API 17 support becomes
    // more widespread, so for now limit the check to those projects *really*
    // working with 17.  When API 17 reaches a certain amount of adoption, change
    // this to flag all apps supporting 17, including those supporting earlier
    // versions as well.
    if (context.getMainProject().getMinSdk() < 17) {
        return;
    }

    if (mTextFields == null) {
        mTextFields = new ArrayList<Element>();
    }
    mTextFields.add(element);
}
 
Example #6
Source File: LayoutConsistencyDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitDocument(@NonNull XmlContext context, @NonNull Document document) {
    Element root = document.getDocumentElement();
    if (root != null) {
        if (context.getPhase() == 1) {
            // Map from ids to types
            Map<String,String> fileMap = Maps.newHashMapWithExpectedSize(10);
            addIds(root, fileMap);

            getFileMapList(context).add(Pair.of(context.file, fileMap));
        } else {
            String name = LintUtils.getLayoutName(context.file);
            Map<String, List<Location>> map = mLocations.get(name);
            if (map != null) {
                lookupLocations(context, root, map);
            }
        }
    }
}
 
Example #7
Source File: TypoDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private static void checkRepeatedWords(XmlContext context, Element element, Node node,
        String text, int lastWordBegin, int lastWordEnd, int begin, int end) {
    if (lastWordBegin != -1 && end - begin == lastWordEnd - lastWordBegin
            && end - begin > 1) {
        // See whether we have a repeated word
        boolean different = false;
        for (int i = lastWordBegin, j = begin; i < lastWordEnd; i++, j++) {
            if (text.charAt(i) != text.charAt(j)) {
                different = true;
                break;
            }
        }
        if (!different && onlySpace(text, lastWordEnd, begin) && isTranslatable(element)) {
            reportRepeatedWord(context, node, text, lastWordBegin, begin, end);
        }
    }
}
 
Example #8
Source File: AccessibilityDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    if (!element.hasAttributeNS(ANDROID_URI, ATTR_CONTENT_DESCRIPTION)) {
        // Ignore views that are explicitly not important for accessibility
        if (VALUE_NO.equals(element.getAttributeNS(ANDROID_URI,
                ATTR_IMPORTANT_FOR_ACCESSIBILITY))) {
            return;
        }
        context.report(ISSUE, element, context.getLocation(element),
                "[Accessibility] Missing `contentDescription` attribute on image");
    } else {
        Attr attributeNode = element.getAttributeNodeNS(ANDROID_URI, ATTR_CONTENT_DESCRIPTION);
        String attribute = attributeNode.getValue();
        if (attribute.isEmpty() || attribute.equals("TODO")) { //$NON-NLS-1$
            context.report(ISSUE, attributeNode, context.getLocation(attributeNode),
                    "[Accessibility] Empty `contentDescription` attribute on image");
        }
    }
}
 
Example #9
Source File: ScrollViewChildDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    List<Element> children = LintUtils.getChildren(element);
    boolean isHorizontal = HORIZONTAL_SCROLL_VIEW.equals(element.getTagName());
    String attributeName = isHorizontal ? ATTR_LAYOUT_WIDTH : ATTR_LAYOUT_HEIGHT;
    for (Element child : children) {
        Attr sizeNode = child.getAttributeNodeNS(ANDROID_URI, attributeName);
        if (sizeNode == null) {
            return;
        }
        String value = sizeNode.getValue();
        if (VALUE_FILL_PARENT.equals(value) || VALUE_MATCH_PARENT.equals(value)) {
            String msg = String.format("This %1$s should use `android:%2$s=\"wrap_content\"`",
                    child.getTagName(), attributeName);
            context.report(ISSUE, sizeNode, context.getLocation(sizeNode), msg);
        }
    }
}
 
Example #10
Source File: ManifestDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void afterCheckFile(@NonNull Context context) {
    XmlContext xmlContext = (XmlContext) context;
    Element element = xmlContext.document.getDocumentElement();
    if (element != null) {
        checkDocumentElement(xmlContext, element);
    }

    if (mSeenUsesSdk == 0 && context.isEnabled(USES_SDK)
            // Not required in Gradle projects; typically defined in build.gradle instead
            // and inserted at build time
            && !context.getMainProject().isGradleProject()) {
        context.report(USES_SDK, Location.create(context.file),
                "Manifest should specify a minimum API level with " +
                "`<uses-sdk android:minSdkVersion=\"?\" />`; if it really supports " +
                "all versions of Android set it to 1.");
    }
}
 
Example #11
Source File: IconDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    String icon = element.getAttributeNS(ANDROID_URI, ATTR_ICON);
    if (icon != null && icon.startsWith(DRAWABLE_PREFIX)) {
        icon = icon.substring(DRAWABLE_PREFIX.length());

        String tagName = element.getTagName();
        if (tagName.equals(TAG_ITEM)) {
            if (mMenuToIcons == null) {
                mMenuToIcons = ArrayListMultimap.create();
            }
            String menu = getBaseName(context.file.getName());
            mMenuToIcons.put(menu, icon);
        } else {
            // Manifest tags: launcher icons
            if (mLauncherIcons == null) {
                mLauncherIcons = Sets.newHashSet();
            }
            mLauncherIcons.add(icon);
        }
    }
}
 
Example #12
Source File: WrongIdDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) {
    assert attribute.getName().equals(ATTR_ID) || attribute.getLocalName().equals(ATTR_ID);
    String id = attribute.getValue();
    mFileIds.add(id);
    mGlobalIds.add(id);

    if (id.equals(NEW_ID_PREFIX) || id.equals(ID_PREFIX) || "@+id".equals(ID_PREFIX)) {
        String message = "Invalid id: missing value";
        context.report(INVALID, attribute, context.getLocation(attribute), message);
    } else if (id.startsWith("@+") && !id.startsWith(NEW_ID_PREFIX) //$NON-NLS-1$
            && !id.startsWith("@+android:id/")  //$NON-NLS-1$
            || id.startsWith(NEW_ID_PREFIX)
            && id.indexOf('/', NEW_ID_PREFIX.length()) != -1) {
        int nameStart = id.startsWith(NEW_ID_PREFIX) ? NEW_ID_PREFIX.length() : 2;
        String suggested = NEW_ID_PREFIX + id.substring(nameStart).replace('/', '_');
        String message = String.format(
                "ID definitions *must* be of the form `@+id/name`; try using `%1$s`", suggested);
        context.report(INVALID, attribute, context.getLocation(attribute), message);
    }
}
 
Example #13
Source File: WrongIdDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    if (element.getTagName().equals(RELATIVE_LAYOUT)) {
        if (mRelativeLayouts == null) {
            mRelativeLayouts = new ArrayList<Element>();
        }
        mRelativeLayouts.add(element);
    } else {
        assert element.getTagName().equals(TAG_ITEM);
        String type = element.getAttribute(ATTR_TYPE);
        if (VALUE_ID.equals(type)) {
            String name = element.getAttribute(ATTR_NAME);
            if (!name.isEmpty()) {
                if (mDeclaredIds == null) {
                    mDeclaredIds = Sets.newHashSet();
                }
                mDeclaredIds.add(ID_PREFIX + name);
            }
        }
    }
}
 
Example #14
Source File: NestedScrollingWidgetDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    boolean vertical = isVerticalScroll(element);
    if (vertical) {
        mVisitingVerticalScroll++;
    } else {
        mVisitingHorizontalScroll++;
    }

    if (mVisitingHorizontalScroll > 1 || mVisitingVerticalScroll > 1) {
        Element parent = findOuterScrollingWidget(element.getParentNode(), vertical);
        if (parent != null) {
            String format;
            if (mVisitingVerticalScroll > 1) {
                format = "The vertically scrolling `%1$s` should not contain another " +
                        "vertically scrolling widget (`%2$s`)";
            } else {
                format = "The horizontally scrolling `%1$s` should not contain another " +
                        "horizontally scrolling widget (`%2$s`)";
            }
            String msg = String.format(format, parent.getTagName(), element.getTagName());
            context.report(ISSUE, element, context.getLocation(element), msg);
        }
    }
}
 
Example #15
Source File: ResourcePrefixDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    if (mPrefix == null || context.getResourceFolderType() != ResourceFolderType.VALUES) {
        return;
    }

    for (Element item : LintUtils.getChildren(element)) {
        Attr nameAttribute = item.getAttributeNode(ATTR_NAME);
        if (nameAttribute != null) {
            String name = nameAttribute.getValue();
            if (!name.startsWith(mPrefix)) {
                String message = getErrorMessage(name);
                context.report(ISSUE, nameAttribute, context.getLocation(nameAttribute),
                        message);
            }
        }
    }
}
 
Example #16
Source File: MissingClassDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private static void checkInnerClass(XmlContext context, Element element, String pkg,
        Node classNameNode, String className) {
    if (pkg != null && className.indexOf('$') == -1 && className.indexOf('.', 1) > 0) {
        boolean haveUpperCase = false;
        for (int i = 0, n = pkg.length(); i < n; i++) {
            if (Character.isUpperCase(pkg.charAt(i))) {
                haveUpperCase = true;
                break;
            }
        }
        if (!haveUpperCase) {
            String fixed = className.charAt(0) + className.substring(1).replace('.','$');
            String message = "Use '$' instead of '.' for inner classes " +
                    "(or use only lowercase letters in package names); replace \"" +
                    className + "\" with \"" + fixed + "\"";
            Location location = context.getLocation(classNameNode);
            context.report(INNERCLASS, element, location, message);
        }
    }
}
 
Example #17
Source File: FullBackupContentDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@NonNull
private static String validatePath(@NonNull XmlContext context, @NonNull Element element) {
    Attr pathNode = element.getAttributeNode(ATTR_PATH);
    if (pathNode == null) {
        return "";
    }
    String value = pathNode.getValue();
    if (value.contains("//")) {
        context.report(ISSUE, element, context.getValueLocation(pathNode),
                "Paths are not allowed to contain `//`");
    } else if (value.contains("..")) {
        context.report(ISSUE, element, context.getValueLocation(pathNode),
                "Paths are not allowed to contain `..`");
    } else if (value.contains("/")) {
        String domain = element.getAttribute(ATTR_DOMAIN);
        if (DOMAIN_SHARED_PREF.equals(domain) || DOMAIN_DATABASE.equals(domain)) {
            context.report(ISSUE, element, context.getValueLocation(pathNode),
                    String.format("Subdirectories are not allowed for domain `%1$s`",
                            domain));
        }
    }
    return value;
}
 
Example #18
Source File: LayoutIdFormat.java    From lewis with Apache License 2.0 6 votes vote down vote up
@Override
public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) {
    String value = attribute.getValue();

    if (!value.isEmpty()) {

        // Make sure this is really one of the android: attributes
        if (!ANDROID_URI.equals(attribute.getNamespaceURI())) {
            return;
        }

        value = value.substring(5); // ignore "@+id/"

        if (!idCorrectFormat(value)) {
            context.report(ISSUE, attribute, context.getLocation(attribute),
                    String.format("The id \"%1$s\", should be written using lowerCamelCase.", value));
        }

    }
}
 
Example #19
Source File: GridLayoutDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private static void ensureAppNamespace(XmlContext context, Element element, String name) {
    Attr attribute = element.getAttributeNodeNS(ANDROID_URI, name);
    if (attribute != null) {
        String prefix = getNamespacePrefix(element.getOwnerDocument(), AUTO_URI);
        boolean haveNamespace = prefix != null;
        if (!haveNamespace) {
            prefix = "app";
        }

        StringBuilder sb = new StringBuilder();
        sb.append("Wrong namespace; with v7 `GridLayout` you should use ").append(prefix)
                .append(":").append(name);
        if (!haveNamespace) {
            sb.append(" (and add `xmlns:app=\"").append(AUTO_URI)
                    .append("\"` to your root element.)");
        }
        String message = sb.toString();

        context.report(ISSUE, attribute, context.getLocation(attribute), message);
    }
}
 
Example #20
Source File: LayoutInflationDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitDocument(@NonNull XmlContext context, @NonNull Document document) {
    Element root = document.getDocumentElement();
    if (root != null) {
        NamedNodeMap attributes = root.getAttributes();
        for (int i = 0, n = attributes.getLength(); i < n; i++) {
            Attr attribute = (Attr) attributes.item(i);
            if (attribute.getLocalName() != null
                    && attribute.getLocalName().startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)) {
                if (mLayoutsWithRootLayoutParams == null) {
                    mLayoutsWithRootLayoutParams = Sets.newHashSetWithExpectedSize(20);
                }
                mLayoutsWithRootLayoutParams.add(LintUtils.getBaseName(context.file.getName()));
                break;
            }
        }
    }
}
 
Example #21
Source File: LintCliXmlParserTest.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
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";
    LintCliXmlParser parser = new LintCliXmlParser();
    File file = File.createTempFile("parsertest2", ".xml");
    //noinspection IOResourceOpenedButNotSafelyClosed
    Writer fw = new BufferedWriter(new FileWriter(file));
    fw.write(xml);
    fw.close();
    LintClient client = new TestClient();
    LintDriver driver = new LintDriver(new BuiltinIssueRegistry(), client);
    Project project = Project.create(client, file.getParentFile(), file.getParentFile());
    XmlContext context = new XmlContext(driver, project, null, file, null, parser);
    Document document = parser.parseXml(context);
    assertNotNull(document);

    //noinspection ResultOfMethodCallIgnored
    file.delete();
}
 
Example #22
Source File: ChildCountDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    int childCount = LintUtils.getChildCount(element);
    String tagName = element.getTagName();
    if (tagName.equals(SCROLL_VIEW) || tagName.equals(HORIZONTAL_SCROLL_VIEW)) {
        if (childCount > 1 && getAccurateChildCount(element) > 1) {
            context.report(SCROLLVIEW_ISSUE, element,
                    context.getLocation(element), "A scroll view can have only one child");
        }
    } else {
        // Adapter view
        if (childCount > 0 && getAccurateChildCount(element) > 0) {
            context.report(ADAPTER_VIEW_ISSUE, element,
                    context.getLocation(element),
                    "A list/grid should have no children declared in XML");
        }
    }
}
 
Example #23
Source File: SignatureOrSystemDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) {
    String protectionLevel = attribute.getValue();
    if (protectionLevel != null
        && protectionLevel.equals(SIGNATURE_OR_SYSTEM)) {
        String message = "`protectionLevel` should probably not be set to `signatureOrSystem`";
        context.report(ISSUE, attribute, context.getLocation(attribute), message);
    }
}
 
Example #24
Source File: MainActivityDetector.java    From android-custom-lint-rules with Apache License 2.0 5 votes vote down vote up
@Override
public void visitElement(XmlContext context, Element activityElement) {
    // Checks every activity and reports an error if there is no activity with a launcher
    // intent.
    mHasActivity = true;
    if (isMainActivity(activityElement)) {
        mHasLauncherActivity = true;
    }
}
 
Example #25
Source File: ObsoleteLayoutParamsDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    String layout = element.getAttribute(ATTR_LAYOUT);
    if (layout.startsWith(LAYOUT_RESOURCE_PREFIX)) { // Ignore @android:layout/ layouts
        layout = layout.substring(LAYOUT_RESOURCE_PREFIX.length());

        Node parent = element.getParentNode();
        if (parent.getNodeType() == Node.ELEMENT_NODE) {
            String tag = parent.getNodeName();
            if (tag.indexOf('.') == -1 && !tag.equals(VIEW_MERGE)) {
                if (!context.getProject().getReportIssues()) {
                    // If this is a library project not being analyzed, ignore it
                    return;
                }

                if (mIncludes == null) {
                    mIncludes = new HashMap<String, List<Pair<File, String>>>();
                }
                List<Pair<File, String>> includes = mIncludes.get(layout);
                if (includes == null) {
                    includes = new ArrayList<Pair<File, String>>();
                    mIncludes.put(layout, includes);
                }
                includes.add(Pair.of(context.file, tag));
            }
        }
    }
}
 
Example #26
Source File: LayoutConsistencyDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@NonNull
private List<Pair<File, Map<String, String>>> getFileMapList(
        @NonNull XmlContext context) {
    String name = LintUtils.getLayoutName(context.file);
    List<Pair<File, Map<String, String>>> list = mMap.get(name);
    if (list == null) {
        list = Lists.newArrayListWithCapacity(4);
        mMap.put(name, list);
    }
    return list;
}
 
Example #27
Source File: ArraySizeDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private static void incrementalCheckCount(@NonNull XmlContext context, @NonNull Element element,
        @NonNull String name, int childCount) {
    LintClient client = context.getClient();
    Project project = context.getMainProject();
    AbstractResourceRepository resources = client.getProjectResources(project, true);
    if (resources == null) {
        return;
    }
    List<ResourceItem> items = resources.getResourceItem(ResourceType.ARRAY, name);
    if (items != null) {
        for (ResourceItem item : items) {
            ResourceFile source = item.getSource();
            if (source != null && LintUtils.isSameResourceFile(context.file,
                                                               source.getFile())) {
                continue;
            }
            ResourceValue rv = item.getResourceValue(false);
            if (rv instanceof ArrayResourceValue) {
                ArrayResourceValue arv = (ArrayResourceValue) rv;
                if (childCount != arv.getElementCount()) {
                    String thisName = context.file.getParentFile().getName() + File.separator
                            + context.file.getName();
                    assert source != null;
                    File otherFile = source.getFile();
                    String otherName = otherFile.getParentFile().getName() + File.separator
                            + otherFile.getName();
                    String message = String.format(
                            "Array `%1$s` has an inconsistent number of items (%2$d in `%3$s`, %4$d in `%5$s`)",
                            name, childCount, thisName, arv.getElementCount(), otherName);

                    context.report(INCONSISTENT, element, context.getLocation(element),
                            message);
                }
            }
        }
    }
}
 
Example #28
Source File: HardcodedValuesDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) {
    String value = attribute.getValue();
    if (!value.isEmpty() && (value.charAt(0) != '@' && value.charAt(0) != '?')) {
        // Make sure this is really one of the android: attributes
        if (!ANDROID_URI.equals(attribute.getNamespaceURI())) {
            return;
        }

        context.report(ISSUE, attribute, context.getLocation(attribute),
            String.format("[I18N] Hardcoded string \"%1$s\", should use `@string` resource",
                          value));
    }
}
 
Example #29
Source File: Utf8Detector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void visitDocument(@NonNull XmlContext context, @NonNull Document document) {
    String xml = context.getContents();
    if (xml == null) {
        return;
    }

    // AAPT: The prologue must be in the first line
    int lineEnd = 0;
    int max = xml.length();
    for (; lineEnd < max; lineEnd++) {
        char c = xml.charAt(lineEnd);
        if (c == '\n' || c == '\r') {
            break;
        }
    }

    for (int i = 16; i < lineEnd - 5; i++) { // +4: Skip at least <?xml encoding="
        if ((xml.charAt(i) == 'u' || xml.charAt(i) == 'U')
                && (xml.charAt(i + 1) == 't' || xml.charAt(i + 1) == 'T')
                && (xml.charAt(i + 2) == 'f' || xml.charAt(i + 2) == 'F')
                && (xml.charAt(i + 3) == '-' || xml.charAt(i + 3) == '_')
                && (xml.charAt(i + 4) == '8')) {
            return;
        }
    }

    int encodingIndex = xml.lastIndexOf("encoding", lineEnd); //$NON-NLS-1$
    if (encodingIndex != -1) {
        Matcher matcher = ENCODING_PATTERN.matcher(xml);
        if (matcher.find(encodingIndex)) {
            String encoding = matcher.group(1);
            Location location = Location.create(context.file, xml,
                    matcher.start(1), matcher.end(1));
            context.report(ISSUE, null, location, String.format(
                    "%1$s: Not using UTF-8 as the file encoding. This can lead to subtle " +
                            "bugs with non-ascii characters", encoding));
        }
    }
}
 
Example #30
Source File: UseCompoundDrawableDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
    int childCount = LintUtils.getChildCount(element);
    if (childCount == 2) {
        List<Element> children = LintUtils.getChildren(element);
        Element first = children.get(0);
        Element second = children.get(1);
        if ((first.getTagName().equals(IMAGE_VIEW) &&
                second.getTagName().equals(TEXT_VIEW) &&
                !first.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_WEIGHT)) ||
            ((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;
            }

            // Certain scale types cannot be done with compound drawables
            String scaleType = first.getTagName().equals(IMAGE_VIEW)
                    ? first.getAttributeNS(ANDROID_URI, ATTR_SCALE_TYPE)
                    : second.getAttributeNS(ANDROID_URI, ATTR_SCALE_TYPE);
            if (scaleType != null && !scaleType.isEmpty()) {
                // For now, ignore if any scale type is set
                return;
            }

            context.report(ISSUE, element, context.getLocation(element),
                    "This tag and its children can be replaced by one `<TextView/>` and " +
                            "a compound drawable");
        }
    }
}