Corrected bug 747530, inner class fields interpreted as local variables.

Incorporated catch parameters as local variables.
This commit is contained in:
Rick Giles 2003-06-02 18:06:35 +00:00
parent c1bc1ef555
commit 4981978ee2
11 changed files with 117 additions and 9 deletions

View File

@ -58,7 +58,8 @@
</tr>
<tr>
<td><span class="code">LocalVariableName</span></td>
<td>local, non-<span class="code">final</span> variables</td>
<td>local, non-<span class="code">final</span> variables, including
<span class="code">catch</span> parameters</td>
<td><span class="default">^[a-z][a-zA-Z0-9]*$</span></td>
</tr>
<tr>
@ -110,6 +111,22 @@
&lt;/module&gt;
</pre>
</li>
<li>
Module <span class="code">LocalVariableName</span> also has property <span class="code">tokens</span>
which can be used to control whether the check applies to variable declarations or
<span class="code">catch</span> clause parameters through
tokens
<span class="code">VARIABLE_DEF</span> and <span class="code">PARAMETER_DEF</span>.
For example, the following configuration element ensures that
<span class="code">catch</span> clause parameters begin with <span class="code">"e"</span>,
followed by letters and digits:
<pre class="body">
&lt;module name=&quot;LocalVariableName&quot;&gt;
&lt;property name=&quot;format&quot; value=&quot;^e[a-zA-Z0-9]*$&quot;/&gt;
&lt;property name=&quot;tokens&quot; value=&quot;PARAMETER_DEF&quot;/&gt;
&lt;/module&gt;
</pre>
</li>
<li>
Module <span class="code">TypeName</span> also has property <span class="code">tokens</span>
which can be used to control whether the check applies to classes or interfaces through

View File

@ -90,6 +90,8 @@
<li class="body">EmptyBlock does not accept stmt option (bug 747400)</li>
<li class="body">Inner class fields interpreted as local variables (bug 747530)</li>
</ul>

View File

@ -178,4 +178,32 @@ public final class ScopeUtils
return retVal;
}
/**
* Determines whether a node is a local variable definition,
* i.e. is declared in a code block, a for initializer, or a
* catch parameter.
* @param aAST the node to check.
* @return whether aAST is a local variable definition.
*/
public static boolean isLocalVariableDef(DetailAST aAST)
{
// variable declaration?
if (aAST.getType() == TokenTypes.VARIABLE_DEF) {
final DetailAST parent = aAST.getParent();
if (parent != null) {
final int type = parent.getType();
return (type == TokenTypes.SLIST)
|| (type == TokenTypes.FOR_INIT);
}
}
// catch parameter?
else if (aAST.getType() == TokenTypes.PARAMETER_DEF) {
final DetailAST parent = aAST.getParent();
if (parent != null) {
return (parent.getType() == TokenTypes.LITERAL_CATCH);
}
}
return false;
}
}

View File

@ -134,7 +134,9 @@ public class HiddenFieldCheck
private void processVariable(DetailAST aAST)
{
if (!ScopeUtils.inInterfaceBlock(aAST)) {
if (ScopeUtils.inCodeBlock(aAST)) {
if (ScopeUtils.isLocalVariableDef(aAST)
|| (aAST.getType() == TokenTypes.PARAMETER_DEF))
{
//local variable or parameter. Does it shadow a field?
final DetailAST nameAST = aAST.findFirstToken(TokenTypes.IDENT);
final String name = nameAST.getText();

View File

@ -71,7 +71,6 @@ public class LocalFinalVariableNameCheck
aAST.findFirstToken(TokenTypes.MODIFIERS);
final boolean isFinal = (modifiersAST != null)
&& modifiersAST.branchContains(TokenTypes.FINAL);
return (isFinal && ScopeUtils.inCodeBlock(aAST));
return (isFinal && ScopeUtils.isLocalVariableDef(aAST));
}
}

View File

@ -25,7 +25,8 @@ import com.puppycrawl.tools.checkstyle.api.TokenTypes;
/**
* <p>
* Checks that local, non-final variable names conform to a format specified
* by the format property. The format is a
* by the format property. A catch parameter is considered to be
* a local variable. The format is a
* <a href="http://jakarta.apache.org/regexp/apidocs/org/apache/regexp/RE.html">
* regular expression</a>
* and defaults to
@ -61,7 +62,10 @@ public class LocalVariableNameCheck
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public int[] getDefaultTokens()
{
return new int[] {TokenTypes.VARIABLE_DEF};
return new int[] {
TokenTypes.VARIABLE_DEF,
TokenTypes.PARAMETER_DEF,
};
}
/** @see com.puppycrawl.tools.checkstyle.checks.AbstractNameCheck */
@ -71,7 +75,6 @@ public class LocalVariableNameCheck
aAST.findFirstToken(TokenTypes.MODIFIERS);
final boolean isFinal = (modifiersAST != null)
&& modifiersAST.branchContains(TokenTypes.FINAL);
return (!isFinal && ScopeUtils.inCodeBlock(aAST));
return (!isFinal && ScopeUtils.isLocalVariableDef(aAST));
}
}

View File

@ -73,6 +73,6 @@ public class MemberNameCheck
&& modifiersAST.branchContains(TokenTypes.LITERAL_STATIC);
return (!isStatic && !ScopeUtils.inInterfaceBlock(aAST)
&& !ScopeUtils.inCodeBlock(aAST));
&& !ScopeUtils.isLocalVariableDef(aAST));
}
}

View File

@ -41,4 +41,19 @@ class InputInner
protected static Object sWeird = new Object();
/** demonstrate bug in handling static final **/
static Object sWeird2 = new Object();
/** demonstrate bug in local final variable */
public interface Inter
{
}
public static void main()
{
Inter m = new Inter()
{
private static final int CDS = 1;
private int ABC;
};
}
}

View File

@ -28,5 +28,14 @@ public class LocalFinalVariableNameCheckTest
};
verify(checkConfig, getPath("InputSimple.java"), expected);
}
public void testInnerClass()
throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(LocalFinalVariableNameCheck.class);
final String[] expected = {};
verify(checkConfig, getPath("InputInner.java"), expected);
}
}

View File

@ -18,5 +18,27 @@ public class LocalVariableNameCheckTest
};
verify(checkConfig, getPath("InputSimple.java"), expected);
}
public void testInnerClass()
throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(LocalVariableNameCheck.class);
final String[] expected = {};
verify(checkConfig, getPath("InputInner.java"), expected);
}
public void testCatchParameter()
throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(LocalVariableNameCheck.class);
checkConfig.addAttribute("tokens", "PARAMETER_DEF");
checkConfig.addAttribute("format", "^e$");
final String[] expected = {
"74:24: Name 'ex' must match pattern '^e$'.",
};
verify(checkConfig, getPath("InputEmptyStatement.java"), expected);
}
}

View File

@ -17,5 +17,16 @@ public class MemberNameCheckTest
};
verify(checkConfig, getPath("InputSimple.java"), expected);
}
public void testInnerClass()
throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(MemberNameCheck.class);
final String[] expected = {
"56:25: Name 'ABC' must match pattern '^[a-z][a-zA-Z0-9]*$'.",
};
verify(checkConfig, getPath("InputInner.java"), expected);
}
}