forked from phoedos/pmd
Add support for Unicode for JSP/JSF.
Add support to not parse body of <script> for JSP/JSF. Add new NoInlineScript rule for JSP/JSF. git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/branches/pmd/4.2.x@7015 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
@ -392,8 +392,16 @@
|
||||
<delete file="src/net/sourceforge/pmd/jsp/ast/ParseException.java" />
|
||||
<delete file="src/net/sourceforge/pmd/jsp/ast/CharStream.java" />
|
||||
<jjtree target="etc/grammar/JspParser.jjt" outputdirectory="src/net/sourceforge/pmd/jsp/ast/" javacchome="${javacc-home.path}" />
|
||||
|
||||
<!-- Generate Unicode w/o Unicode Escapes CharStream implementation -->
|
||||
<javacc static="false" usercharstream="false" unicodeinput="true" javaunicodeescape="false" target="src/net/sourceforge/pmd/jsp/ast/JspParser.jj" outputdirectory="src/net/sourceforge/pmd/jsp/ast" javacchome="${javacc-home.path}" />
|
||||
<replace file="src/net/sourceforge/pmd/jsp/ast/SimpleCharStream.java" token="public class SimpleCharStream" value="public class JspCharStream implements CharStream" />
|
||||
<replace file="src/net/sourceforge/pmd/jsp/ast/SimpleCharStream.java" token="public SimpleCharStream" value="public JspCharStream" />
|
||||
<move file="src/net/sourceforge/pmd/jsp/ast/SimpleCharStream.java" tofile="src/net/sourceforge/pmd/jsp/ast/JspCharStream.java"/>
|
||||
<delete file="src/net/sourceforge/pmd/jsp/ast/JspParser.java" />
|
||||
|
||||
<!-- Ensure generated using CharStream interface -->
|
||||
<javacc static="false" usercharstream="true" target="src/net/sourceforge/pmd/jsp/ast/JspParser.jj" outputdirectory="src/net/sourceforge/pmd/jsp/ast" javacchome="${javacc-home.path}" />
|
||||
<javacc static="false" usercharstream="true" unicodeinput="true" javaunicodeescape="false" target="src/net/sourceforge/pmd/jsp/ast/JspParser.jj" outputdirectory="src/net/sourceforge/pmd/jsp/ast" javacchome="${javacc-home.path}" />
|
||||
|
||||
<delete file="src/net/sourceforge/pmd/jsp/ast/JspParser.jj" />
|
||||
<replace file="src/net/sourceforge/pmd/jsp/ast/JspParserTokenManager.java" token="throw new Error" value="throw new RuntimeException" />
|
||||
|
@ -13,6 +13,8 @@ Fixed bug 2904832 - Type resolution not working for ASTType when using an inner
|
||||
|
||||
Correct -benchmark reporting of Rule visits via the RuleChain
|
||||
Fix issue with Type Resolution incorrectly handling of Classes with same name as a java.lang Class.
|
||||
The JSP/JSF parser can now parse Unicode input.
|
||||
The JSP/JSP parser can now handle <script>...</script> tags. The AST HtmlScript node contains the content.
|
||||
|
||||
Dependencies updates: asm updated to 3.2
|
||||
|
||||
@ -23,6 +25,7 @@ New rule:
|
||||
Controversial : AvoidLiteralsInIfCondition (patch 2591627), UseConcurrentHashMap
|
||||
StrictExceptions : AvoidCatchingGenericException, AvoidLosingExceptionInformation
|
||||
Naming : GenericsNaming
|
||||
JSP: NoInlineScript
|
||||
|
||||
February 08, 2009 - 4.2.5:
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
/* JSP Parser for PMD.
|
||||
/* JSP Parser for PMD.
|
||||
* It supports supports more-or-less well written JSP files.
|
||||
* The JSP Document style is supported, except for inline DTD.
|
||||
* The JSP Page style (<% ... %>) is supported.
|
||||
* Java code is not parsed.
|
||||
* Script code inside <script> ... </script> is not parsed.
|
||||
*/
|
||||
|
||||
options {
|
||||
USER_CHAR_STREAM = true;
|
||||
NODE_USES_PARSER=true;
|
||||
UNICODE_INPUT=true;
|
||||
|
||||
IGNORE_CASE = true;
|
||||
STATIC = false;
|
||||
@ -19,7 +21,7 @@ options {
|
||||
PARSER_BEGIN(JspParser)
|
||||
/**
|
||||
* JSP Parser for PMD.
|
||||
* @author Pieter – Application Engineers NV/SA – http://www.ae.be
|
||||
* @author Pieter Application Engineers NV/SA http://www.ae.be
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.jsp.ast;
|
||||
@ -78,6 +80,7 @@ PARSER_END(JspParser)
|
||||
* - JspExpressionState : inside an expression <%= ... %>
|
||||
* - JspDeclarationState : inside a declaration <%! ... %>
|
||||
* - JspCommentState : inside a comment <%-- ... --%>
|
||||
* - HtmlScriptContentState : inside an HTML script <script> ... </script>
|
||||
*/
|
||||
|
||||
|
||||
@ -263,6 +266,18 @@ PARSER_END(JspParser)
|
||||
| < COMMENT_TEXT: (~[]) >
|
||||
}
|
||||
|
||||
<HtmlScriptContentState> TOKEN :
|
||||
{
|
||||
<HTML_SCRIPT_CONTENT: (~[]) >
|
||||
| <HTML_SCRIPT_END_TAG : "</script" | "</Script" | "</SCRIPT">
|
||||
{
|
||||
// We've done a custom lookahead for the closing </script> and found it.
|
||||
// Put it back into the input stream, so it can be processed normally.
|
||||
input_stream.backup(8);
|
||||
image.setLength(image.length() - 8); // kill the "<script"
|
||||
matchedToken.image = image.toString();
|
||||
} : AfterTagState
|
||||
}
|
||||
|
||||
/** ******************************************************************** */
|
||||
/** ************************* JSP GRAMMAR **************************** */
|
||||
@ -498,9 +513,20 @@ void Element() :
|
||||
(Attribute())*
|
||||
(
|
||||
(<TAG_END>
|
||||
{ jjtThis.setEmpty(false); }
|
||||
{
|
||||
jjtThis.setEmpty(false);
|
||||
|
||||
(Content())?
|
||||
// Content in a <script> element needs special treatment (like a comment or CDataSection).
|
||||
// Tell the TokenManager to start looking for the body of a script element. In this
|
||||
// state all text will be consumed by the next token up to the closing </script> tag.
|
||||
// This is a context sensitive switch for the token manager, not something one can
|
||||
// express using normal JavaCC syntax. Hence the hoop jumping.
|
||||
if ("script".equalsIgnoreCase(startTagName.image)) {
|
||||
token_source.SwitchTo(HtmlScriptContentState);
|
||||
}
|
||||
}
|
||||
|
||||
(HtmlScript() | Content())?
|
||||
|
||||
<ENDTAG_START>
|
||||
endTagName = <TAG_NAME>
|
||||
@ -645,3 +671,16 @@ void DoctypeExternalId() :
|
||||
{ jjtThis.setUri(quoteContent(systemLiteral.image)); }
|
||||
)
|
||||
}
|
||||
|
||||
void HtmlScript() :
|
||||
{
|
||||
StringBuffer content = new StringBuffer();
|
||||
Token t;
|
||||
}
|
||||
{
|
||||
(t = <HTML_SCRIPT_CONTENT> { content.append(t.image); })*
|
||||
<HTML_SCRIPT_END_TAG>
|
||||
{
|
||||
jjtThis.setImage(content.toString().trim());
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
package test.net.sourceforge.pmd.jsp.ast;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.jsp.ast.ASTAttribute;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTAttributeValue;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTCData;
|
||||
@ -8,14 +15,9 @@ import net.sourceforge.pmd.jsp.ast.ASTCommentTag;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTDoctypeDeclaration;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTDoctypeExternalId;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTElement;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTHtmlScript;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
/**
|
||||
* Test parsing of a JSP in document style, by checking the generated AST.
|
||||
*
|
||||
@ -157,6 +159,17 @@ public class JspDocStyleTest extends AbstractJspNodesTst {
|
||||
assertEquals("Correct comment content expected!", "comment", comment.getImage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test parsing of HTML <script> element.
|
||||
*/
|
||||
@Test
|
||||
public void testHtmlScript() {
|
||||
Set scripts = getNodes(ASTHtmlScript.class, TEST_HTML_SCRIPT);
|
||||
assertEquals("One script expected!", 1, scripts.size());
|
||||
ASTHtmlScript script = (ASTHtmlScript) scripts.iterator().next();
|
||||
assertEquals("Correct script content expected!", "Script!", script.getImage());
|
||||
}
|
||||
|
||||
private static final String TEST_SIMPLEST_HTML = "<html/>";
|
||||
|
||||
private static final String TEST_ELEMENT_AND_NAMESPACE = "<h:html MyNsPrefix:MyAttr='MyValue'/>";
|
||||
@ -173,6 +186,9 @@ public class JspDocStyleTest extends AbstractJspNodesTst {
|
||||
private static final String TEST_ATTRIBUTE_VALUE_CONTAINING_HASH =
|
||||
"<tag:if something=\"#yes#\" foo=\"CREATE\"> <a href=\"#\">foo</a> </tag:if>";
|
||||
|
||||
private static final String TEST_HTML_SCRIPT =
|
||||
"<html><head><script>Script!</script></head></html>";
|
||||
|
||||
public static junit.framework.Test suite() {
|
||||
return new junit.framework.JUnit4TestAdapter(JspDocStyleTest.class);
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package test.net.sourceforge.pmd.jsp.rules;
|
||||
|
||||
import org.junit.Before;
|
||||
|
||||
import test.net.sourceforge.pmd.testframework.SimpleAggregatorTst;
|
||||
|
||||
public class NoInlineScriptTest extends SimpleAggregatorTst {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
addRule("jsp", "NoInlineScript");
|
||||
}
|
||||
|
||||
public static junit.framework.Test suite() {
|
||||
return new junit.framework.JUnit4TestAdapter(NoInlineScriptTest.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<test-data>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
A violation.
|
||||
]]></description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
<html><head><script>Some script</script></head></html>
|
||||
]]></code>
|
||||
<source-type>jsp</source-type>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
A violation.
|
||||
]]></description>
|
||||
<expected-problems>1</expected-problems>
|
||||
<code><![CDATA[
|
||||
<html><head><script src="script location">Some script</script></head></html>
|
||||
]]></code>
|
||||
<source-type>jsp</source-type>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
Ok, no 'src' with empty body.
|
||||
]]></description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
<html><head><script></script></head></html>
|
||||
]]></code>
|
||||
<source-type>jsp</source-type>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
Ok, only 'src' with empty whitespace body.
|
||||
]]></description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
<html><head><script src="script location"> </script></head></html>
|
||||
]]></code>
|
||||
<source-type>jsp</source-type>
|
||||
</test-code>
|
||||
<test-code>
|
||||
<description><![CDATA[
|
||||
Ok, only 'src' without body.
|
||||
]]></description>
|
||||
<expected-problems>0</expected-problems>
|
||||
<code><![CDATA[
|
||||
<html><head><script src="script location"/></head></html>
|
||||
]]></code>
|
||||
<source-type>jsp</source-type>
|
||||
</test-code>
|
||||
</test-data>
|
@ -261,7 +261,39 @@ and
|
||||
|
||||
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="Content-Type"Â content="text/html; charset=UTF-8" />
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
||||
<rule
|
||||
name="NoInlineScript"
|
||||
class="net.sourceforge.pmd.rules.XPathRule"
|
||||
message="Avoiding inlining HTML script content"
|
||||
externalInfoUrl="http://pmd.sourceforge.net/rules/basic-jsp.html#JspEncoding">
|
||||
<description>
|
||||
<![CDATA[
|
||||
Avoid inlining HTML script content. Consider externalizing the HTML script using the 'src' attribute on the <script> element.
|
||||
Externalized script could be reused between pages. Browsers can also cache the script, reducing overall download bandwidth.
|
||||
]]>
|
||||
</description>
|
||||
<priority>3</priority>
|
||||
<properties>
|
||||
<property name="xpath">
|
||||
<value>
|
||||
<![CDATA[
|
||||
//HtmlScript[@Image != '']
|
||||
]]>
|
||||
</value>
|
||||
</property>
|
||||
</properties>
|
||||
<example>
|
||||
<![CDATA[
|
||||
Most browsers should be able to interpret the following headers:
|
||||
|
||||
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
|
||||
|
||||
<meta http-equiv="Content-Type"Â content="text/html; charset=UTF-8" />
|
||||
]]>
|
||||
</example>
|
||||
</rule>
|
||||
|
20
pmd/src/net/sourceforge/pmd/jsp/ast/ASTHtmlScript.java
Normal file
20
pmd/src/net/sourceforge/pmd/jsp/ast/ASTHtmlScript.java
Normal file
@ -0,0 +1,20 @@
|
||||
/* Generated By:JJTree: Do not edit this line. ASTHtmlScript.java Version 4.1 */
|
||||
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=false,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY= */
|
||||
package net.sourceforge.pmd.jsp.ast;
|
||||
|
||||
public class ASTHtmlScript extends SimpleNode {
|
||||
public ASTHtmlScript(int id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
public ASTHtmlScript(JspParser p, int id) {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
public Object jjtAccept(JspParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=8170f25fd45a522c3d56439f6d24e048 (do not edit this line) */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/* Generated By:JJTree&JavaCC: Do not edit this line. JspParserConstants.java */
|
||||
/**
|
||||
* JSP Parser for PMD.
|
||||
* @author Pieter � Application Engineers NV/SA � http://www.ae.be
|
||||
* @author Pieter Application Engineers NV/SA http://www.ae.be
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.jsp.ast;
|
||||
@ -163,41 +163,47 @@ public interface JspParserConstants {
|
||||
int COMMENT_END = 75;
|
||||
/** RegularExpression Id. */
|
||||
int COMMENT_TEXT = 76;
|
||||
/** RegularExpression Id. */
|
||||
int HTML_SCRIPT_CONTENT = 77;
|
||||
/** RegularExpression Id. */
|
||||
int HTML_SCRIPT_END_TAG = 78;
|
||||
|
||||
/** Lexical state. */
|
||||
int CommentState = 0;
|
||||
int HtmlScriptContentState = 0;
|
||||
/** Lexical state. */
|
||||
int AttrValueBetweenDoubleQuotesState = 1;
|
||||
int CommentState = 1;
|
||||
/** Lexical state. */
|
||||
int AttrValueBetweenSingleQuotesState = 2;
|
||||
int AttrValueBetweenDoubleQuotesState = 2;
|
||||
/** Lexical state. */
|
||||
int StartTagState = 3;
|
||||
int AttrValueBetweenSingleQuotesState = 3;
|
||||
/** Lexical state. */
|
||||
int CDataState = 4;
|
||||
int StartTagState = 4;
|
||||
/** Lexical state. */
|
||||
int DocTypeExternalIdState = 5;
|
||||
int CDataState = 5;
|
||||
/** Lexical state. */
|
||||
int DocTypeState = 6;
|
||||
int DocTypeExternalIdState = 6;
|
||||
/** Lexical state. */
|
||||
int JspCommentState = 7;
|
||||
int DocTypeState = 7;
|
||||
/** Lexical state. */
|
||||
int JspDeclarationState = 8;
|
||||
int JspCommentState = 8;
|
||||
/** Lexical state. */
|
||||
int JspExpressionState = 9;
|
||||
int JspDeclarationState = 9;
|
||||
/** Lexical state. */
|
||||
int JspScriptletState = 10;
|
||||
int JspExpressionState = 10;
|
||||
/** Lexical state. */
|
||||
int InTagState = 11;
|
||||
int JspScriptletState = 11;
|
||||
/** Lexical state. */
|
||||
int AfterTagState = 12;
|
||||
int InTagState = 12;
|
||||
/** Lexical state. */
|
||||
int AttrValueState = 13;
|
||||
int AfterTagState = 13;
|
||||
/** Lexical state. */
|
||||
int JspDirectiveAttributesState = 14;
|
||||
int AttrValueState = 14;
|
||||
/** Lexical state. */
|
||||
int JspDirectiveState = 15;
|
||||
int JspDirectiveAttributesState = 15;
|
||||
/** Lexical state. */
|
||||
int DEFAULT = 16;
|
||||
int JspDirectiveState = 16;
|
||||
/** Lexical state. */
|
||||
int DEFAULT = 17;
|
||||
|
||||
/** Literal token values. */
|
||||
String[] tokenImage = {
|
||||
@ -278,6 +284,8 @@ public interface JspParserConstants {
|
||||
"<DOLLAR_OR_HASH_DOUBLE_QUOTE>",
|
||||
"<COMMENT_END>",
|
||||
"<COMMENT_TEXT>",
|
||||
"<HTML_SCRIPT_CONTENT>",
|
||||
"<HTML_SCRIPT_END_TAG>",
|
||||
};
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,7 @@ public interface JspParserTreeConstants
|
||||
public int JJTDECLARATION = 19;
|
||||
public int JJTDOCTYPEDECLARATION = 20;
|
||||
public int JJTDOCTYPEEXTERNALID = 21;
|
||||
public int JJTHTMLSCRIPT = 22;
|
||||
|
||||
|
||||
public String[] jjtNodeName = {
|
||||
@ -50,6 +51,7 @@ public interface JspParserTreeConstants
|
||||
"Declaration",
|
||||
"DoctypeDeclaration",
|
||||
"DoctypeExternalId",
|
||||
"HtmlScript",
|
||||
};
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=d7bde07aef0db02727c15b118c4c677f (do not edit this line) */
|
||||
/* JavaCC - OriginalChecksum=e88447ad3f3129b84d706554cb6c3195 (do not edit this line) */
|
||||
|
@ -25,5 +25,6 @@ public interface JspParserVisitor
|
||||
public Object visit(ASTDeclaration node, Object data);
|
||||
public Object visit(ASTDoctypeDeclaration node, Object data);
|
||||
public Object visit(ASTDoctypeExternalId node, Object data);
|
||||
public Object visit(ASTHtmlScript node, Object data);
|
||||
}
|
||||
/* JavaCC - OriginalChecksum=85c3652943205ef4624387751f8ca0e6 (do not edit this line) */
|
||||
/* JavaCC - OriginalChecksum=04069d9511f38dbdc673d112c08dd375 (do not edit this line) */
|
||||
|
@ -92,4 +92,7 @@ public class JspParserVisitorAdapter implements JspParserVisitor {
|
||||
return visit((SimpleNode) node, data);
|
||||
}
|
||||
|
||||
public Object visit(ASTHtmlScript node, Object data) {
|
||||
return visit((SimpleNode) node, data);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import net.sourceforge.pmd.jsp.ast.ASTDoctypeDeclaration;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTDoctypeExternalId;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTElExpression;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTElement;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTHtmlScript;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTJspComment;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTJspDeclaration;
|
||||
import net.sourceforge.pmd.jsp.ast.ASTJspDirective;
|
||||
@ -213,4 +214,8 @@ public abstract class AbstractJspRule extends CommonAbstractRule implements
|
||||
public Object visit(ASTDoctypeExternalId node, Object data) {
|
||||
return visit((SimpleNode)node, data);
|
||||
}
|
||||
|
||||
public Object visit(ASTHtmlScript node, Object data) {
|
||||
return visit((SimpleNode)node, data);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user