Skip to content

Commit 2bf3105

Browse files
Added cache
1 parent 4663d2a commit 2bf3105

File tree

3 files changed

+55
-20
lines changed

3 files changed

+55
-20
lines changed

packages/cursorless-engine/src/languages/LanguageDefinition.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ import {
1313
type TextDocument,
1414
} from "@cursorless/common";
1515
import { TreeSitterScopeHandler } from "../processTargets/modifiers/scopeHandlers";
16+
import { LanguageDefinitionCache } from "./LanguageDefinitionCache";
1617
import { TreeSitterQuery } from "./TreeSitterQuery";
1718
import type { QueryCapture } from "./TreeSitterQuery/QueryCapture";
1819
import { validateQueryCaptures } from "./TreeSitterQuery/validateQueryCaptures";
1920

21+
const cache = new LanguageDefinitionCache();
22+
2023
/**
2124
* Represents a language definition for a single language, including the
2225
* tree-sitter query used to extract scopes for the given language
@@ -94,28 +97,26 @@ export class LanguageDefinition {
9497
document: TextDocument,
9598
captureName: SimpleScopeTypeType,
9699
): QueryCapture[] {
97-
return this.query
98-
.matches(document)
99-
.map((match) => match.captures.find(({ name }) => name === captureName))
100-
.filter((capture) => capture != null);
100+
if (!cache.isValid(document)) {
101+
cache.update(document, this.getCapturesMap(document));
102+
}
103+
104+
return cache.get(captureName);
101105
}
102106

103-
getMultipleCaptures(
104-
document: TextDocument,
105-
captureNames: SimpleScopeTypeType[],
106-
): StringRecord<QueryCapture[]> {
107+
/**
108+
* This is a low level function that returns a map of all captures in the document.
109+
*/
110+
private getCapturesMap(document: TextDocument): StringRecord<QueryCapture[]> {
107111
const matches = this.query.matches(document);
108112
const result: StringRecord<QueryCapture[]> = {};
109-
const captureNamesSet = new Set<string>(captureNames);
110113

111114
for (const match of matches) {
112115
for (const capture of match.captures) {
113-
if (captureNamesSet.has(capture.name)) {
114-
if (result[capture.name] == null) {
115-
result[capture.name] = [];
116-
}
117-
result[capture.name]!.push(capture);
116+
if (result[capture.name] == null) {
117+
result[capture.name] = [];
118118
}
119+
result[capture.name]!.push(capture);
119120
}
120121
}
121122

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type {
2+
SimpleScopeTypeType,
3+
StringRecord,
4+
TextDocument,
5+
} from "@cursorless/common";
6+
import type { QueryCapture } from "./TreeSitterQuery/QueryCapture";
7+
import { ide } from "..";
8+
9+
export class LanguageDefinitionCache {
10+
private languageId: string = "";
11+
private documentUri: string = "";
12+
private documentVersion: number = -1;
13+
private captures: StringRecord<QueryCapture[]> = {};
14+
15+
isValid(document: TextDocument) {
16+
if (ide().runMode === "test") {
17+
return false;
18+
}
19+
return (
20+
this.languageId === document.languageId &&
21+
this.documentUri === document.uri.toString() &&
22+
this.documentVersion === document.version
23+
);
24+
}
25+
26+
update(document: TextDocument, captures: StringRecord<QueryCapture[]>) {
27+
this.languageId = document.languageId;
28+
this.documentUri = document.uri.toString();
29+
this.documentVersion = document.version;
30+
this.captures = captures;
31+
}
32+
33+
get(captureName: SimpleScopeTypeType): QueryCapture[] {
34+
return this.captures[captureName] ?? [];
35+
}
36+
}

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/getDelimiterOccurrences.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,12 @@ export function getDelimiterOccurrences(
2222
return [];
2323
}
2424

25-
const captures = languageDefinition?.getMultipleCaptures(document, [
26-
"disqualifyDelimiter",
27-
"textFragment",
28-
]);
2925
const disqualifyDelimiters = createRangeIterator(
30-
captures?.disqualifyDelimiter,
26+
languageDefinition?.getCaptures(document, "disqualifyDelimiter"),
27+
);
28+
const textFragments = createRangeIterator(
29+
languageDefinition?.getCaptures(document, "textFragment"),
3130
);
32-
const textFragments = createRangeIterator(captures?.textFragment);
3331

3432
const delimiterTextToDelimiterInfoMap = Object.fromEntries(
3533
individualDelimiters.map((individualDelimiter) => [

0 commit comments

Comments
 (0)