diff options
Diffstat (limited to 'language-web/src/main/js/editor/xtextServiceResults.ts')
-rw-r--r-- | language-web/src/main/js/editor/xtextServiceResults.ts | 138 |
1 files changed, 132 insertions, 6 deletions
diff --git a/language-web/src/main/js/editor/xtextServiceResults.ts b/language-web/src/main/js/editor/xtextServiceResults.ts index 8a4afa40..6c3d9daf 100644 --- a/language-web/src/main/js/editor/xtextServiceResults.ts +++ b/language-web/src/main/js/editor/xtextServiceResults.ts | |||
@@ -22,20 +22,32 @@ export const VALID_CONFLICTS = ['invalidStateId', 'canceled'] as const; | |||
22 | 22 | ||
23 | export type Conflict = typeof VALID_CONFLICTS[number]; | 23 | export type Conflict = typeof VALID_CONFLICTS[number]; |
24 | 24 | ||
25 | export function isConflict(value: unknown): value is Conflict { | ||
26 | return typeof value === 'string' && VALID_CONFLICTS.includes(value as Conflict); | ||
27 | } | ||
28 | |||
25 | export interface IServiceConflictResult { | 29 | export interface IServiceConflictResult { |
26 | conflict: Conflict; | 30 | conflict: Conflict; |
27 | } | 31 | } |
28 | 32 | ||
29 | export function isServiceConflictResult(result: unknown): result is IServiceConflictResult { | 33 | export function isServiceConflictResult(result: unknown): result is IServiceConflictResult { |
30 | const serviceConflictResult = result as IServiceConflictResult; | 34 | const serviceConflictResult = result as IServiceConflictResult; |
31 | return typeof serviceConflictResult.conflict === 'string' | 35 | return typeof serviceConflictResult === 'object' |
32 | && VALID_CONFLICTS.includes(serviceConflictResult.conflict); | 36 | && isConflict(serviceConflictResult.conflict); |
37 | } | ||
38 | |||
39 | export function isInvalidStateIdConflictResult(result: unknown): boolean { | ||
40 | return isServiceConflictResult(result) && result.conflict === 'invalidStateId'; | ||
33 | } | 41 | } |
34 | 42 | ||
35 | export const VALID_SEVERITIES = ['error', 'warning', 'info', 'ignore'] as const; | 43 | export const VALID_SEVERITIES = ['error', 'warning', 'info', 'ignore'] as const; |
36 | 44 | ||
37 | export type Severity = typeof VALID_SEVERITIES[number]; | 45 | export type Severity = typeof VALID_SEVERITIES[number]; |
38 | 46 | ||
47 | export function isSeverity(value: unknown): value is Severity { | ||
48 | return typeof value === 'string' && VALID_SEVERITIES.includes(value as Severity); | ||
49 | } | ||
50 | |||
39 | export interface IIssue { | 51 | export interface IIssue { |
40 | description: string; | 52 | description: string; |
41 | 53 | ||
@@ -54,8 +66,7 @@ export function isIssue(value: unknown): value is IIssue { | |||
54 | const issue = value as IIssue; | 66 | const issue = value as IIssue; |
55 | return typeof issue === 'object' | 67 | return typeof issue === 'object' |
56 | && typeof issue.description === 'string' | 68 | && typeof issue.description === 'string' |
57 | && typeof issue.severity === 'string' | 69 | && isSeverity(issue.severity) |
58 | && VALID_SEVERITIES.includes(issue.severity) | ||
59 | && typeof issue.line === 'number' | 70 | && typeof issue.line === 'number' |
60 | && typeof issue.column === 'number' | 71 | && typeof issue.column === 'number' |
61 | && typeof issue.offset === 'number' | 72 | && typeof issue.offset === 'number' |
@@ -66,9 +77,124 @@ export interface IValidationResult { | |||
66 | issues: IIssue[]; | 77 | issues: IIssue[]; |
67 | } | 78 | } |
68 | 79 | ||
80 | function isArrayOfType<T>(value: unknown, check: (entry: unknown) => entry is T): value is T[] { | ||
81 | return Array.isArray(value) && (value as T[]).every(check); | ||
82 | } | ||
83 | |||
69 | export function isValidationResult(result: unknown): result is IValidationResult { | 84 | export function isValidationResult(result: unknown): result is IValidationResult { |
70 | const validationResult = result as IValidationResult; | 85 | const validationResult = result as IValidationResult; |
71 | return typeof validationResult === 'object' | 86 | return typeof validationResult === 'object' |
72 | && Array.isArray(validationResult.issues) | 87 | && isArrayOfType(validationResult.issues, isIssue); |
73 | && validationResult.issues.every(isIssue); | 88 | } |
89 | |||
90 | export interface IReplaceRegion { | ||
91 | offset: number; | ||
92 | |||
93 | length: number; | ||
94 | |||
95 | text: string; | ||
96 | } | ||
97 | |||
98 | export function isReplaceRegion(value: unknown): value is IReplaceRegion { | ||
99 | const replaceRegion = value as IReplaceRegion; | ||
100 | return typeof replaceRegion === 'object' | ||
101 | && typeof replaceRegion.offset === 'number' | ||
102 | && typeof replaceRegion.length === 'number' | ||
103 | && typeof replaceRegion.text === 'string'; | ||
104 | } | ||
105 | |||
106 | export interface ITextRegion { | ||
107 | offset: number; | ||
108 | |||
109 | length: number; | ||
110 | } | ||
111 | |||
112 | export function isTextRegion(value: unknown): value is ITextRegion { | ||
113 | const textRegion = value as ITextRegion; | ||
114 | return typeof textRegion === 'object' | ||
115 | && typeof textRegion.offset === 'number' | ||
116 | && typeof textRegion.length === 'number'; | ||
117 | } | ||
118 | |||
119 | export const VALID_XTEXT_CONTENT_ASSIST_ENTRY_KINDS = [ | ||
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 | |||
141 | export type XtextContentAssistEntryKind = typeof VALID_XTEXT_CONTENT_ASSIST_ENTRY_KINDS[number]; | ||
142 | |||
143 | export 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 | |||
150 | export interface IContentAssistEntry { | ||
151 | prefix: string; | ||
152 | |||
153 | proposal: string; | ||
154 | |||
155 | label?: string; | ||
156 | |||
157 | description?: string; | ||
158 | |||
159 | documentation?: string; | ||
160 | |||
161 | escapePosition?: number; | ||
162 | |||
163 | textReplacements: IReplaceRegion[]; | ||
164 | |||
165 | editPositions: ITextRegion[]; | ||
166 | |||
167 | kind: XtextContentAssistEntryKind | string; | ||
168 | } | ||
169 | |||
170 | function isStringOrUndefined(value: unknown): value is string | undefined { | ||
171 | return typeof value === 'string' || typeof value === 'undefined'; | ||
172 | } | ||
173 | |||
174 | function isNumberOrUndefined(value: unknown): value is number | undefined { | ||
175 | return typeof value === 'number' || typeof value === 'undefined'; | ||
176 | } | ||
177 | |||
178 | export function isContentAssistEntry(value: unknown): value is IContentAssistEntry { | ||
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 | |||
192 | export interface IContentAssistResult extends IDocumentStateResult { | ||
193 | entries: IContentAssistEntry[]; | ||
194 | } | ||
195 | |||
196 | export function isContentAssistResult(result: unknown): result is IContentAssistResult { | ||
197 | const contentAssistResult = result as IContentAssistResult; | ||
198 | return isDocumentStateResult(result) | ||
199 | && isArrayOfType(contentAssistResult.entries, isContentAssistEntry); | ||
74 | } | 200 | } |