Class StringExpressionClassifier
StringConcatRewriter (concat → backtick rewrite)
and the MCP StringLiteralExtractor (single-literal extraction to i18n).
Single source of truth for "find the smallest expression whose token range matches a selection" + "is this expression a single string literal vs a `+`-style concatenation". Both editors care about exactly the same classification step; before this extraction each carried its own copy.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordResult offindEnclosingTextMethodDeclaration(ParseTree, int, int): the resolved text-type and method names ready to feed straight intoek9_edit_localized_textastextTypeName/methodName. -
Method Summary
Modifier and TypeMethodDescriptionstatic EK9Parser.StringLitContextExtract thestringLitparse-tree node from an expression that is a single string literal (double-quoted or backtick).static EK9Parser.ExpressionContextfindEnclosingConcatExpression(org.antlr.v4.runtime.tree.ParseTree root, int line, int col) Walk a parse tree looking for the smallestEK9Parser.ExpressionContextthat BOTH (a) contains the cursor position and (b) is a binary+concat expression.static EK9Parser.ExpressionContextfindEnclosingStringLiteralExpression(org.antlr.v4.runtime.tree.ParseTree root, int line, int col) Walk a parse tree looking for the smallestEK9Parser.ExpressionContextthat BOTH (a) contains the cursor position and (b) is a single string literal (double-quoted or backtick interpolation).findEnclosingTextMethodDeclaration(org.antlr.v4.runtime.tree.ParseTree root, int line, int col) Walk a parse tree looking for the smallestEK9Parser.TextBodyDeclarationContextthat contains the cursor — i.e.static EK9Parser.ExpressionContextfindExpressionAtCursor(org.antlr.v4.runtime.tree.ParseTree root, int line, int col) Walk a parse tree looking for the smallestEK9Parser.ExpressionContextwhose token range CONTAINS the cursor position (line, col).static EK9Parser.ExpressionContextfindSmallestEnclosingExpression(org.antlr.v4.runtime.tree.ParseTree root, int startLine, int startCol, int endLine, int endCol) Walk a parse tree looking for the smallestEK9Parser.ExpressionContextwhose source token range exactly matches the selection.static booleanTrue when the expression's outer operator is binary+with two operand expressions.static booleanTrue when the expression resolves to a single string-literal primary — double-quoted or backtick interpolation.static int[]Token-range bounds of an expression as 1-based (line, col) coordinates.
-
Method Details
-
findSmallestEnclosingExpression
public static EK9Parser.ExpressionContext findSmallestEnclosingExpression(org.antlr.v4.runtime.tree.ParseTree root, int startLine, int startCol, int endLine, int endCol) Walk a parse tree looking for the smallestEK9Parser.ExpressionContextwhose source token range exactly matches the selection. Match is start-token == (startLine, startCol-1) and stop-token-end == (endLine, endCol-1) — ANTLR columns are 0-based.Returns
nullwhen no expression node spans precisely the selection (typical when the caller's range covers part of a token, crosses statement boundaries, or selects whitespace). -
isAddExpression
True when the expression's outer operator is binary+with two operand expressions. Used by both editors as the "this is a concat chain" gate. -
isSingleStringLiteral
True when the expression resolves to a single string-literal primary — double-quoted or backtick interpolation. Idempotency check for the rewriter; primary admission gate for the extractor. -
extractStringLit
Extract thestringLitparse-tree node from an expression that is a single string literal (double-quoted or backtick). Returnsnullwhen the expression is not a literal. -
findExpressionAtCursor
public static EK9Parser.ExpressionContext findExpressionAtCursor(org.antlr.v4.runtime.tree.ParseTree root, int line, int col) Walk a parse tree looking for the smallestEK9Parser.ExpressionContextwhose token range CONTAINS the cursor position (line, col). 1-based columns. MirrorsfindSmallestEnclosingExpression(ParseTree, int, int, int, int)but for point-containment rather than exact-range matching — the IDE right-click flow needs to find "what expression is the cursor inside" without an explicit selection.Returns
nullwhen no expression node contains the position (cursor on whitespace, in a comment, in indentation, etc). -
findEnclosingConcatExpression
public static EK9Parser.ExpressionContext findEnclosingConcatExpression(org.antlr.v4.runtime.tree.ParseTree root, int line, int col) Walk a parse tree looking for the smallestEK9Parser.ExpressionContextthat BOTH (a) contains the cursor position and (b) is a binary+concat expression. Used by the IDE's right-click "Rewrite to Backtick Interpolation" trigger — the user clicks anywhere inside the concat (including on an operand) and we want to rewrite the enclosing concat, not the operand sub-expression.Returns
nullwhen no concat expression spans the cursor position. -
findEnclosingStringLiteralExpression
public static EK9Parser.ExpressionContext findEnclosingStringLiteralExpression(org.antlr.v4.runtime.tree.ParseTree root, int line, int col) Walk a parse tree looking for the smallestEK9Parser.ExpressionContextthat BOTH (a) contains the cursor position and (b) is a single string literal (double-quoted or backtick interpolation). Used by the IDE's right-click "Extract to Localized Text…" trigger — the user clicks anywhere inside the literal and we want to extract the literal itself.Excludes concat operands — a literal that's part of a `+`-chain routes the user through the rewrite-first flow instead. Specifically: when the cursor is on a literal that's a direct child of a concat ExpressionContext, that concat case is NOT returned by this method (the literal IS returned as the smallest single-literal match, but the IDE-side menu builder gates by also checking that no enclosing concat exists — see EditorContextMenuBuilder).
Returns
nullwhen no single-string-literal expression spans the cursor position. -
tokenRange
Token-range bounds of an expression as 1-based (line, col) coordinates. Output shape mirrors what MCP-tool selection parameters expect:[startLine, startCol, endLine, endCol], inclusive on both ends. Returnsnullif the expression has missing token data. -
findEnclosingTextMethodDeclaration
public static StringExpressionClassifier.TextMethodTarget findEnclosingTextMethodDeclaration(org.antlr.v4.runtime.tree.ParseTree root, int line, int col) Walk a parse tree looking for the smallestEK9Parser.TextBodyDeclarationContextthat contains the cursor — i.e. the cursor is on/inside a text method definition. Returns aStringExpressionClassifier.TextMethodTargetrecord carrying the resolvedtextTypeName(from the enclosingEK9Parser.TextDeclarationContext) andmethodName(from the body declaration's identifier).Used by the IDE's right-click "Remove Text Method…" trigger in an i18n file: cursor inside a
mainWelcome()block surfaces the action with both names resolved, so the MCP dispatch is one-step (no user typing required).Returns
nullwhen no text body declaration contains the cursor position, or when the enclosing text-type identifier can't be resolved.
-