cleanup annotations, makes it easier to read (#2905)
ckeanup annotations Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
@ -24,14 +24,15 @@ export {
|
|||||||
LspWorkerEventType,
|
LspWorkerEventType,
|
||||||
} from './client/codec'
|
} from './client/codec'
|
||||||
export type { LanguageServerOptions } from './plugin/lsp'
|
export type { LanguageServerOptions } from './plugin/lsp'
|
||||||
export type { TransactionInfo, RelevantUpdate } from './plugin/annotations'
|
|
||||||
export { updateInfo, TransactionAnnotation } from './plugin/annotations'
|
|
||||||
export {
|
export {
|
||||||
LanguageServerPlugin,
|
LanguageServerPlugin,
|
||||||
LanguageServerPluginSpec,
|
LanguageServerPluginSpec,
|
||||||
docPathFacet,
|
docPathFacet,
|
||||||
languageId,
|
languageId,
|
||||||
workspaceFolders,
|
workspaceFolders,
|
||||||
|
lspSemanticTokensEvent,
|
||||||
|
lspDiagnosticsEvent,
|
||||||
|
lspFormatCodeEvent,
|
||||||
} from './plugin/lsp'
|
} from './plugin/lsp'
|
||||||
export { posToOffset, offsetToPos } from './plugin/util'
|
export { posToOffset, offsetToPos } from './plugin/util'
|
||||||
|
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
import { hasNextSnippetField, pickedCompletion } from '@codemirror/autocomplete'
|
|
||||||
import { Annotation, Transaction } from '@codemirror/state'
|
|
||||||
import type { ViewUpdate } from '@codemirror/view'
|
|
||||||
|
|
||||||
export enum LspAnnotation {
|
|
||||||
SemanticTokens = 'semantic-tokens',
|
|
||||||
FormatCode = 'format-code',
|
|
||||||
Diagnostics = 'diagnostics',
|
|
||||||
}
|
|
||||||
|
|
||||||
const lspEvent = Annotation.define<LspAnnotation>()
|
|
||||||
export const lspSemanticTokensEvent = lspEvent.of(LspAnnotation.SemanticTokens)
|
|
||||||
export const lspFormatCodeEvent = lspEvent.of(LspAnnotation.FormatCode)
|
|
||||||
export const lspDiagnosticsEvent = lspEvent.of(LspAnnotation.Diagnostics)
|
|
||||||
|
|
||||||
export enum TransactionAnnotation {
|
|
||||||
Remote = 'remote',
|
|
||||||
UserSelect = 'user.select',
|
|
||||||
UserInput = 'user.input',
|
|
||||||
UserMove = 'user.move',
|
|
||||||
UserDelete = 'user.delete',
|
|
||||||
UserUndo = 'user.undo',
|
|
||||||
UserRedo = 'user.redo',
|
|
||||||
|
|
||||||
SemanticTokens = 'SemanticTokens',
|
|
||||||
FormatCode = 'FormatCode',
|
|
||||||
Diagnostics = 'Diagnostics',
|
|
||||||
|
|
||||||
PickedCompletion = 'PickedCompletion',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TransactionInfo {
|
|
||||||
annotations: TransactionAnnotation[]
|
|
||||||
time: number | null
|
|
||||||
docChanged: boolean
|
|
||||||
addToHistory: boolean
|
|
||||||
inSnippet: boolean
|
|
||||||
transaction: Transaction
|
|
||||||
}
|
|
||||||
|
|
||||||
export const updateInfo = (update: ViewUpdate): TransactionInfo[] => {
|
|
||||||
let transactionInfos: TransactionInfo[] = []
|
|
||||||
|
|
||||||
for (const tr of update.transactions) {
|
|
||||||
let annotations: TransactionAnnotation[] = []
|
|
||||||
|
|
||||||
if (tr.isUserEvent('select')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserSelect)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.isUserEvent('input')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserInput)
|
|
||||||
}
|
|
||||||
if (tr.isUserEvent('delete')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserDelete)
|
|
||||||
}
|
|
||||||
if (tr.isUserEvent('undo')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserUndo)
|
|
||||||
}
|
|
||||||
if (tr.isUserEvent('redo')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserRedo)
|
|
||||||
}
|
|
||||||
if (tr.isUserEvent('move')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserMove)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(pickedCompletion) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.PickedCompletion)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(lspSemanticTokensEvent.type) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.SemanticTokens)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(lspFormatCodeEvent.type) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.FormatCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(lspDiagnosticsEvent.type) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.Diagnostics)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(Transaction.remote) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.Remote)
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionInfos.push({
|
|
||||||
annotations,
|
|
||||||
time: tr.annotation(Transaction.time) || null,
|
|
||||||
docChanged: tr.docChanged,
|
|
||||||
addToHistory: tr.annotation(Transaction.addToHistory) || false,
|
|
||||||
inSnippet: hasNextSnippetField(update.state),
|
|
||||||
transaction: tr,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return transactionInfos
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RelevantUpdate {
|
|
||||||
overall: boolean
|
|
||||||
userSelect: boolean
|
|
||||||
time: number | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const relevantUpdate = (update: ViewUpdate): RelevantUpdate => {
|
|
||||||
const infos = updateInfo(update)
|
|
||||||
// Make sure we are not in a snippet
|
|
||||||
if (infos.some((info) => info.inSnippet)) {
|
|
||||||
return {
|
|
||||||
overall: false,
|
|
||||||
userSelect: false,
|
|
||||||
time: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
overall: infos.some(
|
|
||||||
(info) =>
|
|
||||||
info.docChanged ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserInput) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserDelete) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserUndo) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserRedo) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserMove)
|
|
||||||
),
|
|
||||||
userSelect: infos.some((info) =>
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserSelect)
|
|
||||||
),
|
|
||||||
time: infos.length ? infos[0].time : null,
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,13 @@ import type {
|
|||||||
CompletionResult,
|
CompletionResult,
|
||||||
} from '@codemirror/autocomplete'
|
} from '@codemirror/autocomplete'
|
||||||
import { completeFromList, snippetCompletion } from '@codemirror/autocomplete'
|
import { completeFromList, snippetCompletion } from '@codemirror/autocomplete'
|
||||||
import { Facet, StateEffect, Extension, Transaction } from '@codemirror/state'
|
import {
|
||||||
|
Facet,
|
||||||
|
StateEffect,
|
||||||
|
Extension,
|
||||||
|
Transaction,
|
||||||
|
Annotation,
|
||||||
|
} from '@codemirror/state'
|
||||||
import type {
|
import type {
|
||||||
ViewUpdate,
|
ViewUpdate,
|
||||||
PluginValue,
|
PluginValue,
|
||||||
@ -22,11 +28,6 @@ import {
|
|||||||
import { URI } from 'vscode-uri'
|
import { URI } from 'vscode-uri'
|
||||||
|
|
||||||
import { LanguageServerClient } from '../client'
|
import { LanguageServerClient } from '../client'
|
||||||
import {
|
|
||||||
lspSemanticTokensEvent,
|
|
||||||
lspFormatCodeEvent,
|
|
||||||
relevantUpdate,
|
|
||||||
} from './annotations'
|
|
||||||
import { CompletionItemKindMap } from './autocomplete'
|
import { CompletionItemKindMap } from './autocomplete'
|
||||||
import { addToken, SemanticToken } from './semantic-tokens'
|
import { addToken, SemanticToken } from './semantic-tokens'
|
||||||
import { deferExecution, posToOffset, formatMarkdownContents } from './util'
|
import { deferExecution, posToOffset, formatMarkdownContents } from './util'
|
||||||
@ -47,6 +48,17 @@ export const workspaceFolders = Facet.define<
|
|||||||
LSP.WorkspaceFolder[]
|
LSP.WorkspaceFolder[]
|
||||||
>({ combine: useLast })
|
>({ combine: useLast })
|
||||||
|
|
||||||
|
export enum LspAnnotation {
|
||||||
|
SemanticTokens = 'semantic-tokens',
|
||||||
|
FormatCode = 'format-code',
|
||||||
|
Diagnostics = 'diagnostics',
|
||||||
|
}
|
||||||
|
|
||||||
|
const lspEvent = Annotation.define<LspAnnotation>()
|
||||||
|
export const lspSemanticTokensEvent = lspEvent.of(LspAnnotation.SemanticTokens)
|
||||||
|
export const lspFormatCodeEvent = lspEvent.of(LspAnnotation.FormatCode)
|
||||||
|
export const lspDiagnosticsEvent = lspEvent.of(LspAnnotation.Diagnostics)
|
||||||
|
|
||||||
export interface LanguageServerOptions {
|
export interface LanguageServerOptions {
|
||||||
// We assume this is the main project directory, we are currently working in.
|
// We assume this is the main project directory, we are currently working in.
|
||||||
workspaceFolders: LSP.WorkspaceFolder[]
|
workspaceFolders: LSP.WorkspaceFolder[]
|
||||||
@ -131,11 +143,6 @@ export class LanguageServerPlugin implements PluginValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(viewUpdate: ViewUpdate) {
|
update(viewUpdate: ViewUpdate) {
|
||||||
const isRelevant = relevantUpdate(viewUpdate)
|
|
||||||
if (!isRelevant.overall) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the doc didn't change we can return early.
|
// If the doc didn't change we can return early.
|
||||||
if (!viewUpdate.docChanged) {
|
if (!viewUpdate.docChanged) {
|
||||||
return
|
return
|
||||||
|
@ -4,7 +4,7 @@ import { EditorView, Decoration, DecorationSet } from '@codemirror/view'
|
|||||||
|
|
||||||
import { Tag, tags } from '@lezer/highlight'
|
import { Tag, tags } from '@lezer/highlight'
|
||||||
|
|
||||||
import { lspSemanticTokensEvent } from './annotations'
|
import { lspSemanticTokensEvent } from './lsp'
|
||||||
|
|
||||||
export interface SemanticToken {
|
export interface SemanticToken {
|
||||||
from: number
|
from: number
|
||||||
|
@ -23,16 +23,12 @@ import {
|
|||||||
} from '@codemirror/state'
|
} from '@codemirror/state'
|
||||||
import { completionStatus } from '@codemirror/autocomplete'
|
import { completionStatus } from '@codemirror/autocomplete'
|
||||||
import {
|
import {
|
||||||
TransactionAnnotation,
|
|
||||||
offsetToPos,
|
offsetToPos,
|
||||||
posToOffset,
|
posToOffset,
|
||||||
LanguageServerOptions,
|
LanguageServerOptions,
|
||||||
LanguageServerClient,
|
LanguageServerClient,
|
||||||
docPathFacet,
|
docPathFacet,
|
||||||
languageId,
|
languageId,
|
||||||
TransactionInfo,
|
|
||||||
updateInfo,
|
|
||||||
RelevantUpdate,
|
|
||||||
lspPlugin,
|
lspPlugin,
|
||||||
} from '@kittycad/codemirror-lsp-client'
|
} from '@kittycad/codemirror-lsp-client'
|
||||||
import { deferExecution } from 'lib/utils'
|
import { deferExecution } from 'lib/utils'
|
||||||
@ -193,36 +189,6 @@ const completionDecoration = StateField.define<CompletionState>({
|
|||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const relevantUpdate = (update: ViewUpdate): RelevantUpdate => {
|
|
||||||
const infos = updateInfo(update)
|
|
||||||
|
|
||||||
// Make sure we are not in a snippet
|
|
||||||
if (infos.some((info: TransactionInfo) => info.inSnippet)) {
|
|
||||||
return {
|
|
||||||
overall: false,
|
|
||||||
userSelect: false,
|
|
||||||
time: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
overall: infos.some(
|
|
||||||
(info: TransactionInfo) =>
|
|
||||||
info.transaction.annotation(copilotPluginEvent.type) !== undefined ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserSelect) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserInput) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserDelete) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserUndo) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserRedo) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserMove)
|
|
||||||
),
|
|
||||||
userSelect: infos.some((info: TransactionInfo) =>
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserSelect)
|
|
||||||
),
|
|
||||||
time: infos.length ? infos[0].time : null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A view plugin that requests completions from the server after a delay
|
// A view plugin that requests completions from the server after a delay
|
||||||
export class CompletionRequester implements PluginValue {
|
export class CompletionRequester implements PluginValue {
|
||||||
private client: LanguageServerClient
|
private client: LanguageServerClient
|
||||||
@ -243,19 +209,39 @@ export class CompletionRequester implements PluginValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(viewUpdate: ViewUpdate) {
|
update(viewUpdate: ViewUpdate) {
|
||||||
const isRelevant = relevantUpdate(viewUpdate)
|
// Make sure we are in a state where we can request completions.
|
||||||
if (!isRelevant.overall) {
|
if (!editorManager.copilotEnabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isUserSelect = false
|
||||||
|
let isRelevant = false
|
||||||
|
for (const tr of viewUpdate.transactions) {
|
||||||
|
if (tr.isUserEvent('select')) {
|
||||||
|
isUserSelect = true
|
||||||
|
break
|
||||||
|
} else if (tr.isUserEvent('input')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.isUserEvent('delete')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.isUserEvent('undo')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.isUserEvent('redo')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.isUserEvent('move')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.annotation(copilotPluginEvent.type) !== undefined) {
|
||||||
|
isRelevant = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we have a user select event, we want to clear the ghost text.
|
// If we have a user select event, we want to clear the ghost text.
|
||||||
if (isRelevant.userSelect) {
|
if (isUserSelect) {
|
||||||
this._deffererUserSelect(true)
|
this._deffererUserSelect(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we are in a state where we can request completions.
|
if (!isRelevant) {
|
||||||
if (!editorManager.copilotEnabled) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,9 @@ import { Extension } from '@codemirror/state'
|
|||||||
import { ViewPlugin, PluginValue, ViewUpdate } from '@codemirror/view'
|
import { ViewPlugin, PluginValue, ViewUpdate } from '@codemirror/view'
|
||||||
import {
|
import {
|
||||||
LanguageServerOptions,
|
LanguageServerOptions,
|
||||||
updateInfo,
|
|
||||||
TransactionInfo,
|
|
||||||
RelevantUpdate,
|
|
||||||
TransactionAnnotation,
|
|
||||||
LanguageServerClient,
|
LanguageServerClient,
|
||||||
lspPlugin,
|
lspPlugin,
|
||||||
|
lspFormatCodeEvent,
|
||||||
} from '@kittycad/codemirror-lsp-client'
|
} from '@kittycad/codemirror-lsp-client'
|
||||||
import { deferExecution } from 'lib/utils'
|
import { deferExecution } from 'lib/utils'
|
||||||
import { codeManager, editorManager, kclManager } from 'lib/singletons'
|
import { codeManager, editorManager, kclManager } from 'lib/singletons'
|
||||||
@ -18,34 +15,6 @@ import { UpdateCanExecuteResponse } from 'wasm-lib/kcl/bindings/UpdateCanExecute
|
|||||||
|
|
||||||
const changesDelay = 600
|
const changesDelay = 600
|
||||||
|
|
||||||
export const relevantUpdate = (update: ViewUpdate): RelevantUpdate => {
|
|
||||||
const infos = updateInfo(update)
|
|
||||||
// Make sure we are not in a snippet
|
|
||||||
if (infos.some((info: TransactionInfo) => info.inSnippet)) {
|
|
||||||
return {
|
|
||||||
overall: false,
|
|
||||||
userSelect: false,
|
|
||||||
time: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
overall: infos.some(
|
|
||||||
(info: TransactionInfo) =>
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserSelect) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserInput) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserDelete) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserUndo) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserRedo) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserMove) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.FormatCode)
|
|
||||||
),
|
|
||||||
userSelect: infos.some((info: TransactionInfo) =>
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserSelect)
|
|
||||||
),
|
|
||||||
time: infos.length ? infos[0].time : null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// A view plugin that requests completions from the server after a delay
|
// A view plugin that requests completions from the server after a delay
|
||||||
export class KclPlugin implements PluginValue {
|
export class KclPlugin implements PluginValue {
|
||||||
private viewUpdate: ViewUpdate | null = null
|
private viewUpdate: ViewUpdate | null = null
|
||||||
@ -75,18 +44,38 @@ export class KclPlugin implements PluginValue {
|
|||||||
this.viewUpdate = viewUpdate
|
this.viewUpdate = viewUpdate
|
||||||
editorManager.setEditorView(viewUpdate.view)
|
editorManager.setEditorView(viewUpdate.view)
|
||||||
|
|
||||||
const isRelevant = relevantUpdate(viewUpdate)
|
let isUserSelect = false
|
||||||
if (!isRelevant.overall) {
|
let isRelevant = false
|
||||||
return
|
for (const tr of viewUpdate.transactions) {
|
||||||
|
if (tr.isUserEvent('select')) {
|
||||||
|
isUserSelect = true
|
||||||
|
break
|
||||||
|
} else if (tr.isUserEvent('input')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.isUserEvent('delete')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.isUserEvent('undo')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.isUserEvent('redo')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.isUserEvent('move')) {
|
||||||
|
isRelevant = true
|
||||||
|
} else if (tr.annotation(lspFormatCodeEvent.type)) {
|
||||||
|
isRelevant = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a user select event, we want to update what parts are
|
// If we have a user select event, we want to update what parts are
|
||||||
// highlighted.
|
// highlighted.
|
||||||
if (isRelevant.userSelect) {
|
if (isUserSelect) {
|
||||||
this._deffererUserSelect(true)
|
this._deffererUserSelect(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isRelevant) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (!viewUpdate.docChanged) {
|
if (!viewUpdate.docChanged) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user