fix for bug 1560940: MultipleStringLiteralCheck now ignores annotations by default. It is possible to retain the old behaviour by setting the new check property ignoreOccurrenceContext to an empty value.

This commit is contained in:
Lars Kühne 2007-02-11 13:37:19 +00:00
parent 03b0bc8f47
commit a501b8d95a
5 changed files with 109 additions and 0 deletions

View File

@ -19,6 +19,7 @@
package com.puppycrawl.tools.checkstyle.checks.coding;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
@ -42,6 +43,12 @@ public class MultipleStringLiteralsCheck extends Check
* <String, ArrayList>, with the ArrayList containing StringInfo objects.
*/
private final HashMap mStringMap = new HashMap();
/**
* Marks the TokenTypes where duplicate strings should be ignored.
*/
private final BitSet mIgnoreOccurrenceContext = new BitSet();
/**
* The allowed number of string duplicates in a file before an error is
* generated.
@ -68,6 +75,7 @@ public class MultipleStringLiteralsCheck extends Check
public MultipleStringLiteralsCheck()
{
setIgnoreStringsRegexp("^\"\"$");
mIgnoreOccurrenceContext.set(TokenTypes.ANNOTATION);
}
/**
@ -86,6 +94,20 @@ public class MultipleStringLiteralsCheck extends Check
}
}
/**
* Adds a set of tokens the check is interested in.
* @param aStrRep the string representation of the tokens interested in
*/
public final void setIgnoreOccurrenceContext(String[] aStrRep)
{
mIgnoreOccurrenceContext.clear();
for (int i = 0; i < aStrRep.length; i++) {
final String s = aStrRep[i];
final int type = TokenTypes.getTokenId(s);
mIgnoreOccurrenceContext.set(type);
}
}
/** {@inheritDoc} */
public int[] getDefaultTokens()
{
@ -95,6 +117,9 @@ public class MultipleStringLiteralsCheck extends Check
/** {@inheritDoc} */
public void visitToken(DetailAST aAST)
{
if (isInIgnoreOccurrenceContext(aAST)) {
return;
}
final String currentString = aAST.getText();
if ((mPattern == null) || !mPattern.matcher(currentString).find()) {
ArrayList hitList = (ArrayList) mStringMap.get(currentString);
@ -108,6 +133,28 @@ public class MultipleStringLiteralsCheck extends Check
}
}
/**
* Analyses the path from the AST root to a given AST for occurrences
* of the token types in {@link #mIgnoreOccurrenceContext}.
*
* @param aAST the node from where to start searching towards the root node
* @return whether the path from the root node to aAST contains one of the
* token type in {@link #mIgnoreOccurrenceContext}.
*/
private boolean isInIgnoreOccurrenceContext(DetailAST aAST)
{
for (DetailAST token = aAST;
token.getParent() != null;
token = token.getParent())
{
final int type = token.getType();
if (mIgnoreOccurrenceContext.get(type)) {
return true;
}
}
return false;
}
/** {@inheritDoc} */
public void beginTree(DetailAST aRootAST)
{

View File

@ -15,4 +15,16 @@ public class InputMultipleStringLiterals
// The following is not reported, since it is two string literals.
String a2 = "String" + "Contents";
}
@SuppressWarnings("unchecked")
void method2(){}
@SuppressWarnings("unchecked")
void method3(){}
@SuppressWarnings("unchecked")
void method4(){}
@SuppressWarnings("unchecked")
void method5(){}
}

View File

@ -56,4 +56,21 @@ public class MultipleStringLiteralsCheckTest extends BaseCheckTestCase
getPath("coding" + File.separator + "InputMultipleStringLiterals.java"),
expected);
}
public void testItWithoutIgnoringAnnotations() throws Exception
{
DefaultConfiguration checkConfig =
createCheckConfig(MultipleStringLiteralsCheck.class);
checkConfig.addAttribute("allowedDuplicates", "3");
checkConfig.addAttribute("ignoreOccurrenceContext", "");
final String[] expected = {
"19:23: The String \"unchecked\" appears 4 times in the file.",
};
verify(checkConfig,
getPath("coding" + File.separator + "InputMultipleStringLiterals.java"),
expected);
}
}

View File

@ -2019,6 +2019,23 @@ case 3:
<td><a href="property_types.html#regexp">regular expression</a></td>
<td><span class="default">^""$</span> (ignore empty strings)</td>
</tr>
<tr>
<td>ignoreOccurrenceContext</td>
<td>
Token type names where duplicate strings are ignored even if they don't match
ignoredStringsRegexp. This allows you to exclude syntactical contexts like
Annotations or static initializers from the check.
</td>
<td>
<a href="property_types.html#stringSet">list</a> of
<a href="api/com/puppycrawl/tools/checkstyle/api/TokenTypes.html">token type</a>
names
</td>
<td>
<span class="default">ANNOTATION</span>
(ignore strings inside the context of an annotation)
</td>
</tr>
</table>
</subsection>
@ -2046,6 +2063,17 @@ case 3:
<source>
&lt;module name=&quot;MultipleStringLiterals&quot;&gt;
&lt;property name=&quot;allowedDuplicates&quot; value='^((&quot;&quot;)|(&quot;, &quot;))$'/&gt;
&lt;/module&gt;
</source>
<p>
To configure the check so that it flags duplicate strings in all
syntactical contexts, even in annotations like
<span class="default">@SuppressWarnings("unchecked")</span>:
</p>
<source>
&lt;module name=&quot;MultipleStringLiterals&quot;&gt;
&lt;property name=&quot;ignoreOccurrenceContext&quot; value=&quot;&quot;/&gt;
&lt;/module&gt;
</source>
</subsection>

View File

@ -16,6 +16,11 @@
<li>
checkstyle-all.jar contained some classes from jakarta commons-collections twice. (bug 1630361)
</li>
<li>
Multiple string literal check now ignores annotations by default (bug 1560940).
It is possible to retain the old behaviour by setting the new check property
ignoreOccurrenceContext to an empty value.
</li>
</ul>
<p>New features:</p>