22 * Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io). All rights reserved.
33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 * ------------------------------------------------------------------------------------------ */
5- import { MonacoToProtocolConverter } from './converter' ;
6- import { Workspace , TextDocumentDidChangeEvent , TextDocument , Event , Emitter } from "vscode-base-languageclient/lib/services" ;
5+ import { MonacoToProtocolConverter , ProtocolToMonacoConverter } from './converter' ;
6+ import { Workspace , TextDocumentDidChangeEvent , TextDocument , Event , Emitter } from 'vscode-base-languageclient/lib/services' ;
7+ import { WorkspaceEdit } from 'vscode-base-languageclient/lib/base' ;
78import IModel = monaco . editor . IModel ;
9+ import IResourceEdit = monaco . languages . IResourceEdit ;
810
911export class MonacoWorkspace implements Workspace {
1012
@@ -15,8 +17,7 @@ export class MonacoWorkspace implements Workspace {
1517 protected readonly onDidCloseTextDocumentEmitter = new Emitter < TextDocument > ( ) ;
1618 protected readonly onDidChangeTextDocumentEmitter = new Emitter < TextDocumentDidChangeEvent > ( ) ;
1719
18- constructor (
19- protected readonly m2p : MonacoToProtocolConverter ) {
20+ constructor ( protected readonly p2m : ProtocolToMonacoConverter , protected readonly m2p : MonacoToProtocolConverter ) {
2021 for ( const model of monaco . editor . getModels ( ) ) {
2122 this . addModel ( model ) ;
2223 }
@@ -83,4 +84,46 @@ export class MonacoWorkspace implements Workspace {
8384 return this . onDidChangeTextDocumentEmitter . event ;
8485 }
8586
87+ public applyEdit ( workspaceEdit : WorkspaceEdit ) : Promise < boolean > {
88+ const edit : monaco . languages . WorkspaceEdit = this . p2m . asWorkspaceEdit ( workspaceEdit ) ;
89+
90+ // Collect all referenced models
91+ const models = edit . edits . reduce ( ( acc : { [ uri : string ] : monaco . editor . IModel } , currentEdit ) => {
92+ acc [ currentEdit . resource . toString ( ) ] = monaco . editor . getModel ( currentEdit . resource ) ;
93+ return acc ;
94+ } , { } ) ;
95+
96+ // If any of the models do not exist, refuse to apply the edit.
97+ if ( ! Object . keys ( models ) . map ( uri => models [ uri ] ) . every ( model => ! ! model ) ) {
98+ return Promise . resolve ( false ) ;
99+ }
100+
101+ // Group edits by resource so we can batch them when applying
102+ const editsByResource = edit . edits . reduce ( ( acc : { [ uri : string ] : IResourceEdit [ ] } , currentEdit ) => {
103+ const uri = currentEdit . resource . toString ( ) ;
104+ if ( ! ( uri in acc ) ) {
105+ acc [ uri ] = [ ] ;
106+ }
107+ acc [ uri ] . push ( currentEdit ) ;
108+ return acc ;
109+ } , { } ) ;
110+
111+ // Apply edits for each resource
112+ Object . keys ( editsByResource ) . forEach ( uri => {
113+ models [ uri ] . pushEditOperations (
114+ [ ] , // Do not try and preserve editor selections.
115+ editsByResource [ uri ] . map ( resourceEdit => {
116+ return {
117+ identifier : { major : 1 , minor : 0 } ,
118+ range : monaco . Range . lift ( resourceEdit . range ) ,
119+ text : resourceEdit . newText ,
120+ forceMoveMarkers : true ,
121+ } ;
122+ } ) ,
123+ ( ) => [ ] , // Do not try and preserve editor selections.
124+ ) ;
125+ } ) ;
126+ return Promise . resolve ( true ) ;
127+ }
128+
86129}
0 commit comments