Skip to content

Commit

Permalink
Issue checkstyle#8179: Inability to use xpath for violation for Empty…
Browse files Browse the repository at this point in the history
…LineSeparator Check
  • Loading branch information
AkMo3 committed Mar 17, 2021
1 parent 9df8837 commit a7baeea
Show file tree
Hide file tree
Showing 16 changed files with 288 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -477,12 +477,54 @@ private void processMultipleLinesInside(DetailAST ast) {
if (isClassMemberBlock(astType)) {
final List<Integer> emptyLines = getEmptyLines(ast);
final List<Integer> emptyLinesToLog = getEmptyLinesToLog(emptyLines);

for (Integer lineNo : emptyLinesToLog) {
// Checkstyle counts line numbers from 0 but IDE from 1
log(lineNo + 1, MSG_MULTIPLE_LINES_INSIDE);
log(getLastElementBeforeEmptyLines(ast, lineNo), MSG_MULTIPLE_LINES_INSIDE,
lineNo + 2);
}
}
}

/**
* Returns the element after which empty lines exist.
*
* @param ast the ast to check.
* @param line the empty line which gives violation.
* @return The DetailAST after which empty lines are present.
*/
private DetailAST getLastElementBeforeEmptyLines(DetailAST ast, int line) {
DetailAST travelAST = ast;
if (ast.getFirstChild().getLineNo() <= line) {
travelAST = ast.getFirstChild();
while (travelAST.getNextSibling() != null
&& travelAST.getNextSibling().getLineNo() <= line) {
travelAST = travelAST.getNextSibling();
}
if (travelAST.hasChildren()) {
travelAST = getLastElementBeforeEmptyLines(travelAST, line);
}
}
if (travelAST.getNextSibling() != null && isAstPostFixType(travelAST.getNextSibling())) {
travelAST = getLastElementBeforeEmptyLines(travelAST.getNextSibling()
.getFirstChild().getFirstChild(), line);
}
return travelAST;
}

/**
* Checks if ast is postfix type.
*
* @param ast the ast to check.
* @return true, if ast is of type postfix.
*/
private static boolean isAstPostFixType(DetailAST ast) {
boolean isPostFix = false;
if (ast.getType() == TokenTypes.EXPR
&& ast.getFirstChild().getType() == TokenTypes.METHOD_CALL
&& ast.getFirstChild().getFirstChild().getType() == TokenTypes.DOT) {
isPostFix = true;
}
return isPostFix;
}

