Skip to content

Commit 772442c

Browse files
committed
PR feedback
1 parent 38d35f7 commit 772442c

File tree

6 files changed

+93
-87
lines changed

6 files changed

+93
-87
lines changed

packages/cursorless-engine/src/cursorlessEngine.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { MarkStageFactoryImpl } from "./processTargets/MarkStageFactoryImpl";
99
import { ModifierStageFactoryImpl } from "./processTargets/ModifierStageFactoryImpl";
1010
import { ScopeHandlerFactoryImpl } from "./processTargets/modifiers/scopeHandlers";
1111
import { injectIde } from "./singletons/ide.singleton";
12-
import { LanguageDefinitionsImpl } from "./languages/LanguageDefinitionsImpl";
12+
import { LanguageDefinitions } from "./languages/LanguageDefinitions";
1313

1414
export function createCursorlessEngine(
1515
treeSitter: TreeSitter,
@@ -37,7 +37,7 @@ export function createCursorlessEngine(
3737

3838
const testCaseRecorder = new TestCaseRecorder(hatTokenMap);
3939

40-
const languageDefinitions = new LanguageDefinitionsImpl(treeSitter);
40+
const languageDefinitions = new LanguageDefinitions(treeSitter);
4141
const scopeHandlerFactory = new ScopeHandlerFactoryImpl(languageDefinitions);
4242
const markStageFactory = new MarkStageFactoryImpl();
4343
const modifierStageFactory = new ModifierStageFactoryImpl(
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { ScopeType, SimpleScopeType } from "@cursorless/common";
2+
import { Query } from "web-tree-sitter";
3+
import { ide } from "../singletons/ide.singleton";
4+
import { join } from "path";
5+
import { TreeSitterScopeHandler } from "../processTargets/modifiers/scopeHandlers";
6+
import { TreeSitter } from "../typings/TreeSitter";
7+
import { existsSync, readFileSync } from "fs";
8+
import { LanguageId } from "./constants";
9+
10+
/**
11+
* Represents a language definition for a single language, including the
12+
* tree-sitter query used to extract scopes for the given language
13+
*/
14+
export class LanguageDefinition {
15+
private constructor(private treeSitter: TreeSitter, private query: Query) {}
16+
17+
/**
18+
* Construct a language definition for the given language id, if the language
19+
* has a new-style query definition, or return null if the language doesn't
20+
*
21+
* @param treeSitter The tree-sitter instance to use for parsing
22+
* @param languageId The language id for which to create a language definition
23+
* @returns A language definition for the given language id, or null if the given language
24+
* id doesn't have a new-style query definition
25+
*/
26+
static create(
27+
treeSitter: TreeSitter,
28+
languageId: LanguageId,
29+
): LanguageDefinition | null {
30+
const queryPath = join(ide().assetsRoot, "queries", `${languageId}.scm`);
31+
32+
if (!existsSync(queryPath)) {
33+
return null;
34+
}
35+
36+
const rawLanguageQueryString = readFileSync(queryPath, "utf8");
37+
38+
return new LanguageDefinition(
39+
treeSitter,
40+
treeSitter.getLanguage(languageId)!.query(rawLanguageQueryString),
41+
);
42+
}
43+
44+
/**
45+
* @param scopeType The scope type for which to get a scope handler
46+
* @returns A scope handler for the given scope type and language id, or
47+
* undefined if the given scope type / language id combination is still using
48+
* legacy pathways
49+
*/
50+
getScopeHandler(scopeType: ScopeType) {
51+
if (!this.query.captureNames.includes(scopeType.type)) {
52+
return undefined;
53+
}
54+
55+
return new TreeSitterScopeHandler(
56+
this.treeSitter,
57+
this.query,
58+
scopeType as SimpleScopeType,
59+
);
60+
}
61+
}

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

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
1-
import { ScopeType } from "@cursorless/common";
2-
import { ScopeHandler } from "../processTargets/modifiers/scopeHandlers/scopeHandler.types";
1+
import { isLanguageSupported } from ".";
2+
import { TreeSitter } from "..";
3+
import { LanguageDefinition } from "./LanguageDefinition";
34

4-
export interface LanguageDefinitions {
5-
get(languageId: string): LanguageDefinition | undefined;
6-
}
5+
/**
6+
* Keeps a map from language ids to {@link LanguageDefinition} instances,
7+
* constructing them as necessary
8+
*/
9+
export class LanguageDefinitions {
10+
/**
11+
* Maps from language id to {@link LanguageDefinition} or `null` if language
12+
* doesn't have new-style definitions
13+
*/
14+
private languageDefinitions: Map<string, LanguageDefinition | null> =
15+
new Map();
16+
17+
constructor(private treeSitter: TreeSitter) {}
18+
19+
get(languageId: string): LanguageDefinition | undefined {
20+
let definition = this.languageDefinitions.get(languageId);
21+
22+
if (definition === undefined) {
23+
definition = isLanguageSupported(languageId)
24+
? LanguageDefinition.create(this.treeSitter, languageId)
25+
: null;
26+
27+
this.languageDefinitions.set(languageId, definition);
28+
}
729

8-
export interface LanguageDefinition {
9-
maybeGetLanguageScopeHandler: (
10-
scopeType: ScopeType,
11-
) => ScopeHandler | undefined;
30+
return definition ?? undefined;
31+
}
1232
}

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

Lines changed: 0 additions & 37 deletions
This file was deleted.

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class ScopeHandlerFactoryImpl implements ScopeHandlerFactory {
5656
default:
5757
return this.languageDefinitions
5858
.get(languageId)
59-
?.maybeGetLanguageScopeHandler(scopeType);
59+
?.getScopeHandler(scopeType);
6060
}
6161
}
6262
}

0 commit comments

Comments
 (0)