0
# Text Processing and Validation
1
2
Text processing utilities for source code analysis including line range calculation, identifier validation, comment extraction, position-based operations, and various text validation functions for TypeScript constructs.
3
4
## Capabilities
5
6
### Line Range Analysis
7
8
Utilities for analyzing line structure and line breaks in source files.
9
10
```typescript { .api }
11
/**
12
* Get line ranges for all lines in a source file
13
* @param sourceFile - Source file to analyze
14
* @returns Array of line ranges with position and content length information
15
*/
16
function getLineRanges(sourceFile: ts.SourceFile): LineRange[];
17
18
/**
19
* Get the line break style used in a source file
20
* @param sourceFile - Source file to analyze
21
* @returns Line break string (e.g., '\n', '\r\n', '\r')
22
*/
23
function getLineBreakStyle(sourceFile: ts.SourceFile): string;
24
25
/**
26
* Check if two positions are on the same line
27
* @param sourceFile - Source file containing the positions
28
* @param pos1 - First position
29
* @param pos2 - Second position
30
* @returns true if both positions are on the same line
31
*/
32
function isSameLine(sourceFile: ts.SourceFile, pos1: number, pos2: number): boolean;
33
34
/**
35
* Line range interface with content length information
36
*/
37
interface LineRange extends ts.TextRange {
38
/** Length of actual content on the line (excluding line break) */
39
contentLength: number;
40
}
41
```
42
43
### Identifier and Name Validation
44
45
Utilities for validating TypeScript identifiers and property names.
46
47
```typescript { .api }
48
/**
49
* Check if text is a valid TypeScript identifier
50
* @param text - Text to validate
51
* @param languageVersion - TypeScript language version (optional)
52
* @returns true if text is valid identifier
53
*/
54
function isValidIdentifier(text: string, languageVersion?: ts.ScriptTarget): boolean;
55
56
/**
57
* Check if text can be used as property access (obj.prop)
58
* @param text - Text to validate
59
* @param languageVersion - TypeScript language version (optional)
60
* @returns true if text is valid for property access
61
*/
62
function isValidPropertyAccess(text: string, languageVersion?: ts.ScriptTarget): boolean;
63
64
/**
65
* Check if text is a valid property name
66
* @param text - Text to validate
67
* @param languageVersion - TypeScript language version (optional)
68
* @returns true if text is valid property name
69
*/
70
function isValidPropertyName(text: string, languageVersion?: ts.ScriptTarget): boolean;
71
72
/**
73
* Check if text is a valid numeric literal
74
* @param text - Text to validate
75
* @param languageVersion - TypeScript language version (optional)
76
* @returns true if text is valid numeric literal
77
*/
78
function isValidNumericLiteral(text: string, languageVersion?: ts.ScriptTarget): boolean;
79
80
/**
81
* Check if text is a valid JSX identifier
82
* @param text - Text to validate
83
* @param languageVersion - TypeScript language version (optional)
84
* @returns true if text is valid JSX identifier
85
*/
86
function isValidJsxIdentifier(text: string, languageVersion?: ts.ScriptTarget): boolean;
87
```
88
89
### Property Name Analysis
90
91
Utilities for working with property names and numeric properties.
92
93
```typescript { .api }
94
/**
95
* Extract property name from a property name node
96
* @param propertyName - Property name node
97
* @returns String representation of property name or undefined if not extractable
98
*/
99
function getPropertyName(propertyName: ts.PropertyName): string | undefined;
100
101
/**
102
* Check if property name is numeric
103
* @param name - Property name to check
104
* @returns true if name represents a numeric property
105
*/
106
function isNumericPropertyName(name: string | ts.__String): boolean;
107
```
108
109
### Well-Known Symbol Analysis
110
111
Utilities for analyzing well-known symbol property access.
112
113
```typescript { .api }
114
/**
115
* Check if expression is a well-known symbol literal (Symbol.iterator, etc.)
116
* @param node - Expression to check
117
* @returns true if expression is well-known symbol access
118
*/
119
function isWellKnownSymbolLiterally(node: ts.Expression): node is WellKnownSymbolLiteral;
120
121
/**
122
* Get property name information for well-known symbol
123
* @param node - Well-known symbol literal node
124
* @returns Property name information
125
* @deprecated Use getLateBoundPropertyNames instead
126
*/
127
function getPropertyNameOfWellKnownSymbol(node: WellKnownSymbolLiteral): PropertyName;
128
129
/**
130
* Interface for well-known symbol literal expressions
131
*/
132
interface WellKnownSymbolLiteral extends ts.PropertyAccessExpression {
133
expression: ts.Identifier & {text: 'Symbol', escapedText: 'symbol'};
134
}
135
136
/**
137
* Property name information
138
*/
139
interface PropertyName {
140
displayName: string;
141
symbolName: ts.__String;
142
}
143
```
144
145
### Late-Bound Property Analysis
146
147
Utilities for analyzing dynamically computed property names.
148
149
```typescript { .api }
150
/**
151
* Analyze late-bound property names from an expression
152
* @param node - Expression to analyze
153
* @param checker - Type checker instance
154
* @returns Late-bound property names information
155
*/
156
function getLateBoundPropertyNames(node: ts.Expression, checker: ts.TypeChecker): LateBoundPropertyNames;
157
158
/**
159
* Get late-bound property names from a property name node
160
* @param node - Property name node
161
* @param checker - Type checker instance
162
* @returns Late-bound property names information
163
*/
164
function getLateBoundPropertyNamesOfPropertyName(node: ts.PropertyName, checker: ts.TypeChecker): LateBoundPropertyNames;
165
166
/**
167
* Get single late-bound property name if deterministic
168
* @param node - Property name node
169
* @param checker - Type checker instance
170
* @returns Single property name if deterministic, undefined otherwise
171
*/
172
function getSingleLateBoundPropertyNameOfPropertyName(node: ts.PropertyName, checker: ts.TypeChecker): PropertyName | undefined;
173
174
/**
175
* Late-bound property names result
176
*/
177
interface LateBoundPropertyNames {
178
/** Whether all property names are known at compile time */
179
known: boolean;
180
/** Array of resolved property names */
181
names: PropertyName[];
182
}
183
```
184
185
### Expression Analysis
186
187
Utilities for analyzing expressions and their side effects.
188
189
```typescript { .api }
190
/**
191
* Check if expression has side effects
192
* @param node - Expression to analyze
193
* @param options - Side effect analysis options
194
* @returns true if expression may have side effects
195
*/
196
function hasSideEffects(node: ts.Expression, options?: SideEffectOptions): boolean;
197
198
/**
199
* Check if expression value is used (not discarded)
200
* @param node - Expression to check
201
* @returns true if expression value is used
202
*/
203
function isExpressionValueUsed(node: ts.Expression): boolean;
204
205
/**
206
* Get access kind for a node (read, write, delete)
207
* @param node - Node to analyze
208
* @returns Access kind flags
209
*/
210
function getAccessKind(node: ts.Node): AccessKind;
211
212
/**
213
* Check if expression is a reassignment target
214
* @param node - Expression to check
215
* @returns true if expression is being reassigned
216
*/
217
function isReassignmentTarget(node: ts.Expression): boolean;
218
219
/**
220
* Side effect analysis options
221
*/
222
enum SideEffectOptions {
223
None = 0,
224
TaggedTemplate = 1,
225
Constructor = 2,
226
JsxElement = 4
227
}
228
229
/**
230
* Access kind enumeration
231
*/
232
enum AccessKind {
233
None = 0,
234
Read = 1,
235
Write = 2,
236
Delete = 4,
237
ReadWrite = Read | Write,
238
Modification = Write | Delete
239
}
240
```
241
242
### Const Assertion Analysis
243
244
Utilities for analyzing const assertions and readonly contexts.
245
246
```typescript { .api }
247
/**
248
* Check if assertion expression is a const assertion
249
* @param node - Assertion expression to check
250
* @returns true if assertion is 'as const'
251
*/
252
function isConstAssertion(node: ts.AssertionExpression): boolean;
253
254
/**
255
* Check if expression is in const context
256
* @param node - Expression to check
257
* @returns true if expression is in const assertion context
258
*/
259
function isInConstContext(node: ts.Expression): boolean;
260
261
/**
262
* Check if call expression is readonly assignment declaration
263
* @param node - Call expression to check
264
* @param checker - Type checker instance
265
* @returns true if call creates readonly assignment
266
*/
267
function isReadonlyAssignmentDeclaration(node: ts.CallExpression, checker: ts.TypeChecker): boolean;
268
269
/**
270
* Check if call expression is bindable Object.defineProperty call
271
* @param node - Call expression to check
272
* @returns true if call is bindable defineProperty
273
*/
274
function isBindableObjectDefinePropertyCall(node: ts.CallExpression): boolean;
275
```
276
277
### Utility Functions
278
279
Miscellaneous text processing and utility functions.
280
281
```typescript { .api }
282
/**
283
* Remove parentheses from expression
284
* @param node - Expression that may be parenthesized
285
* @returns Unwrapped expression
286
*/
287
function unwrapParentheses(node: ts.Expression): ts.Expression;
288
289
/**
290
* Format pseudo big int value as string
291
* @param v - Pseudo big int value
292
* @returns Formatted string representation
293
*/
294
function formatPseudoBigInt(v: ts.PseudoBigInt): string;
295
296
/**
297
* Check if switch statement has exhaustive case clauses
298
* @param node - Switch statement to check
299
* @param checker - Type checker instance
300
* @returns true if all cases are covered
301
*/
302
function hasExhaustiveCaseClauses(node: ts.SwitchStatement, checker: ts.TypeChecker): boolean;
303
304
/**
305
* Get base class expression from class-like declaration
306
* @param node - Class-like declaration
307
* @returns Base class expression if present
308
*/
309
function getBaseOfClassLikeExpression(node: ts.ClassLikeDeclaration): ts.ExpressionWithTypeArguments | undefined;
310
```
311
312
### Directive Analysis
313
314
Utilities for analyzing TypeScript compiler directives.
315
316
```typescript { .api }
317
/**
318
* Get TypeScript check directive from source text
319
* @param source - Source text to analyze
320
* @returns Check directive if found
321
*/
322
function getTsCheckDirective(source: string): ts.CheckJsDirective | undefined;
323
324
/**
325
* Get check JS directive from source text (deprecated)
326
* @param source - Source text to analyze
327
* @returns Check directive if found
328
* @deprecated Use getTsCheckDirective instead
329
*/
330
function getCheckJsDirective(source: string): ts.CheckJsDirective | undefined;
331
```
332
333
**Usage Examples:**
334
335
```typescript
336
import * as ts from "typescript";
337
import {
338
getLineRanges,
339
isValidIdentifier,
340
getPropertyName,
341
hasSideEffects,
342
isConstAssertion,
343
unwrapParentheses,
344
SideEffectOptions,
345
AccessKind
346
} from "tsutils/util";
347
348
// Line analysis example
349
function analyzeSourceLines(sourceFile: ts.SourceFile) {
350
const lines = getLineRanges(sourceFile);
351
const lineBreakStyle = getLineBreakStyle(sourceFile);
352
353
console.log(`File has ${lines.length} lines`);
354
console.log(`Line break style: ${JSON.stringify(lineBreakStyle)}`);
355
356
lines.forEach((line, index) => {
357
console.log(`Line ${index + 1}: ${line.contentLength} characters`);
358
});
359
}
360
361
// Identifier validation example
362
function validateIdentifiers(identifiers: string[]) {
363
identifiers.forEach(id => {
364
if (isValidIdentifier(id)) {
365
console.log(`"${id}" is a valid identifier`);
366
} else {
367
console.log(`"${id}" is not a valid identifier`);
368
}
369
370
if (isValidPropertyAccess(id)) {
371
console.log(`"${id}" can be used in property access`);
372
}
373
});
374
}
375
376
// Property name analysis
377
function analyzePropertyAccess(node: ts.PropertyAccessExpression) {
378
const propertyName = getPropertyName(node.name);
379
if (propertyName) {
380
console.log(`Property name: ${propertyName}`);
381
382
if (isNumericPropertyName(propertyName)) {
383
console.log("Property name is numeric");
384
}
385
}
386
}
387
388
// Side effect analysis
389
function analyzeSideEffects(expression: ts.Expression) {
390
const hasEffects = hasSideEffects(expression, SideEffectOptions.None);
391
const hasEffectsWithConstructors = hasSideEffects(expression, SideEffectOptions.Constructor);
392
393
console.log(`Expression has side effects: ${hasEffects}`);
394
console.log(`With constructor calls: ${hasEffectsWithConstructors}`);
395
396
const isUsed = isExpressionValueUsed(expression);
397
console.log(`Expression value is used: ${isUsed}`);
398
}
399
400
// Const assertion analysis
401
function analyzeConstAssertions(node: ts.Node) {
402
if (ts.isAsExpression(node) || ts.isTypeAssertion(node)) {
403
if (isConstAssertion(node)) {
404
console.log("Found const assertion");
405
}
406
}
407
408
if (ts.isExpression(node) && isInConstContext(node)) {
409
console.log("Expression is in const context");
410
}
411
}
412
413
// Expression unwrapping
414
function analyzeExpression(expr: ts.Expression) {
415
const unwrapped = unwrapParentheses(expr);
416
417
if (unwrapped !== expr) {
418
console.log("Expression was parenthesized");
419
}
420
421
console.log(`Unwrapped expression: ${ts.SyntaxKind[unwrapped.kind]}`);
422
}
423
424
// Position-based analysis
425
function checkPositionInLine(sourceFile: ts.SourceFile, pos1: number, pos2: number) {
426
if (isSameLine(sourceFile, pos1, pos2)) {
427
console.log("Positions are on the same line");
428
} else {
429
console.log("Positions are on different lines");
430
}
431
}
432
```