@@ -27,6 +27,7 @@ describe('TopLevelSectionCompletionProvider', () => {
2727
2828 beforeEach ( ( ) => {
2929 mockComponents . syntaxTreeManager . getSyntaxTree . reset ( ) ;
30+ mockDocumentManager . getLine . reset ( ) ;
3031 mockSyntaxTree . topLevelSections . reset ( ) ;
3132 mockComponents . syntaxTreeManager . getSyntaxTree . returns ( mockSyntaxTree ) ;
3233
@@ -530,4 +531,114 @@ describe('TopLevelSectionCompletionProvider', () => {
530531 expect ( constantsItem ) . toBeUndefined ( ) ;
531532 } ) ;
532533 } ) ;
534+
535+ describe ( 'Cursor-local query resolution' , ( ) => {
536+ const wholeDocumentNodeText = Array . from ( { length : 1200 } , ( ) => ' SomeKey: SomeVeryLongValueToken' ) . join (
537+ '\n' ,
538+ ) ;
539+
540+ function paramsForLine ( line : string ) : CompletionParams {
541+ return {
542+ textDocument : { uri : 'file:///test.yaml' } ,
543+ position : { line : 0 , character : line . length } ,
544+ } ;
545+ }
546+
547+ test ( 'ranks with the cursor token when parser context contains a large multiline node' , ( ) => {
548+ const cursorLine = 'Res' ;
549+ mockSyntaxTree . topLevelSections . returns ( [ ] ) ;
550+ mockDocumentManager . getLine . returns ( cursorLine ) ;
551+
552+ const mockContext = createTopLevelContext ( 'Unknown' , { text : wholeDocumentNodeText } ) ;
553+
554+ const result = provider . getCompletions ( mockContext , paramsForLine ( cursorLine ) ) ;
555+
556+ const resources = result ?. find (
557+ ( item ) => item . label === 'Resources' && item . kind === CompletionItemKind . Class ,
558+ ) ;
559+ const resourcesSnippet = result ?. find (
560+ ( item ) => item . label === 'Resources' && item . kind === CompletionItemKind . File ,
561+ ) ;
562+ expect ( resources ?. preselect ) . toBe ( true ) ;
563+ expect ( resourcesSnippet ?. filterText ) . toBe ( cursorLine ) ;
564+ } ) ;
565+
566+ test ( 'ranks with the cursor token when parser context is empty' , ( ) => {
567+ const cursorLine = 'Par' ;
568+ mockSyntaxTree . topLevelSections . returns ( [ ] ) ;
569+ mockDocumentManager . getLine . returns ( cursorLine ) ;
570+
571+ const mockContext = createTopLevelContext ( 'Unknown' , { text : '' } ) ;
572+
573+ const result = provider . getCompletions ( mockContext , paramsForLine ( cursorLine ) ) ;
574+
575+ const parameters = result ?. find (
576+ ( item ) => item . label === 'Parameters' && item . kind === CompletionItemKind . Class ,
577+ ) ;
578+ expect ( parameters ?. preselect ) . toBe ( true ) ;
579+ } ) ;
580+
581+ test ( 'prefers the cursor token over stale short parser context' , ( ) => {
582+ const cursorLine = 'Res' ;
583+ mockSyntaxTree . topLevelSections . returns ( [ ] ) ;
584+ mockDocumentManager . getLine . returns ( cursorLine ) ;
585+
586+ const mockContext = createTopLevelContext ( 'Unknown' , { text : 'Par' } ) ;
587+
588+ const result = provider . getCompletions ( mockContext , paramsForLine ( cursorLine ) ) ;
589+
590+ const resources = result ?. find (
591+ ( item ) => item . label === 'Resources' && item . kind === CompletionItemKind . Class ,
592+ ) ;
593+ expect ( resources ?. preselect ) . toBe ( true ) ;
594+ } ) ;
595+
596+ test ( 'returns no completions when the cursor token is inside a YAML comment' , ( ) => {
597+ const cursorLine = ' # This mentions Conditions' ;
598+ mockSyntaxTree . topLevelSections . returns ( [ ] ) ;
599+ mockDocumentManager . getLine . returns ( cursorLine ) ;
600+
601+ const mockContext = createTopLevelContext ( 'Unknown' , { text : '' , type : DocumentType . YAML } ) ;
602+
603+ expect ( provider . getCompletions ( mockContext , paramsForLine ( cursorLine ) ) ) . toEqual ( [ ] ) ;
604+ } ) ;
605+
606+ test ( 'keeps JSON snippet filter text bounded after quote handling' , ( ) => {
607+ const cursorLine = ' "Res' ;
608+ mockSyntaxTree . topLevelSections . returns ( [ ] ) ;
609+ mockDocumentManager . getLine . returns ( cursorLine ) ;
610+
611+ const mockContext = createTopLevelContext ( 'Unknown' , {
612+ text : wholeDocumentNodeText ,
613+ type : DocumentType . JSON ,
614+ } ) ;
615+
616+ const result = provider . getCompletions ( mockContext , paramsForLine ( cursorLine ) ) ;
617+
618+ const resourcesSnippet = result ?. find (
619+ ( item ) => item . label === 'Resources' && item . kind === CompletionItemKind . File ,
620+ ) ;
621+ expect ( resourcesSnippet ?. filterText ) . toBe ( '"Res"' ) ;
622+ expect ( result ?. every ( ( item ) => ! item . filterText ?. includes ( wholeDocumentNodeText ) ) ) . toBe ( true ) ;
623+ } ) ;
624+
625+ test ( 'returns useful unranked completions when neither cursor nor context provides a valid query' , ( ) => {
626+ mockSyntaxTree . topLevelSections . returns ( [ ] ) ;
627+ mockDocumentManager . getLine . returns ( undefined ) ;
628+
629+ const mockContext = createTopLevelContext ( 'Unknown' , { text : wholeDocumentNodeText } ) ;
630+
631+ const result = provider . getCompletions ( mockContext , mockParams ) ;
632+
633+ const resources = result ?. find (
634+ ( item ) => item . label === 'Resources' && item . kind === CompletionItemKind . Class ,
635+ ) ;
636+ const resourcesSnippet = result ?. find (
637+ ( item ) => item . label === 'Resources' && item . kind === CompletionItemKind . File ,
638+ ) ;
639+ expect ( resources ) . toBeDefined ( ) ;
640+ expect ( resources ?. preselect ) . toBeUndefined ( ) ;
641+ expect ( resourcesSnippet ?. filterText ) . toBe ( '' ) ;
642+ } ) ;
643+ } ) ;
533644} ) ;
0 commit comments