diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractCheck.java index 430257d5dc1..c20752d4c4d 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/AbstractCheck.java @@ -246,7 +246,21 @@ public final void setTabWidth(int tabWidth) { * @param args arguments to format */ public final void log(DetailAST ast, String key, Object... args) { - log(ast.getLineNo(), ast.getColumnNo(), key, args); + final int col = 1 + CommonUtils.lengthExpandedTabs( + getLines()[ast.getLineNo() - 1], ast.getColumnNo(), tabWidth); + messages.add( + new LocalizedMessage( + ast.getLineNo(), + col, + ast.getColumnNo(), + ast.getType(), + getMessageBundle(), + key, + args, + getSeverityLevel(), + getId(), + getClass(), + getCustomMessages().get(key))); } @Override diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java index 3161f30bf48..cd1fcd8fd1d 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java @@ -68,6 +68,8 @@ public final class LocalizedMessage private final int lineNo; /** The column number. **/ private final int columnNo; + /** The column char index. **/ + private final int columnCharIndex; /** The token type constant. See {@link TokenTypes}. **/ private final int tokenType; @@ -99,6 +101,7 @@ public final class LocalizedMessage * * @param lineNo line number associated with the message * @param columnNo column number associated with the message + * @param columnCharIndex column char index associated with the message * @param tokenType token type of the event associated with the message. See {@link TokenTypes} * @param bundle resource bundle name * @param key the key to locate the translation @@ -111,6 +114,7 @@ public final class LocalizedMessage // -@cs[ParameterNumber] Class is immutable, we need that amount of arguments. public LocalizedMessage(int lineNo, int columnNo, + int columnCharIndex, int tokenType, String bundle, String key, @@ -121,6 +125,7 @@ public LocalizedMessage(int lineNo, String customMessage) { this.lineNo = lineNo; this.columnNo = columnNo; + this.columnCharIndex = columnCharIndex; this.tokenType = tokenType; this.key = key; @@ -137,6 +142,35 @@ public LocalizedMessage(int lineNo, this.customMessage = customMessage; } + /** + * Creates a new {@code LocalizedMessage} instance. + * + * @param lineNo line number associated with the message + * @param columnNo column number associated with the message + * @param tokenType token type of the event associated with the message. See {@link TokenTypes} + * @param bundle resource bundle name + * @param key the key to locate the translation + * @param args arguments for the translation + * @param severityLevel severity level for the message + * @param moduleId the id of the module the message is associated with + * @param sourceClass the Class that is the source of the message + * @param customMessage optional custom message overriding the default + */ + // -@cs[ParameterNumber] Class is immutable, we need that amount of arguments. + public LocalizedMessage(int lineNo, + int columnNo, + int tokenType, + String bundle, + String key, + Object[] args, + SeverityLevel severityLevel, + String moduleId, + Class sourceClass, + String customMessage) { + this(lineNo, columnNo, columnNo, tokenType, bundle, key, args, severityLevel, moduleId, + sourceClass, customMessage); + } + /** * Creates a new {@code LocalizedMessage} instance. * @@ -257,6 +291,7 @@ public boolean equals(Object object) { final LocalizedMessage localizedMessage = (LocalizedMessage) object; return Objects.equals(lineNo, localizedMessage.lineNo) && Objects.equals(columnNo, localizedMessage.columnNo) + && Objects.equals(columnCharIndex, localizedMessage.columnCharIndex) && Objects.equals(tokenType, localizedMessage.tokenType) && Objects.equals(severityLevel, localizedMessage.severityLevel) && Objects.equals(moduleId, localizedMessage.moduleId) @@ -269,8 +304,8 @@ public boolean equals(Object object) { @Override public int hashCode() { - return Objects.hash(lineNo, columnNo, tokenType, severityLevel, moduleId, key, bundle, - sourceClass, customMessage, Arrays.hashCode(args)); + return Objects.hash(lineNo, columnNo, columnCharIndex, tokenType, severityLevel, moduleId, + key, bundle, sourceClass, customMessage, Arrays.hashCode(args)); } /** Clears the cache. */ @@ -349,6 +384,14 @@ public int getColumnNo() { return columnNo; } + /** + * Gets the column char index. + * @return the column char index + */ + public int getColumnCharIndex() { + return columnCharIndex; + } + /** * Gets the token type. * @return the token type diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/api/LocalizedMessageTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/api/LocalizedMessageTest.java index 972d5868a84..e8183e69b97 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/api/LocalizedMessageTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/api/LocalizedMessageTest.java @@ -223,6 +223,15 @@ public void testTokenType() { assertEquals("Invalid token type", TokenTypes.OBJBLOCK, localizedMessage2.getTokenType()); } + @Test + public void testGetColumnCharIndex() { + final LocalizedMessage localizedMessage1 = new LocalizedMessage(1, 1, 123, + TokenTypes.CLASS_DEF, "messages.properties", "key", null, SeverityLevel.ERROR, + null, getClass(), null); + + assertEquals("Invalid column char index", 123, localizedMessage1.getColumnCharIndex()); + } + @Test public void testCompareToWithDifferentModuleId() { final LocalizedMessage message1 = createSampleLocalizedMessageWithId("module1");