Skip to content

Commit

Permalink
Snippet text edits
Browse files Browse the repository at this point in the history
  • Loading branch information
Maria Solano committed Jan 8, 2024
1 parent d1c83db commit c8e9163
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 18 deletions.
23 changes: 14 additions & 9 deletions client-node-tests/src/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { strictEqual, ok } from 'assert';
import {
Position, Range, TextDocumentIdentifier, TextDocumentItem, VersionedTextDocumentIdentifier, Command, CodeLens, CodeActionContext,
Diagnostic, DiagnosticSeverity, WorkspaceChange, TextDocumentEdit, CreateFile, RenameFile, DeleteFile, ChangeAnnotation,
AnnotatedTextEdit
AnnotatedTextEdit,
TextEdit
} from 'vscode-languageclient';

suite('Protocol Helper Tests', () => {
Expand Down Expand Up @@ -124,17 +125,21 @@ suite('Protocol Helper Tests', () => {
strictEqual(workspaceEdit.documentChanges!.length, 2);
let edits = (workspaceEdit.documentChanges![0] as TextDocumentEdit).edits;
strictEqual(edits.length, 3);
rangeEqual(edits[0].range, Range.create(0,1,0,1));
strictEqual(edits[0].newText, 'insert');
rangeEqual(edits[1].range, Range.create(0,1,2,3));
strictEqual(edits[1].newText, 'replace');
rangeEqual(edits[2].range, Range.create(0,1,2,3));
strictEqual(edits[2].newText, '');
let edit = edits[0] as TextEdit;
rangeEqual(edit.range, Range.create(0,1,0,1));
strictEqual(edit.newText, 'insert');
edit = edits[1] as TextEdit;
rangeEqual(edit.range, Range.create(0,1,2,3));
strictEqual(edit.newText, 'replace');
edit = edits[2] as TextEdit;
rangeEqual(edit.range, Range.create(0,1,2,3));
strictEqual(edit.newText, '');

edits = (workspaceEdit.documentChanges![1] as TextDocumentEdit).edits;
strictEqual(edits.length, 1);
rangeEqual(edits[0].range, Range.create(2,3,2,3));
strictEqual(edits[0].newText, 'insert');
edit = edits[0] as TextEdit;
rangeEqual(edit.range, Range.create(2,3,2,3));
strictEqual(edit.newText, 'insert');

workspaceChange.createFile('file:///create.txt');
workspaceChange.renameFile('file:///old.txt', 'file:///new.txt');
Expand Down
2 changes: 2 additions & 0 deletions client/src/common/protocolConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,8 @@ export function createConverter(uriConverter: URIConverter | undefined, trustMar
for (const edit of change.edits) {
if (ls.AnnotatedTextEdit.is(edit)) {
result.replace(uri, asRange(edit.range), edit.newText, asMetadata(edit.annotationId));
} else if (ls.SnippetTextEdit.is(edit)) {
result.replace(uri, asRange(edit.range), edit.snippet.value, asMetadata(edit.annotationId));
} else {
result.replace(uri, asRange(edit.range), edit.newText);
}
Expand Down
10 changes: 9 additions & 1 deletion protocol/src/common/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4094,6 +4094,14 @@ export interface WorkspaceEditClientCapabilities {
* @since 3.16.0
*/
changeAnnotationSupport?: ChangeAnnotationsSupportOptions;

/**
* Whether the client supports snippets as text edits.
*
* @since 3.18.0
* @proposed
*/
snippetEditSupport?: boolean;
}

/**
Expand Down Expand Up @@ -4207,7 +4215,7 @@ export {
DidChangeNotebookDocumentNotification, DidSaveNotebookDocumentParams, DidSaveNotebookDocumentNotification, DidCloseNotebookDocumentParams,
DidCloseNotebookDocumentNotification,
// Inline Completions
InlineCompletionClientCapabilities, InlineCompletionOptions, InlineCompletionParams, InlineCompletionRegistrationOptions, InlineCompletionRequest
InlineCompletionClientCapabilities, InlineCompletionOptions, InlineCompletionParams, InlineCompletionRegistrationOptions, InlineCompletionRequest,
};

// To be backwards compatible
Expand Down
66 changes: 58 additions & 8 deletions types/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1026,8 +1026,11 @@ export interface TextDocumentEdit {
*
* @since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a
* client capability.
*
* @since 3.18.0 - support for SnippetTextEdit. This is guarded using a
* client capability.
*/
edits: (TextEdit | AnnotatedTextEdit)[];
edits: (TextEdit | AnnotatedTextEdit | SnippetTextEdit)[];
}

/**
Expand All @@ -1038,7 +1041,7 @@ export namespace TextDocumentEdit {
/**
* Creates a new `TextDocumentEdit`
*/
export function create(textDocument: OptionalVersionedTextDocumentIdentifier, edits: (TextEdit | AnnotatedTextEdit)[]): TextDocumentEdit {
export function create(textDocument: OptionalVersionedTextDocumentIdentifier, edits: (TextEdit | AnnotatedTextEdit | SnippetTextEdit)[]): TextDocumentEdit {
return { textDocument, edits };
}

Expand Down Expand Up @@ -1330,8 +1333,11 @@ export interface TextEditChange {
*
* @since 3.16.0 - support for annotated text edits. This is usually
* guarded using a client capability.
*
* @since 3.18.0 - support for snippet text edits. This is usually
* guarded using a client capability.
*/
all(): (TextEdit | AnnotatedTextEdit)[];
all(): (TextEdit | AnnotatedTextEdit | SnippetTextEdit)[];

/**
* Clears the edits for this change.
Expand All @@ -1345,8 +1351,11 @@ export interface TextEditChange {
*
* @since 3.16.0 - support for annotated text edits. This is usually
* guarded using a client capability.
*
* @since 3.18.0 - support for snippet text edits. This is usually
* guarded using a client capability.
*/
add(edit: TextEdit | AnnotatedTextEdit): void;
add(edit: TextEdit | AnnotatedTextEdit | SnippetTextEdit): void;

/**
* Insert the given text at the given position.
Expand Down Expand Up @@ -1380,10 +1389,10 @@ export interface TextEditChange {

class TextEditChangeImpl implements TextEditChange {

private edits: (TextEdit | AnnotatedTextEdit)[];
private edits: (TextEdit | AnnotatedTextEdit | SnippetTextEdit)[];
private changeAnnotations: ChangeAnnotations | undefined;

public constructor(edits: (TextEdit | AnnotatedTextEdit)[], changeAnnotations?: ChangeAnnotations) {
public constructor(edits: (TextEdit | AnnotatedTextEdit | SnippetTextEdit)[], changeAnnotations?: ChangeAnnotations) {
this.edits = edits;
this.changeAnnotations = changeAnnotations;
}
Expand Down Expand Up @@ -1451,11 +1460,11 @@ class TextEditChangeImpl implements TextEditChange {
}
}

public add(edit: TextEdit | AnnotatedTextEdit): void {
public add(edit: TextEdit | AnnotatedTextEdit | SnippetTextEdit): void {
this.edits.push(edit);
}

public all(): (TextEdit | AnnotatedTextEdit)[] {
public all(): (TextEdit | AnnotatedTextEdit | SnippetTextEdit)[] {
return this.edits;
}

Expand All @@ -1470,6 +1479,39 @@ class TextEditChangeImpl implements TextEditChange {
}
}

/**
* An interactive text edit.
*
* @since 3.18.0
* @proposed
*/
export interface SnippetTextEdit {
/**
* The range of the text document to be manipulated.
*/
range: Range;

/**
* The snippet to be inserted.
*/
snippet: StringValue;

/**
* The actual identifier of the snippet edit.
*/
annotationId?: ChangeAnnotationIdentifier;
}

export namespace SnippetTextEdit {
export function is(value: any): value is SnippetTextEdit {
const candidate = value as SnippetTextEdit;
return Is.objectLiteral(candidate)
&& Range.is(candidate.range)
&& StringValue.isSnippet(candidate.snippet)
&& (ChangeAnnotation.is(candidate.annotationId) || ChangeAnnotationIdentifier.is(candidate.annotationId));
}
}

/**
* A helper class
*/
Expand Down Expand Up @@ -4283,6 +4325,7 @@ export interface StringValue {
* The kind of string value.
*/
kind: 'snippet';

/**
* The snippet string.
*/
Expand All @@ -4293,6 +4336,13 @@ export namespace StringValue {
export function createSnippet(value: string): StringValue {
return { kind: 'snippet', value };
}

export function isSnippet(value: any): value is StringValue {
const candidate = value as StringValue;
return Is.objectLiteral(candidate)
&& candidate.kind === 'snippet'
&& Is.string(candidate.value);
}
}

/**
Expand Down

0 comments on commit c8e9163

Please sign in to comment.