aboutsummaryrefslogtreecommitdiffstats
path: root/language-web/src/main/js/xtext/xtextServiceResults.ts
diff options
context:
space:
mode:
Diffstat (limited to 'language-web/src/main/js/xtext/xtextServiceResults.ts')
-rw-r--r--language-web/src/main/js/xtext/xtextServiceResults.ts284
1 files changed, 75 insertions, 209 deletions
diff --git a/language-web/src/main/js/xtext/xtextServiceResults.ts b/language-web/src/main/js/xtext/xtextServiceResults.ts
index b2de1e4a..b6867e2f 100644
--- a/language-web/src/main/js/xtext/xtextServiceResults.ts
+++ b/language-web/src/main/js/xtext/xtextServiceResults.ts
@@ -1,239 +1,105 @@
1export interface IPongResult { 1import { z } from 'zod';
2 pong: string;
3}
4
5export function isPongResult(result: unknown): result is IPongResult {
6 const pongResult = result as IPongResult;
7 return typeof pongResult === 'object'
8 && typeof pongResult.pong === 'string';
9}
10
11export interface IDocumentStateResult {
12 stateId: string;
13}
14
15export function isDocumentStateResult(result: unknown): result is IDocumentStateResult {
16 const documentStateResult = result as IDocumentStateResult;
17 return typeof documentStateResult === 'object'
18 && typeof documentStateResult.stateId === 'string';
19}
20
21export const VALID_CONFLICTS = ['invalidStateId', 'canceled'] as const;
22
23export type Conflict = typeof VALID_CONFLICTS[number];
24
25export function isConflict(value: unknown): value is Conflict {
26 return typeof value === 'string' && VALID_CONFLICTS.includes(value as Conflict);
27}
28
29export interface IServiceConflictResult {
30 conflict: Conflict;
31}
32
33export function isServiceConflictResult(result: unknown): result is IServiceConflictResult {
34 const serviceConflictResult = result as IServiceConflictResult;
35 return typeof serviceConflictResult === 'object'
36 && isConflict(serviceConflictResult.conflict);
37}
38
39export function isInvalidStateIdConflictResult(result: unknown): boolean {
40 return isServiceConflictResult(result) && result.conflict === 'invalidStateId';
41}
42
43export const VALID_SEVERITIES = ['error', 'warning', 'info', 'ignore'] as const;
44
45export type Severity = typeof VALID_SEVERITIES[number];
46
47export function isSeverity(value: unknown): value is Severity {
48 return typeof value === 'string' && VALID_SEVERITIES.includes(value as Severity);
49}
50
51export interface IIssue {
52 description: string;
53
54 severity: Severity;
55
56 line: number;
57
58 column: number;
59
60 offset: number;
61
62 length: number;
63}
64 2
65export function isIssue(value: unknown): value is IIssue { 3export const pongResult = z.object({
66 const issue = value as IIssue; 4 pong: z.string().nonempty(),
67 return typeof issue === 'object' 5});
68 && typeof issue.description === 'string'
69 && isSeverity(issue.severity)
70 && typeof issue.line === 'number'
71 && typeof issue.column === 'number'
72 && typeof issue.offset === 'number'
73 && typeof issue.length === 'number';
74}
75 6
76export interface IValidationResult { 7export type PongResult = z.infer<typeof pongResult>;
77 issues: IIssue[];
78}
79 8
80function isArrayOfType<T>(value: unknown, check: (entry: unknown) => entry is T): value is T[] { 9export const documentStateResult = z.object({
81 return Array.isArray(value) && (value as T[]).every(check); 10 stateId: z.string().nonempty(),
82} 11});
83 12
84export function isValidationResult(result: unknown): result is IValidationResult { 13export type DocumentStateResult = z.infer<typeof documentStateResult>;
85 const validationResult = result as IValidationResult;
86 return typeof validationResult === 'object'
87 && isArrayOfType(validationResult.issues, isIssue);
88}
89
90export interface IReplaceRegion {
91 offset: number;
92 14
93 length: number; 15export const conflict = z.enum(['invalidStateId', 'canceled']);
94 16
95 text: string; 17export type Conflict = z.infer<typeof conflict>;
96}
97 18
98export function isReplaceRegion(value: unknown): value is IReplaceRegion { 19export const serviceConflictResult = z.object({
99 const replaceRegion = value as IReplaceRegion; 20 conflict,
100 return typeof replaceRegion === 'object' 21});
101 && typeof replaceRegion.offset === 'number'
102 && typeof replaceRegion.length === 'number'
103 && typeof replaceRegion.text === 'string';
104}
105 22
106export interface ITextRegion { 23export type ServiceConflictResult = z.infer<typeof serviceConflictResult>;
107 offset: number;
108 24
109 length: number; 25export function isConflictResult(result: unknown, conflictType: Conflict): boolean {
26 const parsedConflictResult = serviceConflictResult.safeParse(result);
27 return parsedConflictResult.success && parsedConflictResult.data.conflict === conflictType;
110} 28}
111 29
112export function isTextRegion(value: unknown): value is ITextRegion { 30export const severity = z.enum(['error', 'warning', 'info', 'ignore']);
113 const textRegion = value as ITextRegion;
114 return typeof textRegion === 'object'
115 && typeof textRegion.offset === 'number'
116 && typeof textRegion.length === 'number';
117}
118 31
119export const VALID_XTEXT_CONTENT_ASSIST_ENTRY_KINDS = [ 32export type Severity = z.infer<typeof severity>;
120 'TEXT',
121 'METHOD',
122 'FUNCTION',
123 'CONSTRUCTOR',
124 'FIELD',
125 'VARIABLE',
126 'CLASS',
127 'INTERFACE',
128 'MODULE',
129 'PROPERTY',
130 'UNIT',
131 'VALUE',
132 'ENUM',
133 'KEYWORD',
134 'SNIPPET',
135 'COLOR',
136 'FILE',
137 'REFERENCE',
138 'UNKNOWN',
139] as const;
140
141export type XtextContentAssistEntryKind = typeof VALID_XTEXT_CONTENT_ASSIST_ENTRY_KINDS[number];
142
143export function isXtextContentAssistEntryKind(
144 value: unknown,
145): value is XtextContentAssistEntryKind {
146 return typeof value === 'string'
147 && VALID_XTEXT_CONTENT_ASSIST_ENTRY_KINDS.includes(value as XtextContentAssistEntryKind);
148}
149 33
150export interface IContentAssistEntry { 34export const issue = z.object({
151 prefix: string; 35 description: z.string().nonempty(),
36 severity,
37 line: z.number().int(),
38 column: z.number().int().nonnegative(),
39 offset: z.number().int().nonnegative(),
40 length: z.number().int().nonnegative(),
41});
152 42
153 proposal: string; 43export type Issue = z.infer<typeof issue>;
154 44
155 label?: string; 45export const validationResult = z.object({
46 issues: issue.array(),
47});
156 48
157 description?: string; 49export type ValidationResult = z.infer<typeof validationResult>;
158 50
159 documentation?: string; 51export const replaceRegion = z.object({
52 offset: z.number().int().nonnegative(),
53 length: z.number().int().nonnegative(),
54 text: z.string(),
55});
160 56
161 escapePosition?: number; 57export type ReplaceRegion = z.infer<typeof replaceRegion>;
162 58
163 textReplacements: IReplaceRegion[]; 59export const textRegion = z.object({
60 offset: z.number().int().nonnegative(),
61 length: z.number().int().nonnegative(),
62});
164 63
165 editPositions: ITextRegion[]; 64export type TextRegion = z.infer<typeof textRegion>;
166 65
167 kind: XtextContentAssistEntryKind | string; 66export const contentAssistEntry = z.object({
168} 67 prefix: z.string(),
68 proposal: z.string().nonempty(),
69 label: z.string().optional(),
70 description: z.string().nonempty().optional(),
71 documentation: z.string().nonempty().optional(),
72 escapePosition: z.number().int().nonnegative().optional(),
73 textReplacements: replaceRegion.array(),
74 editPositions: textRegion.array(),
75 kind: z.string().nonempty(),
76});
169 77
170function isStringOrUndefined(value: unknown): value is string | undefined { 78export type ContentAssistEntry = z.infer<typeof contentAssistEntry>;
171 return typeof value === 'string' || typeof value === 'undefined';
172}
173 79
174function isNumberOrUndefined(value: unknown): value is number | undefined { 80export const contentAssistResult = documentStateResult.extend({
175 return typeof value === 'number' || typeof value === 'undefined'; 81 entries: contentAssistEntry.array(),
176} 82});
177 83
178export function isContentAssistEntry(value: unknown): value is IContentAssistEntry { 84export type ContentAssistResult = z.infer<typeof contentAssistResult>;
179 const entry = value as IContentAssistEntry;
180 return typeof entry === 'object'
181 && typeof entry.prefix === 'string'
182 && typeof entry.proposal === 'string'
183 && isStringOrUndefined(entry.label)
184 && isStringOrUndefined(entry.description)
185 && isStringOrUndefined(entry.documentation)
186 && isNumberOrUndefined(entry.escapePosition)
187 && isArrayOfType(entry.textReplacements, isReplaceRegion)
188 && isArrayOfType(entry.editPositions, isTextRegion)
189 && typeof entry.kind === 'string';
190}
191 85
192export interface IContentAssistResult extends IDocumentStateResult { 86export const highlightingRegion = z.object({
193 entries: IContentAssistEntry[]; 87 offset: z.number().int().nonnegative(),
194} 88 length: z.number().int().nonnegative(),
195 89 styleClasses: z.string().nonempty().array(),
196export function isContentAssistResult(result: unknown): result is IContentAssistResult { 90});
197 const contentAssistResult = result as IContentAssistResult;
198 return isDocumentStateResult(result)
199 && isArrayOfType(contentAssistResult.entries, isContentAssistEntry);
200}
201 91
202export interface IHighlightingRegion { 92export type HighlightingRegion = z.infer<typeof highlightingRegion>;
203 offset: number;
204 93
205 length: number; 94export const highlightingResult = z.object({
95 regions: highlightingRegion.array(),
96});
206 97
207 styleClasses: string[]; 98export type HighlightingResult = z.infer<typeof highlightingResult>;
208}
209 99
210export function isHighlightingRegion(value: unknown): value is IHighlightingRegion { 100export const occurrencesResult = documentStateResult.extend({
211 const region = value as IHighlightingRegion; 101 writeRegions: textRegion.array(),
212 return typeof region === 'object' 102 readRegions: textRegion.array(),
213 && typeof region.offset === 'number' 103});
214 && typeof region.length === 'number'
215 && isArrayOfType(region.styleClasses, (s): s is string => typeof s === 'string');
216}
217
218export interface IHighlightingResult {
219 regions: IHighlightingRegion[];
220}
221 104
222export function isHighlightingResult(result: unknown): result is IHighlightingResult { 105export type OccurrencesResult = z.infer<typeof occurrencesResult>;
223 const highlightingResult = result as IHighlightingResult;
224 return typeof highlightingResult === 'object'
225 && isArrayOfType(highlightingResult.regions, isHighlightingRegion);
226}
227
228export interface IOccurrencesResult extends IDocumentStateResult {
229 writeRegions: ITextRegion[];
230
231 readRegions: ITextRegion[];
232}
233
234export function isOccurrencesResult(result: unknown): result is IOccurrencesResult {
235 const occurrencesResult = result as IOccurrencesResult;
236 return isDocumentStateResult(occurrencesResult)
237 && isArrayOfType(occurrencesResult.writeRegions, isTextRegion)
238 && isArrayOfType(occurrencesResult.readRegions, isTextRegion);
239}