@istar-ts/core 0.11.0 → 0.12.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/README.md +9 -0
- package/dist/index.cjs +180 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +133 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +171 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -908,4 +908,137 @@ export declare function defineProperties<const S extends PropertyShape, const Ki
|
|
|
908
908
|
}): PropertySchema<S, Kind>;
|
|
909
909
|
export declare function validateModelProperties<EK extends string, LK extends string>(model: IstarModel<EK, LK>, schemas: readonly PropertySchema<PropertyShape, string>[]): ModelPropertyIssue[];
|
|
910
910
|
//#endregion
|
|
911
|
+
//#region src/diagnostics.d.ts
|
|
912
|
+
/**
|
|
913
|
+
* The Goal Model Diagnostics Protocol: findings about a model's elements and links, published by
|
|
914
|
+
* any analyser (a language server, a validator, a simulation…) and anchored by element id rather
|
|
915
|
+
* than by text position. Data only: diagnostics are never part of the model and are never
|
|
916
|
+
* written to disk.
|
|
917
|
+
*
|
|
918
|
+
* See goal-controller issue #24 (option D). Producers publish per source; consumers see the
|
|
919
|
+
* union of every source, deduplicated by `(elementId, key, message)`.
|
|
920
|
+
*/
|
|
921
|
+
export type DiagnosticSeverity = "error" | "warning" | "info" | "hint";
|
|
922
|
+
/** Most severe first. */
|
|
923
|
+
export declare const DIAGNOSTIC_SEVERITIES: readonly DiagnosticSeverity[];
|
|
924
|
+
/** A zero-based position in the producer's document (as in LSP). */
|
|
925
|
+
export interface DiagnosticPosition {
|
|
926
|
+
readonly line: number;
|
|
927
|
+
readonly character: number;
|
|
928
|
+
}
|
|
929
|
+
export interface DiagnosticRange {
|
|
930
|
+
readonly start: DiagnosticPosition;
|
|
931
|
+
readonly end: DiagnosticPosition;
|
|
932
|
+
}
|
|
933
|
+
export interface GoalDiagnostic {
|
|
934
|
+
/** Id of the element or link the diagnostic is about. */
|
|
935
|
+
readonly elementId: string;
|
|
936
|
+
/** The custom property it is about; absent for the element as a whole. */
|
|
937
|
+
readonly key?: string;
|
|
938
|
+
readonly severity: DiagnosticSeverity;
|
|
939
|
+
readonly message: string;
|
|
940
|
+
/** Who published it (e.g. `mutrose`, `goal-language`). */
|
|
941
|
+
readonly source?: string;
|
|
942
|
+
/** Where it was found in the producer's document, if it has one. */
|
|
943
|
+
readonly range?: DiagnosticRange;
|
|
944
|
+
readonly code?: string;
|
|
945
|
+
/** Producer data, passed through untouched. */
|
|
946
|
+
readonly data?: unknown;
|
|
947
|
+
}
|
|
948
|
+
/** Negative when `a` is more severe than `b`. */
|
|
949
|
+
export declare function compareSeverity(a: DiagnosticSeverity, b: DiagnosticSeverity): number;
|
|
950
|
+
/** The most severe severity in a list (what a badge shows), or `undefined` if it is empty. */
|
|
951
|
+
export declare function worstDiagnosticSeverity(diagnostics: readonly {
|
|
952
|
+
readonly severity: DiagnosticSeverity;
|
|
953
|
+
}[] | undefined): DiagnosticSeverity | undefined;
|
|
954
|
+
/**
|
|
955
|
+
* The union of several lists, in order, without duplicates: diagnostics with the same
|
|
956
|
+
* `(elementId, key, message)` count once, keeping the first one's position and the most severe
|
|
957
|
+
* severity among them.
|
|
958
|
+
*/
|
|
959
|
+
export declare function mergeDiagnostics(lists: Iterable<readonly GoalDiagnostic[] | undefined>): GoalDiagnostic[];
|
|
960
|
+
/** Diagnostics by element (or link) id, each list in the input order. */
|
|
961
|
+
export declare function groupDiagnostics(diagnostics: readonly GoalDiagnostic[] | undefined): ReadonlyMap<string, readonly GoalDiagnostic[]>;
|
|
962
|
+
/**
|
|
963
|
+
* Holds the diagnostics of several sources. Each `publish` replaces that source's set, so a
|
|
964
|
+
* producer re-publishes everything it currently reports, as an LSP server does.
|
|
965
|
+
*/
|
|
966
|
+
export interface DiagnosticsStore {
|
|
967
|
+
/**
|
|
968
|
+
* Replaces `source`'s diagnostics (an empty list clears them). Entries without a `source` get
|
|
969
|
+
* this one.
|
|
970
|
+
*/
|
|
971
|
+
publish(source: string, diagnostics: readonly GoalDiagnostic[]): void;
|
|
972
|
+
/** Removes one source's diagnostics, or every source's. */
|
|
973
|
+
clear(source?: string): void;
|
|
974
|
+
/** Sources with diagnostics, in the order they first published. */
|
|
975
|
+
sources(): readonly string[];
|
|
976
|
+
/** One source's diagnostics. */
|
|
977
|
+
get(source: string): readonly GoalDiagnostic[];
|
|
978
|
+
/**
|
|
979
|
+
* Every source's diagnostics, merged (see `mergeDiagnostics`). The same array until the next
|
|
980
|
+
* change, so it can back `useSyncExternalStore`.
|
|
981
|
+
*/
|
|
982
|
+
getAll(): readonly GoalDiagnostic[];
|
|
983
|
+
subscribe(listener: () => void): () => void;
|
|
984
|
+
}
|
|
985
|
+
export declare function createDiagnosticsStore(): DiagnosticsStore;
|
|
986
|
+
/**
|
|
987
|
+
* The parts of an LSP `Diagnostic` the adapter reads (structurally typed, so no LSP library is
|
|
988
|
+
* needed). The element is taken from `data.elementId`, or MutRoSe's `data.nodeId`; the property
|
|
989
|
+
* from `data.key`.
|
|
990
|
+
*/
|
|
991
|
+
export interface LspDiagnosticLike {
|
|
992
|
+
readonly range?: DiagnosticRange;
|
|
993
|
+
/** LSP numbering: 1 error, 2 warning, 3 information, 4 hint. */
|
|
994
|
+
readonly severity?: number;
|
|
995
|
+
readonly message: string | {
|
|
996
|
+
readonly value: string;
|
|
997
|
+
};
|
|
998
|
+
readonly source?: string;
|
|
999
|
+
readonly code?: string | number | {
|
|
1000
|
+
readonly value: string | number;
|
|
1001
|
+
};
|
|
1002
|
+
readonly data?: unknown;
|
|
1003
|
+
}
|
|
1004
|
+
export interface FromLspOptions<D extends LspDiagnosticLike = LspDiagnosticLike> {
|
|
1005
|
+
/**
|
|
1006
|
+
* The element of a diagnostic whose `data` names none, e.g. by looking its range up in the
|
|
1007
|
+
* document. Return `undefined` to drop it.
|
|
1008
|
+
*/
|
|
1009
|
+
readonly elementIdFor?: (diagnostic: D) => string | undefined;
|
|
1010
|
+
/**
|
|
1011
|
+
* `'vscode'` for `vscode.Diagnostic` objects, whose severity counts from 0 (error) to 3
|
|
1012
|
+
* (hint). Default `'lsp'`, the protocol's 1 to 4.
|
|
1013
|
+
*/
|
|
1014
|
+
readonly severityNumbering?: "lsp" | "vscode";
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* One LSP diagnostic anchored by `data.elementId` (or `data.nodeId`), or `undefined` when it
|
|
1018
|
+
* names no element. For range-anchored diagnostics use `fromLspDiagnostics` with `elementIdFor`.
|
|
1019
|
+
*/
|
|
1020
|
+
export declare function fromLspDiagnostic(diagnostic: LspDiagnosticLike): GoalDiagnostic | undefined;
|
|
1021
|
+
/** LSP diagnostics as goal diagnostics; those that can't be anchored to an element are dropped. */
|
|
1022
|
+
export declare function fromLspDiagnostics<D extends LspDiagnosticLike>(diagnostics: readonly D[], options?: FromLspOptions<D>): GoalDiagnostic[];
|
|
1023
|
+
/**
|
|
1024
|
+
* The shape MutRoSe's VS Code extension posts to its webview: `{ nodeId, severity, message }`
|
|
1025
|
+
* (plus `range` and `source`). `nodeId` is missing when no node could be found.
|
|
1026
|
+
*/
|
|
1027
|
+
export interface NodeIdDiagnostic {
|
|
1028
|
+
readonly nodeId?: string;
|
|
1029
|
+
readonly key?: string;
|
|
1030
|
+
readonly severity: DiagnosticSeverity | string;
|
|
1031
|
+
readonly message: string;
|
|
1032
|
+
readonly source?: string;
|
|
1033
|
+
readonly range?: DiagnosticRange;
|
|
1034
|
+
readonly code?: string;
|
|
1035
|
+
}
|
|
1036
|
+
/** One `{ nodeId, severity, message }` diagnostic, or `undefined` without a `nodeId`. */
|
|
1037
|
+
export declare function fromNodeIdDiagnostic(diagnostic: NodeIdDiagnostic): GoalDiagnostic | undefined;
|
|
1038
|
+
/**
|
|
1039
|
+
* `{ nodeId, severity, message }` diagnostics (MutRoSe) as goal diagnostics, dropping those
|
|
1040
|
+
* without a node: `store.publish('mutrose', fromNodeIdDiagnostics(message.diagnostics))`.
|
|
1041
|
+
*/
|
|
1042
|
+
export declare function fromNodeIdDiagnostics(diagnostics: readonly NodeIdDiagnostic[]): GoalDiagnostic[];
|
|
1043
|
+
//#endregion
|
|
911
1044
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -908,4 +908,137 @@ export declare function defineProperties<const S extends PropertyShape, const Ki
|
|
|
908
908
|
}): PropertySchema<S, Kind>;
|
|
909
909
|
export declare function validateModelProperties<EK extends string, LK extends string>(model: IstarModel<EK, LK>, schemas: readonly PropertySchema<PropertyShape, string>[]): ModelPropertyIssue[];
|
|
910
910
|
//#endregion
|
|
911
|
+
//#region src/diagnostics.d.ts
|
|
912
|
+
/**
|
|
913
|
+
* The Goal Model Diagnostics Protocol: findings about a model's elements and links, published by
|
|
914
|
+
* any analyser (a language server, a validator, a simulation…) and anchored by element id rather
|
|
915
|
+
* than by text position. Data only: diagnostics are never part of the model and are never
|
|
916
|
+
* written to disk.
|
|
917
|
+
*
|
|
918
|
+
* See goal-controller issue #24 (option D). Producers publish per source; consumers see the
|
|
919
|
+
* union of every source, deduplicated by `(elementId, key, message)`.
|
|
920
|
+
*/
|
|
921
|
+
export type DiagnosticSeverity = "error" | "warning" | "info" | "hint";
|
|
922
|
+
/** Most severe first. */
|
|
923
|
+
export declare const DIAGNOSTIC_SEVERITIES: readonly DiagnosticSeverity[];
|
|
924
|
+
/** A zero-based position in the producer's document (as in LSP). */
|
|
925
|
+
export interface DiagnosticPosition {
|
|
926
|
+
readonly line: number;
|
|
927
|
+
readonly character: number;
|
|
928
|
+
}
|
|
929
|
+
export interface DiagnosticRange {
|
|
930
|
+
readonly start: DiagnosticPosition;
|
|
931
|
+
readonly end: DiagnosticPosition;
|
|
932
|
+
}
|
|
933
|
+
export interface GoalDiagnostic {
|
|
934
|
+
/** Id of the element or link the diagnostic is about. */
|
|
935
|
+
readonly elementId: string;
|
|
936
|
+
/** The custom property it is about; absent for the element as a whole. */
|
|
937
|
+
readonly key?: string;
|
|
938
|
+
readonly severity: DiagnosticSeverity;
|
|
939
|
+
readonly message: string;
|
|
940
|
+
/** Who published it (e.g. `mutrose`, `goal-language`). */
|
|
941
|
+
readonly source?: string;
|
|
942
|
+
/** Where it was found in the producer's document, if it has one. */
|
|
943
|
+
readonly range?: DiagnosticRange;
|
|
944
|
+
readonly code?: string;
|
|
945
|
+
/** Producer data, passed through untouched. */
|
|
946
|
+
readonly data?: unknown;
|
|
947
|
+
}
|
|
948
|
+
/** Negative when `a` is more severe than `b`. */
|
|
949
|
+
export declare function compareSeverity(a: DiagnosticSeverity, b: DiagnosticSeverity): number;
|
|
950
|
+
/** The most severe severity in a list (what a badge shows), or `undefined` if it is empty. */
|
|
951
|
+
export declare function worstDiagnosticSeverity(diagnostics: readonly {
|
|
952
|
+
readonly severity: DiagnosticSeverity;
|
|
953
|
+
}[] | undefined): DiagnosticSeverity | undefined;
|
|
954
|
+
/**
|
|
955
|
+
* The union of several lists, in order, without duplicates: diagnostics with the same
|
|
956
|
+
* `(elementId, key, message)` count once, keeping the first one's position and the most severe
|
|
957
|
+
* severity among them.
|
|
958
|
+
*/
|
|
959
|
+
export declare function mergeDiagnostics(lists: Iterable<readonly GoalDiagnostic[] | undefined>): GoalDiagnostic[];
|
|
960
|
+
/** Diagnostics by element (or link) id, each list in the input order. */
|
|
961
|
+
export declare function groupDiagnostics(diagnostics: readonly GoalDiagnostic[] | undefined): ReadonlyMap<string, readonly GoalDiagnostic[]>;
|
|
962
|
+
/**
|
|
963
|
+
* Holds the diagnostics of several sources. Each `publish` replaces that source's set, so a
|
|
964
|
+
* producer re-publishes everything it currently reports, as an LSP server does.
|
|
965
|
+
*/
|
|
966
|
+
export interface DiagnosticsStore {
|
|
967
|
+
/**
|
|
968
|
+
* Replaces `source`'s diagnostics (an empty list clears them). Entries without a `source` get
|
|
969
|
+
* this one.
|
|
970
|
+
*/
|
|
971
|
+
publish(source: string, diagnostics: readonly GoalDiagnostic[]): void;
|
|
972
|
+
/** Removes one source's diagnostics, or every source's. */
|
|
973
|
+
clear(source?: string): void;
|
|
974
|
+
/** Sources with diagnostics, in the order they first published. */
|
|
975
|
+
sources(): readonly string[];
|
|
976
|
+
/** One source's diagnostics. */
|
|
977
|
+
get(source: string): readonly GoalDiagnostic[];
|
|
978
|
+
/**
|
|
979
|
+
* Every source's diagnostics, merged (see `mergeDiagnostics`). The same array until the next
|
|
980
|
+
* change, so it can back `useSyncExternalStore`.
|
|
981
|
+
*/
|
|
982
|
+
getAll(): readonly GoalDiagnostic[];
|
|
983
|
+
subscribe(listener: () => void): () => void;
|
|
984
|
+
}
|
|
985
|
+
export declare function createDiagnosticsStore(): DiagnosticsStore;
|
|
986
|
+
/**
|
|
987
|
+
* The parts of an LSP `Diagnostic` the adapter reads (structurally typed, so no LSP library is
|
|
988
|
+
* needed). The element is taken from `data.elementId`, or MutRoSe's `data.nodeId`; the property
|
|
989
|
+
* from `data.key`.
|
|
990
|
+
*/
|
|
991
|
+
export interface LspDiagnosticLike {
|
|
992
|
+
readonly range?: DiagnosticRange;
|
|
993
|
+
/** LSP numbering: 1 error, 2 warning, 3 information, 4 hint. */
|
|
994
|
+
readonly severity?: number;
|
|
995
|
+
readonly message: string | {
|
|
996
|
+
readonly value: string;
|
|
997
|
+
};
|
|
998
|
+
readonly source?: string;
|
|
999
|
+
readonly code?: string | number | {
|
|
1000
|
+
readonly value: string | number;
|
|
1001
|
+
};
|
|
1002
|
+
readonly data?: unknown;
|
|
1003
|
+
}
|
|
1004
|
+
export interface FromLspOptions<D extends LspDiagnosticLike = LspDiagnosticLike> {
|
|
1005
|
+
/**
|
|
1006
|
+
* The element of a diagnostic whose `data` names none, e.g. by looking its range up in the
|
|
1007
|
+
* document. Return `undefined` to drop it.
|
|
1008
|
+
*/
|
|
1009
|
+
readonly elementIdFor?: (diagnostic: D) => string | undefined;
|
|
1010
|
+
/**
|
|
1011
|
+
* `'vscode'` for `vscode.Diagnostic` objects, whose severity counts from 0 (error) to 3
|
|
1012
|
+
* (hint). Default `'lsp'`, the protocol's 1 to 4.
|
|
1013
|
+
*/
|
|
1014
|
+
readonly severityNumbering?: "lsp" | "vscode";
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* One LSP diagnostic anchored by `data.elementId` (or `data.nodeId`), or `undefined` when it
|
|
1018
|
+
* names no element. For range-anchored diagnostics use `fromLspDiagnostics` with `elementIdFor`.
|
|
1019
|
+
*/
|
|
1020
|
+
export declare function fromLspDiagnostic(diagnostic: LspDiagnosticLike): GoalDiagnostic | undefined;
|
|
1021
|
+
/** LSP diagnostics as goal diagnostics; those that can't be anchored to an element are dropped. */
|
|
1022
|
+
export declare function fromLspDiagnostics<D extends LspDiagnosticLike>(diagnostics: readonly D[], options?: FromLspOptions<D>): GoalDiagnostic[];
|
|
1023
|
+
/**
|
|
1024
|
+
* The shape MutRoSe's VS Code extension posts to its webview: `{ nodeId, severity, message }`
|
|
1025
|
+
* (plus `range` and `source`). `nodeId` is missing when no node could be found.
|
|
1026
|
+
*/
|
|
1027
|
+
export interface NodeIdDiagnostic {
|
|
1028
|
+
readonly nodeId?: string;
|
|
1029
|
+
readonly key?: string;
|
|
1030
|
+
readonly severity: DiagnosticSeverity | string;
|
|
1031
|
+
readonly message: string;
|
|
1032
|
+
readonly source?: string;
|
|
1033
|
+
readonly range?: DiagnosticRange;
|
|
1034
|
+
readonly code?: string;
|
|
1035
|
+
}
|
|
1036
|
+
/** One `{ nodeId, severity, message }` diagnostic, or `undefined` without a `nodeId`. */
|
|
1037
|
+
export declare function fromNodeIdDiagnostic(diagnostic: NodeIdDiagnostic): GoalDiagnostic | undefined;
|
|
1038
|
+
/**
|
|
1039
|
+
* `{ nodeId, severity, message }` diagnostics (MutRoSe) as goal diagnostics, dropping those
|
|
1040
|
+
* without a node: `store.publish('mutrose', fromNodeIdDiagnostics(message.diagnostics))`.
|
|
1041
|
+
*/
|
|
1042
|
+
export declare function fromNodeIdDiagnostics(diagnostics: readonly NodeIdDiagnostic[]): GoalDiagnostic[];
|
|
1043
|
+
//#endregion
|
|
911
1044
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -2026,6 +2026,176 @@ function validateModelProperties(model, schemas) {
|
|
|
2026
2026
|
return issues;
|
|
2027
2027
|
}
|
|
2028
2028
|
//#endregion
|
|
2029
|
-
|
|
2029
|
+
//#region src/diagnostics.ts
|
|
2030
|
+
/** Most severe first. */
|
|
2031
|
+
const DIAGNOSTIC_SEVERITIES = [
|
|
2032
|
+
"error",
|
|
2033
|
+
"warning",
|
|
2034
|
+
"info",
|
|
2035
|
+
"hint"
|
|
2036
|
+
];
|
|
2037
|
+
const RANK = {
|
|
2038
|
+
error: 0,
|
|
2039
|
+
warning: 1,
|
|
2040
|
+
info: 2,
|
|
2041
|
+
hint: 3
|
|
2042
|
+
};
|
|
2043
|
+
/** Negative when `a` is more severe than `b`. */
|
|
2044
|
+
function compareSeverity(a, b) {
|
|
2045
|
+
return RANK[a] - RANK[b];
|
|
2046
|
+
}
|
|
2047
|
+
/** The most severe severity in a list (what a badge shows), or `undefined` if it is empty. */
|
|
2048
|
+
function worstDiagnosticSeverity(diagnostics) {
|
|
2049
|
+
let worst;
|
|
2050
|
+
for (const d of diagnostics ?? []) {
|
|
2051
|
+
if (worst === void 0 || RANK[d.severity] < RANK[worst]) worst = d.severity;
|
|
2052
|
+
if (worst === "error") break;
|
|
2053
|
+
}
|
|
2054
|
+
return worst;
|
|
2055
|
+
}
|
|
2056
|
+
function identity(d) {
|
|
2057
|
+
return `${d.elementId}\u0000${d.key ?? ""}\u0000${d.message}`;
|
|
2058
|
+
}
|
|
2059
|
+
/**
|
|
2060
|
+
* The union of several lists, in order, without duplicates: diagnostics with the same
|
|
2061
|
+
* `(elementId, key, message)` count once, keeping the first one's position and the most severe
|
|
2062
|
+
* severity among them.
|
|
2063
|
+
*/
|
|
2064
|
+
function mergeDiagnostics(lists) {
|
|
2065
|
+
const result = [];
|
|
2066
|
+
const index = /* @__PURE__ */ new Map();
|
|
2067
|
+
for (const list of lists) for (const d of list ?? []) {
|
|
2068
|
+
const id = identity(d);
|
|
2069
|
+
const at = index.get(id);
|
|
2070
|
+
if (at === void 0) {
|
|
2071
|
+
index.set(id, result.length);
|
|
2072
|
+
result.push(d);
|
|
2073
|
+
} else if (RANK[d.severity] < RANK[result[at].severity]) result[at] = {
|
|
2074
|
+
...result[at],
|
|
2075
|
+
severity: d.severity
|
|
2076
|
+
};
|
|
2077
|
+
}
|
|
2078
|
+
return result;
|
|
2079
|
+
}
|
|
2080
|
+
/** Diagnostics by element (or link) id, each list in the input order. */
|
|
2081
|
+
function groupDiagnostics(diagnostics) {
|
|
2082
|
+
const map = /* @__PURE__ */ new Map();
|
|
2083
|
+
for (const d of diagnostics ?? []) {
|
|
2084
|
+
const list = map.get(d.elementId);
|
|
2085
|
+
if (list) list.push(d);
|
|
2086
|
+
else map.set(d.elementId, [d]);
|
|
2087
|
+
}
|
|
2088
|
+
return map;
|
|
2089
|
+
}
|
|
2090
|
+
const NONE = [];
|
|
2091
|
+
function createDiagnosticsStore() {
|
|
2092
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
2093
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
2094
|
+
let merged = NONE;
|
|
2095
|
+
const changed = () => {
|
|
2096
|
+
merged = bySource.size === 0 ? NONE : mergeDiagnostics(bySource.values());
|
|
2097
|
+
for (const listener of listeners) listener();
|
|
2098
|
+
};
|
|
2099
|
+
return {
|
|
2100
|
+
publish(source, diagnostics) {
|
|
2101
|
+
if (diagnostics.length === 0) {
|
|
2102
|
+
if (bySource.delete(source)) changed();
|
|
2103
|
+
return;
|
|
2104
|
+
}
|
|
2105
|
+
bySource.set(source, diagnostics.map((d) => d.source === void 0 ? {
|
|
2106
|
+
...d,
|
|
2107
|
+
source
|
|
2108
|
+
} : d));
|
|
2109
|
+
changed();
|
|
2110
|
+
},
|
|
2111
|
+
clear(source) {
|
|
2112
|
+
if (source === void 0) {
|
|
2113
|
+
if (bySource.size === 0) return;
|
|
2114
|
+
bySource.clear();
|
|
2115
|
+
} else if (!bySource.delete(source)) return;
|
|
2116
|
+
changed();
|
|
2117
|
+
},
|
|
2118
|
+
sources: () => [...bySource.keys()],
|
|
2119
|
+
get: (source) => bySource.get(source) ?? NONE,
|
|
2120
|
+
getAll: () => merged,
|
|
2121
|
+
subscribe(listener) {
|
|
2122
|
+
listeners.add(listener);
|
|
2123
|
+
return () => listeners.delete(listener);
|
|
2124
|
+
}
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
const LSP_SEVERITIES = [
|
|
2128
|
+
"error",
|
|
2129
|
+
"warning",
|
|
2130
|
+
"info",
|
|
2131
|
+
"hint"
|
|
2132
|
+
];
|
|
2133
|
+
function anchorOf(data) {
|
|
2134
|
+
if (typeof data !== "object" || data === null) return {};
|
|
2135
|
+
const record = data;
|
|
2136
|
+
const elementId = typeof record.elementId === "string" ? record.elementId : typeof record.nodeId === "string" ? record.nodeId : void 0;
|
|
2137
|
+
return {
|
|
2138
|
+
...elementId ? { elementId } : {},
|
|
2139
|
+
...typeof record.key === "string" ? { key: record.key } : {}
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2142
|
+
function convertLsp(d, options) {
|
|
2143
|
+
const anchor = anchorOf(d.data);
|
|
2144
|
+
const elementId = anchor.elementId ?? options.elementIdFor?.(d);
|
|
2145
|
+
if (!elementId) return void 0;
|
|
2146
|
+
const base = options.severityNumbering === "vscode" ? 0 : 1;
|
|
2147
|
+
const severity = d.severity === void 0 ? "error" : LSP_SEVERITIES[d.severity - base] ?? "error";
|
|
2148
|
+
const code = typeof d.code === "object" ? d.code.value : d.code;
|
|
2149
|
+
return {
|
|
2150
|
+
elementId,
|
|
2151
|
+
...anchor.key !== void 0 ? { key: anchor.key } : {},
|
|
2152
|
+
severity,
|
|
2153
|
+
message: typeof d.message === "string" ? d.message : d.message.value,
|
|
2154
|
+
...d.source !== void 0 ? { source: d.source } : {},
|
|
2155
|
+
...d.range ? { range: d.range } : {},
|
|
2156
|
+
...code !== void 0 ? { code: String(code) } : {},
|
|
2157
|
+
...d.data !== void 0 ? { data: d.data } : {}
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2160
|
+
/**
|
|
2161
|
+
* One LSP diagnostic anchored by `data.elementId` (or `data.nodeId`), or `undefined` when it
|
|
2162
|
+
* names no element. For range-anchored diagnostics use `fromLspDiagnostics` with `elementIdFor`.
|
|
2163
|
+
*/
|
|
2164
|
+
function fromLspDiagnostic(diagnostic) {
|
|
2165
|
+
return convertLsp(diagnostic, {});
|
|
2166
|
+
}
|
|
2167
|
+
/** LSP diagnostics as goal diagnostics; those that can't be anchored to an element are dropped. */
|
|
2168
|
+
function fromLspDiagnostics(diagnostics, options = {}) {
|
|
2169
|
+
const result = [];
|
|
2170
|
+
for (const d of diagnostics) {
|
|
2171
|
+
const converted = convertLsp(d, options);
|
|
2172
|
+
if (converted) result.push(converted);
|
|
2173
|
+
}
|
|
2174
|
+
return result;
|
|
2175
|
+
}
|
|
2176
|
+
/** One `{ nodeId, severity, message }` diagnostic, or `undefined` without a `nodeId`. */
|
|
2177
|
+
function fromNodeIdDiagnostic(diagnostic) {
|
|
2178
|
+
const { nodeId, severity, ...rest } = diagnostic;
|
|
2179
|
+
if (!nodeId) return void 0;
|
|
2180
|
+
return {
|
|
2181
|
+
...rest,
|
|
2182
|
+
elementId: nodeId,
|
|
2183
|
+
severity: Object.hasOwn(RANK, severity) ? severity : "info"
|
|
2184
|
+
};
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* `{ nodeId, severity, message }` diagnostics (MutRoSe) as goal diagnostics, dropping those
|
|
2188
|
+
* without a node: `store.publish('mutrose', fromNodeIdDiagnostics(message.diagnostics))`.
|
|
2189
|
+
*/
|
|
2190
|
+
function fromNodeIdDiagnostics(diagnostics) {
|
|
2191
|
+
const result = [];
|
|
2192
|
+
for (const d of diagnostics) {
|
|
2193
|
+
const converted = fromNodeIdDiagnostic(d);
|
|
2194
|
+
if (converted) result.push(converted);
|
|
2195
|
+
}
|
|
2196
|
+
return result;
|
|
2197
|
+
}
|
|
2198
|
+
//#endregion
|
|
2199
|
+
export { ACTOR_KINDS, ACTOR_LINK_KINDS, CONTRIBUTION_LABELS, DEFAULT_DIAGRAM, DEFAULT_ELEMENT_SIZE, DEPENDENCY_LINK_KINDS, DIAGNOSTIC_SEVERITIES, ELEMENT_KINDS, FILE_METAMODEL_KEY, ISTAR_2_0, ISTAR_PREFIX, ISTAR_VERSION, LINK_KINDS, LINK_KIND_INFO, METAMODEL_VERSION, MetamodelError, ModelOperationError, NODE_KINDS, NODE_KIND_INFO, NODE_LINK_KINDS, PISTAR_TOOL, PistarParseError, PistarWriteError, addDependency, addElement, boolean, canLink, childrenOf, compareSeverity, connect, createDiagnosticsStore, createEmptyModel, createModelStore, defaultIdGenerator, defineMetamodelExtension, defineProperties, dependencyEnds, dependencyLinksOf, disconnect, effectiveElementKind, effectiveLinkKind, elementBehavesLike, elementKindDefinition, enumOf, extendMetamodel, fileMetamodelExtension, fileMetamodelOf, fromLspDiagnostic, fromLspDiagnostics, fromNodeIdDiagnostic, fromNodeIdDiagnostics, getSourceLayout, groupDiagnostics, hostMetamodelOf, inheritMetamodel, inheritSourceLayout, isActor, isActorIn, isActorKind, isActorKindIn, isActorLinkKind, isContributionLabel, isDependencyLinkKind, isElementKind, isLinkKind, isNode, isNodeIn, isNodeKind, isNodeKindIn, isNodeLinkKind, linkKindDefinition, linksOf, mergeDiagnostics, metamodelOf, moveElement, nestElement, number, parsePistar, prop, removeElement, removeElements, setHostMetamodel, shortKindName, string, toPistar, toPistarObject, updateDiagram, updateElement, updateLink, validateFileMetamodel, validateModel, validateModelProperties, withFileMetamodel, withMetamodel, worstDiagnosticSeverity };
|
|
2030
2200
|
|
|
2031
2201
|
//# sourceMappingURL=index.js.map
|