Issue #2239: Extend RequireThis check message

This commit is contained in:
Vladislav Lisetskiy 2015-12-24 11:13:25 +03:00 committed by Roman Ivanov
parent 10f348bbfd
commit 6c04cd63af
13 changed files with 191 additions and 116 deletions

View File

@ -55,6 +55,16 @@
<Class name="com.puppycrawl.tools.checkstyle.api.DetailAST" />
<Bug pattern="BC_UNCONFIRMED_CAST" />
</Match>
<Match>
<!-- The structure of frames relies on the AST structure which relies on correct/compilable
java files. It is ok to have direct casts to subtypes there. Any problems at runtime do
mean serious problems in the algorithm or AST generation. -->
<Class name="com.puppycrawl.tools.checkstyle.checks.coding.RequireThisCheck"/>
<Or>
<Bug pattern="BC_UNCONFIRMED_CAST"/>
<Bug pattern="BC_UNCONFIRMED_CAST_OF_RETURN_VALUE"/>
</Or>
</Match>
<Match>
<!-- till SonarQube update Checkstyle version. Support both getFileName() and getFilename() -->
<and>

View File

@ -44,6 +44,8 @@
<rule ref="rulesets/java/codesize.xml/TooManyMethods">
<properties>
<property name="maxmethods" value="20"/>
<!-- Reducing the number of methods requires making excess hierarchy or duplicating code, or making existing methods too complex. -->
<property name="violationSuppressXPath" value="//ClassOrInterfaceDeclaration[@Image='RequireThisCheck']"/>
</properties>
</rule>
<rule ref="rulesets/java/codesize.xml/ExcessiveClassLength">

View File

