[java] Avoid using Thread.fillInStackTrace() for token context

This requires to use the option TOKEN_MANAGER_USES_PARSER
This commit is contained in:
Andreas Dangel
2023-08-10 11:27:53 +02:00
parent d061883ca6
commit 41643dd020
3 changed files with 65 additions and 36 deletions

View File

@ -43,7 +43,7 @@
<property name="ast-api-package" value="net.sourceforge.pmd.lang.ast" /> <property name="ast-api-package" value="net.sourceforge.pmd.lang.ast" />
<property name="ast-impl-package" value="${ast-api-package}.impl.javacc" /> <property name="ast-impl-package" value="${ast-api-package}.impl.javacc" />
<property name="grammar-file" value="etc/grammar/${lang-name}.jjt" /> <property name="grammar-file" value="${basedir}/etc/grammar/${lang-name}.jjt" />
<property name="parser-name" value="${lang-name}ParserImpl" /> <property name="parser-name" value="${lang-name}ParserImpl" />
<property name="parser-file" value="${target-package-dir}/${parser-name}.java" /> <property name="parser-file" value="${target-package-dir}/${parser-name}.java" />
@ -108,6 +108,10 @@
<touch file="${stamp-file}" /> <touch file="${stamp-file}" />
<delete dir="${target-package-dir}" /> <delete dir="${target-package-dir}" />
<mkdir dir="${target-package-dir}" /> <mkdir dir="${target-package-dir}" />
<condition property="option-token-manager-uses-parser">
<resourcecontains resource="${grammar-file}" substring="TOKEN_MANAGER_USES_PARSER"/>
</condition>
</target> </target>
<target name="cleanup" unless="javaccBuildNotRequired"> <target name="cleanup" unless="javaccBuildNotRequired">
@ -128,7 +132,7 @@
<arg value="-OUTPUT_DIRECTORY:${target-package-dir}" /> <arg value="-OUTPUT_DIRECTORY:${target-package-dir}" />
<arg value="-NODE_USES_PARSER:false" /> <arg value="-NODE_USES_PARSER:false" />
<arg value="-NODE_PACKAGE:${lang-ast-package}" /> <arg value="-NODE_PACKAGE:${lang-ast-package}" />
<arg value="etc/grammar/${lang-name}.jjt" /> <arg value="${grammar-file}" />
</java> </java>
</target> </target>
@ -189,6 +193,7 @@
<antcall target="constants-files" /> <antcall target="constants-files" />
<antcall target="constants-files-token-manager-uses-parser" />
<!-- For compatibility --> <!-- For compatibility -->
@ -359,8 +364,7 @@
<replaceregexp> <replaceregexp>
<regexp pattern="package ${lang-ast-package};" /> <regexp pattern="package ${lang-ast-package};" />
<substitution expression="\0 <substitution expression="\0${line.separator}${line.separator}import static ${lang-ast-package}.${token-constants-name}.*;" />
import static ${lang-ast-package}.${token-constants-name}.*;" />
<fileset file="${tokenmgr-file}" /> <fileset file="${tokenmgr-file}" />
<fileset file="${parser-file}" /> <fileset file="${parser-file}" />
</replaceregexp> </replaceregexp>
@ -455,6 +459,15 @@ public final class ${token-constants-name} \{${line.separator}
</target> </target>
<target name="constants-files-token-manager-uses-parser" if="option-token-manager-uses-parser">
<echo level="info">Option TOKEN_MANAGER_USES_PARSER is enabled</echo>
<replaceregexp flags="g">
<regexp pattern="return new ${tokenmgr-name}\(cs\);" />
<substitution expression="return new ${parser-name}(cs).token_source;" />
<fileset file="${token-constants-file}"/>
</replaceregexp>
</target>
<target name="cleanup-nodes"> <target name="cleanup-nodes">
<replaceregexp flags="g"> <replaceregexp flags="g">

View File

@ -279,6 +279,7 @@ options {
MULTI = true; MULTI = true;
VISITOR = true; VISITOR = true;
NODE_PACKAGE="net.sourceforge.pmd.lang.java.ast"; NODE_PACKAGE="net.sourceforge.pmd.lang.java.ast";
TOKEN_MANAGER_USES_PARSER = true;
// disable the calculation of expected tokens when a parse error occurs // disable the calculation of expected tokens when a parse error occurs
// depending on the possible allowed next tokens, this // depending on the possible allowed next tokens, this
@ -292,9 +293,10 @@ options {
PARSER_BEGIN(JavaParserImpl) PARSER_BEGIN(JavaParserImpl)
package net.sourceforge.pmd.lang.java.ast; package net.sourceforge.pmd.lang.java.ast;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Collections; import java.util.Deque;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -305,6 +307,7 @@ import net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken;
import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.ast.TokenMgrError; import net.sourceforge.pmd.lang.ast.TokenMgrError;
import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.java.ast.JavaParserImplTokenManager.TokenContext;
import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind; import net.sourceforge.pmd.lang.java.types.JPrimitiveType.PrimitiveTypeKind;
class JavaParserImpl { class JavaParserImpl {
@ -582,6 +585,13 @@ class JavaParserImpl {
*/ */
private boolean inExplicitConstructorInvoc = false; private boolean inExplicitConstructorInvoc = false;
private Deque<TokenContext> tokenContexts = new ArrayDeque<TokenContext>();
TokenContext determineTokenContext() {
if (tokenContexts.isEmpty()) {
return null;
}
return tokenContexts.peek();
}
} }
PARSER_END(JavaParserImpl) PARSER_END(JavaParserImpl)
@ -597,22 +607,7 @@ TOKEN_MGR_DECLS :
java.util.regex.Pattern.compile("^}(?:[^\"\\\\\n\r]|\\\\(?:[ntbrfs\\\\'\"]|[0-7][0-7]?|[0-3][0-7][0-7]))*(\\{|\")"); java.util.regex.Pattern.compile("^}(?:[^\"\\\\\n\r]|\\\\(?:[ntbrfs\\\\'\"]|[0-7][0-7]?|[0-3][0-7][0-7]))*(\\{|\")");
private TokenContext determineContext() { private TokenContext determineContext() {
Throwable t = new Throwable().fillInStackTrace(); return parser.determineTokenContext();
for (StackTraceElement e : t.getStackTrace()) {
String method = e.getMethodName();
if ("TextBlockTemplate".equals(method)) {
return TokenContext.TEXT_BLOCK_TEMPLATE;
} else if ("StringTemplate".equals(method)) {
return TokenContext.STRING_TEMPLATE;
} else if ("Block".equals(method)
|| "ClassOrInterfaceBody".equals(method)
|| "ArrayInitializer".equals(method)
|| "MemberValueArrayInitializer".equals(method)
|| "SwitchBlock".equals(method)) {
return TokenContext.BLOCK;
}
}
return null;
} }
private net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken rereadTokenAs(int kind, int length) { private net.sourceforge.pmd.lang.ast.impl.javacc.JavaccToken rereadTokenAs(int kind, int length) {
@ -1286,11 +1281,11 @@ void EnumDeclaration():
void EnumBody(): void EnumBody():
{} {}
{ {
"{" "{" { tokenContexts.push(TokenContext.BLOCK); }
[ EnumConstant() ( LOOKAHEAD(2) "," EnumConstant() )* ] [ EnumConstant() ( LOOKAHEAD(2) "," EnumConstant() )* ]
[ "," { jjtThis.setTrailingComma(); } ] [ "," { jjtThis.setTrailingComma(); } ]
[ ";" { jjtThis.setSeparatorSemi(); } ( ClassOrInterfaceBodyDeclaration() )* ] [ ";" { jjtThis.setSeparatorSemi(); } ( ClassOrInterfaceBodyDeclaration() )* ]
"}" "}" { tokenContexts.pop(); }
} }
void EnumConstant(): void EnumConstant():
@ -1333,9 +1328,9 @@ void RecordComponent():
void RecordBody(): void RecordBody():
{} {}
{ {
"{" "{" { tokenContexts.push(TokenContext.BLOCK); }
( RecordBodyDeclaration() )* ( RecordBodyDeclaration() )*
"}" "}" { tokenContexts.pop(); }
} }
void RecordBodyDeclaration() #void : void RecordBodyDeclaration() #void :
@ -1375,7 +1370,9 @@ void TypeParameter():
void ClassOrInterfaceBody(): void ClassOrInterfaceBody():
{} {}
{ {
"{" ( ClassOrInterfaceBodyDeclaration() )* "}" "{" { tokenContexts.push(TokenContext.BLOCK); }
( ClassOrInterfaceBodyDeclaration() )*
"}" { tokenContexts.pop(); }
} }
void ClassOrInterfaceBodyDeclaration() #void: void ClassOrInterfaceBodyDeclaration() #void:
@ -1436,7 +1433,9 @@ void VariableInitializer() #void:
void ArrayInitializer() : void ArrayInitializer() :
{} {}
{ {
"{" [ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}" "{" { tokenContexts.push(TokenContext.BLOCK); }
[ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ]
"}" { tokenContexts.pop(); }
} }
void MethodDeclaration() : void MethodDeclaration() :
@ -1501,10 +1500,10 @@ void ConstructorDeclaration() :
private void ConstructorBlock() #Block: private void ConstructorBlock() #Block:
{} {}
{ {
"{" "{" { tokenContexts.push(TokenContext.BLOCK); }
[ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ] [ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ]
( BlockStatement() )* ( BlockStatement() )*
"}" "}" { tokenContexts.pop(); }
} }
void ExplicitConstructorInvocation() : void ExplicitConstructorInvocation() :
@ -2329,19 +2328,27 @@ void Template() :
void StringTemplate() #void : void StringTemplate() #void :
{} {}
{ {
{ tokenContexts.push(TokenContext.STRING_TEMPLATE); }
<STRING_TEMPLATE_BEGIN> { setLastTokenImage(jjtThis); } #TemplateFragment <STRING_TEMPLATE_BEGIN> { setLastTokenImage(jjtThis); } #TemplateFragment
EmbeddedExpression() EmbeddedExpression()
( <STRING_TEMPLATE_MID> { setLastTokenImage(jjtThis); } #TemplateFragment EmbeddedExpression() )* ( <STRING_TEMPLATE_MID> { setLastTokenImage(jjtThis); } #TemplateFragment EmbeddedExpression() )*
<STRING_TEMPLATE_END> { setLastTokenImage(jjtThis); } #TemplateFragment <STRING_TEMPLATE_END> { setLastTokenImage(jjtThis); } #TemplateFragment
{ tokenContexts.pop(); }
} }
void TextBlockTemplate() #void : void TextBlockTemplate() #void :
{} {}
{ {
{ tokenContexts.push(TokenContext.TEXT_BLOCK_TEMPLATE); }
<TEXT_BLOCK_TEMPLATE_BEGIN> { setLastTokenImage(jjtThis); } #TemplateFragment <TEXT_BLOCK_TEMPLATE_BEGIN> { setLastTokenImage(jjtThis); } #TemplateFragment
EmbeddedExpression() EmbeddedExpression()
( <TEXT_BLOCK_TEMPLATE_MID> { setLastTokenImage(jjtThis); } #TemplateFragment EmbeddedExpression() )* ( <TEXT_BLOCK_TEMPLATE_MID> { setLastTokenImage(jjtThis); } #TemplateFragment EmbeddedExpression() )*
<TEXT_BLOCK_TEMPLATE_END> { setLastTokenImage(jjtThis); } #TemplateFragment <TEXT_BLOCK_TEMPLATE_END> { setLastTokenImage(jjtThis); } #TemplateFragment
{ tokenContexts.pop(); }
} }
void EmbeddedExpression() #void : void EmbeddedExpression() #void :
@ -2507,7 +2514,9 @@ void LabeledStatement() :
void Block() : void Block() :
{} {}
{ {
"{" ( BlockStatement() )* "}" "{" { tokenContexts.push(TokenContext.BLOCK); }
( BlockStatement() )*
"}" { tokenContexts.pop(); }
} }
void BlockStatement() #void: void BlockStatement() #void:
@ -2638,12 +2647,12 @@ void SwitchStatement():
void SwitchBlock() #void: void SwitchBlock() #void:
{} {}
{ {
"{" "{" { tokenContexts.push(TokenContext.BLOCK); }
( (
LOOKAHEAD(SwitchLabel() ":") (SwitchFallthroughBranch())+ LOOKAHEAD(SwitchLabel() ":") (SwitchFallthroughBranch())+
| (SwitchArrowBranch())* | (SwitchArrowBranch())*
) )
"}" "}" { tokenContexts.pop(); }
} }
void SwitchArrowBranch(): void SwitchArrowBranch():
@ -2940,7 +2949,9 @@ void MemberValue() #void:
void MemberValueArrayInitializer(): void MemberValueArrayInitializer():
{} {}
{ {
"{" (MemberValue() ( LOOKAHEAD(2) "," MemberValue() )*)? [ "," ] "}" "{" { tokenContexts.push(TokenContext.BLOCK); }
(MemberValue() ( LOOKAHEAD(2) "," MemberValue() )*)? [ "," ]
"}" { tokenContexts.pop(); }
} }
/* /*
@ -2965,7 +2976,9 @@ void AnnotationTypeDeclaration():
void AnnotationTypeBody(): void AnnotationTypeBody():
{} {}
{ {
"{" ( AnnotationTypeMemberDeclaration() )* "}" "{" { tokenContexts.push(TokenContext.BLOCK); }
( AnnotationTypeMemberDeclaration() )*
"}" { tokenContexts.pop(); }
} }
void AnnotationTypeMemberDeclaration() #void: void AnnotationTypeMemberDeclaration() #void:
@ -3010,7 +3023,9 @@ void ModuleDeclaration():
[LOOKAHEAD({isKeyword("open")}) <IDENTIFIER> {jjtThis.setOpen(true);}] [LOOKAHEAD({isKeyword("open")}) <IDENTIFIER> {jjtThis.setOpen(true);}]
LOOKAHEAD({isKeyword("module")}) <IDENTIFIER> LOOKAHEAD({isKeyword("module")}) <IDENTIFIER>
ModuleName() ModuleName()
"{" (ModuleDirective())* "}" "{" { tokenContexts.push(TokenContext.BLOCK); }
(ModuleDirective())*
"}" { tokenContexts.pop(); }
} }
void ModuleDirective() #void: void ModuleDirective() #void:

View File

@ -29,7 +29,7 @@ public final class SyntacticJavaTokenizerFactory {
public static TokenManager<JavaccToken> createTokenizer(CharStream cs) { public static TokenManager<JavaccToken> createTokenizer(CharStream cs) {
final List<JavaccToken> tokenList = new ArrayList<>(); final List<JavaccToken> tokenList = new ArrayList<>();
JavaParserImplTokenManager tokenManager = new JavaParserImplTokenManager(cs) { JavaParserImplTokenManager tokenManager = new JavaParserImplTokenManager(null, cs) {
@Override @Override
public JavaccToken getNextToken() { public JavaccToken getNextToken() {
JavaccToken token = super.getNextToken(); JavaccToken token = super.getNextToken();
@ -40,6 +40,7 @@ public final class SyntacticJavaTokenizerFactory {
LanguageVersion latestVersion = JavaLanguageModule.getInstance().getLatestVersion(); LanguageVersion latestVersion = JavaLanguageModule.getInstance().getLatestVersion();
JavaParserImpl parser = new JavaParserImpl(tokenManager); JavaParserImpl parser = new JavaParserImpl(tokenManager);
tokenManager.parser = parser;
parser.setJdkVersion(JavaLanguageProperties.getInternalJdkVersion(latestVersion)); parser.setJdkVersion(JavaLanguageProperties.getInternalJdkVersion(latestVersion));
parser.setPreview(JavaLanguageProperties.isPreviewEnabled(latestVersion)); parser.setPreview(JavaLanguageProperties.isPreviewEnabled(latestVersion));