/**
Expand Down Expand Up @@ -534,7 +576,7 @@ private static List<Integer> getEmptyLinesToLog(List<Integer> emptyLines) {
int previousEmptyLineNo = emptyLines.get(0);
for (int emptyLineNo : emptyLines) {
if (previousEmptyLineNo + 1 == emptyLineNo) {
emptyLinesToLog.add(emptyLineNo);
emptyLinesToLog.add(previousEmptyLineNo);
}
previousEmptyLineNo = emptyLineNo;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ containsTab=Line contains a tab character.
empty.line.separator=''{0}'' should be separated from previous statement.
empty.line.separator.multiple.lines=''{0}'' has more than 1 empty lines before.
empty.line.separator.multiple.lines.after=''{0}'' has more than 1 empty lines after.
empty.line.separator.multiple.lines.inside=There is more than 1 empty line one after another.
empty.line.separator.multiple.lines.inside=Line ''{0}'' has more than 1 empty line one after another.
file.containsTab=File contains tab characters (this is the first instance).
line.new=''{0}'' should be on a new line.
line.previous=''{0}'' should be on the previous line.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ containsTab=Die Zeile enthält ein Tabulatorzeichen.
empty.line.separator=''{0}'' sollte von der vorherigen Anweisung durch eine leere Zeile getrennt werden.
empty.line.separator.multiple.lines=Vor ''{0}'' steht mehr als eine leere Zeile.
empty.line.separator.multiple.lines.after=Hinter ''{0}'' steht mehr als eine leere Zeile.
empty.line.separator.multiple.lines.inside=Es stehen mehrere leere Zeilen hintereinander.
empty.line.separator.multiple.lines.inside=Zeile '' {0} '' enthält nacheinander mehr als eine leere Zeile.
file.containsTab=Die Datei enthält Tabulatorzeichen (dies ist das erste Vorkommen).
line.new=''{0}'' sollte in einer neuen Zeile stehen.
line.previous=''{0}'' sollte in der vorherigen Zeile stehen.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ containsTab=La línea contiene un carácter de tabulación.
empty.line.separator=''{0}'' debe ser separado de la declaración anterior.
empty.line.separator.multiple.lines=''{0}'' cuenta con más de 1 líneas vacías antes.
empty.line.separator.multiple.lines.after=''{0}'' cuenta con más de 1 líneas vacías después.
empty.line.separator.multiple.lines.inside=Hay más de 1 una línea vacía después de otra.
empty.line.separator.multiple.lines.inside=La línea '' {0} '' tiene más de 1 línea vacía una tras otra.
file.containsTab=Archivo contiene caracteres de tabulación (este es el primer ejemplo).
line.new=''{0}'' debería estar en una línea nueva.
line.previous=''{0}'' debería estar en la línea anterior.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ containsTab=Rivi sisältää sarkainmerkin.
empty.line.separator=''{0}'' olisi erotettava edellisen selonteon.
empty.line.separator.multiple.lines=''{0}'' on yli 1 tyhjää riviä ennen.
empty.line.separator.multiple.lines.after=''{0}'' on yli 1 tyhjää riviä jälkeen.
empty.line.separator.multiple.lines.inside=On enemmän kuin 1 tyhjä rivi yksi toisensa jälkeen.
empty.line.separator.multiple.lines.inside=Rivillä '' {0} '' on enemmän kuin yksi tyhjä rivi peräkkäin.
file.containsTab=Tiedosto sisältää sarkainmerkeillä (tämä on ensisijaisesti).
line.new=''{0}'' pitää olla uudella rivillä.
line.previous=''{0}'' pitää olla edellisellä rivillä.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ containsTab=La ligne contient un caractère tabulation.
empty.line.separator=''{0}'' doit être séparé de la déclaration précédente.
empty.line.separator.multiple.lines=''{0}'' a plus d''une ligne vide avant.
empty.line.separator.multiple.lines.after=''{0}'' compte plus d''une ligne vide après.
empty.line.separator.multiple.lines.inside=Il y a plus d''une ligne vide une après l'autre.
empty.line.separator.multiple.lines.inside=La ligne '' {0} '' a plus d'une ligne vide l'une après l'autre.
file.containsTab=Le fichier contient des caractères de tabulation (ce n''est que la première occurence).
line.new=''{0}'' devrait être sur une nouvelle ligne.
line.previous=''{0}'' devrait être sur la ligne précédente.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ containsTab=行にタブ文字が含まれています。
empty.line.separator=''{0}'' は前の文から分離する必要があります。
empty.line.separator.multiple.lines=''{0}'' の前に空行が複数あります。
empty.line.separator.multiple.lines.after=''{0}'' の後に空行が複数あります。
empty.line.separator.multiple.lines.inside=空行が複数続いています
empty.line.separator.multiple.lines.inside='' {0} ''には、次々に複数の空の行があります
file.containsTab=ファイルにタブ文字が含まれています(ここが最初の出現箇所です)。
line.new=''{0}'' は新しい行にあるべきです。
line.previous=''{0}'' は前の行にあるべきです。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ containsTab=A linha contém um caractere de tabulação.
empty.line.separator=''{0}'' deveria ser separado da instrução anterior.
empty.line.separator.multiple.lines=''{0}'' é precedido por mais do que 1 linha vazia.
empty.line.separator.multiple.lines.after=''{0}'' é sucedido por mais do que 1 linha vazia.
empty.line.separator.multiple.lines.inside=Há duas ou mais linhas vazias consecutivas.
empty.line.separator.multiple.lines.inside=A linha '' {0} '' tem mais de 1 linha vazia, uma após a outra.
file.containsTab=O arquivo contém caracteres de tabulação (esta é a primeira ocorrência).
line.new=''{0}'' deveria estar numa nova linha.
line.previous=''{0}'' deveria estar na linha anterior.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ containsTab=Satır, sekme karakteri içermekte.
empty.line.separator={0} 'Bir önceki deyimi ayrılmalıdır.
empty.line.separator.multiple.lines={0} daha önce en fazla 1 boş hatları vardır.
empty.line.separator.multiple.lines.after=''{0}'' sonra 1'den fazla boş hatları vardır.
empty.line.separator.multiple.lines.inside=birbiri ardına 1'den fazla boş satır biri var.
empty.line.separator.multiple.lines.inside='' {0} '' satırında birbiri ardına 1'den fazla boş satır var.
file.containsTab=Dosya, sekme karakterleri içermekte (sadece ilk bulunan gösteriliyor).
line.new=''{0}'' ifadesi yeni bir satırda olmalı.
line.previous=''{0}'' ifadesi önceki satırda olmalı.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ containsTab=行内含有制表符 tab 。
empty.line.separator=''{0}' 前应有空行。
empty.line.separator.multiple.lines=''{0}'' 前只应有一个空行。
empty.line.separator.multiple.lines.after=''{0}'' 后只应有一个空行。
empty.line.separator.multiple.lines.inside=还有陆续超过1空行之一
empty.line.separator.multiple.lines.inside=''{0}''一个接一个地有多个空行
file.containsTab=文件含有制表符 tab (这只是第一例)。
line.new=''{0}'' 应另起一行。
line.previous=''{0}'' 应在前一行。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,12 @@ public void testPreviousLineEmptiness() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(EmptyLineSeparatorCheck.class);
checkConfig.addAttribute("allowMultipleEmptyLinesInsideClassMembers", "false");
final String[] expected = {
"11: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"16: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"22: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"31: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"9:26: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 11),
"14:5: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 16),
"20:67: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 22),
"29:44: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 31),
"39:17: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 41),

};
verify(checkConfig,
getPath("InputEmptyLineSeparatorPreviousLineEmptiness.java"), expected);
Expand All @@ -270,12 +272,12 @@ public void testDisAllowMultipleEmptyLinesInsideClassMembers() throws Exception
final DefaultConfiguration checkConfig = createModuleConfig(EmptyLineSeparatorCheck.class);
checkConfig.addAttribute("allowMultipleEmptyLinesInsideClassMembers", "false");
final String[] expected = {
"27: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"39: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"45: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"50: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"55: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"56: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"25:11: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 27),
"37:11: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 39),
"43:11: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 45),
"48:31: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 50),
"53:11: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 55),
"53:11: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 56),
"60:1: " + getCheckMessage(MSG_SHOULD_BE_SEPARATED, "CLASS_DEF"),
};
verify(checkConfig,
Expand Down Expand Up @@ -464,8 +466,8 @@ public void testEmptyLineSeparatorRecordsAndCompactCtorsNoEmptyLines() throws Ex

final String[] expected = {
"2:1: " + getCheckMessage(MSG_SHOULD_BE_SEPARATED, "package"),
"16: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"22: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE),
"14:27: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 16),
"20:29: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 22),
};

verify(checkConfig,
Expand All @@ -486,4 +488,43 @@ public void testEmptyLineSeparatorMultipleSingleTypeVariables() throws Exception
expected);
}

@Test
public void testEmptyLineSeparatorEmptyLinesInsideClassMembersRecursive() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(EmptyLineSeparatorCheck.class);
checkConfig.addAttribute("allowMultipleEmptyLinesInsideClassMembers", "false");
final String[] expected = {
"19:15: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 21),
};
verify(checkConfig,
getPath("InputEmptyLineSeparatorRecursive.java"),
expected);
}

@Test
public void testEmptyLineSeparatorNewMethodDef() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(EmptyLineSeparatorCheck.class);
checkConfig.addAttribute("allowMultipleEmptyLinesInsideClassMembers", "false");
final String[] expected = {
"81:15: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 83),
"81:15: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 84),
};
verify(checkConfig,
getPath("InputEmptyLineSeparatorNewMethodDef.java"),
expected);
}

@Test
public void testEmptyLineSeparatorPostFixCornerCases() throws Exception {
final DefaultConfiguration checkConfig = createModuleConfig(EmptyLineSeparatorCheck.class);
checkConfig.addAttribute("allowMultipleEmptyLinesInsideClassMembers", "false");
final String[] expected = {
"10:19: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 13),
"24:29: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 27),
"35:29: " + getCheckMessage(MSG_MULTIPLE_LINES_INSIDE, 37),
};
verify(checkConfig,
getPath("InputEmptyLineSeparatorPostFixCornerCases.java"),
expected);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
*
*/
public class InputEmptyLineSeparatorRecordsAndCompactCtorsNoEmptyLines {
public void foo() {
public void foo() { // violation


} // ^ violation
}

public record MyRecord1(){
public MyRecord1{
public MyRecord1{ // violation


} // ^ violation
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.puppycrawl.tools.checkstyle.checks.whitespace.emptylineseparator;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
* Config:
* allowMultipleEmptyLinesInsideClassMembers = false
*/
public class InputEmptyLineSeparatorNewMethodDef {
HashMap<String, String> myMap =
new HashMap<>();

void processOne() { // ok

int a;

int b;

new Map() {
@Override
public int size() {
return 0;
}

@Override
public boolean isEmpty() {
return false;
}

@Override
public boolean containsKey(Object key) {
return false;
}

@Override
public boolean containsValue(Object value) {
return false;
}

@Override
public Object get(Object key) {
return null;
}

@Override
public Object put(Object key, Object value) {
return null;
}

@Override
public Object remove(Object key) {
return null;
}

@Override
public void putAll(Map m) {

}

@Override
public void clear() {

}

@Override
public Set<Object> keySet() {
return null;
}

@Override
public Collection<Object> values() {
return null;
}

@Override
public Set<Entry<Object, Object>> entrySet() {
return null;
// violation



}

@Override
public boolean equals(Object o) {
return false;
}

@Override
public int hashCode() {
return 0;
}
}.putAll(myMap);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.puppycrawl.tools.checkstyle.checks.whitespace.emptylineseparator;

/**
* Config:
* allowMultipleEmptyLinesInsideClassMembers = false
*/
public class InputEmptyLineSeparatorPostFixCornerCases {

protected void foo1() throws Exception {
int a = 25;
// violation


foo(a);
}

void foo(int a) {
System.out.println(a);
}

protected void foo() {

Object[] defaults = new Object[] {
"String One",
// violation


"String Two",

};
}

protected void foo2() {
Object[] defaults = new Object[] {
"String One", 13,


"String Two", // violation above this line.
};
}
}
Loading

0 comments on commit a7baeea

Please sign in to comment.