@@ -514,6 +514,52 @@ func TestProjectCollectionBuilder(t *testing.T) {
514514 session .DidOpenFile (context .Background (), "file:///script.ts" , 1 , files ["/script.ts" ].(string ), lsproto .LanguageKindTypeScript )
515515 // Test should terminate
516516 })
517+
518+ t .Run ("file moves to inferred project after import is deleted" , func (t * testing.T ) {
519+ t .Parallel ()
520+ // This test verifies that when a node_modules dependency file is open and its import
521+ // is deleted from the project root, requesting language service for the dependency
522+ // correctly moves it to an inferred project.
523+ files := map [string ]any {
524+ "/project/tsconfig.json" : `{"compilerOptions": {"strict": true}}` ,
525+ "/project/index.ts" : `import { helper } from "./node_modules/dep/index";` ,
526+ "/project/node_modules/dep/index.d.ts" : `export declare function helper(): void;` ,
527+ }
528+ session , _ := projecttestutil .Setup (files )
529+
530+ // Step 1: Open the project root file
531+ rootUri := lsproto .DocumentUri ("file:///project/index.ts" )
532+ session .DidOpenFile (context .Background (), rootUri , 1 , files ["/project/index.ts" ].(string ), lsproto .LanguageKindTypeScript )
533+ _ , err := session .GetLanguageService (context .Background (), rootUri )
534+ assert .NilError (t , err )
535+
536+ // Step 2: Open the node_modules dependency file - should be in the configured project
537+ depUri := lsproto .DocumentUri ("file:///project/node_modules/dep/index.d.ts" )
538+ session .DidOpenFile (context .Background (), depUri , 1 , files ["/project/node_modules/dep/index.d.ts" ].(string ), lsproto .LanguageKindTypeScript )
539+
540+ snapshot , release := session .Snapshot ()
541+ configuredProject := snapshot .ProjectCollection .ConfiguredProject (tspath .Path ("/project/tsconfig.json" ))
542+ assert .Assert (t , configuredProject != nil , "configured project should exist" )
543+ defaultProject := snapshot .GetDefaultProject (depUri )
544+ assert .Equal (t , defaultProject , configuredProject , "dependency should be in the configured project initially" )
545+ release ()
546+
547+ // Step 3: Delete the import from the root file
548+ session .DidChangeFile (context .Background (), rootUri , 2 , []lsproto.TextDocumentContentChangePartialOrWholeDocument {{
549+ WholeDocument : & lsproto.TextDocumentContentChangeWholeDocument {Text : `// import removed` },
550+ }})
551+
552+ // Step 4: Request language service for the dependency - it should now be in an inferred project
553+ ls , err := session .GetLanguageService (context .Background (), depUri )
554+ assert .NilError (t , err )
555+ assert .Assert (t , ls != nil , "language service should be available for dependency" )
556+
557+ snapshot , release = session .Snapshot ()
558+ defer release ()
559+ defaultProject = snapshot .GetDefaultProject (depUri )
560+ assert .Assert (t , defaultProject != nil , "dependency should have a default project" )
561+ assert .Equal (t , defaultProject .Kind , project .KindInferred , "dependency should be in an inferred project after import is deleted" )
562+ })
517563}
518564
519565func filesForSolutionConfigFile (solutionRefs []string , compilerOptions string , ownFiles []string ) map [string ]any {
0 commit comments