Skip to content

Commit

Permalink
Add LSP resource operation support.
Browse files Browse the repository at this point in the history
Signed-off-by: Yaohai Zheng <[email protected]>
  • Loading branch information
yaohaizh committed Oct 29, 2018
1 parent a56e2cd commit 954371c
Show file tree
Hide file tree
Showing 20 changed files with 1,893 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/******************************************************************************
* Copyright (c) 2018 Microsoft Corporation and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
******************************************************************************/

package org.eclipse.lsp4j;

/**
* The kind of failure handling supported by the client.
*/
public final class FailureHandlingKind {

private FailureHandlingKind() {
}

/**
* Applying the workspace change is simply aborted if one of the changes
* provided fails. All operations executed before the failing operation stay
* executed.
*/
public static final String Abort = "abort";

/**
* All operations are executed transactional. That means they either all succeed
* or no changes at all are applied to the workspace.
*/
public static final String Transactional = "transactional";

/**
* If the workspace edit contains only textual file changes they are executed
* transactional. If resource changes (create, rename or delete file) are part
* of the change the failure handling strategy is abort.
*/
public static final String TextOnlyTransactional = "textOnlyTransactional";

/**
* The client tries to undo the operations already executed. But there is no
* guaruntee that this is succeeding.
*/
public static final String Undo = "undo";
}
273 changes: 257 additions & 16 deletions org.eclipse.lsp4j/src/main/java/org/eclipse/lsp4j/Protocol.xtend
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ import java.util.ArrayList
import java.util.LinkedHashMap
import java.util.List
import java.util.Map
import org.eclipse.lsp4j.adapters.DocumentChangeListAdapter
import org.eclipse.lsp4j.adapters.HoverTypeAdapter
import org.eclipse.lsp4j.adapters.InitializeParamsTypeAdapter
import org.eclipse.lsp4j.adapters.ResourceChangeListAdapter
import org.eclipse.lsp4j.adapters.ResourceOperationTypeAdapter
import org.eclipse.lsp4j.adapters.VersionedTextDocumentIdentifierTypeAdapter
import org.eclipse.lsp4j.generator.JsonRpcData
import org.eclipse.lsp4j.jsonrpc.json.adapters.JsonElementTypeAdapter
Expand Down Expand Up @@ -58,6 +60,18 @@ class WorkspaceEditCapabilities {
*/
@Beta Boolean resourceChanges

/**
* The resource operations the client supports. Clients should at least
* support 'create', 'rename' and 'delete' files and folders.
*/
List<ResourceOperationKind> resourceOperations;

/**
* The failure handling strategy of a client if applying the workspace edit
* fails.
*/
FailureHandlingKind failureHandling;

new() {
}

Expand Down Expand Up @@ -2518,6 +2532,26 @@ class ReferenceParams extends TextDocumentPositionParams {
}
}

@JsonRpcData
class PrepareRenameResult {
/**
* The capabilities the language server provides.
*/
@NonNull
Range range

@NonNull
String placeholder

new() {
}

new(@NonNull Range range, @NonNull String placeholder) {
this.range = range
this.placeholder = placeholder
}
}

/**
* The rename request is sent from the client to the server to do a workspace wide rename of a symbol.
*/
Expand Down Expand Up @@ -2552,6 +2586,24 @@ class RenameParams {
}
}

/**
* Rename options
*/
@JsonRpcData
class RenameOptions {
/**
* Renames should be checked and tested before being executed.
*/
Boolean prepareProvider;

new() {
}

new(Boolean prepareProvider) {
this.prepareProvider = prepareProvider
}
}

