Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit c9d20a8

Browse files
authored
Switch to fast-json-patch (#281)
* Switch to fast-json-patch * Remove operation cloning * Use escapePathComponent()
1 parent b86665b commit c9d20a8

File tree

7 files changed

+134
-124
lines changed

7 files changed

+134
-124
lines changed

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,13 @@
3434
},
3535
"dependencies": {
3636
"@reactivex/rxjs": "^5.3.0",
37-
"@types/json-patch": "0.0.29",
3837
"chai": "^4.0.1",
3938
"chai-as-promised": "^6.0.0",
4039
"chalk": "^1.1.3",
4140
"commander": "^2.9.0",
41+
"fast-json-patch": "^1.2.2",
4242
"glob": "^7.1.1",
4343
"iterare": "^0.0.8",
44-
"json-patch": "^0.6.1",
4544
"lodash": "^4.17.4",
4645
"mz": "^2.6.0",
4746
"object-hash": "^1.1.8",

src/connection.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { Observable, Subscription, Symbol } from '@reactivex/rxjs';
22
import { EventEmitter } from 'events';
3-
import { apply, OpPatch } from 'json-patch';
3+
import jsonpatch from 'fast-json-patch';
44
import { camelCase, omit } from 'lodash';
5-
import { cloneDeep } from 'lodash';
65
import { FORMAT_TEXT_MAP, Span, Tracer } from 'opentracing';
76
import { inspect } from 'util';
87
import { ErrorCodes, Message, StreamMessageReader as VSCodeStreamMessageReader, StreamMessageWriter as VSCodeStreamMessageWriter } from 'vscode-jsonrpc';
@@ -239,7 +238,7 @@ export function registerLanguageHandler(messageEmitter: MessageEmitter, messageW
239238
return;
240239
}
241240
// Call handler method with params and span
242-
let observable: Observable<OpPatch>;
241+
let observable: Observable<jsonpatch.Operation>;
243242
try {
244243
// Convert return value to Observable
245244
const returnValue = (handler as any)[method](message.params, span);
@@ -270,10 +269,7 @@ export function registerLanguageHandler(messageEmitter: MessageEmitter, messageW
270269
})
271270
// Build up final result for BC
272271
// TODO send null if client declared streaming capability
273-
// Clone patches to not modify the values of the patches
274-
.map(cloneDeep)
275-
.toArray()
276-
.map(patches => apply(null, patches))
272+
.reduce<jsonpatch.Operation, any>(jsonpatch.applyReducer, null)
277273
.finally(() => {
278274
// Finish span
279275
span.finish();

src/request-type.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { OpPatch } from 'json-patch';
1+
import jsonpatch from 'fast-json-patch';
22
import * as vscode from 'vscode-languageserver';
33

44
export interface InitializeParams extends vscode.InitializeParams {
@@ -232,5 +232,5 @@ export interface PartialResultParams {
232232
* A JSON Patch that represents updates to the partial result as specified in RFC6902
233233
* https://tools.ietf.org/html/rfc6902
234234
*/
235-
patch: OpPatch[];
235+
patch: jsonpatch.Operation[];
236236
}

src/test/connection.test.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11

2-
import { Observable } from '@reactivex/rxjs';
2+
import { Observable, Subject } from '@reactivex/rxjs';
33
import * as assert from 'assert';
44
import { EventEmitter } from 'events';
5-
import { OpPatch } from 'json-patch';
5+
import jsonpatch from 'fast-json-patch';
66
import { Span } from 'opentracing';
77
import * as sinon from 'sinon';
88
import { PassThrough } from 'stream';
@@ -93,7 +93,7 @@ describe('connection', () => {
9393
});
9494
it('should call a handler on request and send the result of the returned Observable', async () => {
9595
const handler: TypeScriptService = Object.create(TypeScriptService.prototype);
96-
const hoverStub = sinon.stub(handler, 'textDocumentHover').returns(Observable.of<OpPatch>(
96+
const hoverStub = sinon.stub(handler, 'textDocumentHover').returns(Observable.of<jsonpatch.Operation>(
9797
{ op: 'add', path: '', value: [] },
9898
{ op: 'add', path: '/-', value: 123 }
9999
));
@@ -260,20 +260,19 @@ describe('connection', () => {
260260
it('should call a handler on request and send partial results of the returned Observable', async () => {
261261
const handler: { [K in keyof TypeScriptService]: TypeScriptService[K] & sinon.SinonStub } = sinon.createStubInstance(TypeScriptService);
262262
handler.initialize.returns(Observable.of({ op: 'add', path: '', value: { capabilities: { streaming: true }}}));
263-
handler.textDocumentHover.returns(Observable.of<OpPatch>(
264-
{ op: 'add', path: '', value: [] },
265-
{ op: 'add', path: '/-', value: 123 }
266-
));
263+
264+
const hoverSubject = new Subject();
265+
handler.textDocumentHover.returns(hoverSubject);
266+
267267
const emitter = new EventEmitter();
268268
const writer = {
269269
write: sinon.spy()
270270
};
271+
271272
registerLanguageHandler(emitter as MessageEmitter, writer as any, handler as any);
272-
emitter.emit('message', { jsonrpc: '2.0', id: 1, method: 'initialize', params: { capabilities: { streaming: true }}});
273-
emitter.emit('message', { jsonrpc: '2.0', id: 2, method: 'textDocument/hover', params: [1, 2] });
274-
sinon.assert.calledOnce(handler.textDocumentHover);
275273

276-
sinon.assert.callCount(writer.write, 5);
274+
// Send initialize
275+
emitter.emit('message', { jsonrpc: '2.0', id: 1, method: 'initialize', params: { capabilities: { streaming: true }}});
277276
assert.deepEqual(writer.write.args[0], [{
278277
jsonrpc: '2.0',
279278
method: '$/partialResult',
@@ -287,16 +286,29 @@ describe('connection', () => {
287286
id: 1,
288287
result: { capabilities: { streaming: true } }
289288
}], 'Expected to send final result for initialize');
289+
290+
// Send hover
291+
emitter.emit('message', { jsonrpc: '2.0', id: 2, method: 'textDocument/hover', params: [1, 2] });
292+
sinon.assert.calledOnce(handler.textDocumentHover);
293+
294+
// Simulate initializing JSON Patch Operation
295+
hoverSubject.next({ op: 'add', path: '', value: [] });
290296
assert.deepEqual(writer.write.args[2], [{
291297
jsonrpc: '2.0',
292298
method: '$/partialResult',
293299
params: { id: 2, patch: [{ op: 'add', path: '', value: [] }] }
294300
}], 'Expected to send partial result that initializes array');
301+
302+
// Simulate streamed value
303+
hoverSubject.next({ op: 'add', path: '/-', value: 123 });
295304
assert.deepEqual(writer.write.args[3], [{
296305
jsonrpc: '2.0',
297306
method: '$/partialResult',
298307
params: { id: 2, patch: [{ op: 'add', path: '/-', value: 123 }] }
299308
}], 'Expected to send partial result that adds 123 to array');
309+
310+
// Complete Subject to trigger final response
311+
hoverSubject.complete();
300312
assert.deepEqual(writer.write.args[4], [{
301313
jsonrpc: '2.0',
302314
id: 2,

0 commit comments

Comments
 (0)