diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle.ts index 78ddd1e99316..eb58a7f9d5b9 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-lifecycle.ts @@ -15,7 +15,7 @@ import ts from 'typescript'; import { createPropertyAccess } from '../utils/ast-helpers'; -import { addTodoComment } from '../utils/comment-helpers'; +import { addCommentedNodeText, addTodoComment } from '../utils/comment-helpers'; import { RefactorContext } from '../utils/refactor-context'; const FOCUSED_SKIPPED_RENAMES = new Map([ @@ -77,7 +77,6 @@ export function transformPending( ) { hasPending = true; const replacement = ts.factory.createEmptyStatement(); - const originalText = bodyNode.getFullText().trim(); reporter.reportTransformation( sourceFile, @@ -87,12 +86,7 @@ export function transformPending( const category = 'pending'; reporter.recordTodo(category, sourceFile, bodyNode); addTodoComment(replacement, category); - ts.addSyntheticLeadingComment( - replacement, - ts.SyntaxKind.SingleLineCommentTrivia, - ` ${originalText}`, - true, - ); + addCommentedNodeText(replacement, bodyNode); return replacement; } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher.ts index c1e669b144ef..1e0a87dc80f2 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-matcher.ts @@ -21,7 +21,7 @@ import { createPropertyAccess, } from '../utils/ast-helpers'; import { getJasmineMethodName, isJasmineCallExpression } from '../utils/ast-validation'; -import { addTodoComment } from '../utils/comment-helpers'; +import { addCommentedNodeText, addTodoComment } from '../utils/comment-helpers'; import { RefactorContext } from '../utils/refactor-context'; const SUGAR_MATCHER_CHANGES = new Map([ @@ -607,18 +607,12 @@ export function transformExpectNothing( // The statement is `expect().nothing()`, which can be removed. const replacement = ts.factory.createEmptyStatement(); - const originalText = node.getFullText().trim(); reporter.reportTransformation(sourceFile, node, 'Removed `expect().nothing()` statement.'); const category = 'expect-nothing'; reporter.recordTodo(category, sourceFile, node); addTodoComment(replacement, category); - ts.addSyntheticLeadingComment( - replacement, - ts.SyntaxKind.SingleLineCommentTrivia, - ` ${originalText}`, - true, - ); + addCommentedNodeText(replacement, node); return replacement; } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts index 6832e36b9273..f71353cc9783 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/transformers/jasmine-misc.ts @@ -16,7 +16,7 @@ import ts from 'typescript'; import { addVitestValueImport } from '../utils/ast-helpers'; import { getJasmineMethodName, isJasmineCallExpression } from '../utils/ast-validation'; -import { addTodoComment } from '../utils/comment-helpers'; +import { addCommentedNodeText, addTodoComment } from '../utils/comment-helpers'; import { RefactorContext } from '../utils/refactor-context'; import { createViCallExpression } from '../utils/refactor-helpers'; import { TodoCategory } from '../utils/todo-notes'; @@ -143,7 +143,6 @@ export function transformJasmineMembers(node: ts.Node, refactorCtx: RefactorCont case 'MAX_PRETTY_PRINT_DEPTH': case 'MAX_PRETTY_PRINT_CHARS': { const replacement = ts.factory.createEmptyStatement(); - const originalText = node.getFullText().trim(); reporter.reportTransformation( sourceFile, @@ -153,12 +152,7 @@ export function transformJasmineMembers(node: ts.Node, refactorCtx: RefactorCont const category = 'unsupported-jasmine-member'; reporter.recordTodo(category, sourceFile, node); addTodoComment(replacement, category, { name: memberName }); - ts.addSyntheticLeadingComment( - replacement, - ts.SyntaxKind.SingleLineCommentTrivia, - ` ${originalText}`, - true, - ); + addCommentedNodeText(replacement, node); return replacement; } diff --git a/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers.ts b/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers.ts index 2ece945e2951..02a9255deb3a 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers.ts @@ -70,3 +70,23 @@ export function addTodoComment( true, ); } + +/** + * Safely comments out the full text of a node line-by-line and attaches + * it to a target node. This prevents multi-line statements from breaking + * syntax when converted to single-line comments. + * @param targetNode The node to which the comments will be added. + * @param nodeToComment The original node whose text will be commented out. + */ +export function addCommentedNodeText(targetNode: ts.Node, nodeToComment: ts.Node): void { + const originalText = nodeToComment.getFullText().trim(); + const lines = originalText.split('\n'); + for (const line of lines) { + ts.addSyntheticLeadingComment( + targetNode, + ts.SyntaxKind.SingleLineCommentTrivia, + ` ${line.trim()}`, + true, + ); + } +} diff --git a/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers_spec.ts b/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers_spec.ts index ddfb1b8b7ad1..4f44b2664368 100644 --- a/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers_spec.ts +++ b/packages/schematics/angular/refactor/jasmine-vitest/utils/comment-helpers_spec.ts @@ -7,7 +7,7 @@ */ import ts from 'typescript'; -import { addTodoComment } from './comment-helpers'; +import { addCommentedNodeText, addTodoComment } from './comment-helpers'; describe('addTodoComment', () => { function createTestHarness(sourceText: string) { @@ -65,4 +65,19 @@ describe('addTodoComment', () => { expect(result.trim().startsWith('// TODO')).toBe(true); expect(result).toContain('const mySpy = jasmine.createSpy()'); }); + + describe('addCommentedNodeText', () => { + it('should comment out a multiline node line-by-line', () => { + const sourceText = `expect()\n .nothing();`; + const sourceFile = ts.createSourceFile('test.ts', sourceText, ts.ScriptTarget.Latest, true); + const statement = sourceFile.statements[0]; + const replacement = ts.factory.createEmptyStatement(); + const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); + + addCommentedNodeText(replacement, statement); + + const result = printer.printNode(ts.EmitHint.Unspecified, replacement, sourceFile); + expect(result).toContain('// expect()\n// .nothing();'); + }); + }); });