@ -53,13 +53,11 @@ import com.puppycrawl.tools.checkstyle.utils.ScopeUtils;
* &lt;/module&gt;
* </pre>
*
* <p>Limitations: I'm not currently doing anything about static variables
* <p>Limitations: Nothing is currently done about static variables
* or catch-blocks. Static methods invoked on a class name seem to be OK;
* both the class name and the method name have a DOT parent.
* Non-static methods invoked on either this or a variable name seem to be
* OK, likewise.</p>
* <p>Much of the code for this check was cribbed from Rick Giles's
* {@code HiddenFieldCheck}.</p>
*
* @author Stephen Bloch
* @author o_sukhodolsky
@ -77,7 +75,6 @@ public class RequireThisCheck extends Check {
* file.
*/
public static final String MSG_VARIABLE = "require.this.variable";
/**
* Set of all declaration tokens.
*/
@ -95,12 +92,12 @@ public class RequireThisCheck extends Check {
/**
* Tree of all the parsed frames.
*/
private Map<DetailAST, LexicalFrame> frames;
private Map<DetailAST, AbstractFrame> frames;
/**
* Frame for the currently processed AST.
*/
private LexicalFrame current;
private AbstractFrame current;
/** Whether we should check fields usage. */
private boolean checkFields = true;
@ -148,8 +145,7 @@ public class RequireThisCheck extends Check {
@Override
public void beginTree(DetailAST rootAST) {
final Deque<LexicalFrame> frameStack = Lists.newLinkedList();
frameStack.add(new GlobalFrame());
final Deque<AbstractFrame> frameStack = Lists.newLinkedList();
frames = Maps.newHashMap();
@ -204,37 +200,60 @@ public class RequireThisCheck extends Check {
break;
case TokenTypes.METHOD_CALL:
// let's check method calls
if (checkMethods && isClassMethod(ast)) {
log(ast, MSG_METHOD, ast.getText());
if (checkMethods) {
final AbstractFrame frame = checkMethod(ast);
if (frame != null) {
logViolation(MSG_METHOD, ast, frame);
}
}
break;
default:
if (checkFields) {
processField(ast, parentType);
final AbstractFrame frame = processField(ast, parentType);
if (frame != null) {
logViolation(MSG_VARIABLE, ast, frame);
}
}
break;
}
}
/**
* Helper method to log a LocalizedMessage.
* @param ast a node to get line id column numbers associated with the message.
* @param msgKey key to locale message format.
* @param frame the frame, where the violation is found.
*/
private void logViolation(String msgKey, DetailAST ast, AbstractFrame frame) {
if (frame.getFrameName().equals(getNearestClassFrameName())) {
log(ast, msgKey, ast.getText(), "");
}
else {
log(ast, msgKey, ast.getText(), frame.getFrameName() + '.');
}
}
/**
* Process validation of Field.
* @param ast field definition ast token
* @param parentType type of the parent
* @return frame, where the field is declared, if the violation is found and null otherwise
*/
private void processField(DetailAST ast, int parentType) {
private AbstractFrame processField(DetailAST ast, int parentType) {
final boolean importOrPackage = ScopeUtils.getSurroundingScope(ast) == null;
final boolean methodNameInMethodCall = parentType == TokenTypes.DOT
&& ast.getPreviousSibling() != null;
final boolean typeName = parentType == TokenTypes.TYPE
|| parentType == TokenTypes.LITERAL_NEW;
AbstractFrame frame = null;
if (!importOrPackage
&& !methodNameInMethodCall
&& !typeName
&& !isDeclarationToken(parentType)
&& isClassField(ast)) {
log(ast, MSG_VARIABLE, ast.getText());
&& !isDeclarationToken(parentType)) {
frame = checkField(ast);
}
return frame;
}
/**
@ -243,9 +262,9 @@ public class RequireThisCheck extends Check {
* @param frameStack Stack containing the FrameTree being built
* @param ast AST to parse
*/
private static void collectDeclarations(Deque<LexicalFrame> frameStack,
private static void collectDeclarations(Deque<AbstractFrame> frameStack,
DetailAST ast) {
final LexicalFrame frame = frameStack.peek();
final AbstractFrame frame = frameStack.peek();
switch (ast.getType()) {
case TokenTypes.VARIABLE_DEF :
collectVariableDeclarations(ast, frame);
@ -259,15 +278,14 @@ public class RequireThisCheck extends Check {
case TokenTypes.ENUM_DEF :
case TokenTypes.ANNOTATION_DEF :
final DetailAST classIdent = ast.findFirstToken(TokenTypes.IDENT);
frame.addIdent(classIdent);
frameStack.addFirst(new ClassFrame(frame));
frameStack.addFirst(new ClassFrame(frame, classIdent.getText()));
break;
case TokenTypes.SLIST :
frameStack.addFirst(new BlockFrame(frame));
break;
case TokenTypes.METHOD_DEF :
final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
if (frame instanceof ClassFrame) {
if (frame.getType() == FrameType.CLASS_FRAME) {
final DetailAST mods =
ast.findFirstToken(TokenTypes.MODIFIERS);
if (mods.branchContains(TokenTypes.LITERAL_STATIC)) {
@ -292,10 +310,9 @@ public class RequireThisCheck extends Check {
* @param ast variable token
* @param frame current frame
*/
private static void collectVariableDeclarations(DetailAST ast, LexicalFrame frame) {
final DetailAST ident =
ast.findFirstToken(TokenTypes.IDENT);
if (frame instanceof ClassFrame) {
private static void collectVariableDeclarations(DetailAST ast, AbstractFrame frame) {
final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
if (frame.getType() == FrameType.CLASS_FRAME) {
final DetailAST mods =
ast.findFirstToken(TokenTypes.MODIFIERS);
if (ScopeUtils.isInInterfaceBlock(ast)
@ -317,7 +334,7 @@ public class RequireThisCheck extends Check {
* @param frameStack Stack containing the FrameTree being built
* @param ast AST that was parsed
*/
private void endCollectingDeclarations(Queue<LexicalFrame> frameStack,
private void endCollectingDeclarations(Queue<AbstractFrame> frameStack,
DetailAST ast) {
switch (ast.getType()) {
case TokenTypes.CLASS_DEF :
@ -336,33 +353,40 @@ public class RequireThisCheck extends Check {
/**
* Check if given name is a name for class field in current environment.
* @param ident an IDENT ast to check
* @return true is the given name is name of member.
* @param ast an IDENT ast to check
* @return frame, where the field is declared, if the violation is found and null otherwise
*/
private boolean isClassField(DetailAST ident) {
final LexicalFrame frame = findFrame(ident, false);
return frame instanceof ClassFrame
&& ((ClassFrame) frame).hasInstanceMember(ident);
private AbstractFrame checkField(DetailAST ast) {
final AbstractFrame frame = findFrame(ast, false);
if (frame != null
&& frame.getType() == FrameType.CLASS_FRAME
&& ((ClassFrame) frame).hasInstanceMember(ast)) {
return frame;
}
return null;
}
/**
* Check if given name is a name for class method in current environment.
* @param ident the IDENT ast of the name to check
* @return true is the given name is name of method.
* @param ast the IDENT ast of the name to check
* @return frame, where the method is declared, if the violation is found and null otherwise
*/
private boolean isClassMethod(DetailAST ident) {
final LexicalFrame frame = findFrame(ident, true);
return frame instanceof ClassFrame
&& ((ClassFrame) frame).hasInstanceMethod(ident);
private AbstractFrame checkMethod(DetailAST ast) {
final AbstractFrame frame = findFrame(ast, true);
if (frame != null
&& ((ClassFrame) frame).hasInstanceMethod(ast)) {
return frame;
}
return null;
}
/**
* Find frame containing declaration.
* @param name IDENT ast of the declaration to find.
* @param lookForMethod whether we are looking for a method name.
* @return LexicalFrame containing declaration or null.
* @return AbstractFrame containing declaration or null.
*/
private LexicalFrame findFrame(DetailAST name, boolean lookForMethod) {
private AbstractFrame findFrame(DetailAST name, boolean lookForMethod) {
if (current == null) {
return null;
}
@ -380,29 +404,64 @@ public class RequireThisCheck extends Check {
return DECLARATION_TOKENS.contains(parentType);
}
/**
* Get the name of the nearest parent ClassFrame.
* @return the name of the nearest parent ClassFrame.
*/
private String getNearestClassFrameName() {
AbstractFrame frame = current;
while (frame.getType() != FrameType.CLASS_FRAME) {
frame = frame.getParent();
}
return frame.getFrameName();
}
/** An AbstractFrame type. */
private enum FrameType {
/** Class frame type. */
CLASS_FRAME,
/** Method frame type. */
METHOD_FRAME,
/** Block frame type. */
BLOCK_FRAME,
}
/**
* A declaration frame.
* @author Stephen Bloch
*/
private static class LexicalFrame {
private abstract static class AbstractFrame {
/** Set of name of variables declared in this frame. */
private final Set<DetailAST> varIdents;
/**
* Parent frame.
*/
private final LexicalFrame parent;
private final AbstractFrame parent;
/**
* Frame name.
*/
private final String frameName;
/**
* Constructor -- invokable only via super() from subclasses.
*
* @param parent parent frame
* @param frameName frame name
*/
protected LexicalFrame(LexicalFrame parent) {
protected AbstractFrame(AbstractFrame parent, String frameName) {
this.parent = parent;
this.frameName = frameName;
varIdents = Sets.newHashSet();
}
/**
* Get the type of the frame.
* @return a FrameType.
*/
protected abstract FrameType getType();
/**
* Add a name to the frame.
* @param identToAdd the name we're adding
@ -411,10 +470,14 @@ public class RequireThisCheck extends Check {
varIdents.add(identToAdd);
}
protected LexicalFrame getParent() {
protected AbstractFrame getParent() {
return parent;
}
protected String getFrameName() {
return frameName;
}
/** Check whether the frame contains a given name.
* @param nameToFind the IDENT ast of the name we're looking for
* @return whether it was found
@ -428,14 +491,14 @@ public class RequireThisCheck extends Check {
* @param lookForMethod whether we are looking for a method name.
* @return whether it was found.
*/
protected LexicalFrame getIfContains(DetailAST nameToFind, boolean lookForMethod) {
LexicalFrame frame = null;
protected AbstractFrame getIfContains(DetailAST nameToFind, boolean lookForMethod) {
AbstractFrame frame;
if (!lookForMethod
&& contains(nameToFind)) {
frame = this;
}
else if (parent != null) {
else {
frame = parent.getIfContains(nameToFind, lookForMethod);
}
return frame;
@ -489,41 +552,30 @@ public class RequireThisCheck extends Check {
}
}
/**
* The global frame; should hold only class names.
* @author Stephen Bloch
*/
private static class GlobalFrame extends LexicalFrame {
/**
* Constructor for the root of the FrameTree.
*/
protected GlobalFrame() {
super(null);
}
}
/**
* A frame initiated at method definition; holds parameter names.
* @author Stephen Bloch
*/
private static class MethodFrame extends LexicalFrame {
private static class MethodFrame extends AbstractFrame {
/**
* Creates method frame.
* @param parent parent frame
*/
protected MethodFrame(LexicalFrame parent) {
super(parent);
protected MethodFrame(AbstractFrame parent) {
super(parent, null);
}
@Override
protected FrameType getType() {
return FrameType.METHOD_FRAME;
}
}
/**
* A frame initiated at class definition; holds instance variable
* names. For the present, I'm not worried about other class names,
* method names, etc.
* A frame initiated at class< enum or interface definition; holds instance variable names.
* @author Stephen Bloch
*/
private static class ClassFrame extends LexicalFrame {
private static class ClassFrame extends AbstractFrame {
/** Set of idents of instance members declared in this frame. */
private final Set<DetailAST> instanceMembers;
/** Set of idents of instance methods declared in this frame. */
@ -536,15 +588,21 @@ public class RequireThisCheck extends Check {
/**
* Creates new instance of ClassFrame.
* @param parent parent frame
* @param frameName frame name
*/
ClassFrame(LexicalFrame parent) {
super(parent);
ClassFrame(AbstractFrame parent, String frameName) {
super(parent, frameName);
instanceMembers = Sets.newHashSet();
instanceMethods = Sets.newHashSet();
staticMembers = Sets.newHashSet();
staticMethods = Sets.newHashSet();
}
@Override
protected FrameType getType() {
return FrameType.CLASS_FRAME;
}
/**
* Adds static member's ident.
* @param ident an ident of static member of the class
@ -599,8 +657,7 @@ public class RequireThisCheck extends Check {
@Override
boolean contains(DetailAST nameToFind) {
return super.contains(nameToFind)
|| containsName(instanceMembers, nameToFind)
return containsName(instanceMembers, nameToFind)
|| containsName(instanceMethods, nameToFind)
|| containsName(staticMembers, nameToFind)
|| containsName(staticMethods, nameToFind);
@ -613,13 +670,13 @@ public class RequireThisCheck extends Check {
}
@Override
protected LexicalFrame getIfContains(DetailAST nameToFind, boolean lookForMethod) {
LexicalFrame frame;
protected AbstractFrame getIfContains(DetailAST nameToFind, boolean lookForMethod) {
AbstractFrame frame = null;
if (contains(nameToFind)) {
frame = this;
}
else {
else if (getParent() != null) {
frame = getParent().getIfContains(nameToFind, lookForMethod);
}
return frame;
@ -627,19 +684,22 @@ public class RequireThisCheck extends Check {
}
/**
* A frame initiated on entering a statement list; holds local variable
* names. For the present, I'm not worried about other class names,
* method names, etc.
* A frame initiated on entering a statement list; holds local variable names.
* @author Stephen Bloch
*/
private static class BlockFrame extends LexicalFrame {
private static class BlockFrame extends AbstractFrame {
/**
* Creates block frame.
* @param parent parent frame
*/
protected BlockFrame(LexicalFrame parent) {
super(parent);
protected BlockFrame(AbstractFrame parent) {
super(parent, null);
}
@Override
protected FrameType getType() {
return FrameType.BLOCK_FRAME;
}
}
}

View File

@ -42,8 +42,8 @@ redundant.throws.classInfo=Unable to get class information for {0}.
redundant.throws.duplicate=Redundant throws: ''{0}'' listed more then one time.
redundant.throws.subclass=Redundant throws: ''{0}'' is subclass of ''{1}''.
redundant.throws.unchecked=Redundant throws: ''{0}'' is unchecked exception.
require.this.variable=Reference to instance variable ''{0}'' needs \"this.\".
require.this.method=Method call to ''{0}'' needs \"this.\".
require.this.variable=Reference to instance variable ''{0}'' needs \"{1}this.\".
require.this.method=Method call to ''{0}'' needs \"{1}this.\".
return.count=Return count is {0,number,integer} (max allowed is {1,number,integer}).
simplify.boolReturn=Conditional logic can be removed.
simplify.expression=Expression can be simplified.

View File

@ -42,8 +42,8 @@ redundant.throws.classInfo=Klassen-Information für {0} nicht verfügbar.
redundant.throws.duplicate=Überflüssige throws-Deklaration: ''{0}'' ist mehrfach aufgeführt.
redundant.throws.subclass=Überflüssige throws-Deklaration: ''{0}'' ist Unterklasse von ''{1}''.
redundant.throws.unchecked=Überflüssige throws-Deklaration: ''{0}'' ist eine unchecked Exception (abgeleitet von RuntimeException).
require.this.variable=Dereferenzierung der Instanzvariable ''{0}'' muss über \"this.\" erfolgen.
require.this.method=Methodenaufruf ''{0}'' muss über \"this.\" erfolgen.
require.this.variable=Dereferenzierung der Instanzvariable ''{0}'' muss über \"{1}this.\" erfolgen.
require.this.method=Methodenaufruf ''{0}'' muss über \"{1}this.\" erfolgen.
return.count={0,number,integer} return-Anweisungen (Obergrenze ist {1,number,integer}).
simplify.boolReturn=Die Verzweigung sollte entfernt werden.
simplify.expression=Der Ausdruck kann vereinfacht werden.

View File

@ -60,8 +60,8 @@ explicit.init=La variable ''{0}'' se inicializa explicitamente a ''{1}'' (valor
default.comes.last=La etiqueta default debe ser la última etiqueta en el switch.
missing.ctor=La clase debería definir un constructor.
fall.through=Caída desde la etiqueta anterior en la sentencia switch.
require.this.variable=La referencia a la variable de instancia ''{0}'' necesita \"this.\".
require.this.method=La llamada al método ''{0}'' necesita \"this.\".
require.this.variable=La referencia a la variable de instancia ''{0}'' necesita \"{1}this.\".
require.this.method=La llamada al método ''{0}'' necesita \"{1}this.\".
multiple.variable.declarations=Sólo se permite una definición de variable por línea.
multiple.variable.declarations.comma=Cada declaración de variable debe estar en su línea.

View File

@ -54,8 +54,8 @@ multiple.variable.declarations.comma = Jokainen muuttuja ilmoitus on oltava oman
nested.for.depth = Sisäkkäisiä syvyys on {0, numero, kokonaisluku} (max sallittu on {1, numero, kokonaisluku}).
parameter.assignment = Tehtävä parametrin ''{0}'' ei ole sallittu.
redundant.throws.classInfo = Ei saada luokan tietoa {0} .
require.this.variable = Viittaus Esimerkiksi muuttuja ''{0}'' tarvitsee \"tämä.\".
require.this.method = Menetelmä kehotus ''{0}'' tarvitsee \"tämä.\".
require.this.variable = Viittaus Esimerkiksi muuttuja ''{0}'' tarvitsee \"{1}this.\".
require.this.method = Menetelmä kehotus ''{0}'' tarvitsee \"{1}this.\".
return.count = Paluu määrä on {0, numero, kokonaisluku} (max sallittu on {1, numero, kokonaisluku}).
string.literal.equality = Kirjaimellinen Strings pitäisi verrata käyttämällä tasavertaisten (), ei ''{0}''.
unnecessary.paren.assign = Tarpeettomia sulkuja noin tehtävän oikealla puolella.

View File

@ -60,8 +60,8 @@ explicit.init=L''initialisation explicite de la variable ''{0}'' à la valeur ''
default.comes.last=Le cas \"default\" devrait apparaitre en dernier dans le bloc \"switch\".
missing.ctor=Il manque un constructeur à la classe.
fall.through=Le cas précédent du \"switch\" ne contient pas de break, return, throw ou continue.
require.this.variable=La référence à la variable d''instance ''{0}'' doit utiliser \"this.\".
require.this.method=L''appel à la méthode ''{0}'' nécessite l''utilisation de \"this.\".
require.this.variable=La référence à la variable d''instance ''{0}'' doit utiliser \"{1}this.\".
require.this.method=L''appel à la méthode ''{0}'' nécessite l''utilisation de \"{1}this.\".
multiple.variable.declarations=Ne déclarez pas plus d''une variable par ligne.
multiple.variable.declarations.comma=Chaque déclaration de variable doit faire l''objet d''une instruction à part.

View File

@ -67,8 +67,8 @@ multiple.string.literal = 文字列 {0} は、このファイルに {1} に出
multiple.variable.declarations = 行に1つの変数定義だけが許可されます。
multiple.variable.declarations.comma = 各変数の宣言には、独自のステートメントでなければなりません。
nested.for.depth = 入れ子のforの深さ {0,number,integer}(許可された最大値は{1,number,integer})。
require.this.variable = インスタンス変数 ''{0}'' への参照には \"this\"が必要です。
require.this.method = メソッド ''{0}'' への呼び出しは、 \"this\" が必要です。
require.this.variable = インスタンス変数 ''{0}'' への参照には \"{1}this.\" が必要です。
require.this.method = メソッド ''{0}'' への呼び出しは、 \"{1}this.\" が必要です。
unnecessary.paren.assign = 代入右辺の周りに不要な括弧。
unnecessary.paren.expr = 式の周りの不要な括弧。
unnecessary.paren.ident = 識別子の前後に不要な括弧 ''{0}''。

View File

@ -47,8 +47,8 @@ multiple.string.literal = The String {0} aparece {1} vezes no arquivo.
multiple.variable.declarations = Apenas uma definição de variável por linha permitidos.
multiple.variable.declarations.comma = Cada declaração de variável deve estar em sua própria declaração.
nested.for.depth = Aninhado para a profundidade é {0, number, integer} (máximo permitido é {1, number, integer}).
require.this.variable = Referência a variável de instância ''{0}'' precisa de \"isso.\".
require.this.method = Chamada de método para ''{0}'' precisa de \"isso.\".
require.this.variable = Referência a variável de instância ''{0}'' precisa de \"{1}this.\".
require.this.method = Chamada de método para ''{0}'' precisa de \"{1}this.\".
unnecessary.paren.assign = Parênteses desnecessários ao redor do lado direito atribuição.
unnecessary.paren.expr = Parênteses desnecessários ao redor expressão.
unnecessary.paren.ident = Parênteses desnecessários ao redor identificador ''{0}''.

View File

@ -71,8 +71,8 @@ redundant.throws.duplicate = ''throws'' ifadesinde ''{0}'' tekrardan kullanılm
redundant.throws.subclass = ''{0}'', ''{1}'' sınıfının alt sınıfıdır, ''throws'' kullanımı gereksizdir.
redundant.throws.unchecked = ''{0}'' ''unchecked'' bir istisnadır, ''throws'' kullanımı gereksizdir.
require.this.method = ''{0}'' metoduna erişim "this." kullanılarak yapılmalıdır.
require.this.variable = ''{0}'' değişkenine erişim "this." kullanılarak yapılmalıdır.
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}).

View File

@ -48,15 +48,16 @@ public class RequireThisCheckTest extends BaseCheckTestSupport {
final DefaultConfiguration checkConfig =
createCheckConfig(RequireThisCheck.class);
final String[] expected = {
"11:9: " + getCheckMessage(MSG_VARIABLE, "i", "\"this\""),
"17:9: " + getCheckMessage(MSG_METHOD, "method1", "\"this\""),
"31:9: " + getCheckMessage(MSG_VARIABLE, "i", "\"this\""),
"49:13: " + getCheckMessage(MSG_VARIABLE, "z", "\"this\""),
"56:9: " + getCheckMessage(MSG_VARIABLE, "z", "\"this\""),
"113:9: " + getCheckMessage(MSG_VARIABLE, "i", "\"this\""),
"114:9: " + getCheckMessage(MSG_VARIABLE, "i", "\"this\""),
"115:9: " + getCheckMessage(MSG_METHOD, "instanceMethod", "\"this\""),
"121:13: " + getCheckMessage(MSG_METHOD, "instanceMethod", "\"this\""),
"11:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
"17:9: " + getCheckMessage(MSG_METHOD, "method1", ""),
"31:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
"49:13: " + getCheckMessage(MSG_VARIABLE, "z", ""),
"56:9: " + getCheckMessage(MSG_VARIABLE, "z", ""),
"113:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
"114:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
"115:9: " + getCheckMessage(MSG_METHOD, "instanceMethod", ""),
"121:13: " + getCheckMessage(MSG_METHOD, "instanceMethod", "Issue2240."),
"122:13: " + getCheckMessage(MSG_VARIABLE, "i", "Issue2240."),
};
verify(checkConfig,
getPath("InputRequireThis.java"),
@ -69,9 +70,9 @@ public class RequireThisCheckTest extends BaseCheckTestSupport {
createCheckConfig(RequireThisCheck.class);
checkConfig.addAttribute("checkFields", "false");
final String[] expected = {
"17:9: " + getCheckMessage(MSG_METHOD, "method1", "\"this\""),
"115:9: " + getCheckMessage(MSG_METHOD, "instanceMethod", "\"this\""),
"121:13: " + getCheckMessage(MSG_METHOD, "instanceMethod", "\"this\""),
"17:9: " + getCheckMessage(MSG_METHOD, "method1", ""),
"115:9: " + getCheckMessage(MSG_METHOD, "instanceMethod", ""),
"121:13: " + getCheckMessage(MSG_METHOD, "instanceMethod", "Issue2240."),
};
verify(checkConfig,
getPath("InputRequireThis.java"),
@ -84,12 +85,13 @@ public class RequireThisCheckTest extends BaseCheckTestSupport {
createCheckConfig(RequireThisCheck.class);
checkConfig.addAttribute("checkMethods", "false");
final String[] expected = {
"11:9: " + getCheckMessage(MSG_VARIABLE, "i", "\"this\""),
"31:9: " + getCheckMessage(MSG_VARIABLE, "i", "\"this\""),
"49:13: " + getCheckMessage(MSG_VARIABLE, "z", "\"this\""),
"56:9: " + getCheckMessage(MSG_VARIABLE, "z", "\"this\""),
"113:9: " + getCheckMessage(MSG_VARIABLE, "i", "\"this\""),
"114:9: " + getCheckMessage(MSG_VARIABLE, "i", "\"this\""),
"11:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
"31:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
"49:13: " + getCheckMessage(MSG_VARIABLE, "z", ""),
"56:9: " + getCheckMessage(MSG_VARIABLE, "z", ""),
"113:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
"114:9: " + getCheckMessage(MSG_VARIABLE, "i", ""),
"122:13: " + getCheckMessage(MSG_VARIABLE, "i", "Issue2240."),
};
verify(checkConfig,
getPath("InputRequireThis.java"),
@ -109,8 +111,8 @@ public class RequireThisCheckTest extends BaseCheckTestSupport {
final DefaultConfiguration checkConfig =
createCheckConfig(RequireThisCheck.class);
final String[] expected = {
"7:19: " + getCheckMessage(MSG_VARIABLE, "number", "\"this\""),
"8:16: " + getCheckMessage(MSG_METHOD, "other", "\"this\""),
"7:19: " + getCheckMessage(MSG_VARIABLE, "number", ""),
"8:16: " + getCheckMessage(MSG_METHOD, "other", ""),
};
verify(checkConfig,
getPath("InputRequireThis2.java"),

View File

@ -119,6 +119,7 @@ class Issue2240 {
class Nested {
void bar() {
instanceMethod();
i++;
}
}
}