diff --git a/config/checker-framework-suppressions/checker-nullness-optional-interning-suppressions.xml b/config/checker-framework-suppressions/checker-nullness-optional-interning-suppressions.xml index 200241965a2..1565d4fdd3c 100644 --- a/config/checker-framework-suppressions/checker-nullness-optional-interning-suppressions.xml +++ b/config/checker-framework-suppressions/checker-nullness-optional-interning-suppressions.xml @@ -5358,6 +5358,13 @@ + + src/main/java/com/puppycrawl/tools/checkstyle/grammar/CompositeLexerContextCache.java + dereference.of.nullable + dereference of possibly-null reference currentContext + if (currentContext.getCurlyBraceDepth() == 0) { + + src/main/java/com/puppycrawl/tools/checkstyle/gui/BaseCellEditor.java return diff --git a/config/import-control.xml b/config/import-control.xml index acf6a101c24..4a4b61362bf 100644 --- a/config/import-control.xml +++ b/config/import-control.xml @@ -307,6 +307,12 @@ + + + + + + diff --git a/config/linkcheck-suppressions.txt b/config/linkcheck-suppressions.txt index 8030a07f70c..00921c6958b 100644 --- a/config/linkcheck-suppressions.txt +++ b/config/linkcheck-suppressions.txt @@ -1341,3 +1341,7 @@ com/puppycrawl/tools/checkstyle/xpath/iterators/ReverseListIterator.html#%3Cinit%3E(java.util.Collection): doesn't exist. com/puppycrawl/tools/checkstyle/utils/UnmodifiableCollectionUtil.html#copyOfArray(T%5B%5D,int): doesn't exist. com/puppycrawl/tools/checkstyle/site/XdocsTemplateSink.CustomPrintWriter.html#%3Cinit%3E(java.io.Writer): doesn't exist. +com/puppycrawl/tools/checkstyle/grammar/CompositeLexerContextCache.html#%3Cinit%3E(org.antlr.v4.runtime.Lexer): doesn't exist. +com/puppycrawl/tools/checkstyle/grammar/CompositeLexerContextCache.TemplateContext.html#%3Cinit%3E(int,int): doesn't exist. +#%3Cinit%3E(org.antlr.v4.runtime.Lexer): doesn't exist. +#%3Cinit%3E(int,int): doesn't exist. diff --git a/pom.xml b/pom.xml index 3ab7a4eca56..9e80811b499 100644 --- a/pom.xml +++ b/pom.xml @@ -4362,6 +4362,7 @@ com.puppycrawl.tools.checkstyle.Checker* com.puppycrawl.tools.checkstyle.ThreadModeSettings* com.puppycrawl.tools.checkstyle.grammar.CrAwareLexerSimulator* + com.puppycrawl.tools.checkstyle.grammar.CompositeLexerContextCache* com.puppycrawl.tools.checkstyle.AuditEventFormatter* com.puppycrawl.tools.checkstyle.XdocsPropertyType* @@ -4393,6 +4394,8 @@ com.puppycrawl.tools.checkstyle.ThreadModeSettingsTest com.puppycrawl.tools.checkstyle.grammar.CrAwareLexerSimulatorTest com.puppycrawl.tools.checkstyle.grammar.javadoc.JavadocParseTreeTest + + com.puppycrawl.tools.checkstyle.grammar.java21.Java21AstRegressionTest com.puppycrawl.tools.checkstyle.filefilters.BeforeExecutionExclusionFileFilterTest com.puppycrawl.tools.checkstyle.checks.TranslationCheckTest diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/JavaAstVisitor.java b/src/main/java/com/puppycrawl/tools/checkstyle/JavaAstVisitor.java index 958134a6dd2..69e216c31bd 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/JavaAstVisitor.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/JavaAstVisitor.java @@ -1808,164 +1808,84 @@ private static DetailAstImpl buildSimpleStringTemplateArgument( @Override public DetailAstImpl visitStringTemplate(JavaLanguageParser.StringTemplateContext ctx) { - final DetailAstImpl begin = buildStringTemplateBeginning(ctx); - - final Optional startExpression = Optional.ofNullable(ctx.expr()) - .map(this::visit); - - if (startExpression.isPresent()) { - final DetailAstImpl imaginaryExpr = - createImaginary(TokenTypes.EMBEDDED_EXPRESSION); - imaginaryExpr.addChild(startExpression.orElseThrow()); - begin.addChild(imaginaryExpr); - } + final DetailAstImpl stringTemplateBegin = visit(ctx.stringTemplateBegin()); + + Optional.ofNullable(ctx.expr()) + .map(this::visit) + .ifPresent(expression -> { + final DetailAstImpl imaginaryExpression = + createImaginary(TokenTypes.EMBEDDED_EXPRESSION); + imaginaryExpression.addChild(expression); + stringTemplateBegin.addChild(imaginaryExpression); + }); ctx.stringTemplateMiddle().stream() .map(this::buildStringTemplateMiddle) - .collect(Collectors.toUnmodifiableList()) - .forEach(begin::addChild); - - final DetailAstImpl end = buildStringTemplateEnd(ctx); - begin.addChild(end); - return begin; - } + .forEach(stringTemplateBegin::addChild); - /** - * Builds the beginning of a string template AST. - * - * @param ctx the StringTemplateContext to build AST from - * @return string template AST - */ - private static DetailAstImpl buildStringTemplateBeginning( - JavaLanguageParser.StringTemplateContext ctx) { - - // token looks like '"' StringFragment '\{' - final TerminalNode context = ctx.STRING_TEMPLATE_BEGIN(); - final Token token = context.getSymbol(); - final String tokenText = context.getText(); - final int tokenStartIndex = token.getCharPositionInLine(); - final int tokenLineNumber = token.getLine(); - final int tokenTextLength = tokenText.length(); - - final DetailAstImpl stringTemplateBegin = createImaginary( - TokenTypes.STRING_TEMPLATE_BEGIN, QUOTE, - tokenLineNumber, tokenStartIndex - ); - - // remove delimiters '"' and '\{' - final String stringFragment = tokenText.substring( - QUOTE.length(), tokenTextLength - EMBEDDED_EXPRESSION_BEGIN.length()); - - final DetailAstImpl stringTemplateContent = createImaginary( - TokenTypes.STRING_TEMPLATE_CONTENT, stringFragment, - tokenLineNumber, tokenStartIndex + QUOTE.length() - ); - stringTemplateBegin.addChild(stringTemplateContent); - - final DetailAstImpl embeddedBegin = createImaginary( - TokenTypes.EMBEDDED_EXPRESSION_BEGIN, EMBEDDED_EXPRESSION_BEGIN, - tokenLineNumber, - tokenStartIndex + tokenTextLength - EMBEDDED_EXPRESSION_BEGIN.length() - ); - stringTemplateBegin.addChild(embeddedBegin); + final DetailAstImpl stringTemplateEnd = visit(ctx.stringTemplateEnd()); + stringTemplateBegin.addChild(stringTemplateEnd); return stringTemplateBegin; } /** - * Builds the middle of a string template AST. + * Builds a string template middle AST. * - * @param middleContext the StringTemplateMiddleContext to build AST from + * @param ctx the StringTemplateMiddleContext to build AST from * @return DetailAstImpl of string template middle */ private DetailAstImpl buildStringTemplateMiddle( - JavaLanguageParser.StringTemplateMiddleContext middleContext) { - - // token looks like '}' StringFragment '\{' - final TerminalNode context = middleContext.STRING_TEMPLATE_MID(); - final Token token = context.getSymbol(); - final int tokenStartIndex = token.getCharPositionInLine(); - final int tokenLineNumber = token.getLine(); - final String tokenText = context.getText(); - final int tokenTextLength = tokenText.length(); - - final DetailAstImpl embeddedExpressionEnd = createImaginary( - TokenTypes.EMBEDDED_EXPRESSION_END, EMBEDDED_EXPRESSION_END, - tokenLineNumber, tokenStartIndex - ); - - // remove delimiters '}' and '\\' '{' - final String stringFragment = tokenText.substring( - EMBEDDED_EXPRESSION_END.length(), - tokenTextLength - EMBEDDED_EXPRESSION_BEGIN.length() - ); - - final DetailAstImpl content = createImaginary( - TokenTypes.STRING_TEMPLATE_CONTENT, stringFragment, - tokenLineNumber, tokenStartIndex + EMBEDDED_EXPRESSION_END.length() - ); - embeddedExpressionEnd.addNextSibling(content); - - final DetailAstImpl embeddedBegin = createImaginary( - TokenTypes.EMBEDDED_EXPRESSION_BEGIN, EMBEDDED_EXPRESSION_BEGIN, - tokenLineNumber, - tokenStartIndex + tokenTextLength - EMBEDDED_EXPRESSION_BEGIN.length() - ); - content.addNextSibling(embeddedBegin); - - final Optional embeddedExpression = Optional.ofNullable(middleContext.expr()) - .map(this::visit); - - if (embeddedExpression.isPresent()) { - final DetailAstImpl imaginaryExpr = - createImaginary(TokenTypes.EMBEDDED_EXPRESSION); - imaginaryExpr.addChild(embeddedExpression.orElseThrow()); - embeddedExpressionEnd.addNextSibling(imaginaryExpr); - } + JavaLanguageParser.StringTemplateMiddleContext ctx) { + final DetailAstImpl stringTemplateMiddle = + visit(ctx.stringTemplateMid()); + + Optional.ofNullable(ctx.expr()) + .map(this::visit) + .ifPresent(expression -> { + final DetailAstImpl imaginaryExpression = + createImaginary(TokenTypes.EMBEDDED_EXPRESSION); + imaginaryExpression.addChild(expression); + addLastSibling(stringTemplateMiddle, imaginaryExpression); + }); + + return stringTemplateMiddle; + } + + @Override + public DetailAstImpl visitStringTemplateBegin( + JavaLanguageParser.StringTemplateBeginContext ctx) { + final DetailAstImpl stringTemplateBegin = + create(ctx.STRING_TEMPLATE_BEGIN()); + final Optional stringTemplateContent = + Optional.ofNullable(ctx.STRING_TEMPLATE_CONTENT()) + .map(this::create); + stringTemplateContent.ifPresent(stringTemplateBegin::addChild); + final DetailAstImpl embeddedExpressionBegin = create(ctx.EMBEDDED_EXPRESSION_BEGIN()); + stringTemplateBegin.addChild(embeddedExpressionBegin); + return stringTemplateBegin; + } + @Override + public DetailAstImpl visitStringTemplateMid(JavaLanguageParser.StringTemplateMidContext ctx) { + final DetailAstImpl embeddedExpressionEnd = create(ctx.EMBEDDED_EXPRESSION_END()); + final Optional stringTemplateContent = + Optional.ofNullable(ctx.STRING_TEMPLATE_CONTENT()) + .map(this::create); + stringTemplateContent.ifPresent(self -> addLastSibling(embeddedExpressionEnd, self)); + final DetailAstImpl embeddedExpressionBegin = create(ctx.EMBEDDED_EXPRESSION_BEGIN()); + addLastSibling(embeddedExpressionEnd, embeddedExpressionBegin); return embeddedExpressionEnd; } - /** - * Builds the end of a string template AST. - * - * @param ctx the StringTemplateContext to build AST from - * @return DetailAstImpl of string template end - */ - private static DetailAstImpl buildStringTemplateEnd( - JavaLanguageParser.StringTemplateContext ctx) { - - // token looks like '}' StringFragment '"' - final TerminalNode context = ctx.STRING_TEMPLATE_END(); - final Token token = context.getSymbol(); - final String tokenText = context.getText(); - final int tokenStartIndex = token.getCharPositionInLine(); - final int tokenLineNumber = token.getLine(); - final int tokenTextLength = tokenText.length(); - - final DetailAstImpl embeddedExpressionEnd = createImaginary( - TokenTypes.EMBEDDED_EXPRESSION_END, EMBEDDED_EXPRESSION_END, - tokenLineNumber, tokenStartIndex - ); - - // remove delimiters '}' and '"' - final String stringFragment = tokenText.substring( - EMBEDDED_EXPRESSION_END.length(), - tokenTextLength - QUOTE.length() - ); - - final DetailAstImpl endContent = createImaginary( - TokenTypes.STRING_TEMPLATE_CONTENT, stringFragment, - tokenLineNumber, - tokenStartIndex + EMBEDDED_EXPRESSION_END.length() - ); - embeddedExpressionEnd.addNextSibling(endContent); - - final DetailAstImpl stringTemplateEnd = createImaginary( - TokenTypes.STRING_TEMPLATE_END, QUOTE, - tokenLineNumber, - tokenStartIndex + tokenTextLength - QUOTE.length() - ); - endContent.addNextSibling(stringTemplateEnd); + @Override + public DetailAstImpl visitStringTemplateEnd(JavaLanguageParser.StringTemplateEndContext ctx) { + final DetailAstImpl embeddedExpressionEnd = create(ctx.EMBEDDED_EXPRESSION_END()); + final Optional stringTemplateContent = + Optional.ofNullable(ctx.STRING_TEMPLATE_CONTENT()) + .map(this::create); + stringTemplateContent.ifPresent(self -> addLastSibling(embeddedExpressionEnd, self)); + final DetailAstImpl stringTemplateEnd = create(ctx.STRING_TEMPLATE_END()); + addLastSibling(embeddedExpressionEnd, stringTemplateEnd); return embeddedExpressionEnd; } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/JavaParser.java b/src/main/java/com/puppycrawl/tools/checkstyle/JavaParser.java index 518db6a0c13..e56c35d8c9e 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/JavaParser.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/JavaParser.java @@ -40,6 +40,7 @@ import com.puppycrawl.tools.checkstyle.api.FileContents; import com.puppycrawl.tools.checkstyle.api.FileText; import com.puppycrawl.tools.checkstyle.api.TokenTypes; +import com.puppycrawl.tools.checkstyle.grammar.CompositeLexerContextCache; import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageLexer; import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageParser; import com.puppycrawl.tools.checkstyle.utils.ParserUtil; @@ -84,7 +85,9 @@ public static DetailAST parse(FileContents contents) final String fullText = contents.getText().getFullText().toString(); final CharStream codePointCharStream = CharStreams.fromString(fullText); final JavaLanguageLexer lexer = new JavaLanguageLexer(codePointCharStream, true); + final CompositeLexerContextCache contextCache = new CompositeLexerContextCache(lexer); lexer.setCommentListener(contents); + lexer.setContextCache(contextCache); final CommonTokenStream tokenStream = new CommonTokenStream(lexer); final JavaLanguageParser parser = diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/grammar/CompositeLexerContextCache.java b/src/main/java/com/puppycrawl/tools/checkstyle/grammar/CompositeLexerContextCache.java new file mode 100644 index 00000000000..e9657cc44e3 --- /dev/null +++ b/src/main/java/com/puppycrawl/tools/checkstyle/grammar/CompositeLexerContextCache.java @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code and other text files for adherence to a set of rules. +// Copyright (C) 2001-2024 the original author or authors. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +/////////////////////////////////////////////////////////////////////////////////////////////// + +package com.puppycrawl.tools.checkstyle.grammar; + +import java.util.ArrayDeque; +import java.util.Deque; + +import org.antlr.v4.runtime.Lexer; + +import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageLexer; + +/** + * This class is used to keep track of the lexer context to help us determine + * when to switch lexer modes. + */ +public final class CompositeLexerContextCache { + + /** Stack for tracking string template contexts. */ + private final Deque templateContextStack; + + /** The lexer to use. */ + private final Lexer lexer; + + /** + * Creates a new CompositeLexerContextCache instance. + * + * @param lexer the lexer to use + */ + public CompositeLexerContextCache(Lexer lexer) { + templateContextStack = new ArrayDeque<>(); + this.lexer = lexer; + } + + /** + * Update the left curly brace context if we are in a string template. + */ + public void updateLeftCurlyBraceContext() { + if (isInTemplateContext()) { + final TemplateContext currentContext = templateContextStack.pop(); + final TemplateContext newContext = new TemplateContext(currentContext.getMode(), + currentContext.getCurlyBraceDepth() + 1); + templateContextStack.push(newContext); + } + } + + /** + * Update the right curly brace context if we are in a string template. + */ + public void updateRightCurlyBraceContext() { + if (isInTemplateContext()) { + final TemplateContext currentContext = templateContextStack.peek(); + if (currentContext.getCurlyBraceDepth() == 0) { + // This right curly brace is the start delimiter + // of a template middle or end. We consume + // the right curly brace to be used as the first token + // in the appropriate lexer mode rule, enter + // the corresponding lexer mode, and keep consuming + // the rest of the template middle or end. + lexer.setType(JavaLanguageLexer.EMBEDDED_EXPRESSION_END); + lexer.pushMode(currentContext.getMode()); + } + else { + // We've consumed a right curly brace within an embedded expression. + final TemplateContext newContext = new TemplateContext(currentContext.getMode(), + currentContext.getCurlyBraceDepth() - 1); + templateContextStack.push(newContext); + } + } + } + + /** + * Enter a string template context. + * + * @param mode the lexer mode to enter + */ + public void enterTemplateContext(int mode) { + final TemplateContext newContext = new TemplateContext(mode, 0); + templateContextStack.push(newContext); + lexer.pushMode(mode); + } + + /** + * Exit a string template context. + */ + public void exitTemplateContext() { + templateContextStack.pop(); + lexer.popMode(); + } + + /** + * Check if we are in a string template context. + * + * @return true if we are in a string template context + */ + private boolean isInTemplateContext() { + return !templateContextStack.isEmpty(); + } + + /** + * A class to represent the context of a string template. + */ + private static final class TemplateContext { + + /** The lexer mode of this context. */ + private final int mode; + + /** The depth of this context. */ + private final int curlyBraceDepth; + + /** + * Creates a new TemplateContext instance. + * + * @param mode the lexer mode of this context + * @param curlyBraceDepth the depth of this context + */ + private TemplateContext(int mode, int curlyBraceDepth) { + this.mode = mode; + this.curlyBraceDepth = curlyBraceDepth; + } + + /** + * Get the lexer mode of this context. + * + * @return current lexer mode + */ + private int getMode() { + return mode; + } + + /** + * Current depth of this context. + * + * @return current depth + */ + private int getCurlyBraceDepth() { + return curlyBraceDepth; + } + } + +} diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java/JavaLanguageLexer.g4 b/src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java/JavaLanguageLexer.g4 index ed456f61ae6..4e9e0a0d5ab 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java/JavaLanguageLexer.g4 +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java/JavaLanguageLexer.g4 @@ -121,6 +121,7 @@ tokens { @header { import com.puppycrawl.tools.checkstyle.grammar.CommentListener; +import com.puppycrawl.tools.checkstyle.grammar.CompositeLexerContextCache; import com.puppycrawl.tools.checkstyle.grammar.CrAwareLexerSimulator; } @@ -139,23 +140,27 @@ import com.puppycrawl.tools.checkstyle.grammar.CrAwareLexerSimulator; } private CommentListener commentListener = null; + private CompositeLexerContextCache contextCache = null; /** * Sets the CommentListener for the lexer. * * @param commentListener the commentListener to use in this lexer */ - public void setCommentListener(CommentListener commentListener){ + public void setCommentListener(CommentListener commentListener) { this.commentListener = commentListener; } + public void setContextCache(CompositeLexerContextCache contextCache) { + this.contextCache = contextCache; + } + /** Tracks the starting line of a block comment. */ int startLine = -1; /** Tracks the starting column of a block comment. */ int startCol = -1; - private int stringTemplateDepth = 0; } // Keywords and restricted identifiers @@ -249,9 +254,14 @@ LITERAL_FALSE: 'false'; CHAR_LITERAL: '\'' (EscapeSequence | ~['\\\r\n]) '\''; -fragment StringFragment: (EscapeSequence | ~["\\\r\n])*; +fragment StringFragment: (EscapeSequence | ~["\\\r\n]); -STRING_LITERAL: '"' StringFragment '"'; +STRING_LITERAL: '"' StringFragment* '"'; + +STRING_TEMPLATE_BEGIN: '"' + { _input.LA(1) != '"' }? + { contextCache.enterTemplateContext(StringTemplate); } + ; TEXT_BLOCK_LITERAL_BEGIN: '"' '"' '"' -> pushMode(TextBlock); @@ -261,8 +271,12 @@ LITERAL_NULL: 'null'; LPAREN: '('; RPAREN: ')'; -LCURLY: '{'; -RCURLY: '}'; +LCURLY: '{' + { contextCache.updateLeftCurlyBraceContext(); } + ; +RCURLY: '}' + { contextCache.updateRightCurlyBraceContext(); } + ; LBRACK: '['; RBRACK: ']'; SEMI: ';'; @@ -321,18 +335,7 @@ AT: '@'; ELLIPSIS: '...'; // String templates -STRING_TEMPLATE_BEGIN: '"' StringFragment '\\' '{' - {stringTemplateDepth++;} - ; -STRING_TEMPLATE_MID: {stringTemplateDepth > 0}? - '}' StringFragment '\\' '{' - ; - -STRING_TEMPLATE_END: {stringTemplateDepth > 0}? - '}' StringFragment '"' - {stringTemplateDepth--;} - ; // Text block fragments @@ -464,3 +467,11 @@ mode TextBlock; TEXT_BLOCK_LITERAL_END : '"' '"' '"' -> popMode ; + +mode StringTemplate; + + STRING_TEMPLATE_CONTENT: StringFragment+; + + EMBEDDED_EXPRESSION_BEGIN: '\\' '{' -> pushMode(DEFAULT_MODE); + + STRING_TEMPLATE_END: '"' { contextCache.exitTemplateContext(); }; diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java/JavaLanguageParser.g4 b/src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java/JavaLanguageParser.g4 index 8e121bb82a3..9db56a2dea6 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java/JavaLanguageParser.g4 +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/grammar/java/JavaLanguageParser.g4 @@ -767,14 +767,34 @@ template : stringTemplate ; + stringTemplate - : STRING_TEMPLATE_BEGIN expr? stringTemplateMiddle* STRING_TEMPLATE_END + : stringTemplateBegin expr? stringTemplateMiddle* stringTemplateEnd ; stringTemplateMiddle - : STRING_TEMPLATE_MID expr? + : stringTemplateMid expr? + ; + +stringTemplateBegin + : STRING_TEMPLATE_BEGIN + STRING_TEMPLATE_CONTENT? + EMBEDDED_EXPRESSION_BEGIN + ; + +stringTemplateMid + : EMBEDDED_EXPRESSION_END + STRING_TEMPLATE_CONTENT? + EMBEDDED_EXPRESSION_BEGIN + ; + +stringTemplateEnd + : EMBEDDED_EXPRESSION_END + STRING_TEMPLATE_CONTENT? + STRING_TEMPLATE_END ; + classType : (classOrInterfaceType[false] DOT)? annotations[false] id typeArguments? ; diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/JavaAstVisitorTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/JavaAstVisitorTest.java index 14bced10e26..3caa27216f6 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/JavaAstVisitorTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/JavaAstVisitorTest.java @@ -40,11 +40,13 @@ import com.puppycrawl.tools.checkstyle.api.FileContents; import com.puppycrawl.tools.checkstyle.api.FileText; import com.puppycrawl.tools.checkstyle.api.TokenTypes; +import com.puppycrawl.tools.checkstyle.grammar.CompositeLexerContextCache; import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageLexer; import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageParser; import com.puppycrawl.tools.checkstyle.grammar.java.JavaLanguageParserBaseVisitor; import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil; +// -@cs[ClassDataAbstractionCoupling] No way to split up class usage. public class JavaAstVisitorTest extends AbstractModuleTestSupport { /** @@ -240,7 +242,9 @@ public void testNoStackOverflowOnDeepStringConcat() throws Exception { final String fullText = contents.getText().getFullText().toString(); final CharStream codePointCharStream = CharStreams.fromString(fullText); final JavaLanguageLexer lexer = new JavaLanguageLexer(codePointCharStream, true); + final CompositeLexerContextCache contextCache = new CompositeLexerContextCache(lexer); lexer.setCommentListener(contents); + lexer.setContextCache(contextCache); final CommonTokenStream tokenStream = new CommonTokenStream(lexer); final JavaLanguageParser parser = new JavaLanguageParser(tokenStream); diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/grammar/java21/Java21AstRegressionTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/grammar/java21/Java21AstRegressionTest.java index 89ba8c9361d..237a21e192a 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/grammar/java21/Java21AstRegressionTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/grammar/java21/Java21AstRegressionTest.java @@ -46,6 +46,15 @@ public void testBasicStringTemplate() throws Exception { "InputStringTemplateBasic.java")); } + @Test + public void testStringTemplateNested() throws Exception { + verifyAst( + getNonCompilablePath( + "ExpectedStringTemplateNested.txt"), + getNonCompilablePath( + "InputStringTemplateNested.java")); + } + /** * Test for tabs instead of spaces in the input file. * All node columns are -3 when compared to the above test. This is diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateBasic.txt b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateBasic.txt index 605e052c881..bda890d21a2 100644 --- a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateBasic.txt +++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateBasic.txt @@ -81,10 +81,8 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | `--DOT -> . [16:26] | | |--IDENT -> STR [16:23] | | `--STRING_TEMPLATE_BEGIN -> " [16:27] - | | |--STRING_TEMPLATE_CONTENT -> [16:28] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [16:28] | | |--EMBEDDED_EXPRESSION_END -> } [16:32] - | | |--STRING_TEMPLATE_CONTENT -> [16:33] | | `--STRING_TEMPLATE_END -> " [16:33] | `--SEMI -> ; [16:34] |--VARIABLE_DEF -> VARIABLE_DEF [19:4] @@ -115,7 +113,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | `--DOT -> . [22:24] | | |--IDENT -> STR [22:21] | | `--STRING_TEMPLATE_BEGIN -> " [22:26] - | | |--STRING_TEMPLATE_CONTENT -> [22:27] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [22:27] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [22:31] | | | `--METHOD_CALL -> ( [22:31] @@ -130,7 +127,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | `--RPAREN -> ) [22:37] | | | `--RPAREN -> ) [22:38] | | |--EMBEDDED_EXPRESSION_END -> } [22:40] - | | |--STRING_TEMPLATE_CONTENT -> [22:41] | | `--STRING_TEMPLATE_END -> " [22:41] | `--SEMI -> ; [22:42] |--VARIABLE_DEF -> VARIABLE_DEF [25:4] @@ -144,22 +140,18 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--DOT -> . [25:24] | | | |--IDENT -> STR [25:21] | | | `--STRING_TEMPLATE_BEGIN -> " [25:26] - | | | |--STRING_TEMPLATE_CONTENT -> [25:27] | | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [25:27] | | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [25:30] | | | | `--IDENT -> x [25:30] | | | |--EMBEDDED_EXPRESSION_END -> } [25:32] - | | | |--STRING_TEMPLATE_CONTENT -> [25:33] | | | `--STRING_TEMPLATE_END -> " [25:33] | | `--DOT -> . [25:41] | | |--IDENT -> STR [25:38] | | `--STRING_TEMPLATE_BEGIN -> " [25:43] - | | |--STRING_TEMPLATE_CONTENT -> [25:44] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [25:44] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [25:47] | | | `--IDENT -> y [25:47] | | |--EMBEDDED_EXPRESSION_END -> } [25:49] - | | |--STRING_TEMPLATE_CONTENT -> [25:50] | | `--STRING_TEMPLATE_END -> " [25:50] | `--SEMI -> ; [25:51] |--VARIABLE_DEF -> VARIABLE_DEF [28:4] @@ -173,7 +165,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--DOT -> . [28:24] | | | |--IDENT -> STR [28:21] | | | `--STRING_TEMPLATE_BEGIN -> " [28:26] - | | | |--STRING_TEMPLATE_CONTENT -> [28:27] | | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [28:27] | | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [28:31] | | | | `--METHOD_CALL -> ( [28:31] @@ -188,12 +179,10 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | | `--RPAREN -> ) [28:37] | | | | `--RPAREN -> ) [28:38] | | | |--EMBEDDED_EXPRESSION_END -> } [28:40] - | | | |--STRING_TEMPLATE_CONTENT -> [28:41] | | | `--STRING_TEMPLATE_END -> " [28:41] | | `--DOT -> . [28:49] | | |--IDENT -> STR [28:46] | | `--STRING_TEMPLATE_BEGIN -> " [28:51] - | | |--STRING_TEMPLATE_CONTENT -> [28:52] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [28:52] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [28:56] | | | `--METHOD_CALL -> ( [28:56] @@ -208,7 +197,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | `--RPAREN -> ) [28:62] | | | `--RPAREN -> ) [28:63] | | |--EMBEDDED_EXPRESSION_END -> } [28:65] - | | |--STRING_TEMPLATE_CONTENT -> [28:66] | | `--STRING_TEMPLATE_END -> " [28:66] | `--SEMI -> ; [28:67] |--VARIABLE_DEF -> VARIABLE_DEF [31:4] @@ -222,22 +210,18 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--DOT -> . [31:24] | | | |--IDENT -> STR [31:21] | | | `--STRING_TEMPLATE_BEGIN -> " [31:26] - | | | |--STRING_TEMPLATE_CONTENT -> [31:27] | | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [31:27] | | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [31:30] | | | | `--IDENT -> x [31:30] | | | |--EMBEDDED_EXPRESSION_END -> } [31:32] - | | | |--STRING_TEMPLATE_CONTENT -> [31:33] | | | `--STRING_TEMPLATE_END -> " [31:33] | | `--DOT -> . [31:41] | | |--IDENT -> STR [31:38] | | `--STRING_TEMPLATE_BEGIN -> " [31:43] - | | |--STRING_TEMPLATE_CONTENT -> [31:44] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [31:44] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [31:47] | | | `--IDENT -> y [31:47] | | |--EMBEDDED_EXPRESSION_END -> } [31:49] - | | |--STRING_TEMPLATE_CONTENT -> [31:50] | | `--STRING_TEMPLATE_END -> " [31:50] | `--SEMI -> ; [31:51] |--VARIABLE_DEF -> VARIABLE_DEF [34:4] @@ -250,14 +234,12 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | `--DOT -> . [34:24] | | |--IDENT -> STR [34:21] | | `--STRING_TEMPLATE_BEGIN -> " [34:26] - | | |--STRING_TEMPLATE_CONTENT -> [34:27] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [34:27] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [34:32] | | | `--PLUS -> + [34:32] | | | |--IDENT -> x [34:30] | | | `--IDENT -> y [34:34] | | |--EMBEDDED_EXPRESSION_END -> } [34:36] - | | |--STRING_TEMPLATE_CONTENT -> [34:37] | | `--STRING_TEMPLATE_END -> " [34:37] | `--SEMI -> ; [34:38] |--VARIABLE_DEF -> VARIABLE_DEF [37:4] @@ -377,6 +359,8 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | `--RPAREN -> ) [46:31] | | | `--RPAREN -> ) [46:32] | | |--EMBEDDED_EXPRESSION_END -> } [47:12] + | | |--STRING_TEMPLATE_CONTENT -> there [47:13] + | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [47:20] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [49:12] | | | `--PLUS -> + [49:12] | | | |--PLUS -> + [48:22] @@ -412,10 +396,7 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | |--EMBEDDED_EXPRESSION_END -> } [49:25] | | | |--STRING_TEMPLATE_CONTENT -> x [49:26] | | | `--STRING_TEMPLATE_END -> " [49:27] - | | |--STRING_TEMPLATE_CONTENT -> there [47:13] - | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [47:20] | | |--EMBEDDED_EXPRESSION_END -> } [50:12] - | | |--STRING_TEMPLATE_CONTENT -> [50:13] | | `--STRING_TEMPLATE_END -> " [50:13] | `--SEMI -> ; [50:14] |--VARIABLE_DEF -> VARIABLE_DEF [52:4] @@ -522,10 +503,8 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | `--NUM_INT -> 0 [62:17] | | | `--RPAREN -> ) [62:18] | | `--STRING_TEMPLATE_BEGIN -> " [62:20] - | | |--STRING_TEMPLATE_CONTENT -> [62:21] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [62:21] | | |--EMBEDDED_EXPRESSION_END -> } [62:25] - | | |--STRING_TEMPLATE_CONTENT -> [62:26] | | `--STRING_TEMPLATE_END -> " [62:26] | |--SEMI -> ; [62:27] | |--EXPR -> EXPR [63:19] @@ -563,15 +542,15 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:26] | | | `--IDENT -> x [64:26] | | |--EMBEDDED_EXPRESSION_END -> } [64:28] - | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:33] - | | | `--IDENT -> y [64:33] | | |--STRING_TEMPLATE_CONTENT -> . [64:29] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [64:30] + | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:33] + | | | `--IDENT -> y [64:33] | | |--EMBEDDED_EXPRESSION_END -> } [64:35] - | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:40] - | | | `--IDENT -> x [64:40] | | |--STRING_TEMPLATE_CONTENT -> . [64:36] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [64:37] + | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:40] + | | | `--IDENT -> x [64:40] | | |--EMBEDDED_EXPRESSION_END -> } [64:42] | | |--STRING_TEMPLATE_CONTENT -> . [64:43] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [64:44] @@ -579,7 +558,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--STRING_TEMPLATE_CONTENT -> . [64:47] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [64:48] | | |--EMBEDDED_EXPRESSION_END -> } [64:50] - | | |--STRING_TEMPLATE_CONTENT -> [64:51] | | `--STRING_TEMPLATE_END -> " [64:51] | |--SEMI -> ; [64:52] | `--RCURLY -> } [65:4] diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateBasicWithTabs.txt b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateBasicWithTabs.txt index b732010600f..ecbb0b3520b 100644 --- a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateBasicWithTabs.txt +++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateBasicWithTabs.txt @@ -81,10 +81,8 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | `--DOT -> . [16:23] | | |--IDENT -> STR [16:20] | | `--STRING_TEMPLATE_BEGIN -> " [16:24] - | | |--STRING_TEMPLATE_CONTENT -> [16:25] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [16:25] | | |--EMBEDDED_EXPRESSION_END -> } [16:29] - | | |--STRING_TEMPLATE_CONTENT -> [16:30] | | `--STRING_TEMPLATE_END -> " [16:30] | `--SEMI -> ; [16:31] |--VARIABLE_DEF -> VARIABLE_DEF [19:1] @@ -115,7 +113,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | `--DOT -> . [22:21] | | |--IDENT -> STR [22:18] | | `--STRING_TEMPLATE_BEGIN -> " [22:23] - | | |--STRING_TEMPLATE_CONTENT -> [22:24] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [22:24] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [22:28] | | | `--METHOD_CALL -> ( [22:28] @@ -130,7 +127,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | `--RPAREN -> ) [22:34] | | | `--RPAREN -> ) [22:35] | | |--EMBEDDED_EXPRESSION_END -> } [22:37] - | | |--STRING_TEMPLATE_CONTENT -> [22:38] | | `--STRING_TEMPLATE_END -> " [22:38] | `--SEMI -> ; [22:39] |--VARIABLE_DEF -> VARIABLE_DEF [25:1] @@ -144,22 +140,18 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--DOT -> . [25:21] | | | |--IDENT -> STR [25:18] | | | `--STRING_TEMPLATE_BEGIN -> " [25:23] - | | | |--STRING_TEMPLATE_CONTENT -> [25:24] | | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [25:24] | | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [25:27] | | | | `--IDENT -> x [25:27] | | | |--EMBEDDED_EXPRESSION_END -> } [25:29] - | | | |--STRING_TEMPLATE_CONTENT -> [25:30] | | | `--STRING_TEMPLATE_END -> " [25:30] | | `--DOT -> . [25:38] | | |--IDENT -> STR [25:35] | | `--STRING_TEMPLATE_BEGIN -> " [25:40] - | | |--STRING_TEMPLATE_CONTENT -> [25:41] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [25:41] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [25:44] | | | `--IDENT -> y [25:44] | | |--EMBEDDED_EXPRESSION_END -> } [25:46] - | | |--STRING_TEMPLATE_CONTENT -> [25:47] | | `--STRING_TEMPLATE_END -> " [25:47] | `--SEMI -> ; [25:48] |--VARIABLE_DEF -> VARIABLE_DEF [28:1] @@ -173,7 +165,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--DOT -> . [28:21] | | | |--IDENT -> STR [28:18] | | | `--STRING_TEMPLATE_BEGIN -> " [28:23] - | | | |--STRING_TEMPLATE_CONTENT -> [28:24] | | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [28:24] | | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [28:28] | | | | `--METHOD_CALL -> ( [28:28] @@ -188,12 +179,10 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | | `--RPAREN -> ) [28:34] | | | | `--RPAREN -> ) [28:35] | | | |--EMBEDDED_EXPRESSION_END -> } [28:37] - | | | |--STRING_TEMPLATE_CONTENT -> [28:38] | | | `--STRING_TEMPLATE_END -> " [28:38] | | `--DOT -> . [28:46] | | |--IDENT -> STR [28:43] | | `--STRING_TEMPLATE_BEGIN -> " [28:48] - | | |--STRING_TEMPLATE_CONTENT -> [28:49] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [28:49] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [28:53] | | | `--METHOD_CALL -> ( [28:53] @@ -208,7 +197,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | `--RPAREN -> ) [28:59] | | | `--RPAREN -> ) [28:60] | | |--EMBEDDED_EXPRESSION_END -> } [28:62] - | | |--STRING_TEMPLATE_CONTENT -> [28:63] | | `--STRING_TEMPLATE_END -> " [28:63] | `--SEMI -> ; [28:64] |--VARIABLE_DEF -> VARIABLE_DEF [31:1] @@ -222,22 +210,18 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--DOT -> . [31:21] | | | |--IDENT -> STR [31:18] | | | `--STRING_TEMPLATE_BEGIN -> " [31:23] - | | | |--STRING_TEMPLATE_CONTENT -> [31:24] | | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [31:24] | | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [31:27] | | | | `--IDENT -> x [31:27] | | | |--EMBEDDED_EXPRESSION_END -> } [31:29] - | | | |--STRING_TEMPLATE_CONTENT -> [31:30] | | | `--STRING_TEMPLATE_END -> " [31:30] | | `--DOT -> . [31:38] | | |--IDENT -> STR [31:35] | | `--STRING_TEMPLATE_BEGIN -> " [31:40] - | | |--STRING_TEMPLATE_CONTENT -> [31:41] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [31:41] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [31:44] | | | `--IDENT -> y [31:44] | | |--EMBEDDED_EXPRESSION_END -> } [31:46] - | | |--STRING_TEMPLATE_CONTENT -> [31:47] | | `--STRING_TEMPLATE_END -> " [31:47] | `--SEMI -> ; [31:48] |--VARIABLE_DEF -> VARIABLE_DEF [34:1] @@ -250,14 +234,12 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | `--DOT -> . [34:21] | | |--IDENT -> STR [34:18] | | `--STRING_TEMPLATE_BEGIN -> " [34:23] - | | |--STRING_TEMPLATE_CONTENT -> [34:24] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [34:24] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [34:29] | | | `--PLUS -> + [34:29] | | | |--IDENT -> x [34:27] | | | `--IDENT -> y [34:31] | | |--EMBEDDED_EXPRESSION_END -> } [34:33] - | | |--STRING_TEMPLATE_CONTENT -> [34:34] | | `--STRING_TEMPLATE_END -> " [34:34] | `--SEMI -> ; [34:35] |--VARIABLE_DEF -> VARIABLE_DEF [37:1] @@ -377,6 +359,8 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | `--RPAREN -> ) [46:22] | | | `--RPAREN -> ) [46:23] | | |--EMBEDDED_EXPRESSION_END -> } [47:3] + | | |--STRING_TEMPLATE_CONTENT -> there [47:4] + | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [47:11] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [49:3] | | | `--PLUS -> + [49:3] | | | |--PLUS -> + [48:13] @@ -412,10 +396,7 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | |--EMBEDDED_EXPRESSION_END -> } [49:16] | | | |--STRING_TEMPLATE_CONTENT -> x [49:17] | | | `--STRING_TEMPLATE_END -> " [49:18] - | | |--STRING_TEMPLATE_CONTENT -> there [47:4] - | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [47:11] | | |--EMBEDDED_EXPRESSION_END -> } [50:3] - | | |--STRING_TEMPLATE_CONTENT -> [50:4] | | `--STRING_TEMPLATE_END -> " [50:4] | `--SEMI -> ; [50:5] |--VARIABLE_DEF -> VARIABLE_DEF [52:1] @@ -522,10 +503,8 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | | | `--NUM_INT -> 0 [62:11] | | | `--RPAREN -> ) [62:12] | | `--STRING_TEMPLATE_BEGIN -> " [62:14] - | | |--STRING_TEMPLATE_CONTENT -> [62:15] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [62:15] | | |--EMBEDDED_EXPRESSION_END -> } [62:19] - | | |--STRING_TEMPLATE_CONTENT -> [62:20] | | `--STRING_TEMPLATE_END -> " [62:20] | |--SEMI -> ; [62:21] | |--EXPR -> EXPR [63:13] @@ -563,15 +542,15 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:20] | | | `--IDENT -> x [64:20] | | |--EMBEDDED_EXPRESSION_END -> } [64:22] - | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:27] - | | | `--IDENT -> y [64:27] | | |--STRING_TEMPLATE_CONTENT -> . [64:23] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [64:24] + | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:27] + | | | `--IDENT -> y [64:27] | | |--EMBEDDED_EXPRESSION_END -> } [64:29] - | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:34] - | | | `--IDENT -> x [64:34] | | |--STRING_TEMPLATE_CONTENT -> . [64:30] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [64:31] + | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [64:34] + | | | `--IDENT -> x [64:34] | | |--EMBEDDED_EXPRESSION_END -> } [64:36] | | |--STRING_TEMPLATE_CONTENT -> . [64:37] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [64:38] @@ -579,7 +558,6 @@ COMPILATION_UNIT -> COMPILATION_UNIT [2:0] | | |--STRING_TEMPLATE_CONTENT -> . [64:41] | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [64:42] | | |--EMBEDDED_EXPRESSION_END -> } [64:44] - | | |--STRING_TEMPLATE_CONTENT -> [64:45] | | `--STRING_TEMPLATE_END -> " [64:45] | |--SEMI -> ; [64:46] | `--RCURLY -> } [65:1] diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateNested.txt b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateNested.txt new file mode 100644 index 00000000000..d459f1e28a0 --- /dev/null +++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/ExpectedStringTemplateNested.txt @@ -0,0 +1,139 @@ +COMPILATION_UNIT -> COMPILATION_UNIT [2:0] +|--PACKAGE_DEF -> package [2:0] +| |--ANNOTATIONS -> ANNOTATIONS [2:47] +| |--DOT -> . [2:47] +| | |--DOT -> . [2:39] +| | | |--DOT -> . [2:28] +| | | | |--DOT -> . [2:22] +| | | | | |--DOT -> . [2:11] +| | | | | | |--IDENT -> com [2:8] +| | | | | | `--IDENT -> puppycrawl [2:12] +| | | | | `--IDENT -> tools [2:23] +| | | | `--IDENT -> checkstyle [2:29] +| | | `--IDENT -> grammar [2:40] +| | `--IDENT -> java21 [2:48] +| `--SEMI -> ; [2:54] +|--IMPORT -> import [4:0] +| |--DOT -> . [4:25] +| | |--DOT -> . [4:16] +| | | |--DOT -> . [4:11] +| | | | |--IDENT -> java [4:7] +| | | | `--IDENT -> util [4:12] +| | | `--IDENT -> function [4:17] +| | `--IDENT -> Supplier [4:26] +| `--SEMI -> ; [4:34] +`--CLASS_DEF -> CLASS_DEF [6:0] + |--MODIFIERS -> MODIFIERS [6:0] + | `--LITERAL_PUBLIC -> public [6:0] + |--LITERAL_CLASS -> class [6:7] + |--IDENT -> InputStringTemplateNested [6:13] + `--OBJBLOCK -> OBJBLOCK [6:39] + |--LCURLY -> { [6:39] + |--VARIABLE_DEF -> VARIABLE_DEF [7:4] + | |--MODIFIERS -> MODIFIERS [7:4] + | |--TYPE -> TYPE [7:4] + | | `--LITERAL_INT -> int [7:4] + | |--IDENT -> x [7:8] + | |--ASSIGN -> = [7:10] + | | `--EXPR -> EXPR [7:12] + | | `--NUM_INT -> 2 [7:12] + | `--SEMI -> ; [7:13] + |--VARIABLE_DEF -> VARIABLE_DEF [8:4] + | |--MODIFIERS -> MODIFIERS [8:4] + | | `--FINAL -> final [8:4] + | |--TYPE -> TYPE [8:10] + | | `--IDENT -> String [8:10] + | |--IDENT -> s [8:17] + | |--ASSIGN -> = [8:19] + | | `--EXPR -> EXPR [9:15] + | | `--DOT -> . [9:15] + | | |--IDENT -> STR [9:12] + | | `--STRING_TEMPLATE_BEGIN -> " [9:16] + | | |--STRING_TEMPLATE_CONTENT -> x [9:17] + | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [9:18] + | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [9:23] + | | | `--METHOD_CALL -> ( [9:23] + | | | |--IDENT -> sp [9:21] + | | | |--ELIST -> ELIST [9:27] + | | | | `--LAMBDA -> -> [9:27] + | | | | |--LPAREN -> ( [9:24] + | | | | |--PARAMETERS -> PARAMETERS [9:25] + | | | | |--RPAREN -> ) [9:25] + | | | | `--SLIST -> { [9:30] + | | | | |--LITERAL_RETURN -> return [10:16] + | | | | | |--EXPR -> EXPR [10:26] + | | | | | | `--DOT -> . [10:26] + | | | | | | |--IDENT -> STR [10:23] + | | | | | | `--STRING_TEMPLATE_BEGIN -> " [10:27] + | | | | | | |--STRING_TEMPLATE_CONTENT -> x [10:28] + | | | | | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [10:29] + | | | | | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [10:34] + | | | | | | | `--METHOD_CALL -> ( [10:34] + | | | | | | | |--IDENT -> sp [10:32] + | | | | | | | |--ELIST -> ELIST [10:38] + | | | | | | | | `--LAMBDA -> -> [10:38] + | | | | | | | | |--LPAREN -> ( [10:35] + | | | | | | | | |--PARAMETERS -> PARAMETERS [10:36] + | | | | | | | | |--RPAREN -> ) [10:36] + | | | | | | | | `--SLIST -> { [10:41] + | | | | | | | | |--LITERAL_RETURN -> return [11:20] + | | | | | | | | | |--EXPR -> EXPR [11:48] + | | | | | | | | | | `--PLUS -> + [11:48] + | | | | | | | | | | |--PLUS -> + [11:42] + | | | | | | | | | | | |--DOT -> . [11:30] + | | | | | | | | | | | | |--IDENT -> STR [11:27] + | | | | | | | | | | | | `--STRING_TEMPLATE_BEGIN -> " [11:31] + | | | | | | | | | | | | |--STRING_TEMPLATE_CONTENT -> x [11:32] + | | | | | | | | | | | | |--EMBEDDED_EXPRESSION_BEGIN -> \{ [11:33] + | | | | | | | | | | | | |--EMBEDDED_EXPRESSION -> EMBEDDED_EXPRESSION [11:36] + | | | | | | | | | | | | | `--IDENT -> x [11:36] + | | | | | | | | | | | | |--EMBEDDED_EXPRESSION_END -> } [11:38] + | | | | | | | | | | | | |--STRING_TEMPLATE_CONTENT -> x [11:39] + | | | | | | | | | | | | `--STRING_TEMPLATE_END -> " [11:40] + | | | | | | | | | | | `--STRING_LITERAL -> "{" [11:44] + | | | | | | | | | | `--STRING_LITERAL -> "}}}" [11:50] + | | | | | | | | | `--SEMI -> ; [11:55] + | | | | | | | | `--RCURLY -> } [12:16] + | | | | | | | `--RPAREN -> ) [12:17] + | | | | | | |--EMBEDDED_EXPRESSION_END -> } [12:19] + | | | | | | |--STRING_TEMPLATE_CONTENT -> x [12:20] + | | | | | | `--STRING_TEMPLATE_END -> " [12:21] + | | | | | `--SEMI -> ; [12:22] + | | | | `--RCURLY -> } [13:12] + | | | `--RPAREN -> ) [13:13] + | | |--EMBEDDED_EXPRESSION_END -> } [13:14] + | | |--STRING_TEMPLATE_CONTENT -> x [13:15] + | | `--STRING_TEMPLATE_END -> " [13:16] + | `--SEMI -> ; [13:17] + |--METHOD_DEF -> METHOD_DEF [15:4] + | |--MODIFIERS -> MODIFIERS [15:4] + | | |--LITERAL_PRIVATE -> private [15:4] + | | `--LITERAL_STATIC -> static [15:12] + | |--TYPE -> TYPE [15:19] + | | `--IDENT -> String [15:19] + | |--IDENT -> sp [15:26] + | |--LPAREN -> ( [15:28] + | |--PARAMETERS -> PARAMETERS [15:29] + | | `--PARAMETER_DEF -> PARAMETER_DEF [15:29] + | | |--MODIFIERS -> MODIFIERS [15:29] + | | |--TYPE -> TYPE [15:29] + | | | |--IDENT -> Supplier [15:29] + | | | `--TYPE_ARGUMENTS -> TYPE_ARGUMENTS [15:37] + | | | |--GENERIC_START -> < [15:37] + | | | |--TYPE_ARGUMENT -> TYPE_ARGUMENT [15:38] + | | | | `--IDENT -> String [15:38] + | | | `--GENERIC_END -> > [15:44] + | | `--IDENT -> y [15:46] + | |--RPAREN -> ) [15:47] + | `--SLIST -> { [15:49] + | |--LITERAL_RETURN -> return [16:8] + | | |--EXPR -> EXPR [16:20] + | | | `--METHOD_CALL -> ( [16:20] + | | | |--DOT -> . [16:16] + | | | | |--IDENT -> y [16:15] + | | | | `--IDENT -> get [16:17] + | | | |--ELIST -> ELIST [16:21] + | | | `--RPAREN -> ) [16:21] + | | `--SEMI -> ; [16:22] + | `--RCURLY -> } [17:4] + `--RCURLY -> } [18:0] diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/InputStringTemplateNested.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/InputStringTemplateNested.java new file mode 100644 index 00000000000..7a1bffb8e6d --- /dev/null +++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/grammar/java21/InputStringTemplateNested.java @@ -0,0 +1,18 @@ +//non-compiled with javac: Compilable with Java21 +package com.puppycrawl.tools.checkstyle.grammar.java21; + +import java.util.function.Supplier; + +public class InputStringTemplateNested { + int x = 2; + final String s = + STR."x\{ sp(() -> { + return STR."x\{ sp(() -> { + return STR."x\{ x }x" + "{" + "}}}"; + }) }x"; + })}x"; + + private static String sp(Supplier y) { + return y.get(); + } +}