<commit_before>////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2016 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle.checks;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.beanutils.ConversionException;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.AuditEvent;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;

/**
 * Maintains a set of check suppressions from {@link SuppressWarnings}
 * annotations.
 * @author <NAME>
 * @author <NAME>
 */
public class SuppressWarningsHolder
    extends AbstractCheck {

    /**
     * A key is pointing to the warning message text in "messages.properties"
     * file.
     */
    public static final String MSG_KEY = "suppress.warnings.invalid.target";

    /**
     * Optional prefix for warning suppressions that are only intended to be
     * recognized by checkstyle. For instance, to suppress {@code
     * FallThroughCheck} only in checkstyle (and not in javac), use the
     * suppression {@code "checkstyle:fallthrough"} or {@code "checkstyle:FallThrough"}.
     * To suppress the warning in both tools, just use {@code "fallthrough"}.
     */
    public static final String CHECKSTYLE_PREFIX = "checkstyle:";

    /** Java.lang namespace prefix, which is stripped from SuppressWarnings */
    private static final String JAVA_LANG_PREFIX = "java.lang.";

    /** Suffix to be removed from subclasses of Check. */
    private static final String CHECK_SUFFIX = "Check";

    /** Special warning id for matching all the warnings. */
    private static final String ALL_WARNING_MATCHING_ID = "all";

    /** A map from check source names to suppression aliases. */
    private static final Map<String, String> CHECK_ALIAS_MAP = new HashMap<>();

    /**
     * A thread-local holder for the list of suppression entries for the last
     * file parsed.
     */
    private static final ThreadLocal<List<Entry>> ENTRIES = new ThreadLocal<>();

    /**
     * Returns the default alias for the source name of a check, which is the
     * source name in lower case with any dotted prefix or "Check" suffix
     * removed.
     * @param sourceName the source name of the check (generally the class
     *        name)
     * @return the default alias for the given check
     */
    public static String getDefaultAlias(String sourceName) {
        final int startIndex = sourceName.lastIndexOf('.') + 1;
        int endIndex = sourceName.length();
        if (sourceName.endsWith(CHECK_SUFFIX)) {
            endIndex -= CHECK_SUFFIX.length();
        }
        return sourceName.substring(startIndex, endIndex).toLowerCase(Locale.ENGLISH);
    }

    /**
     * Returns the alias for the source name of a check. If an alias has been
     * explicitly registered via {@link #registerAlias(String, String)}, that
     * alias is returned; otherwise, the default alias is used.
     * @param sourceName the source name of the check (generally the class
     *        name)
     * @return the current alias for the given check
     */
    public static String getAlias(String sourceName) {
        String checkAlias = CHECK_ALIAS_MAP.get(sourceName);
        if (checkAlias == null) {
            checkAlias = getDefaultAlias(sourceName);
        }
        return checkAlias;
    }

    /**
     * Registers an alias for the source name of a check.
     * @param sourceName the source name of the check (generally the class
     *        name)
     * @param checkAlias the alias used in {@link SuppressWarnings} annotations
     */
    public static void registerAlias(String sourceName, String checkAlias) {
        CHECK_ALIAS_MAP.put(sourceName, checkAlias);
    }

    /**
     * Registers a list of source name aliases based on a comma-separated list
     * of {@code source=alias} items, such as {@code
     * com.puppycrawl.tools.checkstyle.checks.sizes.ParameterNumberCheck=
     * paramnum}.
     * @param aliasList the list of comma-separated alias assignments
     */
    public void setAliasList(String aliasList) {
        for (String sourceAlias : aliasList.split(",")) {
            final int index = sourceAlias.indexOf('=');
            if (index > 0) {
                registerAlias(sourceAlias.substring(0, index), sourceAlias
                    .substring(index + 1));
            }
            else if (!sourceAlias.isEmpty()) {
                throw new ConversionException(
                    "'=' expected in alias list item: " + sourceAlias);
            }
        }
    }

    /**
     * Checks for a suppression of a check with the given source name and
     * location in the last file processed.
     * @param event audit event.
     * @return whether the check with the given name is suppressed at the given
     *         source location
     */
    public static boolean isSuppressed(AuditEvent event) {
        final List<Entry> entries = ENTRIES.get();
        final String sourceName = event.getSourceName();
        final String checkAlias = getAlias(sourceName);
        final int line = event.getLine();
        final int column = event.getColumn();
        boolean suppressed = false;
        for (Entry entry : entries) {
            final boolean afterStart =
                entry.getFirstLine() < line
                    || entry.getFirstLine() == line
                            && (column == 0 || entry.getFirstColumn() <= column);
            final boolean beforeEnd =
                entry.getLastLine() > line
                    || entry.getLastLine() == line && entry
                        .getLastColumn() >= column;
            final boolean nameMatches =
                ALL_WARNING_MATCHING_ID.equals(entry.getCheckName())
                    || entry.getCheckName().equalsIgnoreCase(checkAlias);
            final boolean idMatches = event.getModuleId() != null
                && event.getModuleId().equals(entry.getCheckName());
            if (afterStart && beforeEnd && (nameMatches || idMatches)) {
                suppressed = true;
            }
        }
        return suppressed;
    }

    @Override
    public int[] getDefaultTokens() {
        return getAcceptableTokens();
    }

    @Override
    public int[] getAcceptableTokens() {
        return new int[] {TokenTypes.ANNOTATION};
    }

    @Override
    public int[] getRequiredTokens() {
        return getAcceptableTokens();
    }

    @Override
    public void beginTree(DetailAST rootAST) {
        ENTRIES.set(new LinkedList<Entry>());
    }

    @Override
    public void visitToken(DetailAST ast) {
        // check whether annotation is SuppressWarnings
        // expected children: AT ( IDENT | DOT ) LPAREN <values> RPAREN<commit_msg>Issue #2218: Move initialization of suppressions list in SuppressWarningsHolder<commit_after>////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2016 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle.checks;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.beanutils.ConversionException;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.AuditEvent;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;

/**
 * Maintains a set of check suppressions from {@link SuppressWarnings}
 * annotations.
 * @author <NAME>
 * @author <NAME>
 */
public class SuppressWarningsHolder
    extends AbstractCheck {

    /**
     * A key is pointing to the warning message text in "messages.properties"
     * file.
     */
    public static final String MSG_KEY = "suppress.warnings.invalid.target";

    /**
     * Optional prefix for warning suppressions that are only intended to be
     * recognized by checkstyle. For instance, to suppress {@code
     * FallThroughCheck} only in checkstyle (and not in javac), use the
     * suppression {@code "checkstyle:fallthrough"} or {@code "checkstyle:FallThrough"}.
     * To suppress the warning in both tools, just use {@code "fallthrough"}.
     */
    public static final String CHECKSTYLE_PREFIX = "checkstyle:";

    /** Java.lang namespace prefix, which is stripped from SuppressWarnings */
    private static final String JAVA_LANG_PREFIX = "java.lang.";

    /** Suffix to be removed from subclasses of Check. */
    private static final String CHECK_SUFFIX = "Check";

    /** Special warning id for matching all the warnings. */
    private static final String ALL_WARNING_MATCHING_ID = "all";

    /** A map from check source names to suppression aliases. */
    private static final Map<String, String> CHECK_ALIAS_MAP = new HashMap<>();

    /**
     * A thread-local holder for the list of suppression entries for the last
     * file parsed.
     */
    private static final ThreadLocal<List<Entry>> ENTRIES = new ThreadLocal<List<Entry>>() {
        @Override
        protected List<Entry> initialValue() {
            return new LinkedList<>();
        }
    };

    /**
     * Returns the default alias for the source name of a check, which is the
     * source name in lower case with any dotted prefix or "Check" suffix
     * removed.
     * @param sourceName the source name of the check (generally the class
     *        name)
     * @return the default alias for the given check
     */
    public static String getDefaultAlias(String sourceName) {
        final int startIndex = sourceName.lastIndexOf('.') + 1;
        int endIndex = sourceName.length();
        if (sourceName.endsWith(CHECK_SUFFIX)) {
            endIndex -= CHECK_SUFFIX.length();
        }
        return sourceName.substring(startIndex, endIndex).toLowerCase(Locale.ENGLISH);
    }

    /**
     * Returns the alias for the source name of a check. If an alias has been
     * explicitly registered via {@link #registerAlias(String, String)}, that
     * alias is returned; otherwise, the default alias is used.
     * @param sourceName the source name of the check (generally the class
     *        name)
     * @return the current alias for the given check
     */
    public static String getAlias(String sourceName) {
        String checkAlias = CHECK_ALIAS_MAP.get(sourceName);
        if (checkAlias == null) {
            checkAlias = getDefaultAlias(sourceName);
        }
        return checkAlias;
    }

    /**
     * Registers an alias for the source name of a check.
     * @param sourceName the source name of the check (generally the class
     *        name)
     * @param checkAlias the alias used in {@link SuppressWarnings} annotations
     */
    public static void registerAlias(String sourceName, String checkAlias) {
        CHECK_ALIAS_MAP.put(sourceName, checkAlias);
    }

    /**
     * Registers a list of source name aliases based on a comma-separated list
     * of {@code source=alias} items, such as {@code
     * com.puppycrawl.tools.checkstyle.checks.sizes.ParameterNumberCheck=
     * paramnum}.
     * @param aliasList the list of comma-separated alias assignments
     */
    public void setAliasList(String aliasList) {
        for (String sourceAlias : aliasList.split(",")) {
            final int index = sourceAlias.indexOf('=');
            if (index > 0) {
                registerAlias(sourceAlias.substring(0, index), sourceAlias
                    .substring(index + 1));
            }
            else if (!sourceAlias.isEmpty()) {
                throw new ConversionException(
                    "'=' expected in alias list item: " + sourceAlias);
            }
        }
    }

    /**
     * Checks for a suppression of a check with the given source name and
     * location in the last file processed.
     * @param event audit event.
     * @return whether the check with the given name is suppressed at the given
     *         source location
     */
    public static boolean isSuppressed(AuditEvent event) {
        final List<Entry> entries = ENTRIES.get();
        final String sourceName = event.getSourceName();
        final String checkAlias = getAlias(sourceName);
        final int line = event.getLine();
        final int column = event.getColumn();
        boolean suppressed = false;
        for (Entry entry : entries) {
            final boolean afterStart =
                entry.getFirstLine() < line
                    || entry.getFirstLine() == line
                            && (column == 0 || entry.getFirstColumn() <= column);
            final boolean beforeEnd =
                entry.getLastLine() > line
                    || entry.getLastLine() == line && entry
                        .getLastColumn() >= column;
            final boolean nameMatches =
                ALL_WARNING_MATCHING_ID.equals(entry.getCheckName())
                    || entry.getCheckName().equalsIgnoreCase(checkAlias);
            final boolean idMatches = event.getModuleId() != null
                && event.getModuleId().equals(entry.getCheckName());
            if (afterStart && beforeEnd && (nameMatches || idMatches)) {
                suppressed = true;
            }
        }
        return suppressed;
    }

    @Override
    public int[] getDefaultTokens() {
        return getAcceptableTokens();
    }

    @Override
    public int[] getAcceptableTokens() {
        return new int[] {TokenTypes.ANNOTATION};
    }

    @Override
    public int[] getRequiredTokens() {
        return getAcceptableTokens();
    }

    @Override
    public void beginTree(DetailAST rootAST) {
        ENTRIES.get().clear();
    }

    @Override
    public void visitToken(DetailAST ast) {
        // check whether annotation is SuppressWarnings
        // expected children: AT ( IDENT | DOT ) LPAREN <values> RPAREN
{'fraction_non_alphanumeric': 0.1081267217630854, 'fraction_numerical': 0.003881793137991485, 'mean_word_length': 2.391295116772824, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4377853', 'n_tokens_mistral': 4174, 'n_tokens_neox': 4019, 'n_words': 1457}