diff --git a/e2e/playwright/flow-tests.spec.ts b/e2e/playwright/flow-tests.spec.ts index 57f6ec1a3..3b93e9b66 100644 --- a/e2e/playwright/flow-tests.spec.ts +++ b/e2e/playwright/flow-tests.spec.ts @@ -1455,8 +1455,6 @@ test.describe('Can create sketches on all planes and their back sides', () => { }) test.describe('Copilot ghost text', () => { - test.skip(true, 'temporarily disabled') - test('completes code in empty file', async ({ page }) => { const u = await getUtils(page) // const PUR = 400 / 37.5 //pixeltoUnitRatio @@ -3715,16 +3713,14 @@ test.describe('Regression tests', () => { // Make sure it's not a link await expect(zooLogo).not.toHaveAttribute('href') }) - test.fixme( - 'Position _ Is Out Of Range... regression test', - async ({ page }) => { - const u = await getUtils(page) - // const PUR = 400 / 37.5 //pixeltoUnitRatio - await page.setViewportSize({ width: 1200, height: 500 }) - await page.addInitScript(async () => { - localStorage.setItem( - 'persistCode', - `const exampleSketch = startSketchOn("XZ") + test('Position _ Is Out Of Range... regression test', async ({ page }) => { + const u = await getUtils(page) + // const PUR = 400 / 37.5 //pixeltoUnitRatio + await page.setViewportSize({ width: 1200, height: 500 }) + await page.addInitScript(async () => { + localStorage.setItem( + 'persistCode', + `const exampleSketch = startSketchOn("XZ") |> startProfileAt([0, 0], %) |> angledLine({ angle: 50, length: 45 }, %) |> yLineTo(0, %) @@ -3733,51 +3729,51 @@ test.describe('Regression tests', () => { const example = extrude(5, exampleSketch) shell({ faces: ['end'], thickness: 0.25 }, exampleSketch)` - ) - }) + ) + }) - await u.waitForAuthSkipAppStart() + await u.waitForAuthSkipAppStart() - // error in guter - await expect(page.locator('.cm-lint-marker-error')).toBeVisible() + // error in guter + await expect(page.locator('.cm-lint-marker-error')).toBeVisible() - // error text on hover - await page.hover('.cm-lint-marker-error') - await expect(page.getByText('Unexpected token').first()).toBeVisible() + // error text on hover + await page.hover('.cm-lint-marker-error') + await expect(page.getByText('Unexpected token').first()).toBeVisible() - // Okay execution finished, let's start editing text below the error. - await u.codeLocator.click() - // Go to the end of the editor - // This bug happens when there is a diagnostic in the editor and you try to - // edit text below it. - // Or delete a huge chunk of text and then try to edit below it. - await page.keyboard.press('End') - await page.keyboard.down('Shift') - await page.keyboard.press('ArrowUp') - await page.keyboard.press('ArrowUp') - await page.keyboard.press('ArrowUp') - await page.keyboard.press('ArrowUp') - await page.keyboard.up('Shift') - await page.keyboard.press('Backspace') - await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible() + // Okay execution finished, let's start editing text below the error. + await u.codeLocator.click() + // Go to the end of the editor + // This bug happens when there is a diagnostic in the editor and you try to + // edit text below it. + // Or delete a huge chunk of text and then try to edit below it. + await page.keyboard.press('End') + await page.keyboard.down('Shift') + await page.keyboard.press('ArrowUp') + await page.keyboard.press('ArrowUp') + await page.keyboard.press('ArrowUp') + await page.keyboard.press('ArrowUp') + await page.keyboard.press('ArrowUp') + await page.keyboard.up('Shift') + await page.keyboard.press('Backspace') + await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible() - await page.keyboard.press('Enter') - await page.keyboard.press('Enter') - await page.keyboard.type('thing: "blah"', { delay: 100 }) - await page.keyboard.press('Enter') + await page.keyboard.press('Enter') + await page.keyboard.press('Enter') + await page.keyboard.type('thing: "blah"', { delay: 100 }) + await page.keyboard.press('Enter') - await expect(page.locator('.cm-content')) - .toHaveText(`const exampleSketch = startSketchOn("XZ") + await expect(page.locator('.cm-content')) + .toContainText(`const exampleSketch = startSketchOn("XZ") |> startProfileAt([0, 0], %) |> angledLine({ angle: 50, length: 45 }, %) |> yLineTo(0, %) - |> close(%) - + |> close(% + thing: "blah"`) - await expect(page.locator('.cm-lint-marker-error')).toBeVisible() - } - ) + await expect(page.locator('.cm-lint-marker-error')).toBeVisible() + }) }) test.describe('Sketch tests', () => { diff --git a/packages/codemirror-lsp-client/src/index.ts b/packages/codemirror-lsp-client/src/index.ts index deeeb756c..708aca942 100644 --- a/packages/codemirror-lsp-client/src/index.ts +++ b/packages/codemirror-lsp-client/src/index.ts @@ -1,10 +1,7 @@ -import { autocompletion } from '@codemirror/autocomplete' -import { foldService, syntaxTree } from '@codemirror/language' +import { foldService } from '@codemirror/language' import { Extension, EditorState } from '@codemirror/state' import { ViewPlugin } from '@codemirror/view' -import { CompletionTriggerKind } from 'vscode-languageserver-protocol' - import { docPathFacet, LanguageServerPlugin, @@ -13,7 +10,6 @@ import { workspaceFolders, LanguageServerOptions, } from './plugin/lsp' -import { offsetToPos } from './plugin/util' export type { LanguageServerClientOptions } from './client' export { LanguageServerClient } from './client' @@ -57,59 +53,5 @@ export function lspPlugin(options: LanguageServerOptions): Extension { }), ] - if (options.client.getServerCapabilities().completionProvider) { - ext.push( - autocompletion({ - defaultKeymap: false, - override: [ - async (context) => { - if (plugin === null) { - return null - } - - const { state, pos, explicit } = context - - let nodeBefore = syntaxTree(state).resolveInner(pos, -1) - if ( - nodeBefore.name === 'BlockComment' || - nodeBefore.name === 'LineComment' - ) - return null - - const line = state.doc.lineAt(pos) - let trigKind: CompletionTriggerKind = CompletionTriggerKind.Invoked - let trigChar: string | undefined - if ( - !explicit && - plugin.client - .getServerCapabilities() - .completionProvider?.triggerCharacters?.includes( - line.text[pos - line.from - 1] - ) - ) { - trigKind = CompletionTriggerKind.TriggerCharacter - trigChar = line.text[pos - line.from - 1] - } - if ( - trigKind === CompletionTriggerKind.Invoked && - !context.matchBefore(/\w+$/) - ) { - return null - } - - return await plugin.requestCompletion( - context, - offsetToPos(state.doc, pos), - { - triggerKind: trigKind, - triggerCharacter: trigChar, - } - ) - }, - ], - }) - ) - } - return ext } diff --git a/packages/codemirror-lsp-client/src/plugin/autocomplete.ts b/packages/codemirror-lsp-client/src/plugin/autocomplete.ts index 714fdc8b8..a1352c71c 100644 --- a/packages/codemirror-lsp-client/src/plugin/autocomplete.ts +++ b/packages/codemirror-lsp-client/src/plugin/autocomplete.ts @@ -1,5 +1,6 @@ import { acceptCompletion, + autocompletion, clearSnippet, closeCompletion, hasNextSnippetField, @@ -8,10 +9,17 @@ import { prevSnippetField, startCompletion, } from '@codemirror/autocomplete' -import { Prec } from '@codemirror/state' -import { EditorView, keymap, KeyBinding } from '@codemirror/view' +import { Prec, Extension } from '@codemirror/state' +import { EditorView, keymap, KeyBinding, ViewPlugin } from '@codemirror/view' -import { CompletionItemKind } from 'vscode-languageserver-protocol' +import { + CompletionItemKind, + CompletionTriggerKind, +} from 'vscode-languageserver-protocol' + +import { LanguageServerPlugin } from './lsp' +import { offsetToPos } from './util' +import { syntaxTree } from '@codemirror/language' export const CompletionItemKindMap = Object.fromEntries( Object.entries(CompletionItemKind).map(([key, value]) => [value, key]) @@ -46,6 +54,59 @@ const lspAutocompleteKeymap: readonly KeyBinding[] = [ }, ] -export const lspAutocompleteKeymapExt = Prec.highest( - keymap.of(lspAutocompleteKeymap) -) +const lspAutocompleteKeymapExt = Prec.highest(keymap.of(lspAutocompleteKeymap)) + +export default function lspAutocompleteExt( + plugin: ViewPlugin +): Extension { + return [ + lspAutocompleteKeymapExt, + autocompletion({ + defaultKeymap: false, + override: [ + async (context) => { + const { state, pos, explicit, view } = context + let value = view?.plugin(plugin) + if (!value) return null + + let nodeBefore = syntaxTree(state).resolveInner(pos, -1) + if ( + nodeBefore.name === 'BlockComment' || + nodeBefore.name === 'LineComment' + ) + return null + + const line = state.doc.lineAt(pos) + let trigKind: CompletionTriggerKind = CompletionTriggerKind.Invoked + let trigChar: string | undefined + if ( + !explicit && + value.client + .getServerCapabilities() + .completionProvider?.triggerCharacters?.includes( + line.text[pos - line.from - 1] + ) + ) { + trigKind = CompletionTriggerKind.TriggerCharacter + trigChar = line.text[pos - line.from - 1] + } + if ( + trigKind === CompletionTriggerKind.Invoked && + !context.matchBefore(/\w+$/) + ) { + return null + } + + return await value.requestCompletion( + context, + offsetToPos(state.doc, pos), + { + triggerKind: trigKind, + triggerCharacter: trigChar, + } + ) + }, + ], + }), + ] +} diff --git a/packages/codemirror-lsp-client/src/plugin/lsp.ts b/packages/codemirror-lsp-client/src/plugin/lsp.ts index 93b9a5163..c8940fa27 100644 --- a/packages/codemirror-lsp-client/src/plugin/lsp.ts +++ b/packages/codemirror-lsp-client/src/plugin/lsp.ts @@ -31,7 +31,7 @@ import { LanguageServerClient } from '../client' import { CompletionItemKindMap } from './autocomplete' import { addToken, SemanticToken } from './semantic-tokens' import { deferExecution, posToOffset, formatMarkdownContents } from './util' -import { lspAutocompleteKeymapExt } from './autocomplete' +import lspAutocompleteExt from './autocomplete' import lspHoverExt from './hover' import lspFormatExt from './format' import lspIndentExt from './indent' @@ -556,7 +556,7 @@ export class LanguageServerPluginSpec { provide(plugin: ViewPlugin): Extension { return [ - lspAutocompleteKeymapExt, + lspAutocompleteExt(plugin), lspFormatExt(plugin), lspHoverExt(plugin), lspIndentExt(), diff --git a/src/editor/plugins/lsp/copilot/index.ts b/src/editor/plugins/lsp/copilot/index.ts index 04402f152..4ca9d274e 100644 --- a/src/editor/plugins/lsp/copilot/index.ts +++ b/src/editor/plugins/lsp/copilot/index.ts @@ -29,7 +29,6 @@ import { LanguageServerClient, docPathFacet, languageId, - lspPlugin, } from '@kittycad/codemirror-lsp-client' import { deferExecution } from 'lib/utils' import { CopilotLspCompletionParams } from 'wasm-lib/kcl/bindings/CopilotLspCompletionParams' @@ -621,7 +620,6 @@ export const copilotPlugin = (options: LanguageServerOptions): Extension => { ) return [ - /*lspPlugin(options), completionPlugin, copilotAutocompleteKeymapExt, domHandlers, @@ -632,6 +630,6 @@ export const copilotPlugin = (options: LanguageServerOptions): Extension => { plugin.rejectSuggestionCommand() return null - }),*/ + }), ] }