Fix false positive for literal text in if conditions (#285)

* Fix false positive for literal text in `if` conditions

Use token.value (parsed string without YAML quotes) instead of token.source
(raw YAML text) for expression parsing in single-line strings. This fixes a
false positive where `if: "${{ expr }}"` incorrectly triggered the
"literal text in condition" error because the outer quotes were treated as
literal text.

Follow-up to PR #216
Related issue: https://github.com/github/vscode-github-actions/issues/542

* Move issue reference to comment
This commit is contained in:
eric sciple
2026-01-05 08:33:10 -06:00
committed by GitHub
parent 1cfe9f9f86
commit 1a42526360
3 changed files with 115 additions and 65 deletions
@@ -451,7 +451,13 @@ class TemplateReader {
}
const allowedContext = definitionInfo.allowedContext;
const raw = token.source || token.value;
const isSingleLine = token.range === undefined || token.range.start.line === token.range.end.line;
// For single-line strings, use token.value (without YAML quotes) for expression detection,
// because token.source includes quote characters that would be incorrectly detected as literal text.
// For multi-line block scalars, use token.source directly because it makes position calculation easier
// (no quote characters to handle, and token.source preserves the original line/column structure in YAML).
const raw = isSingleLine ? token.value : token.source ?? token.value;
let startExpression: number = raw.indexOf(OPEN_EXPRESSION);
if (startExpression < 0) {
@@ -496,14 +502,17 @@ class TemplateReader {
);
let tr = token.range!;
if (tr.start.line === tr.end.line) {
// If it's a single line expression, adjust the range to only cover the sub-expression
if (isSingleLine) {
// Single-line: Adjust the range to only cover the sub-expression.
// Calculate offset to account for YAML quote characters.
// For example, `"${{ expr }}"` has source with quotes, value without.
const offset = (token.source ?? raw).indexOf(OPEN_EXPRESSION) - raw.indexOf(OPEN_EXPRESSION);
tr = {
start: {line: tr.start.line, column: tr.start.column + startExpression},
end: {line: tr.end.line, column: tr.start.column + endExpression + 1}
start: {line: tr.start.line, column: tr.start.column + startExpression + offset},
end: {line: tr.end.line, column: tr.start.column + endExpression + 1 + offset}
};
} else {
// Adjust the range to only cover the expression for multi-line strings
// Multi-line: Adjust the range to only cover the expression
const startRaw = raw.substring(0, startExpression);
const adjustedStartLine = startRaw.split("\n").length;
const beginningOfLine = startRaw.lastIndexOf("\n");