From 6ac7ea616d68aa96fc4ccaac3b03d942bd48da19 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 10:00:31 +0100 Subject: [PATCH 01/71] Started working on scope tests --- .../common/src/testUtil/getFixturePaths.ts | 18 +++ .../scopes/javascript/assignment.name.txt | 2 + .../src/suite/scopes.vscode.test.ts | 113 ++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt create mode 100644 packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts diff --git a/packages/common/src/testUtil/getFixturePaths.ts b/packages/common/src/testUtil/getFixturePaths.ts index 034d3ceeff..4424a96910 100644 --- a/packages/common/src/testUtil/getFixturePaths.ts +++ b/packages/common/src/testUtil/getFixturePaths.ts @@ -21,6 +21,10 @@ export function getRecordedTestsDirPath() { return path.join(getFixturesPath(), "recorded"); } +export function getScopeTestsDirPath() { + return path.join(getFixturesPath(), "scopes"); +} + export function getRecordedTestPaths() { const directory = getRecordedTestsDirPath(); const relativeDir = path.dirname(directory); @@ -32,3 +36,17 @@ export function getRecordedTestPaths() { path: p, })); } + +export function getScopeTestPaths() { + const directory = getScopeTestsDirPath(); + const relativeDir = path.dirname(directory); + + return walkFilesSync(directory) + .filter((p) => p.endsWith(".txt")) + .map((p) => ({ + path: p, + name: path.relative(relativeDir, p.substring(0, p.lastIndexOf("."))), + languageId: path.dirname(path.relative(directory, p)), + facetId: path.basename(p.substring(0, p.lastIndexOf("."))), + })); +} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt new file mode 100644 index 0000000000..4ef4d3479b --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt @@ -0,0 +1,2 @@ +const name = "Hello world"; +--- \ No newline at end of file diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts new file mode 100644 index 0000000000..dd85de06fd --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -0,0 +1,113 @@ +import { + asyncSafety, + GeneralizedRange, + getScopeTestPaths, + Position, + Range, + ScopeRanges, + ScopeType, +} from "@cursorless/common"; +import { getCursorlessApi, openNewEditor } from "@cursorless/vscode-common"; +import { assert } from "chai"; +import { promises as fsp } from "node:fs"; +import { endToEndTestSetup } from "../endToEndTestSetup"; + +suite.only("scope test cases", async function () { + endToEndTestSetup(this); + + getScopeTestPaths().forEach(({ path, name, languageId, facetId }) => + test( + name, + asyncSafety(() => runTest(path, languageId, facetId)), + ), + ); +}); + +async function runTest(file: string, languageId: string, facetId: string) { + const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; + const scopeType = getScope(facetId); + const fixture = (await fsp.readFile(file)).toString(); + const delimiterIndex = fixture.match(/\r?\n^---$/m)?.index; + + assert.ok( + delimiterIndex != null, + "Can't find delimiter '---' in scope fixture", + ); + + const code = fixture.slice(0, delimiterIndex); + + await openNewEditor(code, { languageId }); + + const editor = ide.activeTextEditor!; + + const scopes = scopeProvider.provideScopeRanges(editor, { + visibleOnly: false, + scopeType, + }); + + const updatedFixture = serializesScopes(code, scopes); + + console.log(updatedFixture); +} + +function serializesScopes(code: string, scopes: ScopeRanges[]): string { + const codeLines = code.split(/\r?\n/); + const lines: string[] = [code, "---", ""]; + + for (const scope of scopes) { + for (const target of scope.targets) { + lines.push(renderHeader(codeLines, "Content", target.contentRange)); + } + } + + return lines.join("\n"); +} + +function renderHeader( + codeLines: string[], + header: string, + range: Range, +): string { + const { start, end } = range; + const lines: string[] = [`[${header}]`]; + + codeLines.forEach((codeLine, index) => { + lines.push(codeLine); + if (index === start.line) { + lines.push(renderStartRange(start, end, codeLine.length)); + } else if (index === end.line) { + lines.push(renderEndRange(end)); + } + }); + + return lines.join("\n"); +} + +const SYMBOL = "^"; + +function renderStartRange( + start: Position, + end: Position, + rowLength: number, +): string { + const chars: string[] = []; + const length = start.line === end.line ? end.character : rowLength; + for (let i = 0; i < length; ++i) { + chars.push(i < start.character ? " " : SYMBOL); + } + return chars.join(""); +} + +function renderEndRange(end: Position): string { + return new Array(end.character).join(SYMBOL); +} + +function getScope(facetId: string): ScopeType { + if (facetId.endsWith(".name")) { + return { type: "name" }; + } + if (facetId.endsWith(".value")) { + return { type: "value" }; + } + throw Error(`Unknown facetId ${facetId}`); +} From 9bc6d8a0e1358f4862ac08f235fe073e7d46c21e Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 10:47:43 +0100 Subject: [PATCH 02/71] Extend scope provider interface --- packages/common/src/types/ScopeProvider.ts | 5 ++++ .../src/scopeProviders/getTargetRanges.ts | 25 +++++++++++++++++++ .../src/suite/scopes.vscode.test.ts | 1 - 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/common/src/types/ScopeProvider.ts b/packages/common/src/types/ScopeProvider.ts index 4855995fd6..fdbeb73bfc 100644 --- a/packages/common/src/types/ScopeProvider.ts +++ b/packages/common/src/types/ScopeProvider.ts @@ -178,7 +178,12 @@ export interface ScopeRanges { */ export interface TargetRanges { contentRange: Range; + removalRange: Range; removalHighlightRange: GeneralizedRange; + interior: TargetRanges[] | undefined; + boundary: TargetRanges[] | undefined; + leadingDelimiter: TargetRanges | undefined; + trailingDelimiter: TargetRanges | undefined; } /** diff --git a/packages/cursorless-engine/src/scopeProviders/getTargetRanges.ts b/packages/cursorless-engine/src/scopeProviders/getTargetRanges.ts index 8be5e52e72..516ae0f7cd 100644 --- a/packages/cursorless-engine/src/scopeProviders/getTargetRanges.ts +++ b/packages/cursorless-engine/src/scopeProviders/getTargetRanges.ts @@ -6,10 +6,35 @@ import { import { Target } from "../typings/target.types"; export function getTargetRanges(target: Target): TargetRanges { + const interior = (() => { + try { + target.getInteriorStrict().map(getTargetRanges); + } catch (error) { + return undefined; + } + })(); + + const boundary = (() => { + try { + target.getBoundaryStrict().map(getTargetRanges); + } catch (error) { + return undefined; + } + })(); + return { contentRange: target.contentRange, + removalRange: target.getRemovalRange(), removalHighlightRange: target.isLine ? toLineRange(target.getRemovalHighlightRange()) : toCharacterRange(target.getRemovalHighlightRange()), + interior, + boundary, + leadingDelimiter: getOptionalTarget(target.getLeadingDelimiterTarget()), + trailingDelimiter: getOptionalTarget(target.getTrailingDelimiterTarget()), }; } + +function getOptionalTarget(target: Target | undefined) { + return target != null ? getTargetRanges(target) : undefined; +} diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index dd85de06fd..c7ccbb918c 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -1,6 +1,5 @@ import { asyncSafety, - GeneralizedRange, getScopeTestPaths, Position, Range, From 832627610926ecad1b6c0ee789bb0975f7327725 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 10:51:14 +0100 Subject: [PATCH 03/71] Add insertion delimiter --- packages/common/src/types/ScopeProvider.ts | 5 +++-- .../cursorless-engine/src/scopeProviders/getTargetRanges.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/common/src/types/ScopeProvider.ts b/packages/common/src/types/ScopeProvider.ts index fdbeb73bfc..0c0cd7335a 100644 --- a/packages/common/src/types/ScopeProvider.ts +++ b/packages/common/src/types/ScopeProvider.ts @@ -180,10 +180,11 @@ export interface TargetRanges { contentRange: Range; removalRange: Range; removalHighlightRange: GeneralizedRange; - interior: TargetRanges[] | undefined; - boundary: TargetRanges[] | undefined; leadingDelimiter: TargetRanges | undefined; trailingDelimiter: TargetRanges | undefined; + interior: TargetRanges[] | undefined; + boundary: TargetRanges[] | undefined; + insertionDelimiter: string; } /** diff --git a/packages/cursorless-engine/src/scopeProviders/getTargetRanges.ts b/packages/cursorless-engine/src/scopeProviders/getTargetRanges.ts index 516ae0f7cd..6e4a7f5a4b 100644 --- a/packages/cursorless-engine/src/scopeProviders/getTargetRanges.ts +++ b/packages/cursorless-engine/src/scopeProviders/getTargetRanges.ts @@ -28,10 +28,11 @@ export function getTargetRanges(target: Target): TargetRanges { removalHighlightRange: target.isLine ? toLineRange(target.getRemovalHighlightRange()) : toCharacterRange(target.getRemovalHighlightRange()), - interior, - boundary, leadingDelimiter: getOptionalTarget(target.getLeadingDelimiterTarget()), trailingDelimiter: getOptionalTarget(target.getTrailingDelimiterTarget()), + interior, + boundary, + insertionDelimiter: target.insertionDelimiter, }; } From 5feb0cf9206400f36583241b77c69833e2731be1 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 11:28:59 +0100 Subject: [PATCH 04/71] Added additional test --- .../scopes/javascript/assignment.name.txt | 30 ++++++- .../scopes/javascript/assignment.value.txt | 22 +++++ .../src/suite/scopes.vscode.test.ts | 85 ++++++++++++++++--- 3 files changed, 125 insertions(+), 12 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt index 4ef4d3479b..2b80559e6f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt @@ -1,2 +1,30 @@ const name = "Hello world"; ---- \ No newline at end of file +--- + +[Content] +const name = "Hello world"; + ^^^^ + +[Removal] +const name = "Hello world"; +^^^^^^^^^^^^^ + +[Leading delimiter: Content] +const name = "Hello world"; + ^ + +[Leading delimiter: Removal] +const name = "Hello world"; + ^ + +[Trailing delimiter: Content] +const name = "Hello world"; + ^ + +[Trailing delimiter: Removal] +const name = "Hello world"; + ^ + +[Domain] +const name = "Hello world"; +^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt new file mode 100644 index 0000000000..08b557b0f5 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt @@ -0,0 +1,22 @@ +const name = "Hello world"; +--- + +[Content] +const name = "Hello world"; + ^^^^^^^^^^^^^ + +[Removal] +const name = "Hello world"; + ^^^^^^^^^^^^^^^^ + +[Leading delimiter: Content] +const name = "Hello world"; + ^^^ + +[Leading delimiter: Removal] +const name = "Hello world"; + ^^^ + +[Domain] +const name = "Hello world"; +^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index c7ccbb918c..315c066d78 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -5,13 +5,15 @@ import { Range, ScopeRanges, ScopeType, + shouldUpdateFixtures, + TargetRanges, } from "@cursorless/common"; import { getCursorlessApi, openNewEditor } from "@cursorless/vscode-common"; import { assert } from "chai"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; -suite.only("scope test cases", async function () { +suite("Scope test cases", async function () { endToEndTestSetup(this); getScopeTestPaths().forEach(({ path, name, languageId, facetId }) => @@ -44,31 +46,92 @@ async function runTest(file: string, languageId: string, facetId: string) { scopeType, }); - const updatedFixture = serializesScopes(code, scopes); + const outputFixture = [code, "---", serializeScopes(code, scopes)].join("\n"); - console.log(updatedFixture); + if (shouldUpdateFixtures()) { + await fsp.writeFile(file, outputFixture); + } else { + assert.equal(outputFixture, fixture); + } } -function serializesScopes(code: string, scopes: ScopeRanges[]): string { +function serializeScopes(code: string, scopes: ScopeRanges[]): string { const codeLines = code.split(/\r?\n/); - const lines: string[] = [code, "---", ""]; + return scopes.map((scope) => serializeScope(codeLines, scope)).join("\n"); +} - for (const scope of scopes) { - for (const target of scope.targets) { - lines.push(renderHeader(codeLines, "Content", target.contentRange)); - } +function serializeScope(codeLines: string[], scope: ScopeRanges): string { + return [ + serializeTargets(codeLines, scope.targets, []), + serializeHeader(codeLines, [], "Domain", scope.domain), + ].join("\n"); +} + +function serializeTargets( + codeLines: string[], + targets: TargetRanges[], + prefix: string[], +): string { + return targets + .map((target) => serializeTarget(codeLines, target, prefix)) + .join("\n"); +} + +function serializeTarget( + codeLines: string[], + target: TargetRanges, + prefix: string[], +): string { + const lines: string[] = []; + + lines.push( + serializeHeader(codeLines, prefix, "Content", target.contentRange), + serializeHeader(codeLines, prefix, "Removal", target.removalRange), + ); + + if (target.leadingDelimiter != null) { + lines.push( + serializeTarget(codeLines, target.leadingDelimiter, [ + ...prefix, + "Leading delimiter", + ]), + ); + } + + if (target.trailingDelimiter != null) { + lines.push( + serializeTarget(codeLines, target.trailingDelimiter, [ + ...prefix, + "Trailing delimiter", + ]), + ); + } + + if (target.interior != null) { + lines.push( + serializeTargets(codeLines, target.interior, [...prefix, "Interior"]), + ); + } + + if (target.boundary != null) { + lines.push( + serializeTargets(codeLines, target.boundary, [...prefix, "Boundary"]), + ); } return lines.join("\n"); } -function renderHeader( +function serializeHeader( codeLines: string[], + prefix: string[], header: string, range: Range, ): string { const { start, end } = range; - const lines: string[] = [`[${header}]`]; + const fullHeader = + prefix.length > 0 ? `${prefix.join(" | ")}: ${header}` : header; + const lines: string[] = ["", `[${fullHeader}]`]; codeLines.forEach((codeLine, index) => { lines.push(codeLine); From 6cd7cc0485d0e43aacf5d917b7b5fa3cf1e09978 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:32:21 +0000 Subject: [PATCH 05/71] [pre-commit.ci lite] apply automatic fixes --- .../src/suite/fixtures/scopes/javascript/assignment.name.txt | 2 +- .../src/suite/fixtures/scopes/javascript/assignment.value.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt index 2b80559e6f..504fce6250 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt @@ -27,4 +27,4 @@ const name = "Hello world"; [Domain] const name = "Hello world"; -^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file +^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt index 08b557b0f5..c0009d76f5 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt @@ -19,4 +19,4 @@ const name = "Hello world"; [Domain] const name = "Hello world"; -^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file +^^^^^^^^^^^^^^^^^^^^^^^^^^^ From eac4b30156ff7bc348166d5f5ceb4bd5da48f60f Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 11:36:42 +0100 Subject: [PATCH 06/71] Trailing newline --- .../src/suite/fixtures/scopes/javascript/assignment.name.txt | 2 +- .../src/suite/fixtures/scopes/javascript/assignment.value.txt | 2 +- .../cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt index 2b80559e6f..504fce6250 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt @@ -27,4 +27,4 @@ const name = "Hello world"; [Domain] const name = "Hello world"; -^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file +^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt index 08b557b0f5..c0009d76f5 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt @@ -19,4 +19,4 @@ const name = "Hello world"; [Domain] const name = "Hello world"; -^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ No newline at end of file +^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 315c066d78..31715d5f8b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -46,7 +46,9 @@ async function runTest(file: string, languageId: string, facetId: string) { scopeType, }); - const outputFixture = [code, "---", serializeScopes(code, scopes)].join("\n"); + const outputFixture = [code, "---", serializeScopes(code, scopes), ""].join( + "\n", + ); if (shouldUpdateFixtures()) { await fsp.writeFile(file, outputFixture); From 0348ae4a6a421dd1764136801b1dc9185c04e1d1 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 11:58:17 +0100 Subject: [PATCH 07/71] Added example with multipole scopes --- .../javascript/assignment.multiple.value.txt | 53 ++++++++++++ .../src/suite/scopes.vscode.test.ts | 86 +++++++++++++------ 2 files changed, 115 insertions(+), 24 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt new file mode 100644 index 0000000000..b262d91df9 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt @@ -0,0 +1,53 @@ +const name = "Hello world"; +const value = 2; +--- + +[Content 1] +const name = "Hello world"; + ^^^^^^^^^^^^^ +const value = 2; + +[Removal 1] +const name = "Hello world"; + ^^^^^^^^^^^^^^^^ +const value = 2; + +[Leading delimiter: Content 1] +const name = "Hello world"; + ^^^ +const value = 2; + +[Leading delimiter: Removal 1] +const name = "Hello world"; + ^^^ +const value = 2; + +[Domain 1] +const name = "Hello world"; +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +const value = 2; + +[Content 2] +const name = "Hello world"; +const value = 2; + ^ + +[Removal 2] +const name = "Hello world"; +const value = 2; + ^^^^ + +[Leading delimiter: Content 2] +const name = "Hello world"; +const value = 2; + ^^^ + +[Leading delimiter: Removal 2] +const name = "Hello world"; +const value = 2; + ^^^ + +[Domain 2] +const name = "Hello world"; +const value = 2; +^^^^^^^^^^^^^^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 31715d5f8b..d6ebfabd53 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -46,9 +46,14 @@ async function runTest(file: string, languageId: string, facetId: string) { scopeType, }); - const outputFixture = [code, "---", serializeScopes(code, scopes), ""].join( - "\n", - ); + const codeLines = code.split(/\r?\n/); + + const outputFixture = [ + ...codeLines, + "---", + serializeScopes(codeLines, scopes), + "", + ].join("\n"); if (shouldUpdateFixtures()) { await fsp.writeFile(file, outputFixture); @@ -57,15 +62,22 @@ async function runTest(file: string, languageId: string, facetId: string) { } } -function serializeScopes(code: string, scopes: ScopeRanges[]): string { - const codeLines = code.split(/\r?\n/); - return scopes.map((scope) => serializeScope(codeLines, scope)).join("\n"); +function serializeScopes(codeLines: string[], scopes: ScopeRanges[]): string { + return scopes + .map((scope, index) => + serializeScope(codeLines, scope, scopes.length > 1 ? index : undefined), + ) + .join("\n"); } -function serializeScope(codeLines: string[], scope: ScopeRanges): string { +function serializeScope( + codeLines: string[], + scope: ScopeRanges, + index: number | undefined, +): string { return [ - serializeTargets(codeLines, scope.targets, []), - serializeHeader(codeLines, [], "Domain", scope.domain), + serializeTargets(codeLines, scope.targets, [], index), + serializeHeader(codeLines, [], "Domain", index, scope.domain), ].join("\n"); } @@ -73,9 +85,10 @@ function serializeTargets( codeLines: string[], targets: TargetRanges[], prefix: string[], + index: number | undefined, ): string { return targets - .map((target) => serializeTarget(codeLines, target, prefix)) + .map((target) => serializeTarget(codeLines, target, prefix, index)) .join("\n"); } @@ -83,41 +96,56 @@ function serializeTarget( codeLines: string[], target: TargetRanges, prefix: string[], + index: number | undefined, ): string { const lines: string[] = []; lines.push( - serializeHeader(codeLines, prefix, "Content", target.contentRange), - serializeHeader(codeLines, prefix, "Removal", target.removalRange), + serializeHeader(codeLines, prefix, "Content", index, target.contentRange), + serializeHeader(codeLines, prefix, "Removal", index, target.removalRange), ); if (target.leadingDelimiter != null) { lines.push( - serializeTarget(codeLines, target.leadingDelimiter, [ - ...prefix, - "Leading delimiter", - ]), + serializeTarget( + codeLines, + target.leadingDelimiter, + [...prefix, "Leading delimiter"], + index, + ), ); } if (target.trailingDelimiter != null) { lines.push( - serializeTarget(codeLines, target.trailingDelimiter, [ - ...prefix, - "Trailing delimiter", - ]), + serializeTarget( + codeLines, + target.trailingDelimiter, + [...prefix, "Trailing delimiter"], + index, + ), ); } if (target.interior != null) { lines.push( - serializeTargets(codeLines, target.interior, [...prefix, "Interior"]), + serializeTargets( + codeLines, + target.interior, + [...prefix, "Interior"], + index, + ), ); } if (target.boundary != null) { lines.push( - serializeTargets(codeLines, target.boundary, [...prefix, "Boundary"]), + serializeTargets( + codeLines, + target.boundary, + [...prefix, "Boundary"], + index, + ), ); } @@ -128,11 +156,21 @@ function serializeHeader( codeLines: string[], prefix: string[], header: string, + index: number | undefined, range: Range, ): string { const { start, end } = range; - const fullHeader = - prefix.length > 0 ? `${prefix.join(" | ")}: ${header}` : header; + const fullHeader = (() => { + const parts: string[] = []; + if (prefix.length > 0) { + parts.push(prefix.join(" | ") + ":"); + } + parts.push(header); + if (index != null) { + parts.push(index.toString()); + } + return parts.join(" "); + })(); const lines: string[] = ["", `[${fullHeader}]`]; codeLines.forEach((codeLine, index) => { From dde8a77101b81aa3ff01954def7e8ec265f2708b Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 12:11:05 +0100 Subject: [PATCH 08/71] Added function --- .../fixtures/scopes/javascript/function.txt | 25 +++++++++++++++++++ .../src/suite/scopes.vscode.test.ts | 11 ++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt new file mode 100644 index 0000000000..205b008287 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt @@ -0,0 +1,25 @@ +function myFunk() { + +} +--- + +[Content] +function myFunk() { +^^^^^^^^^^^^^^^^^^^ + +} +^ + +[Removal] +function myFunk() { +^^^^^^^^^^^^^^^^^^^ + +} +^ + +[Domain] +function myFunk() { +^^^^^^^^^^^^^^^^^^^ + +} +^ diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index d6ebfabd53..68f864d418 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -65,7 +65,11 @@ async function runTest(file: string, languageId: string, facetId: string) { function serializeScopes(codeLines: string[], scopes: ScopeRanges[]): string { return scopes .map((scope, index) => - serializeScope(codeLines, scope, scopes.length > 1 ? index : undefined), + serializeScope( + codeLines, + scope, + scopes.length > 1 ? index + 1 : undefined, + ), ) .join("\n"); } @@ -201,7 +205,7 @@ function renderStartRange( } function renderEndRange(end: Position): string { - return new Array(end.character).join(SYMBOL); + return new Array(end.character + 1).join(SYMBOL); } function getScope(facetId: string): ScopeType { @@ -211,5 +215,8 @@ function getScope(facetId: string): ScopeType { if (facetId.endsWith(".value")) { return { type: "value" }; } + if (facetId.endsWith("function")) { + return { type: "namedFunction" }; + } throw Error(`Unknown facetId ${facetId}`); } From 9f793678da8bc910cee9d4934dcba6fad62c067b Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 13:55:33 +0100 Subject: [PATCH 09/71] Changed representation --- .../javascript/assignment.multiple.value.txt | 60 ++++----- .../scopes/javascript/assignment.name.txt | 28 ++--- .../scopes/javascript/assignment.value.txt | 20 +-- .../fixtures/scopes/javascript/function.txt | 30 ++--- .../suite/fixtures/scopes/javascript/line.txt | 117 ++++++++++++++++++ .../src/suite/scopes.vscode.test.ts | 46 ++++--- 6 files changed, 214 insertions(+), 87 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt index b262d91df9..57a2104851 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt @@ -3,51 +3,51 @@ const value = 2; --- [Content 1] -const name = "Hello world"; - ^^^^^^^^^^^^^ -const value = 2; + const name = "Hello world"; + [-------------] + const value = 2; [Removal 1] -const name = "Hello world"; - ^^^^^^^^^^^^^^^^ -const value = 2; + const name = "Hello world"; + [----------------] + const value = 2; [Leading delimiter: Content 1] -const name = "Hello world"; - ^^^ -const value = 2; + const name = "Hello world"; + [---] + const value = 2; [Leading delimiter: Removal 1] -const name = "Hello world"; - ^^^ -const value = 2; + const name = "Hello world"; + [---] + const value = 2; [Domain 1] -const name = "Hello world"; -^^^^^^^^^^^^^^^^^^^^^^^^^^^ -const value = 2; + const name = "Hello world"; +[---------------------------] + const value = 2; [Content 2] -const name = "Hello world"; -const value = 2; - ^ + const name = "Hello world"; + const value = 2; + [-] [Removal 2] -const name = "Hello world"; -const value = 2; - ^^^^ + const name = "Hello world"; + const value = 2; + [----] [Leading delimiter: Content 2] -const name = "Hello world"; -const value = 2; - ^^^ + const name = "Hello world"; + const value = 2; + [---] [Leading delimiter: Removal 2] -const name = "Hello world"; -const value = 2; - ^^^ + const name = "Hello world"; + const value = 2; + [---] [Domain 2] -const name = "Hello world"; -const value = 2; -^^^^^^^^^^^^^^^^ + const name = "Hello world"; + const value = 2; +[----------------] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt index 504fce6250..1a99561c6c 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt @@ -2,29 +2,29 @@ const name = "Hello world"; --- [Content] -const name = "Hello world"; - ^^^^ + const name = "Hello world"; + [----] [Removal] -const name = "Hello world"; -^^^^^^^^^^^^^ + const name = "Hello world"; +[-------------] [Leading delimiter: Content] -const name = "Hello world"; - ^ + const name = "Hello world"; + [-] [Leading delimiter: Removal] -const name = "Hello world"; - ^ + const name = "Hello world"; + [-] [Trailing delimiter: Content] -const name = "Hello world"; - ^ + const name = "Hello world"; + [-] [Trailing delimiter: Removal] -const name = "Hello world"; - ^ + const name = "Hello world"; + [-] [Domain] -const name = "Hello world"; -^^^^^^^^^^^^^^^^^^^^^^^^^^^ + const name = "Hello world"; +[---------------------------] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt index c0009d76f5..c7a7984b7b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt @@ -2,21 +2,21 @@ const name = "Hello world"; --- [Content] -const name = "Hello world"; - ^^^^^^^^^^^^^ + const name = "Hello world"; + [-------------] [Removal] -const name = "Hello world"; - ^^^^^^^^^^^^^^^^ + const name = "Hello world"; + [----------------] [Leading delimiter: Content] -const name = "Hello world"; - ^^^ + const name = "Hello world"; + [---] [Leading delimiter: Removal] -const name = "Hello world"; - ^^^ + const name = "Hello world"; + [---] [Domain] -const name = "Hello world"; -^^^^^^^^^^^^^^^^^^^^^^^^^^^ + const name = "Hello world"; +[---------------------------] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt index 205b008287..082c644e5f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt @@ -4,22 +4,22 @@ function myFunk() { --- [Content] -function myFunk() { -^^^^^^^^^^^^^^^^^^^ - -} -^ + function myFunk() { +[------------------- + + } + -] [Removal] -function myFunk() { -^^^^^^^^^^^^^^^^^^^ - -} -^ + function myFunk() { +[------------------- + + } + -] [Domain] -function myFunk() { -^^^^^^^^^^^^^^^^^^^ - -} -^ + function myFunk() { +[------------------- + + } + -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt new file mode 100644 index 0000000000..f4e469a779 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt @@ -0,0 +1,117 @@ + +aaa + +--- + +[Content 1] + +[] + aaa + + +[Removal 1] + +[ + aaa + ] + + +[Trailing delimiter: Content 1] + +[ + aaa + ] + + +[Trailing delimiter: Removal 1] + +[ + aaa + ] + + +[Domain 1] + +[] + aaa + + +[Content 2] + + aaa +[---] + + +[Removal 2] + + aaa +[--- + + ] + +[Leading delimiter: Content 2] + +[ + aaa + ] + + +[Leading delimiter: Removal 2] + +[ + aaa + ] + + +[Trailing delimiter: Content 2] + + aaa + [ + + ] + +[Trailing delimiter: Removal 2] + + aaa + [ + + ] + +[Domain 2] + + aaa +[---] + + +[Content 3] + + aaa + +[] + +[Removal 3] + + aaa + [ + + ] + +[Leading delimiter: Content 3] + + aaa + [ + + ] + +[Leading delimiter: Removal 3] + + aaa + [ + + ] + +[Domain 3] + + aaa + +[] diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 68f864d418..67446ffcfd 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -13,7 +13,8 @@ import { assert } from "chai"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; -suite("Scope test cases", async function () { +// TODO: Remove .only +suite.only("Scope test cases", async function () { endToEndTestSetup(this); getScopeTestPaths().forEach(({ path, name, languageId, facetId }) => @@ -178,34 +179,40 @@ function serializeHeader( const lines: string[] = ["", `[${fullHeader}]`]; codeLines.forEach((codeLine, index) => { - lines.push(codeLine); + lines.push(" " + codeLine); if (index === start.line) { - lines.push(renderStartRange(start, end, codeLine.length)); + if (range.isSingleLine) { + lines.push(serializeRange(start, end)); + } else { + lines.push(serializeStartRange(start, codeLine.length)); + } } else if (index === end.line) { - lines.push(renderEndRange(end)); + lines.push(serializeEndRange(end)); } }); return lines.join("\n"); } -const SYMBOL = "^"; +function serializeRange(start: Position, end: Position): string { + return [ + new Array(start.character + 1).join(" "), + "[", + new Array(end.character - start.character + 1).join("-"), + "]", + ].join(""); +} -function renderStartRange( - start: Position, - end: Position, - rowLength: number, -): string { - const chars: string[] = []; - const length = start.line === end.line ? end.character : rowLength; - for (let i = 0; i < length; ++i) { - chars.push(i < start.character ? " " : SYMBOL); - } - return chars.join(""); +function serializeStartRange(start: Position, rowLength: number): string { + return [ + new Array(start.character + 1).join(" "), + "[", + new Array(rowLength - start.character + 1).join("-"), + ].join(""); } -function renderEndRange(end: Position): string { - return new Array(end.character + 1).join(SYMBOL); +function serializeEndRange(end: Position): string { + return [" ", new Array(end.character + 1).join("-"), "]"].join(""); } function getScope(facetId: string): ScopeType { @@ -218,5 +225,8 @@ function getScope(facetId: string): ScopeType { if (facetId.endsWith("function")) { return { type: "namedFunction" }; } + if (facetId.endsWith("line")) { + return { type: "line" }; + } throw Error(`Unknown facetId ${facetId}`); } From 33263bb5587acfb9daa783023ca1ed7b57b388ee Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 12:57:10 +0000 Subject: [PATCH 10/71] [pre-commit.ci lite] apply automatic fixes --- .../fixtures/scopes/javascript/function.txt | 6 +- .../suite/fixtures/scopes/javascript/line.txt | 68 +++++++++---------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt index 082c644e5f..bc49dc781b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt @@ -6,20 +6,20 @@ function myFunk() { [Content] function myFunk() { [------------------- - + } -] [Removal] function myFunk() { [------------------- - + } -] [Domain] function myFunk() { [------------------- - + } -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt index f4e469a779..17d2cc6b3a 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt @@ -4,114 +4,114 @@ aaa --- [Content 1] - + [] aaa - + [Removal 1] - + [ aaa ] - + [Trailing delimiter: Content 1] - + [ aaa ] - + [Trailing delimiter: Removal 1] - + [ aaa ] - + [Domain 1] - + [] aaa - + [Content 2] - + aaa [---] - + [Removal 2] - + aaa [--- - + ] [Leading delimiter: Content 2] - + [ aaa ] - + [Leading delimiter: Removal 2] - + [ aaa ] - + [Trailing delimiter: Content 2] - + aaa [ - + ] [Trailing delimiter: Removal 2] - + aaa [ - + ] [Domain 2] - + aaa [---] - + [Content 3] - + aaa - + [] [Removal 3] - + aaa [ - + ] [Leading delimiter: Content 3] - + aaa [ - + ] [Leading delimiter: Removal 3] - + aaa [ - + ] [Domain 3] - + aaa - + [] From 91a5fc28f9ec66a1856645f54d5f05fe9748cb61 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 14:01:13 +0100 Subject: [PATCH 11/71] Change file ending --- .editorconfig | 2 +- .../common/src/testUtil/getFixturePaths.ts | 2 +- ...ignment.name.txt => assignment.name.scope} | 0 ...nment.value.txt => assignment.value.scope} | 0 .../{function.txt => function.scope} | 6 +- .../javascript/{line.txt => line.scope} | 68 +++++++++---------- ...le.value.txt => tale.multiple.value.scope} | 0 7 files changed, 39 insertions(+), 39 deletions(-) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/{assignment.name.txt => assignment.name.scope} (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/{assignment.value.txt => assignment.value.scope} (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/{function.txt => function.scope} (97%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/{line.txt => line.scope} (89%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/{assignment.multiple.value.txt => tale.multiple.value.scope} (100%) diff --git a/.editorconfig b/.editorconfig index 3d2dcf13eb..07aafa6773 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,7 +17,7 @@ indent_size = 4 [*.svg] insert_final_newline = false -[*.{yml,yaml}] +[*.{yml,yaml,scope}] # Trailing whitespace breaks yaml files if you use a multiline string # with a line that has trailing white space. Many of our recorded # tests use strings with trailing white space to represent the final diff --git a/packages/common/src/testUtil/getFixturePaths.ts b/packages/common/src/testUtil/getFixturePaths.ts index 4424a96910..6584baf4e2 100644 --- a/packages/common/src/testUtil/getFixturePaths.ts +++ b/packages/common/src/testUtil/getFixturePaths.ts @@ -42,7 +42,7 @@ export function getScopeTestPaths() { const relativeDir = path.dirname(directory); return walkFilesSync(directory) - .filter((p) => p.endsWith(".txt")) + .filter((p) => p.endsWith(".scope")) .map((p) => ({ path: p, name: path.relative(relativeDir, p.substring(0, p.lastIndexOf("."))), diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.txt rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.txt rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope similarity index 97% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope index bc49dc781b..082c644e5f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope @@ -6,20 +6,20 @@ function myFunk() { [Content] function myFunk() { [------------------- - + } -] [Removal] function myFunk() { [------------------- - + } -] [Domain] function myFunk() { [------------------- - + } -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope similarity index 89% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope index 17d2cc6b3a..f4e469a779 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.txt +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope @@ -4,114 +4,114 @@ aaa --- [Content 1] - + [] aaa - + [Removal 1] - + [ aaa ] - + [Trailing delimiter: Content 1] - + [ aaa ] - + [Trailing delimiter: Removal 1] - + [ aaa ] - + [Domain 1] - + [] aaa - + [Content 2] - + aaa [---] - + [Removal 2] - + aaa [--- - + ] [Leading delimiter: Content 2] - + [ aaa ] - + [Leading delimiter: Removal 2] - + [ aaa ] - + [Trailing delimiter: Content 2] - + aaa [ - + ] [Trailing delimiter: Removal 2] - + aaa [ - + ] [Domain 2] - + aaa [---] - + [Content 3] - + aaa - + [] [Removal 3] - + aaa [ - + ] [Leading delimiter: Content 3] - + aaa [ - + ] [Leading delimiter: Removal 3] - + aaa [ - + ] [Domain 3] - + aaa - + [] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.multiple.value.txt rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope From 9123d4be023d4d68adb446fec723ae0e4d6e55a1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:02:42 +0000 Subject: [PATCH 12/71] [pre-commit.ci lite] apply automatic fixes --- .../fixtures/scopes/javascript/function.scope | 6 +- .../fixtures/scopes/javascript/line.scope | 68 +++++++++---------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope index 082c644e5f..bc49dc781b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope @@ -6,20 +6,20 @@ function myFunk() { [Content] function myFunk() { [------------------- - + } -] [Removal] function myFunk() { [------------------- - + } -] [Domain] function myFunk() { [------------------- - + } -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope index f4e469a779..17d2cc6b3a 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope @@ -4,114 +4,114 @@ aaa --- [Content 1] - + [] aaa - + [Removal 1] - + [ aaa ] - + [Trailing delimiter: Content 1] - + [ aaa ] - + [Trailing delimiter: Removal 1] - + [ aaa ] - + [Domain 1] - + [] aaa - + [Content 2] - + aaa [---] - + [Removal 2] - + aaa [--- - + ] [Leading delimiter: Content 2] - + [ aaa ] - + [Leading delimiter: Removal 2] - + [ aaa ] - + [Trailing delimiter: Content 2] - + aaa [ - + ] [Trailing delimiter: Removal 2] - + aaa [ - + ] [Domain 2] - + aaa [---] - + [Content 3] - + aaa - + [] [Removal 3] - + aaa [ - + ] [Leading delimiter: Content 3] - + aaa [ - + ] [Leading delimiter: Removal 3] - + aaa [ - + ] [Domain 3] - + aaa - + [] From ec2004cf048399a133f441740e849973857caf8e Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 14:10:58 +0100 Subject: [PATCH 13/71] number --- .editorconfig | 11 +++++- .../fixtures/scopes/javascript/line.scope | 34 +++++++++---------- .../javascript/tale.multiple.value.scope | 20 +++++------ .../src/suite/scopes.vscode.test.ts | 7 ++-- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/.editorconfig b/.editorconfig index 07aafa6773..a2c7255f55 100644 --- a/.editorconfig +++ b/.editorconfig @@ -17,7 +17,7 @@ indent_size = 4 [*.svg] insert_final_newline = false -[*.{yml,yaml,scope}] +[*.{yml,yaml}] # Trailing whitespace breaks yaml files if you use a multiline string # with a line that has trailing white space. Many of our recorded # tests use strings with trailing white space to represent the final @@ -36,3 +36,12 @@ indent_style = unset trim_trailing_whitespace = unset insert_final_newline = unset max_line_length = unset + +[*.scope] +charset = unset +end_of_line = unset +indent_size = unset +indent_style = unset +trim_trailing_whitespace = unset +insert_final_newline = unset +max_line_length = unset diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope index f4e469a779..a0a50152fe 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope @@ -3,114 +3,114 @@ aaa --- -[Content 1] +[#1 Content] [] aaa -[Removal 1] +[#1 Removal] [ aaa ] -[Trailing delimiter: Content 1] +[#1 Trailing delimiter: Content] [ aaa ] -[Trailing delimiter: Removal 1] +[#1 Trailing delimiter: Removal] [ aaa ] -[Domain 1] +[#1 Domain] [] aaa -[Content 2] +[#2 Content] aaa [---] -[Removal 2] +[#2 Removal] aaa [--- ] -[Leading delimiter: Content 2] +[#2 Leading delimiter: Content] [ aaa ] -[Leading delimiter: Removal 2] +[#2 Leading delimiter: Removal] [ aaa ] -[Trailing delimiter: Content 2] +[#2 Trailing delimiter: Content] aaa [ ] -[Trailing delimiter: Removal 2] +[#2 Trailing delimiter: Removal] aaa [ ] -[Domain 2] +[#2 Domain] aaa [---] -[Content 3] +[#3 Content] aaa [] -[Removal 3] +[#3 Removal] aaa [ ] -[Leading delimiter: Content 3] +[#3 Leading delimiter: Content] aaa [ ] -[Leading delimiter: Removal 3] +[#3 Leading delimiter: Removal] aaa [ ] -[Domain 3] +[#3 Domain] aaa diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope index 57a2104851..a529d23b29 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope @@ -2,52 +2,52 @@ const name = "Hello world"; const value = 2; --- -[Content 1] +[#1 Content] const name = "Hello world"; [-------------] const value = 2; -[Removal 1] +[#1 Removal] const name = "Hello world"; [----------------] const value = 2; -[Leading delimiter: Content 1] +[#1 Leading delimiter: Content] const name = "Hello world"; [---] const value = 2; -[Leading delimiter: Removal 1] +[#1 Leading delimiter: Removal] const name = "Hello world"; [---] const value = 2; -[Domain 1] +[#1 Domain] const name = "Hello world"; [---------------------------] const value = 2; -[Content 2] +[#2 Content] const name = "Hello world"; const value = 2; [-] -[Removal 2] +[#2 Removal] const name = "Hello world"; const value = 2; [----] -[Leading delimiter: Content 2] +[#2 Leading delimiter: Content] const name = "Hello world"; const value = 2; [---] -[Leading delimiter: Removal 2] +[#2 Leading delimiter: Removal] const name = "Hello world"; const value = 2; [---] -[Domain 2] +[#2 Domain] const name = "Hello world"; const value = 2; [----------------] diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 67446ffcfd..b53cbf807a 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -167,13 +167,14 @@ function serializeHeader( const { start, end } = range; const fullHeader = (() => { const parts: string[] = []; + if (index != null) { + parts.push(`#${index}`); + } if (prefix.length > 0) { parts.push(prefix.join(" | ") + ":"); } parts.push(header); - if (index != null) { - parts.push(index.toString()); - } + return parts.join(" "); })(); const lines: string[] = ["", `[${fullHeader}]`]; From fcefb468f60dc00e06ee8a3301085b22df78da2a Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 14:15:22 +0100 Subject: [PATCH 14/71] fix --- .../fixtures/scopes/javascript/function.scope | 6 +- .../fixtures/scopes/javascript/line.scope | 117 ++++++++++++++++++ 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope index bc49dc781b..082c644e5f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope @@ -6,20 +6,20 @@ function myFunk() { [Content] function myFunk() { [------------------- - + } -] [Removal] function myFunk() { [------------------- - + } -] [Domain] function myFunk() { [------------------- - + } -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope index e69de29bb2..a0a50152fe 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope @@ -0,0 +1,117 @@ + +aaa + +--- + +[#1 Content] + +[] + aaa + + +[#1 Removal] + +[ + aaa + ] + + +[#1 Trailing delimiter: Content] + +[ + aaa + ] + + +[#1 Trailing delimiter: Removal] + +[ + aaa + ] + + +[#1 Domain] + +[] + aaa + + +[#2 Content] + + aaa +[---] + + +[#2 Removal] + + aaa +[--- + + ] + +[#2 Leading delimiter: Content] + +[ + aaa + ] + + +[#2 Leading delimiter: Removal] + +[ + aaa + ] + + +[#2 Trailing delimiter: Content] + + aaa + [ + + ] + +[#2 Trailing delimiter: Removal] + + aaa + [ + + ] + +[#2 Domain] + + aaa +[---] + + +[#3 Content] + + aaa + +[] + +[#3 Removal] + + aaa + [ + + ] + +[#3 Leading delimiter: Content] + + aaa + [ + + ] + +[#3 Leading delimiter: Removal] + + aaa + [ + + ] + +[#3 Domain] + + aaa + +[] From 191454fb472093df5e436dd7b21754d2aec4cefc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:16:50 +0000 Subject: [PATCH 15/71] [pre-commit.ci lite] apply automatic fixes --- .../fixtures/scopes/javascript/function.scope | 6 +- .../fixtures/scopes/javascript/line.scope | 68 +++++++++---------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope index 082c644e5f..bc49dc781b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope @@ -6,20 +6,20 @@ function myFunk() { [Content] function myFunk() { [------------------- - + } -] [Removal] function myFunk() { [------------------- - + } -] [Domain] function myFunk() { [------------------- - + } -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope index a0a50152fe..9790034b81 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope @@ -4,114 +4,114 @@ aaa --- [#1 Content] - + [] aaa - + [#1 Removal] - + [ aaa ] - + [#1 Trailing delimiter: Content] - + [ aaa ] - + [#1 Trailing delimiter: Removal] - + [ aaa ] - + [#1 Domain] - + [] aaa - + [#2 Content] - + aaa [---] - + [#2 Removal] - + aaa [--- - + ] [#2 Leading delimiter: Content] - + [ aaa ] - + [#2 Leading delimiter: Removal] - + [ aaa ] - + [#2 Trailing delimiter: Content] - + aaa [ - + ] [#2 Trailing delimiter: Removal] - + aaa [ - + ] [#2 Domain] - + aaa [---] - + [#3 Content] - + aaa - + [] [#3 Removal] - + aaa [ - + ] [#3 Leading delimiter: Content] - + aaa [ - + ] [#3 Leading delimiter: Removal] - + aaa [ - + ] [#3 Domain] - + aaa - + [] From 5814cd51ae608828075a2e2b312aa1d62ecea1f1 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 14:35:25 +0100 Subject: [PATCH 16/71] test --- .editorconfig | 9 --- .pre-commit-config.yaml | 2 +- .../fixtures/scopes/javascript/function.scope | 6 +- .../fixtures/scopes/javascript/line.scope | 68 +++++++++---------- 4 files changed, 38 insertions(+), 47 deletions(-) diff --git a/.editorconfig b/.editorconfig index a2c7255f55..3d2dcf13eb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -36,12 +36,3 @@ indent_style = unset trim_trailing_whitespace = unset insert_final_newline = unset max_line_length = unset - -[*.scope] -charset = unset -end_of_line = unset -indent_size = unset -indent_style = unset -trim_trailing_whitespace = unset -insert_final_newline = unset -max_line_length = unset diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fdba0648cb..c1fadfaf86 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: # tests use strings with trailing white space to represent the final # document contents. For example # packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/ruby/changeCondition.yml - exclude: ^packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/.*/[^/]*\.yml$ + exclude: ^packages/cursorless-vscode-e2e/src/suite/fixtures/.*/[^/]*\.(yml|scope)$ - repo: local hooks: - id: eslint diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope index bc49dc781b..082c644e5f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope @@ -6,20 +6,20 @@ function myFunk() { [Content] function myFunk() { [------------------- - + } -] [Removal] function myFunk() { [------------------- - + } -] [Domain] function myFunk() { [------------------- - + } -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope index 9790034b81..a0a50152fe 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope @@ -4,114 +4,114 @@ aaa --- [#1 Content] - + [] aaa - + [#1 Removal] - + [ aaa ] - + [#1 Trailing delimiter: Content] - + [ aaa ] - + [#1 Trailing delimiter: Removal] - + [ aaa ] - + [#1 Domain] - + [] aaa - + [#2 Content] - + aaa [---] - + [#2 Removal] - + aaa [--- - + ] [#2 Leading delimiter: Content] - + [ aaa ] - + [#2 Leading delimiter: Removal] - + [ aaa ] - + [#2 Trailing delimiter: Content] - + aaa [ - + ] [#2 Trailing delimiter: Removal] - + aaa [ - + ] [#2 Domain] - + aaa [---] - + [#3 Content] - + aaa - + [] [#3 Removal] - + aaa [ - + ] [#3 Leading delimiter: Content] - + aaa [ - + ] [#3 Leading delimiter: Removal] - + aaa [ - + ] [#3 Domain] - + aaa - + [] From e3753b32fdeba3be54e51789ec0435b35c1faa8c Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 14:40:41 +0100 Subject: [PATCH 17/71] fix --- packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index b53cbf807a..8cb7c1f698 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -13,7 +13,7 @@ import { assert } from "chai"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; -// TODO: Remove .only +// fixme: Remove .only suite.only("Scope test cases", async function () { endToEndTestSetup(this); From 7dcde957dad42966e6ede3cf8a3ff83d67c6e8ea Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 14:55:40 +0100 Subject: [PATCH 18/71] Added paragraph --- .../scopes/javascript/paragraph.scope | 91 +++++++++++++++++++ .../src/suite/scopes.vscode.test.ts | 6 +- 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope new file mode 100644 index 0000000000..9c61063939 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope @@ -0,0 +1,91 @@ + +aaa +bbb + +--- + +[Content] + + aaa +[--- + bbb + ---] + + +[Removal] + +[ + aaa + bbb + + ] + +[Leading delimiter: Content] + +[] + aaa + bbb + + +[Leading delimiter: Removal] + +[ + aaa + ] + bbb + + +[Leading delimiter | Trailing delimiter: Content] + +[ + aaa + ] + bbb + + +[Leading delimiter | Trailing delimiter: Removal] + +[ + aaa + ] + bbb + + +[Trailing delimiter: Content] + + aaa + bbb + +[] + +[Trailing delimiter: Removal] + + aaa + bbb + [ + + ] + +[Trailing delimiter | Leading delimiter: Content] + + aaa + bbb + [ + + ] + +[Trailing delimiter | Leading delimiter: Removal] + + aaa + bbb + [ + + ] + +[Domain] + + aaa +[--- + bbb + ---] + diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 8cb7c1f698..53e5b299db 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -13,8 +13,7 @@ import { assert } from "chai"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; -// fixme: Remove .only -suite.only("Scope test cases", async function () { +suite("Scope test cases", async function () { endToEndTestSetup(this); getScopeTestPaths().forEach(({ path, name, languageId, facetId }) => @@ -229,5 +228,8 @@ function getScope(facetId: string): ScopeType { if (facetId.endsWith("line")) { return { type: "line" }; } + if (facetId.endsWith("paragraph")) { + return { type: "paragraph" }; + } throw Error(`Unknown facetId ${facetId}`); } From c5d8fdb47c9a00ead4f6f57bce3a763bbb1c9d64 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 15:11:35 +0100 Subject: [PATCH 19/71] fix --- .../cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 53e5b299db..a929237e63 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -27,7 +27,7 @@ suite("Scope test cases", async function () { async function runTest(file: string, languageId: string, facetId: string) { const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; const scopeType = getScope(facetId); - const fixture = (await fsp.readFile(file)).toString(); + const fixture = (await fsp.readFile(file)).toString().replace(/\r\n/g, "\n"); const delimiterIndex = fixture.match(/\r?\n^---$/m)?.index; assert.ok( @@ -46,7 +46,7 @@ async function runTest(file: string, languageId: string, facetId: string) { scopeType, }); - const codeLines = code.split(/\r?\n/); + const codeLines = code.split("\n"); const outputFixture = [ ...codeLines, From 071e815fe6376ffa8a809e4e4488e467996677d1 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 15:18:47 +0100 Subject: [PATCH 20/71] try --- packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index a929237e63..3638f0ad7e 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -27,7 +27,7 @@ suite("Scope test cases", async function () { async function runTest(file: string, languageId: string, facetId: string) { const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; const scopeType = getScope(facetId); - const fixture = (await fsp.readFile(file)).toString().replace(/\r\n/g, "\n"); + const fixture = (await fsp.readFile(file, "utf8")).toString(); const delimiterIndex = fixture.match(/\r?\n^---$/m)?.index; assert.ok( From c6b8aaf1ab6a09c4915bb3df003bc62fa52cb931 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 15:27:49 +0100 Subject: [PATCH 21/71] fix --- .../cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 3638f0ad7e..75760ec0dd 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -27,7 +27,9 @@ suite("Scope test cases", async function () { async function runTest(file: string, languageId: string, facetId: string) { const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; const scopeType = getScope(facetId); - const fixture = (await fsp.readFile(file, "utf8")).toString(); + const fixture = (await fsp.readFile(file, "utf8")) + .toString() + .replaceAll("\r\n", "\n"); const delimiterIndex = fixture.match(/\r?\n^---$/m)?.index; assert.ok( From b756723044a7ac86728a87b4cf161280631e9cd3 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 15:57:49 +0100 Subject: [PATCH 22/71] New format --- .../scopes/javascript/assignment.name.scope | 14 +++++----- .../scopes/javascript/assignment.value.scope | 10 +++---- .../fixtures/scopes/javascript/function.scope | 6 ++--- .../fixtures/scopes/javascript/line.scope | 26 +++++++++---------- .../scopes/javascript/paragraph.scope | 18 ++++++------- .../javascript/tale.multiple.value.scope | 20 +++++++------- .../src/suite/scopes.vscode.test.ts | 17 ++++++++---- 7 files changed, 59 insertions(+), 52 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.scope index 1a99561c6c..f3ba99a0d1 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.scope @@ -3,28 +3,28 @@ const name = "Hello world"; [Content] const name = "Hello world"; - [----] + ^^^^ [Removal] const name = "Hello world"; -[-------------] + ^^^^^^^^^^^^^ [Leading delimiter: Content] const name = "Hello world"; - [-] + ^ [Leading delimiter: Removal] const name = "Hello world"; - [-] + ^ [Trailing delimiter: Content] const name = "Hello world"; - [-] + ^ [Trailing delimiter: Removal] const name = "Hello world"; - [-] + ^ [Domain] const name = "Hello world"; -[---------------------------] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.scope index c7a7984b7b..8b00d5a960 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.scope @@ -3,20 +3,20 @@ const name = "Hello world"; [Content] const name = "Hello world"; - [-------------] + ^^^^^^^^^^^^^ [Removal] const name = "Hello world"; - [----------------] + ^^^^^^^^^^^^^^^^ [Leading delimiter: Content] const name = "Hello world"; - [---] + ^^^ [Leading delimiter: Removal] const name = "Hello world"; - [---] + ^^^ [Domain] const name = "Hello world"; -[---------------------------] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope index 082c644e5f..a8b6e53c85 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope @@ -4,22 +4,22 @@ function myFunk() { --- [Content] - function myFunk() { [------------------- + function myFunk() { } -] [Removal] - function myFunk() { [------------------- + function myFunk() { } -] [Domain] - function myFunk() { [------------------- + function myFunk() { } -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope index a0a50152fe..65ab199357 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope @@ -10,22 +10,22 @@ aaa [#1 Removal] - [ + aaa ] [#1 Trailing delimiter: Content] - [ + aaa ] [#1 Trailing delimiter: Removal] - [ + aaa ] @@ -39,48 +39,48 @@ aaa [#2 Content] aaa -[---] + ^^^ [#2 Removal] - aaa [--- + aaa ] [#2 Leading delimiter: Content] - [ + aaa ] [#2 Leading delimiter: Removal] - [ + aaa ] [#2 Trailing delimiter: Content] - aaa [ + aaa ] [#2 Trailing delimiter: Removal] - aaa [ + aaa ] [#2 Domain] aaa -[---] + ^^^ [#3 Content] @@ -91,22 +91,22 @@ aaa [#3 Removal] - aaa [ + aaa ] [#3 Leading delimiter: Content] - aaa [ + aaa ] [#3 Leading delimiter: Removal] - aaa [ + aaa ] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope index 9c61063939..142dc82096 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope @@ -6,15 +6,15 @@ bbb [Content] - aaa [--- + aaa bbb ---] [Removal] - [ + aaa bbb @@ -28,24 +28,24 @@ bbb [Leading delimiter: Removal] - [ + aaa ] bbb [Leading delimiter | Trailing delimiter: Content] - [ + aaa ] bbb [Leading delimiter | Trailing delimiter: Removal] - [ + aaa ] bbb @@ -61,31 +61,31 @@ bbb [Trailing delimiter: Removal] aaa - bbb [ + bbb ] [Trailing delimiter | Leading delimiter: Content] aaa - bbb [ + bbb ] [Trailing delimiter | Leading delimiter: Removal] aaa - bbb [ + bbb ] [Domain] - aaa [--- + aaa bbb ---] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope index a529d23b29..6778a7e0df 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope @@ -4,50 +4,50 @@ const value = 2; [#1 Content] const name = "Hello world"; - [-------------] + ^^^^^^^^^^^^^ const value = 2; [#1 Removal] const name = "Hello world"; - [----------------] + ^^^^^^^^^^^^^^^^ const value = 2; [#1 Leading delimiter: Content] const name = "Hello world"; - [---] + ^^^ const value = 2; [#1 Leading delimiter: Removal] const name = "Hello world"; - [---] + ^^^ const value = 2; [#1 Domain] const name = "Hello world"; -[---------------------------] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ const value = 2; [#2 Content] const name = "Hello world"; const value = 2; - [-] + ^ [#2 Removal] const name = "Hello world"; const value = 2; - [----] + ^^^^ [#2 Leading delimiter: Content] const name = "Hello world"; const value = 2; - [---] + ^^^ [#2 Leading delimiter: Removal] const name = "Hello world"; const value = 2; - [---] + ^^^ [#2 Domain] const name = "Hello world"; const value = 2; -[----------------] + ^^^^^^^^^^^^^^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 75760ec0dd..e65efda839 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -181,15 +181,21 @@ function serializeHeader( const lines: string[] = ["", `[${fullHeader}]`]; codeLines.forEach((codeLine, index) => { - lines.push(" " + codeLine); + const fullCodeLine = " " + codeLine; + if (index === start.line) { if (range.isSingleLine) { + lines.push(fullCodeLine); lines.push(serializeRange(start, end)); } else { lines.push(serializeStartRange(start, codeLine.length)); + lines.push(fullCodeLine); } } else if (index === end.line) { + lines.push(fullCodeLine); lines.push(serializeEndRange(end)); + } else { + lines.push(fullCodeLine); } }); @@ -197,11 +203,12 @@ function serializeHeader( } function serializeRange(start: Position, end: Position): string { + if (start.isEqual(end)) { + return [new Array(start.character + 1).join(" "), "[]"].join(""); + } return [ - new Array(start.character + 1).join(" "), - "[", - new Array(end.character - start.character + 1).join("-"), - "]", + new Array(start.character + 2).join(" "), + new Array(end.character - start.character + 1).join("^"), ].join(""); } From 9965927e89913042f811c67809b352dd63b7b4db Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 17:23:21 +0100 Subject: [PATCH 23/71] Added facets --- packages/common/src/facets.ts | 131 ++++++++++++++++++ packages/common/src/index.ts | 1 + ...nment.name.scope => name.assignment.scope} | 0 .../{function.scope => namedFunction.scope} | 0 .../javascript/tale.multiple.value.scope | 53 ------- ...ent.value.scope => value.assignment.scope} | 0 .../{javascript => plaintext}/line.scope | 0 .../{javascript => plaintext}/paragraph.scope | 0 .../src/suite/scopes.vscode.test.ts | 62 ++++++--- 9 files changed, 175 insertions(+), 72 deletions(-) create mode 100644 packages/common/src/facets.ts rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/{assignment.name.scope => name.assignment.scope} (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/{function.scope => namedFunction.scope} (100%) delete mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/{assignment.value.scope => value.assignment.scope} (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{javascript => plaintext}/line.scope (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{javascript => plaintext}/paragraph.scope (100%) diff --git a/packages/common/src/facets.ts b/packages/common/src/facets.ts new file mode 100644 index 0000000000..d725796c46 --- /dev/null +++ b/packages/common/src/facets.ts @@ -0,0 +1,131 @@ +import { SimpleScopeTypeType } from "."; + +const scopeSupportFacets = [ + // "list", + // "list.interior", + // "map", + // "map.interior", + // "collectionKey", + "namedFunction", + // "namedFunction.interior", + // "functionName", + // "anonymousFunction", + // "anonymousFunction.interior", + "name.assignment", + "value.assignment", + // "value.assignment.removal", + // "value.return", + // "value.return.removal", + // "value.collectionItem", + // "value.collectionItem.removal", + // "statement", + // "ifStatement", + // "condition.if", + // "condition.while", + // "condition.doWhile", + // "condition.for", + // "condition.ternary", + // "branch", + // "comment.line", + // "comment.block", + // "string.singleLine", + // "string.multiLine", + // "textFragment", + // "functionCall", + // "functionCallee", + // "argumentOrParameter.argument", + // "argumentOrParameter.argument.removal", + // "argumentOrParameter.parameter", + // "argumentOrParameter.parameter.removal", + // "class", + // "class.interior", + // "className", + // "type", +] as const; + +const textualScopeSupportFacets = ["line", "paragraph"] as const; + +export type ScopeSupportFacet = (typeof scopeSupportFacets)[number]; +export type TextualScopeSupportFacet = + (typeof textualScopeSupportFacets)[number]; + +export interface ScopeSupportFacetInfo { + label: string; + description: string; + scopeType: SimpleScopeTypeType; + examples: string[]; +} + +export const scopeSupportFacetInfos: Record< + ScopeSupportFacet, + ScopeSupportFacetInfo +> = { + namedFunction: { + label: "Named function", + description: "A named function", + scopeType: "namedFunction", + examples: ["function foo() {}", "const foo = () => {}"], + }, + ["name.assignment"]: { + label: "Assignment name", + description: "Name(LHS) of an assignment", + scopeType: "name", + examples: ["const foo = 1"], + }, + ["value.assignment"]: { + label: "Assignment value", + description: "Value(RHS) of an assignment", + scopeType: "value", + examples: ["const foo = 1"], + }, + // list: { + // label: "List", + // description: "A list of items", + // scopeType: "list", + // }, + // "list.interior": { + // label: "List interior", + // description: "Excludes the opening and closing delimiters of the list", + // scopeType: "list", + // }, + // map: { + // label: "Map", + // description: "A map of key-value pairs", + // scopeType: "map", + // }, + // "map.interior": { + // label: "Map interior", + // description: "Excludes the opening and closing delimiters of the map", + // scopeType: "map", + // }, +}; + +export const textualScopeSupportFacetInfos: Record< + TextualScopeSupportFacet, + ScopeSupportFacetInfo +> = { + line: { + label: "Line", + description: "A single line in the document", + scopeType: "line", + examples: ["foo"], + }, + paragraph: { + label: "Paragraph", + description: + "A single paragraph(contiguous block of lines) in the document", + scopeType: "paragraph", + examples: ["foo\nbar"], + }, +}; + +export enum ScopeSupportFacetLevel { + supported, + unsupported, + notApplicable, +} + +export type LanguageScopeSupportFacetMap = Record< + ScopeSupportFacet, + ScopeSupportFacetLevel +>; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index cb0d911db0..ea1a30aedb 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -93,3 +93,4 @@ export * from "./types/TestCaseFixture"; export * from "./util/getEnvironmentVariableStrict"; export * from "./util/CompositeKeyDefaultMap"; export * from "./util/toPlainObject"; +export * from "./facets"; diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.name.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/function.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope deleted file mode 100644 index 6778a7e0df..0000000000 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/tale.multiple.value.scope +++ /dev/null @@ -1,53 +0,0 @@ -const name = "Hello world"; -const value = 2; ---- - -[#1 Content] - const name = "Hello world"; - ^^^^^^^^^^^^^ - const value = 2; - -[#1 Removal] - const name = "Hello world"; - ^^^^^^^^^^^^^^^^ - const value = 2; - -[#1 Leading delimiter: Content] - const name = "Hello world"; - ^^^ - const value = 2; - -[#1 Leading delimiter: Removal] - const name = "Hello world"; - ^^^ - const value = 2; - -[#1 Domain] - const name = "Hello world"; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - const value = 2; - -[#2 Content] - const name = "Hello world"; - const value = 2; - ^ - -[#2 Removal] - const name = "Hello world"; - const value = 2; - ^^^^ - -[#2 Leading delimiter: Content] - const name = "Hello world"; - const value = 2; - ^^^ - -[#2 Leading delimiter: Removal] - const name = "Hello world"; - const value = 2; - ^^^ - -[#2 Domain] - const name = "Hello world"; - const value = 2; - ^^^^^^^^^^^^^^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/assignment.value.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/line.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/paragraph.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index e65efda839..3ac217e929 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -1,22 +1,45 @@ import { asyncSafety, + getLanguageScopeSupport, getScopeTestPaths, Position, Range, ScopeRanges, + ScopeSupportFacet, + scopeSupportFacetInfos, ScopeType, shouldUpdateFixtures, TargetRanges, + TextualScopeSupportFacet, + textualScopeSupportFacetInfos, } from "@cursorless/common"; import { getCursorlessApi, openNewEditor } from "@cursorless/vscode-common"; import { assert } from "chai"; +import { groupBy } from "lodash"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; -suite("Scope test cases", async function () { +suite.only("Scope test cases", async function () { endToEndTestSetup(this); - getScopeTestPaths().forEach(({ path, name, languageId, facetId }) => + const testPaths = getScopeTestPaths(); + const languages = groupBy(testPaths, (test) => test.languageId); + + if (!shouldUpdateFixtures()) { + Object.entries(languages).forEach(([languageId, testPaths]) => + test( + languageId, + asyncSafety(() => + testLanguageSupport( + languageId, + testPaths.map((test) => test.facetId), + ), + ), + ), + ); + } + + testPaths.forEach(({ path, name, languageId, facetId }) => test( name, asyncSafety(() => runTest(path, languageId, facetId)), @@ -24,9 +47,17 @@ suite("Scope test cases", async function () { ); }); +async function testLanguageSupport(languageId: string, facetIds: string[]) { + console.log(languageId); + console.log(facetIds); + const scopeSupport = getLanguageScopeSupport(languageId); + + assert.isTrue(scopeSupport != null, "Missing scope support"); +} + async function runTest(file: string, languageId: string, facetId: string) { const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; - const scopeType = getScope(facetId); + const scopeType = getScopeType(facetId); const fixture = (await fsp.readFile(file, "utf8")) .toString() .replaceAll("\r\n", "\n"); @@ -175,7 +206,6 @@ function serializeHeader( parts.push(prefix.join(" | ") + ":"); } parts.push(header); - return parts.join(" "); })(); const lines: string[] = ["", `[${fullHeader}]`]; @@ -224,21 +254,15 @@ function serializeEndRange(end: Position): string { return [" ", new Array(end.character + 1).join("-"), "]"].join(""); } -function getScope(facetId: string): ScopeType { - if (facetId.endsWith(".name")) { - return { type: "name" }; - } - if (facetId.endsWith(".value")) { - return { type: "value" }; - } - if (facetId.endsWith("function")) { - return { type: "namedFunction" }; - } - if (facetId.endsWith("line")) { - return { type: "line" }; +function getScopeType(facetId: string): ScopeType { + if (facetId in textualScopeSupportFacetInfos) { + const { scopeType } = + textualScopeSupportFacetInfos[facetId as TextualScopeSupportFacet]; + return { type: scopeType }; } - if (facetId.endsWith("paragraph")) { - return { type: "paragraph" }; + if (facetId in scopeSupportFacetInfos) { + const { scopeType } = scopeSupportFacetInfos[facetId as ScopeSupportFacet]; + return { type: scopeType }; } - throw Error(`Unknown facetId ${facetId}`); + throw Error(`Unknown facetId '${facetId}'`); } From 5e76ff088e38636fb0c3b6727c4e629917507df4 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 17:35:49 +0100 Subject: [PATCH 24/71] update --- .../src/suite/scopes.vscode.test.ts | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 3ac217e929..ceff48fa41 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -1,6 +1,5 @@ import { asyncSafety, - getLanguageScopeSupport, getScopeTestPaths, Position, Range, @@ -15,31 +14,13 @@ import { } from "@cursorless/common"; import { getCursorlessApi, openNewEditor } from "@cursorless/vscode-common"; import { assert } from "chai"; -import { groupBy } from "lodash"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; -suite.only("Scope test cases", async function () { +suite("Scope test cases", async function () { endToEndTestSetup(this); - const testPaths = getScopeTestPaths(); - const languages = groupBy(testPaths, (test) => test.languageId); - - if (!shouldUpdateFixtures()) { - Object.entries(languages).forEach(([languageId, testPaths]) => - test( - languageId, - asyncSafety(() => - testLanguageSupport( - languageId, - testPaths.map((test) => test.facetId), - ), - ), - ), - ); - } - - testPaths.forEach(({ path, name, languageId, facetId }) => + getScopeTestPaths().forEach(({ path, name, languageId, facetId }) => test( name, asyncSafety(() => runTest(path, languageId, facetId)), @@ -47,14 +28,6 @@ suite.only("Scope test cases", async function () { ); }); -async function testLanguageSupport(languageId: string, facetIds: string[]) { - console.log(languageId); - console.log(facetIds); - const scopeSupport = getLanguageScopeSupport(languageId); - - assert.isTrue(scopeSupport != null, "Missing scope support"); -} - async function runTest(file: string, languageId: string, facetId: string) { const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; const scopeType = getScopeType(facetId); From 1995cde235f355d4ca8a43c07657cdcbce597dee Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 22 Nov 2023 18:33:59 +0100 Subject: [PATCH 25/71] Added language specific scope support facets --- packages/common/src/index.ts | 3 +- .../getLanguageScopeSupport.ts | 20 +++++++ .../src/scopeSupportFacets/javascript.ts | 12 +++++ .../src/scopeSupportFacets/plaintext.ts | 11 ++++ .../scopeSupportFacets.ts} | 7 ++- .../common/src/testUtil/getFixturePaths.ts | 2 +- .../src/suite/scopes.vscode.test.ts | 52 ++++++++++++++++++- .../src/constructTestHelpers.ts | 6 +++ packages/cursorless-vscode/src/extension.ts | 2 + packages/vscode-common/src/TestHelpers.ts | 6 +++ 10 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts create mode 100644 packages/common/src/scopeSupportFacets/javascript.ts create mode 100644 packages/common/src/scopeSupportFacets/plaintext.ts rename packages/common/src/{facets.ts => scopeSupportFacets/scopeSupportFacets.ts} (95%) diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index ea1a30aedb..d38f9a83bd 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -93,4 +93,5 @@ export * from "./types/TestCaseFixture"; export * from "./util/getEnvironmentVariableStrict"; export * from "./util/CompositeKeyDefaultMap"; export * from "./util/toPlainObject"; -export * from "./facets"; +export * from "./scopeSupportFacets/scopeSupportFacets"; +export * from "./scopeSupportFacets/getLanguageScopeSupport"; diff --git a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts new file mode 100644 index 0000000000..3dd176d2a3 --- /dev/null +++ b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts @@ -0,0 +1,20 @@ +import { javascriptSupport } from "./javascript"; +import { plaintextSupport } from "./plaintext"; +import { + LanguageScopeSupportFacetMap, + TextualLanguageScopeSupportFacetMap, +} from "./scopeSupportFacets"; + + + +export function getLanguageScopeSupport( + languageId: string, +): TextualLanguageScopeSupportFacetMap | LanguageScopeSupportFacetMap { + switch (languageId) { + case "plaintext": + return plaintextSupport; + case "javascript": + return javascriptSupport; + } + throw Error(`Unsupported language: '${languageId}'`); +} diff --git a/packages/common/src/scopeSupportFacets/javascript.ts b/packages/common/src/scopeSupportFacets/javascript.ts new file mode 100644 index 0000000000..948b3dd688 --- /dev/null +++ b/packages/common/src/scopeSupportFacets/javascript.ts @@ -0,0 +1,12 @@ +import { + LanguageScopeSupportFacetMap, + ScopeSupportFacetLevel, +} from "@cursorless/common"; + +const { supported } = ScopeSupportFacetLevel; + +export const javascriptSupport: LanguageScopeSupportFacetMap = { + namedFunction: supported, + ["name.assignment"]: supported, + ["value.assignment"]: supported, +}; diff --git a/packages/common/src/scopeSupportFacets/plaintext.ts b/packages/common/src/scopeSupportFacets/plaintext.ts new file mode 100644 index 0000000000..94e5e549e3 --- /dev/null +++ b/packages/common/src/scopeSupportFacets/plaintext.ts @@ -0,0 +1,11 @@ +import { + ScopeSupportFacetLevel, + TextualLanguageScopeSupportFacetMap, +} from "@cursorless/common"; + +const { supported } = ScopeSupportFacetLevel; + +export const plaintextSupport: TextualLanguageScopeSupportFacetMap = { + line: supported, + paragraph: supported, +}; diff --git a/packages/common/src/facets.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts similarity index 95% rename from packages/common/src/facets.ts rename to packages/common/src/scopeSupportFacets/scopeSupportFacets.ts index d725796c46..202555fb16 100644 --- a/packages/common/src/facets.ts +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts @@ -1,4 +1,4 @@ -import { SimpleScopeTypeType } from "."; +import { SimpleScopeTypeType } from ".."; const scopeSupportFacets = [ // "list", @@ -129,3 +129,8 @@ export type LanguageScopeSupportFacetMap = Record< ScopeSupportFacet, ScopeSupportFacetLevel >; + +export type TextualLanguageScopeSupportFacetMap = Record< + TextualScopeSupportFacet, + ScopeSupportFacetLevel +>; diff --git a/packages/common/src/testUtil/getFixturePaths.ts b/packages/common/src/testUtil/getFixturePaths.ts index 6584baf4e2..b5f52eb075 100644 --- a/packages/common/src/testUtil/getFixturePaths.ts +++ b/packages/common/src/testUtil/getFixturePaths.ts @@ -47,6 +47,6 @@ export function getScopeTestPaths() { path: p, name: path.relative(relativeDir, p.substring(0, p.lastIndexOf("."))), languageId: path.dirname(path.relative(directory, p)), - facetId: path.basename(p.substring(0, p.lastIndexOf("."))), + facet: path.basename(p.substring(0, p.lastIndexOf("."))), })); } diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index ceff48fa41..e1ff801231 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -6,6 +6,7 @@ import { ScopeRanges, ScopeSupportFacet, scopeSupportFacetInfos, + ScopeSupportFacetLevel, ScopeType, shouldUpdateFixtures, TargetRanges, @@ -14,20 +15,67 @@ import { } from "@cursorless/common"; import { getCursorlessApi, openNewEditor } from "@cursorless/vscode-common"; import { assert } from "chai"; +import { groupBy } from "lodash"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; suite("Scope test cases", async function () { endToEndTestSetup(this); - getScopeTestPaths().forEach(({ path, name, languageId, facetId }) => + const testPaths = getScopeTestPaths(); + const languages = groupBy(testPaths, (test) => test.languageId); + + if (!shouldUpdateFixtures()) { + Object.entries(languages).forEach(([languageId, testPaths]) => + test( + languageId, + asyncSafety(() => + testLanguageSupport( + languageId, + testPaths.map((test) => test.facet), + ), + ), + ), + ); + } + + testPaths.forEach(({ path, name, languageId, facet }) => test( name, - asyncSafety(() => runTest(path, languageId, facetId)), + asyncSafety(() => runTest(path, languageId, facet)), ), ); }); +async function testLanguageSupport(languageId: string, testedFacets: string[]) { + const { getLanguageScopeSupport } = (await getCursorlessApi()).testHelpers!; + + const scopeSupport: Record = + getLanguageScopeSupport(languageId); + + if (scopeSupport == null) { + assert.fail(`Missing scope support for language '${languageId}'`); + } + + const supportedFacets = Object.keys(scopeSupport).filter( + (facet) => scopeSupport[facet] === ScopeSupportFacetLevel.supported, + ); + + // Assert that all tested facets are supported by the language + for (const testedFacet of testedFacets) { + if (!supportedFacets.includes(testedFacet)) { + assert.fail(`Missing scope support for tested facet '${testedFacet}'`); + } + } + + // Assert that all supported facets are tested + for (const supportedFacet of supportedFacets) { + if (!testedFacets.includes(supportedFacet)) { + assert.fail(`Missing test for scope support facet '${supportedFacet}'`); + } + } +} + async function runTest(file: string, languageId: string, facetId: string) { const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; const scopeType = getScopeType(facetId); diff --git a/packages/cursorless-vscode/src/constructTestHelpers.ts b/packages/cursorless-vscode/src/constructTestHelpers.ts index 106a131386..7fce834837 100644 --- a/packages/cursorless-vscode/src/constructTestHelpers.ts +++ b/packages/cursorless-vscode/src/constructTestHelpers.ts @@ -4,12 +4,14 @@ import { ExtraSnapshotField, HatTokenMap, IDE, + LanguageScopeSupportFacetMap, NormalizedIDE, ScopeProvider, SerializedMarks, TargetPlainObject, TestCaseSnapshot, TextEditor, + TextualLanguageScopeSupportFacetMap, } from "@cursorless/common"; import { StoredTargetKey, @@ -33,12 +35,16 @@ export function constructTestHelpers( scopeProvider: ScopeProvider, injectIde: (ide: IDE) => void, runIntegrationTests: () => Promise, + getLanguageScopeSupport: ( + languageId: string, + ) => TextualLanguageScopeSupportFacetMap | LanguageScopeSupportFacetMap, ): TestHelpers | undefined { return { commandServerApi: commandServerApi!, ide: normalizedIde, injectIde, scopeProvider, + getLanguageScopeSupport, toVscodeEditor, diff --git a/packages/cursorless-vscode/src/extension.ts b/packages/cursorless-vscode/src/extension.ts index 0fc0096262..728f7b8e4f 100644 --- a/packages/cursorless-vscode/src/extension.ts +++ b/packages/cursorless-vscode/src/extension.ts @@ -2,6 +2,7 @@ import { Disposable, FakeIDE, getFakeCommandServerApi, + getLanguageScopeSupport, IDE, isTesting, NormalizedIDE, @@ -142,6 +143,7 @@ export async function activate( scopeProvider, injectIde, runIntegrationTests, + getLanguageScopeSupport, ) : undefined, diff --git a/packages/vscode-common/src/TestHelpers.ts b/packages/vscode-common/src/TestHelpers.ts index 467c8d2782..fb61376b18 100644 --- a/packages/vscode-common/src/TestHelpers.ts +++ b/packages/vscode-common/src/TestHelpers.ts @@ -4,12 +4,14 @@ import type { ExtraSnapshotField, HatTokenMap, IDE, + LanguageScopeSupportFacetMap, NormalizedIDE, ScopeProvider, SerializedMarks, TargetPlainObject, TestCaseSnapshot, TextEditor, + TextualLanguageScopeSupportFacetMap, } from "@cursorless/common"; import * as vscode from "vscode"; import { VscodeApi } from "./VscodeApi"; @@ -51,4 +53,8 @@ export interface TestHelpers { * A thin wrapper around the VSCode API that allows us to mock it for testing. */ vscodeApi: VscodeApi; + + getLanguageScopeSupport: ( + languageId: string, + ) => TextualLanguageScopeSupportFacetMap | LanguageScopeSupportFacetMap; } From b93893e2dfb9fccb4cf745ccac996ab3cf719286 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Wed, 22 Nov 2023 17:35:32 +0000 Subject: [PATCH 26/71] [pre-commit.ci lite] apply automatic fixes --- .../common/src/scopeSupportFacets/getLanguageScopeSupport.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts index 3dd176d2a3..a4379d5f12 100644 --- a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts +++ b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts @@ -5,8 +5,6 @@ import { TextualLanguageScopeSupportFacetMap, } from "./scopeSupportFacets"; - - export function getLanguageScopeSupport( languageId: string, ): TextualLanguageScopeSupportFacetMap | LanguageScopeSupportFacetMap { From f45a753bd777b9f251b43d982da1c38f33f72f36 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 23 Nov 2023 02:16:11 +0100 Subject: [PATCH 27/71] clean up --- .../cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 3 +-- packages/cursorless-vscode/src/constructTestHelpers.ts | 4 ---- packages/cursorless-vscode/src/extension.ts | 2 -- packages/vscode-common/src/TestHelpers.ts | 4 ---- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index e1ff801231..c88c2082c0 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -1,5 +1,6 @@ import { asyncSafety, + getLanguageScopeSupport, getScopeTestPaths, Position, Range, @@ -48,8 +49,6 @@ suite("Scope test cases", async function () { }); async function testLanguageSupport(languageId: string, testedFacets: string[]) { - const { getLanguageScopeSupport } = (await getCursorlessApi()).testHelpers!; - const scopeSupport: Record = getLanguageScopeSupport(languageId); diff --git a/packages/cursorless-vscode/src/constructTestHelpers.ts b/packages/cursorless-vscode/src/constructTestHelpers.ts index 7fce834837..d2d19cb85e 100644 --- a/packages/cursorless-vscode/src/constructTestHelpers.ts +++ b/packages/cursorless-vscode/src/constructTestHelpers.ts @@ -35,16 +35,12 @@ export function constructTestHelpers( scopeProvider: ScopeProvider, injectIde: (ide: IDE) => void, runIntegrationTests: () => Promise, - getLanguageScopeSupport: ( - languageId: string, - ) => TextualLanguageScopeSupportFacetMap | LanguageScopeSupportFacetMap, ): TestHelpers | undefined { return { commandServerApi: commandServerApi!, ide: normalizedIde, injectIde, scopeProvider, - getLanguageScopeSupport, toVscodeEditor, diff --git a/packages/cursorless-vscode/src/extension.ts b/packages/cursorless-vscode/src/extension.ts index 728f7b8e4f..0fc0096262 100644 --- a/packages/cursorless-vscode/src/extension.ts +++ b/packages/cursorless-vscode/src/extension.ts @@ -2,7 +2,6 @@ import { Disposable, FakeIDE, getFakeCommandServerApi, - getLanguageScopeSupport, IDE, isTesting, NormalizedIDE, @@ -143,7 +142,6 @@ export async function activate( scopeProvider, injectIde, runIntegrationTests, - getLanguageScopeSupport, ) : undefined, diff --git a/packages/vscode-common/src/TestHelpers.ts b/packages/vscode-common/src/TestHelpers.ts index fb61376b18..37d76d03d9 100644 --- a/packages/vscode-common/src/TestHelpers.ts +++ b/packages/vscode-common/src/TestHelpers.ts @@ -53,8 +53,4 @@ export interface TestHelpers { * A thin wrapper around the VSCode API that allows us to mock it for testing. */ vscodeApi: VscodeApi; - - getLanguageScopeSupport: ( - languageId: string, - ) => TextualLanguageScopeSupportFacetMap | LanguageScopeSupportFacetMap; } From d5d4c2851f43f82c169b3390fc36a6e144ef04d9 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 23 Nov 2023 02:16:55 +0100 Subject: [PATCH 28/71] clean up --- packages/cursorless-vscode/src/constructTestHelpers.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/cursorless-vscode/src/constructTestHelpers.ts b/packages/cursorless-vscode/src/constructTestHelpers.ts index d2d19cb85e..106a131386 100644 --- a/packages/cursorless-vscode/src/constructTestHelpers.ts +++ b/packages/cursorless-vscode/src/constructTestHelpers.ts @@ -4,14 +4,12 @@ import { ExtraSnapshotField, HatTokenMap, IDE, - LanguageScopeSupportFacetMap, NormalizedIDE, ScopeProvider, SerializedMarks, TargetPlainObject, TestCaseSnapshot, TextEditor, - TextualLanguageScopeSupportFacetMap, } from "@cursorless/common"; import { StoredTargetKey, From 473a0849b4d60b7618689aa3ab8809c032a45c9c Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 23 Nov 2023 02:17:17 +0100 Subject: [PATCH 29/71] cleanup --- packages/vscode-common/src/TestHelpers.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/vscode-common/src/TestHelpers.ts b/packages/vscode-common/src/TestHelpers.ts index 37d76d03d9..467c8d2782 100644 --- a/packages/vscode-common/src/TestHelpers.ts +++ b/packages/vscode-common/src/TestHelpers.ts @@ -4,14 +4,12 @@ import type { ExtraSnapshotField, HatTokenMap, IDE, - LanguageScopeSupportFacetMap, NormalizedIDE, ScopeProvider, SerializedMarks, TargetPlainObject, TestCaseSnapshot, TextEditor, - TextualLanguageScopeSupportFacetMap, } from "@cursorless/common"; import * as vscode from "vscode"; import { VscodeApi } from "./VscodeApi"; From ee9fa800964c7c0870663cd8903d1734d9f548c6 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 23 Nov 2023 02:32:13 +0100 Subject: [PATCH 30/71] Improve fail message --- .../src/suite/scopes.vscode.test.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index c88c2082c0..0561189b4a 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -61,17 +61,21 @@ async function testLanguageSupport(languageId: string, testedFacets: string[]) { ); // Assert that all tested facets are supported by the language - for (const testedFacet of testedFacets) { - if (!supportedFacets.includes(testedFacet)) { - assert.fail(`Missing scope support for tested facet '${testedFacet}'`); - } + const unsupportedFacets = testedFacets.filter( + (testedFacet) => !supportedFacets.includes(testedFacet), + ); + if (unsupportedFacets.length > 0) { + const values = unsupportedFacets.join(", "); + assert.fail(`Missing scope support for tested facets [${values}]`); } // Assert that all supported facets are tested - for (const supportedFacet of supportedFacets) { - if (!testedFacets.includes(supportedFacet)) { - assert.fail(`Missing test for scope support facet '${supportedFacet}'`); - } + const untestedFacets = supportedFacets.filter( + (supportedFacet) => !testedFacets.includes(supportedFacet), + ); + if (untestedFacets.length > 0) { + const values = untestedFacets.join(", "); + assert.fail(`Missing test for scope support facets [${values}]`); } } From 2f8dfa2e414bc222388b95da2f1bc17d74687639 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 23 Nov 2023 02:53:11 +0100 Subject: [PATCH 31/71] Support fixture numbers --- .../common/src/testUtil/getFixturePaths.ts | 2 +- .../fixtures/scopes/plaintext/line.scope | 111 +---------------- .../fixtures/scopes/plaintext/line2.scope | 117 ++++++++++++++++++ 3 files changed, 122 insertions(+), 108 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope diff --git a/packages/common/src/testUtil/getFixturePaths.ts b/packages/common/src/testUtil/getFixturePaths.ts index b5f52eb075..a71b59c9b4 100644 --- a/packages/common/src/testUtil/getFixturePaths.ts +++ b/packages/common/src/testUtil/getFixturePaths.ts @@ -47,6 +47,6 @@ export function getScopeTestPaths() { path: p, name: path.relative(relativeDir, p.substring(0, p.lastIndexOf("."))), languageId: path.dirname(path.relative(directory, p)), - facet: path.basename(p.substring(0, p.lastIndexOf("."))), + facet: path.basename(p).match(/([a-zA-Z.]+)\d*\.scope/)![1], })); } diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope index 65ab199357..84f95cdb1f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope @@ -1,117 +1,14 @@ - aaa - --- -[#1 Content] - -[] - aaa - - -[#1 Removal] -[ - - aaa - ] - - -[#1 Trailing delimiter: Content] -[ - - aaa - ] - - -[#1 Trailing delimiter: Removal] -[ - - aaa - ] - - -[#1 Domain] - -[] - aaa - - -[#2 Content] - +[Content] aaa ^^^ - - -[#2 Removal] - -[--- - aaa - - ] - -[#2 Leading delimiter: Content] -[ - - aaa - ] - -[#2 Leading delimiter: Removal] -[ - - aaa - ] - - -[#2 Trailing delimiter: Content] - - [ - aaa - - ] - -[#2 Trailing delimiter: Removal] - - [ - aaa - - ] - -[#2 Domain] - +[Removal] aaa ^^^ - - -[#3 Content] - - aaa - -[] -[#3 Removal] - - [ +[Domain] aaa - - ] - -[#3 Leading delimiter: Content] - - [ - aaa - - ] - -[#3 Leading delimiter: Removal] - - [ - aaa - - ] - -[#3 Domain] - - aaa - -[] + ^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope new file mode 100644 index 0000000000..65ab199357 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -0,0 +1,117 @@ + +aaa + +--- + +[#1 Content] + +[] + aaa + + +[#1 Removal] +[ + + aaa + ] + + +[#1 Trailing delimiter: Content] +[ + + aaa + ] + + +[#1 Trailing delimiter: Removal] +[ + + aaa + ] + + +[#1 Domain] + +[] + aaa + + +[#2 Content] + + aaa + ^^^ + + +[#2 Removal] + +[--- + aaa + + ] + +[#2 Leading delimiter: Content] +[ + + aaa + ] + + +[#2 Leading delimiter: Removal] +[ + + aaa + ] + + +[#2 Trailing delimiter: Content] + + [ + aaa + + ] + +[#2 Trailing delimiter: Removal] + + [ + aaa + + ] + +[#2 Domain] + + aaa + ^^^ + + +[#3 Content] + + aaa + +[] + +[#3 Removal] + + [ + aaa + + ] + +[#3 Leading delimiter: Content] + + [ + aaa + + ] + +[#3 Leading delimiter: Removal] + + [ + aaa + + ] + +[#3 Domain] + + aaa + +[] From bf70406115d3df9db7cdc7497df7373c2d432121 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 23 Nov 2023 03:36:17 +0100 Subject: [PATCH 32/71] Made format more compact --- .../scopes/javascript/name.assignment.scope | 6 - .../scopes/javascript/namedFunction.scope | 12 -- .../scopes/javascript/value.assignment.scope | 3 - .../fixtures/scopes/plaintext/line.scope | 6 - .../fixtures/scopes/plaintext/line2.scope | 45 +------- .../fixtures/scopes/plaintext/paragraph.scope | 23 +--- .../src/suite/scopes.vscode.test.ts | 106 +++++++++++++----- 7 files changed, 81 insertions(+), 120 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope index f3ba99a0d1..0ac98ff79f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope @@ -10,17 +10,11 @@ const name = "Hello world"; ^^^^^^^^^^^^^ [Leading delimiter: Content] - const name = "Hello world"; - ^ - [Leading delimiter: Removal] const name = "Hello world"; ^ [Trailing delimiter: Content] - const name = "Hello world"; - ^ - [Trailing delimiter: Removal] const name = "Hello world"; ^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope index a8b6e53c85..0f9817302a 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope @@ -4,19 +4,7 @@ function myFunk() { --- [Content] -[------------------- - function myFunk() { - - } - -] - [Removal] -[------------------- - function myFunk() { - - } - -] - [Domain] [------------------- function myFunk() { diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope index 8b00d5a960..6ebe392473 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope @@ -10,9 +10,6 @@ const name = "Hello world"; ^^^^^^^^^^^^^^^^ [Leading delimiter: Content] - const name = "Hello world"; - ^^^ - [Leading delimiter: Removal] const name = "Hello world"; ^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope index 84f95cdb1f..3b2e8d06cd 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope @@ -2,13 +2,7 @@ aaa --- [Content] - aaa - ^^^ - [Removal] - aaa - ^^^ - [Domain] aaa ^^^ diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope index 65ab199357..8f83734228 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -4,6 +4,7 @@ aaa --- [#1 Content] +[#1 Domain] [] aaa @@ -17,12 +18,6 @@ aaa [#1 Trailing delimiter: Content] -[ - - aaa - ] - - [#1 Trailing delimiter: Removal] [ @@ -30,13 +25,8 @@ aaa ] -[#1 Domain] - -[] - aaa - - [#2 Content] +[#2 Domain] aaa ^^^ @@ -50,12 +40,6 @@ aaa ] [#2 Leading delimiter: Content] -[ - - aaa - ] - - [#2 Leading delimiter: Removal] [ @@ -64,12 +48,6 @@ aaa [#2 Trailing delimiter: Content] - - [ - aaa - - ] - [#2 Trailing delimiter: Removal] [ @@ -77,13 +55,8 @@ aaa ] -[#2 Domain] - - aaa - ^^^ - - [#3 Content] +[#3 Domain] aaa @@ -97,21 +70,9 @@ aaa ] [#3 Leading delimiter: Content] - - [ - aaa - - ] - [#3 Leading delimiter: Removal] [ aaa ] - -[#3 Domain] - - aaa - -[] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope index 142dc82096..741110e93d 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope @@ -5,6 +5,7 @@ bbb --- [Content] +[Domain] [--- aaa @@ -36,13 +37,6 @@ bbb [Leading delimiter | Trailing delimiter: Content] -[ - - aaa - ] - bbb - - [Leading delimiter | Trailing delimiter: Removal] [ @@ -67,13 +61,6 @@ bbb ] [Trailing delimiter | Leading delimiter: Content] - - aaa - [ - bbb - - ] - [Trailing delimiter | Leading delimiter: Removal] aaa @@ -81,11 +68,3 @@ bbb bbb ] - -[Domain] - -[--- - aaa - bbb - ---] - diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 0561189b4a..15f01c83c8 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -134,11 +134,28 @@ function serializeScopes(codeLines: string[], scopes: ScopeRanges[]): string { function serializeScope( codeLines: string[], scope: ScopeRanges, - index: number | undefined, + scopeIndex: number | undefined, ): string { + if ( + scope.targets.length === 1 && + scope.targets[0].contentRange.isRangeEqual(scope.domain) + ) { + return serializeTarget( + codeLines, + scope.targets[0], + [], + scopeIndex, + undefined, + scope.domain, + ); + } + + // If we have multiple targets or the domain is not equal to the content range: add domain last return [ - serializeTargets(codeLines, scope.targets, [], index), - serializeHeader(codeLines, [], "Domain", index, scope.domain), + serializeTargets(codeLines, scope.targets, [], scopeIndex), + "", + serializeHeader([], "Domain", scopeIndex, undefined), + serializeCodeRange(codeLines, scope.domain), ].join("\n"); } @@ -146,10 +163,18 @@ function serializeTargets( codeLines: string[], targets: TargetRanges[], prefix: string[], - index: number | undefined, + scopeIndex: number | undefined, ): string { return targets - .map((target) => serializeTarget(codeLines, target, prefix, index)) + .map((target, index) => + serializeTarget( + codeLines, + target, + prefix, + scopeIndex, + targets.length > 1 ? index + 1 : undefined, + ), + ) .join("\n"); } @@ -157,14 +182,32 @@ function serializeTarget( codeLines: string[], target: TargetRanges, prefix: string[], - index: number | undefined, + scopeIndex: number | undefined, + targetIndex: number | undefined, + domain?: Range, ): string { const lines: string[] = []; - lines.push( - serializeHeader(codeLines, prefix, "Content", index, target.contentRange), - serializeHeader(codeLines, prefix, "Removal", index, target.removalRange), - ); + lines.push("", serializeHeader(prefix, "Content", scopeIndex, targetIndex)); + + // Add removal and domain headers below content header if their ranges are equal + if (target.contentRange.isRangeEqual(target.removalRange)) { + lines.push(serializeHeader(prefix, "Removal", scopeIndex, targetIndex)); + } + if (domain != null && target.contentRange.isRangeEqual(domain)) { + lines.push(serializeHeader(prefix, "Domain", scopeIndex, targetIndex)); + } + + lines.push(serializeCodeRange(codeLines, target.contentRange)); + + // Add separate removal header below content if their ranges are not equal + if (!target.contentRange.isRangeEqual(target.removalRange)) { + lines.push( + "", + serializeHeader(prefix, "Removal", scopeIndex, targetIndex), + serializeCodeRange(codeLines, target.removalRange), + ); + } if (target.leadingDelimiter != null) { lines.push( @@ -172,7 +215,8 @@ function serializeTarget( codeLines, target.leadingDelimiter, [...prefix, "Leading delimiter"], - index, + scopeIndex, + undefined, ), ); } @@ -183,7 +227,8 @@ function serializeTarget( codeLines, target.trailingDelimiter, [...prefix, "Trailing delimiter"], - index, + scopeIndex, + undefined, ), ); } @@ -194,7 +239,7 @@ function serializeTarget( codeLines, target.interior, [...prefix, "Interior"], - index, + scopeIndex, ), ); } @@ -205,7 +250,7 @@ function serializeTarget( codeLines, target.boundary, [...prefix, "Boundary"], - index, + scopeIndex, ), ); } @@ -214,25 +259,28 @@ function serializeTarget( } function serializeHeader( - codeLines: string[], prefix: string[], header: string, - index: number | undefined, - range: Range, + scopeIndex: number | undefined, + targetIndex: number | undefined, ): string { + const parts: string[] = []; + if (scopeIndex != null) { + parts.push(`#${scopeIndex}`); + } + if (prefix.length > 0) { + parts.push(prefix.join(" | ") + ":"); + } + parts.push(header); + if (targetIndex != null) { + parts.push(targetIndex.toString()); + } + return `[${parts.join(" ")}]`; +} + +function serializeCodeRange(codeLines: string[], range: Range): string { const { start, end } = range; - const fullHeader = (() => { - const parts: string[] = []; - if (index != null) { - parts.push(`#${index}`); - } - if (prefix.length > 0) { - parts.push(prefix.join(" | ") + ":"); - } - parts.push(header); - return parts.join(" "); - })(); - const lines: string[] = ["", `[${fullHeader}]`]; + const lines: string[] = []; codeLines.forEach((codeLine, index) => { const fullCodeLine = " " + codeLine; From bf5e1871835ad54eb284425428907c6389212037 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 23 Nov 2023 03:49:24 +0100 Subject: [PATCH 33/71] cleanup --- .../fixtures/scopes/plaintext/paragraph.scope | 18 --- .../src/suite/scopes.vscode.test.ts | 141 ++++++++++-------- 2 files changed, 79 insertions(+), 80 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope index 741110e93d..379dfa8b27 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope @@ -36,15 +36,6 @@ bbb bbb -[Leading delimiter | Trailing delimiter: Content] -[Leading delimiter | Trailing delimiter: Removal] -[ - - aaa - ] - bbb - - [Trailing delimiter: Content] aaa @@ -59,12 +50,3 @@ bbb bbb ] - -[Trailing delimiter | Leading delimiter: Content] -[Trailing delimiter | Leading delimiter: Removal] - - aaa - [ - bbb - - ] diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 15f01c83c8..1b7635f592 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -143,7 +143,7 @@ function serializeScope( return serializeTarget( codeLines, scope.targets[0], - [], + undefined, scopeIndex, undefined, scope.domain, @@ -152,105 +152,88 @@ function serializeScope( // If we have multiple targets or the domain is not equal to the content range: add domain last return [ - serializeTargets(codeLines, scope.targets, [], scopeIndex), - "", - serializeHeader([], "Domain", scopeIndex, undefined), - serializeCodeRange(codeLines, scope.domain), - ].join("\n"); -} - -function serializeTargets( - codeLines: string[], - targets: TargetRanges[], - prefix: string[], - scopeIndex: number | undefined, -): string { - return targets - .map((target, index) => + ...scope.targets.map((target, index) => serializeTarget( codeLines, target, - prefix, + undefined, scopeIndex, - targets.length > 1 ? index + 1 : undefined, + scope.targets.length > 1 ? index + 1 : undefined, ), - ) - .join("\n"); + ), + "", + serializeHeader(undefined, "Domain", scopeIndex, undefined), + serializeCodeRange(codeLines, scope.domain), + ].join("\n"); } function serializeTarget( codeLines: string[], target: TargetRanges, - prefix: string[], + prefix: string | undefined, scopeIndex: number | undefined, targetIndex: number | undefined, domain?: Range, ): string { - const lines: string[] = []; - - lines.push("", serializeHeader(prefix, "Content", scopeIndex, targetIndex)); - - // Add removal and domain headers below content header if their ranges are equal - if (target.contentRange.isRangeEqual(target.removalRange)) { - lines.push(serializeHeader(prefix, "Removal", scopeIndex, targetIndex)); - } - if (domain != null && target.contentRange.isRangeEqual(domain)) { - lines.push(serializeHeader(prefix, "Domain", scopeIndex, targetIndex)); - } - - lines.push(serializeCodeRange(codeLines, target.contentRange)); - - // Add separate removal header below content if their ranges are not equal - if (!target.contentRange.isRangeEqual(target.removalRange)) { - lines.push( - "", - serializeHeader(prefix, "Removal", scopeIndex, targetIndex), - serializeCodeRange(codeLines, target.removalRange), - ); - } + const lines: string[] = [ + serializeTargetBasics( + codeLines, + target, + prefix, + scopeIndex, + targetIndex, + domain, + ), + ]; if (target.leadingDelimiter != null) { lines.push( - serializeTarget( + serializeTargetBasics( codeLines, target.leadingDelimiter, - [...prefix, "Leading delimiter"], + "Leading delimiter", scopeIndex, - undefined, + targetIndex, ), ); } if (target.trailingDelimiter != null) { lines.push( - serializeTarget( + serializeTargetBasics( codeLines, target.trailingDelimiter, - [...prefix, "Trailing delimiter"], + "Trailing delimiter", scopeIndex, - undefined, + targetIndex, ), ); } if (target.interior != null) { lines.push( - serializeTargets( - codeLines, - target.interior, - [...prefix, "Interior"], - scopeIndex, + ...target.interior.map((interior) => + serializeTargetBasics( + codeLines, + interior, + "Interior", + scopeIndex, + targetIndex, + ), ), ); } if (target.boundary != null) { lines.push( - serializeTargets( - codeLines, - target.boundary, - [...prefix, "Boundary"], - scopeIndex, + ...target.boundary.map((interior) => + serializeTargetBasics( + codeLines, + interior, + "Boundary", + scopeIndex, + targetIndex, + ), ), ); } @@ -258,8 +241,42 @@ function serializeTarget( return lines.join("\n"); } +function serializeTargetBasics( + codeLines: string[], + target: TargetRanges, + prefix: string | undefined, + scopeIndex: number | undefined, + targetIndex: number | undefined, + domain?: Range, +): string { + const lines: string[] = []; + + lines.push("", serializeHeader(prefix, "Content", scopeIndex, targetIndex)); + + // Add removal and domain headers below content header if their ranges are equal + if (target.contentRange.isRangeEqual(target.removalRange)) { + lines.push(serializeHeader(prefix, "Removal", scopeIndex, targetIndex)); + } + if (domain != null && target.contentRange.isRangeEqual(domain)) { + lines.push(serializeHeader(prefix, "Domain", scopeIndex, targetIndex)); + } + + lines.push(serializeCodeRange(codeLines, target.contentRange)); + + // Add separate removal header below content if their ranges are not equal + if (!target.contentRange.isRangeEqual(target.removalRange)) { + lines.push( + "", + serializeHeader(prefix, "Removal", scopeIndex, targetIndex), + serializeCodeRange(codeLines, target.removalRange), + ); + } + + return lines.join("\n"); +} + function serializeHeader( - prefix: string[], + prefix: string | undefined, header: string, scopeIndex: number | undefined, targetIndex: number | undefined, @@ -268,8 +285,8 @@ function serializeHeader( if (scopeIndex != null) { parts.push(`#${scopeIndex}`); } - if (prefix.length > 0) { - parts.push(prefix.join(" | ") + ":"); + if (prefix != null) { + parts.push(prefix + ":"); } parts.push(header); if (targetIndex != null) { From f2b63d844f61a2cdd95b77d415d64758fdbf1269 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Fri, 24 Nov 2023 14:58:24 +0100 Subject: [PATCH 34/71] Use curly braces for empty ranch --- .../src/suite/fixtures/scopes/plaintext/line2.scope | 4 ++-- .../src/suite/fixtures/scopes/plaintext/paragraph.scope | 4 ++-- .../cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope index 8f83734228..d55af21cb2 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -6,7 +6,7 @@ aaa [#1 Content] [#1 Domain] -[] +{} aaa @@ -60,7 +60,7 @@ aaa aaa -[] +{} [#3 Removal] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope index 379dfa8b27..d8734e19b2 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope @@ -23,7 +23,7 @@ bbb [Leading delimiter: Content] -[] +{} aaa bbb @@ -41,7 +41,7 @@ bbb aaa bbb -[] +{} [Trailing delimiter: Removal] diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 1b7635f592..156a7464eb 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -323,7 +323,7 @@ function serializeCodeRange(codeLines: string[], range: Range): string { function serializeRange(start: Position, end: Position): string { if (start.isEqual(end)) { - return [new Array(start.character + 1).join(" "), "[]"].join(""); + return [new Array(start.character + 1).join(" "), "{}"].join(""); } return [ new Array(start.character + 2).join(" "), From 9f9de741e40b6f940f2d8e3412d44c33c5107b4b Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Fri, 24 Nov 2023 15:03:36 +0100 Subject: [PATCH 35/71] Annotate or trailing whitespace lines --- .../scopes/javascript/namedFunction.scope | 2 +- .../fixtures/scopes/plaintext/line2.scope | 40 +++++++++---------- .../fixtures/scopes/plaintext/paragraph.scope | 24 +++++------ .../src/suite/scopes.vscode.test.ts | 3 +- 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope index 0f9817302a..3d6f5fe391 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope @@ -8,6 +8,6 @@ function myFunk() { [Domain] [------------------- function myFunk() { - + â—‚ } -] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope index d55af21cb2..6193a14866 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -5,74 +5,74 @@ aaa [#1 Content] [#1 Domain] - + â—‚ {} aaa - + â—‚ [#1 Removal] [ - + â—‚ aaa ] - + â—‚ [#1 Trailing delimiter: Content] [#1 Trailing delimiter: Removal] [ - + â—‚ aaa ] - + â—‚ [#2 Content] [#2 Domain] - + â—‚ aaa ^^^ - + â—‚ [#2 Removal] - + â—‚ [--- aaa - + â—‚ ] [#2 Leading delimiter: Content] [#2 Leading delimiter: Removal] [ - + â—‚ aaa ] - + â—‚ [#2 Trailing delimiter: Content] [#2 Trailing delimiter: Removal] - + â—‚ [ aaa - + â—‚ ] [#3 Content] [#3 Domain] - + â—‚ aaa - + â—‚ {} [#3 Removal] - + â—‚ [ aaa - + â—‚ ] [#3 Leading delimiter: Content] [#3 Leading delimiter: Removal] - + â—‚ [ aaa - + â—‚ ] diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope index d8734e19b2..2e721f8a9f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope @@ -6,47 +6,47 @@ bbb [Content] [Domain] - + â—‚ [--- aaa bbb ---] - + â—‚ [Removal] [ - + â—‚ aaa bbb - + â—‚ ] [Leading delimiter: Content] - + â—‚ {} aaa bbb - + â—‚ [Leading delimiter: Removal] [ - + â—‚ aaa ] bbb - + â—‚ [Trailing delimiter: Content] - + â—‚ aaa bbb - + â—‚ {} [Trailing delimiter: Removal] - + â—‚ aaa [ bbb - + â—‚ ] diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 156a7464eb..02468e4ce4 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -300,7 +300,8 @@ function serializeCodeRange(codeLines: string[], range: Range): string { const lines: string[] = []; codeLines.forEach((codeLine, index) => { - const fullCodeLine = " " + codeLine; + const suffix = codeLine.length === 0 || codeLine.endsWith(" ") ? "â—‚" : ""; + const fullCodeLine = ` ${codeLine}${suffix}`; if (index === start.line) { if (range.isSingleLine) { From fc63d439753f8f6fda41557da325521629fd35fc Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 26 Nov 2023 13:09:12 +0100 Subject: [PATCH 36/71] Extract serialize scopes to own file --- .../src/suite/scopes.vscode.test.ts | 239 +----------------- .../src/suite/serializeScopes.ts | 230 +++++++++++++++++ 2 files changed, 232 insertions(+), 237 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 02468e4ce4..6e39a99e74 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -2,15 +2,11 @@ import { asyncSafety, getLanguageScopeSupport, getScopeTestPaths, - Position, - Range, - ScopeRanges, ScopeSupportFacet, scopeSupportFacetInfos, ScopeSupportFacetLevel, ScopeType, shouldUpdateFixtures, - TargetRanges, TextualScopeSupportFacet, textualScopeSupportFacetInfos, } from "@cursorless/common"; @@ -19,6 +15,7 @@ import { assert } from "chai"; import { groupBy } from "lodash"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; +import { serializeScopes } from "./serializeScopes"; suite("Scope test cases", async function () { endToEndTestSetup(this); @@ -103,14 +100,7 @@ async function runTest(file: string, languageId: string, facetId: string) { scopeType, }); - const codeLines = code.split("\n"); - - const outputFixture = [ - ...codeLines, - "---", - serializeScopes(codeLines, scopes), - "", - ].join("\n"); + const outputFixture = serializeScopes(code, scopes); if (shouldUpdateFixtures()) { await fsp.writeFile(file, outputFixture); @@ -119,231 +109,6 @@ async function runTest(file: string, languageId: string, facetId: string) { } } -function serializeScopes(codeLines: string[], scopes: ScopeRanges[]): string { - return scopes - .map((scope, index) => - serializeScope( - codeLines, - scope, - scopes.length > 1 ? index + 1 : undefined, - ), - ) - .join("\n"); -} - -function serializeScope( - codeLines: string[], - scope: ScopeRanges, - scopeIndex: number | undefined, -): string { - if ( - scope.targets.length === 1 && - scope.targets[0].contentRange.isRangeEqual(scope.domain) - ) { - return serializeTarget( - codeLines, - scope.targets[0], - undefined, - scopeIndex, - undefined, - scope.domain, - ); - } - - // If we have multiple targets or the domain is not equal to the content range: add domain last - return [ - ...scope.targets.map((target, index) => - serializeTarget( - codeLines, - target, - undefined, - scopeIndex, - scope.targets.length > 1 ? index + 1 : undefined, - ), - ), - "", - serializeHeader(undefined, "Domain", scopeIndex, undefined), - serializeCodeRange(codeLines, scope.domain), - ].join("\n"); -} - -function serializeTarget( - codeLines: string[], - target: TargetRanges, - prefix: string | undefined, - scopeIndex: number | undefined, - targetIndex: number | undefined, - domain?: Range, -): string { - const lines: string[] = [ - serializeTargetBasics( - codeLines, - target, - prefix, - scopeIndex, - targetIndex, - domain, - ), - ]; - - if (target.leadingDelimiter != null) { - lines.push( - serializeTargetBasics( - codeLines, - target.leadingDelimiter, - "Leading delimiter", - scopeIndex, - targetIndex, - ), - ); - } - - if (target.trailingDelimiter != null) { - lines.push( - serializeTargetBasics( - codeLines, - target.trailingDelimiter, - "Trailing delimiter", - scopeIndex, - targetIndex, - ), - ); - } - - if (target.interior != null) { - lines.push( - ...target.interior.map((interior) => - serializeTargetBasics( - codeLines, - interior, - "Interior", - scopeIndex, - targetIndex, - ), - ), - ); - } - - if (target.boundary != null) { - lines.push( - ...target.boundary.map((interior) => - serializeTargetBasics( - codeLines, - interior, - "Boundary", - scopeIndex, - targetIndex, - ), - ), - ); - } - - return lines.join("\n"); -} - -function serializeTargetBasics( - codeLines: string[], - target: TargetRanges, - prefix: string | undefined, - scopeIndex: number | undefined, - targetIndex: number | undefined, - domain?: Range, -): string { - const lines: string[] = []; - - lines.push("", serializeHeader(prefix, "Content", scopeIndex, targetIndex)); - - // Add removal and domain headers below content header if their ranges are equal - if (target.contentRange.isRangeEqual(target.removalRange)) { - lines.push(serializeHeader(prefix, "Removal", scopeIndex, targetIndex)); - } - if (domain != null && target.contentRange.isRangeEqual(domain)) { - lines.push(serializeHeader(prefix, "Domain", scopeIndex, targetIndex)); - } - - lines.push(serializeCodeRange(codeLines, target.contentRange)); - - // Add separate removal header below content if their ranges are not equal - if (!target.contentRange.isRangeEqual(target.removalRange)) { - lines.push( - "", - serializeHeader(prefix, "Removal", scopeIndex, targetIndex), - serializeCodeRange(codeLines, target.removalRange), - ); - } - - return lines.join("\n"); -} - -function serializeHeader( - prefix: string | undefined, - header: string, - scopeIndex: number | undefined, - targetIndex: number | undefined, -): string { - const parts: string[] = []; - if (scopeIndex != null) { - parts.push(`#${scopeIndex}`); - } - if (prefix != null) { - parts.push(prefix + ":"); - } - parts.push(header); - if (targetIndex != null) { - parts.push(targetIndex.toString()); - } - return `[${parts.join(" ")}]`; -} - -function serializeCodeRange(codeLines: string[], range: Range): string { - const { start, end } = range; - const lines: string[] = []; - - codeLines.forEach((codeLine, index) => { - const suffix = codeLine.length === 0 || codeLine.endsWith(" ") ? "â—‚" : ""; - const fullCodeLine = ` ${codeLine}${suffix}`; - - if (index === start.line) { - if (range.isSingleLine) { - lines.push(fullCodeLine); - lines.push(serializeRange(start, end)); - } else { - lines.push(serializeStartRange(start, codeLine.length)); - lines.push(fullCodeLine); - } - } else if (index === end.line) { - lines.push(fullCodeLine); - lines.push(serializeEndRange(end)); - } else { - lines.push(fullCodeLine); - } - }); - - return lines.join("\n"); -} - -function serializeRange(start: Position, end: Position): string { - if (start.isEqual(end)) { - return [new Array(start.character + 1).join(" "), "{}"].join(""); - } - return [ - new Array(start.character + 2).join(" "), - new Array(end.character - start.character + 1).join("^"), - ].join(""); -} - -function serializeStartRange(start: Position, rowLength: number): string { - return [ - new Array(start.character + 1).join(" "), - "[", - new Array(rowLength - start.character + 1).join("-"), - ].join(""); -} - -function serializeEndRange(end: Position): string { - return [" ", new Array(end.character + 1).join("-"), "]"].join(""); -} - function getScopeType(facetId: string): ScopeType { if (facetId in textualScopeSupportFacetInfos) { const { scopeType } = diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts new file mode 100644 index 0000000000..5f73474ff3 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts @@ -0,0 +1,230 @@ +import { Position, Range, ScopeRanges, TargetRanges } from "@cursorless/common"; + +export function serializeScopes(code: string, scopes: ScopeRanges[]): string { + const codeLines = code.split("\n"); + return [ + ...codeLines, + "---", + ...scopes.map((scope, index) => + serializeScope( + codeLines, + scope, + scopes.length > 1 ? index + 1 : undefined, + ), + ), + "", + ].join("\n"); +} + +function serializeScope( + codeLines: string[], + scope: ScopeRanges, + scopeIndex: number | undefined, +): string { + if ( + scope.targets.length === 1 && + scope.targets[0].contentRange.isRangeEqual(scope.domain) + ) { + return serializeTarget( + codeLines, + scope.targets[0], + undefined, + scopeIndex, + undefined, + scope.domain, + ); + } + + // If we have multiple targets or the domain is not equal to the content range: add domain last + return [ + ...scope.targets.map((target, index) => + serializeTarget( + codeLines, + target, + undefined, + scopeIndex, + scope.targets.length > 1 ? index + 1 : undefined, + ), + ), + "", + serializeHeader(undefined, "Domain", scopeIndex, undefined), + serializeCodeRange(codeLines, scope.domain), + ].join("\n"); +} + +function serializeTarget( + codeLines: string[], + target: TargetRanges, + prefix: string | undefined, + scopeIndex: number | undefined, + targetIndex: number | undefined, + domain?: Range, +): string { + const lines: string[] = [ + serializeTargetBasics( + codeLines, + target, + prefix, + scopeIndex, + targetIndex, + domain, + ), + ]; + + if (target.leadingDelimiter != null) { + lines.push( + serializeTargetBasics( + codeLines, + target.leadingDelimiter, + "Leading delimiter", + scopeIndex, + targetIndex, + ), + ); + } + + if (target.trailingDelimiter != null) { + lines.push( + serializeTargetBasics( + codeLines, + target.trailingDelimiter, + "Trailing delimiter", + scopeIndex, + targetIndex, + ), + ); + } + + if (target.interior != null) { + lines.push( + ...target.interior.map((interior) => + serializeTargetBasics( + codeLines, + interior, + "Interior", + scopeIndex, + targetIndex, + ), + ), + ); + } + + if (target.boundary != null) { + lines.push( + ...target.boundary.map((interior) => + serializeTargetBasics( + codeLines, + interior, + "Boundary", + scopeIndex, + targetIndex, + ), + ), + ); + } + + return lines.join("\n"); +} + +function serializeTargetBasics( + codeLines: string[], + target: TargetRanges, + prefix: string | undefined, + scopeIndex: number | undefined, + targetIndex: number | undefined, + domain?: Range, +): string { + const lines: string[] = []; + + lines.push("", serializeHeader(prefix, "Content", scopeIndex, targetIndex)); + + // Add removal and domain headers below content header if their ranges are equal + if (target.contentRange.isRangeEqual(target.removalRange)) { + lines.push(serializeHeader(prefix, "Removal", scopeIndex, targetIndex)); + } + if (domain != null && target.contentRange.isRangeEqual(domain)) { + lines.push(serializeHeader(prefix, "Domain", scopeIndex, targetIndex)); + } + + lines.push(serializeCodeRange(codeLines, target.contentRange)); + + // Add separate removal header below content if their ranges are not equal + if (!target.contentRange.isRangeEqual(target.removalRange)) { + lines.push( + "", + serializeHeader(prefix, "Removal", scopeIndex, targetIndex), + serializeCodeRange(codeLines, target.removalRange), + ); + } + + return lines.join("\n"); +} + +function serializeHeader( + prefix: string | undefined, + header: string, + scopeIndex: number | undefined, + targetIndex: number | undefined, +): string { + const parts: string[] = []; + if (scopeIndex != null) { + parts.push(`#${scopeIndex}`); + } + if (prefix != null) { + parts.push(prefix + ":"); + } + parts.push(header); + if (targetIndex != null) { + parts.push(targetIndex.toString()); + } + return `[${parts.join(" ")}]`; +} + +function serializeCodeRange(codeLines: string[], range: Range): string { + const { start, end } = range; + const lines: string[] = []; + + codeLines.forEach((codeLine, index) => { + const suffix = codeLine.length === 0 || codeLine.endsWith(" ") ? "â—‚" : ""; + const fullCodeLine = ` ${codeLine}${suffix}`; + + if (index === start.line) { + if (range.isSingleLine) { + lines.push(fullCodeLine); + lines.push(serializeRange(start, end)); + } else { + lines.push(serializeStartRange(start, codeLine.length)); + lines.push(fullCodeLine); + } + } else if (index === end.line) { + lines.push(fullCodeLine); + lines.push(serializeEndRange(end)); + } else { + lines.push(fullCodeLine); + } + }); + + return lines.join("\n"); +} + +function serializeRange(start: Position, end: Position): string { + if (start.isEqual(end)) { + return [new Array(start.character + 1).join(" "), "{}"].join(""); + } + return [ + new Array(start.character + 2).join(" "), + new Array(end.character - start.character + 1).join("^"), + ].join(""); +} + +function serializeStartRange(start: Position, rowLength: number): string { + return [ + new Array(start.character + 1).join(" "), + "[", + new Array(rowLength - start.character + 1).join("-"), + ].join(""); +} + +function serializeEndRange(end: Position): string { + return [" ", new Array(end.character + 1).join("-"), "]"].join(""); +} From cbd156f6a644bd45aac0b970dcc37bec66de6c45 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:25:23 +0000 Subject: [PATCH 37/71] Update line2.scope --- .../fixtures/scopes/plaintext/line2.scope | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope index 6193a14866..9ff2408397 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -3,19 +3,20 @@ aaa --- -[#1 Content] -[#1 Domain] - â—‚ -{} - aaa - â—‚ +[#1 Content] = +[#1 Domain] = (0,0)-(0,0) +0| + >< +1| aaa -[#1 Removal] -[ - â—‚ - aaa - ] - â—‚ +2| + +[#1 Removal] = (0,0)-(1,0) +0| + > +1| aaa + < +2| [#1 Trailing delimiter: Content] [#1 Trailing delimiter: Removal] From 653354e8498ef36496af5490c80ddab389c1f0ec Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:26:02 +0000 Subject: [PATCH 38/71] Update namedFunction.scope --- .../scopes/javascript/namedFunction.scope | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope index 3d6f5fe391..d53e579bfa 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope @@ -3,11 +3,12 @@ function myFunk() { } --- -[Content] -[Removal] -[Domain] -[------------------- - function myFunk() { - â—‚ - } - -] +[Content] = +[Removal] = +[Domain] = (0,0)-(2,1) +0| function myFunk() { + >------------------- +1| + +2| } + -< From fee4588afa7a0fa9c7eaafdad88a638cb14e09f5 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Sun, 26 Nov 2023 19:27:20 +0000 Subject: [PATCH 39/71] Update name.assignment.scope --- .../suite/fixtures/scopes/javascript/name.assignment.scope | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope index 0ac98ff79f..a464c553fb 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope @@ -1,9 +1,9 @@ const name = "Hello world"; --- -[Content] - const name = "Hello world"; - ^^^^ +[Content] = (0,5)-(0,9) +0| const name = "Hello world"; + >----< [Removal] const name = "Hello world"; From 1a96826bfcc681468dacbde3759c0fbe84193d19 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Mon, 27 Nov 2023 11:47:43 +0100 Subject: [PATCH 40/71] Updates scope representation --- .../scopes/javascript/name.assignment.scope | 28 ++- .../scopes/javascript/namedFunction.scope | 4 +- .../scopes/javascript/value.assignment.scope | 25 ++- .../fixtures/scopes/plaintext/line.scope | 10 +- .../fixtures/scopes/plaintext/line2.scope | 134 ++++++++------- .../fixtures/scopes/plaintext/paragraph.scope | 104 +++++++----- .../src/suite/serializeScopes.ts | 160 ++++++++++-------- 7 files changed, 253 insertions(+), 212 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope index a464c553fb..aa4a9d827e 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope @@ -1,24 +1,22 @@ const name = "Hello world"; --- -[Content] = (0,5)-(0,9) +[Content] = 0:6-0:10 0| const name = "Hello world"; >----< -[Removal] - const name = "Hello world"; - ^^^^^^^^^^^^^ +[Removal] = +0| const name = "Hello world"; + >-------------< -[Leading delimiter: Content] -[Leading delimiter: Removal] - const name = "Hello world"; - ^ +[Leading delimiter] = 0:5-0:6 +0| const name = "Hello world"; + >-< -[Trailing delimiter: Content] -[Trailing delimiter: Removal] - const name = "Hello world"; - ^ +[Trailing delimiter] = 0:10-0:11 +0| const name = "Hello world"; + >-< -[Domain] - const name = "Hello world"; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[Domain] = 0:0-0:27 +0| const name = "Hello world"; + >---------------------------< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope index d53e579bfa..f5efbfa87f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope @@ -5,10 +5,10 @@ function myFunk() { [Content] = [Removal] = -[Domain] = (0,0)-(2,1) +[Domain] = 0:0-2:1 0| function myFunk() { >------------------- -1| +1| 2| } -< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope index 6ebe392473..3d86d49d80 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope @@ -1,19 +1,18 @@ const name = "Hello world"; --- -[Content] - const name = "Hello world"; - ^^^^^^^^^^^^^ +[Content] = 0:13-0:26 +0| const name = "Hello world"; + >-------------< -[Removal] - const name = "Hello world"; - ^^^^^^^^^^^^^^^^ +[Removal] = +0| const name = "Hello world"; + >----------------< -[Leading delimiter: Content] -[Leading delimiter: Removal] - const name = "Hello world"; - ^^^ +[Leading delimiter] = 0:10-0:13 +0| const name = "Hello world"; + >---< -[Domain] - const name = "Hello world"; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +[Domain] = 0:0-0:27 +0| const name = "Hello world"; + >---------------------------< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope index 3b2e8d06cd..02952f022e 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope @@ -1,8 +1,8 @@ aaa --- -[Content] -[Removal] -[Domain] - aaa - ^^^ +[Content] = +[Removal] = +[Domain] = 0:0-0:3 +0| aaa + >---< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope index 9ff2408397..f04ed50cf3 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -4,76 +4,84 @@ aaa --- [#1 Content] = -[#1 Domain] = (0,0)-(0,0) -0| +[#1 Domain] = 0:0-0:0 +0| >< 1| aaa 2| -[#1 Removal] = (0,0)-(1,0) -0| + +[#1 Removal] = +0| + > +1| aaa + < +2| + + +[#1 Trailing delimiter] = 0:0-1:0 +0| + > +1| aaa + < +2| + + +[#2 Content] = +[#2 Domain] = 1:0-1:3 +0| + +1| aaa + >---< +2| + + +[#2 Removal] = +0| + +1| aaa + >--- +2| + < + +[#2 Leading delimiter] = 0:0-1:0 +0| > 1| aaa < 2| -[#1 Trailing delimiter: Content] -[#1 Trailing delimiter: Removal] -[ - â—‚ - aaa - ] - â—‚ - -[#2 Content] -[#2 Domain] - â—‚ - aaa - ^^^ - â—‚ - -[#2 Removal] - â—‚ -[--- - aaa - â—‚ - ] - -[#2 Leading delimiter: Content] -[#2 Leading delimiter: Removal] -[ - â—‚ - aaa - ] - â—‚ - -[#2 Trailing delimiter: Content] -[#2 Trailing delimiter: Removal] - â—‚ - [ - aaa - â—‚ - ] - -[#3 Content] -[#3 Domain] - â—‚ - aaa - â—‚ -{} - -[#3 Removal] - â—‚ - [ - aaa - â—‚ - ] - -[#3 Leading delimiter: Content] -[#3 Leading delimiter: Removal] - â—‚ - [ - aaa - â—‚ - ] + +[#2 Trailing delimiter] = 1:3-2:0 +0| + +1| aaa + > +2| + < + +[#3 Content] = +[#3 Domain] = 2:0-2:0 +0| + +1| aaa + +2| + >< + +[#3 Removal] = +0| + +1| aaa + > +2| + < + +[#3 Leading delimiter] = 1:3-2:0 +0| + +1| aaa + > +2| + < diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope index 2e721f8a9f..053e77e8db 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope @@ -4,49 +4,61 @@ bbb --- -[Content] -[Domain] - â—‚ -[--- - aaa - bbb - ---] - â—‚ - -[Removal] -[ - â—‚ - aaa - bbb - â—‚ - ] - -[Leading delimiter: Content] - â—‚ -{} - aaa - bbb - â—‚ - -[Leading delimiter: Removal] -[ - â—‚ - aaa - ] - bbb - â—‚ - -[Trailing delimiter: Content] - â—‚ - aaa - bbb - â—‚ -{} - -[Trailing delimiter: Removal] - â—‚ - aaa - [ - bbb - â—‚ - ] +[Content] = +[Domain] = 1:0-2:3 +0| + +1| aaa + >--- +2| bbb + ---< +3| + + +[Removal] = +0| + > +1| aaa + --- +2| bbb + --- +3| + < + +[Leading delimiter: Content] = 0:0-0:0 +0| + >< +1| aaa + +2| bbb + +3| + +[Leading delimiter: Removal] = 0:0-1:0 +0| + > +1| aaa + < +2| bbb + +3| + + +[Trailing delimiter: Content] = 3:0-3:0 +0| + +1| aaa + +2| bbb + +3| + >< +[Trailing delimiter: Removal] = 2:3-3:0 +0| + +1| aaa + +2| bbb + > +3| + < diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts index 5f73474ff3..066140068f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts @@ -1,4 +1,4 @@ -import { Position, Range, ScopeRanges, TargetRanges } from "@cursorless/common"; +import { Range, ScopeRanges, TargetRanges } from "@cursorless/common"; export function serializeScopes(code: string, scopes: ScopeRanges[]): string { const codeLines = code.split("\n"); @@ -28,7 +28,6 @@ function serializeScope( return serializeTarget( codeLines, scope.targets[0], - undefined, scopeIndex, undefined, scope.domain, @@ -41,13 +40,12 @@ function serializeScope( serializeTarget( codeLines, target, - undefined, scopeIndex, scope.targets.length > 1 ? index + 1 : undefined, ), ), "", - serializeHeader(undefined, "Domain", scopeIndex, undefined), + serializeHeader(undefined, "Domain", scopeIndex, undefined, scope.domain), serializeCodeRange(codeLines, scope.domain), ].join("\n"); } @@ -55,21 +53,44 @@ function serializeScope( function serializeTarget( codeLines: string[], target: TargetRanges, - prefix: string | undefined, scopeIndex: number | undefined, targetIndex: number | undefined, domain?: Range, ): string { - const lines: string[] = [ - serializeTargetBasics( - codeLines, - target, - prefix, - scopeIndex, - targetIndex, - domain, + const lines: string[] = [""]; + + const headers = ["Content"]; + + // Add removal and domain headers below content header if their ranges are equal + if (target.contentRange.isRangeEqual(target.removalRange)) { + headers.push("Removal"); + } + if (domain != null) { + headers.push("Domain"); + } + + lines.push( + ...headers.map((header, index) => + serializeHeader( + undefined, + header, + scopeIndex, + targetIndex, + index === headers.length - 1 ? target.contentRange : undefined, + ), ), - ]; + ); + + lines.push(serializeCodeRange(codeLines, target.contentRange)); + + // Add separate removal header below content if their ranges are not equal + if (!target.contentRange.isRangeEqual(target.removalRange)) { + lines.push( + "", + serializeHeader(undefined, "Removal", scopeIndex, targetIndex), + serializeCodeRange(codeLines, target.removalRange), + ); + } if (target.leadingDelimiter != null) { lines.push( @@ -132,27 +153,37 @@ function serializeTargetBasics( prefix: string | undefined, scopeIndex: number | undefined, targetIndex: number | undefined, - domain?: Range, ): string { - const lines: string[] = []; + const lines: string[] = [""]; - lines.push("", serializeHeader(prefix, "Content", scopeIndex, targetIndex)); - - // Add removal and domain headers below content header if their ranges are equal if (target.contentRange.isRangeEqual(target.removalRange)) { - lines.push(serializeHeader(prefix, "Removal", scopeIndex, targetIndex)); - } - if (domain != null && target.contentRange.isRangeEqual(domain)) { - lines.push(serializeHeader(prefix, "Domain", scopeIndex, targetIndex)); - } - - lines.push(serializeCodeRange(codeLines, target.contentRange)); - - // Add separate removal header below content if their ranges are not equal - if (!target.contentRange.isRangeEqual(target.removalRange)) { lines.push( - "", - serializeHeader(prefix, "Removal", scopeIndex, targetIndex), + serializeHeader( + prefix, + undefined, + scopeIndex, + targetIndex, + target.contentRange, + ), + ); + lines.push(serializeCodeRange(codeLines, target.contentRange)); + } else { + lines.push( + serializeHeader( + prefix, + "Content", + scopeIndex, + targetIndex, + target.contentRange, + ), + serializeCodeRange(codeLines, target.contentRange), + serializeHeader( + prefix, + "Removal", + scopeIndex, + targetIndex, + target.removalRange, + ), serializeCodeRange(codeLines, target.removalRange), ); } @@ -162,69 +193,62 @@ function serializeTargetBasics( function serializeHeader( prefix: string | undefined, - header: string, + header: string | undefined, scopeIndex: number | undefined, targetIndex: number | undefined, + range?: Range, ): string { const parts: string[] = []; if (scopeIndex != null) { parts.push(`#${scopeIndex}`); } if (prefix != null) { - parts.push(prefix + ":"); + if (header != null) { + parts.push(prefix + ":"); + } else { + parts.push(prefix); + } + } + if (header != null) { + parts.push(header); } - parts.push(header); if (targetIndex != null) { parts.push(targetIndex.toString()); } - return `[${parts.join(" ")}]`; + const suffix = range != null ? ` ${range.toString()}` : ""; + return `[${parts.join(" ")}] =${suffix}`; } function serializeCodeRange(codeLines: string[], range: Range): string { const { start, end } = range; const lines: string[] = []; - codeLines.forEach((codeLine, index) => { - const suffix = codeLine.length === 0 || codeLine.endsWith(" ") ? "â—‚" : ""; - const fullCodeLine = ` ${codeLine}${suffix}`; + codeLines.forEach((codeLine, lineNumber) => { + lines.push(`${lineNumber}| ${codeLine}`.trimEnd()); - if (index === start.line) { - if (range.isSingleLine) { - lines.push(fullCodeLine); - lines.push(serializeRange(start, end)); + if (lineNumber === start.line) { + const prefix = fill(" ", start.character + 2) + ">"; + if (start.line === end.line) { + lines.push(prefix + fill("-", end.character - start.character) + "<"); + } else { + lines.push(prefix + fill("-", codeLine.length - start.character)); + } + } else if (lineNumber > start.line && lineNumber < end.line) { + if (codeLine.length > 0) { + lines.push(" " + fill("-", codeLine.length)); } else { - lines.push(serializeStartRange(start, codeLine.length)); - lines.push(fullCodeLine); + lines.push(""); } - } else if (index === end.line) { - lines.push(fullCodeLine); - lines.push(serializeEndRange(end)); + } else if (lineNumber === end.line) { + lines.push(" " + fill("-", end.character) + "<"); } else { - lines.push(fullCodeLine); + lines.push(""); } }); return lines.join("\n"); } -function serializeRange(start: Position, end: Position): string { - if (start.isEqual(end)) { - return [new Array(start.character + 1).join(" "), "{}"].join(""); - } - return [ - new Array(start.character + 2).join(" "), - new Array(end.character - start.character + 1).join("^"), - ].join(""); -} - -function serializeStartRange(start: Position, rowLength: number): string { - return [ - new Array(start.character + 1).join(" "), - "[", - new Array(rowLength - start.character + 1).join("-"), - ].join(""); -} - -function serializeEndRange(end: Position): string { - return [" ", new Array(end.character + 1).join("-"), "]"].join(""); +function fill(character: string, count: number): string { + return new Array(count + 1).join(character); } From 0e70883d6ed7d80c70ebe4f88aca6cbbbe4123d2 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Mon, 27 Nov 2023 12:12:19 +0100 Subject: [PATCH 41/71] Add range to removal --- .../fixtures/scopes/javascript/name.assignment.scope | 2 +- .../fixtures/scopes/javascript/value.assignment.scope | 2 +- .../src/suite/fixtures/scopes/plaintext/line2.scope | 6 +++--- .../src/suite/fixtures/scopes/plaintext/paragraph.scope | 2 +- .../cursorless-vscode-e2e/src/suite/serializeScopes.ts | 8 +++++++- 5 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope index aa4a9d827e..79ec846403 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope @@ -5,7 +5,7 @@ const name = "Hello world"; 0| const name = "Hello world"; >----< -[Removal] = +[Removal] = 0:0-0:13 0| const name = "Hello world"; >-------------< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope index 3d86d49d80..109e3b0604 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope @@ -5,7 +5,7 @@ const name = "Hello world"; 0| const name = "Hello world"; >-------------< -[Removal] = +[Removal] = 0:10-0:26 0| const name = "Hello world"; >----------------< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope index f04ed50cf3..026e7bbf01 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -12,7 +12,7 @@ aaa 2| -[#1 Removal] = +[#1 Removal] = 0:0-1:0 0| > 1| aaa @@ -37,7 +37,7 @@ aaa 2| -[#2 Removal] = +[#2 Removal] = 1:0-2:0 0| 1| aaa @@ -70,7 +70,7 @@ aaa 2| >< -[#3 Removal] = +[#3 Removal] = 1:3-2:0 0| 1| aaa diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope index 053e77e8db..64080cab1f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope @@ -15,7 +15,7 @@ bbb 3| -[Removal] = +[Removal] = 0:0-3:0 0| > 1| aaa diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts index 066140068f..f21006e9a9 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts @@ -87,7 +87,13 @@ function serializeTarget( if (!target.contentRange.isRangeEqual(target.removalRange)) { lines.push( "", - serializeHeader(undefined, "Removal", scopeIndex, targetIndex), + serializeHeader( + undefined, + "Removal", + scopeIndex, + targetIndex, + target.removalRange, + ), serializeCodeRange(codeLines, target.removalRange), ); } From ed21c4d6add2980fa63a6f4d1b1903fd22ace832 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Mon, 27 Nov 2023 12:57:53 +0100 Subject: [PATCH 42/71] Update --- packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts index f21006e9a9..a0e407321f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts @@ -230,7 +230,9 @@ function serializeCodeRange(codeLines: string[], range: Range): string { const lines: string[] = []; codeLines.forEach((codeLine, lineNumber) => { - lines.push(`${lineNumber}| ${codeLine}`.trimEnd()); + lines.push( + codeLine.length > 0 ? `${lineNumber}| ${codeLine}` : `${lineNumber}|`, + ); if (lineNumber === start.line) { const prefix = fill(" ", start.character + 2) + ">"; From f783cb1c90ecc7552c257c8b5a407ec6084d99f6 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Mon, 27 Nov 2023 13:14:53 +0100 Subject: [PATCH 43/71] Added rest of textual scopes --- .../src/scopeSupportFacets/plaintext.ts | 4 +++ .../scopeSupportFacets/scopeSupportFacets.ts | 33 ++++++++++++++++++- .../fixtures/scopes/plaintext/character.scope | 20 +++++++++++ .../fixtures/scopes/plaintext/document.scope | 20 +++++++++++ .../fixtures/scopes/plaintext/token.scope | 19 +++++++++++ .../fixtures/scopes/plaintext/word.scope | 28 ++++++++++++++++ .../fixtures/scopes/plaintext/word2.scope | 14 ++++++++ 7 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope diff --git a/packages/common/src/scopeSupportFacets/plaintext.ts b/packages/common/src/scopeSupportFacets/plaintext.ts index 94e5e549e3..d1b59218f6 100644 --- a/packages/common/src/scopeSupportFacets/plaintext.ts +++ b/packages/common/src/scopeSupportFacets/plaintext.ts @@ -6,6 +6,10 @@ import { const { supported } = ScopeSupportFacetLevel; export const plaintextSupport: TextualLanguageScopeSupportFacetMap = { + character: supported, + word: supported, + token: supported, line: supported, paragraph: supported, + document: supported, }; diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts index 202555fb16..b6fb6972f9 100644 --- a/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts @@ -43,7 +43,14 @@ const scopeSupportFacets = [ // "type", ] as const; -const textualScopeSupportFacets = ["line", "paragraph"] as const; +const textualScopeSupportFacets = [ + "character", + "word", + "token", + "line", + "paragraph", + "document", +] as const; export type ScopeSupportFacet = (typeof scopeSupportFacets)[number]; export type TextualScopeSupportFacet = @@ -104,6 +111,24 @@ export const textualScopeSupportFacetInfos: Record< TextualScopeSupportFacet, ScopeSupportFacetInfo > = { + character: { + label: "Character", + description: "A single character in the document", + scopeType: "character", + examples: ["a", "."], + }, + word: { + label: "Word", + description: "A single word in a token", + scopeType: "word", + examples: ["foo_bar", "fooBar"], + }, + token: { + label: "Token", + description: "A single token in the document", + scopeType: "token", + examples: ["foo", "("], + }, line: { label: "Line", description: "A single line in the document", @@ -117,6 +142,12 @@ export const textualScopeSupportFacetInfos: Record< scopeType: "paragraph", examples: ["foo\nbar"], }, + document: { + label: "Documents", + description: "The entire document", + scopeType: "document", + examples: ["foo\n\nbar"], + }, }; export enum ScopeSupportFacetLevel { diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope new file mode 100644 index 0000000000..d6655314af --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope @@ -0,0 +1,20 @@ +aaa +--- + +[#1 Content] = +[#1 Removal] = +[#1 Domain] = 0:0-0:1 +0| aaa + >-< + +[#2 Content] = +[#2 Removal] = +[#2 Domain] = 0:1-0:2 +0| aaa + >-< + +[#3 Content] = +[#3 Removal] = +[#3 Domain] = 0:2-0:3 +0| aaa + >-< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope new file mode 100644 index 0000000000..6b36bd30a9 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope @@ -0,0 +1,20 @@ +aaa + +bbb + +ccc +--- + +[Content] = +[Removal] = +[Domain] = 0:0-4:3 +0| aaa + >--- +1| + +2| bbb + --- +3| + +4| ccc + ---< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope new file mode 100644 index 0000000000..914f468409 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope @@ -0,0 +1,19 @@ + aaa +--- + +[Content] = +[Domain] = 0:2-0:5 +0| aaa + >---< + +[Removal] = 0:0-0:7 +0| aaa + >-------< + +[Leading delimiter] = 0:0-0:2 +0| aaa + >--< + +[Trailing delimiter] = 0:5-0:7 +0| aaa + >--< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope new file mode 100644 index 0000000000..7608cdf532 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope @@ -0,0 +1,28 @@ +aaa_bbb +--- + +[#1 Content] = +[#1 Domain] = 0:0-0:3 +0| aaa_bbb + >---< + +[#1 Removal] = 0:0-0:4 +0| aaa_bbb + >----< + +[#1 Trailing delimiter] = 0:3-0:4 +0| aaa_bbb + >-< + +[#2 Content] = +[#2 Domain] = 0:4-0:7 +0| aaa_bbb + >---< + +[#2 Removal] = 0:3-0:7 +0| aaa_bbb + >----< + +[#2 Leading delimiter] = 0:3-0:4 +0| aaa_bbb + >-< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope new file mode 100644 index 0000000000..b05886de8b --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope @@ -0,0 +1,14 @@ +aaaBbb +--- + +[#1 Content] = +[#1 Removal] = +[#1 Domain] = 0:0-0:3 +0| aaaBbb + >---< + +[#2 Content] = +[#2 Removal] = +[#2 Domain] = 0:3-0:6 +0| aaaBbb + >---< From 4c39f557a12da3d7bdb3bc7340561eb91fb875db Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 30 Nov 2023 13:44:22 +0100 Subject: [PATCH 44/71] Added insertion delimiter --- .../scopes/javascript/name.assignment.scope | 2 ++ .../scopes/javascript/namedFunction.scope | 2 ++ .../scopes/javascript/value.assignment.scope | 2 ++ .../fixtures/scopes/plaintext/character.scope | 6 ++++ .../fixtures/scopes/plaintext/document.scope | 2 ++ .../fixtures/scopes/plaintext/line.scope | 2 ++ .../fixtures/scopes/plaintext/line2.scope | 6 ++++ .../fixtures/scopes/plaintext/paragraph.scope | 2 ++ .../fixtures/scopes/plaintext/token.scope | 2 ++ .../fixtures/scopes/plaintext/word.scope | 4 +++ .../fixtures/scopes/plaintext/word2.scope | 4 +++ .../src/suite/serializeScopes.ts | 36 ++++++++++++++++--- 12 files changed, 65 insertions(+), 5 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope index 79ec846403..5923a0157a 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/name.assignment.scope @@ -20,3 +20,5 @@ const name = "Hello world"; [Domain] = 0:0-0:27 0| const name = "Hello world"; >---------------------------< + +[Insertion delimiter] = " " diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope index f5efbfa87f..b0f16a02df 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/namedFunction.scope @@ -12,3 +12,5 @@ function myFunk() { 2| } -< + +[Insertion delimiter] = "\n\n" diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope index 109e3b0604..caa452d3f8 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.assignment.scope @@ -16,3 +16,5 @@ const name = "Hello world"; [Domain] = 0:0-0:27 0| const name = "Hello world"; >---------------------------< + +[Insertion delimiter] = " " diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope index d6655314af..413a0f25a1 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope @@ -7,14 +7,20 @@ aaa 0| aaa >-< +[#1 Insertion delimiter] = "" + [#2 Content] = [#2 Removal] = [#2 Domain] = 0:1-0:2 0| aaa >-< +[#2 Insertion delimiter] = "" + [#3 Content] = [#3 Removal] = [#3 Domain] = 0:2-0:3 0| aaa >-< + +[#3 Insertion delimiter] = "" diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope index 6b36bd30a9..b602c396ce 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope @@ -18,3 +18,5 @@ ccc 4| ccc ---< + +[Insertion delimiter] = "\n" diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope index 02952f022e..61e4b32f55 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope @@ -6,3 +6,5 @@ aaa [Domain] = 0:0-0:3 0| aaa >---< + +[Insertion delimiter] = "\n" diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope index 026e7bbf01..0305d7c868 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -28,6 +28,8 @@ aaa 2| +[#1 Insertion delimiter] = "\n" + [#2 Content] = [#2 Domain] = 1:0-1:3 0| @@ -61,6 +63,8 @@ aaa 2| < +[#2 Insertion delimiter] = "\n" + [#3 Content] = [#3 Domain] = 2:0-2:0 0| @@ -85,3 +89,5 @@ aaa > 2| < + +[#3 Insertion delimiter] = "\n" diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope index 64080cab1f..fb6b0a3fef 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope @@ -62,3 +62,5 @@ bbb > 3| < + +[Insertion delimiter] = "\n\n" diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope index 914f468409..b40804aff9 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope @@ -17,3 +17,5 @@ [Trailing delimiter] = 0:5-0:7 0| aaa >--< + +[Insertion delimiter] = " " diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope index 7608cdf532..6af9658dda 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope @@ -14,6 +14,8 @@ aaa_bbb 0| aaa_bbb >-< +[#1 Insertion delimiter] = "_" + [#2 Content] = [#2 Domain] = 0:4-0:7 0| aaa_bbb @@ -26,3 +28,5 @@ aaa_bbb [#2 Leading delimiter] = 0:3-0:4 0| aaa_bbb >-< + +[#2 Insertion delimiter] = "_" diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope index b05886de8b..dbc83e4658 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope @@ -7,8 +7,12 @@ aaaBbb 0| aaaBbb >---< +[#1 Insertion delimiter] = "" + [#2 Content] = [#2 Removal] = [#2 Domain] = 0:3-0:6 0| aaaBbb >---< + +[#2 Insertion delimiter] = "" diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts index a0e407321f..33bba62081 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts @@ -21,10 +21,7 @@ function serializeScope( scope: ScopeRanges, scopeIndex: number | undefined, ): string { - if ( - scope.targets.length === 1 && - scope.targets[0].contentRange.isRangeEqual(scope.domain) - ) { + if (scope.targets.length === 1) { return serializeTarget( codeLines, scope.targets[0], @@ -65,7 +62,7 @@ function serializeTarget( if (target.contentRange.isRangeEqual(target.removalRange)) { headers.push("Removal"); } - if (domain != null) { + if (domain != null && target.contentRange.isRangeEqual(domain)) { headers.push("Domain"); } @@ -150,9 +147,38 @@ function serializeTarget( ); } + if (domain != null && !target.contentRange.isRangeEqual(domain)) { + lines.push( + "", + serializeHeader(undefined, "Domain", scopeIndex, targetIndex, domain), + serializeCodeRange(codeLines, domain), + ); + } + + lines.push( + serializeTargetInsertionDelimiter(target, scopeIndex, targetIndex), + ); + return lines.join("\n"); } +function serializeTargetInsertionDelimiter( + target: TargetRanges, + scopeIndex: number | undefined, + targetIndex: number | undefined, +): string { + const header = serializeHeader( + undefined, + "Insertion delimiter", + scopeIndex, + targetIndex, + ); + const delimiter = target.insertionDelimiter + .replaceAll("\r\n", "\\r\\n") + .replaceAll("\n", "\\n"); + return `\n${header} "${delimiter}"`; +} + function serializeTargetBasics( codeLines: string[], target: TargetRanges, From 963675e7bd7658715a206548ad409e39ac411826 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 30 Nov 2023 13:53:23 +0100 Subject: [PATCH 45/71] Add padding --- .../fixtures/scopes/plaintext/character.scope | 2 ++ .../suite/fixtures/scopes/plaintext/line2.scope | 2 ++ .../suite/fixtures/scopes/plaintext/word.scope | 1 + .../suite/fixtures/scopes/plaintext/word2.scope | 1 + .../src/suite/serializeScopes.ts | 16 ++++++++-------- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope index 413a0f25a1..92ce8be6f4 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope @@ -9,6 +9,7 @@ aaa [#1 Insertion delimiter] = "" + [#2 Content] = [#2 Removal] = [#2 Domain] = 0:1-0:2 @@ -17,6 +18,7 @@ aaa [#2 Insertion delimiter] = "" + [#3 Content] = [#3 Removal] = [#3 Domain] = 0:2-0:3 diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope index 0305d7c868..aa70ecc82b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope @@ -30,6 +30,7 @@ aaa [#1 Insertion delimiter] = "\n" + [#2 Content] = [#2 Domain] = 1:0-1:3 0| @@ -65,6 +66,7 @@ aaa [#2 Insertion delimiter] = "\n" + [#3 Content] = [#3 Domain] = 2:0-2:0 0| diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope index 6af9658dda..c8b08df664 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope @@ -16,6 +16,7 @@ aaa_bbb [#1 Insertion delimiter] = "_" + [#2 Content] = [#2 Domain] = 0:4-0:7 0| aaa_bbb diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope index dbc83e4658..a94f3eb776 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope @@ -9,6 +9,7 @@ aaaBbb [#1 Insertion delimiter] = "" + [#2 Content] = [#2 Removal] = [#2 Domain] = 0:3-0:6 diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts index 33bba62081..c138ed6e1e 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts @@ -1,19 +1,19 @@ import { Range, ScopeRanges, TargetRanges } from "@cursorless/common"; export function serializeScopes(code: string, scopes: ScopeRanges[]): string { - const codeLines = code.split("\n"); - return [ - ...codeLines, - "---", - ...scopes.map((scope, index) => + const codeLines = code.split(/\r?\n/g); + + const serializedScopes = scopes + .map((scope, index) => serializeScope( codeLines, scope, scopes.length > 1 ? index + 1 : undefined, ), - ), - "", - ].join("\n"); + ) + .join("\n\n"); + + return [...codeLines, "---", serializedScopes, ""].join("\n"); } function serializeScope( From c5da832bace9db64d0780b49a84885a6b0c94fc7 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:14:38 +0000 Subject: [PATCH 46/71] Minor tweaks --- .../src/suite/scopes.vscode.test.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 6e39a99e74..623277216b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -12,7 +12,7 @@ import { } from "@cursorless/common"; import { getCursorlessApi, openNewEditor } from "@cursorless/vscode-common"; import { assert } from "chai"; -import { groupBy } from "lodash"; +import { groupBy, uniq } from "lodash"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; import { serializeScopes } from "./serializeScopes"; @@ -26,7 +26,7 @@ suite("Scope test cases", async function () { if (!shouldUpdateFixtures()) { Object.entries(languages).forEach(([languageId, testPaths]) => test( - languageId, + `${languageId} facet coverage`, asyncSafety(() => testLanguageSupport( languageId, @@ -45,6 +45,12 @@ suite("Scope test cases", async function () { ); }); +/** + * Ensures that all supported facets for a language are tested, and that all + * tested facets are listed as supported in {@link getLanguageScopeSupport} + * @param languageId The language to test + * @param testedFacets The facets for {@link languageId} that are tested + */ async function testLanguageSupport(languageId: string, testedFacets: string[]) { const scopeSupport: Record = getLanguageScopeSupport(languageId); @@ -62,8 +68,10 @@ async function testLanguageSupport(languageId: string, testedFacets: string[]) { (testedFacet) => !supportedFacets.includes(testedFacet), ); if (unsupportedFacets.length > 0) { - const values = unsupportedFacets.join(", "); - assert.fail(`Missing scope support for tested facets [${values}]`); + const values = uniq(unsupportedFacets).join(", "); + assert.fail( + `${languageId}: Facets [${values}] are tested but not listed in getLanguageScopeSupport`, + ); } // Assert that all supported facets are tested @@ -72,7 +80,9 @@ async function testLanguageSupport(languageId: string, testedFacets: string[]) { ); if (untestedFacets.length > 0) { const values = untestedFacets.join(", "); - assert.fail(`Missing test for scope support facets [${values}]`); + assert.fail( + `${languageId}: Missing test for scope support facets [${values}]`, + ); } } From ef8d45248f4964fec32a8f276ffe7f62530cbb33 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:16:19 +0000 Subject: [PATCH 47/71] More tweaks --- .../cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 623277216b..f93930396b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -56,7 +56,7 @@ async function testLanguageSupport(languageId: string, testedFacets: string[]) { getLanguageScopeSupport(languageId); if (scopeSupport == null) { - assert.fail(`Missing scope support for language '${languageId}'`); + assert.fail(`Missing scope support entry in getLanguageScopeSupport`); } const supportedFacets = Object.keys(scopeSupport).filter( @@ -70,7 +70,7 @@ async function testLanguageSupport(languageId: string, testedFacets: string[]) { if (unsupportedFacets.length > 0) { const values = uniq(unsupportedFacets).join(", "); assert.fail( - `${languageId}: Facets [${values}] are tested but not listed in getLanguageScopeSupport`, + `Facets [${values}] are tested but not listed in getLanguageScopeSupport`, ); } @@ -80,9 +80,7 @@ async function testLanguageSupport(languageId: string, testedFacets: string[]) { ); if (untestedFacets.length > 0) { const values = untestedFacets.join(", "); - assert.fail( - `${languageId}: Missing test for scope support facets [${values}]`, - ); + assert.fail(`Missing test for scope support facets [${values}]`); } } From 66669f2b003698fe117761097d77417cc44b6afb Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:19:24 +0000 Subject: [PATCH 48/71] cleanup --- packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index f93930396b..2be7bc34ec 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -90,7 +90,7 @@ async function runTest(file: string, languageId: string, facetId: string) { const fixture = (await fsp.readFile(file, "utf8")) .toString() .replaceAll("\r\n", "\n"); - const delimiterIndex = fixture.match(/\r?\n^---$/m)?.index; + const delimiterIndex = fixture.match(/^---$/m)?.index; assert.ok( delimiterIndex != null, From 6c38cc351ac5396a767816d3cdc1aa12aa0af853 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:24:00 +0000 Subject: [PATCH 49/71] rename --- .../cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 4 ++-- .../suite/{serializeScopes.ts => serializeScopeFixture.ts} | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) rename packages/cursorless-vscode-e2e/src/suite/{serializeScopes.ts => serializeScopeFixture.ts} (98%) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 2be7bc34ec..3b9b1d42a6 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -15,7 +15,7 @@ import { assert } from "chai"; import { groupBy, uniq } from "lodash"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; -import { serializeScopes } from "./serializeScopes"; +import { serializeScopeFixture } from "./serializeScopeFixture"; suite("Scope test cases", async function () { endToEndTestSetup(this); @@ -108,7 +108,7 @@ async function runTest(file: string, languageId: string, facetId: string) { scopeType, }); - const outputFixture = serializeScopes(code, scopes); + const outputFixture = serializeScopeFixture(code, scopes); if (shouldUpdateFixtures()) { await fsp.writeFile(file, outputFixture); diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts similarity index 98% rename from packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts rename to packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts index c138ed6e1e..447212d90c 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts @@ -1,7 +1,10 @@ import { Range, ScopeRanges, TargetRanges } from "@cursorless/common"; -export function serializeScopes(code: string, scopes: ScopeRanges[]): string { - const codeLines = code.split(/\r?\n/g); +export function serializeScopeFixture( + code: string, + scopes: ScopeRanges[], +): string { + const codeLines = code.split("\n"); const serializedScopes = scopes .map((scope, index) => From eb348ba41dcd71b993110984807efd8370a5feed Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:46:30 +0000 Subject: [PATCH 50/71] More cleanup --- .../src/suite/serializeScopeFixture.ts | 234 +++++++++--------- .../src/suite/serializeTargetRange.ts | 65 +++++ 2 files changed, 180 insertions(+), 119 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/serializeTargetRange.ts diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts index 447212d90c..80a3768472 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts @@ -1,4 +1,5 @@ import { Range, ScopeRanges, TargetRanges } from "@cursorless/common"; +import { serializeTargetRange } from "./serializeTargetRange"; export function serializeScopeFixture( code: string, @@ -21,42 +22,55 @@ export function serializeScopeFixture( function serializeScope( codeLines: string[], - scope: ScopeRanges, + { domain, targets }: ScopeRanges, scopeIndex: number | undefined, ): string { - if (scope.targets.length === 1) { - return serializeTarget( + if (targets.length === 1) { + return serializeTarget({ codeLines, - scope.targets[0], + target: targets[0], scopeIndex, - undefined, - scope.domain, - ); + targetIndex: undefined, + domain, + }); } // If we have multiple targets or the domain is not equal to the content range: add domain last return [ - ...scope.targets.map((target, index) => - serializeTarget( + ...targets.map((target, index) => + serializeTarget({ codeLines, target, scopeIndex, - scope.targets.length > 1 ? index + 1 : undefined, - ), + targetIndex: index + 1, + }), ), "", - serializeHeader(undefined, "Domain", scopeIndex, undefined, scope.domain), - serializeCodeRange(codeLines, scope.domain), + serializeHeader({ + header: "Domain", + scopeIndex, + targetIndex: undefined, + range: domain, + }), + serializeTargetRange(codeLines, domain), ].join("\n"); } -function serializeTarget( - codeLines: string[], - target: TargetRanges, - scopeIndex: number | undefined, - targetIndex: number | undefined, - domain?: Range, -): string { +interface SerializedTargetArg { + codeLines: string[]; + target: TargetRanges; + scopeIndex: number | undefined; + targetIndex: number | undefined; + domain?: Range; +} + +function serializeTarget({ + codeLines, + target, + scopeIndex, + targetIndex, + domain, +}: SerializedTargetArg): string { const lines: string[] = [""]; const headers = ["Content"]; @@ -71,67 +85,65 @@ function serializeTarget( lines.push( ...headers.map((header, index) => - serializeHeader( - undefined, + serializeHeader({ header, scopeIndex, targetIndex, - index === headers.length - 1 ? target.contentRange : undefined, - ), + range: index === headers.length - 1 ? target.contentRange : undefined, + }), ), ); - lines.push(serializeCodeRange(codeLines, target.contentRange)); + lines.push(serializeTargetRange(codeLines, target.contentRange)); // Add separate removal header below content if their ranges are not equal if (!target.contentRange.isRangeEqual(target.removalRange)) { lines.push( "", - serializeHeader( - undefined, - "Removal", + serializeHeader({ + header: "Removal", scopeIndex, targetIndex, - target.removalRange, - ), - serializeCodeRange(codeLines, target.removalRange), + range: target.removalRange, + }), + serializeTargetRange(codeLines, target.removalRange), ); } if (target.leadingDelimiter != null) { lines.push( - serializeTargetBasics( + serializeTargetBasics({ codeLines, - target.leadingDelimiter, - "Leading delimiter", + target: target.leadingDelimiter, + prefix: "Leading delimiter", scopeIndex, targetIndex, - ), + }), ); } if (target.trailingDelimiter != null) { lines.push( - serializeTargetBasics( + serializeTargetBasics({ codeLines, - target.trailingDelimiter, - "Trailing delimiter", + target: target.trailingDelimiter, + prefix: "Trailing delimiter", scopeIndex, targetIndex, - ), + }), ); } if (target.interior != null) { lines.push( ...target.interior.map((interior) => - serializeTargetBasics( + serializeTargetBasics({ codeLines, - interior, - "Interior", + target: interior, + prefix: "Interior", scopeIndex, targetIndex, - ), + }), ), ); } @@ -139,13 +151,13 @@ function serializeTarget( if (target.boundary != null) { lines.push( ...target.boundary.map((interior) => - serializeTargetBasics( + serializeTargetBasics({ codeLines, - interior, - "Boundary", + target: interior, + prefix: "Boundary", scopeIndex, targetIndex, - ), + }), ), ); } @@ -153,8 +165,13 @@ function serializeTarget( if (domain != null && !target.contentRange.isRangeEqual(domain)) { lines.push( "", - serializeHeader(undefined, "Domain", scopeIndex, targetIndex, domain), - serializeCodeRange(codeLines, domain), + serializeHeader({ + header: "Domain", + scopeIndex, + targetIndex, + range: domain, + }), + serializeTargetRange(codeLines, domain), ); } @@ -170,69 +187,84 @@ function serializeTargetInsertionDelimiter( scopeIndex: number | undefined, targetIndex: number | undefined, ): string { - const header = serializeHeader( - undefined, - "Insertion delimiter", + const header = serializeHeader({ + header: "Insertion delimiter", scopeIndex, targetIndex, - ); + }); const delimiter = target.insertionDelimiter .replaceAll("\r\n", "\\r\\n") .replaceAll("\n", "\\n"); return `\n${header} "${delimiter}"`; } -function serializeTargetBasics( - codeLines: string[], - target: TargetRanges, - prefix: string | undefined, - scopeIndex: number | undefined, - targetIndex: number | undefined, -): string { +interface SerializedTargetBasicsArg { + codeLines: string[]; + target: TargetRanges; + prefix: string | undefined; + scopeIndex: number | undefined; + targetIndex: number | undefined; +} + +function serializeTargetBasics({ + codeLines, + target, + prefix, + scopeIndex, + targetIndex, +}: SerializedTargetBasicsArg): string { const lines: string[] = [""]; if (target.contentRange.isRangeEqual(target.removalRange)) { lines.push( - serializeHeader( + serializeHeader({ prefix, - undefined, + header: undefined, scopeIndex, targetIndex, - target.contentRange, - ), + range: target.contentRange, + }), ); - lines.push(serializeCodeRange(codeLines, target.contentRange)); + lines.push(serializeTargetRange(codeLines, target.contentRange)); } else { lines.push( - serializeHeader( + serializeHeader({ prefix, - "Content", + header: "Content", scopeIndex, targetIndex, - target.contentRange, - ), - serializeCodeRange(codeLines, target.contentRange), - serializeHeader( + range: target.contentRange, + }), + serializeTargetRange(codeLines, target.contentRange), + serializeHeader({ prefix, - "Removal", + header: "Removal", scopeIndex, targetIndex, - target.removalRange, - ), - serializeCodeRange(codeLines, target.removalRange), + range: target.removalRange, + }), + serializeTargetRange(codeLines, target.removalRange), ); } return lines.join("\n"); } -function serializeHeader( - prefix: string | undefined, - header: string | undefined, - scopeIndex: number | undefined, - targetIndex: number | undefined, - range?: Range, -): string { +interface SerializeHeaderArg { + prefix?: string; + header: string | undefined; + scopeIndex: number | undefined; + targetIndex: number | undefined; + range?: Range; +} + +function serializeHeader({ + prefix, + header, + scopeIndex, + targetIndex, + range, +}: SerializeHeaderArg): string { const parts: string[] = []; if (scopeIndex != null) { parts.push(`#${scopeIndex}`); @@ -250,42 +282,6 @@ function serializeHeader( if (targetIndex != null) { parts.push(targetIndex.toString()); } - const suffix = range != null ? ` ${range.toString()}` : ""; + const suffix = range != null ? ` ${range}` : ""; return `[${parts.join(" ")}] =${suffix}`; } - -function serializeCodeRange(codeLines: string[], range: Range): string { - const { start, end } = range; - const lines: string[] = []; - - codeLines.forEach((codeLine, lineNumber) => { - lines.push( - codeLine.length > 0 ? `${lineNumber}| ${codeLine}` : `${lineNumber}|`, - ); - - if (lineNumber === start.line) { - const prefix = fill(" ", start.character + 2) + ">"; - if (start.line === end.line) { - lines.push(prefix + fill("-", end.character - start.character) + "<"); - } else { - lines.push(prefix + fill("-", codeLine.length - start.character)); - } - } else if (lineNumber > start.line && lineNumber < end.line) { - if (codeLine.length > 0) { - lines.push(" " + fill("-", codeLine.length)); - } else { - lines.push(""); - } - } else if (lineNumber === end.line) { - lines.push(" " + fill("-", end.character) + "<"); - } else { - lines.push(""); - } - }); - - return lines.join("\n"); -} - -function fill(character: string, count: number): string { - return new Array(count + 1).join(character); -} diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeTargetRange.ts b/packages/cursorless-vscode-e2e/src/suite/serializeTargetRange.ts new file mode 100644 index 0000000000..ba02725aa0 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/serializeTargetRange.ts @@ -0,0 +1,65 @@ +import { Range } from "@cursorless/common"; + +/** + * Given the code of a fixture and a range, return a string that annotates the + * range in the code. For example, given the code: + * + * ``` + * aaa bbb + * ccc + * + * ddd eee + * ``` + * + * and the range (0, 4)-(3, 3), this function will return: + * + * ``` + * 0| aaa bbb + * >--- + * 1| ccc + * --- + * 2| + * + * 3| ddd eee + * ---< + * ``` + * + * @param codeLines The code of the fixture, split into lines + * @param range The range to represent + * @returns A string that annotates {@link range} in {@link codeLines} + */ +export function serializeTargetRange(codeLines: string[], range: Range): string { + const { start, end } = range; + const lines: string[] = []; + + codeLines.forEach((codeLine, lineNumber) => { + // Output the line itself, prefixed by `n| `, eg `3| const foo = "bar"` + lines.push( + codeLine.length > 0 ? `${lineNumber}| ${codeLine}` : `${lineNumber}|` + ); + + if (lineNumber === start.line) { + const prefix = fill(" ", start.character + 2) + ">"; + if (start.line === end.line) { + lines.push(prefix + fill("-", end.character - start.character) + "<"); + } else { + lines.push(prefix + fill("-", codeLine.length - start.character)); + } + } else if (lineNumber > start.line && lineNumber < end.line) { + if (codeLine.length > 0) { + lines.push(" " + fill("-", codeLine.length)); + } else { + lines.push(""); + } + } else if (lineNumber === end.line) { + lines.push(" " + fill("-", end.character) + "<"); + } else { + lines.push(""); + } + }); + + return lines.join("\n"); +} +function fill(character: string, count: number): string { + return new Array(count + 1).join(character); +} From 2f51f657a43a111ecfe4c2e0e7c0c80feb20d023 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:48:04 +0000 Subject: [PATCH 51/71] [pre-commit.ci lite] apply automatic fixes --- .../src/suite/serializeTargetRange.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeTargetRange.ts b/packages/cursorless-vscode-e2e/src/suite/serializeTargetRange.ts index ba02725aa0..13f5360478 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeTargetRange.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeTargetRange.ts @@ -28,14 +28,17 @@ import { Range } from "@cursorless/common"; * @param range The range to represent * @returns A string that annotates {@link range} in {@link codeLines} */ -export function serializeTargetRange(codeLines: string[], range: Range): string { +export function serializeTargetRange( + codeLines: string[], + range: Range, +): string { const { start, end } = range; const lines: string[] = []; codeLines.forEach((codeLine, lineNumber) => { // Output the line itself, prefixed by `n| `, eg `3| const foo = "bar"` lines.push( - codeLine.length > 0 ? `${lineNumber}| ${codeLine}` : `${lineNumber}|` + codeLine.length > 0 ? `${lineNumber}| ${codeLine}` : `${lineNumber}|`, ); if (lineNumber === start.line) { From 459761cea0368d1ca963c834e44c17c6e5bce242 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:56:38 +0000 Subject: [PATCH 52/71] More cleanup --- .../src/suite/serializeScopeFixture.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts index 80a3768472..20c38ca87f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts @@ -92,10 +92,9 @@ function serializeTarget({ range: index === headers.length - 1 ? target.contentRange : undefined, }), ), + serializeTargetRange(codeLines, target.contentRange), ); - lines.push(serializeTargetRange(codeLines, target.contentRange)); - // Add separate removal header below content if their ranges are not equal if (!target.contentRange.isRangeEqual(target.removalRange)) { lines.push( @@ -192,10 +191,8 @@ function serializeTargetInsertionDelimiter( scopeIndex, targetIndex, }); - const delimiter = target.insertionDelimiter - .replaceAll("\r\n", "\\r\\n") - .replaceAll("\n", "\\n"); - return `\n${header} "${delimiter}"`; + + return `\n${header} ${JSON.stringify(target.insertionDelimiter)}`; } interface SerializedTargetBasicsArg { From c096e8a4cc32189ff6a72f16bc017b5cde77d3d0 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:58:15 +0000 Subject: [PATCH 53/71] More tweaks --- .../cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts index 20c38ca87f..e27ece8d6f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts @@ -221,8 +221,8 @@ function serializeTargetBasics({ targetIndex, range: target.contentRange, }), + serializeTargetRange(codeLines, target.contentRange), ); - lines.push(serializeTargetRange(codeLines, target.contentRange)); } else { lines.push( serializeHeader({ From ac9091430727f89aa9538669582de4ac786520ab Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:02:00 +0000 Subject: [PATCH 54/71] fix tests --- .../cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 3b9b1d42a6..48d554a4be 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -92,12 +92,12 @@ async function runTest(file: string, languageId: string, facetId: string) { .replaceAll("\r\n", "\n"); const delimiterIndex = fixture.match(/^---$/m)?.index; - assert.ok( - delimiterIndex != null, + assert.isNotNull( + delimiterIndex, "Can't find delimiter '---' in scope fixture", ); - const code = fixture.slice(0, delimiterIndex); + const code = fixture.slice(0, delimiterIndex! - 1); await openNewEditor(code, { languageId }); From da04e0332020c7725b36c57721b1975cb18c1f74 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:05:00 +0000 Subject: [PATCH 55/71] more cleanup --- .../src/suite/serializeScopeFixture.ts | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts index e27ece8d6f..76c8aa1f02 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts @@ -111,7 +111,7 @@ function serializeTarget({ if (target.leadingDelimiter != null) { lines.push( - serializeTargetBasics({ + serializeTargetCompact({ codeLines, target: target.leadingDelimiter, prefix: "Leading delimiter", @@ -123,7 +123,7 @@ function serializeTarget({ if (target.trailingDelimiter != null) { lines.push( - serializeTargetBasics({ + serializeTargetCompact({ codeLines, target: target.trailingDelimiter, prefix: "Trailing delimiter", @@ -136,7 +136,7 @@ function serializeTarget({ if (target.interior != null) { lines.push( ...target.interior.map((interior) => - serializeTargetBasics({ + serializeTargetCompact({ codeLines, target: interior, prefix: "Interior", @@ -150,7 +150,7 @@ function serializeTarget({ if (target.boundary != null) { lines.push( ...target.boundary.map((interior) => - serializeTargetBasics({ + serializeTargetCompact({ codeLines, target: interior, prefix: "Boundary", @@ -195,7 +195,7 @@ function serializeTargetInsertionDelimiter( return `\n${header} ${JSON.stringify(target.insertionDelimiter)}`; } -interface SerializedTargetBasicsArg { +interface SerializedTargetCompactArg { codeLines: string[]; target: TargetRanges; prefix: string | undefined; @@ -203,13 +203,20 @@ interface SerializedTargetBasicsArg { targetIndex: number | undefined; } -function serializeTargetBasics({ +/** + * Given a target, serialize it compactly, including only the content and + * removal ranges. We use this for auxiliary targets like delimiters and + * interior/boundary targets of a target that we're serializing. + * @param arg Configuration object + * @returns A string representing the target + */ +function serializeTargetCompact({ codeLines, target, prefix, scopeIndex, targetIndex, -}: SerializedTargetBasicsArg): string { +}: SerializedTargetCompactArg): string { const lines: string[] = [""]; if (target.contentRange.isRangeEqual(target.removalRange)) { From 637d8eaab465b866e5d42c6d2949d5398630eada Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:16:49 +0000 Subject: [PATCH 56/71] more cleanup --- .../src/suite/serializeHeader.ts | 53 +++++++++++++++++++ .../src/suite/serializeScopeFixture.ts | 45 ++-------------- 2 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts new file mode 100644 index 0000000000..430fa8b2e9 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts @@ -0,0 +1,53 @@ +import { Range } from "@cursorless/common"; + +interface SerializeHeaderArg { + prefix?: string; + header: string | undefined; + scopeIndex: number | undefined; + targetIndex: number | undefined; + range?: Range; +} + +/** + * Constructs a header string from a configuration object. For example: + * + * ``` + * serializeHeader({ + * prefix: "Leading delimiter", + * header: "Content", + * scopeIndex: 1, + * targetIndex: 2, + * range: new Range(new Position(1, 2), new Position(3, 4)), + * }) === "[#1 Leading delimiter: Content 2] =1:2-3:4" + * ``` + * + * @param param A configuration object + * @returns A string representing the header + */ +export function serializeHeader({ + prefix, + header, + scopeIndex, + targetIndex, + range, +}: SerializeHeaderArg): string { + const parts: string[] = []; + if (scopeIndex != null) { + parts.push(`#${scopeIndex}`); + } + if (prefix != null) { + if (header != null) { + parts.push(prefix + ":"); + } else { + parts.push(prefix); + } + } + if (header != null) { + parts.push(header); + } + if (targetIndex != null) { + parts.push(targetIndex.toString()); + } + const suffix = range != null ? ` ${range}` : ""; + return `[${parts.join(" ")}] =${suffix}`; +} diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts index 76c8aa1f02..8f6e6cd68d 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts @@ -1,5 +1,6 @@ import { Range, ScopeRanges, TargetRanges } from "@cursorless/common"; import { serializeTargetRange } from "./serializeTargetRange"; +import { serializeHeader } from "./serializeHeader"; export function serializeScopeFixture( code: string, @@ -56,7 +57,7 @@ function serializeScope( ].join("\n"); } -interface SerializedTargetArg { +interface SerializeTargetArg { codeLines: string[]; target: TargetRanges; scopeIndex: number | undefined; @@ -70,7 +71,7 @@ function serializeTarget({ scopeIndex, targetIndex, domain, -}: SerializedTargetArg): string { +}: SerializeTargetArg): string { const lines: string[] = [""]; const headers = ["Content"]; @@ -195,7 +196,7 @@ function serializeTargetInsertionDelimiter( return `\n${header} ${JSON.stringify(target.insertionDelimiter)}`; } -interface SerializedTargetCompactArg { +interface SerializeTargetCompactArg { codeLines: string[]; target: TargetRanges; prefix: string | undefined; @@ -216,7 +217,7 @@ function serializeTargetCompact({ prefix, scopeIndex, targetIndex, -}: SerializedTargetCompactArg): string { +}: SerializeTargetCompactArg): string { const lines: string[] = [""]; if (target.contentRange.isRangeEqual(target.removalRange)) { @@ -253,39 +254,3 @@ function serializeTargetCompact({ return lines.join("\n"); } - -interface SerializeHeaderArg { - prefix?: string; - header: string | undefined; - scopeIndex: number | undefined; - targetIndex: number | undefined; - range?: Range; -} - -function serializeHeader({ - prefix, - header, - scopeIndex, - targetIndex, - range, -}: SerializeHeaderArg): string { - const parts: string[] = []; - if (scopeIndex != null) { - parts.push(`#${scopeIndex}`); - } - if (prefix != null) { - if (header != null) { - parts.push(prefix + ":"); - } else { - parts.push(prefix); - } - } - if (header != null) { - parts.push(header); - } - if (targetIndex != null) { - parts.push(targetIndex.toString()); - } - const suffix = range != null ? ` ${range}` : ""; - return `[${parts.join(" ")}] =${suffix}`; -} From aa05a6576168d70f7334a634cb5a6741f5297c2f Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 30 Nov 2023 18:46:01 +0100 Subject: [PATCH 57/71] Update target number --- .../src/suite/serializeScopes.ts | 82 ++++++++++--------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts index c138ed6e1e..382de195e1 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopes.ts @@ -19,13 +19,13 @@ export function serializeScopes(code: string, scopes: ScopeRanges[]): string { function serializeScope( codeLines: string[], scope: ScopeRanges, - scopeIndex: number | undefined, + scopeNumber: number | undefined, ): string { if (scope.targets.length === 1) { return serializeTarget( codeLines, scope.targets[0], - scopeIndex, + scopeNumber, undefined, scope.domain, ); @@ -37,12 +37,12 @@ function serializeScope( serializeTarget( codeLines, target, - scopeIndex, + scopeNumber, scope.targets.length > 1 ? index + 1 : undefined, ), ), "", - serializeHeader(undefined, "Domain", scopeIndex, undefined, scope.domain), + serializeHeader(undefined, "Domain", scopeNumber, undefined, scope.domain), serializeCodeRange(codeLines, scope.domain), ].join("\n"); } @@ -50,8 +50,8 @@ function serializeScope( function serializeTarget( codeLines: string[], target: TargetRanges, - scopeIndex: number | undefined, - targetIndex: number | undefined, + scopeNumber: number | undefined, + targetNumber: number | undefined, domain?: Range, ): string { const lines: string[] = [""]; @@ -71,8 +71,8 @@ function serializeTarget( serializeHeader( undefined, header, - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, index === headers.length - 1 ? target.contentRange : undefined, ), ), @@ -87,8 +87,8 @@ function serializeTarget( serializeHeader( undefined, "Removal", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, target.removalRange, ), serializeCodeRange(codeLines, target.removalRange), @@ -101,8 +101,8 @@ function serializeTarget( codeLines, target.leadingDelimiter, "Leading delimiter", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, ), ); } @@ -113,8 +113,8 @@ function serializeTarget( codeLines, target.trailingDelimiter, "Trailing delimiter", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, ), ); } @@ -126,8 +126,8 @@ function serializeTarget( codeLines, interior, "Interior", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, ), ), ); @@ -140,8 +140,8 @@ function serializeTarget( codeLines, interior, "Boundary", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, ), ), ); @@ -150,13 +150,13 @@ function serializeTarget( if (domain != null && !target.contentRange.isRangeEqual(domain)) { lines.push( "", - serializeHeader(undefined, "Domain", scopeIndex, targetIndex, domain), + serializeHeader(undefined, "Domain", scopeNumber, targetNumber, domain), serializeCodeRange(codeLines, domain), ); } lines.push( - serializeTargetInsertionDelimiter(target, scopeIndex, targetIndex), + serializeTargetInsertionDelimiter(target, scopeNumber, targetNumber), ); return lines.join("\n"); @@ -164,14 +164,14 @@ function serializeTarget( function serializeTargetInsertionDelimiter( target: TargetRanges, - scopeIndex: number | undefined, - targetIndex: number | undefined, + scopeNumber: number | undefined, + targetNumber: number | undefined, ): string { const header = serializeHeader( undefined, "Insertion delimiter", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, ); const delimiter = target.insertionDelimiter .replaceAll("\r\n", "\\r\\n") @@ -183,8 +183,8 @@ function serializeTargetBasics( codeLines: string[], target: TargetRanges, prefix: string | undefined, - scopeIndex: number | undefined, - targetIndex: number | undefined, + scopeNumber: number | undefined, + targetNumber: number | undefined, ): string { const lines: string[] = [""]; @@ -193,8 +193,8 @@ function serializeTargetBasics( serializeHeader( prefix, undefined, - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, target.contentRange, ), ); @@ -204,16 +204,16 @@ function serializeTargetBasics( serializeHeader( prefix, "Content", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, target.contentRange, ), serializeCodeRange(codeLines, target.contentRange), serializeHeader( prefix, "Removal", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, target.removalRange, ), serializeCodeRange(codeLines, target.removalRange), @@ -226,14 +226,19 @@ function serializeTargetBasics( function serializeHeader( prefix: string | undefined, header: string | undefined, - scopeIndex: number | undefined, - targetIndex: number | undefined, + scopeNumber: number | undefined, + targetNumber: number | undefined, range?: Range, ): string { const parts: string[] = []; - if (scopeIndex != null) { - parts.push(`#${scopeIndex}`); + if (scopeNumber != null || targetNumber != null) { + if (targetNumber != null) { + parts.push(`#${scopeNumber ?? 1}.${targetNumber}`); + } else { + parts.push(`#${scopeNumber}`); + } } + if (prefix != null) { if (header != null) { parts.push(prefix + ":"); @@ -241,12 +246,11 @@ function serializeHeader( parts.push(prefix); } } + if (header != null) { parts.push(header); } - if (targetIndex != null) { - parts.push(targetIndex.toString()); - } + const suffix = range != null ? ` ${range.toString()}` : ""; return `[${parts.join(" ")}] =${suffix}`; } From 35718a33ff40e990833fbd20bf11322d1fd47b2f Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 30 Nov 2023 18:50:57 +0100 Subject: [PATCH 58/71] use number instead of index --- .../src/suite/serializeHeader.ts | 22 ++--- .../src/suite/serializeScopeFixture.ts | 80 +++++++++---------- 2 files changed, 53 insertions(+), 49 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts index 430fa8b2e9..06c57420de 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts @@ -3,8 +3,8 @@ import { Range } from "@cursorless/common"; interface SerializeHeaderArg { prefix?: string; header: string | undefined; - scopeIndex: number | undefined; - targetIndex: number | undefined; + scopeNumber: number | undefined; + targetNumber: number | undefined; range?: Range; } @@ -27,14 +27,19 @@ interface SerializeHeaderArg { export function serializeHeader({ prefix, header, - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, range, }: SerializeHeaderArg): string { const parts: string[] = []; - if (scopeIndex != null) { - parts.push(`#${scopeIndex}`); + if (scopeNumber != null || targetNumber != null) { + if (targetNumber != null) { + parts.push(`#${scopeNumber ?? 1}.${targetNumber}`); + } else { + parts.push(`#${scopeNumber}`); + } } + if (prefix != null) { if (header != null) { parts.push(prefix + ":"); @@ -42,12 +47,11 @@ export function serializeHeader({ parts.push(prefix); } } + if (header != null) { parts.push(header); } - if (targetIndex != null) { - parts.push(targetIndex.toString()); - } + const suffix = range != null ? ` ${range}` : ""; return `[${parts.join(" ")}] =${suffix}`; } diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts index 8f6e6cd68d..fd90d98258 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts @@ -24,14 +24,14 @@ export function serializeScopeFixture( function serializeScope( codeLines: string[], { domain, targets }: ScopeRanges, - scopeIndex: number | undefined, + scopeNumber: number | undefined, ): string { if (targets.length === 1) { return serializeTarget({ codeLines, target: targets[0], - scopeIndex, - targetIndex: undefined, + scopeNumber, + targetNumber: undefined, domain, }); } @@ -42,15 +42,15 @@ function serializeScope( serializeTarget({ codeLines, target, - scopeIndex, - targetIndex: index + 1, + scopeNumber, + targetNumber: index + 1, }), ), "", serializeHeader({ header: "Domain", - scopeIndex, - targetIndex: undefined, + scopeNumber, + targetNumber: undefined, range: domain, }), serializeTargetRange(codeLines, domain), @@ -60,16 +60,16 @@ function serializeScope( interface SerializeTargetArg { codeLines: string[]; target: TargetRanges; - scopeIndex: number | undefined; - targetIndex: number | undefined; + scopeNumber: number | undefined; + targetNumber: number | undefined; domain?: Range; } function serializeTarget({ codeLines, target, - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, domain, }: SerializeTargetArg): string { const lines: string[] = [""]; @@ -88,8 +88,8 @@ function serializeTarget({ ...headers.map((header, index) => serializeHeader({ header, - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, range: index === headers.length - 1 ? target.contentRange : undefined, }), ), @@ -102,8 +102,8 @@ function serializeTarget({ "", serializeHeader({ header: "Removal", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, range: target.removalRange, }), serializeTargetRange(codeLines, target.removalRange), @@ -116,8 +116,8 @@ function serializeTarget({ codeLines, target: target.leadingDelimiter, prefix: "Leading delimiter", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, }), ); } @@ -128,8 +128,8 @@ function serializeTarget({ codeLines, target: target.trailingDelimiter, prefix: "Trailing delimiter", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, }), ); } @@ -141,8 +141,8 @@ function serializeTarget({ codeLines, target: interior, prefix: "Interior", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, }), ), ); @@ -155,8 +155,8 @@ function serializeTarget({ codeLines, target: interior, prefix: "Boundary", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, }), ), ); @@ -167,8 +167,8 @@ function serializeTarget({ "", serializeHeader({ header: "Domain", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, range: domain, }), serializeTargetRange(codeLines, domain), @@ -176,7 +176,7 @@ function serializeTarget({ } lines.push( - serializeTargetInsertionDelimiter(target, scopeIndex, targetIndex), + serializeTargetInsertionDelimiter(target, scopeNumber, targetNumber), ); return lines.join("\n"); @@ -184,13 +184,13 @@ function serializeTarget({ function serializeTargetInsertionDelimiter( target: TargetRanges, - scopeIndex: number | undefined, - targetIndex: number | undefined, + scopeNumber: number | undefined, + targetNumber: number | undefined, ): string { const header = serializeHeader({ header: "Insertion delimiter", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, }); return `\n${header} ${JSON.stringify(target.insertionDelimiter)}`; @@ -200,8 +200,8 @@ interface SerializeTargetCompactArg { codeLines: string[]; target: TargetRanges; prefix: string | undefined; - scopeIndex: number | undefined; - targetIndex: number | undefined; + scopeNumber: number | undefined; + targetNumber: number | undefined; } /** @@ -215,8 +215,8 @@ function serializeTargetCompact({ codeLines, target, prefix, - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, }: SerializeTargetCompactArg): string { const lines: string[] = [""]; @@ -225,8 +225,8 @@ function serializeTargetCompact({ serializeHeader({ prefix, header: undefined, - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, range: target.contentRange, }), serializeTargetRange(codeLines, target.contentRange), @@ -236,16 +236,16 @@ function serializeTargetCompact({ serializeHeader({ prefix, header: "Content", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, range: target.contentRange, }), serializeTargetRange(codeLines, target.contentRange), serializeHeader({ prefix, header: "Removal", - scopeIndex, - targetIndex, + scopeNumber, + targetNumber, range: target.removalRange, }), serializeTargetRange(codeLines, target.removalRange), From 12e7588cc77ad44e2b84573097810005e3cb0c37 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 30 Nov 2023 18:57:59 +0100 Subject: [PATCH 59/71] Support subdirectories --- packages/common/src/testUtil/getFixturePaths.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common/src/testUtil/getFixturePaths.ts b/packages/common/src/testUtil/getFixturePaths.ts index a71b59c9b4..c28486ee15 100644 --- a/packages/common/src/testUtil/getFixturePaths.ts +++ b/packages/common/src/testUtil/getFixturePaths.ts @@ -46,7 +46,7 @@ export function getScopeTestPaths() { .map((p) => ({ path: p, name: path.relative(relativeDir, p.substring(0, p.lastIndexOf("."))), - languageId: path.dirname(path.relative(directory, p)), + languageId: path.dirname(path.relative(directory, p)).split(path.sep)[0], facet: path.basename(p).match(/([a-zA-Z.]+)\d*\.scope/)![1], })); } From b0f4fef69a422f65aaed996edecd32e904a58c88 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 30 Nov 2023 18:59:50 +0100 Subject: [PATCH 60/71] Updated comment --- packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts index 06c57420de..109e126176 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts @@ -15,10 +15,10 @@ interface SerializeHeaderArg { * serializeHeader({ * prefix: "Leading delimiter", * header: "Content", - * scopeIndex: 1, - * targetIndex: 2, + * scopeNumber: 1, + * targetNumber: 2, * range: new Range(new Position(1, 2), new Position(3, 4)), - * }) === "[#1 Leading delimiter: Content 2] =1:2-3:4" + * }) === "[#1.2 Leading delimiter: Content] = 1:2-3:4" * ``` * * @param param A configuration object From 06d00b45ce23e45e7fb9343f1bd80c5ae97c3c51 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Thu, 30 Nov 2023 20:28:08 +0100 Subject: [PATCH 61/71] Added element tags facet --- .../getLanguageScopeSupport.ts | 3 +++ .../common/src/scopeSupportFacets/html.ts | 14 +++++++++++++ .../src/scopeSupportFacets/javascript.ts | 4 +++- .../scopeSupportFacets/scopeSupportFacets.ts | 14 +++++++++++++ .../fixtures/scopes/html/key.attribute.scope | 20 +++++++++++++++++++ .../fixtures/scopes/html/tags.element.scope | 20 +++++++++++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 packages/common/src/scopeSupportFacets/html.ts create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/key.attribute.scope create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope diff --git a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts index a4379d5f12..f337620c35 100644 --- a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts +++ b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts @@ -1,3 +1,4 @@ +import { htmlSupport } from "./html"; import { javascriptSupport } from "./javascript"; import { plaintextSupport } from "./plaintext"; import { @@ -13,6 +14,8 @@ export function getLanguageScopeSupport( return plaintextSupport; case "javascript": return javascriptSupport; + case "html": + return htmlSupport; } throw Error(`Unsupported language: '${languageId}'`); } diff --git a/packages/common/src/scopeSupportFacets/html.ts b/packages/common/src/scopeSupportFacets/html.ts new file mode 100644 index 0000000000..177618c67c --- /dev/null +++ b/packages/common/src/scopeSupportFacets/html.ts @@ -0,0 +1,14 @@ +import { + LanguageScopeSupportFacetMap, + ScopeSupportFacetLevel, +} from "@cursorless/common"; + +const { supported, notApplicable } = ScopeSupportFacetLevel; + +export const htmlSupport: LanguageScopeSupportFacetMap = { + ["key.attribute"]: supported, + ["tags.element"]: supported, + namedFunction: notApplicable, + ["name.assignment"]: notApplicable, + ["value.assignment"]: notApplicable, +}; diff --git a/packages/common/src/scopeSupportFacets/javascript.ts b/packages/common/src/scopeSupportFacets/javascript.ts index 948b3dd688..bb4ce08cac 100644 --- a/packages/common/src/scopeSupportFacets/javascript.ts +++ b/packages/common/src/scopeSupportFacets/javascript.ts @@ -3,10 +3,12 @@ import { ScopeSupportFacetLevel, } from "@cursorless/common"; -const { supported } = ScopeSupportFacetLevel; +const { supported, notApplicable } = ScopeSupportFacetLevel; export const javascriptSupport: LanguageScopeSupportFacetMap = { namedFunction: supported, ["name.assignment"]: supported, ["value.assignment"]: supported, + ["key.attribute"]: notApplicable, + ["tags.element"]: notApplicable, }; diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts index b6fb6972f9..1f9b30649e 100644 --- a/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts @@ -12,6 +12,7 @@ const scopeSupportFacets = [ // "anonymousFunction", // "anonymousFunction.interior", "name.assignment", + "key.attribute", "value.assignment", // "value.assignment.removal", // "value.return", @@ -41,6 +42,7 @@ const scopeSupportFacets = [ // "class.interior", // "className", // "type", + "tags.element", ] as const; const textualScopeSupportFacets = [ @@ -79,12 +81,24 @@ export const scopeSupportFacetInfos: Record< scopeType: "name", examples: ["const foo = 1"], }, + ["key.attribute"]: { + label: "Attributes key", + description: "Key(LHS) of an attribute", + scopeType: "collectionKey", + examples: ['id="root"'], + }, ["value.assignment"]: { label: "Assignment value", description: "Value(RHS) of an assignment", scopeType: "value", examples: ["const foo = 1"], }, + ["tags.element"]: { + label: "Tags", + description: "Both tags in an xml element", + scopeType: "xmlBothTags", + examples: ["
"], + }, // list: { // label: "List", // description: "A list of items", diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/key.attribute.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/key.attribute.scope new file mode 100644 index 0000000000..6bedb626d7 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/key.attribute.scope @@ -0,0 +1,20 @@ +
+--- + +[Content] = 0:5-0:7 +0|
+ >--< + +[Removal] = 0:5-0:8 +0|
+ >---< + +[Trailing delimiter] = 0:7-0:8 +0|
+ >-< + +[Domain] = 0:5-0:14 +0|
+ >---------< + +[Insertion delimiter] = " " diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope new file mode 100644 index 0000000000..c1d9b48503 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope @@ -0,0 +1,20 @@ +
hello
+--- + +[#1.1 Content] = +[#1.1 Removal] = 0:0-0:5 +0|
hello
+ >-----< + +[#1.1 Insertion delimiter] = " " + +[#1.2 Content] = +[#1.2 Removal] = 0:10-0:16 +0|
hello
+ >------< + +[#1.2 Insertion delimiter] = " " + +[Domain] = 0:0-0:16 +0|
hello
+ >----------------< From b8c2ade42248879f201d7520a5a67b4b3eb70c2a Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Fri, 1 Dec 2023 05:15:45 +0100 Subject: [PATCH 62/71] Added iteration scope --- .../common/src/scopeSupportFacets/html.ts | 5 + .../src/scopeSupportFacets/javascript.ts | 5 + .../scopeSupportFacets/scopeSupportFacets.ts | 36 ++++++- .../javascript/key.mapPair.iteration.scope | 7 ++ .../scopes/javascript/key.mapPair.scope | 20 ++++ .../javascript/value.mapPair.iteration.scope | 13 +++ .../scopes/javascript/value.mapPair.scope | 20 ++++ .../src/suite/scopes.vscode.test.ts | 54 ++++++++--- .../src/suite/serializeScopeFixture.ts | 94 ++++++++++++++++--- 9 files changed, 227 insertions(+), 27 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/key.mapPair.iteration.scope create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/key.mapPair.scope create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.mapPair.iteration.scope create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.mapPair.scope diff --git a/packages/common/src/scopeSupportFacets/html.ts b/packages/common/src/scopeSupportFacets/html.ts index 177618c67c..b68cd9d0ff 100644 --- a/packages/common/src/scopeSupportFacets/html.ts +++ b/packages/common/src/scopeSupportFacets/html.ts @@ -8,7 +8,12 @@ const { supported, notApplicable } = ScopeSupportFacetLevel; export const htmlSupport: LanguageScopeSupportFacetMap = { ["key.attribute"]: supported, ["tags.element"]: supported, + namedFunction: notApplicable, ["name.assignment"]: notApplicable, + ["key.mapPair"]: notApplicable, + ["key.mapPair.iteration"]: notApplicable, + ["value.mapPair"]: notApplicable, + ["value.mapPair.iteration"]: notApplicable, ["value.assignment"]: notApplicable, }; diff --git a/packages/common/src/scopeSupportFacets/javascript.ts b/packages/common/src/scopeSupportFacets/javascript.ts index bb4ce08cac..cc20d63846 100644 --- a/packages/common/src/scopeSupportFacets/javascript.ts +++ b/packages/common/src/scopeSupportFacets/javascript.ts @@ -8,7 +8,12 @@ const { supported, notApplicable } = ScopeSupportFacetLevel; export const javascriptSupport: LanguageScopeSupportFacetMap = { namedFunction: supported, ["name.assignment"]: supported, + ["key.mapPair"]: notApplicable, + ["key.mapPair.iteration"]: notApplicable, + ["value.mapPair"]: notApplicable, + ["value.mapPair.iteration"]: notApplicable, ["value.assignment"]: supported, + ["key.attribute"]: notApplicable, ["tags.element"]: notApplicable, }; diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts index 1f9b30649e..3d415d7453 100644 --- a/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts @@ -13,7 +13,11 @@ const scopeSupportFacets = [ // "anonymousFunction.interior", "name.assignment", "key.attribute", + "key.mapPair", + "key.mapPair.iteration", "value.assignment", + "value.mapPair", + "value.mapPair.iteration", // "value.assignment.removal", // "value.return", // "value.return.removal", @@ -62,6 +66,7 @@ export interface ScopeSupportFacetInfo { label: string; description: string; scopeType: SimpleScopeTypeType; + isIteration?: boolean; examples: string[]; } @@ -87,12 +92,38 @@ export const scopeSupportFacetInfos: Record< scopeType: "collectionKey", examples: ['id="root"'], }, + ["key.mapPair"]: { + label: "Map key", + description: "Key(LHS) of a map pair", + scopeType: "collectionKey", + examples: ["value: 0"], + }, + ["key.mapPair.iteration"]: { + label: "Map pair key iteration", + description: "Iteration of map pair keys", + scopeType: "collectionKey", + isIteration: true, + examples: ["{ value: 0 }"], + }, ["value.assignment"]: { label: "Assignment value", description: "Value(RHS) of an assignment", scopeType: "value", examples: ["const foo = 1"], }, + ["value.mapPair"]: { + label: "Map pair value", + description: "Key(RHS) of a map pair", + scopeType: "value", + examples: ["value: 0"], + }, + ["value.mapPair.iteration"]: { + label: "Map pair value iteration", + description: "Iteration of map pair values", + scopeType: "value", + isIteration: true, + examples: ["{ value: 0 }"], + }, ["tags.element"]: { label: "Tags", description: "Both tags in an xml element", @@ -170,9 +201,8 @@ export enum ScopeSupportFacetLevel { notApplicable, } -export type LanguageScopeSupportFacetMap = Record< - ScopeSupportFacet, - ScopeSupportFacetLevel +export type LanguageScopeSupportFacetMap = Partial< + Record >; export type TextualLanguageScopeSupportFacetMap = Record< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/key.mapPair.iteration.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/key.mapPair.iteration.scope new file mode 100644 index 0000000000..6802f51c3a --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/key.mapPair.iteration.scope @@ -0,0 +1,7 @@ +{ value: 123 } +--- + +[Range] = +[Domain] = 0:1-0:13 +0| { value: 123 } + >------------< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/key.mapPair.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/key.mapPair.scope new file mode 100644 index 0000000000..12ed6538b7 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/key.mapPair.scope @@ -0,0 +1,20 @@ +{ value: 123 } +--- + +[Content] = 0:2-0:7 +0| { value: 123 } + >-----< + +[Removal] = 0:2-0:9 +0| { value: 123 } + >-------< + +[Trailing delimiter] = 0:7-0:9 +0| { value: 123 } + >--< + +[Domain] = 0:2-0:12 +0| { value: 123 } + >----------< + +[Insertion delimiter] = " " diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.mapPair.iteration.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.mapPair.iteration.scope new file mode 100644 index 0000000000..50f1cdca8c --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.mapPair.iteration.scope @@ -0,0 +1,13 @@ +{ value: 123 } +--- + +[#1 Range] = +[#1 Domain] = 0:0-0:14 +0| { value: 123 } + >--------------< + + +[#2 Range] = +[#2 Domain] = 0:1-0:13 +0| { value: 123 } + >------------< diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.mapPair.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.mapPair.scope new file mode 100644 index 0000000000..ef3761a512 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/javascript/value.mapPair.scope @@ -0,0 +1,20 @@ +{ value: 123 } +--- + +[Content] = 0:9-0:12 +0| { value: 123 } + >---< + +[Removal] = 0:7-0:12 +0| { value: 123 } + >-----< + +[Leading delimiter] = 0:7-0:9 +0| { value: 123 } + >--< + +[Domain] = 0:2-0:12 +0| { value: 123 } + >----------< + +[Insertion delimiter] = " " diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 48d554a4be..adcbac495c 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -15,7 +15,10 @@ import { assert } from "chai"; import { groupBy, uniq } from "lodash"; import { promises as fsp } from "node:fs"; import { endToEndTestSetup } from "../endToEndTestSetup"; -import { serializeScopeFixture } from "./serializeScopeFixture"; +import { + serializeIterationScopeFixture, + serializeScopeFixture, +} from "./serializeScopeFixture"; suite("Scope test cases", async function () { endToEndTestSetup(this); @@ -86,7 +89,7 @@ async function testLanguageSupport(languageId: string, testedFacets: string[]) { async function runTest(file: string, languageId: string, facetId: string) { const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; - const scopeType = getScopeType(facetId); + const { scopeType, isIteration } = getScopeType(facetId); const fixture = (await fsp.readFile(file, "utf8")) .toString() .replaceAll("\r\n", "\n"); @@ -103,12 +106,27 @@ async function runTest(file: string, languageId: string, facetId: string) { const editor = ide.activeTextEditor!; - const scopes = scopeProvider.provideScopeRanges(editor, { - visibleOnly: false, - scopeType, - }); + const outputFixture = ((): string => { + const config = { + visibleOnly: false, + scopeType, + }; + + if (isIteration) { + const iterationScopes = scopeProvider.provideIterationScopeRanges( + editor, + { + ...config, + includeNestedTargets: false, + }, + ); + return serializeIterationScopeFixture(code, iterationScopes); + } + + const scopes = scopeProvider.provideScopeRanges(editor, config); - const outputFixture = serializeScopeFixture(code, scopes); + return serializeScopeFixture(code, scopes); + })(); if (shouldUpdateFixtures()) { await fsp.writeFile(file, outputFixture); @@ -117,15 +135,25 @@ async function runTest(file: string, languageId: string, facetId: string) { } } -function getScopeType(facetId: string): ScopeType { +function getScopeType(facetId: string): { + scopeType: ScopeType; + isIteration: boolean; +} { if (facetId in textualScopeSupportFacetInfos) { - const { scopeType } = + const { scopeType, isIteration } = textualScopeSupportFacetInfos[facetId as TextualScopeSupportFacet]; - return { type: scopeType }; + return { + scopeType: { type: scopeType }, + isIteration: isIteration ?? false, + }; } if (facetId in scopeSupportFacetInfos) { - const { scopeType } = scopeSupportFacetInfos[facetId as ScopeSupportFacet]; - return { type: scopeType }; + const { scopeType, isIteration } = + scopeSupportFacetInfos[facetId as ScopeSupportFacet]; + return { + scopeType: { type: scopeType }, + isIteration: isIteration ?? false, + }; } - throw Error(`Unknown facetId '${facetId}'`); + throw Error(`Unknown facet '${facetId}'`); } diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts index fd90d98258..fdc0c39a3b 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeScopeFixture.ts @@ -1,6 +1,11 @@ -import { Range, ScopeRanges, TargetRanges } from "@cursorless/common"; -import { serializeTargetRange } from "./serializeTargetRange"; +import { + IterationScopeRanges, + Range, + ScopeRanges, + TargetRanges, +} from "@cursorless/common"; import { serializeHeader } from "./serializeHeader"; +import { serializeTargetRange } from "./serializeTargetRange"; export function serializeScopeFixture( code: string, @@ -8,15 +13,35 @@ export function serializeScopeFixture( ): string { const codeLines = code.split("\n"); - const serializedScopes = scopes - .map((scope, index) => - serializeScope( - codeLines, - scope, - scopes.length > 1 ? index + 1 : undefined, - ), - ) - .join("\n\n"); + const serializedScopes = scopes.map((scope, index) => + serializeScope(codeLines, scope, scopes.length > 1 ? index + 1 : undefined), + ); + + return serializeScopeFixtureHelper(codeLines, serializedScopes); +} + +export function serializeIterationScopeFixture( + code: string, + scopes: IterationScopeRanges[], +): string { + const codeLines = code.split("\n"); + + const serializedScopes = scopes.map((scope, index) => + serializeIterationScope( + codeLines, + scope, + scopes.length > 1 ? index + 1 : undefined, + ), + ); + + return serializeScopeFixtureHelper(codeLines, serializedScopes); +} + +function serializeScopeFixtureHelper( + codeLines: string[], + scopes: string[], +): string { + const serializedScopes = scopes.join("\n\n"); return [...codeLines, "---", serializedScopes, ""].join("\n"); } @@ -57,6 +82,53 @@ function serializeScope( ].join("\n"); } +function serializeIterationScope( + codeLines: string[], + { domain, ranges }: IterationScopeRanges, + scopeNumber: number | undefined, +): string { + const lines: string[] = [""]; + + const groupHeaders = !ranges.some( + (range) => !domain.isRangeEqual(range.range), + ); + + ranges.forEach((range, index) => { + if (!groupHeaders && index > 0) { + lines.push(""); + } + + lines.push( + serializeHeader({ + header: "Range", + scopeNumber, + targetNumber: ranges.length > 1 ? index + 1 : undefined, + range: groupHeaders ? undefined : range.range, + }), + ); + + if (!groupHeaders) { + lines.push(serializeTargetRange(codeLines, range.range)); + } + }); + + if (!groupHeaders) { + lines.push(""); + } + + lines.push( + serializeHeader({ + header: "Domain", + scopeNumber, + targetNumber: undefined, + range: domain, + }), + serializeTargetRange(codeLines, domain), + ); + + return lines.join("\n"); +} + interface SerializeTargetArg { codeLines: string[]; target: TargetRanges; From 5f1d1785f9bd782af224015747689dd9b15a77bd Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Fri, 1 Dec 2023 05:55:13 +0100 Subject: [PATCH 63/71] Up date javascript support --- packages/common/src/scopeSupportFacets/javascript.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/common/src/scopeSupportFacets/javascript.ts b/packages/common/src/scopeSupportFacets/javascript.ts index cc20d63846..66d1474cb0 100644 --- a/packages/common/src/scopeSupportFacets/javascript.ts +++ b/packages/common/src/scopeSupportFacets/javascript.ts @@ -8,10 +8,10 @@ const { supported, notApplicable } = ScopeSupportFacetLevel; export const javascriptSupport: LanguageScopeSupportFacetMap = { namedFunction: supported, ["name.assignment"]: supported, - ["key.mapPair"]: notApplicable, - ["key.mapPair.iteration"]: notApplicable, - ["value.mapPair"]: notApplicable, - ["value.mapPair.iteration"]: notApplicable, + ["key.mapPair"]: supported, + ["key.mapPair.iteration"]: supported, + ["value.mapPair"]: supported, + ["value.mapPair.iteration"]: supported, ["value.assignment"]: supported, ["key.attribute"]: notApplicable, From 93d36d0a9fb69e31b704996ee73e58b48291e35e Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Fri, 1 Dec 2023 12:46:31 +0100 Subject: [PATCH 64/71] Update number serialization --- .../suite/fixtures/scopes/html/tags.element.scope | 12 ++++++------ .../src/suite/serializeHeader.ts | 9 ++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope index c1d9b48503..8d3a4c60fb 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope @@ -1,19 +1,19 @@
hello
--- -[#1.1 Content] = -[#1.1 Removal] = 0:0-0:5 +[#.1 Content] = +[#.1 Removal] = 0:0-0:5 0|
hello
>-----< -[#1.1 Insertion delimiter] = " " +[#.1 Insertion delimiter] = " " -[#1.2 Content] = -[#1.2 Removal] = 0:10-0:16 +[#.2 Content] = +[#.2 Removal] = 0:10-0:16 0|
hello
>------< -[#1.2 Insertion delimiter] = " " +[#.2 Insertion delimiter] = " " [Domain] = 0:0-0:16 0|
hello
diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts index 109e126176..715de45d4f 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts @@ -33,11 +33,14 @@ export function serializeHeader({ }: SerializeHeaderArg): string { const parts: string[] = []; if (scopeNumber != null || targetNumber != null) { + const numberParts: string[] = ["#"]; + if (scopeNumber != null) { + numberParts.push(scopeNumber.toString()); + } if (targetNumber != null) { - parts.push(`#${scopeNumber ?? 1}.${targetNumber}`); - } else { - parts.push(`#${scopeNumber}`); + numberParts.push(`.${targetNumber}`); } + parts.push(numberParts.join("")); } if (prefix != null) { From b8a80a8de4e0a5021f0a26ba55484e79dfca08d4 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 2 Dec 2023 09:15:28 +0100 Subject: [PATCH 65/71] Update target number --- .../suite/fixtures/scopes/html/tags.element.scope | 12 ++++++------ .../src/suite/serializeHeader.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope index 8d3a4c60fb..10ab2153df 100644 --- a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope @@ -1,19 +1,19 @@
hello
--- -[#.1 Content] = -[#.1 Removal] = 0:0-0:5 +[.1 Content] = +[.1 Removal] = 0:0-0:5 0|
hello
>-----< -[#.1 Insertion delimiter] = " " +[.1 Insertion delimiter] = " " -[#.2 Content] = -[#.2 Removal] = 0:10-0:16 +[.2 Content] = +[.2 Removal] = 0:10-0:16 0|
hello
>------< -[#.2 Insertion delimiter] = " " +[.2 Insertion delimiter] = " " [Domain] = 0:0-0:16 0|
hello
diff --git a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts index 715de45d4f..ec54ee0876 100644 --- a/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts +++ b/packages/cursorless-vscode-e2e/src/suite/serializeHeader.ts @@ -33,9 +33,9 @@ export function serializeHeader({ }: SerializeHeaderArg): string { const parts: string[] = []; if (scopeNumber != null || targetNumber != null) { - const numberParts: string[] = ["#"]; + const numberParts: string[] = []; if (scopeNumber != null) { - numberParts.push(scopeNumber.toString()); + numberParts.push(`#${scopeNumber}`); } if (targetNumber != null) { numberParts.push(`.${targetNumber}`); From cfebfd9b57c6117115f7e7db630e79411cc9e5e6 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 5 Dec 2023 18:32:16 +0100 Subject: [PATCH 66/71] cleanup --- packages/common/src/index.ts | 5 +- .../getLanguageScopeSupport.ts | 10 +- .../common/src/scopeSupportFacets/html.ts | 4 +- .../src/scopeSupportFacets/javascript.ts | 4 +- .../scopeSupportFacetInfos.ts | 66 ++++++ .../scopeSupportFacets/scopeSupportFacets.ts | 211 ------------------ .../scopeSupportFacets.types.ts | 87 ++++++++ .../{plaintext.ts => textual.ts} | 4 +- .../textualScopeSupportFacetInfos.ts | 47 ++++ .../html/{tags.element.scope => tags.scope} | 0 .../{plaintext => textual}/character.scope | 0 .../{plaintext => textual}/document.scope | 0 .../scopes/{plaintext => textual}/line.scope | 0 .../scopes/{plaintext => textual}/line2.scope | 0 .../{plaintext => textual}/paragraph.scope | 0 .../scopes/{plaintext => textual}/token.scope | 0 .../scopes/{plaintext => textual}/word.scope | 0 .../scopes/{plaintext => textual}/word2.scope | 0 .../src/suite/scopes.vscode.test.ts | 30 +-- 19 files changed, 229 insertions(+), 239 deletions(-) create mode 100644 packages/common/src/scopeSupportFacets/scopeSupportFacetInfos.ts delete mode 100644 packages/common/src/scopeSupportFacets/scopeSupportFacets.ts create mode 100644 packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts rename packages/common/src/scopeSupportFacets/{plaintext.ts => textual.ts} (69%) create mode 100644 packages/common/src/scopeSupportFacets/textualScopeSupportFacetInfos.ts rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/{tags.element.scope => tags.scope} (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{plaintext => textual}/character.scope (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{plaintext => textual}/document.scope (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{plaintext => textual}/line.scope (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{plaintext => textual}/line2.scope (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{plaintext => textual}/paragraph.scope (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{plaintext => textual}/token.scope (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{plaintext => textual}/word.scope (100%) rename packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/{plaintext => textual}/word2.scope (100%) diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 506db2b371..f7f75fc665 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -94,5 +94,8 @@ export * from "./types/TestCaseFixture"; export * from "./util/getEnvironmentVariableStrict"; export * from "./util/CompositeKeyDefaultMap"; export * from "./util/toPlainObject"; -export * from "./scopeSupportFacets/scopeSupportFacets"; +export * from "./scopeSupportFacets/scopeSupportFacets.types"; +export * from "./scopeSupportFacets/scopeSupportFacetInfos"; +export * from "./scopeSupportFacets/textualScopeSupportFacetInfos"; export * from "./scopeSupportFacets/getLanguageScopeSupport"; +export * from "./scopeSupportFacets/textual"; diff --git a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts index f337620c35..588d470101 100644 --- a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts +++ b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts @@ -1,17 +1,11 @@ import { htmlSupport } from "./html"; import { javascriptSupport } from "./javascript"; -import { plaintextSupport } from "./plaintext"; -import { - LanguageScopeSupportFacetMap, - TextualLanguageScopeSupportFacetMap, -} from "./scopeSupportFacets"; +import { LanguageScopeSupportFacetMap } from "./scopeSupportFacets.types"; export function getLanguageScopeSupport( languageId: string, -): TextualLanguageScopeSupportFacetMap | LanguageScopeSupportFacetMap { +): LanguageScopeSupportFacetMap { switch (languageId) { - case "plaintext": - return plaintextSupport; case "javascript": return javascriptSupport; case "html": diff --git a/packages/common/src/scopeSupportFacets/html.ts b/packages/common/src/scopeSupportFacets/html.ts index b68cd9d0ff..b7428adccc 100644 --- a/packages/common/src/scopeSupportFacets/html.ts +++ b/packages/common/src/scopeSupportFacets/html.ts @@ -1,13 +1,13 @@ import { LanguageScopeSupportFacetMap, ScopeSupportFacetLevel, -} from "@cursorless/common"; +} from "./scopeSupportFacets.types"; const { supported, notApplicable } = ScopeSupportFacetLevel; export const htmlSupport: LanguageScopeSupportFacetMap = { ["key.attribute"]: supported, - ["tags.element"]: supported, + ["tags"]: supported, namedFunction: notApplicable, ["name.assignment"]: notApplicable, diff --git a/packages/common/src/scopeSupportFacets/javascript.ts b/packages/common/src/scopeSupportFacets/javascript.ts index 66d1474cb0..2242b494c5 100644 --- a/packages/common/src/scopeSupportFacets/javascript.ts +++ b/packages/common/src/scopeSupportFacets/javascript.ts @@ -1,7 +1,7 @@ import { LanguageScopeSupportFacetMap, ScopeSupportFacetLevel, -} from "@cursorless/common"; +} from "./scopeSupportFacets.types"; const { supported, notApplicable } = ScopeSupportFacetLevel; @@ -15,5 +15,5 @@ export const javascriptSupport: LanguageScopeSupportFacetMap = { ["value.assignment"]: supported, ["key.attribute"]: notApplicable, - ["tags.element"]: notApplicable, + ["tags"]: notApplicable, }; diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacetInfos.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacetInfos.ts new file mode 100644 index 0000000000..2f6096dd9b --- /dev/null +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacetInfos.ts @@ -0,0 +1,66 @@ +import { + ScopeSupportFacet, + ScopeSupportFacetInfo, +} from "./scopeSupportFacets.types"; + +export const scopeSupportFacetInfos: Record< + ScopeSupportFacet, + ScopeSupportFacetInfo +> = { + namedFunction: { + label: "Named function", + description: "A named function", + scopeType: "namedFunction", + examples: ["function foo() {}", "const foo = () => {}"], + }, + ["name.assignment"]: { + label: "Assignment name", + description: "Name(LHS) of an assignment", + scopeType: "name", + examples: ["const foo = 1"], + }, + ["key.attribute"]: { + label: "Attributes key", + description: "Key(LHS) of an attribute", + scopeType: "collectionKey", + examples: ['id="root"'], + }, + ["key.mapPair"]: { + label: "Map key", + description: "Key(LHS) of a map pair", + scopeType: "collectionKey", + examples: ["value: 0"], + }, + ["key.mapPair.iteration"]: { + label: "Map pair key iteration", + description: "Iteration of map pair keys", + scopeType: "collectionKey", + isIteration: true, + examples: ["{ value: 0 }"], + }, + ["value.assignment"]: { + label: "Assignment value", + description: "Value(RHS) of an assignment", + scopeType: "value", + examples: ["const foo = 1"], + }, + ["value.mapPair"]: { + label: "Map pair value", + description: "Key(RHS) of a map pair", + scopeType: "value", + examples: ["value: 0"], + }, + ["value.mapPair.iteration"]: { + label: "Map pair value iteration", + description: "Iteration of map pair values", + scopeType: "value", + isIteration: true, + examples: ["{ value: 0 }"], + }, + ["tags"]: { + label: "Tags", + description: "Both tags in an xml element", + scopeType: "xmlBothTags", + examples: ["
"], + }, +}; diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts deleted file mode 100644 index 3d415d7453..0000000000 --- a/packages/common/src/scopeSupportFacets/scopeSupportFacets.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { SimpleScopeTypeType } from ".."; - -const scopeSupportFacets = [ - // "list", - // "list.interior", - // "map", - // "map.interior", - // "collectionKey", - "namedFunction", - // "namedFunction.interior", - // "functionName", - // "anonymousFunction", - // "anonymousFunction.interior", - "name.assignment", - "key.attribute", - "key.mapPair", - "key.mapPair.iteration", - "value.assignment", - "value.mapPair", - "value.mapPair.iteration", - // "value.assignment.removal", - // "value.return", - // "value.return.removal", - // "value.collectionItem", - // "value.collectionItem.removal", - // "statement", - // "ifStatement", - // "condition.if", - // "condition.while", - // "condition.doWhile", - // "condition.for", - // "condition.ternary", - // "branch", - // "comment.line", - // "comment.block", - // "string.singleLine", - // "string.multiLine", - // "textFragment", - // "functionCall", - // "functionCallee", - // "argumentOrParameter.argument", - // "argumentOrParameter.argument.removal", - // "argumentOrParameter.parameter", - // "argumentOrParameter.parameter.removal", - // "class", - // "class.interior", - // "className", - // "type", - "tags.element", -] as const; - -const textualScopeSupportFacets = [ - "character", - "word", - "token", - "line", - "paragraph", - "document", -] as const; - -export type ScopeSupportFacet = (typeof scopeSupportFacets)[number]; -export type TextualScopeSupportFacet = - (typeof textualScopeSupportFacets)[number]; - -export interface ScopeSupportFacetInfo { - label: string; - description: string; - scopeType: SimpleScopeTypeType; - isIteration?: boolean; - examples: string[]; -} - -export const scopeSupportFacetInfos: Record< - ScopeSupportFacet, - ScopeSupportFacetInfo -> = { - namedFunction: { - label: "Named function", - description: "A named function", - scopeType: "namedFunction", - examples: ["function foo() {}", "const foo = () => {}"], - }, - ["name.assignment"]: { - label: "Assignment name", - description: "Name(LHS) of an assignment", - scopeType: "name", - examples: ["const foo = 1"], - }, - ["key.attribute"]: { - label: "Attributes key", - description: "Key(LHS) of an attribute", - scopeType: "collectionKey", - examples: ['id="root"'], - }, - ["key.mapPair"]: { - label: "Map key", - description: "Key(LHS) of a map pair", - scopeType: "collectionKey", - examples: ["value: 0"], - }, - ["key.mapPair.iteration"]: { - label: "Map pair key iteration", - description: "Iteration of map pair keys", - scopeType: "collectionKey", - isIteration: true, - examples: ["{ value: 0 }"], - }, - ["value.assignment"]: { - label: "Assignment value", - description: "Value(RHS) of an assignment", - scopeType: "value", - examples: ["const foo = 1"], - }, - ["value.mapPair"]: { - label: "Map pair value", - description: "Key(RHS) of a map pair", - scopeType: "value", - examples: ["value: 0"], - }, - ["value.mapPair.iteration"]: { - label: "Map pair value iteration", - description: "Iteration of map pair values", - scopeType: "value", - isIteration: true, - examples: ["{ value: 0 }"], - }, - ["tags.element"]: { - label: "Tags", - description: "Both tags in an xml element", - scopeType: "xmlBothTags", - examples: ["
"], - }, - // list: { - // label: "List", - // description: "A list of items", - // scopeType: "list", - // }, - // "list.interior": { - // label: "List interior", - // description: "Excludes the opening and closing delimiters of the list", - // scopeType: "list", - // }, - // map: { - // label: "Map", - // description: "A map of key-value pairs", - // scopeType: "map", - // }, - // "map.interior": { - // label: "Map interior", - // description: "Excludes the opening and closing delimiters of the map", - // scopeType: "map", - // }, -}; - -export const textualScopeSupportFacetInfos: Record< - TextualScopeSupportFacet, - ScopeSupportFacetInfo -> = { - character: { - label: "Character", - description: "A single character in the document", - scopeType: "character", - examples: ["a", "."], - }, - word: { - label: "Word", - description: "A single word in a token", - scopeType: "word", - examples: ["foo_bar", "fooBar"], - }, - token: { - label: "Token", - description: "A single token in the document", - scopeType: "token", - examples: ["foo", "("], - }, - line: { - label: "Line", - description: "A single line in the document", - scopeType: "line", - examples: ["foo"], - }, - paragraph: { - label: "Paragraph", - description: - "A single paragraph(contiguous block of lines) in the document", - scopeType: "paragraph", - examples: ["foo\nbar"], - }, - document: { - label: "Documents", - description: "The entire document", - scopeType: "document", - examples: ["foo\n\nbar"], - }, -}; - -export enum ScopeSupportFacetLevel { - supported, - unsupported, - notApplicable, -} - -export type LanguageScopeSupportFacetMap = Partial< - Record ->; - -export type TextualLanguageScopeSupportFacetMap = Record< - TextualScopeSupportFacet, - ScopeSupportFacetLevel ->; diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts new file mode 100644 index 0000000000..7fbc67e2c8 --- /dev/null +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts @@ -0,0 +1,87 @@ +import { SimpleScopeTypeType } from "../types/command/PartialTargetDescriptor.types"; + +const scopeSupportFacets = [ + // "list", + // "list.interior", + // "map", + // "map.interior", + // "collectionKey", + "namedFunction", + // "namedFunction.interior", + // "functionName", + // "anonymousFunction", + // "anonymousFunction.interior", + "name.assignment", + "key.attribute", + "key.mapPair", + "key.mapPair.iteration", + "value.assignment", + "value.mapPair", + "value.mapPair.iteration", + // "value.assignment.removal", + // "value.return", + // "value.return.removal", + // "value.collectionItem", + // "value.collectionItem.removal", + // "statement", + // "ifStatement", + // "condition.if", + // "condition.while", + // "condition.doWhile", + // "condition.for", + // "condition.ternary", + // "branch", + // "comment.line", + // "comment.block", + // "string.singleLine", + // "string.multiLine", + // "textFragment", + // "functionCall", + // "functionCallee", + // "argumentOrParameter.argument", + // "argumentOrParameter.argument.removal", + // "argumentOrParameter.parameter", + // "argumentOrParameter.parameter.removal", + // "class", + // "class.interior", + // "className", + // "type", + "tags", +] as const; + +const textualScopeSupportFacets = [ + "character", + "word", + "token", + "line", + "paragraph", + "document", +] as const; + +export interface ScopeSupportFacetInfo { + readonly label: string; + readonly description: string; + readonly scopeType: SimpleScopeTypeType; + readonly isIteration?: boolean; + readonly examples: readonly string[]; +} + +export enum ScopeSupportFacetLevel { + supported, + unsupported, + notApplicable, +} + +export type ScopeSupportFacet = (typeof scopeSupportFacets)[number]; + +export type TextualScopeSupportFacet = + (typeof textualScopeSupportFacets)[number]; + +export type LanguageScopeSupportFacetMap = Partial< + Record +>; + +export type TextualLanguageScopeSupportFacetMap = Record< + TextualScopeSupportFacet, + ScopeSupportFacetLevel +>; diff --git a/packages/common/src/scopeSupportFacets/plaintext.ts b/packages/common/src/scopeSupportFacets/textual.ts similarity index 69% rename from packages/common/src/scopeSupportFacets/plaintext.ts rename to packages/common/src/scopeSupportFacets/textual.ts index d1b59218f6..916bcf6d6a 100644 --- a/packages/common/src/scopeSupportFacets/plaintext.ts +++ b/packages/common/src/scopeSupportFacets/textual.ts @@ -1,11 +1,11 @@ import { ScopeSupportFacetLevel, TextualLanguageScopeSupportFacetMap, -} from "@cursorless/common"; +} from "./scopeSupportFacets.types"; const { supported } = ScopeSupportFacetLevel; -export const plaintextSupport: TextualLanguageScopeSupportFacetMap = { +export const textualScopeSupport: TextualLanguageScopeSupportFacetMap = { character: supported, word: supported, token: supported, diff --git a/packages/common/src/scopeSupportFacets/textualScopeSupportFacetInfos.ts b/packages/common/src/scopeSupportFacets/textualScopeSupportFacetInfos.ts new file mode 100644 index 0000000000..8f25c375a4 --- /dev/null +++ b/packages/common/src/scopeSupportFacets/textualScopeSupportFacetInfos.ts @@ -0,0 +1,47 @@ +import { + ScopeSupportFacetInfo, + TextualScopeSupportFacet, +} from "./scopeSupportFacets.types"; + +export const textualScopeSupportFacetInfos: Record< + TextualScopeSupportFacet, + ScopeSupportFacetInfo +> = { + character: { + label: "Character", + description: "A single character in the document", + scopeType: "character", + examples: ["a", "."], + }, + word: { + label: "Word", + description: "A single word in a token", + scopeType: "word", + examples: ["foo_bar", "fooBar"], + }, + token: { + label: "Token", + description: "A single token in the document", + scopeType: "token", + examples: ["foo", "("], + }, + line: { + label: "Line", + description: "A single line in the document", + scopeType: "line", + examples: ["foo"], + }, + paragraph: { + label: "Paragraph", + description: + "A single paragraph(contiguous block of lines) in the document", + scopeType: "paragraph", + examples: ["foo\nbar"], + }, + document: { + label: "Documents", + description: "The entire document", + scopeType: "document", + examples: ["foo\n\nbar"], + }, +}; diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.element.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/html/tags.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/character.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/character.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/character.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/document.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/document.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/document.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/line.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/line.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/line2.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/line2.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/line2.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/paragraph.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/paragraph.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/paragraph.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/token.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/token.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/token.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/word.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/word.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope b/packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/word2.scope similarity index 100% rename from packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/plaintext/word2.scope rename to packages/cursorless-vscode-e2e/src/suite/fixtures/scopes/textual/word2.scope diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index adcbac495c..2d51429bff 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -9,6 +9,7 @@ import { shouldUpdateFixtures, TextualScopeSupportFacet, textualScopeSupportFacetInfos, + textualScopeSupport, } from "@cursorless/common"; import { getCursorlessApi, openNewEditor } from "@cursorless/vscode-common"; import { assert } from "chai"; @@ -56,7 +57,9 @@ suite("Scope test cases", async function () { */ async function testLanguageSupport(languageId: string, testedFacets: string[]) { const scopeSupport: Record = - getLanguageScopeSupport(languageId); + languageId === "textual" + ? textualScopeSupport + : getLanguageScopeSupport(languageId); if (scopeSupport == null) { assert.fail(`Missing scope support entry in getLanguageScopeSupport`); @@ -89,7 +92,7 @@ async function testLanguageSupport(languageId: string, testedFacets: string[]) { async function runTest(file: string, languageId: string, facetId: string) { const { ide, scopeProvider } = (await getCursorlessApi()).testHelpers!; - const { scopeType, isIteration } = getScopeType(facetId); + const { scopeType, isIteration } = getScopeType(languageId, facetId); const fixture = (await fsp.readFile(file, "utf8")) .toString() .replaceAll("\r\n", "\n"); @@ -135,11 +138,14 @@ async function runTest(file: string, languageId: string, facetId: string) { } } -function getScopeType(facetId: string): { +function getScopeType( + languageId: string, + facetId: string, +): { scopeType: ScopeType; isIteration: boolean; } { - if (facetId in textualScopeSupportFacetInfos) { + if (languageId === "textual") { const { scopeType, isIteration } = textualScopeSupportFacetInfos[facetId as TextualScopeSupportFacet]; return { @@ -147,13 +153,11 @@ function getScopeType(facetId: string): { isIteration: isIteration ?? false, }; } - if (facetId in scopeSupportFacetInfos) { - const { scopeType, isIteration } = - scopeSupportFacetInfos[facetId as ScopeSupportFacet]; - return { - scopeType: { type: scopeType }, - isIteration: isIteration ?? false, - }; - } - throw Error(`Unknown facet '${facetId}'`); + + const { scopeType, isIteration } = + scopeSupportFacetInfos[facetId as ScopeSupportFacet]; + return { + scopeType: { type: scopeType }, + isIteration: isIteration ?? false, + }; } From 72ef3f5d9ef95059926e716d8225d0ed278c81ab Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 5 Dec 2023 18:33:42 +0100 Subject: [PATCH 67/71] rename --- .../src/scopeSupportFacets/getLanguageScopeSupport.ts | 8 ++++---- packages/common/src/scopeSupportFacets/html.ts | 2 +- packages/common/src/scopeSupportFacets/javascript.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts index 588d470101..e813f8dfc1 100644 --- a/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts +++ b/packages/common/src/scopeSupportFacets/getLanguageScopeSupport.ts @@ -1,5 +1,5 @@ -import { htmlSupport } from "./html"; -import { javascriptSupport } from "./javascript"; +import { htmlScopeSupport } from "./html"; +import { javascriptScopeSupport } from "./javascript"; import { LanguageScopeSupportFacetMap } from "./scopeSupportFacets.types"; export function getLanguageScopeSupport( @@ -7,9 +7,9 @@ export function getLanguageScopeSupport( ): LanguageScopeSupportFacetMap { switch (languageId) { case "javascript": - return javascriptSupport; + return javascriptScopeSupport; case "html": - return htmlSupport; + return htmlScopeSupport; } throw Error(`Unsupported language: '${languageId}'`); } diff --git a/packages/common/src/scopeSupportFacets/html.ts b/packages/common/src/scopeSupportFacets/html.ts index b7428adccc..d82b7a0683 100644 --- a/packages/common/src/scopeSupportFacets/html.ts +++ b/packages/common/src/scopeSupportFacets/html.ts @@ -5,7 +5,7 @@ import { const { supported, notApplicable } = ScopeSupportFacetLevel; -export const htmlSupport: LanguageScopeSupportFacetMap = { +export const htmlScopeSupport: LanguageScopeSupportFacetMap = { ["key.attribute"]: supported, ["tags"]: supported, diff --git a/packages/common/src/scopeSupportFacets/javascript.ts b/packages/common/src/scopeSupportFacets/javascript.ts index 2242b494c5..f00dda2984 100644 --- a/packages/common/src/scopeSupportFacets/javascript.ts +++ b/packages/common/src/scopeSupportFacets/javascript.ts @@ -5,7 +5,7 @@ import { const { supported, notApplicable } = ScopeSupportFacetLevel; -export const javascriptSupport: LanguageScopeSupportFacetMap = { +export const javascriptScopeSupport: LanguageScopeSupportFacetMap = { namedFunction: supported, ["name.assignment"]: supported, ["key.mapPair"]: supported, From d4274310f31ca5f304e724739965c772fc312771 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 6 Dec 2023 02:20:51 +0100 Subject: [PATCH 68/71] Update .pre-commit-config.yaml Co-authored-by: Pokey Rule <755842+pokey@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4d3e6dcfc9..6607279d3b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,7 +40,7 @@ repos: # tests use strings with trailing white space to represent the final # document contents. For example # packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/ruby/changeCondition.yml - exclude: ^packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/.*/[^/]*\.yml$|scope$|/generated/|^patches/ + exclude: ^packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/.*/[^/]*\.yml$|\.scope$|/generated/|^patches/ - repo: local hooks: - id: eslint From 616988e46852116b30dfdea7e63e034163486006 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 6 Dec 2023 02:31:33 +0100 Subject: [PATCH 69/71] fix --- packages/common/src/index.ts | 1 - .../common/src/scopeSupportFacets/textual.ts | 15 ------------ .../src/suite/scopes.vscode.test.ts | 24 +++++++++---------- 3 files changed, 12 insertions(+), 28 deletions(-) delete mode 100644 packages/common/src/scopeSupportFacets/textual.ts diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index f7f75fc665..b35bd962f7 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -98,4 +98,3 @@ export * from "./scopeSupportFacets/scopeSupportFacets.types"; export * from "./scopeSupportFacets/scopeSupportFacetInfos"; export * from "./scopeSupportFacets/textualScopeSupportFacetInfos"; export * from "./scopeSupportFacets/getLanguageScopeSupport"; -export * from "./scopeSupportFacets/textual"; diff --git a/packages/common/src/scopeSupportFacets/textual.ts b/packages/common/src/scopeSupportFacets/textual.ts deleted file mode 100644 index 916bcf6d6a..0000000000 --- a/packages/common/src/scopeSupportFacets/textual.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { - ScopeSupportFacetLevel, - TextualLanguageScopeSupportFacetMap, -} from "./scopeSupportFacets.types"; - -const { supported } = ScopeSupportFacetLevel; - -export const textualScopeSupport: TextualLanguageScopeSupportFacetMap = { - character: supported, - word: supported, - token: supported, - line: supported, - paragraph: supported, - document: supported, -}; diff --git a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts index 2d51429bff..95f065c663 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopes.vscode.test.ts @@ -9,7 +9,6 @@ import { shouldUpdateFixtures, TextualScopeSupportFacet, textualScopeSupportFacetInfos, - textualScopeSupport, } from "@cursorless/common"; import { getCursorlessApi, openNewEditor } from "@cursorless/vscode-common"; import { assert } from "chai"; @@ -21,7 +20,7 @@ import { serializeScopeFixture, } from "./serializeScopeFixture"; -suite("Scope test cases", async function () { +suite.only("Scope test cases", async function () { endToEndTestSetup(this); const testPaths = getScopeTestPaths(); @@ -56,18 +55,19 @@ suite("Scope test cases", async function () { * @param testedFacets The facets for {@link languageId} that are tested */ async function testLanguageSupport(languageId: string, testedFacets: string[]) { - const scopeSupport: Record = - languageId === "textual" - ? textualScopeSupport - : getLanguageScopeSupport(languageId); + const supportedFacets = (() => { + if (languageId === "textual") { + return Object.keys(textualScopeSupportFacetInfos); + } - if (scopeSupport == null) { - assert.fail(`Missing scope support entry in getLanguageScopeSupport`); - } + const scopeSupport = getLanguageScopeSupport(languageId); - const supportedFacets = Object.keys(scopeSupport).filter( - (facet) => scopeSupport[facet] === ScopeSupportFacetLevel.supported, - ); + return Object.keys(scopeSupport).filter( + (facet) => + scopeSupport[facet as ScopeSupportFacet] === + ScopeSupportFacetLevel.supported, + ); + })(); // Assert that all tested facets are supported by the language const unsupportedFacets = testedFacets.filter( From 2d8c499ae36be483107b070d8d0b7b49814d7c48 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Wed, 6 Dec 2023 13:54:46 +0000 Subject: [PATCH 70/71] Remove unused type --- .../src/scopeSupportFacets/scopeSupportFacets.types.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts index 7fbc67e2c8..3678d4fea3 100644 --- a/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts @@ -80,8 +80,3 @@ export type TextualScopeSupportFacet = export type LanguageScopeSupportFacetMap = Partial< Record >; - -export type TextualLanguageScopeSupportFacetMap = Record< - TextualScopeSupportFacet, - ScopeSupportFacetLevel ->; From 008f4cea4d78c1334db3b4b60a71898a6bdfc351 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Wed, 6 Dec 2023 17:27:29 +0000 Subject: [PATCH 71/71] Remove examples and label --- .../scopeSupportFacetInfos.ts | 18 ------------------ .../scopeSupportFacets.types.ts | 2 -- .../textualScopeSupportFacetInfos.ts | 12 ------------ 3 files changed, 32 deletions(-) diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacetInfos.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacetInfos.ts index 2f6096dd9b..c50c1d6fe2 100644 --- a/packages/common/src/scopeSupportFacets/scopeSupportFacetInfos.ts +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacetInfos.ts @@ -8,59 +8,41 @@ export const scopeSupportFacetInfos: Record< ScopeSupportFacetInfo > = { namedFunction: { - label: "Named function", description: "A named function", scopeType: "namedFunction", - examples: ["function foo() {}", "const foo = () => {}"], }, ["name.assignment"]: { - label: "Assignment name", description: "Name(LHS) of an assignment", scopeType: "name", - examples: ["const foo = 1"], }, ["key.attribute"]: { - label: "Attributes key", description: "Key(LHS) of an attribute", scopeType: "collectionKey", - examples: ['id="root"'], }, ["key.mapPair"]: { - label: "Map key", description: "Key(LHS) of a map pair", scopeType: "collectionKey", - examples: ["value: 0"], }, ["key.mapPair.iteration"]: { - label: "Map pair key iteration", description: "Iteration of map pair keys", scopeType: "collectionKey", isIteration: true, - examples: ["{ value: 0 }"], }, ["value.assignment"]: { - label: "Assignment value", description: "Value(RHS) of an assignment", scopeType: "value", - examples: ["const foo = 1"], }, ["value.mapPair"]: { - label: "Map pair value", description: "Key(RHS) of a map pair", scopeType: "value", - examples: ["value: 0"], }, ["value.mapPair.iteration"]: { - label: "Map pair value iteration", description: "Iteration of map pair values", scopeType: "value", isIteration: true, - examples: ["{ value: 0 }"], }, ["tags"]: { - label: "Tags", description: "Both tags in an xml element", scopeType: "xmlBothTags", - examples: ["
"], }, }; diff --git a/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts b/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts index 3678d4fea3..c7fcaa681e 100644 --- a/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts +++ b/packages/common/src/scopeSupportFacets/scopeSupportFacets.types.ts @@ -59,11 +59,9 @@ const textualScopeSupportFacets = [ ] as const; export interface ScopeSupportFacetInfo { - readonly label: string; readonly description: string; readonly scopeType: SimpleScopeTypeType; readonly isIteration?: boolean; - readonly examples: readonly string[]; } export enum ScopeSupportFacetLevel { diff --git a/packages/common/src/scopeSupportFacets/textualScopeSupportFacetInfos.ts b/packages/common/src/scopeSupportFacets/textualScopeSupportFacetInfos.ts index 8f25c375a4..a2d3f78227 100644 --- a/packages/common/src/scopeSupportFacets/textualScopeSupportFacetInfos.ts +++ b/packages/common/src/scopeSupportFacets/textualScopeSupportFacetInfos.ts @@ -8,40 +8,28 @@ export const textualScopeSupportFacetInfos: Record< ScopeSupportFacetInfo > = { character: { - label: "Character", description: "A single character in the document", scopeType: "character", - examples: ["a", "."], }, word: { - label: "Word", description: "A single word in a token", scopeType: "word", - examples: ["foo_bar", "fooBar"], }, token: { - label: "Token", description: "A single token in the document", scopeType: "token", - examples: ["foo", "("], }, line: { - label: "Line", description: "A single line in the document", scopeType: "line", - examples: ["foo"], }, paragraph: { - label: "Paragraph", description: "A single paragraph(contiguous block of lines) in the document", scopeType: "paragraph", - examples: ["foo\nbar"], }, document: { - label: "Documents", description: "The entire document", scopeType: "document", - examples: ["foo\n\nbar"], }, };