brighterscript 0.68.4 → 0.69.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/BusyStatusTracker.d.ts +37 -7
- package/dist/BusyStatusTracker.js +73 -8
- package/dist/BusyStatusTracker.js.map +1 -1
- package/dist/DiagnosticCollection.d.ts +19 -5
- package/dist/DiagnosticCollection.js +67 -16
- package/dist/DiagnosticCollection.js.map +1 -1
- package/dist/LanguageServer.d.ts +82 -132
- package/dist/LanguageServer.js +403 -940
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +9 -4
- package/dist/Logger.js +30 -6
- package/dist/Logger.js.map +1 -1
- package/dist/PluginInterface.d.ts +1 -1
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +20 -2
- package/dist/Program.js +124 -49
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +21 -7
- package/dist/ProgramBuilder.js +45 -22
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.js +6 -3
- package/dist/Scope.js.map +1 -1
- package/dist/SemanticTokenUtils.js +1 -1
- package/dist/SemanticTokenUtils.js.map +1 -1
- package/dist/bscPlugin/CallExpressionInfo.js +2 -1
- package/dist/bscPlugin/CallExpressionInfo.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.js +14 -4
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.js +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.js +9 -9
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/common/Sequencer.d.ts +27 -0
- package/dist/common/Sequencer.js +113 -0
- package/dist/common/Sequencer.js.map +1 -0
- package/dist/common/Sequencer.spec.d.ts +1 -0
- package/dist/common/Sequencer.spec.js +75 -0
- package/dist/common/Sequencer.spec.js.map +1 -0
- package/dist/deferred.d.ts +2 -0
- package/dist/deferred.js +10 -0
- package/dist/deferred.js.map +1 -1
- package/dist/files/BrsFile.d.ts +1 -1
- package/dist/files/BrsFile.js +10 -15
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +8 -0
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/interfaces.d.ts +22 -2
- package/dist/lexer/Lexer.js +1 -1
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/logging.d.ts +6 -1
- package/dist/logging.js +14 -1
- package/dist/logging.js.map +1 -1
- package/dist/lsp/ActionQueue.d.ts +35 -0
- package/dist/lsp/ActionQueue.js +115 -0
- package/dist/lsp/ActionQueue.js.map +1 -0
- package/dist/lsp/ActionQueue.spec.d.ts +1 -0
- package/dist/lsp/ActionQueue.spec.js +80 -0
- package/dist/lsp/ActionQueue.spec.js.map +1 -0
- package/dist/lsp/DocumentManager.d.ts +63 -0
- package/dist/lsp/DocumentManager.js +122 -0
- package/dist/lsp/DocumentManager.js.map +1 -0
- package/dist/lsp/DocumentManager.spec.d.ts +1 -0
- package/dist/lsp/DocumentManager.spec.js +103 -0
- package/dist/lsp/DocumentManager.spec.js.map +1 -0
- package/dist/lsp/LspProject.d.ts +231 -0
- package/dist/lsp/LspProject.js +3 -0
- package/dist/lsp/LspProject.js.map +1 -0
- package/dist/lsp/PathFilterer.d.ts +75 -0
- package/dist/lsp/PathFilterer.js +196 -0
- package/dist/lsp/PathFilterer.js.map +1 -0
- package/dist/lsp/PathFilterer.spec.d.ts +1 -0
- package/dist/lsp/PathFilterer.spec.js +182 -0
- package/dist/lsp/PathFilterer.spec.js.map +1 -0
- package/dist/lsp/Project.d.ts +178 -0
- package/dist/lsp/Project.js +438 -0
- package/dist/lsp/Project.js.map +1 -0
- package/dist/lsp/Project.spec.d.ts +1 -0
- package/dist/lsp/Project.spec.js +236 -0
- package/dist/lsp/Project.spec.js.map +1 -0
- package/dist/lsp/ProjectManager.d.ts +221 -0
- package/dist/lsp/ProjectManager.js +735 -0
- package/dist/lsp/ProjectManager.js.map +1 -0
- package/dist/lsp/ProjectManager.spec.d.ts +1 -0
- package/dist/lsp/ProjectManager.spec.js +756 -0
- package/dist/lsp/ProjectManager.spec.js.map +1 -0
- package/dist/lsp/ReaderWriterManager.d.ts +21 -0
- package/dist/lsp/ReaderWriterManager.js +60 -0
- package/dist/lsp/ReaderWriterManager.js.map +1 -0
- package/dist/lsp/worker/MessageHandler.d.ts +99 -0
- package/dist/lsp/worker/MessageHandler.js +138 -0
- package/dist/lsp/worker/MessageHandler.js.map +1 -0
- package/dist/lsp/worker/MessageHandler.spec.d.ts +1 -0
- package/dist/lsp/worker/MessageHandler.spec.js +64 -0
- package/dist/lsp/worker/MessageHandler.spec.js.map +1 -0
- package/dist/lsp/worker/WorkerPool.d.ts +38 -0
- package/dist/lsp/worker/WorkerPool.js +78 -0
- package/dist/lsp/worker/WorkerPool.js.map +1 -0
- package/dist/lsp/worker/WorkerPool.spec.d.ts +1 -0
- package/dist/lsp/worker/WorkerPool.spec.js +59 -0
- package/dist/lsp/worker/WorkerPool.spec.js.map +1 -0
- package/dist/lsp/worker/WorkerThreadProject.d.ts +144 -0
- package/dist/lsp/worker/WorkerThreadProject.js +181 -0
- package/dist/lsp/worker/WorkerThreadProject.js.map +1 -0
- package/dist/lsp/worker/WorkerThreadProject.spec.d.ts +2 -0
- package/dist/lsp/worker/WorkerThreadProject.spec.js +68 -0
- package/dist/lsp/worker/WorkerThreadProject.spec.js.map +1 -0
- package/dist/lsp/worker/WorkerThreadProjectRunner.d.ts +15 -0
- package/dist/lsp/worker/WorkerThreadProjectRunner.js +58 -0
- package/dist/lsp/worker/WorkerThreadProjectRunner.js.map +1 -0
- package/dist/util.d.ts +31 -5
- package/dist/util.js +117 -19
- package/dist/util.js.map +1 -1
- package/package.json +11 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CancellationToken } from 'vscode-languageserver-protocol';
|
|
2
|
+
export declare class ActionQueue {
|
|
3
|
+
constructor(options?: ActionQueueOptions);
|
|
4
|
+
options: ActionQueueOptions;
|
|
5
|
+
private queue;
|
|
6
|
+
/**
|
|
7
|
+
* Run an action. This will run after all previous actions have completed
|
|
8
|
+
* @param action action to be run
|
|
9
|
+
*/
|
|
10
|
+
run<T = any>(action: Action<T>, data?: T): Promise<void>;
|
|
11
|
+
private isRunning;
|
|
12
|
+
/**
|
|
13
|
+
* Process the next pending action. Safe to call even if another action is running, we will only run one action at a time
|
|
14
|
+
*/
|
|
15
|
+
private process;
|
|
16
|
+
private stringifyJson;
|
|
17
|
+
get isIdle(): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Get a promise that resolves when the queue is empty
|
|
20
|
+
*/
|
|
21
|
+
onIdle(): Promise<void>;
|
|
22
|
+
once(eventname: 'idle'): Promise<void>;
|
|
23
|
+
on(eventName: 'idle', handler: () => any): any;
|
|
24
|
+
private emit;
|
|
25
|
+
private emitter;
|
|
26
|
+
dispose(): void;
|
|
27
|
+
}
|
|
28
|
+
export declare type Action<T = any> = (data: T, cancellationToken?: CancellationToken) => any;
|
|
29
|
+
export interface ActionQueueOptions {
|
|
30
|
+
/**
|
|
31
|
+
* Max milliseconds an individual action may run before it's cancelled. This is the amount of time the action actually runs,
|
|
32
|
+
* and does not count the time it waits in the queue
|
|
33
|
+
*/
|
|
34
|
+
maxActionDuration: number;
|
|
35
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ActionQueue = void 0;
|
|
4
|
+
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");
|
|
5
|
+
const deferred_1 = require("../deferred");
|
|
6
|
+
const safeJsonStringify = require("safe-json-stringify");
|
|
7
|
+
const eventemitter3_1 = require("eventemitter3");
|
|
8
|
+
const util_1 = require("../util");
|
|
9
|
+
class ActionQueue {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
var _a;
|
|
12
|
+
var _b;
|
|
13
|
+
this.queue = [];
|
|
14
|
+
this.isRunning = false;
|
|
15
|
+
this.emitter = new eventemitter3_1.EventEmitter();
|
|
16
|
+
this.options = options !== null && options !== void 0 ? options : {};
|
|
17
|
+
(_a = (_b = this.options).maxActionDuration) !== null && _a !== void 0 ? _a : (_b.maxActionDuration = 2147483647);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Run an action. This will run after all previous actions have completed
|
|
21
|
+
* @param action action to be run
|
|
22
|
+
*/
|
|
23
|
+
run(action, data) {
|
|
24
|
+
const deferred = new deferred_1.Deferred();
|
|
25
|
+
this.queue.push({
|
|
26
|
+
action: action,
|
|
27
|
+
data: data,
|
|
28
|
+
deferred: deferred
|
|
29
|
+
});
|
|
30
|
+
void this.process();
|
|
31
|
+
return deferred.promise;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Process the next pending action. Safe to call even if another action is running, we will only run one action at a time
|
|
35
|
+
*/
|
|
36
|
+
async process() {
|
|
37
|
+
if (this.isRunning) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (this.queue.length === 0) {
|
|
41
|
+
this.emit('idle');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
this.isRunning = true;
|
|
45
|
+
//run the action and resolve the deferred if it succeeds
|
|
46
|
+
const queueItem = this.queue.shift();
|
|
47
|
+
const cancellationTokenSource = new vscode_languageserver_protocol_1.CancellationTokenSource();
|
|
48
|
+
//process the action next tick to allow the event loop to catch up
|
|
49
|
+
let actionPromise = Promise.resolve().then(() => {
|
|
50
|
+
return queueItem.action(queueItem.data, cancellationTokenSource.token);
|
|
51
|
+
}).then((result) => {
|
|
52
|
+
queueItem.deferred.resolve(result);
|
|
53
|
+
});
|
|
54
|
+
//register a timeout that will reject if the action takes too long
|
|
55
|
+
let timeoutId;
|
|
56
|
+
const timeoutPromise = new Promise((resolve, reject) => {
|
|
57
|
+
timeoutId = setTimeout(() => {
|
|
58
|
+
cancellationTokenSource.cancel();
|
|
59
|
+
reject(new Error(`Action took longer than ${this.options.maxActionDuration}ms to complete. Data: ${this.stringifyJson(queueItem.data)}`));
|
|
60
|
+
}, this.options.maxActionDuration);
|
|
61
|
+
});
|
|
62
|
+
//wait for the action to finish or the timeout to trigger
|
|
63
|
+
await Promise.race([timeoutPromise, actionPromise]).catch((error) => {
|
|
64
|
+
//if we have an error, reject the deferred
|
|
65
|
+
queueItem.deferred.tryReject(error);
|
|
66
|
+
});
|
|
67
|
+
clearTimeout(timeoutId);
|
|
68
|
+
//small delay to allow the event loop to catch up
|
|
69
|
+
await util_1.default.sleep(1);
|
|
70
|
+
this.isRunning = false;
|
|
71
|
+
//at this point, we've properly handled the action, so try and handle the next one
|
|
72
|
+
await this.process();
|
|
73
|
+
}
|
|
74
|
+
stringifyJson(data) {
|
|
75
|
+
return safeJsonStringify(data, (_, value) => {
|
|
76
|
+
return typeof value === 'bigint' ? value.toString() : value;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
get isIdle() {
|
|
80
|
+
return this.queue.length === 0 && !this.isRunning;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get a promise that resolves when the queue is empty
|
|
84
|
+
*/
|
|
85
|
+
onIdle() {
|
|
86
|
+
if (!this.isIdle) {
|
|
87
|
+
return this.once('idle');
|
|
88
|
+
}
|
|
89
|
+
return Promise.resolve();
|
|
90
|
+
}
|
|
91
|
+
once(eventName) {
|
|
92
|
+
return new Promise((resolve) => {
|
|
93
|
+
const disconnect = this.on(eventName, (...args) => {
|
|
94
|
+
disconnect();
|
|
95
|
+
resolve(args);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
on(eventName, handler) {
|
|
100
|
+
this.emitter.on(eventName, handler);
|
|
101
|
+
return () => {
|
|
102
|
+
this.emitter.removeListener(eventName, handler);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async emit(eventName, data) {
|
|
106
|
+
//emit these events on next tick, otherwise they will be processed immediately which could cause issues
|
|
107
|
+
await util_1.default.sleep(0);
|
|
108
|
+
this.emitter.emit(eventName, data);
|
|
109
|
+
}
|
|
110
|
+
dispose() {
|
|
111
|
+
this.emitter.removeAllListeners();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.ActionQueue = ActionQueue;
|
|
115
|
+
//# sourceMappingURL=ActionQueue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionQueue.js","sourceRoot":"","sources":["../../src/lsp/ActionQueue.ts"],"names":[],"mappings":";;;AACA,mFAAyE;AACzE,0CAAuC;AACvC,yDAAyD;AACzD,iDAA6C;AAC7C,kCAA2B;AAE3B,MAAa,WAAW;IAEpB,YACI,OAA4B;;;QAQxB,UAAK,GAcR,EAAE,CAAC;QAiBA,cAAS,GAAG,KAAK,CAAC;QAqGlB,YAAO,GAAG,IAAI,4BAAY,EAAE,CAAC;QA1IjC,IAAI,CAAC,OAAO,GAAG,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAS,CAAC;QACpC,YAAA,IAAI,CAAC,OAAO,EAAC,iBAAiB,uCAAjB,iBAAiB,GAAK,UAAa,EAAC;IACrD,CAAC;IAoBD;;;OAGG;IACI,GAAG,CAAU,MAAiB,EAAE,IAAQ;QAC3C,MAAM,QAAQ,GAAG,IAAI,mBAAQ,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI;YACV,QAAQ,EAAE,QAAQ;SACrB,CAAC,CAAC;QACH,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC5B,CAAC;IAID;;OAEG;IACK,KAAK,CAAC,OAAO;QACjB,IAAI,IAAI,CAAC,SAAS,EAAE;YAChB,OAAO;SACV;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAClB,OAAO;SACV;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAEtB,wDAAwD;QACxD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,uBAAuB,GAAG,IAAI,wDAAuB,EAAE,CAAC;QAE9D,kEAAkE;QAClE,IAAI,aAAa,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YAC5C,OAAO,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,uBAAuB,CAAC,KAAK,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,kEAAkE;QAClE,IAAI,SAAyB,CAAC;QAC9B,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnD,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBACxB,uBAAuB,CAAC,MAAM,EAAE,CAAC;gBACjC,MAAM,CACF,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,OAAO,CAAC,iBAAiB,yBAAyB,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CACpI,CAAC;YACN,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,yDAAyD;QACzD,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YAChE,0CAA0C;YAC1C,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,YAAY,CAAC,SAAS,CAAC,CAAC;QAExB,iDAAiD;QACjD,MAAM,cAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QAEvB,kFAAkF;QAClF,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAEO,aAAa,CAAC,IAAS;QAC3B,OAAO,iBAAiB,CACpB,IAAI,EACJ,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;YACT,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAChE,CAAC,CACJ,CAAC;IACN,CAAC;IAED,IAAW,MAAM;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;IACtD,CAAC;IAED;;OAEG;IACI,MAAM;QACT,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YACd,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAC5B;QACD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAGM,IAAI,CAAC,SAAiB;QACzB,OAAO,IAAI,OAAO,CAAM,CAAC,OAAO,EAAE,EAAE;YAChC,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,CAAC,SAA6C,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE;gBAClF,UAAU,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,CAAC;YAClB,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAGM,EAAE,CAAC,SAAiB,EAAE,OAA8B;QACvD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,OAAc,CAAC,CAAC;QAC3C,OAAO,GAAG,EAAE;YACR,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,OAAc,CAAC,CAAC;QAC3D,CAAC,CAAC;IACN,CAAC;IAGO,KAAK,CAAC,IAAI,CAAC,SAAiB,EAAE,IAAU;QAC5C,uGAAuG;QACvG,MAAM,cAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;IAGM,OAAO;QACV,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC;IACtC,CAAC;CACJ;AApJD,kCAoJC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const ActionQueue_1 = require("./ActionQueue");
|
|
5
|
+
const util_1 = require("../util");
|
|
6
|
+
const deferred_1 = require("../deferred");
|
|
7
|
+
const testHelpers_spec_1 = require("../testHelpers.spec");
|
|
8
|
+
describe('ActionQueue', () => {
|
|
9
|
+
let queue;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
queue = new ActionQueue_1.ActionQueue();
|
|
12
|
+
});
|
|
13
|
+
it('runs successful actions in sequence', async () => {
|
|
14
|
+
let results = [];
|
|
15
|
+
void queue.run(() => {
|
|
16
|
+
results.push(1);
|
|
17
|
+
});
|
|
18
|
+
await queue.run(() => {
|
|
19
|
+
results.push(2);
|
|
20
|
+
});
|
|
21
|
+
(0, chai_1.expect)(results).to.eql([1, 2]);
|
|
22
|
+
});
|
|
23
|
+
it('runs actions after a failed action', async () => {
|
|
24
|
+
let results = [];
|
|
25
|
+
void queue.run(() => {
|
|
26
|
+
results.push(1);
|
|
27
|
+
});
|
|
28
|
+
void queue.run(() => {
|
|
29
|
+
throw new Error('Crash');
|
|
30
|
+
});
|
|
31
|
+
await queue.run(() => {
|
|
32
|
+
results.push(3);
|
|
33
|
+
});
|
|
34
|
+
(0, chai_1.expect)(results).to.eql([1, 3]);
|
|
35
|
+
});
|
|
36
|
+
it('properly serializes bigInt', async () => {
|
|
37
|
+
queue = new ActionQueue_1.ActionQueue({
|
|
38
|
+
maxActionDuration: 1
|
|
39
|
+
});
|
|
40
|
+
await (0, testHelpers_spec_1.expectThrowsAsync)(async () => {
|
|
41
|
+
await queue.run(async () => {
|
|
42
|
+
await util_1.default.sleep(10);
|
|
43
|
+
}, BigInt(1));
|
|
44
|
+
}, 'Action took longer than 1ms to complete. Data: "1"');
|
|
45
|
+
});
|
|
46
|
+
it('rejects action that took too long, and marks cancellationToken accordingly', async () => {
|
|
47
|
+
queue = new ActionQueue_1.ActionQueue({
|
|
48
|
+
maxActionDuration: 100
|
|
49
|
+
});
|
|
50
|
+
let cancellationToken;
|
|
51
|
+
let results = [];
|
|
52
|
+
let task1Deferred = new deferred_1.Deferred();
|
|
53
|
+
let task1Promise = queue.run(async (data, token) => {
|
|
54
|
+
await util_1.default.sleep(200);
|
|
55
|
+
cancellationToken = token;
|
|
56
|
+
if (!cancellationToken.isCancellationRequested) {
|
|
57
|
+
results.push(1);
|
|
58
|
+
}
|
|
59
|
+
task1Deferred.resolve();
|
|
60
|
+
});
|
|
61
|
+
await queue.run(() => {
|
|
62
|
+
results.push(2);
|
|
63
|
+
});
|
|
64
|
+
(0, chai_1.expect)(results).to.eql([2]);
|
|
65
|
+
//wait for task 1's promise to finish and verify we get an error
|
|
66
|
+
let error;
|
|
67
|
+
try {
|
|
68
|
+
await task1Promise;
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
error = e;
|
|
72
|
+
}
|
|
73
|
+
(0, chai_1.expect)(error === null || error === void 0 ? void 0 : error.message).to.eql('Action took longer than 100ms to complete. Data: undefined');
|
|
74
|
+
//now wait for task1's work to actually finish
|
|
75
|
+
await task1Deferred.promise;
|
|
76
|
+
//the token should be marked as cancelled
|
|
77
|
+
(0, chai_1.expect)(cancellationToken.isCancellationRequested).to.be.true;
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=ActionQueue.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActionQueue.spec.js","sourceRoot":"","sources":["../../src/lsp/ActionQueue.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { MaybePromise } from '../interfaces';
|
|
2
|
+
/**
|
|
3
|
+
* Maintains a queued/buffered list of file operations. These operations don't actually do anything on their own.
|
|
4
|
+
* You need to call the .apply() function and provide an action to operate on them.
|
|
5
|
+
*/
|
|
6
|
+
export declare class DocumentManager {
|
|
7
|
+
private options;
|
|
8
|
+
constructor(options: {
|
|
9
|
+
delay: number;
|
|
10
|
+
flushHandler?: (event: FlushEvent) => any;
|
|
11
|
+
});
|
|
12
|
+
private queue;
|
|
13
|
+
private timeoutHandle;
|
|
14
|
+
private throttle;
|
|
15
|
+
/**
|
|
16
|
+
* Add/set the contents of a file
|
|
17
|
+
*/
|
|
18
|
+
set(options: {
|
|
19
|
+
srcPath: string;
|
|
20
|
+
fileContents?: string;
|
|
21
|
+
allowStandaloneProject?: boolean;
|
|
22
|
+
}): void;
|
|
23
|
+
/**
|
|
24
|
+
* Delete a file or directory. If a directory is provided, all pending changes within that directory will be discarded
|
|
25
|
+
* and only the delete action will be queued
|
|
26
|
+
*/
|
|
27
|
+
delete(srcPath: string): void;
|
|
28
|
+
private isFlushRunning;
|
|
29
|
+
private flush;
|
|
30
|
+
/**
|
|
31
|
+
* Is the manager settled (i.e. no pending files, all files have been fully flushed)
|
|
32
|
+
*/
|
|
33
|
+
get isIdle(): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Returns a promise that resolves when there are no pending files and no active flushes are running. Will immediately resolve if there are no files,
|
|
36
|
+
* and will wait until files are flushed if there are files.
|
|
37
|
+
*/
|
|
38
|
+
onIdle(): Promise<void>;
|
|
39
|
+
once(eventName: 'flush'): Promise<FlushEvent>;
|
|
40
|
+
on(eventName: 'flush', handler: (data: any) => MaybePromise<void>): any;
|
|
41
|
+
private emitSync;
|
|
42
|
+
private emitter;
|
|
43
|
+
dispose(): void;
|
|
44
|
+
}
|
|
45
|
+
export interface SetDocumentAction {
|
|
46
|
+
srcPath: string;
|
|
47
|
+
type: 'set';
|
|
48
|
+
allowStandaloneProject?: boolean;
|
|
49
|
+
fileContents: string;
|
|
50
|
+
}
|
|
51
|
+
export interface DeleteDocumentAction {
|
|
52
|
+
srcPath: string;
|
|
53
|
+
type: 'delete';
|
|
54
|
+
allowStandaloneProject?: boolean;
|
|
55
|
+
}
|
|
56
|
+
export declare type DocumentAction = SetDocumentAction | DeleteDocumentAction;
|
|
57
|
+
export declare type DocumentActionWithStatus = DocumentAction & {
|
|
58
|
+
id: number;
|
|
59
|
+
status: 'accepted' | 'rejected';
|
|
60
|
+
};
|
|
61
|
+
export interface FlushEvent {
|
|
62
|
+
actions: DocumentAction[];
|
|
63
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DocumentManager = void 0;
|
|
4
|
+
const EventEmitter = require("eventemitter3");
|
|
5
|
+
const util_1 = require("../util");
|
|
6
|
+
/**
|
|
7
|
+
* Maintains a queued/buffered list of file operations. These operations don't actually do anything on their own.
|
|
8
|
+
* You need to call the .apply() function and provide an action to operate on them.
|
|
9
|
+
*/
|
|
10
|
+
class DocumentManager {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.queue = new Map();
|
|
14
|
+
this.isFlushRunning = false;
|
|
15
|
+
this.emitter = new EventEmitter();
|
|
16
|
+
}
|
|
17
|
+
throttle() {
|
|
18
|
+
if (this.timeoutHandle) {
|
|
19
|
+
clearTimeout(this.timeoutHandle);
|
|
20
|
+
}
|
|
21
|
+
this.timeoutHandle = setTimeout(() => {
|
|
22
|
+
void this.flush();
|
|
23
|
+
}, this.options.delay);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Add/set the contents of a file
|
|
27
|
+
*/
|
|
28
|
+
set(options) {
|
|
29
|
+
var _a;
|
|
30
|
+
const srcPath = util_1.default.standardizePath(options.srcPath);
|
|
31
|
+
if (this.queue.has(srcPath)) {
|
|
32
|
+
this.queue.delete(srcPath);
|
|
33
|
+
}
|
|
34
|
+
this.queue.set(srcPath, {
|
|
35
|
+
type: 'set',
|
|
36
|
+
srcPath: srcPath,
|
|
37
|
+
fileContents: options.fileContents,
|
|
38
|
+
allowStandaloneProject: (_a = options.allowStandaloneProject) !== null && _a !== void 0 ? _a : false
|
|
39
|
+
});
|
|
40
|
+
//schedule a future flush
|
|
41
|
+
this.throttle();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Delete a file or directory. If a directory is provided, all pending changes within that directory will be discarded
|
|
45
|
+
* and only the delete action will be queued
|
|
46
|
+
*/
|
|
47
|
+
delete(srcPath) {
|
|
48
|
+
srcPath = util_1.default.standardizePath(srcPath);
|
|
49
|
+
//remove any pending action with this exact path
|
|
50
|
+
this.queue.delete(srcPath);
|
|
51
|
+
//we can't tell if this a directory, so just remove all pending changes for files that start with this path
|
|
52
|
+
for (const key of this.queue.keys()) {
|
|
53
|
+
if (key.startsWith(srcPath)) {
|
|
54
|
+
this.queue.delete(key);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//register this delete
|
|
58
|
+
this.queue.set(srcPath, { type: 'delete', srcPath: srcPath });
|
|
59
|
+
//schedule a future flush
|
|
60
|
+
this.throttle();
|
|
61
|
+
}
|
|
62
|
+
async flush() {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
//if we're already running a flush, don't run another
|
|
65
|
+
if (this.isFlushRunning) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.isFlushRunning = true;
|
|
69
|
+
while (this.queue.size > 0) {
|
|
70
|
+
try {
|
|
71
|
+
const event = {
|
|
72
|
+
actions: [...this.queue.values()]
|
|
73
|
+
};
|
|
74
|
+
this.queue.clear();
|
|
75
|
+
await ((_b = (_a = this.options).flushHandler) === null || _b === void 0 ? void 0 : _b.call(_a, event));
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
console.error(e);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
this.emitSync('flush');
|
|
82
|
+
this.isFlushRunning = false;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Is the manager settled (i.e. no pending files, all files have been fully flushed)
|
|
86
|
+
*/
|
|
87
|
+
get isIdle() {
|
|
88
|
+
return this.queue.size === 0 && this.isFlushRunning === false;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns a promise that resolves when there are no pending files and no active flushes are running. Will immediately resolve if there are no files,
|
|
92
|
+
* and will wait until files are flushed if there are files.
|
|
93
|
+
*/
|
|
94
|
+
async onIdle() {
|
|
95
|
+
while (!this.isIdle) {
|
|
96
|
+
await this.once('flush');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
once(eventName) {
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
const off = this.on(eventName, (data) => {
|
|
102
|
+
off();
|
|
103
|
+
resolve(data);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
on(eventName, handler) {
|
|
108
|
+
this.emitter.on(eventName, handler);
|
|
109
|
+
return () => {
|
|
110
|
+
this.emitter.removeListener(eventName, handler);
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
emitSync(eventName, data) {
|
|
114
|
+
this.emitter.emit(eventName, data);
|
|
115
|
+
}
|
|
116
|
+
dispose() {
|
|
117
|
+
this.queue = new Map();
|
|
118
|
+
this.emitter.removeAllListeners();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.DocumentManager = DocumentManager;
|
|
122
|
+
//# sourceMappingURL=DocumentManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocumentManager.js","sourceRoot":"","sources":["../../src/lsp/DocumentManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const util_1 = require("../util");
|
|
5
|
+
const DocumentManager_1 = require("./DocumentManager");
|
|
6
|
+
const testHelpers_spec_1 = require("../testHelpers.spec");
|
|
7
|
+
describe('DocumentManager', () => {
|
|
8
|
+
let manager;
|
|
9
|
+
let results = [];
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
results = [];
|
|
12
|
+
manager = new DocumentManager_1.DocumentManager({
|
|
13
|
+
delay: 5,
|
|
14
|
+
flushHandler: (event) => {
|
|
15
|
+
results.push(...event.actions);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
it('throttles multiple events', async () => {
|
|
20
|
+
manager.set({ srcPath: 'alpha', fileContents: 'one' });
|
|
21
|
+
await util_1.util.sleep(1);
|
|
22
|
+
manager.set({ srcPath: 'alpha', fileContents: 'two' });
|
|
23
|
+
await util_1.util.sleep(1);
|
|
24
|
+
manager.set({ srcPath: 'alpha', fileContents: 'three' });
|
|
25
|
+
await manager.onIdle();
|
|
26
|
+
(0, chai_1.expect)(results).to.eql([{
|
|
27
|
+
type: 'set',
|
|
28
|
+
srcPath: 'alpha',
|
|
29
|
+
fileContents: 'three',
|
|
30
|
+
allowStandaloneProject: false
|
|
31
|
+
}]);
|
|
32
|
+
});
|
|
33
|
+
it('does not lose newly added that arrives during a flush operation', async () => {
|
|
34
|
+
const srcPath = (0, util_1.standardizePath) `${testHelpers_spec_1.rootDir}/source/main.bs`;
|
|
35
|
+
let contentsQueue = [
|
|
36
|
+
'two',
|
|
37
|
+
'three',
|
|
38
|
+
'four'
|
|
39
|
+
];
|
|
40
|
+
manager = new DocumentManager_1.DocumentManager({
|
|
41
|
+
delay: 5,
|
|
42
|
+
flushHandler: (event) => {
|
|
43
|
+
//once the flush happens, add NEW data to the queue. this is the data we need to ensure we don't lose
|
|
44
|
+
if (contentsQueue.length > 0) {
|
|
45
|
+
manager.set({ srcPath: srcPath, fileContents: contentsQueue.shift() });
|
|
46
|
+
}
|
|
47
|
+
//store the actions
|
|
48
|
+
results.push(...event.actions);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
manager.set({ srcPath: srcPath, fileContents: 'one' });
|
|
52
|
+
await manager.onIdle();
|
|
53
|
+
(0, chai_1.expect)(results.map(x => x.fileContents)).to.eql([
|
|
54
|
+
'one',
|
|
55
|
+
'two',
|
|
56
|
+
'three',
|
|
57
|
+
'four'
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
it('any file change delays the first one', async () => {
|
|
61
|
+
manager.set({ srcPath: 'alpha', fileContents: 'one' });
|
|
62
|
+
await util_1.util.sleep(1);
|
|
63
|
+
manager.set({ srcPath: 'beta', fileContents: 'two' });
|
|
64
|
+
await util_1.util.sleep(1);
|
|
65
|
+
manager.set({ srcPath: 'alpha', fileContents: 'three' });
|
|
66
|
+
await util_1.util.sleep(1);
|
|
67
|
+
manager.set({ srcPath: 'beta', fileContents: 'four' });
|
|
68
|
+
await util_1.util.sleep(1);
|
|
69
|
+
await manager.onIdle();
|
|
70
|
+
(0, chai_1.expect)(results).to.eql([{
|
|
71
|
+
type: 'set',
|
|
72
|
+
srcPath: 'alpha',
|
|
73
|
+
fileContents: 'three',
|
|
74
|
+
allowStandaloneProject: false
|
|
75
|
+
}, {
|
|
76
|
+
type: 'set',
|
|
77
|
+
srcPath: 'beta',
|
|
78
|
+
fileContents: 'four',
|
|
79
|
+
allowStandaloneProject: false
|
|
80
|
+
}]);
|
|
81
|
+
});
|
|
82
|
+
it('keeps the last-in change', async () => {
|
|
83
|
+
manager.set({ srcPath: 'alpha', fileContents: 'one' });
|
|
84
|
+
manager.delete('alpha');
|
|
85
|
+
await manager.onIdle();
|
|
86
|
+
(0, chai_1.expect)(results).to.eql([{
|
|
87
|
+
type: 'delete',
|
|
88
|
+
srcPath: 'alpha'
|
|
89
|
+
}]);
|
|
90
|
+
results = [];
|
|
91
|
+
manager.set({ srcPath: 'alpha', fileContents: 'two' });
|
|
92
|
+
manager.delete('alpha');
|
|
93
|
+
manager.set({ srcPath: 'alpha', fileContents: 'three' });
|
|
94
|
+
await manager.onIdle();
|
|
95
|
+
(0, chai_1.expect)(results).to.eql([{
|
|
96
|
+
type: 'set',
|
|
97
|
+
srcPath: 'alpha',
|
|
98
|
+
fileContents: 'three',
|
|
99
|
+
allowStandaloneProject: false
|
|
100
|
+
}]);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=DocumentManager.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocumentManager.spec.js","sourceRoot":"","sources":["../../src/lsp/DocumentManager.spec.ts"],"names":[],"mappings":"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"}
|