Merge branch 'bug-1425'
This commit is contained in:
@ -104,6 +104,35 @@ public class ASTLiteral extends AbstractJavaTypeNode {
|
||||
return isString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to reconstruct the original string literal.
|
||||
* If the original length is greater than the parsed String literal, then
|
||||
* probably some unicode escape sequences have been used.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getEscapedStringLiteral() {
|
||||
String image = getImage();
|
||||
if (!isStringLiteral() && !isCharLiteral()) {
|
||||
return image;
|
||||
}
|
||||
int fullLength = getEndColumn() - getBeginColumn();
|
||||
if (fullLength > image.length()) {
|
||||
StringBuilder result = new StringBuilder(fullLength);
|
||||
for (int i = 0; i < image.length(); i++) {
|
||||
char c = image.charAt(i);
|
||||
if (c < 0x20 || c > 0xff || image.length() == 1) {
|
||||
String hex = "0000" + Integer.toHexString(c);
|
||||
result.append("\\u").append(hex.substring(hex.length() - 4));
|
||||
} else {
|
||||
result.append(c);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a String literal with only one character.
|
||||
* Handles octal and escape characters.
|
||||
|
@ -143,9 +143,11 @@ public class AvoidDuplicateLiteralsRule extends AbstractJavaRule {
|
||||
for (Map.Entry<String, List<ASTLiteral>> entry : literals.entrySet()) {
|
||||
List<ASTLiteral> occurrences = entry.getValue();
|
||||
if (occurrences.size() >= threshold) {
|
||||
Object[] args = new Object[] { entry.getKey(), Integer.valueOf(occurrences.size()),
|
||||
Integer.valueOf(occurrences.get(0).getBeginLine()) };
|
||||
addViolation(data, occurrences.get(0), args);
|
||||
ASTLiteral first = occurrences.get(0);
|
||||
String rawImage = first.getEscapedStringLiteral();
|
||||
Object[] args = new Object[] { rawImage, Integer.valueOf(occurrences.size()),
|
||||
Integer.valueOf(first.getBeginLine()) };
|
||||
addViolation(data, first, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.sourceforge.pmd.lang.java.ast;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@ -54,6 +55,50 @@ public class ASTLiteralTest extends ParserTst {
|
||||
assertTrue(((ASTLiteral)(literals.iterator().next())).isCharLiteral());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringUnicodeEscapesNotEscaped() {
|
||||
ASTLiteral literal = new ASTLiteral(1);
|
||||
literal.setStringLiteral();
|
||||
literal.setImage("abcüabc");
|
||||
literal.testingOnly__setBeginColumn(1);
|
||||
literal.testingOnly__setEndColumn(7);
|
||||
assertEquals("abcüabc", literal.getEscapedStringLiteral());
|
||||
assertEquals("abcüabc", literal.getImage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringUnicodeEscapesInvalid() {
|
||||
ASTLiteral literal = new ASTLiteral(1);
|
||||
literal.setStringLiteral();
|
||||
literal.setImage("abc\\uXYZAabc");
|
||||
literal.testingOnly__setBeginColumn(1);
|
||||
literal.testingOnly__setEndColumn(12);
|
||||
assertEquals("abc\\uXYZAabc", literal.getEscapedStringLiteral());
|
||||
assertEquals("abc\\uXYZAabc", literal.getImage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringUnicodeEscapesValid() {
|
||||
ASTLiteral literal = new ASTLiteral(1);
|
||||
literal.setStringLiteral();
|
||||
literal.setImage("abc\u1234abc");
|
||||
literal.testingOnly__setBeginColumn(1);
|
||||
literal.testingOnly__setEndColumn(12);
|
||||
assertEquals("abc\\u1234abc", literal.getEscapedStringLiteral());
|
||||
assertEquals("abcሴabc", literal.getImage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCharacterUnicodeEscapesValid() {
|
||||
ASTLiteral literal = new ASTLiteral(1);
|
||||
literal.setCharLiteral();
|
||||
literal.setImage("\u0030");
|
||||
literal.testingOnly__setBeginColumn(1);
|
||||
literal.testingOnly__setEndColumn(6);
|
||||
assertEquals("\\u0030", literal.getEscapedStringLiteral());
|
||||
assertEquals("0", literal.getImage());
|
||||
}
|
||||
|
||||
private static final String TEST1 =
|
||||
"public class Foo {" + PMD.EOL +
|
||||
" String x = \"foo\";" + PMD.EOL +
|
||||
@ -88,8 +133,4 @@ public class ASTLiteralTest extends ParserTst {
|
||||
"public class Foo {" + PMD.EOL +
|
||||
" char x = 'x';" + PMD.EOL +
|
||||
"}";
|
||||
|
||||
public static junit.framework.Test suite() {
|
||||
return new junit.framework.JUnit4TestAdapter(ASTLiteralTest.class);
|
||||
}
|
||||
}
|
||||
|
@ -8,19 +8,9 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.Rule;
|
||||
import net.sourceforge.pmd.testframework.SimpleAggregatorTst;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class AvoidDuplicateLiteralsRuleTest extends SimpleAggregatorTst {
|
||||
@Test
|
||||
public void testAll() {
|
||||
Rule rule = findRule("java-strings", "AvoidDuplicateLiterals");
|
||||
rule.setProperty(AvoidDuplicateLiteralsRule.THRESHOLD_DESCRIPTOR, 2);
|
||||
runTests(rule);
|
||||
}
|
||||
|
||||
public class AvoidDuplicateLiteralsRuleTest {
|
||||
@Test
|
||||
public void testStringParserEmptyString() {
|
||||
AvoidDuplicateLiteralsRule.ExceptionParser p = new AvoidDuplicateLiteralsRule.ExceptionParser(',');
|
||||
|
@ -12,6 +12,7 @@ public class StringsRulesTest extends SimpleAggregatorTst {
|
||||
@Override
|
||||
public void setUp() {
|
||||
addRule(RULESET, "AppendCharacterWithChar");
|
||||
addRule(RULESET, "AvoidDuplicateLiterals");
|
||||
addRule(RULESET, "AvoidStringBufferField");
|
||||
addRule(RULESET, "ConsecutiveAppendsShouldReuse");
|
||||
addRule(RULESET, "ConsecutiveLiteralAppends");
|
||||
|
@ -165,4 +165,22 @@ public class Foo {
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
|
||||
<test-code>
|
||||
<description>#1425 Invalid XML Characters in Output</description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<expected-messages>
|
||||
<message>The String literal "Tokenizer \ud801\udc1ctest" appears 4 times in this file; the first occurrence is on line 2</message>
|
||||
</expected-messages>
|
||||
<code><![CDATA[
|
||||
public class Duplicate {
|
||||
String s1 = "Tokenizer \ud801\udc1ctest";
|
||||
String s2 = "Tokenizer \ud801\udc1ctest";
|
||||
String s3 = "Tokenizer \ud801\udc1ctest";
|
||||
String s4 = "Tokenizer \ud801\udc1ctest";
|
||||
char c = '\uffef';
|
||||
char c\u0030 = 'a';
|
||||
}
|
||||
]]></code>
|
||||
</test-code>
|
||||
</test-data>
|
||||
|
Reference in New Issue
Block a user