@@ -668,6 +668,70 @@ describe('DefaultDocumentBuilder', () => {
668
668
}
669
669
} ) ;
670
670
671
+ test ( "References are unlinked on custom reset of document state even if the document didn't reach linked phase yet" , async ( ) => {
672
+ const services = await createServices ( ) ;
673
+ const workspace = services . shared . workspace ;
674
+ const documentFactory = workspace . LangiumDocumentFactory ;
675
+ const documents = workspace . LangiumDocuments ;
676
+ const document = documentFactory . fromString < Model > ( `
677
+ foo 1 A
678
+ foo 11 B
679
+ bar A
680
+ bar B
681
+ ` , URI . parse ( 'file:///test1.txt' ) ) ;
682
+ documents . addDocument ( document ) ;
683
+
684
+ const tokenSource = startCancelableOperation ( ) ;
685
+ const builder = workspace . DocumentBuilder ;
686
+ builder . onBuildPhase ( DocumentState . ComputedScopes , ( ) => {
687
+ tokenSource . cancel ( ) ;
688
+ } ) ;
689
+ try {
690
+ await builder . build ( [ document ] , undefined , tokenSource . token ) ;
691
+ fail ( 'The update is supposed to be cancelled' ) ;
692
+ } catch ( err ) {
693
+ expect ( isOperationCancelled ( err ) ) . toBe ( true ) ;
694
+ }
695
+ expect ( document . state ) . toBe ( DocumentState . ComputedScopes ) ;
696
+ expect ( document . localSymbols ) . toBeDefined ( ) ;
697
+ expect ( document . references ) . toHaveLength ( 0 ) ;
698
+
699
+ // Resolve the reference "on-the-fly"
700
+ // We would expect that doing so will add the reference to the document references
701
+ let first = document . parseResult . value . foos [ 0 ] . bar . ref ;
702
+ expect ( first ) . toBeDefined ( ) ;
703
+ expect ( first ! . $type ) . toBe ( 'Bar' ) ;
704
+ expect ( document . references ) . toHaveLength ( 1 ) ;
705
+
706
+ // Primary testing goal: Reset the document state and clean references in order to get rid of any stale ones;
707
+ // here resetting to IndexedContent in order to also clear any pre-computed scopes/local symbol tables
708
+ builder . resetToState ( document , DocumentState . IndexedContent ) ;
709
+
710
+ expect ( document . state ) . toBe ( DocumentState . IndexedContent ) ;
711
+ expect ( document . localSymbols ) . toBeUndefined ( ) ;
712
+ expect ( document . references ) . toHaveLength ( 0 ) ;
713
+
714
+ // Again, resolve the reference "on-the-fly", this is supposed to work as 'A' is accessible via the index
715
+ first = document . parseResult . value . foos [ 0 ] . bar . ref ;
716
+ expect ( first ) . toBeDefined ( ) ;
717
+ expect ( first ! . $type ) . toBe ( 'Bar' ) ;
718
+ expect ( document . references ) . toHaveLength ( 1 ) ;
719
+
720
+ // In addition: Alternatively, attempt to reset the document state to ComputedScopes
721
+ builder . resetToState ( document , DocumentState . ComputedScopes ) ;
722
+
723
+ expect ( document . state ) . toBe ( DocumentState . IndexedContent ) ;
724
+ expect ( document . references ) . toHaveLength ( 0 ) ;
725
+
726
+ const astNodeReferences = AstUtils . streamAst ( document . parseResult . value ) . flatMap ( AstUtils . streamReferences ) . toArray ( ) ;
727
+ expect ( astNodeReferences ) . toHaveLength ( 2 ) ;
728
+ for ( const ref of astNodeReferences ) {
729
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
730
+ const defaultRef = ref . reference as any ;
731
+ expect ( defaultRef . _ref ) . toBeUndefined ( ) ;
732
+ }
733
+ } ) ;
734
+
671
735
describe ( 'DefaultDocumentBuilder document sorting' , ( ) => {
672
736
let services : LangiumServices ;
673
737
let documentFactory : LangiumDocumentFactory ;
0 commit comments