Skip to content

Commit de64fb5

Browse files
committed
Refactor completions for objects
1 parent f264fd2 commit de64fb5

1 file changed

Lines changed: 88 additions & 82 deletions

File tree

server/src/language-service/completionProvider.ts

Lines changed: 88 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { isAlphaNumeric } from "../util";
3535
import { CompletionSettings, SettingsManager } from '../settings';
3636

3737
const threeLettersOrLessWordsRegex = /\b[\w]{1,3}\b/;
38+
3839
export class CompletionProvider {
3940
private readonly cnfgProvider: ISepticConfigProvider;
4041
private readonly settingsManager: SettingsManager;
@@ -207,78 +208,29 @@ export function getObjectCompletion(
207208
): CompletionItem[] {
208209
cnfg.updateObjectParents(SepticMetaInfoProvider.getInstance().getObjectHierarchy());
209210
refProvider.updateObjectParents(SepticMetaInfoProvider.getInstance().getObjectHierarchy());
210-
const snippets: CompletionItem[] = getRelevantSnippets(offset, refProvider, doc, settings.onlySuggestValidSnippets);
211-
const references: CompletionItem[] = [];
211+
const objectSnippets: CompletionItem[] = getRelevantObjectSnippets(offset, refProvider, doc, settings.onlySuggestValidSnippets);
212212
const obj = cnfg.getObjectFromOffset(offset);
213213
if (!obj) {
214-
return snippets;
214+
return objectSnippets;
215215
}
216-
const ref = cnfg.getXvrRefFromOffset(offset);
216+
const range = findCompletionRange(offset, cnfg, doc)
217217
if (isIdentifierCompletion(offset, obj)) {
218-
const range: Range = ref
219-
? {
220-
start: doc.positionAt(ref.location.start),
221-
end: doc.positionAt(ref.location.end),
222-
}
223-
: {
224-
start: doc.positionAt(offset),
225-
end: doc.positionAt(offset),
226-
};
227-
return getRelevantXvrsIdentifier(
228-
obj,
229-
refProvider.getAllXvrObjects()
230-
).map((obj) => xvrToCompletionItem(obj, range));
218+
return getIdentifierCompletion(obj, refProvider, range);
231219
}
232-
const currentAttr = getCurrentAttr(offset, obj);
220+
const currentAttr = findCurrentAttr(offset, obj);
233221
if (!currentAttr.attr) {
234-
return [...snippets, ...getObjectAttributeCompletion(obj, offset, doc)];
235-
}
236-
if (isReferenceAttribute(obj, currentAttr.attr)) {
237-
const range: Range = ref
238-
? {
239-
start: doc.positionAt(ref.location.start),
240-
end: doc.positionAt(ref.location.end),
241-
}
242-
: {
243-
start: doc.positionAt(offset),
244-
end: doc.positionAt(offset),
245-
};
246-
247-
references.push(
248-
...getRelevantXvrsAttributes(
249-
currentAttr.attr,
250-
refProvider.getAllXvrObjects()
251-
).map((obj) => xvrToCompletionItem(obj, range))
252-
);
222+
return [...objectSnippets, ...getObjectAttributeCompletion(obj, offset, doc)];
253223
}
254-
const enums = getEnumCompletions(obj, currentAttr.attr);
255-
const completions = [...enums, ...references];
224+
const completions = getAttributeValueCompletion(obj, currentAttr.attr, refProvider, range);
256225
if (isEndAttribute(offset, currentAttr.attr)) {
257226
completions.push(...getObjectAttributeCompletion(obj, offset, doc));
258227
if (currentAttr.last) {
259-
completions.push(...snippets);
228+
completions.push(...objectSnippets);
260229
}
261230
}
262231
return completions;
263232
}
264233

265-
function getCurrentAttr(
266-
offset: number,
267-
obj: SepticObject
268-
): { attr: Attribute | undefined; last: boolean } {
269-
if (!obj.attributes.length) {
270-
return { attr: undefined, last: false };
271-
}
272-
let index = 1;
273-
while (index < obj.attributes.length) {
274-
if (obj.attributes[index].start >= offset) {
275-
return { attr: obj.attributes[index - 1], last: false };
276-
}
277-
index += 1;
278-
}
279-
return { attr: obj.attributes[obj.attributes.length - 1], last: true };
280-
}
281-
282234
function getObjectAttributeCompletion(
283235
obj: SepticObject,
284236
offset: number,
@@ -291,7 +243,7 @@ function getObjectAttributeCompletion(
291243
return [];
292244
}
293245
const compItems: CompletionItem[] = [];
294-
const rangeNewLine = getRangeAttrTextEdit(offset, doc);
246+
const rangeNewLine = findRangeAttrTextEdit(offset, doc);
295247
for (const attr of objDoc.attributes) {
296248
if (obj.getAttribute(attr.name)) {
297249
continue;
@@ -316,6 +268,51 @@ function getObjectAttributeCompletion(
316268
return compItems;
317269
}
318270

271+
function getIdentifierCompletion(obj: SepticObject, refProvider: SepticReferenceProvider, range: Range): CompletionItem[] {
272+
return getRelevantXvrsIdentifier(
273+
obj,
274+
refProvider.getAllXvrObjects()
275+
).map((obj) => xvrToCompletionItem(obj, range))
276+
}
277+
278+
function getAttributeValueCompletion(obj: SepticObject, attr: Attribute, refProvider: SepticReferenceProvider, range: Range): CompletionItem[] {
279+
const references = getReferenceCompletions(obj, attr, refProvider, range);
280+
const enums = getEnumCompletions(obj, attr);
281+
return [...references, ...enums];
282+
}
283+
284+
function getReferenceCompletions(obj: SepticObject, attr: Attribute, refProvider: SepticReferenceProvider, range: Range): CompletionItem[] {
285+
if (!isReferenceAttribute(obj, attr)) {
286+
return [];
287+
}
288+
return getRelevantXvrsAttributes(
289+
attr,
290+
refProvider.getAllXvrObjects()
291+
).map((obj) => xvrToCompletionItem(obj, range))
292+
}
293+
294+
function getEnumCompletions(obj: SepticObject, attr: Attribute): CompletionItem[] {
295+
const objectInfo = SepticMetaInfoProvider.getInstance().getObjectDocumentation(obj.type);
296+
if (!objectInfo) {
297+
return [];
298+
}
299+
let attrDoc = objectInfo.attributes.find((a) => a.name === attr.key);
300+
if (!attrDoc) {
301+
return [];
302+
}
303+
if (attrDoc.dataType !== "enum") {
304+
return [];
305+
}
306+
return attrDoc.enums.map((value) => {
307+
return {
308+
label: value,
309+
kind: CompletionItemKind.EnumMember,
310+
detail: `Enum member of ${attrDoc.name}`,
311+
sortText: `1${value}`,
312+
};
313+
});
314+
}
315+
319316
function isIdentifierCompletion(offset: number, obj: SepticObject) {
320317
const objectInfo = SepticMetaInfoProvider.getInstance().getObject(obj.type);
321318
if (!objectInfo?.refs.identifier) {
@@ -347,28 +344,6 @@ function isReferenceAttribute(obj: SepticObject, attr: Attribute): boolean {
347344
return objectInfo.refs.attributes.includes(attr.key);
348345
}
349346

350-
function getEnumCompletions(obj: SepticObject, attr: Attribute): CompletionItem[] {
351-
const objectInfo = SepticMetaInfoProvider.getInstance().getObjectDocumentation(obj.type);
352-
if (!objectInfo) {
353-
return [];
354-
}
355-
let attrDoc = objectInfo.attributes.find((a) => a.name === attr.key);
356-
if (!attrDoc) {
357-
return [];
358-
}
359-
if (attrDoc.dataType !== "enum") {
360-
return [];
361-
}
362-
return attrDoc.enums.map((value) => {
363-
return {
364-
label: value,
365-
kind: CompletionItemKind.EnumMember,
366-
detail: `Enum member of ${attrDoc.name}`,
367-
sortText: `1${value}`,
368-
};
369-
});
370-
}
371-
372347
function isEndAttribute(offset: number, attr: Attribute): boolean {
373348
return offset >= attr.end;
374349
}
@@ -386,7 +361,7 @@ function getTextAttrTextEdit(attr: SepticAttributeDocumentation) {
386361
return attrFormatted;
387362
}
388363

389-
function getRangeAttrTextEdit(
364+
function findRangeAttrTextEdit(
390365
offset: number,
391366
doc: ITextDocument
392367
): { range: Range; addNewLine: boolean } {
@@ -497,7 +472,7 @@ function getRelevantXvrsAttributes(
497472
}
498473
}
499474

500-
function getRelevantSnippets(offset: number, refProvider: SepticReferenceProvider, doc: ITextDocument, onlySuggestValidSnippets: boolean): CompletionItem[] {
475+
function getRelevantObjectSnippets(offset: number, refProvider: SepticReferenceProvider, doc: ITextDocument, onlySuggestValidSnippets: boolean): CompletionItem[] {
501476
const snippets = SepticMetaInfoProvider.getInstance().getSnippets().slice();
502477
if (!onlySuggestValidSnippets) {
503478
return snippets;
@@ -535,4 +510,35 @@ function getObjectsSnippets(objectHierarchy: SepticObjectHierarchy, obj: SepticO
535510
}
536511

537512
return relevantObjects.map((val) => val.toLowerCase());
513+
}
514+
515+
function findCompletionRange(offset: number, cnfg: SepticCnfg, doc: ITextDocument) {
516+
const ref = cnfg.getXvrRefFromOffset(offset);
517+
const range: Range = ref
518+
? {
519+
start: doc.positionAt(ref.location.start),
520+
end: doc.positionAt(ref.location.end),
521+
}
522+
: {
523+
start: doc.positionAt(offset),
524+
end: doc.positionAt(offset),
525+
};
526+
return range;
527+
}
528+
529+
function findCurrentAttr(
530+
offset: number,
531+
obj: SepticObject
532+
): { attr: Attribute | undefined; last: boolean } {
533+
if (!obj.attributes.length) {
534+
return { attr: undefined, last: false };
535+
}
536+
let index = 1;
537+
while (index < obj.attributes.length) {
538+
if (obj.attributes[index].start >= offset) {
539+
return { attr: obj.attributes[index - 1], last: false };
540+
}
541+
index += 1;
542+
}
543+
return { attr: obj.attributes[obj.attributes.length - 1], last: true };
538544
}

0 commit comments

Comments
 (0)