/*
 * 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.checks;

import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.CLASS_CONTEXT;
import static com.android.SdkConstants.CLASS_FRAGMENT;
import static com.android.SdkConstants.CLASS_RESOURCES;
import static com.android.SdkConstants.CLASS_V4_FRAGMENT;
import static com.android.SdkConstants.FORMAT_METHOD;
import static com.android.SdkConstants.GET_STRING_METHOD;
import static com.android.SdkConstants.TAG_STRING;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_BOOLEAN_WRAPPER;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_BYTE_WRAPPER;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_CHARACTER_WRAPPER;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_DOUBLE_WRAPPER;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_FLOAT_WRAPPER;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_INTEGER_WRAPPER;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_LONG_WRAPPER;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_OBJECT;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_SHORT_WRAPPER;
import static com.android.tools.lint.client.api.JavaEvaluatorKt.TYPE_STRING;
import static com.android.utils.CharSequences.indexOf;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.ResourceNamespace;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.resources.ResourceItem;
import com.android.ide.common.resources.ResourceRepository;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.android.resources.ResourceUrl;
import com.android.tools.lint.client.api.JavaEvaluator;
import com.android.tools.lint.client.api.LintClient;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Implementation;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.JavaContext;
import com.android.tools.lint.detector.api.Lint;
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.ResourceEvaluator;
import com.android.tools.lint.detector.api.ResourceXmlDetector;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.SourceCodeScanner;
import com.android.tools.lint.detector.api.XmlContext;
import com.android.utils.Pair;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameterList;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiVariable;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jetbrains.uast.UCallExpression;
import org.jetbrains.uast.UExpression;
import org.jetbrains.uast.ULiteralExpression;
import org.jetbrains.uast.UReferenceExpression;
import org.jetbrains.uast.UastFacade;
import org.jetbrains.uast.util.UastExpressionUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Check which looks for problems with formatting strings such as inconsistencies between
 * translations or between string declaration and string usage in Java.
 *
 * <p>TODO: Handle Resources.getQuantityString as well
 */
public class StringFormatDetector extends ResourceXmlDetector implements SourceCodeScanner {
    private static final Implementation IMPLEMENTATION_XML =
            new Implementation(StringFormatDetector.class, Scope.ALL_RESOURCES_SCOPE);

    @SuppressWarnings("unchecked")
    private static final Implementation IMPLEMENTATION_XML_AND_JAVA =
            new Implementation(
                    StringFormatDetector.class,
                    EnumSet.of(Scope.ALL_RESOURCE_FILES, Scope.JAVA_FILE),
                    Scope.JAVA_FILE_SCOPE);

    /** Whether formatting strings are invalid */
    public static final Issue INVALID =
            Issue.create(
                    "StringFormatInvalid",
                    "Invalid format string",
                    "If a string contains a '%' character, then the string may be a formatting string "
                            + "which will be passed to `String.format` from Java code to replace each '%' "
                            + "occurrence with specific values.\n"
                            + "\n"
                            + "This lint warning checks for two related problems:\n"
                            + "(1) Formatting strings that are invalid, meaning that `String.format` will throw "
                            + "exceptions at runtime when attempting to use the format string.\n"
                            + "(2) Strings containing '%' that are not formatting strings getting passed to "
                            + "a `String.format` call. In this case the '%' will need to be escaped as '%%'.\n"
                            + "\n"
                            + "NOTE: Not all Strings which look like formatting strings are intended for "
                            + "use by `String.format`; for example, they may contain date formats intended "
                            + "for `android.text.format.Time#format()`. Lint cannot always figure out that "
                            + "a String is a date format, so you may get false warnings in those scenarios. "
                            + "See the suppress help topic for information on how to suppress errors in "
                            + "that case.",
                    Category.MESSAGES,
                    9,
                    Severity.ERROR,
                    IMPLEMENTATION_XML);

    /** Whether formatting argument types are consistent across translations */
    public static final Issue ARG_COUNT =
            Issue.create(
                    "StringFormatCount",
                    "Formatting argument types incomplete or inconsistent",
                    "When a formatted string takes arguments, it usually needs to reference the "
                            + "same arguments in all translations (or all arguments if there are no "
                            + "translations.\n"
                            + "\n"
                            + "There are cases where this is not the case, so this issue is a warning rather "
                            + "than an error by default. However, this usually happens when a language is not "
                            + "translated or updated correctly.",
                    Category.MESSAGES,
                    5,
                    Severity.WARNING,
                    IMPLEMENTATION_XML);

    /** Whether the string format supplied in a call to String.format matches the format string */
    public static final Issue ARG_TYPES =
            Issue.create(
                    "StringFormatMatches",
                    "`String.format` string doesn't match the XML format string",
                    "This lint check ensures the following:\n"
                            + "(1) If there are multiple translations of the format string, then all translations "
                            + "use the same type for the same numbered arguments\n"
                            + "(2) The usage of the format string in Java is consistent with the format string, "
                            + "meaning that the parameter types passed to String.format matches those in the "
                            + "format string.",
                    Category.MESSAGES,
                    9,
                    Severity.ERROR,
                    IMPLEMENTATION_XML_AND_JAVA);

    /** This plural does not use the quantity value */
    public static final Issue POTENTIAL_PLURAL =
            Issue.create(
                            "PluralsCandidate",
                            "Potential Plurals",
                            "This lint check looks for potential errors in internationalization where you have "
                                    + "translated a message which involves a quantity and it looks like other parts of "
                                    + "the string may need grammatical changes.\n"
                                    + "\n"
                                    + "For example, rather than something like this:\n"
                                    + "```xml\n"
                                    + "  <string name=\"try_again\">Try again in %d seconds.</string>\n"
                                    + "```\n"
                                    + "you should be using a plural:\n"
                                    + "```xml\n"
                                    + "   <plurals name=\"try_again\">\n"
                                    + "        <item quantity=\"one\">Try again in %d second</item>\n"
                                    + "        <item quantity=\"other\">Try again in %d seconds</item>\n"
                                    + "    </plurals>\n"
                                    + "```\n"
                                    + "This will ensure that in other languages the right set of translations are "
                                    + "provided for the different quantity classes.\n"
                                    + "\n"
                                    + "(This check depends on some heuristics, so it may not accurately determine whether "
                                    + "a string really should be a quantity. You can use tools:ignore to filter out false "
                                    + "positives.",
                            Category.MESSAGES,
                            5,
                            Severity.WARNING,
                            IMPLEMENTATION_XML)
                    .addMoreInfo(
                            "https://developer.android.com/guide/topics/resources/string-resource.html#Plurals");

