@hydranium/protocol 1.0.0-next.10
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/LICENSE +21 -0
- package/README.md +81 -0
- package/lib/abstract-logger.d.ts +66 -0
- package/lib/abstract-logger.d.ts.map +1 -0
- package/lib/abstract-logger.js +110 -0
- package/lib/abstract-logger.js.map +1 -0
- package/lib/browser-runtime.d.ts +124 -0
- package/lib/browser-runtime.d.ts.map +1 -0
- package/lib/browser-runtime.js +11 -0
- package/lib/browser-runtime.js.map +1 -0
- package/lib/client/data-events.d.ts +49 -0
- package/lib/client/data-events.d.ts.map +1 -0
- package/lib/client/data-events.js +60 -0
- package/lib/client/data-events.js.map +1 -0
- package/lib/client/data-port.d.ts +95 -0
- package/lib/client/data-port.d.ts.map +1 -0
- package/lib/client/data-port.js +11 -0
- package/lib/client/data-port.js.map +1 -0
- package/lib/client/data-session.d.ts +129 -0
- package/lib/client/data-session.d.ts.map +1 -0
- package/lib/client/data-session.js +179 -0
- package/lib/client/data-session.js.map +1 -0
- package/lib/client/index.d.ts +39 -0
- package/lib/client/index.d.ts.map +1 -0
- package/lib/client/index.js +55 -0
- package/lib/client/index.js.map +1 -0
- package/lib/client/message-relay.d.ts +111 -0
- package/lib/client/message-relay.d.ts.map +1 -0
- package/lib/client/message-relay.js +139 -0
- package/lib/client/message-relay.js.map +1 -0
- package/lib/client/post-message-transport.d.ts +77 -0
- package/lib/client/post-message-transport.d.ts.map +1 -0
- package/lib/client/post-message-transport.js +95 -0
- package/lib/client/post-message-transport.js.map +1 -0
- package/lib/clock.d.ts +111 -0
- package/lib/clock.d.ts.map +1 -0
- package/lib/clock.js +74 -0
- package/lib/clock.js.map +1 -0
- package/lib/data/data-protocol-methods.d.ts +39 -0
- package/lib/data/data-protocol-methods.d.ts.map +1 -0
- package/lib/data/data-protocol-methods.js +61 -0
- package/lib/data/data-protocol-methods.js.map +1 -0
- package/lib/data/data-server-protocol.d.ts +264 -0
- package/lib/data/data-server-protocol.d.ts.map +1 -0
- package/lib/data/data-server-protocol.js +11 -0
- package/lib/data/data-server-protocol.js.map +1 -0
- package/lib/data/diagnostics.d.ts +97 -0
- package/lib/data/diagnostics.d.ts.map +1 -0
- package/lib/data/diagnostics.js +25 -0
- package/lib/data/diagnostics.js.map +1 -0
- package/lib/data/events.d.ts +107 -0
- package/lib/data/events.d.ts.map +1 -0
- package/lib/data/events.js +11 -0
- package/lib/data/events.js.map +1 -0
- package/lib/data/index.d.ts +15 -0
- package/lib/data/index.d.ts.map +1 -0
- package/lib/data/index.js +38 -0
- package/lib/data/index.js.map +1 -0
- package/lib/data/methods.d.ts +57 -0
- package/lib/data/methods.d.ts.map +1 -0
- package/lib/data/methods.js +60 -0
- package/lib/data/methods.js.map +1 -0
- package/lib/data/requests.d.ts +65 -0
- package/lib/data/requests.d.ts.map +1 -0
- package/lib/data/requests.js +11 -0
- package/lib/data/requests.js.map +1 -0
- package/lib/debouncer.d.ts +75 -0
- package/lib/debouncer.d.ts.map +1 -0
- package/lib/debouncer.js +91 -0
- package/lib/debouncer.js.map +1 -0
- package/lib/errors.d.ts +84 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +113 -0
- package/lib/errors.js.map +1 -0
- package/lib/host-diagnostics.d.ts +58 -0
- package/lib/host-diagnostics.d.ts.map +1 -0
- package/lib/host-diagnostics.js +18 -0
- package/lib/host-diagnostics.js.map +1 -0
- package/lib/index.d.ts +34 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +56 -0
- package/lib/index.js.map +1 -0
- package/lib/latency-collector.d.ts +126 -0
- package/lib/latency-collector.d.ts.map +1 -0
- package/lib/latency-collector.js +137 -0
- package/lib/latency-collector.js.map +1 -0
- package/lib/logger.d.ts +119 -0
- package/lib/logger.d.ts.map +1 -0
- package/lib/logger.js +126 -0
- package/lib/logger.js.map +1 -0
- package/lib/model-server.d.ts +352 -0
- package/lib/model-server.d.ts.map +1 -0
- package/lib/model-server.js +160 -0
- package/lib/model-server.js.map +1 -0
- package/lib/model-service/args.d.ts +64 -0
- package/lib/model-service/args.d.ts.map +1 -0
- package/lib/model-service/args.js +11 -0
- package/lib/model-service/args.js.map +1 -0
- package/lib/model-service/index.d.ts +11 -0
- package/lib/model-service/index.d.ts.map +1 -0
- package/lib/model-service/index.js +31 -0
- package/lib/model-service/index.js.map +1 -0
- package/lib/model-service/reference-candidate.d.ts +56 -0
- package/lib/model-service/reference-candidate.d.ts.map +1 -0
- package/lib/model-service/reference-candidate.js +11 -0
- package/lib/model-service/reference-candidate.js.map +1 -0
- package/lib/noop-logger.d.ts +25 -0
- package/lib/noop-logger.d.ts.map +1 -0
- package/lib/noop-logger.js +36 -0
- package/lib/noop-logger.js.map +1 -0
- package/lib/observable-value.d.ts +72 -0
- package/lib/observable-value.d.ts.map +1 -0
- package/lib/observable-value.js +52 -0
- package/lib/observable-value.js.map +1 -0
- package/lib/patch-merge.d.ts +123 -0
- package/lib/patch-merge.d.ts.map +1 -0
- package/lib/patch-merge.js +104 -0
- package/lib/patch-merge.js.map +1 -0
- package/lib/profile-session.d.ts +87 -0
- package/lib/profile-session.d.ts.map +1 -0
- package/lib/profile-session.js +98 -0
- package/lib/profile-session.js.map +1 -0
- package/lib/profiling.d.ts +83 -0
- package/lib/profiling.d.ts.map +1 -0
- package/lib/profiling.js +20 -0
- package/lib/profiling.js.map +1 -0
- package/lib/project.d.ts +121 -0
- package/lib/project.d.ts.map +1 -0
- package/lib/project.js +34 -0
- package/lib/project.js.map +1 -0
- package/lib/rpc/bind-rpc-methods.d.ts +100 -0
- package/lib/rpc/bind-rpc-methods.d.ts.map +1 -0
- package/lib/rpc/bind-rpc-methods.js +110 -0
- package/lib/rpc/bind-rpc-methods.js.map +1 -0
- package/lib/rpc/create-rpc-proxy.d.ts +188 -0
- package/lib/rpc/create-rpc-proxy.d.ts.map +1 -0
- package/lib/rpc/create-rpc-proxy.js +158 -0
- package/lib/rpc/create-rpc-proxy.js.map +1 -0
- package/lib/rpc/index.d.ts +12 -0
- package/lib/rpc/index.d.ts.map +1 -0
- package/lib/rpc/index.js +31 -0
- package/lib/rpc/index.js.map +1 -0
- package/lib/rpc/wire-prefix.d.ts +37 -0
- package/lib/rpc/wire-prefix.d.ts.map +1 -0
- package/lib/rpc/wire-prefix.js +49 -0
- package/lib/rpc/wire-prefix.js.map +1 -0
- package/lib/testing/data-doubles.d.ts +121 -0
- package/lib/testing/data-doubles.d.ts.map +1 -0
- package/lib/testing/data-doubles.js +102 -0
- package/lib/testing/data-doubles.js.map +1 -0
- package/lib/testing/fake-clock.d.ts +35 -0
- package/lib/testing/fake-clock.d.ts.map +1 -0
- package/lib/testing/fake-clock.js +86 -0
- package/lib/testing/fake-clock.js.map +1 -0
- package/lib/testing/harness.d.ts +24 -0
- package/lib/testing/harness.d.ts.map +1 -0
- package/lib/testing/harness.js +11 -0
- package/lib/testing/harness.js.map +1 -0
- package/lib/testing/index.d.ts +13 -0
- package/lib/testing/index.d.ts.map +1 -0
- package/lib/testing/index.js +41 -0
- package/lib/testing/index.js.map +1 -0
- package/lib/testing/node/duplex-connection.d.ts +25 -0
- package/lib/testing/node/duplex-connection.d.ts.map +1 -0
- package/lib/testing/node/duplex-connection.js +34 -0
- package/lib/testing/node/duplex-connection.js.map +1 -0
- package/lib/testing/node/duplex-stream.d.ts +32 -0
- package/lib/testing/node/duplex-stream.d.ts.map +1 -0
- package/lib/testing/node/duplex-stream.js +35 -0
- package/lib/testing/node/duplex-stream.js.map +1 -0
- package/lib/testing/node/index.d.ts +11 -0
- package/lib/testing/node/index.d.ts.map +1 -0
- package/lib/testing/node/index.js +37 -0
- package/lib/testing/node/index.js.map +1 -0
- package/lib/testing/wait-for.d.ts +69 -0
- package/lib/testing/wait-for.d.ts.map +1 -0
- package/lib/testing/wait-for.js +67 -0
- package/lib/testing/wait-for.js.map +1 -0
- package/lib/tracer.d.ts +115 -0
- package/lib/tracer.d.ts.map +1 -0
- package/lib/tracer.js +205 -0
- package/lib/tracer.js.map +1 -0
- package/lib/transfer-diagnostic.d.ts +73 -0
- package/lib/transfer-diagnostic.d.ts.map +1 -0
- package/lib/transfer-diagnostic.js +45 -0
- package/lib/transfer-diagnostic.js.map +1 -0
- package/lib/transfer-document.d.ts +73 -0
- package/lib/transfer-document.d.ts.map +1 -0
- package/lib/transfer-document.js +46 -0
- package/lib/transfer-document.js.map +1 -0
- package/lib/transfer-element.d.ts +39 -0
- package/lib/transfer-element.d.ts.map +1 -0
- package/lib/transfer-element.js +11 -0
- package/lib/transfer-element.js.map +1 -0
- package/lib/uri.d.ts +62 -0
- package/lib/uri.d.ts.map +1 -0
- package/lib/uri.js +28 -0
- package/lib/uri.js.map +1 -0
- package/lib/util.d.ts +147 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +211 -0
- package/lib/util.js.map +1 -0
- package/package.json +100 -0
- package/src/abstract-logger.ts +120 -0
- package/src/browser-runtime.ts +135 -0
- package/src/client/data-events.ts +71 -0
- package/src/client/data-port.ts +99 -0
- package/src/client/data-session.ts +209 -0
- package/src/client/index.ts +40 -0
- package/src/client/message-relay.ts +216 -0
- package/src/client/post-message-transport.ts +167 -0
- package/src/clock.ts +173 -0
- package/src/data/data-protocol-methods.ts +79 -0
- package/src/data/data-server-protocol.ts +296 -0
- package/src/data/diagnostics.ts +116 -0
- package/src/data/events.ts +127 -0
- package/src/data/index.ts +23 -0
- package/src/data/methods.ts +59 -0
- package/src/data/requests.ts +70 -0
- package/src/debouncer.ts +118 -0
- package/src/errors.ts +127 -0
- package/src/host-diagnostics.ts +63 -0
- package/src/index.ts +41 -0
- package/src/latency-collector.ts +231 -0
- package/src/logger.ts +172 -0
- package/src/model-server.ts +479 -0
- package/src/model-service/args.ts +67 -0
- package/src/model-service/index.ts +16 -0
- package/src/model-service/reference-candidate.ts +58 -0
- package/src/noop-logger.ts +36 -0
- package/src/observable-value.ts +92 -0
- package/src/patch-merge.ts +165 -0
- package/src/profile-session.ts +164 -0
- package/src/profiling.ts +113 -0
- package/src/project.ts +125 -0
- package/src/rpc/README.md +163 -0
- package/src/rpc/bind-rpc-methods.ts +180 -0
- package/src/rpc/create-rpc-proxy.ts +292 -0
- package/src/rpc/index.ts +16 -0
- package/src/rpc/wire-prefix.ts +48 -0
- package/src/testing/data-doubles.ts +178 -0
- package/src/testing/fake-clock.ts +106 -0
- package/src/testing/harness.ts +24 -0
- package/src/testing/index.ts +26 -0
- package/src/testing/node/duplex-connection.ts +50 -0
- package/src/testing/node/duplex-stream.ts +51 -0
- package/src/testing/node/index.ts +22 -0
- package/src/testing/wait-for.ts +94 -0
- package/src/tracer.ts +277 -0
- package/src/transfer-diagnostic.ts +92 -0
- package/src/transfer-document.ts +99 -0
- package/src/transfer-element.ts +43 -0
- package/src/uri.ts +61 -0
- package/src/util.ts +250 -0
package/src/util.ts
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2023 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
/** A user-defined type predicate. */
|
|
11
|
+
export type TypeGuard<T> = (item: unknown) => item is T;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Minimal disposable shape, intentionally identical to `vscode-jsonrpc.Disposable`
|
|
15
|
+
* by structural typing so it interoperates without an actual dependency on that
|
|
16
|
+
* library. Consumers may pass instances of this type wherever a `Disposable`
|
|
17
|
+
* is expected, and vice versa.
|
|
18
|
+
*
|
|
19
|
+
* Re-defined locally rather than re-exported from `vscode-jsonrpc` so adopters
|
|
20
|
+
* pulling this interface in do not transitively see `vscode-jsonrpc` types as
|
|
21
|
+
* part of the framework's public surface.
|
|
22
|
+
*/
|
|
23
|
+
export interface Disposable {
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export namespace Disposable {
|
|
28
|
+
export function create(dispose: () => void): Disposable {
|
|
29
|
+
return { dispose };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Shared no-op {@link Disposable} — `dispose()` does nothing. Use wherever a
|
|
33
|
+
* disposable is required but there is nothing to release (a subscription with
|
|
34
|
+
* no teardown, a listener registration in a test double) instead of a fresh
|
|
35
|
+
* `{ dispose: () => undefined }` literal. Frozen so the shared instance can't
|
|
36
|
+
* be mutated.
|
|
37
|
+
*/
|
|
38
|
+
export const EMPTY: Disposable = Object.freeze({ dispose: () => undefined });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A collection of disposables that itself implements {@link Disposable}.
|
|
43
|
+
*
|
|
44
|
+
* - {@link dispose} is idempotent: repeat calls are safe.
|
|
45
|
+
* - {@link push} returns the added disposable for chaining.
|
|
46
|
+
* - Push-after-disposal disposes the added item immediately (prevents leaks
|
|
47
|
+
* from late arrivals on a collection that has already been torn down).
|
|
48
|
+
* - LIFO drain order: last-pushed disposes first. Matches the convention that
|
|
49
|
+
* later disposables typically depend on earlier ones (e.g., a subscription
|
|
50
|
+
* depends on a connection, so the subscription must dispose first before
|
|
51
|
+
* the connection tears down its transport).
|
|
52
|
+
* - A throwing dispose does not strand subsequent disposables in the drain.
|
|
53
|
+
*
|
|
54
|
+
* Fills the gap left by vscode-jsonrpc and Langium, which provide only the
|
|
55
|
+
* `Disposable` interface and a `Disposable.create()` factory.
|
|
56
|
+
*/
|
|
57
|
+
export class DisposableCollection implements Disposable {
|
|
58
|
+
protected readonly disposables: Disposable[] = [];
|
|
59
|
+
protected _disposed = false;
|
|
60
|
+
|
|
61
|
+
get disposed(): boolean {
|
|
62
|
+
return this._disposed;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
push(disposable: Disposable): Disposable {
|
|
66
|
+
if (this._disposed) {
|
|
67
|
+
disposable.dispose();
|
|
68
|
+
} else {
|
|
69
|
+
this.disposables.push(disposable);
|
|
70
|
+
}
|
|
71
|
+
return disposable;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
dispose(): void {
|
|
75
|
+
if (this._disposed) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this._disposed = true;
|
|
79
|
+
while (this.disposables.length > 0) {
|
|
80
|
+
try {
|
|
81
|
+
this.disposables.pop()!.dispose();
|
|
82
|
+
} catch (_err) {
|
|
83
|
+
// Continue draining — one failed dispose shouldn't strand the rest.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A `Promise` paired with its `resolve` / `reject` callbacks, so producer
|
|
91
|
+
* and consumer code can be in different scopes. Use when a constructor
|
|
92
|
+
* needs to expose a `ready` promise that a later method resolves.
|
|
93
|
+
*
|
|
94
|
+
* Equivalent to Theia / GLSP / Langium's `Deferred` utility — re-implemented
|
|
95
|
+
* here so `@hydranium/protocol` stays runtime-dependency-free.
|
|
96
|
+
*/
|
|
97
|
+
export class Deferred<T = void> {
|
|
98
|
+
readonly promise: Promise<T>;
|
|
99
|
+
resolve!: (value: T | PromiseLike<T>) => void;
|
|
100
|
+
reject!: (reason?: unknown) => void;
|
|
101
|
+
|
|
102
|
+
constructor() {
|
|
103
|
+
this.promise = new Promise<T>((resolve, reject) => {
|
|
104
|
+
this.resolve = resolve;
|
|
105
|
+
this.reject = reject;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A value that is either `T` directly (sync) or a thenable that resolves to `T`
|
|
112
|
+
* (async). Used in framework hook signatures where adopter overrides may be
|
|
113
|
+
* either sync or async without forcing the synchronous fast path to pay an
|
|
114
|
+
* unconditional microtask tick.
|
|
115
|
+
*
|
|
116
|
+
* Uses the permissive `PromiseLike<T>` form so externally-produced thenables
|
|
117
|
+
* (non-native Promise implementations) also flow through.
|
|
118
|
+
*
|
|
119
|
+
* Pair with {@link isPromiseLike} at hot-loop call sites to preserve
|
|
120
|
+
* the sync fast path (an `await` on a non-promise still schedules a microtask).
|
|
121
|
+
*/
|
|
122
|
+
export type MaybePromise<T> = T | PromiseLike<T>;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Type guard distinguishing the async branch of {@link MaybePromise}.
|
|
126
|
+
*
|
|
127
|
+
* At framework call sites in tight loops, guarding before the `await` keeps
|
|
128
|
+
* sync implementations on the synchronous fast path — `await` on
|
|
129
|
+
* a non-promise still schedules a microtask, which for per-node loops adds
|
|
130
|
+
* up. Outside of tight loops a naive `await maybe` is equivalent and
|
|
131
|
+
* shorter; reach for the guard only when the call sits on the build's
|
|
132
|
+
* critical path.
|
|
133
|
+
*
|
|
134
|
+
* Thenable check (`'then' in value`) rather than `instanceof Promise` so
|
|
135
|
+
* non-native Promise implementations also classify as async.
|
|
136
|
+
*/
|
|
137
|
+
export function isPromiseLike<T = unknown>(value: MaybePromise<T>): value is PromiseLike<T> {
|
|
138
|
+
return !!value && typeof (value as PromiseLike<T>).then === 'function';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Removes `readonly` from all properties of `T`. */
|
|
142
|
+
export type Mutable<T> = { -readonly [P in keyof T]: T[P] };
|
|
143
|
+
|
|
144
|
+
/** Returns the same value typed as a {@link Mutable}. Compile-time only. */
|
|
145
|
+
export function asMutable<T>(item: T): Mutable<T> {
|
|
146
|
+
return item;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Type-guard variant: narrows `item` to `Mutable<T> | undefined` if `guard` accepts it. */
|
|
150
|
+
export function toMutable<T>(item: unknown, guard: TypeGuard<T>): item is Mutable<T> | undefined;
|
|
151
|
+
export function toMutable<T>(item: unknown, guard?: TypeGuard<T>): item is Mutable<T> | undefined {
|
|
152
|
+
return guard ? guard(item) : true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Wrap `text` in `quoteChar`, escaping interior occurrences with `replaceChar`.
|
|
157
|
+
*
|
|
158
|
+
* - Empty input becomes a pair of quote characters.
|
|
159
|
+
* - Pre-existing surrounding quotes are not double-wrapped.
|
|
160
|
+
* - Interior `quoteChar` runs are mapped to `replaceChar`.
|
|
161
|
+
*/
|
|
162
|
+
export function quote(text: string, quoteChar = '"', replaceChar = "'"): string {
|
|
163
|
+
if (text.length === 0) {
|
|
164
|
+
return quoteChar + quoteChar;
|
|
165
|
+
}
|
|
166
|
+
let quoted = text;
|
|
167
|
+
if (!quoted.startsWith(quoteChar)) {
|
|
168
|
+
quoted = quoteChar + quoted;
|
|
169
|
+
}
|
|
170
|
+
if (!quoted.endsWith(quoteChar)) {
|
|
171
|
+
quoted += quoteChar;
|
|
172
|
+
}
|
|
173
|
+
return (
|
|
174
|
+
quoteChar +
|
|
175
|
+
quoted
|
|
176
|
+
.substring(1, quoted.length - 1)
|
|
177
|
+
.split(quoteChar)
|
|
178
|
+
.join(replaceChar) +
|
|
179
|
+
quoteChar
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Strip a single layer of `quoteChar` from the start and end of `text` if present. */
|
|
184
|
+
export function unquote(text: string, quoteChar = '"'): string {
|
|
185
|
+
const start = text.startsWith(quoteChar) ? 1 : undefined;
|
|
186
|
+
const end = text.endsWith(quoteChar) ? -1 : undefined;
|
|
187
|
+
return text.slice(start, end);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Capitalise the first character of `input`. */
|
|
191
|
+
export function toPascal(input: string): string {
|
|
192
|
+
return input.charAt(0).toLocaleUpperCase() + input.slice(1);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Format a [codicon](https://github.com/microsoft/vscode-codicons) name as the
|
|
197
|
+
* CSS class string consumed by VS Code- and Theia-style icon hosts.
|
|
198
|
+
*
|
|
199
|
+
* Presentation, not wire contract, and a duplicate of `@eclipse-glsp/client`'s
|
|
200
|
+
* export of the same name — a file importing both barrels gets an ambiguity, so
|
|
201
|
+
* client code that already depends on GLSP takes the upstream one. It stays on
|
|
202
|
+
* this barrel because adopter protocol packages re-export these helpers
|
|
203
|
+
* wholesale, which makes relocating it a breaking change rather than a move.
|
|
204
|
+
*/
|
|
205
|
+
export function codiconCSSString(icon: string): string {
|
|
206
|
+
return `codicon codicon-${icon}`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** The identity function. Useful as a default mapping callback. */
|
|
210
|
+
export function identity<T>(value: T): T {
|
|
211
|
+
return value;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Find a name based on `suggestion` that is not already in `existing`, appending an
|
|
215
|
+
* incrementing numeric suffix until a free slot is found. */
|
|
216
|
+
export function findNextUnique(suggestion: string, existing: string[]): string;
|
|
217
|
+
export function findNextUnique<T>(suggestion: string, existing: T[], nameGetter: (element: T) => string): string;
|
|
218
|
+
export function findNextUnique<T>(suggestion: string, existing: T[], nameGetter?: (element: T) => string): string {
|
|
219
|
+
const names = nameGetter ? existing.map(nameGetter) : (existing as string[]);
|
|
220
|
+
let name = suggestion;
|
|
221
|
+
let index = 1;
|
|
222
|
+
while (names.includes(name)) {
|
|
223
|
+
name = suggestion + index++;
|
|
224
|
+
}
|
|
225
|
+
return name;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Throw if reached. Helper for exhaustiveness checks at the end of a discriminated-union switch. */
|
|
229
|
+
export function unreachable(input: never): never {
|
|
230
|
+
throw new Error('Value detected in unreachable assertion: ' + `${input}`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Resolve a nested value from a plain object using a path of property names.
|
|
235
|
+
* Returns `undefined` for any segment that is not an object or is null.
|
|
236
|
+
*
|
|
237
|
+
* The generic `T` is a caller-provided assertion about the value's type — it
|
|
238
|
+
* is not validated at runtime. Use `unknown` (the default) if the type is
|
|
239
|
+
* uncertain, then narrow with a type-guard.
|
|
240
|
+
*/
|
|
241
|
+
export function getAt<T = unknown>(obj: unknown, path: string[]): T | undefined {
|
|
242
|
+
let cur: unknown = obj;
|
|
243
|
+
for (const seg of path) {
|
|
244
|
+
if (cur == null || typeof cur !== 'object') {
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
cur = (cur as Record<string, unknown>)[seg];
|
|
248
|
+
}
|
|
249
|
+
return cur as T;
|
|
250
|
+
}
|