@JsonRpcData
class ServerCapabilities {
/**
Expand Down Expand Up @@ -2644,7 +2696,7 @@ class ServerCapabilities {
/**
* The server provides rename support.
*/
Boolean renameProvider
Either<Boolean, RenameOptions> renameProvider

/**
* The server provides document link support.
Expand Down Expand Up @@ -3261,6 +3313,193 @@ class TextDocumentEdit {
}
}

@JsonRpcData
@JsonAdapter(ResourceOperationTypeAdapter)
class ResourceOperation {

@NonNull
String kind;

new() {
}

new(@NonNull String kind) {
this.kind = kind;
}
}

/**
* Options to create a file.
*/
@JsonRpcData
class CreateFileOptions {
/**
* Overwrite existing file. Overwrite wins over `ignoreIfExists`
*/
Boolean overwrite

/**
* Ignore if exists.
*/
Boolean ignoreIfExists

new() {
}

new(Boolean overwrite, Boolean ignoreIfExists) {
this.overwrite = overwrite
this.ignoreIfExists = ignoreIfExists
}
}

/**
* Create file operation
*/
@JsonRpcData
class CreateFile extends ResourceOperation {

/**
* The resource to create.
*/
@NonNull
String uri
/**
* Additional options
*/
CreateFileOptions options

new() {
super(ResourceOperationKind.Create)
}

new(@NonNull String uri) {
super(ResourceOperationKind.Create)
this.uri = uri
}

new(@NonNull String uri, CreateFileOptions options) {
super(ResourceOperationKind.Create)
this.uri = uri
this.options = options
}
}

/**
* Rename file options
*/
@JsonRpcData
class RenameFileOptions {
/**
* Overwrite target if existing. Overwrite wins over `ignoreIfExists`
*/
Boolean overwrite
/**
* Ignores if target exists.
*/
Boolean ignoreIfExists

new() {
}

new(Boolean overwrite, Boolean ignoreIfExists) {
this.overwrite = overwrite
this.ignoreIfExists = ignoreIfExists
}
}

/**
* Rename file operation
*/
@JsonRpcData
class RenameFile extends ResourceOperation {
/**
* The old (existing) location.
*/
@NonNull
String oldUri

/**
* The new location.
*/
@NonNull
String newUri
/**
* Rename options.
*/
RenameFileOptions options

new() {
super(ResourceOperationKind.Rename)
}

new(@NonNull String oldUri, @NonNull String newUri) {
super(ResourceOperationKind.Rename)
this.oldUri = oldUri
this.newUri = newUri
}

new(@NonNull String oldUri, @NonNull String newUri, RenameFileOptions options) {
super(ResourceOperationKind.Rename)
this.oldUri = oldUri
this.newUri = newUri
this.options = options
}
}

/**
* Delete file options
*/
@JsonRpcData
class DeleteFileOptions {
/**
* Delete the content recursively if a folder is denoted.
*/
Boolean recursive
/**
* Ignore the operation if the file doesn't exist.
*/
Boolean ignoreIfNotExists

new() {
}

new(Boolean recursive, Boolean ignoreIfNotExists) {
this.recursive = recursive
this.ignoreIfNotExists = ignoreIfNotExists
}
}

/**
* Delete file operation
*/
@JsonRpcData
class DeleteFile extends ResourceOperation {
/**
* The file to delete.
*/
@NonNull
String uri
/**
* Delete options.
*/
DeleteFileOptions options

new() {
super(ResourceOperationKind.Delete)
}

new(@NonNull String uri) {
super(ResourceOperationKind.Delete)
this.uri = uri
}

new(@NonNull String uri, DeleteFileOptions options) {
super(ResourceOperationKind.Delete)
this.uri = uri
this.options = options
}
}

/**
* A resource change.
*
Expand Down Expand Up @@ -3308,8 +3547,9 @@ class WorkspaceEdit {
* version of a text document. Whether a client supports versioned document
* edits is expressed via `WorkspaceClientCapabilities.versionedWorkspaceEdit`.
*/
List<TextDocumentEdit> documentChanges

@JsonAdapter(DocumentChangeListAdapter)
List<Either<TextDocumentEdit, ResourceOperation>> documentChanges

/**
* If resource changes are supported the `WorkspaceEdit`
* uses the property `resourceChanges` which are either a
Expand All @@ -3329,19 +3569,20 @@ class WorkspaceEdit {
this.changes = changes
}

new(List<TextDocumentEdit> documentChanges) {
this.documentChanges = documentChanges
}

/**
* @deprecated According to the protocol documentation, it doesn't make sense to send both
* changes and documentChanges
*/
@Deprecated
new(Map<String, List<TextEdit>> changes, List<TextDocumentEdit> documentChanges) {
this.changes = changes
this.documentChanges = documentChanges
}

new(List<Either<TextDocumentEdit, ResourceOperation>> documentChanges) {
this.documentChanges = documentChanges
}

/**
* @deprecated According to the protocol documentation, it doesn't make sense to send both
* changes and documentChanges
*/
@Deprecated
new(Map<String, List<TextEdit>> changes, List<Either<TextDocumentEdit, ResourceOperation>> documentChanges) {
this.changes = changes
this.documentChanges = documentChanges
}
}

/**
Expand Down
Loading

0 comments on commit 954371c

Please sign in to comment.