Skip to content

Commit c11658e

Browse files
authored
perf: various optimization with ast walk (#2969)
1 parent 71676eb commit c11658e

File tree

4 files changed

+38
-32
lines changed

4 files changed

+38
-32
lines changed

.changeset/little-corners-open.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'typescript-svelte-plugin': patch
3+
'svelte-language-server': patch
4+
'svelte-check': patch
5+
---
6+
7+
perf: various optimization with ast walk

packages/language-server/src/plugins/typescript/features/SemanticTokensProvider.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ export class SemanticTokensProviderImpl implements SemanticTokensProvider {
131131

132132
const startOffset = document.offsetAt(startPosition);
133133
const endOffset = document.offsetAt(endPosition);
134+
const originalText = document.getText();
134135

135136
// Ensure components in the template get no semantic highlighting
136137
if (
@@ -139,9 +140,9 @@ export class SemanticTokensProviderImpl implements SemanticTokensProvider {
139140
classificationType === TokenType.parameter ||
140141
classificationType === TokenType.variable ||
141142
classificationType === TokenType.function) &&
142-
snapshot.svelteNodeAt(startOffset)?.type === 'InlineComponent' &&
143-
(document.getText().charCodeAt(startOffset - 1) === /* < */ 60 ||
144-
document.getText().charCodeAt(startOffset - 1) === /* / */ 47)
143+
(originalText.charCodeAt(startOffset - 1) === /* < */ 60 ||
144+
originalText.charCodeAt(startOffset - 1) === /* / */ 47) &&
145+
snapshot.svelteNodeAt(startOffset)?.type === 'InlineComponent'
145146
) {
146147
return;
147148
}

packages/language-server/src/plugins/typescript/features/utils.ts

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -189,23 +189,20 @@ export function findContainingNode<T extends ts.Node>(
189189
textSpan: ts.TextSpan,
190190
predicate: (node: ts.Node) => node is T
191191
): T | undefined {
192-
const children = node.getChildren();
193-
const end = textSpan.start + textSpan.length;
194-
195-
for (const child of children) {
196-
if (!(child.getStart() <= textSpan.start && child.getEnd() >= end)) {
197-
continue;
198-
}
199-
200-
if (predicate(child)) {
201-
return child;
202-
}
203-
204-
const foundInChildren = findContainingNode(child, textSpan, predicate);
205-
if (foundInChildren) {
206-
return foundInChildren;
192+
// TypeScript will re-parse part of the file in getChildren() to include syntax tokens.
193+
// But for the use cases of this function, we only need the actual nodes like Identifier.
194+
// the forEachChild name is a bit misleading too because it function more like find than forEach
195+
return node.forEachChild((child) => {
196+
if (child.getStart() <= textSpan.start && child.getEnd() >= textSpan.start) {
197+
if (predicate(child)) {
198+
return child;
199+
}
200+
const foundInChildren = findContainingNode(child, textSpan, predicate);
201+
if (foundInChildren) {
202+
return foundInChildren;
203+
}
207204
}
208-
}
205+
});
209206
}
210207

211208
export function findClosestContainingNode<T extends ts.Node>(
@@ -242,15 +239,15 @@ export function findNodeAtSpan<T extends ts.Node>(
242239

243240
const end = start + length;
244241

245-
for (const child of node.getChildren()) {
242+
return node.forEachChild((child) => {
246243
const childStart = child.getStart();
247244
if (end <= childStart) {
248245
return;
249246
}
250247

251248
const childEnd = child.getEnd();
252249
if (start >= childEnd) {
253-
continue;
250+
return;
254251
}
255252

256253
if (start === childStart && end === childEnd) {
@@ -266,7 +263,7 @@ export function findNodeAtSpan<T extends ts.Node>(
266263
if (foundInChildren) {
267264
return foundInChildren;
268265
}
269-
}
266+
});
270267
}
271268

272269
function isSomeAncestor(node: ts.Node, predicate: NodePredicate) {
@@ -349,9 +346,9 @@ export function gatherDescendants<T extends ts.Node>(
349346
if (predicate(node)) {
350347
dest.push(node);
351348
} else {
352-
for (const child of node.getChildren()) {
349+
node.forEachChild((child) => {
353350
gatherDescendants(child, predicate, dest);
354-
}
351+
});
355352
}
356353
return dest;
357354
}
@@ -416,6 +413,7 @@ export function getQuotePreference(
416413
: double;
417414
}
418415
export function findChildOfKind(node: ts.Node, kind: ts.SyntaxKind): ts.Node | undefined {
416+
// this one we do want to use getChildren() because we also want to find syntax tokens,
419417
for (const child of node.getChildren()) {
420418
if (child.kind === kind) {
421419
return child;

packages/typescript-plugin/src/utils.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,15 @@ export function findNodeAtSpan<T extends ts.Node>(
109109

110110
const end = start + length;
111111

112-
for (const child of node.getChildren()) {
112+
return node.forEachChild((child) => {
113113
const childStart = child.getStart();
114114
if (end <= childStart) {
115115
return;
116116
}
117117

118118
const childEnd = child.getEnd();
119119
if (start >= childEnd) {
120-
continue;
120+
return;
121121
}
122122

123123
if (start === childStart && end === childEnd) {
@@ -133,7 +133,7 @@ export function findNodeAtSpan<T extends ts.Node>(
133133
if (foundInChildren) {
134134
return foundInChildren;
135135
}
136-
}
136+
});
137137
}
138138

139139
/**
@@ -144,15 +144,15 @@ export function findNodeAtPosition<T extends ts.Node>(
144144
pos: number,
145145
predicate?: NodeTypePredicate<T>
146146
): T | void {
147-
for (const child of node.getChildren()) {
147+
return node.forEachChild((child) => {
148148
const childStart = child.getStart();
149149
if (pos < childStart) {
150150
return;
151151
}
152152

153153
const childEnd = child.getEnd();
154154
if (pos > childEnd) {
155-
continue;
155+
return;
156156
}
157157

158158
const foundInChildren = findNodeAtPosition(child, pos, predicate);
@@ -166,7 +166,7 @@ export function findNodeAtPosition<T extends ts.Node>(
166166
if (predicate(child)) {
167167
return child;
168168
}
169-
}
169+
});
170170
}
171171

172172
/**
@@ -204,9 +204,9 @@ export function gatherDescendants<T extends ts.Node>(
204204
if (predicate(node)) {
205205
dest.push(node);
206206
} else {
207-
for (const child of node.getChildren()) {
207+
node.forEachChild((child) => {
208208
gatherDescendants(child, predicate, dest);
209-
}
209+
});
210210
}
211211
return dest;
212212
}

0 commit comments

Comments
 (0)