diff options
Diffstat (limited to 'src/main')
69 files changed, 952 insertions, 240 deletions
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/Checker.java b/src/main/java/com/puppycrawl/tools/checkstyle/Checker.java index 80cff6205..9ecc9eff1 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/Checker.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/Checker.java @@ -413,7 +413,7 @@ public class Checker extends AutomaticBean implements MessageDispatcher, RootMod } @Override - public void finishLocalSetup() throws CheckstyleException { + protected void finishLocalSetup() throws CheckstyleException { final Locale locale = new Locale(localeLanguage, localeCountry); LocalizedMessage.setLocale(locale); diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java b/src/main/java/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java index c37302c5f..059e93c98 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/ConfigurationLoader.java @@ -40,7 +40,6 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; -import com.puppycrawl.tools.checkstyle.api.AbstractLoader; import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.Configuration; import com.puppycrawl.tools.checkstyle.api.SeverityLevel; @@ -76,7 +75,7 @@ public final class ConfigurationLoader { "-//Puppy Crawl//DTD Check Configuration 1.0//EN"; /** The resource for version 1_0 of the configuration dtd. */ - private static final String DTD_RESOURCE_NAME_1_0 = + private static final String DTD_CONFIGURATION_NAME_1_0 = "com/puppycrawl/tools/checkstyle/configuration_1_0.dtd"; /** The public ID for version 1_1 of the configuration dtd. */ @@ -84,7 +83,7 @@ public final class ConfigurationLoader { "-//Puppy Crawl//DTD Check Configuration 1.1//EN"; /** The resource for version 1_1 of the configuration dtd. */ - private static final String DTD_RESOURCE_NAME_1_1 = + private static final String DTD_CONFIGURATION_NAME_1_1 = "com/puppycrawl/tools/checkstyle/configuration_1_1.dtd"; /** The public ID for version 1_2 of the configuration dtd. */ @@ -92,7 +91,7 @@ public final class ConfigurationLoader { "-//Puppy Crawl//DTD Check Configuration 1.2//EN"; /** The resource for version 1_2 of the configuration dtd. */ - private static final String DTD_RESOURCE_NAME_1_2 = + private static final String DTD_CONFIGURATION_NAME_1_2 = "com/puppycrawl/tools/checkstyle/configuration_1_2.dtd"; /** The public ID for version 1_3 of the configuration dtd. */ @@ -100,7 +99,7 @@ public final class ConfigurationLoader { "-//Puppy Crawl//DTD Check Configuration 1.3//EN"; /** The resource for version 1_3 of the configuration dtd. */ - private static final String DTD_RESOURCE_NAME_1_3 = + private static final String DTD_CONFIGURATION_NAME_1_3 = "com/puppycrawl/tools/checkstyle/configuration_1_3.dtd"; /** Prefix for the exception when unable to parse resource. */ @@ -166,10 +165,10 @@ public final class ConfigurationLoader { */ private static Map<String, String> createIdToResourceNameMap() { final Map<String, String> map = new HashMap<>(); - map.put(DTD_PUBLIC_ID_1_0, DTD_RESOURCE_NAME_1_0); - map.put(DTD_PUBLIC_ID_1_1, DTD_RESOURCE_NAME_1_1); - map.put(DTD_PUBLIC_ID_1_2, DTD_RESOURCE_NAME_1_2); - map.put(DTD_PUBLIC_ID_1_3, DTD_RESOURCE_NAME_1_3); + map.put(DTD_PUBLIC_ID_1_0, DTD_CONFIGURATION_NAME_1_0); + map.put(DTD_PUBLIC_ID_1_1, DTD_CONFIGURATION_NAME_1_1); + map.put(DTD_PUBLIC_ID_1_2, DTD_CONFIGURATION_NAME_1_2); + map.put(DTD_PUBLIC_ID_1_3, DTD_CONFIGURATION_NAME_1_3); return map; } @@ -224,7 +223,7 @@ public final class ConfigurationLoader { * 'ignore' should be omitted, {@code false} otherwise * @return the check configurations * @throws CheckstyleException if an error occurs - * @deprecated in order to fullfil demands of BooleanParameter IDEA check. + * @deprecated in order to fulfill demands of BooleanParameter IDEA check. * @noinspection BooleanParameter */ @Deprecated @@ -245,7 +244,7 @@ public final class ConfigurationLoader { * @param threadModeSettings the thread mode configuration * @return the check configurations * @throws CheckstyleException if an error occurs - * @deprecated in order to fullfil demands of BooleanParameter IDEA check. + * @deprecated in order to fulfill demands of BooleanParameter IDEA check. * @noinspection BooleanParameter, WeakerAccess */ @Deprecated @@ -297,7 +296,7 @@ public final class ConfigurationLoader { * 'ignore' should be omitted, {@code false} otherwise * @return the check configurations * @throws CheckstyleException if an error occurs - * @deprecated in order to fullfil demands of BooleanParameter IDEA check. + * @deprecated in order to fulfill demands of BooleanParameter IDEA check. * @noinspection BooleanParameter */ @Deprecated @@ -320,7 +319,7 @@ public final class ConfigurationLoader { * @param threadModeSettings the thread mode configuration * @return the check configurations * @throws CheckstyleException if an error occurs - * @deprecated in order to fullfil demands of BooleanParameter IDEA check. + * @deprecated in order to fulfill demands of BooleanParameter IDEA check. * @noinspection BooleanParameter, WeakerAccess */ @Deprecated @@ -580,7 +579,7 @@ public final class ConfigurationLoader { * appear in the public API of the ConfigurationLoader. */ private final class InternalLoader - extends AbstractLoader { + extends XmlLoader { /** Module elements. */ private static final String MODULE = "module"; /** Name attribute. */ diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/DefaultLogger.java b/src/main/java/com/puppycrawl/tools/checkstyle/DefaultLogger.java index e110b0229..23cd2ff83 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/DefaultLogger.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/DefaultLogger.java @@ -28,6 +28,7 @@ import java.nio.charset.StandardCharsets; import com.puppycrawl.tools.checkstyle.api.AuditEvent; import com.puppycrawl.tools.checkstyle.api.AuditListener; import com.puppycrawl.tools.checkstyle.api.AutomaticBean; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.LocalizedMessage; import com.puppycrawl.tools.checkstyle.api.SeverityLevel; @@ -77,7 +78,7 @@ public class DefaultLogger extends AutomaticBean implements AuditListener { * Creates a new {@code DefaultLogger} instance. * @param outputStream where to log infos and errors * @param closeStreamsAfterUse if oS should be closed in auditFinished() - * @deprecated in order to fullfil demands of BooleanParameter IDEA check. + * @deprecated in order to fulfill demands of BooleanParameter IDEA check. * @noinspection BooleanParameter */ @Deprecated @@ -92,7 +93,7 @@ public class DefaultLogger extends AutomaticBean implements AuditListener { * @param closeInfoAfterUse auditFinished should close infoStream. * @param errorStream the {@code OutputStream} for error messages. * @param closeErrorAfterUse auditFinished should close errorStream - * @deprecated in order to fullfil demands of BooleanParameter IDEA check. + * @deprecated in order to fulfill demands of BooleanParameter IDEA check. * @noinspection BooleanParameter */ @Deprecated @@ -112,7 +113,7 @@ public class DefaultLogger extends AutomaticBean implements AuditListener { * @param errorStream the {@code OutputStream} for error messages * @param closeErrorAfterUse auditFinished should close errorStream * @param messageFormatter formatter for the log message. - * @deprecated in order to fullfil demands of BooleanParameter IDEA check. + * @deprecated in order to fulfill demands of BooleanParameter IDEA check. * @noinspection BooleanParameter, WeakerAccess */ @Deprecated @@ -193,6 +194,11 @@ public class DefaultLogger extends AutomaticBean implements AuditListener { formatter = messageFormatter; } + @Override + protected void finishLocalSetup() throws CheckstyleException { + // No code by default + } + /** * Print an Emacs compliant line on the error stream. * If the column number is non zero, then also display it. diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/FileStatefulCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/FileStatefulCheck.java index 7f4c60e77..2c67438d4 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/FileStatefulCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/FileStatefulCheck.java @@ -34,7 +34,7 @@ import java.lang.annotation.Target; * Checker guarantees that each check instance processes only one file at the same time. * Checker guarantees that all check instances have equal (but not the same) configuration. * It means, that if a check holds a property of type "array of strings", - * the property value will not be shared accross check instances. + * the property value will not be shared across check instances. * Instead, each check instance will hold its own array instance. * Checker does not guarantee that each file will have it's own thread - * there might be a list of files, which will be executed on the same thread. diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/GlobalStatefulCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/GlobalStatefulCheck.java index 52cc1f185..9fd6d7408 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/GlobalStatefulCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/GlobalStatefulCheck.java @@ -35,7 +35,7 @@ import java.lang.annotation.Target; * The check methods and fields should be thread safe, because they may be accessed from others * threads at the same time. * Checker guarantees that there will be exactly one check instance - * This is simular to multi-file validation, which checkstyle does not support fully yet. + * This is similar to multi-file validation, which checkstyle does not support fully yet. * Please refer to https://github.com/checkstyle/checkstyle/issues/3540 for details. * @author Andrew Kuchev * @noinspection AnnotationClass, ClassIndependentOfModule, unused diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/PackageNamesLoader.java b/src/main/java/com/puppycrawl/tools/checkstyle/PackageNamesLoader.java index 4c5cf4efd..9b6b0cc57 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/PackageNamesLoader.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/PackageNamesLoader.java @@ -37,7 +37,6 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.google.common.io.Closeables; -import com.puppycrawl.tools.checkstyle.api.AbstractLoader; import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; @@ -46,7 +45,7 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtils; * @author Rick Giles */ public final class PackageNamesLoader - extends AbstractLoader { + extends XmlLoader { /** The public ID for the configuration dtd. */ private static final String DTD_PUBLIC_ID = "-//Puppy Crawl//DTD Package Names 1.0//EN"; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/PackageObjectFactory.java b/src/main/java/com/puppycrawl/tools/checkstyle/PackageObjectFactory.java index 2465edcab..630709739 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/PackageObjectFactory.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/PackageObjectFactory.java @@ -55,7 +55,7 @@ public class PackageObjectFactory implements ModuleFactory { */ public enum ModuleLoadOption { /** - * Searching from registred checkstyle modules and from packages given in countructor. + * Searching from registered checkstyle modules and from packages given in constructor. **/ SEARCH_REGISTERED_PACKAGES, /** @@ -73,7 +73,7 @@ public class PackageObjectFactory implements ModuleFactory { public static final String UNABLE_TO_INSTANTIATE_EXCEPTION_MESSAGE = "PackageObjectFactory.unableToInstantiateExceptionMessage"; - /** Exception message when there is ambigugous module name in config file. */ + /** Exception message when there is ambiguous module name in config file. */ public static final String AMBIGUOUS_MODULE_NAME_EXCEPTION_MESSAGE = "PackageObjectFactory.ambiguousModuleNameExceptionMessage"; @@ -354,7 +354,7 @@ public class PackageObjectFactory implements ModuleFactory { } /** - * Searching to class with given name (or name concatinated with "Check") in existing + * Searching to class with given name (or name concatenated with "Check") in existing * packages. Returns instance if class found or, otherwise, null. * @param name the name of a class. * @return the {@code Object} created by loader. @@ -820,6 +820,8 @@ public class PackageObjectFactory implements ModuleFactory { BASE_PACKAGE + ".filters.IntRangeFilter"); NAME_TO_FULL_MODULE_NAME.put("SeverityMatchFilter", BASE_PACKAGE + ".filters.SeverityMatchFilter"); + NAME_TO_FULL_MODULE_NAME.put("SuppressWithPlainTextCommentFilter", + BASE_PACKAGE + ".filters.SuppressWithPlainTextCommentFilter"); NAME_TO_FULL_MODULE_NAME.put("SuppressionCommentFilter", BASE_PACKAGE + ".filters.SuppressionCommentFilter"); NAME_TO_FULL_MODULE_NAME.put("SuppressionFilter", diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/PropertyCacheFile.java b/src/main/java/com/puppycrawl/tools/checkstyle/PropertyCacheFile.java index 2a0ae4dc2..cd42699dd 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/PropertyCacheFile.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/PropertyCacheFile.java @@ -239,7 +239,7 @@ final class PropertyCacheFile { /** * Serializes object to output stream. - * @param object object to be erialized + * @param object object to be serialized * @param outputStream serialization stream * @throws IOException if an error occurs */ diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalkerAuditEvent.java b/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalkerAuditEvent.java index 629c680f6..a881efb6c 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalkerAuditEvent.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalkerAuditEvent.java @@ -105,6 +105,14 @@ public class TreeWalkerAuditEvent { } /** + * Gets the column char index associated with the message. + * @return the column char index associated with the message + */ + public int getColumnCharIndex() { + return localizedMessage.getColumnCharIndex(); + } + + /** * Returns id of module. * @return the identifier of the module that generated the event. Can return * null. diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/XMLLogger.java b/src/main/java/com/puppycrawl/tools/checkstyle/XMLLogger.java index 0a0095418..10037c524 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/XMLLogger.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/XMLLogger.java @@ -35,6 +35,7 @@ import java.util.concurrent.ConcurrentHashMap; import com.puppycrawl.tools.checkstyle.api.AuditEvent; import com.puppycrawl.tools.checkstyle.api.AuditListener; import com.puppycrawl.tools.checkstyle.api.AutomaticBean; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.SeverityLevel; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; @@ -81,7 +82,7 @@ public class XMLLogger * Sets the output to a defined stream. * @param outputStream the stream to write logs to. * @param closeStream close oS in auditFinished - * @deprecated in order to fullfil demands of BooleanParameter IDEA check. + * @deprecated in order to fulfill demands of BooleanParameter IDEA check. * @noinspection BooleanParameter */ @Deprecated @@ -102,6 +103,11 @@ public class XMLLogger } @Override + protected void finishLocalSetup() throws CheckstyleException { + // No code by default + } + + @Override public void auditStarted(AuditEvent event) { writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); @@ -115,8 +121,6 @@ public class XMLLogger @Override public void auditFinished(AuditEvent event) { - fileMessages.forEach(this::writeFileMessages); - writer.println("</checkstyle>"); if (closeStream) { writer.close(); @@ -180,21 +184,20 @@ public class XMLLogger public void addError(AuditEvent event) { if (event.getSeverityLevel() != SeverityLevel.IGNORE) { final String fileName = event.getFileName(); - if (fileName == null) { + if (fileName == null || !fileMessages.containsKey(fileName)) { synchronized (writerLock) { writeFileError(event); } } else { - final FileMessages messages = fileMessages.computeIfAbsent( - fileName, name -> new FileMessages()); + final FileMessages messages = fileMessages.get(fileName); messages.addError(event); } } } /** - * Outputs the given envet to the writer. + * Outputs the given event to the writer. * @param event An event to print. */ private void writeFileError(AuditEvent event) { @@ -221,14 +224,13 @@ public class XMLLogger @Override public void addException(AuditEvent event, Throwable throwable) { final String fileName = event.getFileName(); - if (fileName == null) { + if (fileName == null || !fileMessages.containsKey(fileName)) { synchronized (writerLock) { writeException(throwable); } } else { - final FileMessages messages = fileMessages.computeIfAbsent( - fileName, name -> new FileMessages()); + final FileMessages messages = fileMessages.get(fileName); messages.addException(throwable); } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractLoader.java b/src/main/java/com/puppycrawl/tools/checkstyle/XmlLoader.java index e0a83f334..5a410f045 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractLoader.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/XmlLoader.java @@ -17,7 +17,7 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //////////////////////////////////////////////////////////////////////////////// -package com.puppycrawl.tools.checkstyle.api; +package com.puppycrawl.tools.checkstyle; import java.io.IOException; import java.io.InputStream; @@ -48,7 +48,7 @@ import org.xml.sax.helpers.DefaultHandler; * @author Oliver Burn * @noinspection ThisEscapedInObjectConstruction */ -public abstract class AbstractLoader +public class XmlLoader extends DefaultHandler { /** Maps public id to resolve to resource name for the DTD. */ private final Map<String, String> publicIdToResourceNameMap; @@ -62,7 +62,7 @@ public abstract class AbstractLoader * @throws SAXException if an error occurs * @throws ParserConfigurationException if an error occurs */ - protected AbstractLoader(String publicId, String dtdResourceName) + protected XmlLoader(String publicId, String dtdResourceName) throws SAXException, ParserConfigurationException { this(new HashMap<>(1)); publicIdToResourceNameMap.put(publicId, dtdResourceName); @@ -74,7 +74,7 @@ public abstract class AbstractLoader * @throws SAXException if an error occurs * @throws ParserConfigurationException if an error occurs */ - protected AbstractLoader(Map<String, String> publicIdToResourceNameMap) + protected XmlLoader(Map<String, String> publicIdToResourceNameMap) throws SAXException, ParserConfigurationException { this.publicIdToResourceNameMap = new HashMap<>(publicIdToResourceNameMap); final SAXParserFactory factory = SAXParserFactory.newInstance(); @@ -145,9 +145,9 @@ public abstract class AbstractLoader } /** - * Configures SAXParserFactory with features requered - * for exectution on very secured environments. - * @param factory factory to be configured with spectial features + * Configures SAXParserFactory with features required + * for execution on very secured environments. + * @param factory factory to be configured with special features * @throws SAXException if an error occurs * @throws ParserConfigurationException if an error occurs */ diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractViolationReporter.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractViolationReporter.java index 1739b6bd5..fa57d7d7b 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractViolationReporter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractViolationReporter.java @@ -27,6 +27,7 @@ import java.util.Map; * {@link LocalizedMessage localized messages} that are created by the module. * * @author lkuehne + * @noinspection NoopMethodInAbstractClass */ public abstract class AbstractViolationReporter extends AutomaticBean { @@ -134,6 +135,11 @@ public abstract class AbstractViolationReporter return messageBundle; } + @Override + protected void finishLocalSetup() throws CheckstyleException { + // No code by default + } + /** * Log a message that has no column information. * diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java index 7e977eaa7..e7a35f69f 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/AutomaticBean.java @@ -53,7 +53,8 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtils; * calling the bean's setters for all configuration attributes. * @author lkuehne */ -public class AutomaticBean +// -@cs[AbstractClassName] We can not brake compatibility with previous versions. +public abstract class AutomaticBean implements Configurable, Contextualizable { /** @@ -78,6 +79,16 @@ public class AutomaticBean private Configuration configuration; /** + * Provides a hook to finish the part of this component's setup that + * was not handled by the bean introspection. + * <p> + * The default implementation does nothing. + * </p> + * @throws CheckstyleException if there is a configuration error. + */ + protected abstract void finishLocalSetup() throws CheckstyleException; + + /** * Creates a BeanUtilsBean that is configured to use * type converters that throw a ConversionException * instead of using the default value when something @@ -259,18 +270,6 @@ public class AutomaticBean } /** - * Provides a hook to finish the part of this component's setup that - * was not handled by the bean introspection. - * <p> - * The default implementation does nothing. - * </p> - * @throws CheckstyleException if there is a configuration error. - */ - protected void finishLocalSetup() throws CheckstyleException { - // No code by default, should be overridden only by demand at subclasses - } - - /** * Called by configure() for every child of this component's Configuration. * <p> * The default implementation throws {@link CheckstyleException} if diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/Configuration.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/Configuration.java index e4fc7191b..c50b2d1f0 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/Configuration.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/Configuration.java @@ -20,8 +20,7 @@ package com.puppycrawl.tools.checkstyle.api; import java.io.Serializable; - -import com.google.common.collect.ImmutableMap; +import java.util.Map; /** * A Configuration is used to configure a Configurable component. The general @@ -61,5 +60,5 @@ public interface Configuration extends Serializable { * for this configuration. * @return unmodifiable map containing custom messages */ - ImmutableMap<String, String> getMessages(); + Map<String, String> getMessages(); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/Context.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/Context.java index 795de7058..e96c66352 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/Context.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/Context.java @@ -19,7 +19,7 @@ package com.puppycrawl.tools.checkstyle.api; -import com.google.common.collect.ImmutableCollection; +import java.util.Collection; /** * A context to be used in subcomponents. The general idea of @@ -40,5 +40,5 @@ public interface Context { * Returns the names of all attributes of this context. * @return the names of all attributes of this context. */ - ImmutableCollection<String> getAttributeNames(); + Collection<String> getAttributeNames(); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/FileContents.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/FileContents.java index ca9a5b363..6aa0ad823 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/FileContents.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/FileContents.java @@ -23,12 +23,12 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import com.google.common.collect.ImmutableMap; import com.puppycrawl.tools.checkstyle.grammars.CommentListener; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; @@ -165,7 +165,7 @@ public final class FileContents implements CommentListener { * @deprecated Use {@link #getSingleLineComments()} instead. */ @Deprecated - public ImmutableMap<Integer, TextBlock> getCppComments() { + public Map<Integer, TextBlock> getCppComments() { return getSingleLineComments(); } @@ -174,8 +174,8 @@ public final class FileContents implements CommentListener { * the value is the comment {@link TextBlock} at the line. * @return the Map of comments */ - public ImmutableMap<Integer, TextBlock> getSingleLineComments() { - return ImmutableMap.copyOf(cppComments); + public Map<Integer, TextBlock> getSingleLineComments() { + return Collections.unmodifiableMap(cppComments); } /** @@ -202,7 +202,7 @@ public final class FileContents implements CommentListener { */ // -@cs[AbbreviationAsWordInName] Can't change yet since class is API. @Deprecated - public ImmutableMap<Integer, List<TextBlock>> getCComments() { + public Map<Integer, List<TextBlock>> getCComments() { return getBlockComments(); } @@ -212,8 +212,8 @@ public final class FileContents implements CommentListener { * that start at that line. * @return the map of comments */ - public ImmutableMap<Integer, List<TextBlock>> getBlockComments() { - return ImmutableMap.copyOf(clangComments); + public Map<Integer, List<TextBlock>> getBlockComments() { + return Collections.unmodifiableMap(clangComments); } /** diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/FileText.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/FileText.java index 3b12ffe20..64e919541 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/FileText.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/FileText.java @@ -37,7 +37,7 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import com.google.common.io.Closeables; +import com.puppycrawl.tools.checkstyle.utils.CommonUtils; /** * Represents the text contents of a file of arbitrary plain text type. @@ -139,7 +139,7 @@ public final class FileText { lines = textLines.toArray(new String[textLines.size()]); } finally { - Closeables.closeQuietly(reader); + CommonUtils.close(reader); } } @@ -209,7 +209,7 @@ public final class FileText { } } finally { - Closeables.closeQuietly(reader); + CommonUtils.close(reader); } return buf.toString(); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/TokenTypes.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/TokenTypes.java index 5b45f5d22..8adc69c73 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/TokenTypes.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/TokenTypes.java @@ -30,6 +30,7 @@ import com.puppycrawl.tools.checkstyle.grammars.GeneratedJavaTokenTypes; * * @author Oliver Burn * @author <a href="mailto:dobratzp@ele.uri.edu">Peter Dobratz</a> + * @noinspection ClassWithTooManyDependents */ public final class TokenTypes { // The following three types are never part of an AST, diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/TranslationCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/TranslationCheck.java index 56303a33b..76601aeae 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/TranslationCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/TranslationCheck.java @@ -47,6 +47,7 @@ import com.puppycrawl.tools.checkstyle.Definitions; import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck; import com.puppycrawl.tools.checkstyle.api.FileText; import com.puppycrawl.tools.checkstyle.api.LocalizedMessage; +import com.puppycrawl.tools.checkstyle.api.MessageDispatcher; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; /** @@ -132,19 +133,19 @@ public class TranslationCheck extends AbstractFileSetCheck { private static final String DEFAULT_TRANSLATION_REGEXP = "^.+\\..+$"; /** - * Regexp pattern for bundles names wich end with language code, followed by country code and + * Regexp pattern for bundles names which end with language code, followed by country code and * variant suffix. For example, messages_es_ES_UNIX.properties. */ private static final Pattern LANGUAGE_COUNTRY_VARIANT_PATTERN = CommonUtils.createPattern("^.+\\_[a-z]{2}\\_[A-Z]{2}\\_[A-Za-z]+\\..+$"); /** - * Regexp pattern for bundles names wich end with language code, followed by country code + * Regexp pattern for bundles names which end with language code, followed by country code * suffix. For example, messages_es_ES.properties. */ private static final Pattern LANGUAGE_COUNTRY_PATTERN = CommonUtils.createPattern("^.+\\_[a-z]{2}\\_[A-Z]{2}\\..+$"); /** - * Regexp pattern for bundles names wich end with language code suffix. + * Regexp pattern for bundles names which end with language code suffix. * For example, messages_es.properties. */ private static final Pattern LANGUAGE_PATTERN = @@ -325,9 +326,11 @@ public class TranslationCheck extends AbstractFileSetCheck { * @param fileName file name. */ private void logMissingTranslation(String filePath, String fileName) { + final MessageDispatcher dispatcher = getMessageDispatcher(); + dispatcher.fireFileStarted(filePath); log(0, MSG_KEY_MISSING_TRANSLATION_FILE, fileName); fireErrors(filePath); - getMessageDispatcher().fireFileFinished(filePath); + dispatcher.fireFileFinished(filePath); } /** @@ -454,6 +457,9 @@ public class TranslationCheck extends AbstractFileSetCheck { private void checkFilesForConsistencyRegardingTheirKeys(SetMultimap<File, String> fileKeys, Set<String> keysThatMustExist) { for (File currentFile : fileKeys.keySet()) { + final MessageDispatcher dispatcher = getMessageDispatcher(); + final String path = currentFile.getPath(); + dispatcher.fireFileStarted(path); final Set<String> currentFileKeys = fileKeys.get(currentFile); final Set<String> missingKeys = keysThatMustExist.stream() .filter(e -> !currentFileKeys.contains(e)).collect(Collectors.toSet()); @@ -462,9 +468,8 @@ public class TranslationCheck extends AbstractFileSetCheck { log(0, MSG_KEY, key); } } - final String path = currentFile.getPath(); fireErrors(path); - getMessageDispatcher().fireFileFinished(path); + dispatcher.fireFileFinished(path); } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck.java index b20f5b96e..ffe0bd9cd 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/UniquePropertiesCheck.java @@ -113,7 +113,7 @@ public class UniquePropertiesCheck extends AbstractFileSetCheck { } ++lineNumber; } - // -1 as check seeks for the first duplicate occurance in file, + // -1 as check seeks for the first duplicate occurrence in file, // so it cannot be the last line. if (lineNumber > fileText.size() - 1) { lineNumber = 0; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/EqualsAvoidNullCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/EqualsAvoidNullCheck.java index 0fc040f7c..326cc8109 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/EqualsAvoidNullCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/EqualsAvoidNullCheck.java @@ -483,7 +483,7 @@ public class EqualsAvoidNullCheck extends AbstractCheck { // The minimal distance between objCalledOn and field (of type String) initialization // is calculated as follows: // String(6) + space(1) + variableName(1) + assign(1) + - // anotherStringVariableName(1) + semicolumn(1) = 11 + // anotherStringVariableName(1) + semicolon(1) = 11 // Example: length of "String s=d;" is 11 symbols. final int minimumSymbolsBetween = 11; if (field.getLineNo() < objCalledOn.getLineNo() diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheck.java index 03977238b..679d79a17 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/FinalLocalVariableCheck.java @@ -251,7 +251,7 @@ public class FinalLocalVariableCheck extends AbstractCheck { case TokenTypes.SLIST: // -@cs[MoveVariableInsideIf] assignment value is modified later so it can't be // moved - final Deque<DetailAST> prevScopeUnitializedVariableData = + final Deque<DetailAST> prevScopeUninitializedVariableData = prevScopeUninitializedVariables.peek(); boolean containsBreak = false; if (ast.getParent().getType() != TokenTypes.CASE_GROUP @@ -263,7 +263,7 @@ public class FinalLocalVariableCheck extends AbstractCheck { } final DetailAST parent = ast.getParent(); if (containsBreak || shouldUpdateUninitializedVariables(parent)) { - updateAllUninitializedVariables(prevScopeUnitializedVariableData); + updateAllUninitializedVariables(prevScopeUninitializedVariableData); } updateCurrentScopeAssignedVariables(); break; @@ -348,35 +348,35 @@ public class FinalLocalVariableCheck extends AbstractCheck { */ private void storePrevScopeUninitializedVariableData() { final ScopeData scopeData = scopeStack.peek(); - final Deque<DetailAST> prevScopeUnitializedVariableData = + final Deque<DetailAST> prevScopeUninitializedVariableData = new ArrayDeque<>(); - scopeData.uninitializedVariables.forEach(prevScopeUnitializedVariableData::push); - prevScopeUninitializedVariables.push(prevScopeUnitializedVariableData); + scopeData.uninitializedVariables.forEach(prevScopeUninitializedVariableData::push); + prevScopeUninitializedVariables.push(prevScopeUninitializedVariableData); } /** * Update current scope data uninitialized variable according to the whole scope data. - * @param prevScopeUnitializedVariableData variable for previous stack of uninitialized + * @param prevScopeUninitializedVariableData variable for previous stack of uninitialized * variables + * @noinspection MethodParameterNamingConvention */ - // -@cs[CyclomaticComplexity] Breaking apart will damage encapsulation. private void updateAllUninitializedVariables( - Deque<DetailAST> prevScopeUnitializedVariableData) { + Deque<DetailAST> prevScopeUninitializedVariableData) { // Check for only previous scope - updateUninitializedVariables(prevScopeUnitializedVariableData); + updateUninitializedVariables(prevScopeUninitializedVariableData); // Check for rest of the scope prevScopeUninitializedVariables.forEach(this::updateUninitializedVariables); } /** * Update current scope data uninitialized variable according to the specific scope data. - * @param scopeUnitializedVariableData variable for specific stack of uninitialized variables + * @param scopeUninitializedVariableData variable for specific stack of uninitialized variables */ - private void updateUninitializedVariables(Deque<DetailAST> scopeUnitializedVariableData) { + private void updateUninitializedVariables(Deque<DetailAST> scopeUninitializedVariableData) { final Iterator<DetailAST> iterator = currentScopeAssignedVariables.peek().iterator(); while (iterator.hasNext()) { final DetailAST assignedVariable = iterator.next(); - for (DetailAST variable : scopeUnitializedVariableData) { + for (DetailAST variable : scopeUninitializedVariableData) { for (ScopeData scopeData : scopeStack) { final FinalVariableCandidate candidate = scopeData.scope.get(variable.getText()); diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalInstantiationCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalInstantiationCheck.java index 75b1284ed..bcdb895b1 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalInstantiationCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalInstantiationCheck.java @@ -116,7 +116,6 @@ public class IllegalInstantiationCheck @Override public void beginTree(DetailAST rootAST) { - super.beginTree(rootAST); pkgName = null; imports.clear(); instantiations.clear(); @@ -328,7 +327,7 @@ public class IllegalInstantiationCheck * @return true if type is standard */ private boolean isStandardClass(String className, String illegal) { - boolean isStandardCalss = false; + boolean isStandardClass = false; // class from java.lang if (illegal.length() - JAVA_LANG.length() == className.length() && illegal.endsWith(className) @@ -343,10 +342,10 @@ public class IllegalInstantiationCheck final boolean isSamePackage = isSamePackage(className); if (!isSameFile && !isSamePackage) { - isStandardCalss = true; + isStandardClass = true; } } - return isStandardCalss; + return isStandardClass; } /** diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalTypeCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalTypeCheck.java index edcb1a0b4..ef2891c81 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalTypeCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/IllegalTypeCheck.java @@ -98,8 +98,6 @@ public final class IllegalTypeCheck extends AbstractCheck { */ public static final String MSG_KEY = "illegal.type"; - /** Abstract classes legal by default. */ - private static final String[] DEFAULT_LEGAL_ABSTRACT_NAMES = {}; /** Types illegal by default. */ private static final String[] DEFAULT_ILLEGAL_TYPES = { "HashSet", @@ -144,7 +142,6 @@ public final class IllegalTypeCheck extends AbstractCheck { /** Creates new instance of the check. */ public IllegalTypeCheck() { setIllegalClassNames(DEFAULT_ILLEGAL_TYPES); - setLegalAbstractClassNames(DEFAULT_LEGAL_ABSTRACT_NAMES); setIgnoredMethodNames(DEFAULT_IGNORED_METHOD_NAMES); } @@ -450,7 +447,6 @@ public final class IllegalTypeCheck extends AbstractCheck { * @noinspection WeakerAccess */ public void setLegalAbstractClassNames(String... classNames) { - legalAbstractClassNames.clear(); Collections.addAll(legalAbstractClassNames, classNames); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheck.java index c2e3de96e..58e5f7b3d 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheck.java @@ -91,6 +91,7 @@ import com.puppycrawl.tools.checkstyle.utils.TokenUtils; * @author o_sukhodolsky * @author Andrei Selkin */ +// -@cs[ClassDataAbstractionCoupling] This check requires to work with and identify many frames. @FileStatefulCheck public class RequireThisCheck extends AbstractCheck { @@ -113,6 +114,7 @@ public class RequireThisCheck extends AbstractCheck { TokenTypes.METHOD_DEF, TokenTypes.CLASS_DEF, TokenTypes.ENUM_DEF, + TokenTypes.ANNOTATION_DEF, TokenTypes.INTERFACE_DEF, TokenTypes.PARAMETER_DEF, TokenTypes.TYPE_ARGUMENT, @@ -145,12 +147,12 @@ public class RequireThisCheck extends AbstractCheck { TokenTypes.BXOR_ASSIGN, }).collect(Collectors.toSet())); + /** Frame for the currently processed AST. */ + private final Deque<AbstractFrame> current = new ArrayDeque<>(); + /** Tree of all the parsed frames. */ private Map<DetailAST, AbstractFrame> frames; - /** Frame for the currently processed AST. */ - private AbstractFrame current; - /** Whether we should check fields usage. */ private boolean checkFields = true; /** Whether we should check methods usage. */ @@ -193,8 +195,10 @@ public class RequireThisCheck extends AbstractCheck { TokenTypes.CLASS_DEF, TokenTypes.INTERFACE_DEF, TokenTypes.ENUM_DEF, + TokenTypes.ANNOTATION_DEF, TokenTypes.CTOR_DEF, TokenTypes.METHOD_DEF, + TokenTypes.LITERAL_FOR, TokenTypes.SLIST, TokenTypes.IDENT, }; @@ -208,7 +212,7 @@ public class RequireThisCheck extends AbstractCheck { @Override public void beginTree(DetailAST rootAST) { frames = new HashMap<>(); - current = null; + current.clear(); final Deque<AbstractFrame> frameStack = new LinkedList<>(); DetailAST curNode = rootAST; @@ -239,7 +243,26 @@ public class RequireThisCheck extends AbstractCheck { case TokenTypes.SLIST : case TokenTypes.METHOD_DEF : case TokenTypes.CTOR_DEF : - current = frames.get(ast); + case TokenTypes.LITERAL_FOR : + current.push(frames.get(ast)); + break; + default : + // do nothing + } + } + + @Override + public void leaveToken(DetailAST ast) { + switch (ast.getType()) { + case TokenTypes.CLASS_DEF : + case TokenTypes.INTERFACE_DEF : + case TokenTypes.ENUM_DEF : + case TokenTypes.ANNOTATION_DEF : + case TokenTypes.SLIST : + case TokenTypes.METHOD_DEF : + case TokenTypes.CTOR_DEF : + case TokenTypes.LITERAL_FOR: + current.pop(); break; default : // do nothing @@ -252,7 +275,12 @@ public class RequireThisCheck extends AbstractCheck { * @param ast IDENT to check. */ private void processIdent(DetailAST ast) { - final int parentType = ast.getParent().getType(); + int parentType = ast.getParent().getType(); + if (parentType == TokenTypes.EXPR + && ast.getParent().getParent().getParent().getType() + == TokenTypes.ANNOTATION_FIELD_DEF) { + parentType = TokenTypes.ANNOTATION_FIELD_DEF; + } switch (parentType) { case TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR: case TokenTypes.ANNOTATION: @@ -328,6 +356,7 @@ public class RequireThisCheck extends AbstractCheck { * @param frameStack stack containing the FrameTree being built. * @param ast AST to parse. */ + // -@cs[JavaNCSS] This method is a big switch and is too hard to remove. private static void collectDeclarations(Deque<AbstractFrame> frameStack, DetailAST ast) { final AbstractFrame frame = frameStack.peek(); switch (ast.getType()) { @@ -336,7 +365,8 @@ public class RequireThisCheck extends AbstractCheck { break; case TokenTypes.PARAMETER_DEF : if (!CheckUtils.isReceiverParameter(ast) - && !isLambdaParameter(ast)) { + && !isLambdaParameter(ast) + && ast.getParent().getType() != TokenTypes.LITERAL_CATCH) { final DetailAST parameterIdent = ast.findFirstToken(TokenTypes.IDENT); frame.addIdent(parameterIdent); } @@ -366,6 +396,20 @@ public class RequireThisCheck extends AbstractCheck { final DetailAST ctorFrameNameIdent = ast.findFirstToken(TokenTypes.IDENT); frameStack.addFirst(new ConstructorFrame(frame, ctorFrameNameIdent)); break; + case TokenTypes.ENUM_CONSTANT_DEF : + final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT); + ((ClassFrame) frame).addStaticMember(ident); + break; + case TokenTypes.LITERAL_CATCH: + final AbstractFrame catchFrame = new CatchFrame(frame, ast); + catchFrame.addIdent(ast.findFirstToken(TokenTypes.PARAMETER_DEF).findFirstToken( + TokenTypes.IDENT)); + frameStack.addFirst(catchFrame); + break; + case TokenTypes.LITERAL_FOR: + final AbstractFrame forFrame = new ForFrame(frame, ast); + frameStack.addFirst(forFrame); + break; case TokenTypes.LITERAL_NEW: if (isAnonymousClassDef(ast)) { frameStack.addFirst(new AnonymousClassFrame(frame, @@ -414,6 +458,8 @@ public class RequireThisCheck extends AbstractCheck { case TokenTypes.SLIST : case TokenTypes.METHOD_DEF : case TokenTypes.CTOR_DEF : + case TokenTypes.LITERAL_CATCH : + case TokenTypes.LITERAL_FOR : frames.put(ast, frameStack.poll()); break; case TokenTypes.LITERAL_NEW : @@ -581,7 +627,8 @@ public class RequireThisCheck extends AbstractCheck { private boolean canBeReferencedFromStaticContext(DetailAST ident) { AbstractFrame variableDeclarationFrame = findFrame(ident, false); boolean staticInitializationBlock = false; - while (variableDeclarationFrame.getType() == FrameType.BLOCK_FRAME) { + while (variableDeclarationFrame.getType() == FrameType.BLOCK_FRAME + || variableDeclarationFrame.getType() == FrameType.FOR_FRAME) { final DetailAST blockFrameNameIdent = variableDeclarationFrame.getFrameNameIdent(); final DetailAST definitionToken = blockFrameNameIdent.getParent(); if (definitionToken.getType() == TokenTypes.STATIC_INIT) { @@ -824,7 +871,7 @@ public class RequireThisCheck extends AbstractCheck { * @return AbstractFrame containing declaration or null. */ private AbstractFrame findClassFrame(DetailAST name, boolean lookForMethod) { - AbstractFrame frame = current; + AbstractFrame frame = current.peek(); while (true) { frame = findFrame(frame, name, lookForMethod); @@ -846,7 +893,7 @@ public class RequireThisCheck extends AbstractCheck { * @return AbstractFrame containing declaration or null. */ private AbstractFrame findFrame(DetailAST name, boolean lookForMethod) { - return findFrame(current, name, lookForMethod); + return findFrame(current.peek(), name, lookForMethod); } /** @@ -858,14 +905,7 @@ public class RequireThisCheck extends AbstractCheck { */ private static AbstractFrame findFrame(AbstractFrame frame, DetailAST name, boolean lookForMethod) { - final AbstractFrame result; - if (frame == null) { - result = null; - } - else { - result = frame.getIfContains(name, lookForMethod); - } - return result; + return frame.getIfContains(name, lookForMethod); } /** @@ -900,7 +940,7 @@ public class RequireThisCheck extends AbstractCheck { * @return the name of the nearest parent ClassFrame. */ private String getNearestClassFrameName() { - AbstractFrame frame = current; + AbstractFrame frame = current.peek(); while (frame.getType() != FrameType.CLASS_FRAME) { frame = frame.getParent(); } @@ -952,6 +992,10 @@ public class RequireThisCheck extends AbstractCheck { METHOD_FRAME, /** Block frame type. */ BLOCK_FRAME, + /** Catch frame type. */ + CATCH_FRAME, + /** Lambda frame type. */ + FOR_FRAME, } /** @@ -1357,4 +1401,44 @@ public class RequireThisCheck extends AbstractCheck { return FrameType.BLOCK_FRAME; } } + + /** + * A frame initiated on entering a catch block; holds local catch variable names. + * @author Richard Veach + */ + public static class CatchFrame extends AbstractFrame { + /** + * Creates catch frame. + * @param parent parent frame. + * @param ident ident frame name ident. + */ + protected CatchFrame(AbstractFrame parent, DetailAST ident) { + super(parent, ident); + } + + @Override + public FrameType getType() { + return FrameType.CATCH_FRAME; + } + } + + /** + * A frame initiated on entering a for block; holds local for variable names. + * @author Richard Veach + */ + public static class ForFrame extends AbstractFrame { + /** + * Creates for frame. + * @param parent parent frame. + * @param ident ident frame name ident. + */ + protected ForFrame(AbstractFrame parent, DetailAST ident) { + super(parent, ident); + } + + @Override + public FrameType getType() { + return FrameType.FOR_FRAME; + } + } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ReturnCountCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ReturnCountCheck.java index 231fcd8fd..fcdcdda9d 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ReturnCountCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/ReturnCountCheck.java @@ -60,6 +60,11 @@ public final class ReturnCountCheck extends AbstractCheck { * file. */ public static final String MSG_KEY = "return.count"; + /** + * A key pointing to the warning message text in "messages.properties" + * file. + */ + public static final String MSG_KEY_VOID = "return.countVoid"; /** Stack of method contexts. */ private final Deque<Context> contextStack = new ArrayDeque<>(); @@ -199,10 +204,10 @@ public final class ReturnCountCheck extends AbstractCheck { // we can't identify which max to use for lambdas, so we can only assign // after the first return statement is seen if (ast.getFirstChild().getType() == TokenTypes.SEMI) { - context.visitLiteralReturn(maxForVoid); + context.visitLiteralReturn(maxForVoid, true); } else { - context.visitLiteralReturn(max); + context.visitLiteralReturn(max, false); } } @@ -217,6 +222,8 @@ public final class ReturnCountCheck extends AbstractCheck { private int count; /** Maximum allowed number of return statements. */ private Integer maxAllowed; + /** Identifies if context is void. */ + private boolean isVoidContext; /** * Creates new method context. @@ -227,10 +234,12 @@ public final class ReturnCountCheck extends AbstractCheck { } /** - * Increase the number of return statements. + * Increase the number of return statements and set context return type. * @param maxAssigned Maximum allowed number of return statements. + * @param voidReturn Identifies if context is void. */ - public void visitLiteralReturn(int maxAssigned) { + public void visitLiteralReturn(int maxAssigned, Boolean voidReturn) { + isVoidContext = voidReturn; if (maxAllowed == null) { maxAllowed = maxAssigned; } @@ -245,7 +254,12 @@ public final class ReturnCountCheck extends AbstractCheck { */ public void checkCount(DetailAST ast) { if (checking && maxAllowed != null && count > maxAllowed) { - log(ast.getLineNo(), ast.getColumnNo(), MSG_KEY, count, maxAllowed); + if (isVoidContext) { + log(ast.getLineNo(), ast.getColumnNo(), MSG_KEY_VOID, count, maxAllowed); + } + else { + log(ast.getLineNo(), ast.getColumnNo(), MSG_KEY, count, maxAllowed); + } } } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/VariableDeclarationUsageDistanceCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/VariableDeclarationUsageDistanceCheck.java index 0e7d9fd07..f13541ef8 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/VariableDeclarationUsageDistanceCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/VariableDeclarationUsageDistanceCheck.java @@ -424,8 +424,13 @@ public class VariableDeclarationUsageDistanceCheck extends AbstractCheck { */ private static int getDistToVariableUsageInChildNode(DetailAST childNode, DetailAST varIdent, int currentDistToVarUsage) { + DetailAST examineNode = childNode; + if (examineNode.getType() == TokenTypes.LABELED_STAT) { + examineNode = examineNode.getFirstChild().getNextSibling(); + } + int resultDist = currentDistToVarUsage; - switch (childNode.getType()) { + switch (examineNode.getType()) { case TokenTypes.VARIABLE_DEF: resultDist++; break; @@ -437,7 +442,7 @@ public class VariableDeclarationUsageDistanceCheck extends AbstractCheck { case TokenTypes.LITERAL_DO: case TokenTypes.LITERAL_IF: case TokenTypes.LITERAL_SWITCH: - if (isVariableInOperatorExpr(childNode, varIdent)) { + if (isVariableInOperatorExpr(examineNode, varIdent)) { resultDist++; } else { @@ -447,11 +452,11 @@ public class VariableDeclarationUsageDistanceCheck extends AbstractCheck { } break; default: - if (childNode.branchContains(TokenTypes.SLIST)) { - resultDist = 0; + if (examineNode.findFirstToken(TokenTypes.SLIST) == null) { + resultDist++; } else { - resultDist++; + resultDist = 0; } } return resultDist; @@ -522,16 +527,17 @@ public class VariableDeclarationUsageDistanceCheck extends AbstractCheck { variableUsageAst = exprWithVariableUsage; } } + + // If there's no any variable usage, then distance = 0. + else if (variableUsageExpressions.isEmpty()) { + variableUsageAst = null; + } // If variable usage exists in different scopes, then distance = // distance until variable first usage. - else if (variableUsageExpressions.size() > 1) { + else { dist++; variableUsageAst = variableUsageExpressions.get(0); } - // If there's no any variable usage, then distance = 0. - else { - variableUsageAst = null; - } } return new SimpleEntry<>(variableUsageAst, dist); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck.java index cc32ef218..c4d2d6d57 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/CustomImportOrderCheck.java @@ -436,7 +436,6 @@ public class CustomImportOrderCheck extends AbstractCheck { * user value. */ public final void setCustomImportOrderRules(final String inputCustomImportOrder) { - customImportOrderRules.clear(); for (String currentState : GROUP_SEPARATOR_PATTERN.split(inputCustomImportOrder)) { addRulesToList(currentState); } @@ -636,7 +635,7 @@ public class CustomImportOrderCheck extends AbstractCheck { } if (SPECIAL_IMPORTS_RULE_GROUP.equals(group)) { bestMatch = findBetterPatternMatch(importPath, - SPECIAL_IMPORTS_RULE_GROUP, specialImportsRegExp, bestMatch); + group, specialImportsRegExp, bestMatch); } } } @@ -691,7 +690,7 @@ public class CustomImportOrderCheck extends AbstractCheck { final String separator = "\\."; final String[] import1Tokens = import1.split(separator); final String[] import2Tokens = import2.split(separator); - for (int i = 0; i < import1Tokens.length && i != import2Tokens.length; i++) { + for (int i = 0; i != import1Tokens.length && i != import2Tokens.length; i++) { final String import1Token = import1Tokens[i]; final String import2Token = import2Tokens[i]; result = import1Token.compareTo(import2Token); @@ -699,6 +698,9 @@ public class CustomImportOrderCheck extends AbstractCheck { break; } } + if (result == 0) { + result = Integer.compare(import1Tokens.length, import2Tokens.length); + } return result; } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportControlLoader.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportControlLoader.java index f6e78691d..93a442b24 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportControlLoader.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportControlLoader.java @@ -34,14 +34,14 @@ import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import com.puppycrawl.tools.checkstyle.api.AbstractLoader; +import com.puppycrawl.tools.checkstyle.XmlLoader; import com.puppycrawl.tools.checkstyle.api.CheckstyleException; /** * Responsible for loading the contents of an import control configuration file. * @author Oliver Burn */ -final class ImportControlLoader extends AbstractLoader { +final class ImportControlLoader extends XmlLoader { /** The public ID for the configuration dtd. */ private static final String DTD_PUBLIC_ID_1_0 = "-//Puppy Crawl//DTD Import Control 1.0//EN"; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheck.java index a6f08bf1d..f769c754c 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheck.java @@ -392,6 +392,10 @@ public class ImportOrderCheck } doVisitToken(ident, isStatic, isStaticAndNotLastImport); + if (isStaticAndNotLastImport && !beforeFirstImport) { + log(ident.getLineNo(), MSG_ORDERING, ident.getText()); + } + } else if (option == ImportOrderOption.BOTTOM) { @@ -401,6 +405,10 @@ public class ImportOrderCheck } doVisitToken(ident, isStatic, isLastImportAndNonStatic); + if (isLastImportAndNonStatic) { + log(ident.getLineNo(), MSG_ORDERING, ident.getText()); + } + } else if (option == ImportOrderOption.ABOVE) { // previous non-static but current is static @@ -440,14 +448,15 @@ public class ImportOrderCheck final int groupIdx = getGroupNumber(name); final int line = ident.getLineNo(); - if (isInSameGroup(groupIdx, isStatic)) { - doVisitTokenInSameGroup(isStatic, previous, name, line); - } - else if (groupIdx > lastGroup) { - if (!beforeFirstImport && separated && line - lastImportLine < 2) { + if (groupIdx > lastGroup) { + if (!beforeFirstImport && separated && line - lastImportLine < 2 + && !isInSameGroup(groupIdx, isStatic)) { log(line, MSG_SEPARATION, name); } } + else if (isInSameGroup(groupIdx, isStatic)) { + doVisitTokenInSameGroup(isStatic, previous, name, line); + } else { log(line, MSG_ORDERING, name); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/LineWrappingHandler.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/LineWrappingHandler.java index f8af0a778..39f2b9ce6 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/LineWrappingHandler.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/LineWrappingHandler.java @@ -262,7 +262,8 @@ public class LineWrappingHandler { if (isCurrentNodeCloseAnnotationAloneInLine || node.getType() == TokenTypes.AT && (parentNode.getParent().getType() == TokenTypes.MODIFIERS - || parentNode.getParent().getType() == TokenTypes.ANNOTATIONS)) { + || parentNode.getParent().getType() == TokenTypes.ANNOTATIONS) + || node.getLineNo() == atNode.getLineNo()) { logWarningMessage(node, firstNodeIndent); } else { diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/TryHandler.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/TryHandler.java index 1b91a5775..eb80609f5 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/TryHandler.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/TryHandler.java @@ -129,9 +129,9 @@ public class TryHandler extends BlockParentHandler { */ private void checkTryResources(final DetailAST resourcesSpecAst) { final DetailAST resourcesAst = resourcesSpecAst.findFirstToken(TokenTypes.RESOURCES); - final int indetation = getIndent().getFirstIndentLevel() + final int indentation = getIndent().getFirstIndentLevel() + getIndentCheck().getLineWrappingIndentation(); - final IndentLevel expectedResourceIndent = new IndentLevel(indetation); + final IndentLevel expectedResourceIndent = new IndentLevel(indentation); final String subType = "resource"; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocMethodCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocMethodCheck.java index 2e0d95e75..ca3aec832 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocMethodCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocMethodCheck.java @@ -100,12 +100,12 @@ public class JavadocMethodCheck extends AbstractTypeAwareCheck { public static final String MSG_DUPLICATE_TAG = "javadoc.duplicateTag"; /** Compiled regexp to match Javadoc tags that take an argument. */ - private static final Pattern MATCH_JAVADOC_ARG = - CommonUtils.createPattern("@(throws|exception|param)\\s+(\\S+)\\s+\\S*"); + private static final Pattern MATCH_JAVADOC_ARG = CommonUtils.createPattern( + "^\\s*(?>\\*|\\/\\*\\*)?\\s*@(throws|exception|param)\\s+(\\S+)\\s+\\S*"); /** Compiled regexp to match first part of multilineJavadoc tags. */ - private static final Pattern MATCH_JAVADOC_ARG_MULTILINE_START = - CommonUtils.createPattern("@(throws|exception|param)\\s+(\\S+)\\s*$"); + private static final Pattern MATCH_JAVADOC_ARG_MULTILINE_START = CommonUtils.createPattern( + "^\\s*(?>\\*|\\/\\*\\*)?\\s*@(throws|exception|param)\\s+(\\S+)\\s*$"); /** Compiled regexp to look for a continuation of the comment. */ private static final Pattern MATCH_JAVADOC_MULTILINE_CONT = @@ -118,10 +118,10 @@ public class JavadocMethodCheck extends AbstractTypeAwareCheck { /** Compiled regexp to match Javadoc tags with no argument. */ private static final Pattern MATCH_JAVADOC_NOARG = - CommonUtils.createPattern("@(return|see)\\s+\\S"); + CommonUtils.createPattern("^\\s*(?>\\*|\\/\\*\\*)?\\s*@(return|see)\\s+\\S"); /** Compiled regexp to match first part of multilineJavadoc tags. */ private static final Pattern MATCH_JAVADOC_NOARG_MULTILINE_START = - CommonUtils.createPattern("@(return|see)\\s*$"); + CommonUtils.createPattern("^\\s*(?>\\*|\\/\\*\\*)?\\s*@(return|see)\\s*$"); /** Compiled regexp to match Javadoc tags with no argument and {}. */ private static final Pattern MATCH_JAVADOC_NOARG_CURLY = CommonUtils.createPattern("\\{\\s*@(inheritDoc)\\s*\\}"); diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/NonEmptyAtclauseDescriptionCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/NonEmptyAtclauseDescriptionCheck.java index 77516206b..73e46a097 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/NonEmptyAtclauseDescriptionCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/NonEmptyAtclauseDescriptionCheck.java @@ -48,6 +48,7 @@ public class NonEmptyAtclauseDescriptionCheck extends AbstractJavadocCheck { JavadocTokenTypes.PARAM_LITERAL, JavadocTokenTypes.RETURN_LITERAL, JavadocTokenTypes.THROWS_LITERAL, + JavadocTokenTypes.EXCEPTION_LITERAL, JavadocTokenTypes.DEPRECATED_LITERAL, }; } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck.java index a0498fc24..293cd4aaa 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/AbstractClassCouplingCheck.java @@ -140,7 +140,7 @@ public abstract class AbstractClassCouplingCheck extends AbstractCheck { } /** - * Sets user-excluded pakcages to ignore. All exlcuded packages should end with a period, + * Sets user-excluded packages to ignore. All excluded packages should end with a period, * so it also appends a dot to a package name. * @param excludedPackages the list of packages to ignore. */ diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/ClassDataAbstractionCouplingCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/ClassDataAbstractionCouplingCheck.java index b960dd5a9..8c41a8c2e 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/ClassDataAbstractionCouplingCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/ClassDataAbstractionCouplingCheck.java @@ -59,14 +59,7 @@ public final class ClassDataAbstractionCouplingCheck @Override public int[] getAcceptableTokens() { - return new int[] { - TokenTypes.PACKAGE_DEF, - TokenTypes.IMPORT, - TokenTypes.CLASS_DEF, - TokenTypes.INTERFACE_DEF, - TokenTypes.ENUM_DEF, - TokenTypes.LITERAL_NEW, - }; + return getRequiredTokens(); } // -@cs[SimpleAccessorNameNotation] Overrides method from the base class. diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/NPathComplexityCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/NPathComplexityCheck.java index 5f62d2c5d..b07268cd4 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/NPathComplexityCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/metrics/NPathComplexityCheck.java @@ -337,7 +337,7 @@ public final class NPathComplexityCheck extends AbstractCheck { } /** - * Calculates number of conditional operators, including inline ternary operatior, for a token. + * Calculates number of conditional operators, including inline ternary operator, for a token. * @param ast inspected token. * @return number of conditional operators. * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.23"> diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/modifier/RedundantModifierCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/modifier/RedundantModifierCheck.java index cc8d1b6b0..5db77a317 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/modifier/RedundantModifierCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/modifier/RedundantModifierCheck.java @@ -289,11 +289,11 @@ public class RedundantModifierCheck modifiers.findFirstToken(TokenTypes.LITERAL_PRIVATE) != null; // declared in a final class? DetailAST parent = ast.getParent(); - while (parent != null) { + while (parent != null && !checkFinal) { if (parent.getType() == TokenTypes.CLASS_DEF) { final DetailAST classModifiers = parent.findFirstToken(TokenTypes.MODIFIERS); - checkFinal = checkFinal || classModifiers.findFirstToken(TokenTypes.FINAL) != null; + checkFinal = classModifiers.findFirstToken(TokenTypes.FINAL) != null; parent = null; } else if (parent.getType() == TokenTypes.LITERAL_NEW @@ -301,6 +301,10 @@ public class RedundantModifierCheck checkFinal = true; parent = null; } + else if (parent.getType() == TokenTypes.ENUM_DEF) { + checkFinal = modifiers.findFirstToken(TokenTypes.LITERAL_STATIC) != null; + parent = null; + } else { parent = parent.getParent(); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/regexp/RegexpSinglelineJavaCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/regexp/RegexpSinglelineJavaCheck.java index c7876e2e2..b82985bbd 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/regexp/RegexpSinglelineJavaCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/regexp/RegexpSinglelineJavaCheck.java @@ -62,15 +62,15 @@ public class RegexpSinglelineJavaCheck extends AbstractCheck { @Override public void beginTree(DetailAST rootAST) { - MatchSuppressor supressor = null; + MatchSuppressor suppressor = null; if (ignoreComments) { - supressor = new CommentSuppressor(getFileContents()); + suppressor = new CommentSuppressor(getFileContents()); } final DetectorOptions options = DetectorOptions.newBuilder() .reporter(this) .compileFlags(0) - .suppressor(supressor) + .suppressor(suppressor) .format(format) .message(message) .minimum(minimum) diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/sizes/MethodCountCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/sizes/MethodCountCheck.java index d31c52586..e9ce934e4 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/sizes/MethodCountCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/sizes/MethodCountCheck.java @@ -112,7 +112,7 @@ public final class MethodCountCheck extends AbstractCheck { @Override public void visitToken(DetailAST ast) { if (ast.getType() == TokenTypes.METHOD_DEF) { - if (isInLastestScopeDefinition(ast)) { + if (isInLatestScopeDefinition(ast)) { raiseCounter(ast); } } @@ -134,11 +134,11 @@ public final class MethodCountCheck extends AbstractCheck { * Checks if there is a scope definition to check and that the method is found inside that scope * (class, enum, etc.). * @param methodDef - * The method to analzye. + * The method to analyze. * @return {@code true} if the method is part of the latest scope definition and should be * counted. */ - private boolean isInLastestScopeDefinition(DetailAST methodDef) { + private boolean isInLatestScopeDefinition(DetailAST methodDef) { boolean result = false; if (!counters.isEmpty()) { diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/NoWhitespaceAfterCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/NoWhitespaceAfterCheck.java index 44a3118fc..4d9562015 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/NoWhitespaceAfterCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/whitespace/NoWhitespaceAfterCheck.java @@ -390,8 +390,12 @@ public class NoWhitespaceAfterCheck extends AbstractCheck { } //ident and lastTypeNode lay on one line else { - if (ident.getColumnNo() >= ast.getColumnNo() + 1 - || lastTypeNode.getColumnNo() > ident.getColumnNo()) { + final int instanceOfSize = 13; + // +2 because ast has `[]` after the ident + if (ident.getColumnNo() >= ast.getColumnNo() + 2 + // +13 because ident (at most 1 character) is followed by + // ' instanceof ' (12 characters) + || lastTypeNode.getColumnNo() >= ident.getColumnNo() + instanceOfSize) { previousElement = lastTypeNode; } else { diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filefilters/BeforeExecutionExclusionFileFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filefilters/BeforeExecutionExclusionFileFilter.java index 39dea8fb9..77fe7c4cd 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filefilters/BeforeExecutionExclusionFileFilter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filefilters/BeforeExecutionExclusionFileFilter.java @@ -83,6 +83,11 @@ public final class BeforeExecutionExclusionFileFilter extends AutomaticBean } @Override + protected void finishLocalSetup() { + // No code by default + } + + @Override public boolean accept(String uri) { return fileNamePattern == null || !fileNamePattern.matcher(uri).find(); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SeverityMatchFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SeverityMatchFilter.java index db2aa9216..9642ee7d3 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SeverityMatchFilter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SeverityMatchFilter.java @@ -21,6 +21,7 @@ package com.puppycrawl.tools.checkstyle.filters; import com.puppycrawl.tools.checkstyle.api.AuditEvent; import com.puppycrawl.tools.checkstyle.api.AutomaticBean; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.Filter; import com.puppycrawl.tools.checkstyle.api.SeverityLevel; @@ -59,6 +60,11 @@ public class SeverityMatchFilter } @Override + protected void finishLocalSetup() throws CheckstyleException { + // No code by default + } + + @Override public boolean accept(AuditEvent event) { final boolean severityMatches = severity == event.getSeverityLevel(); return acceptOnMatch == severityMatches; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressElement.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressElement.java index ad2d6d23e..21c17eea1 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressElement.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressElement.java @@ -24,7 +24,6 @@ import java.util.regex.Pattern; import com.puppycrawl.tools.checkstyle.api.AuditEvent; import com.puppycrawl.tools.checkstyle.api.Filter; -import com.puppycrawl.tools.checkstyle.utils.CommonUtils; /** * This filter processes {@link AuditEvent} @@ -53,6 +52,12 @@ public class SuppressElement /** The pattern for check class names. */ private final String checkPattern; + /** The regexp to match message names against. */ + private final Pattern messageRegexp; + + /** The pattern for message names. */ + private final String messagePattern; + /** Module id filter. */ private final String moduleId; @@ -74,20 +79,33 @@ public class SuppressElement * * @param files regular expression for names of filtered files. * @param checks regular expression for filtered check classes. + * @param message regular expression for messages. * @param modId the id * @param lines lines CSV values and ranges for line number filtering. * @param columns columns CSV values and ranges for column number filtering. */ public SuppressElement(String files, String checks, - String modId, String lines, String columns) { + String message, String modId, String lines, String columns) { filePattern = files; - fileRegexp = Pattern.compile(files); + if (files == null) { + fileRegexp = null; + } + else { + fileRegexp = Pattern.compile(files); + } checkPattern = checks; if (checks == null) { checkRegexp = null; } else { - checkRegexp = CommonUtils.createPattern(checks); + checkRegexp = Pattern.compile(checks); + } + messagePattern = message; + if (message == null) { + messageRegexp = null; + } + else { + messageRegexp = Pattern.compile(message); } moduleId = modId; linesCsv = lines; @@ -109,6 +127,7 @@ public class SuppressElement @Override public boolean accept(AuditEvent event) { return isFileNameAndModuleNotMatching(event) + || !isMessageNameMatching(event) || isLineAndColumnMatch(event); } @@ -119,13 +138,22 @@ public class SuppressElement */ private boolean isFileNameAndModuleNotMatching(AuditEvent event) { return event.getFileName() == null - || !fileRegexp.matcher(event.getFileName()).find() + || fileRegexp != null && !fileRegexp.matcher(event.getFileName()).find() || event.getLocalizedMessage() == null || moduleId != null && !moduleId.equals(event.getModuleId()) || checkRegexp != null && !checkRegexp.matcher(event.getSourceName()).find(); } /** + * Is matching by message. + * @param event event + * @return true is matching or not set. + */ + private boolean isMessageNameMatching(AuditEvent event) { + return messageRegexp == null || messageRegexp.matcher(event.getMessage()).find(); + } + + /** * Whether line and column match. * @param event event to process. * @return true if line and column match. @@ -138,7 +166,8 @@ public class SuppressElement @Override public int hashCode() { - return Objects.hash(filePattern, checkPattern, moduleId, linesCsv, columnsCsv); + return Objects.hash(filePattern, checkPattern, messagePattern, moduleId, linesCsv, + columnsCsv); } @Override @@ -152,6 +181,7 @@ public class SuppressElement final SuppressElement suppressElement = (SuppressElement) other; return Objects.equals(filePattern, suppressElement.filePattern) && Objects.equals(checkPattern, suppressElement.checkPattern) + && Objects.equals(messagePattern, suppressElement.messagePattern) && Objects.equals(moduleId, suppressElement.moduleId) && Objects.equals(linesCsv, suppressElement.linesCsv) && Objects.equals(columnsCsv, suppressElement.columnsCsv); diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWarningsFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWarningsFilter.java index 4e2c6bb5b..f2577138c 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWarningsFilter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWarningsFilter.java @@ -21,6 +21,7 @@ package com.puppycrawl.tools.checkstyle.filters; import com.puppycrawl.tools.checkstyle.api.AuditEvent; import com.puppycrawl.tools.checkstyle.api.AutomaticBean; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.Filter; import com.puppycrawl.tools.checkstyle.checks.SuppressWarningsHolder; @@ -33,6 +34,11 @@ public class SuppressWarningsFilter extends AutomaticBean implements Filter { @Override + protected void finishLocalSetup() throws CheckstyleException { + // No code by default + } + + @Override public boolean accept(AuditEvent event) { return !SuppressWarningsHolder.isSuppressed(event); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithNearbyCommentFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithNearbyCommentFilter.java index 85a387b64..d3fa968ce 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithNearbyCommentFilter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithNearbyCommentFilter.java @@ -31,6 +31,7 @@ import java.util.regex.PatternSyntaxException; import com.puppycrawl.tools.checkstyle.TreeWalkerAuditEvent; import com.puppycrawl.tools.checkstyle.TreeWalkerFilter; import com.puppycrawl.tools.checkstyle.api.AutomaticBean; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.FileContents; import com.puppycrawl.tools.checkstyle.api.TextBlock; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; @@ -183,6 +184,11 @@ public class SuppressWithNearbyCommentFilter } @Override + protected void finishLocalSetup() throws CheckstyleException { + // No code by default + } + + @Override public boolean accept(TreeWalkerAuditEvent event) { boolean accepted = true; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithPlainTextCommentFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithPlainTextCommentFilter.java new file mode 100644 index 000000000..ad380845e --- /dev/null +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressWithPlainTextCommentFilter.java @@ -0,0 +1,349 @@ +//////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code for adherence to a set of rules. +// Copyright (C) 2001-2017 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.filters; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import com.puppycrawl.tools.checkstyle.api.AuditEvent; +import com.puppycrawl.tools.checkstyle.api.AutomaticBean; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; +import com.puppycrawl.tools.checkstyle.api.FileText; +import com.puppycrawl.tools.checkstyle.api.Filter; +import com.puppycrawl.tools.checkstyle.utils.CommonUtils; + +/** + * <p> + * A filter that uses comments to suppress audit events. + * The filter can be used only to suppress audit events received from + * {@link com.puppycrawl.tools.checkstyle.api.FileSetCheck} checks. + * SuppressWithPlainTextCommentFilter knows nothing about AST, + * it treats only plain text comments and extracts the information required for suppression from + * the plain text comments. Currently the filter supports only single line comments. + * </p> + * <p> + * Rationale: + * Sometimes there are legitimate reasons for violating a check. When + * this is a matter of the code in question and not personal + * preference, the best place to override the policy is in the code + * itself. Semi-structured comments can be associated with the check. + * This is sometimes superior to a separate suppressions file, which + * must be kept up-to-date as the source file is edited. + * </p> + * @author Andrei Selkin + */ +public class SuppressWithPlainTextCommentFilter extends AutomaticBean implements Filter { + + /** Comment format which turns checkstyle reporting off. */ + private static final String DEFAULT_OFF_FORMAT = "// CHECKSTYLE:OFF"; + + /** Comment format which turns checkstyle reporting on. */ + private static final String DEFAULT_ON_FORMAT = "// CHECKSTYLE:ON"; + + /** Default check format to suppress. By default the filter suppress all checks. */ + private static final String DEFAULT_CHECK_FORMAT = ".*"; + + /** Regexp which turns checkstyle reporting off. */ + private Pattern offCommentFormat = CommonUtils.createPattern(DEFAULT_OFF_FORMAT); + + /** Regexp which turns checkstyle reporting on. */ + private Pattern onCommentFormat = CommonUtils.createPattern(DEFAULT_ON_FORMAT); + + /** The check format to suppress. */ + private String checkFormat = DEFAULT_CHECK_FORMAT; + + /** The message format to suppress.*/ + private String messageFormat; + + /** + * Sets an off comment format pattern. + * @param pattern off comment format pattern. + */ + public final void setOffCommentFormat(Pattern pattern) { + offCommentFormat = pattern; + } + + /** + * Sets an on comment format pattern. + * @param pattern on comment format pattern. + */ + public final void setOnCommentFormat(Pattern pattern) { + onCommentFormat = pattern; + } + + /** + * Sets a pattern for check format. + * @param format pattern for check format. + */ + public final void setCheckFormat(String format) { + checkFormat = format; + } + + /** + * Sets a pattern for message format. + * @param format pattern for message format. + */ + public final void setMessageFormat(String format) { + messageFormat = format; + } + + @Override + public boolean accept(AuditEvent event) { + boolean accepted = true; + if (event.getLocalizedMessage() != null) { + final FileText fileText = getFileText(event.getFileName()); + if (fileText != null) { + final List<Suppression> suppressions = getSuppressions(fileText); + accepted = getNearestSuppression(suppressions, event) == null; + } + } + return accepted; + } + + @Override + protected void finishLocalSetup() throws CheckstyleException { + // No code by default + } + + /** + * Returns {@link FileText} instance created based on the given file name. + * @param fileName the name of the file. + * @return {@link FileText} instance. + */ + private static FileText getFileText(String fileName) { + final File file = new File(fileName); + FileText result = null; + + // some violations can be on a directory, instead of a file + if (!file.isDirectory()) { + try { + result = new FileText(file, StandardCharsets.UTF_8.name()); + } + catch (IOException ex) { + throw new IllegalStateException("Cannot read source file: " + fileName, ex); + } + } + + return result; + } + + /** + * Returns the list of {@link Suppression} instances retrieved from the given {@link FileText}. + * @param fileText {@link FileText} instance. + * @return list of {@link Suppression} instances. + */ + private List<Suppression> getSuppressions(FileText fileText) { + final List<Suppression> suppressions = new ArrayList<>(); + for (int lineNo = 0; lineNo < fileText.size(); lineNo++) { + final Optional<Suppression> suppression = getSuppression(fileText, lineNo); + suppression.ifPresent(suppressions::add); + } + return suppressions; + } + + /** + * Tries to extract the suppression from the given line. + * @param fileText {@link FileText} instance. + * @param lineNo line number. + * @return {@link Optional} of {@link Suppression}. + */ + private Optional<Suppression> getSuppression(FileText fileText, int lineNo) { + final String line = fileText.get(lineNo); + final Matcher onCommentMatcher = onCommentFormat.matcher(line); + final Matcher offCommentMatcher = offCommentFormat.matcher(line); + + Suppression suppression = null; + if (onCommentMatcher.find()) { + suppression = new Suppression(onCommentMatcher.group(0), + lineNo + 1, onCommentMatcher.start(), SuppressionType.ON, this); + } + if (offCommentMatcher.find()) { + suppression = new Suppression(offCommentMatcher.group(0), + lineNo + 1, offCommentMatcher.start(), SuppressionType.OFF, this); + } + + return Optional.ofNullable(suppression); + } + + /** + * Finds the nearest {@link Suppression} instance which can suppress + * the given {@link AuditEvent}. The nearest suppression is the suppression which scope + * is before the line and column of the event. + * @param suppressions {@link Suppression} instance. + * @param event {@link AuditEvent} instance. + * @return {@link Suppression} instance. + */ + private static Suppression getNearestSuppression(List<Suppression> suppressions, + AuditEvent event) { + return suppressions + .stream() + .filter(suppression -> suppression.isMatch(event)) + .reduce((first, second) -> second) + .filter(suppression -> suppression.suppressionType != SuppressionType.ON) + .orElse(null); + } + + /** Enum which represents the type of the suppression. */ + private enum SuppressionType { + + /** On suppression type. */ + ON, + /** Off suppression type. */ + OFF + + } + + /** The class which represents the suppression. */ + public static class Suppression { + + /** The regexp which is used to match the event source.*/ + private final Pattern eventSourceRegexp; + /** The regexp which is used to match the event message.*/ + private final Pattern eventMessageRegexp; + + /** Suppression text.*/ + private final String text; + /** Suppression line.*/ + private final int lineNo; + /** Suppression column number.*/ + private final int columnNo; + /** Suppression type. */ + private final SuppressionType suppressionType; + + /** + * Creates new suppression instance. + * @param text suppression text. + * @param lineNo suppression line number. + * @param columnNo suppression column number. + * @param suppressionType suppression type. + * @param filter the {@link SuppressWithPlainTextCommentFilter} with the context. + */ + protected Suppression( + String text, + int lineNo, + int columnNo, + SuppressionType suppressionType, + SuppressWithPlainTextCommentFilter filter + ) { + this.text = text; + this.lineNo = lineNo; + this.columnNo = columnNo; + this.suppressionType = suppressionType; + + //Expand regexp for check and message + //Does not intern Patterns with Utils.getPattern() + String format = ""; + try { + if (this.suppressionType == SuppressionType.ON) { + format = CommonUtils.fillTemplateWithStringsByRegexp( + filter.checkFormat, text, filter.onCommentFormat); + eventSourceRegexp = Pattern.compile(format); + if (filter.messageFormat == null) { + eventMessageRegexp = null; + } + else { + format = CommonUtils.fillTemplateWithStringsByRegexp( + filter.messageFormat, text, filter.onCommentFormat); + eventMessageRegexp = Pattern.compile(format); + } + } + else { + format = CommonUtils.fillTemplateWithStringsByRegexp( + filter.checkFormat, text, filter.offCommentFormat); + eventSourceRegexp = Pattern.compile(format); + if (filter.messageFormat == null) { + eventMessageRegexp = null; + } + else { + format = CommonUtils.fillTemplateWithStringsByRegexp( + filter.messageFormat, text, filter.offCommentFormat); + eventMessageRegexp = Pattern.compile(format); + } + } + } + catch (final PatternSyntaxException ex) { + throw new IllegalArgumentException( + "unable to parse expanded comment " + format, ex); + } + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + final Suppression suppression = (Suppression) other; + return Objects.equals(lineNo, suppression.lineNo) + && Objects.equals(columnNo, suppression.columnNo) + && Objects.equals(suppressionType, suppression.suppressionType) + && Objects.equals(text, suppression.text) + && Objects.equals(eventSourceRegexp, suppression.eventSourceRegexp) + && Objects.equals(eventMessageRegexp, suppression.eventMessageRegexp); + } + + @Override + public int hashCode() { + return Objects.hash( + text, lineNo, columnNo, suppressionType, eventSourceRegexp, eventMessageRegexp); + } + + /** + * Checks whether the suppression matches the given {@link AuditEvent}. + * @param event {@link AuditEvent} instance. + * @return true if the suppression matches {@link AuditEvent}. + */ + private boolean isMatch(AuditEvent event) { + boolean match = false; + if (isInScopeOfSuppression(event)) { + final Matcher sourceNameMatcher = eventSourceRegexp.matcher(event.getSourceName()); + if (sourceNameMatcher.find()) { + match = eventMessageRegexp == null + || eventMessageRegexp.matcher(event.getMessage()).find(); + } + else { + match = event.getModuleId() != null + && eventSourceRegexp.matcher(event.getModuleId()).find(); + } + } + return match; + } + + /** + * Checks whether {@link AuditEvent} is in the scope of the suppression. + * @param event {@link AuditEvent} instance. + * @return true if {@link AuditEvent} is in the scope of the suppression. + */ + private boolean isInScopeOfSuppression(AuditEvent event) { + return lineNo <= event.getLine(); + } + } + +} diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilter.java index e87139594..386964a8a 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionCommentFilter.java @@ -32,6 +32,7 @@ import java.util.regex.PatternSyntaxException; import com.puppycrawl.tools.checkstyle.TreeWalkerAuditEvent; import com.puppycrawl.tools.checkstyle.TreeWalkerFilter; import com.puppycrawl.tools.checkstyle.api.AutomaticBean; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.FileContents; import com.puppycrawl.tools.checkstyle.api.TextBlock; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; @@ -179,6 +180,11 @@ public class SuppressionCommentFilter } @Override + protected void finishLocalSetup() throws CheckstyleException { + // No code by default + } + + @Override public boolean accept(TreeWalkerAuditEvent event) { boolean accepted = true; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilter.java index 814ea3173..35e59834e 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionFilter.java @@ -42,7 +42,7 @@ import com.puppycrawl.tools.checkstyle.utils.FilterUtils; */ public class SuppressionFilter extends AutomaticBean implements Filter, ExternalResourceHolder { - /** Filename of supression file. */ + /** Filename of suppression file. */ private String file; /** Tells whether config file existence is optional. */ private boolean optional; @@ -50,7 +50,7 @@ public class SuppressionFilter extends AutomaticBean implements Filter, External private FilterSet filters = new FilterSet(); /** - * Sets name of the supression file. + * Sets name of the suppression file. * @param fileName name of the suppressions file. */ public void setFile(String fileName) { diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionXpathFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionXpathFilter.java index f4b254074..9363ed5ca 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionXpathFilter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionXpathFilter.java @@ -41,7 +41,7 @@ import com.puppycrawl.tools.checkstyle.utils.FilterUtils; public class SuppressionXpathFilter extends AutomaticBean implements TreeWalkerFilter, ExternalResourceHolder { - /** Filename of supression file. */ + /** Filename of suppression file. */ private String file; /** Tells whether config file existence is optional. */ private boolean optional; @@ -49,7 +49,7 @@ public class SuppressionXpathFilter extends AutomaticBean implements private Set<TreeWalkerFilter> filters = new HashSet<>(); /** - * Sets name of the supression file. + * Sets name of the suppression file. * @param fileName name of the suppressions file. */ public void setFile(String fileName) { diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionsLoader.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionsLoader.java index ee3c66ed8..ced67bc97 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionsLoader.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/SuppressionsLoader.java @@ -36,7 +36,7 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.puppycrawl.tools.checkstyle.TreeWalkerFilter; -import com.puppycrawl.tools.checkstyle.api.AbstractLoader; +import com.puppycrawl.tools.checkstyle.XmlLoader; import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.FilterSet; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; @@ -46,25 +46,37 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtils; * @author Rick Giles */ public final class SuppressionsLoader - extends AbstractLoader { + extends XmlLoader { /** The public ID for the configuration dtd. */ private static final String DTD_PUBLIC_ID_1_0 = "-//Puppy Crawl//DTD Suppressions 1.0//EN"; /** The resource for the configuration dtd. */ - private static final String DTD_RESOURCE_NAME_1_0 = + private static final String DTD_SUPPRESSIONS_NAME_1_0 = "com/puppycrawl/tools/checkstyle/suppressions_1_0.dtd"; /** The public ID for the configuration dtd. */ private static final String DTD_PUBLIC_ID_1_1 = "-//Puppy Crawl//DTD Suppressions 1.1//EN"; /** The resource for the configuration dtd. */ - private static final String DTD_RESOURCE_NAME_1_1 = + private static final String DTD_SUPPRESSIONS_NAME_1_1 = "com/puppycrawl/tools/checkstyle/suppressions_1_1.dtd"; /** The public ID for the configuration dtd. */ + private static final String DTD_PUBLIC_ID_1_2 = + "-//Puppy Crawl//DTD Suppressions 1.2//EN"; + /** The resource for the configuration dtd. */ + private static final String DTD_SUPPRESSIONS_NAME_1_2 = + "com/puppycrawl/tools/checkstyle/suppressions_1_2.dtd"; + /** The public ID for the configuration dtd. */ private static final String DTD_PUBLIC_ID_1_1_XPATH = "-//Puppy Crawl//DTD Suppressions Xpath Experimental 1.1//EN"; /** The resource for the configuration dtd. */ - private static final String DTD_RESOURCE_NAME_1_1_XPATH = + private static final String DTD_SUPPRESSIONS_NAME_1_1_XPATH = "com/puppycrawl/tools/checkstyle/suppressions_1_1_xpath_experimental.dtd"; + /** The public ID for the configuration dtd. */ + private static final String DTD_PUBLIC_ID_1_2_XPATH = + "-//Puppy Crawl//DTD Suppressions Xpath Experimental 1.2//EN"; + /** The resource for the configuration dtd. */ + private static final String DTD_SUPPRESSIONS_NAME_1_2_XPATH = + "com/puppycrawl/tools/checkstyle/suppressions_1_2_xpath_experimental.dtd"; /** File search error message. **/ private static final String UNABLE_TO_FIND_ERROR_MESSAGE = "Unable to find: "; /** String literal for attribute name. **/ @@ -72,6 +84,8 @@ public final class SuppressionsLoader /** String literal for attribute name. **/ private static final String ATTRIBUTE_NAME_CHECKS = "checks"; /** String literal for attribute name. **/ + private static final String ATTRIBUTE_NAME_MESSAGE = "message"; + /** String literal for attribute name. **/ private static final String ATTRIBUTE_NAME_ID = "id"; /** String literal for attribute name. **/ private static final String ATTRIBUTE_NAME_QUERY = "query"; @@ -128,20 +142,21 @@ public final class SuppressionsLoader private static SuppressElement getSuppressElement(Attributes attributes) throws SAXException { final String checks = attributes.getValue(ATTRIBUTE_NAME_CHECKS); final String modId = attributes.getValue(ATTRIBUTE_NAME_ID); - if (checks == null && modId == null) { + final String message = attributes.getValue(ATTRIBUTE_NAME_MESSAGE); + if (checks == null && modId == null && message == null) { // -@cs[IllegalInstantiation] SAXException is in the overridden method signature - throw new SAXException("missing checks and id attribute"); + throw new SAXException("missing checks or id or message attribute"); } final SuppressElement suppress; try { final String files = attributes.getValue(ATTRIBUTE_NAME_FILES); final String lines = attributes.getValue(ATTRIBUTE_NAME_LINES); final String columns = attributes.getValue(ATTRIBUTE_NAME_COLUMNS); - suppress = new SuppressElement(files, checks, modId, lines, columns); + suppress = new SuppressElement(files, checks, message, modId, lines, columns); } catch (final PatternSyntaxException ex) { // -@cs[IllegalInstantiation] SAXException is in the overridden method signature - throw new SAXException("invalid files or checks format", ex); + throw new SAXException("invalid files or checks or message format", ex); } return suppress; } @@ -156,19 +171,21 @@ public final class SuppressionsLoader private static XpathFilter getXpathFilter(Attributes attributes) throws SAXException { final String checks = attributes.getValue(ATTRIBUTE_NAME_CHECKS); final String modId = attributes.getValue(ATTRIBUTE_NAME_ID); - if (checks == null && modId == null) { + final String message = attributes.getValue(ATTRIBUTE_NAME_MESSAGE); + if (checks == null && modId == null && message == null) { // -@cs[IllegalInstantiation] SAXException is in the overridden method signature - throw new SAXException("missing checks and id attribute for suppress-xpath"); + throw new SAXException("missing checks or id or message attribute for suppress-xpath"); } final XpathFilter filter; try { final String files = attributes.getValue(ATTRIBUTE_NAME_FILES); final String xpathQuery = attributes.getValue(ATTRIBUTE_NAME_QUERY); - filter = new XpathFilter(files, checks, modId, xpathQuery); + filter = new XpathFilter(files, checks, message, modId, xpathQuery); } catch (final PatternSyntaxException ex) { // -@cs[IllegalInstantiation] SAXException is in the overridden method signature - throw new SAXException("invalid files or checks format for suppress-xpath", ex); + throw new SAXException("invalid files or checks or message format for suppress-xpath", + ex); } return filter; } @@ -266,9 +283,11 @@ public final class SuppressionsLoader */ private static Map<String, String> createIdToResourceNameMap() { final Map<String, String> map = new HashMap<>(); - map.put(DTD_PUBLIC_ID_1_0, DTD_RESOURCE_NAME_1_0); - map.put(DTD_PUBLIC_ID_1_1, DTD_RESOURCE_NAME_1_1); - map.put(DTD_PUBLIC_ID_1_1_XPATH, DTD_RESOURCE_NAME_1_1_XPATH); + map.put(DTD_PUBLIC_ID_1_0, DTD_SUPPRESSIONS_NAME_1_0); + map.put(DTD_PUBLIC_ID_1_1, DTD_SUPPRESSIONS_NAME_1_1); + map.put(DTD_PUBLIC_ID_1_2, DTD_SUPPRESSIONS_NAME_1_2); + map.put(DTD_PUBLIC_ID_1_1_XPATH, DTD_SUPPRESSIONS_NAME_1_1_XPATH); + map.put(DTD_PUBLIC_ID_1_2_XPATH, DTD_SUPPRESSIONS_NAME_1_2_XPATH); return map; } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/filters/XpathFilter.java b/src/main/java/com/puppycrawl/tools/checkstyle/filters/XpathFilter.java index 8079be3df..600340404 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/filters/XpathFilter.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/filters/XpathFilter.java @@ -53,6 +53,12 @@ public class XpathFilter implements TreeWalkerFilter { /** The pattern for check class names. */ private final String checkPattern; + /** The regexp to match message names against. */ + private final Pattern messageRegexp; + + /** The pattern for message names. */ + private final String messagePattern; + /** Module id filter. */ private final String moduleId; @@ -66,13 +72,19 @@ public class XpathFilter implements TreeWalkerFilter { * Creates a {@code XpathElement} instance. * @param files regular expression for names of filtered files * @param checks regular expression for filtered check classes + * @param message regular expression for messages. * @param moduleId the module id * @param query the xpath query */ public XpathFilter(String files, String checks, - String moduleId, String query) { + String message, String moduleId, String query) { filePattern = files; - fileRegexp = Pattern.compile(files); + if (files == null) { + fileRegexp = null; + } + else { + fileRegexp = Pattern.compile(files); + } checkPattern = checks; if (checks == null) { checkRegexp = null; @@ -80,6 +92,13 @@ public class XpathFilter implements TreeWalkerFilter { else { checkRegexp = CommonUtils.createPattern(checks); } + messagePattern = message; + if (message == null) { + messageRegexp = null; + } + else { + messageRegexp = Pattern.compile(message); + } this.moduleId = moduleId; xpathQuery = query; if (xpathQuery == null) { @@ -99,6 +118,7 @@ public class XpathFilter implements TreeWalkerFilter { @Override public boolean accept(TreeWalkerAuditEvent event) { return !isFileNameAndModuleAndCheckNameMatching(event) + || !isMessageNameMatching(event) || !isXpathQueryMatching(event); } @@ -109,26 +129,39 @@ public class XpathFilter implements TreeWalkerFilter { */ private boolean isFileNameAndModuleAndCheckNameMatching(TreeWalkerAuditEvent event) { return event.getFileName() != null - && fileRegexp.matcher(event.getFileName()).find() + && (fileRegexp == null || fileRegexp.matcher(event.getFileName()).find()) && event.getLocalizedMessage() != null && (moduleId == null || moduleId.equals(event.getModuleId())) && (checkRegexp == null || checkRegexp.matcher(event.getSourceName()).find()); } /** + * Is matching by message. + * @param event event + * @return true is matching or not set. + */ + private boolean isMessageNameMatching(TreeWalkerAuditEvent event) { + return messageRegexp == null || messageRegexp.matcher(event.getMessage()).find(); + } + + /** * Is matching by xpath query. * @param event event * @return true is matching */ private boolean isXpathQueryMatching(TreeWalkerAuditEvent event) { - boolean isMatching = false; - if (xpathExpression != null) { + boolean isMatching; + if (xpathExpression == null) { + isMatching = true; + } + else { + isMatching = false; final List<Item> items = getItems(event); for (Item item : items) { final AbstractNode abstractNode = (AbstractNode) item; isMatching = abstractNode.getTokenType() == event.getTokenType() && abstractNode.getLineNumber() == event.getLine() - && abstractNode.getColumnNumber() == event.getColumn(); + && abstractNode.getColumnNumber() == event.getColumnCharIndex(); if (isMatching) { break; } @@ -165,7 +198,7 @@ public class XpathFilter implements TreeWalkerFilter { @Override public int hashCode() { - return Objects.hash(filePattern, checkPattern, moduleId, xpathQuery); + return Objects.hash(filePattern, checkPattern, messagePattern, moduleId, xpathQuery); } @Override @@ -179,6 +212,7 @@ public class XpathFilter implements TreeWalkerFilter { final XpathFilter xpathFilter = (XpathFilter) other; return Objects.equals(filePattern, xpathFilter.filePattern) && Objects.equals(checkPattern, xpathFilter.checkPattern) + && Objects.equals(messagePattern, xpathFilter.messagePattern) && Objects.equals(moduleId, xpathFilter.moduleId) && Objects.equals(xpathQuery, xpathFilter.xpathQuery); } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/AnnotationUtility.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/AnnotationUtility.java index bb673e99b..a36d6092d 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/AnnotationUtility.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/AnnotationUtility.java @@ -155,7 +155,7 @@ public final class AnnotationUtility { for (DetailAST child = holder.getFirstChild(); child != null; child = child.getNextSibling()) { if (child.getType() == TokenTypes.ANNOTATION) { - final DetailAST firstChild = child.getFirstChild(); + final DetailAST firstChild = child.findFirstToken(TokenTypes.AT); final String name = FullIdent.createFullIdent(firstChild.getNextSibling()).getText(); if (annotation.equals(name)) { diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/BlockCommentPosition.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/BlockCommentPosition.java index f35404e7e..5d4934261 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/BlockCommentPosition.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/BlockCommentPosition.java @@ -36,6 +36,18 @@ public final class BlockCommentPosition { } /** + * Node is on type definition. + * @param blockComment DetailAST + * @return true if node is before class, interface, enum or annotation. + */ + public static boolean isOnType(DetailAST blockComment) { + return isOnClass(blockComment) + || isOnInterface(blockComment) + || isOnEnum(blockComment) + || isOnAnnotationDef(blockComment); + } + + /** * Node is on class definition. * @param blockComment DetailAST * @return true if node is before class @@ -80,6 +92,20 @@ public final class BlockCommentPosition { } /** + * Node is on type member declaration. + * @param blockComment DetailAST + * @return true if node is before method, field, constructor, enum constant + * or annotation field + */ + public static boolean isOnMember(DetailAST blockComment) { + return isOnMethod(blockComment) + || isOnField(blockComment) + || isOnConstructor(blockComment) + || isOnEnumConstant(blockComment) + || isOnAnnotationField(blockComment); + } + + /** * Node is on method declaration. * @param blockComment DetailAST * @return true if node is before method @@ -130,6 +156,17 @@ public final class BlockCommentPosition { } /** + * Node is on annotation field declaration. + * @param blockComment DetailAST + * @return true if node is before annotation field + */ + public static boolean isOnAnnotationField(DetailAST blockComment) { + return isOnPlainClassMember(blockComment, TokenTypes.ANNOTATION_FIELD_DEF) + || isOnTokenWithModifiers(blockComment, TokenTypes.ANNOTATION_FIELD_DEF) + || isOnTokenWithAnnotation(blockComment, TokenTypes.ANNOTATION_FIELD_DEF); + } + + /** * Checks that block comment is on specified token without any modifiers. * @param blockComment block comment start DetailAST * @param parentTokenType parent token type @@ -179,11 +216,16 @@ public final class BlockCommentPosition { * @return true if block comment is on specified token without modifiers */ private static boolean isOnPlainClassMember(DetailAST blockComment, int memberType) { - return blockComment.getParent() != null - && blockComment.getParent().getType() == TokenTypes.TYPE - && blockComment.getParent().getParent().getType() == memberType + DetailAST parent = blockComment.getParent(); + // type could be in fully qualified form, so we go up to Type token + while (parent != null && parent.getType() == TokenTypes.DOT) { + parent = parent.getParent(); + } + return parent != null + && parent.getType() == TokenTypes.TYPE + && parent.getParent().getType() == memberType // previous parent sibling is always TokenTypes.MODIFIERS - && blockComment.getParent().getPreviousSibling().getChildCount() == 0; + && parent.getPreviousSibling().getChildCount() == 0; } /** diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/CommonUtils.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/CommonUtils.java index 14b3e03b5..122c6f277 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/CommonUtils.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/CommonUtils.java @@ -129,7 +129,7 @@ public final class CommonUtils { commentContent.setText("*" + content); commentContent.setLineNo(0); // javadoc should starts at 0 column, so COMMENT_CONTENT node - // that contains javadoc identificator has -1 column + // that contains javadoc identifier has -1 column commentContent.setColumnNo(-1); final DetailAST blockCommentEnd = new DetailAST(); diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/JavadocUtils.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/JavadocUtils.java index b744167cd..947760370 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/JavadocUtils.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/JavadocUtils.java @@ -30,6 +30,7 @@ import com.puppycrawl.tools.checkstyle.api.DetailAST; import com.puppycrawl.tools.checkstyle.api.DetailNode; import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes; import com.puppycrawl.tools.checkstyle.api.TextBlock; +import com.puppycrawl.tools.checkstyle.api.TokenTypes; import com.puppycrawl.tools.checkstyle.checks.javadoc.InvalidJavadocTag; import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTag; import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTagInfo; @@ -176,8 +177,8 @@ public final class JavadocUtils { boolean result = false; if (!commentContent.isEmpty()) { - final char docCommentIdentificator = commentContent.charAt(0); - result = docCommentIdentificator == '*'; + final char docCommentIdentifier = commentContent.charAt(0); + result = docCommentIdentifier == '*'; } return result; @@ -400,24 +401,40 @@ public final class JavadocUtils { /** * Checks Javadoc comment it's in right place. - * From Javadoc util documentation: + * <p>From Javadoc util documentation: * "Placement of comments - Documentation comments are recognized only when placed - * immediately before class, interface, constructor, method, or field + * immediately before class, interface, constructor, method, field or annotation field * declarations -- see the class example, method example, and field example. - * Documentation comments placed in the body of a method are ignored. Only one - * documentation comment per declaration statement is recognized by the Javadoc tool." + * Documentation comments placed in the body of a method are ignored."</p> + * <p>If there are many documentation comments per declaration statement, + * only the last one will be recognized.</p> * * @param blockComment Block comment AST * @return true if Javadoc is in right place + * @see <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javadoc.html"> + * Javadoc util documentation</a> */ private static boolean isCorrectJavadocPosition(DetailAST blockComment) { - return BlockCommentPosition.isOnClass(blockComment) - || BlockCommentPosition.isOnInterface(blockComment) - || BlockCommentPosition.isOnEnum(blockComment) - || BlockCommentPosition.isOnMethod(blockComment) - || BlockCommentPosition.isOnField(blockComment) - || BlockCommentPosition.isOnConstructor(blockComment) - || BlockCommentPosition.isOnEnumConstant(blockComment) - || BlockCommentPosition.isOnAnnotationDef(blockComment); + // We must be sure that after this one there are no other documentation comments. + DetailAST sibling = blockComment.getNextSibling(); + while (sibling != null) { + if (sibling.getType() == TokenTypes.BLOCK_COMMENT_BEGIN) { + if (isJavadocComment(getBlockCommentContent(sibling))) { + // Found another javadoc comment, so this one should be ignored. + break; + } + sibling = sibling.getNextSibling(); + } + else if (sibling.getType() == TokenTypes.SINGLE_LINE_COMMENT) { + sibling = sibling.getNextSibling(); + } + else { + // Annotation, declaration or modifier is here. Do not check further. + sibling = null; + } + } + return sibling == null + && (BlockCommentPosition.isOnType(blockComment) + || BlockCommentPosition.isOnMember(blockComment)); } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtils.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtils.java index c05c21c0c..d52f7041c 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtils.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/ModuleReflectionUtils.java @@ -73,7 +73,7 @@ public final class ModuleReflectionUtils { */ public static boolean isCheckstyleModule(Class<?> clazz) { return isValidCheckstyleClass(clazz) - && (isCheckstyleCheck(clazz) + && (isCheckstyleTreeWalkerCheck(clazz) || isFileSetModule(clazz) || isFilterModule(clazz) || isFileFilterModule(clazz) @@ -111,12 +111,13 @@ public final class ModuleReflectionUtils { } /** - * Checks whether a class may be considered as the checkstyle check. + * Checks whether a class may be considered as the checkstyle check + * which has TreeWalker as a parent. * Checkstyle's checks are classes which implement 'AbstractCheck' interface. * @param clazz class to check. * @return true if a class may be considered as the checkstyle check. */ - public static boolean isCheckstyleCheck(Class<?> clazz) { + public static boolean isCheckstyleTreeWalkerCheck(Class<?> clazz) { return AbstractCheck.class.isAssignableFrom(clazz); } diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties index 64b56e1a2..7a2168816 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages.properties @@ -44,7 +44,8 @@ overload.methods.declaration=Overload methods should not be split. Previous over parameter.assignment=Assignment of parameter ''{0}'' is not allowed. require.this.method=Method call to ''{0}'' needs \"{1}this.\". require.this.variable=Reference to instance variable ''{0}'' needs \"{1}this.\". -return.count=Return count is {0,number,integer} (max allowed is {1,number,integer}). +return.count=Return count is {0,number,integer} (max allowed for non-void methods/lambdas is {1,number,integer}). +return.countVoid=Return count is {0,number,integer} (max allowed for void methods/constructors/lambdas is {1,number,integer}). simplify.boolReturn=Conditional logic can be removed. simplify.expression=Expression can be simplified. string.literal.equality=Literal Strings should be compared using equals(), not ''{0}''. diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_de.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_de.properties index bb1308e27..6e46475d4 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_de.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_de.properties @@ -44,7 +44,8 @@ overload.methods.declaration=Die Definition der überladene Methoden steht nicht parameter.assignment=Die Zuweisung des Parameters ''{0}'' ist nicht erlaubt. require.this.method=Der Methodenaufruf ''{0}'' erfordert ein vorangestelltes \"{1}this.\". require.this.variable=Der Instanzvariablenzugriff ''{0}'' erfordert ein vorangestelltes \"{1}this.\". -return.count=Die Methode hat insgesamt {0,number,integer} return-Anweisungen (Obergrenze ist {1,number,integer}). +return.count=Die Methode hat insgesamt {0,number,integer} return-Anweisungen (max erlaubt für nicht void Methoden / Lambdas ist ist {1,number,integer}). +return.countVoid=Die Methode hat insgesamt {0,number,integer} return-Anweisungen (max erlaubt für void Methoden / Konstruktoren / Lambdas ist {1,number,integer}). simplify.boolReturn=Die Verzweigungslogik kann entfernt werden. simplify.expression=Der Ausdruck kann vereinfacht werden. string.literal.equality=Der Vergleich von String-Literalen sollte mit equals() erfolgen, nicht mit ''{0}''. diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_es.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_es.properties index 1a97e0017..3f7b7f6a8 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_es.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_es.properties @@ -44,7 +44,8 @@ overload.methods.declaration=Métodos de sobrecarga no deben ser divididos. Mét parameter.assignment=No esta permitida la asignación del parámetro ''{0}''. require.this.method=La llamada al método ''{0}'' necesita \"{1}this.\". require.this.variable=La referencia a la variable de instancia ''{0}'' necesita \"{1}this.\". -return.count=El número de sentencias return es {0,number,integer} (máximo permitido es {1,number,integer}). +return.count=El número de sentencias return es {0,number,integer} (max permitido para métodos no vacíos / lambdas es {1,number,integer}). +return.countVoid=El número de sentencias return es {0,number,integer} (max permitido para métodos / constructores / lambdas vacíos {1,number,integer}). simplify.boolReturn=Se puede eliminar la lógica condicional. simplify.expression=Se puede simplificar la expresión. string.literal.equality=Las cadenas literales deben compararse usando equals(), no ''{0}''. diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fi.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fi.properties index b28e231c1..1246514af 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fi.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fi.properties @@ -44,7 +44,8 @@ overload.methods.declaration=Ylikuormitus menetelmiä ei tulisi jakaa. Edellinen parameter.assignment=Tehtävä parametrin ''{0}'' ei ole sallittu. require.this.method=Menetelmä kehotus ''{0}'' tarvitsee \"{1}this.\". require.this.variable=Viittaus Esimerkiksi muuttuja ''{0}'' tarvitsee \"{1}this.\". -return.count=Paluu määrä on {0, number, integer} (max sallittu on {1, number, integer}). +return.count=Paluu määrä on {0, number, integer} (max sallittu ei-tyhjiin menetelmiin / lambdas {1, number, integer}). +return.countVoid=Paluu määrä on {0, number, integer} (max sallittu menetelmät / konstruktorit / lambdas ovat {1, number, integer}). simplify.boolReturn=Konditionaalilogiikan voisi poistaa. simplify.expression=Ilmaisua voisi yksinkertaistaa. string.literal.equality=Kirjaimellinen Strings pitäisi verrata käyttämällä tasavertaisten (), ei ''{0}''. diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fr.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fr.properties index 7ae8de9d5..a1d712fbf 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fr.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_fr.properties @@ -44,7 +44,8 @@ overload.methods.declaration=Les méthodes de surcharge ne doivent pas être sé parameter.assignment=Il est interdit d''affecter une valeur au paramètre ''{0}''. require.this.method=L''appel à la méthode ''{0}'' nécessite l''utilisation de \"{1}this.\". require.this.variable=La référence à la variable d''instance ''{0}'' doit utiliser \"{1}this.\". -return.count=Le nombre de return est de {0,number,integer} alors que le maximum autorisé est de {1,number,integer}. +return.count=Le nombre de return est de {0,number,integer} alors que le maximum méthodes non-nulles/lambdas {1,number,integer}. +return.countVoid=Le nombre de return est de {0,number,integer} alors que le maximum autorisé void methods/constructors/lambdas est de {1,number,integer}. simplify.boolReturn=Le test peut être supprimé et l''expression directement retournée. simplify.expression=L''expression peut être simplifiée. string.literal.equality=Les chaines de caractères littérales devraient être comparées avec la méthode equals() et pas avec ''{0}''. diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ja.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ja.properties index 98adfa1fa..ae74664c6 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ja.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_ja.properties @@ -44,7 +44,8 @@ overload.methods.declaration=オーバーロードされているメソッドは parameter.assignment=パラメータ ''{0}'' への代入は許可されていません。 require.this.method=メソッド ''{0}'' への呼び出しは、 \"{1}this.\" が必要です。 require.this.variable=インスタンス変数 ''{0}'' への参照には \"{1}this.\" が必要です。 -return.count=return が {0,number,integer} 個所あります(最大 {1,number,integer} まで)。 +return.count=return が {0,number,integer} 個所あります(非無効メソッド/ ラムダに許される最大値は {1,number,integer} まで)。 +return.countVoid=return が {0,number,integer} 個所あります(無効メソッド/コンストラクタ/ ラムダメソッドに許可される最大値は {1,number,integer} まで)。 simplify.boolReturn=条件ロジックはなくせます。 simplify.expression=表現は簡潔にできます。 string.literal.equality=リテラルの文字列は ''{0}'' ではなく、 equals() を使用して比較するべきです。 diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_pt.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_pt.properties index 73fb2cc7c..da79ad8de 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_pt.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_pt.properties @@ -44,7 +44,8 @@ overload.methods.declaration=Métodos de sobrecarga não devem ser separados. O parameter.assignment=A atribuição ao parâmetro ''{0}'' não é permitda. require.this.method=A chamada de método no ''{0}'' precisa de \"{1}this.\". require.this.variable=A referência à variável de instância ''{0}'' precisa de \"{1}this.\". -return.count=O número de \"return\"s é {0,number,integer} (o máximo permitido é {1,number,integer}). +return.count=O número de \"return\"s é {0,number,integer} (o máximo permitido para métodos não vazios/lambdas é {1,number,integer}). +return.countVoid=O número de \"return\"s é {0,number,integer} (o máximo permitido para vazios métodos/construtores/lambdas é {1,number,integer}). simplify.boolReturn=A lógica condicional pode ser removida. simplify.expression=A expressão pode ser simplicada. string.literal.equality=Literais de String deveriam ser comparados com \"equals()\", não com ''{0}''. diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_tr.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_tr.properties index da4f29763..4e278314c 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_tr.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_tr.properties @@ -45,7 +45,8 @@ overload.methods.declaration=Aşırı yük yöntemleri bölünmüş olmamalıdı parameter.assignment=''{0}'' parametresine atama yapılamaz. require.this.method=''{0}'' metoduna erişim \"{1}this.\" kullanılarak yapılmalıdır. require.this.variable=''{0}'' değişkenine erişim \"{1}this.\" kullanılarak yapılmalıdır. -return.count=Kullanılan ''return'' sayısı {0,number,integer} (maksimum izin verilen değer {1,number,integer}). +return.count=Kullanılan ''return'' sayısı {0,number,integer} (void olmayan yöntemler / lambdas için izin verilen maksimum sayı {1,number,integer}). +return.countVoid=Kullanılan ''return'' sayısı {0,number,integer} (void yöntemleri / kurucu / lambdas için izin verilen maksimum sayı {1,number,integer}). simplify.boolReturn=Koşul mantığı kaldırılabilir. simplify.expression=İfade sadeleştirilebilir. string.literal.equality=''String'' ifadeleri ''{0}'' kullanarak değil, equals() metodu kullanarak karşılaştırılmalı. diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_zh.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_zh.properties index 5bc59c5a1..51bf29a60 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_zh.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/coding/messages_zh.properties @@ -44,7 +44,8 @@ overload.methods.declaration=重载方法应写在一起,上一个重载方法 parameter.assignment=不应对方法参数''{0}''赋值。 require.this.method=对方法 ''{0}'' 的调用需要 \"{1}this.\"。 require.this.variable=对实例属性 ''{0}'' 的引用需要 \"{1}this.\"。 -return.count=Return 次数 {0,number,integer} 次(最多: {1,number,integer} 次)。 +return.count=Return 次数 {0,number,integer} 次(最大允许非空虚方法/ 拉姆达: {1,number,integer} 次)。 +return.countVoid=Return 次数 {0,number,integer} 次(最大允許為void方法/構造函數/ 拉姆达: {1,number,integer} 次)。 simplify.boolReturn=不必要的条件逻辑。 simplify.expression=表达式可被简化。 string.literal.equality=字符串应使用equals()方法进行比较,而非''{0}''。 diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/imports/messages_zh.properties b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/imports/messages_zh.properties index 5298c0e5d..0132462d5 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/checks/imports/messages_zh.properties +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/checks/imports/messages_zh.properties @@ -9,10 +9,10 @@ import.control.disallowed=不允许的导入: {0} 。 import.control.missing.file=找不到导入控制文件。 import.control.unknown.pkg=导入控制文件并未处理此包。 import.duplicate=第{0,number,integer}行重复导入:{1} 。 -import.groups.separated.internally=進口組以前的額外分離 ''{0}''。 -import.illegal=非法进口: {0} 。 +import.groups.separated.internally=导入组之前的额外空行 ''{0}''。 +import.illegal=非法导入: {0} 。 import.lang=不需要从 java.lang 包导入: {0} 。 import.ordering=导入 ''{0}'' 顺序错误。 -import.same=额外 import 当前包下内容:{0} 。 +import.same=额外导入当前包下内容:{0} 。 import.separation=''{0}'' 应与之前的导入语句通过空行隔开。 import.unused=无用导入 - {0} 。 diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/suppressions_1_2.dtd b/src/main/resources/com/puppycrawl/tools/checkstyle/suppressions_1_2.dtd new file mode 100644 index 000000000..56498682e --- /dev/null +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/suppressions_1_2.dtd @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- Add the following to any file that is to be validated against this DTD: + +<!DOCTYPE suppressions PUBLIC + "-//Puppy Crawl//DTD Suppressions 1.2//EN" + "http://checkstyle.sourceforge.net/dtds/suppressions_1_2.dtd"> +--> + +<!ELEMENT suppressions (suppress*)> + +<!ELEMENT suppress EMPTY> +<!ATTLIST suppress files CDATA #IMPLIED + checks CDATA #IMPLIED + message CDATA #IMPLIED + id CDATA #IMPLIED + lines CDATA #IMPLIED + columns CDATA #IMPLIED> diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/suppressions_1_2_xpath_experimental.dtd b/src/main/resources/com/puppycrawl/tools/checkstyle/suppressions_1_2_xpath_experimental.dtd new file mode 100644 index 000000000..f424d8e20 --- /dev/null +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/suppressions_1_2_xpath_experimental.dtd @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- Add the following to any file that is to be validated against this DTD: + +<!DOCTYPE suppressions PUBLIC + "-//Puppy Crawl//DTD Suppressions Xpath Experimental 1.2//EN" + "http://checkstyle.sourceforge.net/dtds/suppressions_1_2_xpath_experimental.dtd"> +--> + +<!ELEMENT suppressions (suppress|suppress-xpath)*> + +<!ELEMENT suppress EMPTY> +<!ATTLIST suppress files CDATA #IMPLIED + checks CDATA #IMPLIED + message CDATA #IMPLIED + id CDATA #IMPLIED + lines CDATA #IMPLIED + columns CDATA #IMPLIED> + +<!ELEMENT suppress-xpath EMPTY> +<!ATTLIST suppress-xpath files CDATA #IMPLIED + checks CDATA #IMPLIED + message CDATA #IMPLIED + id CDATA #IMPLIED + query CDATA #IMPLIED> |