Skip to content

Commit 5bb7050

Browse files
devversionpkozlowski-opensource
authored andcommitted
refactor(migrations): add common helpers for inserting TODOs (angular#57898)
Adds a common helper for inserting TODOs to Tsurge. PR Close angular#57898
1 parent 7ecfd89 commit 5bb7050

File tree

5 files changed

+68
-26
lines changed

5 files changed

+68
-26
lines changed

packages/core/schematics/ng-generate/inject-migration/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ ts_library(
1919
tsconfig = "//packages/core/schematics:tsconfig.json",
2020
deps = [
2121
"//packages/core/schematics/utils",
22+
"//packages/core/schematics/utils/tsurge",
2223
"@npm//@angular-devkit/schematics",
2324
"@npm//@types/node",
2425
"@npm//typescript",

packages/core/schematics/ng-generate/inject-migration/analysis.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -223,29 +223,6 @@ export function getSuperParameters(
223223
return usedParams;
224224
}
225225

226-
/**
227-
* Gets the indentation text of a node. Can be used to
228-
* output text with the same level of indentation.
229-
* @param node Node for which to get the indentation level.
230-
*/
231-
export function getNodeIndentation(node: ts.Node): string {
232-
const fullText = node.getFullText();
233-
const end = fullText.indexOf(node.getText());
234-
let result = '';
235-
236-
for (let i = end - 1; i > -1; i--) {
237-
// Note: LF line endings are `\n` while CRLF are `\r\n`. This logic should cover both, because
238-
// we start from the beginning of the node and go backwards so will always hit `\n` first.
239-
if (fullText[i] !== '\n') {
240-
result = fullText[i] + result;
241-
} else {
242-
break;
243-
}
244-
}
245-
246-
return result;
247-
}
248-
249226
/** Checks whether a parameter node declares a property on its class. */
250227
export function parameterDeclaresProperty(node: ts.ParameterDeclaration): boolean {
251228
return !!node.modifiers?.some(

packages/core/schematics/ng-generate/inject-migration/migration.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import ts from 'typescript';
1010
import {PendingChange, ChangeTracker} from '../../utils/change_tracker';
1111
import {
1212
analyzeFile,
13-
getNodeIndentation,
1413
getSuperParameters,
1514
getConstructorUnusedParameters,
1615
hasGenerics,
@@ -22,6 +21,7 @@ import {getAngularDecorators} from '../../utils/ng_decorators';
2221
import {getImportOfIdentifier} from '../../utils/typescript/imports';
2322
import {closestNode} from '../../utils/typescript/nodes';
2423
import {findUninitializedPropertiesToCombine} from './internal';
24+
import {getLeadingLineWhitespaceOfNode} from '../../utils/tsurge/helpers/ast/leading_space';
2525

2626
/**
2727
* Placeholder used to represent expressions inside the AST.
@@ -173,13 +173,13 @@ function migrateClass(
173173
const superParameters = superCall
174174
? getSuperParameters(constructor, superCall, localTypeChecker)
175175
: null;
176-
const memberIndentation = getNodeIndentation(node.members[0]);
176+
const memberIndentation = getLeadingLineWhitespaceOfNode(node.members[0]);
177177
const removedStatementCount = removedStatements?.size || 0;
178178
const innerReference =
179179
superCall ||
180180
constructor.body?.statements.find((statement) => !removedStatements?.has(statement)) ||
181181
constructor;
182-
const innerIndentation = getNodeIndentation(innerReference);
182+
const innerIndentation = getLeadingLineWhitespaceOfNode(innerReference);
183183
const propsToAdd: string[] = [];
184184
const prependToConstructor: string[] = [];
185185
const afterSuper: string[] = [];
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import ts from 'typescript';
10+
import {Replacement, TextUpdate} from '../../replacement';
11+
import {getLeadingLineWhitespaceOfNode} from './leading_space';
12+
import {ProgramInfo} from '../../program_info';
13+
import {projectFile} from '../../project_paths';
14+
15+
/**
16+
* Inserts a leading single-line TODO for the given node,
17+
* returning a replacement.
18+
*/
19+
export function insertPrecedingLine(
20+
node: ts.Node,
21+
info: ProgramInfo,
22+
todoText: string,
23+
): Replacement {
24+
const leadingSpace = getLeadingLineWhitespaceOfNode(node);
25+
return new Replacement(
26+
projectFile(node.getSourceFile(), info),
27+
new TextUpdate({
28+
position: node.getStart(),
29+
end: node.getStart(),
30+
toInsert: `${todoText}\n${leadingSpace}`,
31+
}),
32+
);
33+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import ts from 'typescript';
10+
11+
/**
12+
* Gets the leading line whitespace of a given node.
13+
*
14+
* Useful for inserting e.g. TODOs without breaking indentation.
15+
*/
16+
export function getLeadingLineWhitespaceOfNode(node: ts.Node): string {
17+
const fullText = node.getFullText().substring(0, node.getStart() - node.getFullStart());
18+
let result = '';
19+
20+
for (let i = fullText.length - 1; i > -1; i--) {
21+
// Note: LF line endings are `\n` while CRLF are `\r\n`. This logic should cover both, because
22+
// we start from the beginning of the node and go backwards so will always hit `\n` first.
23+
if (fullText[i] !== '\n') {
24+
result = fullText[i] + result;
25+
} else {
26+
break;
27+
}
28+
}
29+
30+
return result;
31+
}

0 commit comments

Comments
 (0)