    /**
     * Map from a format string name to a list of declaration file and actual formatting string
     * content. We're using a list since a format string can be defined multiple times, usually for
     * different translations.
     */
    private Map<String, List<Pair<Handle, String>>> mFormatStrings;

    /** Map of strings that do not contain any formatting. */
    private final Map<String, Handle> mNotFormatStrings = new HashMap<>();

    /**
     * Set of strings that have an unknown format such as date formatting; we should not flag these
     * as invalid when used from a String#format call
     */
    private Set<String> mIgnoreStrings;

    /** Constructs a new {@link StringFormatDetector} check */
    public StringFormatDetector() {}

    @Override
    public boolean appliesTo(@NonNull ResourceFolderType folderType) {
        return folderType == ResourceFolderType.VALUES;
    }

    @Override
    public Collection<String> getApplicableElements() {
        return Collections.singletonList(TAG_STRING);
    }

    @Override
    public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
        NodeList childNodes = element.getChildNodes();
        if (childNodes.getLength() > 0) {
            if (childNodes.getLength() == 1) {
                Node child = childNodes.item(0);
                if (child.getNodeType() == Node.TEXT_NODE) {
                    checkTextNode(context, element, stripQuotes(child.getNodeValue()));
                }
            } else {
                // Concatenate children and build up a plain string.
                // This is needed to handle xliff localization documents,
                // but this needs more work so ignore compound XML documents as
                // string values for now:
                StringBuilder sb = new StringBuilder();
                addText(sb, element);
                if (sb.length() > 0) {
                    checkTextNode(context, element, sb.toString());
                }
            }
        }
    }

    static void addText(StringBuilder sb, Node node) {
        short nodeType = node.getNodeType();
        if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) {
            sb.append(stripQuotes(node.getNodeValue().trim()));
        } else {
            NodeList childNodes = node.getChildNodes();
            for (int i = 0, n = childNodes.getLength(); i < n; i++) {
                addText(sb, childNodes.item(i));
            }
        }
    }

    /**
     * Removes all the unescaped quotes. See <a
     * href="http://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling">Escaping
     * apostrophes and quotes</a>
     */
    static String stripQuotes(String s) {
        StringBuilder sb = new StringBuilder();
        boolean isEscaped = false;
        boolean isQuotedBlock = false;
        for (int i = 0, len = s.length(); i < len; i++) {
            char current = s.charAt(i);
            if (isEscaped) {
                sb.append(current);
                isEscaped = false;
            } else {
                isEscaped = current == '\\'; // Next char will be escaped so we will just copy it
                if (current == '"') {
                    isQuotedBlock = !isQuotedBlock;
                } else if (current == '\'') {
                    if (isQuotedBlock) {
                        // We only add single quotes when they are within a quoted block
                        sb.append(current);
                    }
                } else {
                    sb.append(current);
                }
            }
        }

        return sb.toString();
    }

    private void checkTextNode(XmlContext context, Element element, String text) {
        String name = element.getAttribute(ATTR_NAME);
        boolean found = false;
        boolean foundPlural = false;

        // Look at the String and see if it's a format string (contains
        // positional %'s)
        for (int j = 0, m = text.length(); j < m; j++) {
            char c = text.charAt(j);
            if (c == '\\') {
                j++;
            }
            if (c == '%') {
                // Also make sure this String isn't an unformatted String
                String formatted = element.getAttribute("formatted");
                if (!formatted.isEmpty() && !Boolean.parseBoolean(formatted)) {
                    if (!mNotFormatStrings.containsKey(name)) {
                        Handle handle = context.createLocationHandle(element);
                        handle.setClientData(element);
                        mNotFormatStrings.put(name, handle);
                    }
                    return;
                }

                // See if it's not a format string, e.g. "Battery charge is 100%!".
                // If so we want to record this name in a special list such that we can
                // make sure you don't attempt to reference this string from a String.format
                // call.
                Matcher matcher = FORMAT.matcher(text);
                if (!matcher.find(j)) {
                    if (!mNotFormatStrings.containsKey(name)) {
                        Handle handle = context.createLocationHandle(element);
                        handle.setClientData(element);
                        mNotFormatStrings.put(name, handle);
                    }
                    return;
                }

                String conversion = matcher.group(6);
                int conversionClass = getConversionClass(conversion.charAt(0));
                if (conversionClass == CONVERSION_CLASS_UNKNOWN || matcher.group(5) != null) {
                    if (mIgnoreStrings == null) {
                        mIgnoreStrings = new HashSet<>();
                    }
                    mIgnoreStrings.add(name);

                    // Don't process any other strings here; some of them could
                    // accidentally look like a string, e.g. "%H" is a hash code conversion
                    // in String.format (and hour in Time formatting).
                    return;
                }

                if (conversionClass == CONVERSION_CLASS_INTEGER && !foundPlural) {
                    // See if there appears to be further text content here.
                    // Look for whitespace followed by a letter, with no punctuation in between
                    for (int k = matcher.end(); k < m; k++) {
                        char nc = text.charAt(k);
                        if (!Character.isWhitespace(nc)) {
                            if (Character.isLetter(nc)) {
                                foundPlural = checkPotentialPlural(context, element, text, k);
                            }
                            break;
                        }
                    }
                }

                found = true;
                j++; // Ensure that when we process a "%%" we don't separately check the second %
            }
        }

        if (!context.getProject().getReportIssues()) {
            // If this is a library project not being analyzed, ignore it
            return;
        }

        if (name != null) {
            Handle handle = context.createLocationHandle(element);
            handle.setClientData(element);
            if (found) {
                // Record it for analysis when seen in Java code
                if (mFormatStrings == null) {
                    mFormatStrings = new HashMap<>();
                }

                List<Pair<Handle, String>> list = mFormatStrings.get(name);
                if (list == null) {
                    list = new ArrayList<>();
                    mFormatStrings.put(name, list);
                }
                list.add(Pair.of(handle, text));
            } else {
                if (!isReference(text)) {
                    mNotFormatStrings.put(name, handle);
                }
            }
        }
    }

    private static boolean isReference(@NonNull String text) {
        for (int i = 0, n = text.length(); i < n; i++) {
            char c = text.charAt(i);
            if (!Character.isWhitespace(c)) {
                return c == '@' || c == '?';
            }
        }
        return false;
    }

    /**
     * Checks whether the text begins with a non-unit word, pointing to a string that should
     * probably be a plural instead. This
     */
    private static boolean checkPotentialPlural(
            XmlContext context, Element element, String text, int wordBegin) {
        // This method should only be called if the text is known to start with a word
        assert Character.isLetter(text.charAt(wordBegin));

        int wordEnd = wordBegin;
        while (wordEnd < text.length()) {
            if (!Character.isLetter(text.charAt(wordEnd))) {
                break;
            }
            wordEnd++;
        }

        // Eliminate units, since those are not sentences you need to use plurals for, e.g.
        //   "Elevation gain: %1$d m (%2$d ft)"
        // We'll determine whether something is a unit by looking for
        // (1) Multiple uppercase characters (e.g. KB, or MiB), or better yet, uppercase characters
        //     anywhere but as the first letter
        // (2) No vowels (e.g. ft)
        // (3) Adjacent consonants (e.g. ft); this one can eliminate some legitimate
        //     English words as well (e.g. "the") so we should really limit this to
        //     letter pairs that are not common in English. This is probably overkill
        //     so not handled yet. Instead we use a simpler heuristic:
        // (4) Very short "words" (1-2 letters)
        if (wordEnd - wordBegin <= 2) {
            // Very short word (1-2 chars): possible unit, e.g. "m", "ft", "kb", etc
            return false;
        }
        boolean hasVowel = false;
        for (int i = wordBegin; i < wordEnd; i++) {
            // Uppercase character anywhere but first character: probably a unit (e.g. KB)
            char c = text.charAt(i);
            if (i > wordBegin && Character.isUpperCase(c)) {
                return false;
            }
            if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y') {
                hasVowel = true;
            }
        }
        if (!hasVowel) {
            // No vowels: likely unit
            return false;
        }

        String word = text.substring(wordBegin, wordEnd);

        // Some other known abbreviations that we don't want to count:
        if (word.equals("min")) {
            return false;
        }

        // This heuristic only works in English!
        if (Lint.isEnglishResource(context, true)) {
            String message =
                    String.format(
                            "Formatting %%d followed by words (\"%1$s\"): "
                                    + "This should probably be a plural rather than a string",
                            word);
            context.report(POTENTIAL_PLURAL, element, context.getLocation(element), message);
            // Avoid reporting multiple errors on the same string
            // (if it contains more than one %d)
            return true;
        }

        return false;
    }

    @Override
    public void afterCheckRootProject(@NonNull Context context) {
        if (mFormatStrings != null) {
            boolean checkCount = context.isEnabled(ARG_COUNT);
            boolean checkValid = context.isEnabled(INVALID);
            boolean checkTypes = context.isEnabled(ARG_TYPES);

            // Ensure that all the format strings are consistent with respect to each other;
            // e.g. they all have the same number of arguments, they all use all the
            // arguments, and they all use the same types for all the numbered arguments
            for (Map.Entry<String, List<Pair<Handle, String>>> entry : mFormatStrings.entrySet()) {
                String name = entry.getKey();
                List<Pair<Handle, String>> list = entry.getValue();

                // Check argument counts
                if (checkCount) {
                    Handle notFormatted = mNotFormatStrings.get(name);
                    if (notFormatted != null) {
                        list =
                                ImmutableList.<Pair<Handle, String>>builder()
                                        .add(Pair.of(notFormatted, name))
                                        .addAll(list)
                                        .build();
                    }
                    checkArity(context, name, list);
                }

                // Check argument types (and also make sure that the formatting strings are valid)
                if (checkValid || checkTypes) {
                    checkTypes(context, checkValid, checkTypes, name, list);
                }
            }
        }
    }

    private static void checkTypes(
            Context context,
            boolean checkValid,
            boolean checkTypes,
            String name,
            List<Pair<Handle, String>> list) {
        Map<Integer, String> types = new HashMap<>();
        Map<Integer, Handle> typeDefinition = new HashMap<>();
        for (Pair<Handle, String> pair : list) {
            Handle handle = pair.getFirst();
            String formatString = pair.getSecond();

            //boolean warned = false;
            Matcher matcher = FORMAT.matcher(formatString);
            int index = 0;
            int prevIndex = 0;
            int nextNumber = 1;
            while (true) {
                if (matcher.find(index)) {
                    int matchStart = matcher.start();
                    // Make sure this is not an escaped '%'
                    for (; prevIndex < matchStart; prevIndex++) {
                        char c = formatString.charAt(prevIndex);
                        if (c == '\\') {
                            prevIndex++;
                        }
                    }
                    if (prevIndex > matchStart) {
                        // We're in an escape, ignore this result
                        index = prevIndex;
                        continue;
                    }

                    index = matcher.end(); // Ensure loop proceeds
                    String str = formatString.substring(matchStart, matcher.end());
                    if (str.equals("%%") || str.equals("%n")) {
                        // Just an escaped %
                        continue;
                    }

                    if (checkValid) {
                        // Make sure it's a valid format string
                        if (str.length() > 2 && str.charAt(str.length() - 2) == ' ') {
                            char last = str.charAt(str.length() - 1);
                            // If you forget to include the conversion character, e.g.
                            //   "Weight=%1$ g" instead of "Weight=%1$d g", then
                            // you're going to end up with a format string interpreted as
                            // "%1$ g". This means that the space character is interpreted
                            // as a flag character, but it can only be a flag character
                            // when used in conjunction with the numeric conversion
                            // formats (d, o, x, X). If that's not the case, make a
                            // dedicated error message
                            if (last != 'd' && last != 'o' && last != 'x' && last != 'X') {
                                Object clientData = handle.getClientData();
                                if (clientData instanceof Node) {
                                    if (context.getDriver()
                                            .isSuppressed(null, INVALID, (Node) clientData)) {
                                        return;
                                    }
                                }

                                Location location = handle.resolve();
                                String message =
                                        String.format(
                                                "Incorrect formatting string `%1$s`; missing conversion "
                                                        + "character in '`%2$s`' ?",
                                                name, str);
                                context.report(INVALID, location, message);
                                //warned = true;
                                continue;
                            }
                        }
                    }

                    if (!checkTypes) {
                        continue;
                    }

                    // Shouldn't throw a number format exception since we've already
                    // matched the pattern in the regexp
                    int number;
                    String numberString = matcher.group(1);
                    if (numberString != null) {
                        // Strip off trailing $
                        numberString = numberString.substring(0, numberString.length() - 1);
                        number = Integer.parseInt(numberString);
                        nextNumber = number + 1;
                    } else {
                        number = nextNumber++;
                    }
                    String format = matcher.group(6);
                    String currentFormat = types.get(number);
                    if (currentFormat == null) {
                        types.put(number, format);
                        typeDefinition.put(number, handle);
                    } else if (!currentFormat.equals(format)
                            && isIncompatible(currentFormat.charAt(0), format.charAt(0))) {

                        Object clientData = handle.getClientData();
                        if (clientData instanceof Node) {
                            if (context.getDriver()
                                    .isSuppressed(null, ARG_TYPES, (Node) clientData)) {
                                return;
                            }
                        }

                        Location location = handle.resolve();
                        // Attempt to limit the location range to just the formatting
                        // string in question
                        location =
                                refineLocation(
                                        context,
                                        location,
                                        formatString,
                                        matcher.start(),
                                        matcher.end());
                        Location otherLocation = typeDefinition.get(number).resolve();
                        otherLocation.setMessage("Conflicting argument type here");
                        location.setSecondary(otherLocation);
                        File f = otherLocation.getFile();
                        String message =
                                String.format(
                                        "Inconsistent formatting types for argument #%1$d in "
                                                + "format string `%2$s` ('%3$s'): Found both '`%4$s`' and '`%5$s`' "
                                                + "(in %6$s)",
                                        number,
                                        name,
                                        str,
                                        currentFormat,
                                        format,
                                        Lint.getFileNameWithParent(context.getClient(), f));
                        //warned = true;
                        context.report(ARG_TYPES, location, message);
                        break;
                    }
                } else {
                    break;
                }
            }

            // Check that the format string is valid by actually attempting to instantiate
            // it. We only do this if we haven't already complained about this string
            // for other reasons.
            /* Check disabled for now: it had many false reports due to conversion
             * errors (which is expected since we just pass in strings), but once those
             * are eliminated there aren't really any other valid error messages returned
             * (for example, calling the formatter with bogus formatting flags always just
             * returns a "conversion" error. It looks like we'd need to actually pass compatible
             * arguments to trigger other types of formatting errors such as precision errors.
            if (!warned && checkValid) {
                try {
                    formatter.format(formatString, "", "", "", "", "", "", "",
                            "", "", "", "", "", "", "");

                } catch (IllegalFormatException t) { // TODO: UnknownFormatConversionException
                    if (!t.getLocalizedMessage().contains(" != ")
                            && !t.getLocalizedMessage().contains("Conversion")) {
                        Location location = handle.resolve();
                        context.report(INVALID, location,
                                String.format("Wrong format for %1$s: %2$s",
                                        name, t.getLocalizedMessage()), null);
                    }
                }
            }
            */
        }
    }

    /**
     * Returns true if two String.format conversions are "incompatible" (meaning that using these
     * two for the same argument across different translations is more likely an error than
     * intentional. Some conversions are incompatible, e.g. "d" and "s" where one is a number and
     * string, whereas others may work (e.g. float versus integer) but are probably not intentional.
     */
    private static boolean isIncompatible(char conversion1, char conversion2) {
        int class1 = getConversionClass(conversion1);
        int class2 = getConversionClass(conversion2);
        return class1 != class2
                && class1 != CONVERSION_CLASS_UNKNOWN
                && class2 != CONVERSION_CLASS_UNKNOWN;
    }

    private static final int CONVERSION_CLASS_UNKNOWN = 0;
    private static final int CONVERSION_CLASS_STRING = 1;
    private static final int CONVERSION_CLASS_CHARACTER = 2;
    private static final int CONVERSION_CLASS_INTEGER = 3;
    private static final int CONVERSION_CLASS_FLOAT = 4;
    private static final int CONVERSION_CLASS_BOOLEAN = 5;
    private static final int CONVERSION_CLASS_HASHCODE = 6;
    private static final int CONVERSION_CLASS_PERCENT = 7;
    private static final int CONVERSION_CLASS_NEWLINE = 8;
    private static final int CONVERSION_CLASS_DATETIME = 9;

    private static int getConversionClass(char conversion) {
        // See http://developer.android.com/reference/java/util/Formatter.html
        switch (conversion) {
            case 't': // Time/date conversion
            case 'T':
                return CONVERSION_CLASS_DATETIME;
            case 's': // string
            case 'S': // Uppercase string
                return CONVERSION_CLASS_STRING;
            case 'c': // character
            case 'C': // Uppercase character
                return CONVERSION_CLASS_CHARACTER;
            case 'd': // decimal
            case 'o': // octal
            case 'x': // hex
            case 'X':
                return CONVERSION_CLASS_INTEGER;
            case 'f': // decimal float
            case 'e': // exponential float
            case 'E':
            case 'g': // decimal or exponential depending on size
            case 'G':
            case 'a': // hex float
            case 'A':
                return CONVERSION_CLASS_FLOAT;
            case 'b': // boolean
            case 'B':
                return CONVERSION_CLASS_BOOLEAN;
            case 'h': // boolean
            case 'H':
                return CONVERSION_CLASS_HASHCODE;
            case '%': // literal
                return CONVERSION_CLASS_PERCENT;
            case 'n': // literal
                return CONVERSION_CLASS_NEWLINE;
        }

        return CONVERSION_CLASS_UNKNOWN;
    }

    private static Location refineLocation(
            Context context,
            Location location,
            String formatString,
            int substringStart,
            int substringEnd) {
        Position startLocation = location.getStart();
        Position endLocation = location.getEnd();
        if (startLocation != null && endLocation != null) {
            int startOffset = startLocation.getOffset();
            int endOffset = endLocation.getOffset();
            if (startOffset >= 0) {
                CharSequence contents = context.getClient().readFile(location.getFile());
                if (endOffset <= contents.length() && startOffset < endOffset) {
                    int formatOffset = indexOf(contents, formatString, startOffset);
                    if (formatOffset != -1 && formatOffset <= endOffset) {
                        return Location.create(
                                location.getFile(),
                                contents,
                                formatOffset + substringStart,
                                formatOffset + substringEnd);
                    }
                }
            }
        }

        return location;
    }

    /**
     * Check that the number of arguments in the format string is consistent across translations,
     * and that all arguments are used
     */
    private static void checkArity(Context context, String name, List<Pair<Handle, String>> list) {
        // Check to make sure that the argument counts and types are consistent
        int prevCount = -1;
        for (Pair<Handle, String> pair : list) {
            Set<Integer> indices = new HashSet<>();
            int count = getFormatArgumentCount(pair.getSecond(), indices);
            Handle handle = pair.getFirst();
            if (prevCount != -1 && prevCount != count) {
                Object clientData = handle.getClientData();
                if (clientData instanceof Node) {
                    if (context.getDriver().isSuppressed(null, ARG_COUNT, (Node) clientData)) {
                        return;
                    }
                }
                Location location = handle.resolve();
                Location secondary = list.get(0).getFirst().resolve();
                secondary.setMessage("Conflicting number of arguments here");
                location.setSecondary(secondary);
                String message =
                        String.format(
                                "Inconsistent number of arguments in formatting string `%1$s`; "
                                        + "found both %2$d and %3$d",
                                name, prevCount, count);
                context.report(ARG_COUNT, location, message);
                break;
            }

            for (int i = 1; i <= count; i++) {
                if (!indices.contains(i)) {
                    Object clientData = handle.getClientData();
                    if (clientData instanceof Node) {
                        if (context.getDriver().isSuppressed(null, ARG_COUNT, (Node) clientData)) {
                            return;
                        }
                    }

                    Set<Integer> all = new HashSet<>();
                    for (int j = 1; j < count; j++) {
                        all.add(j);
                    }
                    all.removeAll(indices);
                    List<Integer> sorted = new ArrayList<>(all);
                    Collections.sort(sorted);
                    Location location = handle.resolve();
                    String message =
                            String.format(
                                    "Formatting string '`%1$s`' is not referencing numbered arguments %2$s",
                                    name, sorted);
                    context.report(ARG_COUNT, location, message);
                    break;
                }
            }

            prevCount = count;
        }
    }

    // See java.util.Formatter docs
    public static final Pattern FORMAT =
            Pattern.compile(
                    // Generic format:
                    //   %[argument_index$][flags][width][.precision]conversion
                    //
                    "%"
                            +
                            // Argument Index
                            "(\\d+\\$)?"
                            +
                            // Flags
                            "([-+#, 0(<]*)?"
                            +
                            // Width
                            "(\\d+)?"
                            +
                            // Precision
                            "(\\.\\d+)?"
                            +
                            // Conversion. These are all a single character, except date/time conversions
                            // which take a prefix of t/T:
                            "([tT])?"
                            +
                            // The current set of conversion characters are
                            // b,h,s,c,d,o,x,e,f,g,a,t (as well as all those as upper-case characters), plus
                            // n for newlines and % as a literal %. And then there are all the time/date
                            // characters: HIKLm etc. Just match on all characters here since there should
                            // be at least one.
                            "([a-zA-Z%])");

    /** Given a format string returns the format type of the given argument */
    @VisibleForTesting
    @Nullable
    static String getFormatArgumentType(String s, int argument) {
        Matcher matcher = FORMAT.matcher(s);
        int index = 0;
        int prevIndex = 0;
        int nextNumber = 1;
        while (true) {
            if (matcher.find(index)) {
                String value = matcher.group(6);
                if ("%".equals(value) || "n".equals(value)) {
                    index = matcher.end();
                    continue;
                }
                int matchStart = matcher.start();
                // Make sure this is not an escaped '%'
                for (; prevIndex < matchStart; prevIndex++) {
                    char c = s.charAt(prevIndex);
                    if (c == '\\') {
                        prevIndex++;
                    }
                }
                if (prevIndex > matchStart) {
                    // We're in an escape, ignore this result
                    index = prevIndex;
                    continue;
                }

                // Shouldn't throw a number format exception since we've already
                // matched the pattern in the regexp
                int number;
                String numberString = matcher.group(1);
                if (numberString != null) {
                    // Strip off trailing $
                    numberString = numberString.substring(0, numberString.length() - 1);
                    number = Integer.parseInt(numberString);
                    nextNumber = number + 1;
                } else {
                    number = nextNumber++;
                }

                if (number == argument) {
                    return matcher.group(6);
                }
                index = matcher.end();
            } else {
                break;
            }
        }

        return null;
    }

    /**
     * Given a format string returns the number of required arguments. If the {@code seenArguments}
     * parameter is not null, put the indices of any observed arguments into it.
     */
    static int getFormatArgumentCount(@NonNull String s, @Nullable Set<Integer> seenArguments) {
        Matcher matcher = FORMAT.matcher(s);
        int index = 0;
        int prevIndex = 0;
        int nextNumber = 1;
        int max = 0;
        while (true) {
            if (matcher.find(index)) {
                String value = matcher.group(6);
                if ("%".equals(value) || "n".equals(value)) {
                    index = matcher.end();
                    continue;
                }
                int matchStart = matcher.start();
                // Make sure this is not an escaped '%'
                for (; prevIndex < matchStart; prevIndex++) {
                    char c = s.charAt(prevIndex);
                    if (c == '\\') {
                        prevIndex++;
                    }
                }
                if (prevIndex > matchStart) {
                    // We're in an escape, ignore this result
                    index = prevIndex;
                    continue;
                }

                // Shouldn't throw a number format exception since we've already
                // matched the pattern in the regexp
                int number;
                String numberString = matcher.group(1);
                if (numberString != null) {
                    // Strip off trailing $
                    numberString = numberString.substring(0, numberString.length() - 1);
                    number = Integer.parseInt(numberString);
                    nextNumber = number + 1;
                } else {
                    number = nextNumber++;
                }

                if (number > max) {
                    max = number;
                }
                if (seenArguments != null) {
                    seenArguments.add(number);
                }

                index = matcher.end();
            } else {
                break;
            }
        }

        return max;
    }

    /**
     * Determines whether the given {@link String#format(String, Object...)} formatting string is
     * "locale dependent", meaning that its output depends on the locale. This is the case if it for
     * example references decimal numbers of dates and times.
     *
     * @param format the format string
     * @return true if the format is locale sensitive, false otherwise
     */
    public static boolean isLocaleSpecific(@NonNull String format) {
        if (format.indexOf('%') == -1) {
            return false;
        }

        Matcher matcher = FORMAT.matcher(format);
        int index = 0;
        int prevIndex = 0;
        while (true) {
            if (matcher.find(index)) {
                int matchStart = matcher.start();
                // Make sure this is not an escaped '%'
                for (; prevIndex < matchStart; prevIndex++) {
                    char c = format.charAt(prevIndex);
                    if (c == '\\') {
                        prevIndex++;
                    }
                }
                if (prevIndex > matchStart) {
                    // We're in an escape, ignore this result
                    index = prevIndex;
                    continue;
                }

                String type = matcher.group(6);
                if (!type.isEmpty()) {
                    char t = type.charAt(0);

                    // The following formatting characters are locale sensitive:
                    switch (t) {
                        case 'd': // decimal integer
                        case 'e': // scientific
                        case 'E':
                        case 'f': // decimal float
                        case 'g': // general
                        case 'G':
                        case 't': // date/time
                        case 'T':
                            return true;
                    }
                }
                index = matcher.end();
            } else {
                break;
            }
        }

        return false;
    }

    @Override
    public List<String> getApplicableMethodNames() {
        return Arrays.asList(FORMAT_METHOD, GET_STRING_METHOD);
    }

    @Override
    public void visitMethodCall(
            @NonNull JavaContext context,
            @NonNull UCallExpression node,
            @NonNull PsiMethod method) {
        if (mFormatStrings == null && !context.getClient().supportsProjectResources()) {
            return;
        }

        JavaEvaluator evaluator = context.getEvaluator();
        String methodName = method.getName();
        if (methodName.equals(FORMAT_METHOD)) {
            if (evaluator.isMemberInClass(method, TYPE_STRING)) {
                // Check formatting parameters for
                //   java.lang.String#format(String format, Object... formatArgs)
                //   java.lang.String#format(Locale locale, String format, Object... formatArgs)
                checkStringFormatCall(
                        context, method, node, method.getParameterList().getParametersCount() == 3);

                // TODO: Consider also enforcing
                // java.util.Formatter#format(String string, Object... formatArgs)
            }
        } else {
            // Look up any of these string formatting methods:
            // android.content.res.Resources#getString(@StringRes int resId, Object... formatArgs)
            // android.content.Context#getString(@StringRes int resId, Object... formatArgs)
            // android.app.Fragment#getString(@StringRes int resId, Object... formatArgs)
            // android.support.v4.app.Fragment#getString(@StringRes int resId, Object... formatArgs)

            // Many of these also define a plain getString method:
            // android.content.res.Resources#getString(@StringRes int resId)
            // However, while it's possible that these contain formatting strings) it's
            // also possible that they're looking up strings that are not intended to be used
            // for formatting so while we may want to warn about this it's not necessarily
            // an error.
            if (method.getParameterList().getParametersCount() < 2) {
                return;
            }

            if (evaluator.isMemberInSubClassOf(method, CLASS_RESOURCES, false)
                    || evaluator.isMemberInSubClassOf(method, CLASS_CONTEXT, false)
                    || evaluator.isMemberInSubClassOf(method, CLASS_FRAGMENT, false)
                    || evaluator.isMemberInSubClassOf(method, CLASS_V4_FRAGMENT.oldName(), false)
                    || evaluator.isMemberInSubClassOf(method, CLASS_V4_FRAGMENT.newName(), false)) {
                checkStringFormatCall(context, method, node, false);
            }

            // TODO: Consider also looking up
            // android.content.res.Resources#getQuantityString(@PluralsRes int id, int quantity,
            //              Object... formatArgs)
            // though this will require being smarter about cross referencing formatting
            // strings since we'll need to go via the quantity string definitions
        }
    }

    /**
     * Checks a String.format call that is using a string that doesn't contain format placeholders.
     *
     * @param context the context to report errors to
     * @param call the AST node for the {@link String#format}
     * @param name the string name
     * @param handle the string location
     */
    private static void checkNotFormattedHandle(
            JavaContext context, UCallExpression call, String name, Handle handle) {
        Object clientData = handle.getClientData();
        if (clientData instanceof Node) {
            if (context.getDriver().isSuppressed(null, INVALID, (Node) clientData)) {
                return;
            }
        }
        Location location = context.getLocation(call);
        Location secondary = handle.resolve();
        secondary.setMessage("This definition does not require arguments");
        location.setSecondary(secondary);
        String message =
                String.format(
                        "Format string '`%1$s`' is not a valid format string so it should not be "
                                + "passed to `String.format`",
                        name);
        context.report(INVALID, call, location, message);
    }

    /**
     * Check the given String.format call (with the given arguments) to see if the string format is
     * being used correctly
     *
     * @param context the context to report errors to
     * @param calledMethod the method being called
     * @param call the AST node for the {@link String#format}
     * @param specifiesLocale whether the first parameter is a locale string, shifting the
     */
    private void checkStringFormatCall(
            JavaContext context,
            PsiMethod calledMethod,
            UCallExpression call,
            boolean specifiesLocale) {

        int argIndex = specifiesLocale ? 1 : 0;
        List<UExpression> args = call.getValueArguments();

        if (args.size() <= argIndex) {
            return;
        }

        UExpression argument = args.get(argIndex);
        ResourceUrl resource = ResourceEvaluator.getResource(context.getEvaluator(), argument);
        if (resource == null || resource.isFramework() || resource.type != ResourceType.STRING) {
            return;
        }

        String name = resource.name;
        if (mIgnoreStrings != null && mIgnoreStrings.contains(name)) {
            return;
        }

        boolean passingVarArgsArray = false;
        int callCount = args.size() - 1 - argIndex;

        if (callCount == 1) {
            // If instead of a varargs call like
            //    getString(R.string.foo, arg1, arg2, arg3)
            // the code is calling the varargs method with a packed Object array, as in
            //    getString(R.string.foo, new Object[] { arg1, arg2, arg3 })
            // we'll need to handle that such that we don't think this is a single
            // argument

            UExpression lastArg = args.get(args.size() - 1);
            PsiParameterList parameterList = calledMethod.getParameterList();
            int parameterCount = parameterList.getParametersCount();
            if (parameterCount > 0
                    && parameterList.getParameters()[parameterCount - 1].isVarArgs()) {
                boolean knownArity = false;

                boolean argWasReference = false;
                if (lastArg instanceof UReferenceExpression) {
                    PsiElement resolved = ((UReferenceExpression) lastArg).resolve();
                    if (resolved instanceof PsiVariable) {
                        UExpression initializer =
                                UastFacade.INSTANCE.getInitializerBody((PsiVariable) resolved);
                        if (initializer != null
                                && (UastExpressionUtils.isNewArray(initializer)
                                        || UastExpressionUtils.isArrayInitializer(initializer))) {
                            argWasReference = true;
                            // Now handled by check below
                            lastArg = initializer;
                        }
                    }
                }

                if (UastExpressionUtils.isNewArray(lastArg)
                        || UastExpressionUtils.isArrayInitializer(lastArg)) {
                    UCallExpression arrayInitializer = (UCallExpression) lastArg;

                    if (UastExpressionUtils.isNewArrayWithInitializer(lastArg)
                            || UastExpressionUtils.isArrayInitializer(lastArg)) {
                        callCount = arrayInitializer.getValueArgumentCount();
                        knownArity = true;
                    } else if (UastExpressionUtils.isNewArrayWithDimensions(lastArg)) {
                        List<UExpression> arrayDimensions = arrayInitializer.getValueArguments();
                        if (arrayDimensions.size() == 1) {
                            UExpression first = arrayDimensions.get(0);
                            if (first instanceof ULiteralExpression) {
                                Object o = ((ULiteralExpression) first).getValue();
                                if (o instanceof Integer) {
                                    callCount = (Integer) o;
                                    knownArity = true;
                                }
                            }
                        }
                    }
                    if (!knownArity) {
                        if (!argWasReference) {
                            return;
                        }
                    } else {
                        passingVarArgsArray = true;
                    }
                }
            }
        }

        if (callCount > 0 && mNotFormatStrings.containsKey(name)) {
            checkNotFormattedHandle(context, call, name, mNotFormatStrings.get(name));
            return;
        }

        List<Pair<Handle, String>> list = mFormatStrings != null ? mFormatStrings.get(name) : null;
        if (list == null) {
            LintClient client = context.getClient();
            if (client.supportsProjectResources()
                    && !context.getScope().contains(Scope.RESOURCE_FILE)) {
                ResourceRepository resources =
                        client.getResourceRepository(context.getMainProject(), true, false);
                List<ResourceItem> items;
                if (resources != null) {
                    items =
                            resources.getResources(
                                    ResourceNamespace.TODO(), ResourceType.STRING, name);
                } else {
                    // Must be a non-Android module
                    items = null;
                }
                if (items != null) {
                    for (final ResourceItem item : items) {
                        ResourceValue v = item.getResourceValue();
                        if (v != null) {
                            String value = v.getRawXmlValue();
                            // Attempt to resolve indirection
                            if (value == null) {
                                continue;
                            }
                            if (isReference(value)) {
                                // Only resolve a few indirections
                                for (int i = 0; i < 3; i++) {
                                    ResourceUrl url = ResourceUrl.parse(value);
                                    if (url == null || url.isFramework()) {
                                        break;
                                    }
                                    List<ResourceItem> l =
                                            resources.getResources(
                                                    ResourceNamespace.TODO(), url.type, url.name);
                                    if (l != null && !l.isEmpty()) {
                                        v = l.get(0).getResourceValue();
                                        if (v != null) {
                                            value = v.getValue();
                                            if (value == null || !isReference(value)) {
                                                break;
                                            }
                                        } else {
                                            break;
                                        }
                                    } else {
                                        break;
                                    }
                                }
                            }

                            if (value != null && !isReference(value)) {
                                // Make sure it's really a formatting string,
                                // not for example "Battery remaining: 90%"
                                boolean isFormattingString = value.indexOf('%') != -1;
                                for (int j = 0, m = value.length();
                                        j < m && isFormattingString;
                                        j++) {
                                    char c = value.charAt(j);
                                    if (c == '\\') {
                                        j++;
                                    } else if (c == '%') {
                                        Matcher matcher = FORMAT.matcher(value);
                                        if (!matcher.find(j)) {
                                            isFormattingString = false;
                                        } else {
                                            String conversion = matcher.group(6);
                                            int conversionClass =
                                                    getConversionClass(conversion.charAt(0));
                                            if (conversionClass == CONVERSION_CLASS_UNKNOWN
                                                    || matcher.group(5) != null) {
                                                // Some date format etc - don't process
                                                return;
                                            }
                                        }
                                        j++; // Don't process second % in a %%
                                    }
                                    // If the user marked the string with
                                }

                                Handle handle = client.createResourceItemHandle(item);
                                if (isFormattingString) {
                                    if (list == null) {
                                        list = Lists.newArrayList();
                                        if (mFormatStrings == null) {
                                            mFormatStrings = Maps.newHashMap();
                                        }
                                        mFormatStrings.put(name, list);
                                    }
                                    list.add(Pair.of(handle, value));
                                } else if (callCount > 0) {
                                    checkNotFormattedHandle(context, call, name, handle);
                                }
                            }
                        }
                    }
                }
            } else {
                return;
            }
        }

        if (list != null) {
            Set<String> reported = null;
            for (Pair<Handle, String> pair : list) {
                String s = pair.getSecond();
                if (reported != null && reported.contains(s)) {
                    continue;
                }
                int count = getFormatArgumentCount(s, null);
                Handle handle = pair.getFirst();
                if (count != callCount) {
                    Location location = context.getLocation(call);
                    Location secondary = handle.resolve();
                    secondary.setMessage(
                            String.format("This definition requires %1$d arguments", count));
                    location.setSecondary(secondary);
                    String message =
                            String.format(
                                    "Wrong argument count, format string `%1$s` requires `%2$d` but format "
                                            + "call supplies `%3$d`",
                                    name, count, callCount);
                    context.report(ARG_TYPES, call, location, message);
                    if (reported == null) {
                        reported = Sets.newHashSet();
                    }
                    reported.add(s);
                } else {
                    if (passingVarArgsArray) {
                        // Can't currently check these: make sure we don't incorrectly
                        // flag parameters on the Object[] instead of the wrapped parameters
                        return;
                    }
                    for (int i = 1; i <= count; i++) {
                        int argumentIndex = i + argIndex;
                        PsiType type = args.get(argumentIndex).getExpressionType();
                        if (type != null) {
                            boolean valid = true;
                            String formatType = getFormatArgumentType(s, i);
                            if (formatType == null) {
                                continue;
                            }
                            char last = formatType.charAt(formatType.length() - 1);
                            if (formatType.length() >= 2
                                    && Character.toLowerCase(
                                                    formatType.charAt(formatType.length() - 2))
                                            == 't') {
                                // Date time conversion.
                                // TODO
                                continue;
                            }
                            switch (last) {
                                    // Booleans. It's okay to pass objects to these;
                                    // it will print "true" if non-null, but it's
                                    // unusual and probably not intended.
                                case 'b':
                                case 'B':
                                    valid = isBooleanType(type);
                                    break;

                                    // Numeric: integer and floats in various formats
                                case 'x':
                                case 'X':
                                case 'd':
                                case 'o':
                                case 'e':
                                case 'E':
                                case 'f':
                                case 'g':
                                case 'G':
                                case 'a':
                                case 'A':
                                    valid = isNumericType(type, true);
                                    break;
                                case 'c':
                                case 'C':
                                    // Unicode character
                                    valid = isCharacterType(type);
                                    break;
                                case 'h':
                                case 'H': // Hex print of hash code of objects
                                    // From https://developer.android.com/reference/java/util/Formatter.html
                                    // """The following general conversions may be applied to any
                                    // argument type: 'b', 'B', 'h', 'H', 's', 'S' """
                                    // We'll still warn about %s since you may have intended
                                    // numeric formatting, but hex printing seems pretty well
                                    // intended.
                                    continue;
                                case 's':
                                case 'S':
                                    // String. Can pass anything, but warn about
                                    // numbers since you may have meant more
                                    // specific formatting. Use special issue
                                    // explanation for this?
                                    valid = !isBooleanType(type) && !isNumericType(type, false);
                                    break;
                            }

                            if (!valid) {
                                Location location = context.getLocation(args.get(argumentIndex));
                                Location secondary = handle.resolve();
                                secondary.setMessage("Conflicting argument declaration here");
                                location.setSecondary(secondary);
                                String suggestion = null;
                                if (isBooleanType(type)) {
                                    suggestion = "`b`";
                                } else if (isCharacterType(type)) {
                                    suggestion = "'c'";
                                } else if (PsiType.INT.equals(type)
                                        || PsiType.LONG.equals(type)
                                        || PsiType.BYTE.equals(type)
                                        || PsiType.SHORT.equals(type)) {
                                    suggestion = "`d`, 'o' or `x`";
                                } else if (PsiType.FLOAT.equals(type)
                                        || PsiType.DOUBLE.equals(type)) {
                                    suggestion = "`e`, 'f', 'g' or `a`";
                                } else if (type instanceof PsiClassType) {
                                    String fqn = type.getCanonicalText();
                                    if (TYPE_INTEGER_WRAPPER.equals(fqn)
                                            || TYPE_LONG_WRAPPER.equals(fqn)
                                            || TYPE_BYTE_WRAPPER.equals(fqn)
                                            || TYPE_SHORT_WRAPPER.equals(fqn)) {
                                        suggestion = "`d`, 'o' or `x`";
                                    } else if (TYPE_FLOAT_WRAPPER.equals(fqn)
                                            || TYPE_DOUBLE_WRAPPER.equals(fqn)) {
                                        suggestion = "`d`, 'o' or `x`";
                                    } else if (TYPE_OBJECT.equals(fqn)) {
                                        suggestion = "'s' or 'h'";
                                    }
                                }

                                if (suggestion != null) {
                                    suggestion =
                                            " (Did you mean formatting character "
                                                    + suggestion
                                                    + "?)";
                                } else {
                                    suggestion = "";
                                }

                                String canonicalText = type.getCanonicalText();
                                canonicalText =
                                        canonicalText.substring(canonicalText.lastIndexOf('.') + 1);

                                String message =
                                        String.format(
                                                "Wrong argument type for formatting argument '#%1$d' "
                                                        + "in `%2$s`: conversion is '`%3$s`', received `%4$s` "
                                                        + "(argument #%5$d in method call)%6$s",
                                                i,
                                                name,
                                                formatType,
                                                canonicalText,
                                                argumentIndex + 1,
                                                suggestion);

                                if ((last == 's' || last == 'S') && isNumericType(type, false)) {
                                    message =
                                            String.format(
                                                    "Suspicious argument type for formatting argument #%1$d "
                                                            + "in `%2$s`: conversion is `%3$s`, received `%4$s` "
                                                            + "(argument #%5$d in method call)%6$s",
                                                    i,
                                                    name,
                                                    formatType,
                                                    canonicalText,
                                                    argumentIndex + 1,
                                                    suggestion);
                                }

                                context.report(ARG_TYPES, call, location, message);
                                if (reported == null) {
                                    reported = Sets.newHashSet();
                                }
                                reported.add(s);
                            }
                        }
                    }
                }
            }
        }
    }

    private static boolean isCharacterType(PsiType type) {
        //return PsiType.CHAR.isAssignableFrom(type);
        if (type == PsiType.CHAR) {
            return true;
        }
        if (type instanceof PsiClassType) {
            String fqn = type.getCanonicalText();
            return TYPE_CHARACTER_WRAPPER.equals(fqn);
        }

        return false;
    }

    private static boolean isBooleanType(PsiType type) {
        //return PsiType.BOOLEAN.isAssignableFrom(type);
        if (type == PsiType.BOOLEAN) {
            return true;
        }
        if (type instanceof PsiClassType) {
            String fqn = type.getCanonicalText();
            return TYPE_BOOLEAN_WRAPPER.equals(fqn);
        }

        return false;
    }

    //PsiType:java.lang.Boolean
    private static boolean isNumericType(@NonNull PsiType type, boolean allowBigNumbers) {
        if (PsiType.INT.equals(type)
                || PsiType.FLOAT.equals(type)
                || PsiType.DOUBLE.equals(type)
                || PsiType.LONG.equals(type)
                || PsiType.BYTE.equals(type)
                || PsiType.SHORT.equals(type)) {
            return true;
        }

        if (type instanceof PsiClassType) {
            String fqn = type.getCanonicalText();
            if (TYPE_INTEGER_WRAPPER.equals(fqn)
                    || TYPE_FLOAT_WRAPPER.equals(fqn)
                    || TYPE_DOUBLE_WRAPPER.equals(fqn)
                    || TYPE_LONG_WRAPPER.equals(fqn)
                    || TYPE_BYTE_WRAPPER.equals(fqn)
                    || TYPE_SHORT_WRAPPER.equals(fqn)) {
                return true;
            }
            if (allowBigNumbers) {
                if ("java.math.BigInteger".equals(fqn) || "java.math.BigDecimal".equals(fqn)) {
                    return true;
                }
            }
        }

        return false;
    }
}
