@@ -35,6 +35,7 @@ import { isAlphaNumeric } from "../util";
3535import { CompletionSettings , SettingsManager } from '../settings' ;
3636
3737const threeLettersOrLessWordsRegex = / \b [ \w ] { 1 , 3 } \b / ;
38+
3839export 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-
282234function 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+
319316function 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-
372347function 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