From 5f69f3a2f4a3fe06b8c6852d85917ded1dfb5796 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Fri, 10 Jan 2025 10:28:54 -0700 Subject: [PATCH 1/3] Changed code that computes unescaped literal string type to convert CRLF to LF within multi-line triple-quoted strings so the behavior is consistent with runtime. This addresses #9681. --- packages/pyright-internal/src/parser/stringTokenUtils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/pyright-internal/src/parser/stringTokenUtils.ts b/packages/pyright-internal/src/parser/stringTokenUtils.ts index c53dda0dd96b..3cbbc783e07e 100644 --- a/packages/pyright-internal/src/parser/stringTokenUtils.ts +++ b/packages/pyright-internal/src/parser/stringTokenUtils.ts @@ -305,7 +305,6 @@ export function getUnescapedString(stringToken: StringToken | FStringMiddleToken } else if (curChar === Char.LineFeed || curChar === Char.CarriageReturn) { // Skip over the escaped new line (either one or two characters). if (curChar === Char.CarriageReturn && getEscapedCharacter(1) === Char.LineFeed) { - appendOutputChar(curChar); strOffset++; curChar = getEscapedCharacter(); } From d53ff01bc6a7f23c2c6d69f42f28f74c2655f094 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Fri, 10 Jan 2025 11:21:57 -0700 Subject: [PATCH 2/3] Improved error reporting in test harness. --- .../pyright-internal/src/tests/testUtils.ts | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/packages/pyright-internal/src/tests/testUtils.ts b/packages/pyright-internal/src/tests/testUtils.ts index e68630c00976..ad5d0436695c 100644 --- a/packages/pyright-internal/src/tests/testUtils.ts +++ b/packages/pyright-internal/src/tests/testUtils.ts @@ -166,22 +166,6 @@ export function getAnalysisResults( }); } -export function printDiagnostics(fileResults: FileAnalysisResult) { - if (fileResults.errors.length > 0) { - console.error(`Errors in ${fileResults.fileUri}:`); - for (const diag of fileResults.errors) { - console.error(` ${diag.message}`); - } - } - - if (fileResults.warnings.length > 0) { - console.error(`Warnings in ${fileResults.fileUri}:`); - for (const diag of fileResults.warnings) { - console.error(` ${diag.message}`); - } - } -} - export function validateResults( results: FileAnalysisResult[], errorCount: number, @@ -192,22 +176,48 @@ export function validateResults( deprecated?: number ) { assert.strictEqual(results.length, 1); - assert.strictEqual(results[0].errors.length, errorCount); - assert.strictEqual(results[0].warnings.length, warningCount); + + if (results[0].errors.length !== errorCount) { + logDiagnostics(results[0].errors); + assert.fail(`Expected ${errorCount} errors, got ${results[0].errors.length}`); + } + + if (results[0].warnings.length !== warningCount) { + logDiagnostics(results[0].warnings); + assert.fail(`Expected ${warningCount} warnings, got ${results[0].warnings.length}`); + } if (infoCount !== undefined) { - assert.strictEqual(results[0].infos.length, infoCount); + if (results[0].infos.length !== infoCount) { + logDiagnostics(results[0].infos); + assert.fail(`Expected ${infoCount} infos, got ${results[0].infos.length}`); + } } if (unusedCode !== undefined) { - assert.strictEqual(results[0].unusedCodes.length, unusedCode); + if (results[0].unusedCodes.length !== unusedCode) { + logDiagnostics(results[0].unusedCodes); + assert.fail(`Expected ${unusedCode} unused, got ${results[0].unusedCodes.length}`); + } } if (unreachableCode !== undefined) { - assert.strictEqual(results[0].unreachableCodes.length, unreachableCode); + if (results[0].unreachableCodes.length !== unreachableCode) { + logDiagnostics(results[0].unreachableCodes); + assert.fail(`Expected ${unreachableCode} unreachable, got ${results[0].unreachableCodes.length}`); + } } if (deprecated !== undefined) { - assert.strictEqual(results[0].deprecateds.length, deprecated); + if (results[0].deprecateds.length !== deprecated) { + logDiagnostics(results[0].deprecateds); + assert.fail(`Expected ${deprecated} deprecated, got ${results[0].deprecateds.length}`); + } + } +} + +function logDiagnostics(diags: Diagnostic[]) { + for (const diag of diags) { + console.error(diag.message); } } From 198092394eefd9b052b5220f3ff73c90e9f1b090 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Fri, 10 Jan 2025 11:46:48 -0700 Subject: [PATCH 3/3] Fixed regression on Windows --- packages/pyright-internal/src/parser/parser.ts | 5 ++++- packages/pyright-internal/src/parser/stringTokenUtils.ts | 5 ++++- packages/pyright-internal/src/tests/testUtils.ts | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/pyright-internal/src/parser/parser.ts b/packages/pyright-internal/src/parser/parser.ts index 218fb66cd594..03bf4a9bba66 100644 --- a/packages/pyright-internal/src/parser/parser.ts +++ b/packages/pyright-internal/src/parser/parser.ts @@ -5034,7 +5034,10 @@ export class Parser { } } else { const stringToken = stringNode.d.strings[0].d.token; - const stringValue = StringTokenUtils.getUnescapedString(stringNode.d.strings[0].d.token); + const stringValue = StringTokenUtils.getUnescapedString( + stringNode.d.strings[0].d.token, + /* elideCrlf */ false + ); const unescapedString = stringValue.value; const tokenOffset = stringToken.start; const prefixLength = stringToken.prefixLength + stringToken.quoteMarkLength; diff --git a/packages/pyright-internal/src/parser/stringTokenUtils.ts b/packages/pyright-internal/src/parser/stringTokenUtils.ts index 3cbbc783e07e..975d5c5bcfbf 100644 --- a/packages/pyright-internal/src/parser/stringTokenUtils.ts +++ b/packages/pyright-internal/src/parser/stringTokenUtils.ts @@ -51,7 +51,7 @@ function completeUnescapedString(incomplete: IncompleteUnescapedString, original }; } -export function getUnescapedString(stringToken: StringToken | FStringMiddleToken): UnescapedString { +export function getUnescapedString(stringToken: StringToken | FStringMiddleToken, elideCrlf = true): UnescapedString { const escapedString = stringToken.escapedValue; const isRaw = (stringToken.flags & StringTokenFlags.Raw) !== 0; @@ -305,6 +305,9 @@ export function getUnescapedString(stringToken: StringToken | FStringMiddleToken } else if (curChar === Char.LineFeed || curChar === Char.CarriageReturn) { // Skip over the escaped new line (either one or two characters). if (curChar === Char.CarriageReturn && getEscapedCharacter(1) === Char.LineFeed) { + if (!elideCrlf) { + appendOutputChar(curChar); + } strOffset++; curChar = getEscapedCharacter(); } diff --git a/packages/pyright-internal/src/tests/testUtils.ts b/packages/pyright-internal/src/tests/testUtils.ts index ad5d0436695c..e816f4470dc1 100644 --- a/packages/pyright-internal/src/tests/testUtils.ts +++ b/packages/pyright-internal/src/tests/testUtils.ts @@ -218,6 +218,6 @@ export function validateResults( function logDiagnostics(diags: Diagnostic[]) { for (const diag of diags) { - console.error(diag.message); + console.error(` [${diag.range.start.line + 1}:${diag.range.start.character + 1}] ${diag.message}`); } }