diff --git a/config/suppressions.xml b/config/suppressions.xml index 14573da81..5f8fa9a27 100644 --- a/config/suppressions.xml +++ b/config/suppressions.xml @@ -68,6 +68,8 @@ + + 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 0712599cc..3d6e80d03 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 @@ -283,7 +283,7 @@ public class RequireThisCheck extends AbstractCheck { if (frame.getFrameName().equals(getNearestClassFrameName())) { log(ast, msgKey, ast.getText(), ""); } - else { + else if (!(frame instanceof AnonymousClassFrame)) { log(ast, msgKey, ast.getText(), frame.getFrameName() + '.'); } } @@ -361,6 +361,12 @@ public class RequireThisCheck extends AbstractCheck { final DetailAST ctorFrameNameIdent = ast.findFirstToken(TokenTypes.IDENT); frameStack.addFirst(new ConstructorFrame(frame, ctorFrameNameIdent)); break; + case TokenTypes.LITERAL_NEW: + if (isAnonymousClassDef(ast)) { + frameStack.addFirst(new AnonymousClassFrame(frame, + ast.getFirstChild().toString())); + } + break; default: // do nothing } @@ -405,11 +411,26 @@ public class RequireThisCheck extends AbstractCheck { case TokenTypes.CTOR_DEF : frames.put(ast, frameStack.poll()); break; + case TokenTypes.LITERAL_NEW : + if (isAnonymousClassDef(ast)) { + frames.put(ast, frameStack.poll()); + } + break; default : // do nothing } } + /** + * Whether the AST is a definition of an anonymous class. + * @param ast the AST to process. + * @return true if the AST is a definition of an anonymous class. + */ + private static boolean isAnonymousClassDef(DetailAST ast) { + final DetailAST lastChild = ast.getLastChild(); + return lastChild != null && lastChild.getType() == TokenTypes.OBJBLOCK; + } + /** * Returns the class frame where violation is found (where the field is used without 'this') * or null otherwise. @@ -1062,7 +1083,7 @@ public class RequireThisCheck extends AbstractCheck { } /** - * A frame initiated at class< enum or interface definition; holds instance variable names. + * A frame initiated at class, enum or interface definition; holds instance variable names. * @author Stephen Bloch * @author Andrei Selkin */ @@ -1248,6 +1269,30 @@ public class RequireThisCheck extends AbstractCheck { } } + /** + * An anonymous class frame; holds instance variable names. + */ + private static class AnonymousClassFrame extends ClassFrame { + + /** The name of the frame. */ + private final String frameName; + + /** + * Creates anonymous class frame. + * @param parent parent frame. + * @param frameName name of the frame. + */ + protected AnonymousClassFrame(AbstractFrame parent, String frameName) { + super(parent, null); + this.frameName = frameName; + } + + @Override + protected String getFrameName() { + return frameName; + } + } + /** * A frame initiated on entering a statement list; holds local variable names. * @author Stephen Bloch diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheckTest.java index b5f92d808..1b83715fe 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheckTest.java @@ -137,7 +137,11 @@ public class RequireThisCheckTest extends BaseCheckTestSupport { public void testWithAnonymousClass() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(RequireThisCheck.class); checkConfig.addAttribute("validateOnlyOverlapping", "false"); - final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; + final String[] expected = { + "19:25: " + getCheckMessage(MSG_METHOD, "doSideEffect", ""), + "23:24: " + getCheckMessage(MSG_VARIABLE, "bar", "InputRequireThis3."), + "46:17: " + getCheckMessage(MSG_VARIABLE, "foobar", ""), + }; verify(checkConfig, getPath("InputRequireThis3.java"), expected); diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/InputRequireThis3.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/InputRequireThis3.java index 4d326a652..cfbaa8e13 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/InputRequireThis3.java +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/coding/InputRequireThis3.java @@ -1,6 +1,9 @@ package com.puppycrawl.tools.checkstyle.checks.coding; public class InputRequireThis3 { + + private int bar; + interface AnonWithEmpty { public void fooEmpty(); } @@ -17,7 +20,30 @@ public class InputRequireThis3 { } public int doSideEffect() { - return 1; + return bar; + } + }; + + new AnonWithEmpty() { + int anonMember = 0; + + @Override + public void fooEmpty() { + new AnonWithEmpty() { + + @Override + public void fooEmpty() { + anonMember++; + } + }; + } + }; + + new AnonWithEmpty() { + int foobar = 1; + @Override + public void fooEmpty() { + foobar++; } }; }