@@ -160,12 +160,12 @@ type internal FSharpProjectOptionsManager
160160// compiled and #r will refer to files on disk
161161let referencedProjectFileNames = [| |]
162162let site = ProjectSitesAndFiles.CreateProjectSiteForScript( fileName, referencedProjectFileNames, options)
163- let deps , projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite( Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, ( tryGetOrCreateProjectId fileName), fileName, options.ExtraProjectInfo, Some projectOptionsTable, true )
163+ let deps , projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite( Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, ( tryGetOrCreateProjectId fileName), fileName, options.ExtraProjectInfo, Some projectOptionsTable)
164164let parsingOptions , _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions( projectOptions)
165165return ( deps, parsingOptions, projectOptions)
166166else
167167let site = ProjectSitesAndFiles.ProjectSiteOfSingleFile( fileName)
168- let deps , projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite( Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, ( tryGetOrCreateProjectId fileName), fileName, extraProjectInfo, Some projectOptionsTable, true )
168+ let deps , projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite( Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, ( tryGetOrCreateProjectId fileName), fileName, extraProjectInfo, Some projectOptionsTable)
169169let parsingOptions , _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions( projectOptions)
170170return ( deps, parsingOptions, projectOptions)
171171}
@@ -175,7 +175,7 @@ type internal FSharpProjectOptionsManager
175175 projectOptionsTable.AddOrUpdateProject( projectId, ( fun isRefresh ->
176176let extraProjectInfo = Some( box workspace)
177177let tryGetOptionsForReferencedProject f = f|> tryGetOrCreateProjectId|> Option.bind this.TryGetOptionsForProject|> Option.map( fun ( _ , _ , projectOptions ) -> projectOptions)
178- let referencedProjects , projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite( Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, ( tryGetOrCreateProjectId( site.ProjectFileName)), site.ProjectFileName, extraProjectInfo, Some projectOptionsTable, true )
178+ let referencedProjects , projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite( Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, ( tryGetOrCreateProjectId( site.ProjectFileName)), site.ProjectFileName, extraProjectInfo, Some projectOptionsTable)
179179if invalidateConfigthen checkerProvider.Checker.InvalidateConfiguration( projectOptions, startBackgroundCompileIfAlreadySeen= not isRefresh, userOpName= userOpName+ " .UpdateProjectInfo" )
180180let referencedProjectIds = referencedProjects|> Array.choose tryGetOrCreateProjectId
181181let parsingOptions , _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions( projectOptions)
@@ -206,18 +206,18 @@ type internal FSharpProjectOptionsManager
206206match singleFileProjectTable.TryGetValue( projectId) with
207207| true , ( loadTime, _, _) ->
208208try
209- let fileName = document.FilePath
210- let! cancellationToken = Async.CancellationToken
211- let! sourceText = document.GetTextAsync( cancellationToken) |> Async.AwaitTask
212- // NOTE: we don't use FCS cross-project references from scripts to projects. The projects must have been
213- // compiled and #r will refer to files on disk.
214- let tryGetOrCreateProjectId _ = None
215- let! _referencedProjectFileNames , parsingOptions , projectOptions = this.ComputeSingleFileOptions( tryGetOrCreateProjectId, fileName, loadTime, sourceText.ToString())
216- this.AddOrUpdateSingleFileProject( projectId, ( loadTime, parsingOptions, projectOptions))
217- return Some( parsingOptions, None, projectOptions)
209+ let fileName = document.FilePath
210+ let! cancellationToken = Async.CancellationToken
211+ let! sourceText = document.GetTextAsync( cancellationToken) |> Async.AwaitTask
212+ // NOTE: we don't use FCS cross-project references from scripts to projects. The projects must have been
213+ // compiled and #r will refer to files on disk.
214+ let tryGetOrCreateProjectId _ = None
215+ let! _referencedProjectFileNames , parsingOptions , projectOptions = this.ComputeSingleFileOptions( tryGetOrCreateProjectId, fileName, loadTime, sourceText.ToString())
216+ this.AddOrUpdateSingleFileProject( projectId, ( loadTime, parsingOptions, projectOptions))
217+ return Some( parsingOptions, None, projectOptions)
218218with ex->
219- Assert.Exception( ex)
220- return None
219+ Assert.Exception( ex)
220+ return None
221221| _ -> return this.TryGetOptionsForProject( projectId)
222222}
223223
@@ -658,26 +658,51 @@ type internal FSharpLanguageService(package : FSharpPackage) =
658658| ( VSConstants.S_ OK, textLines) ->
659659let filename = VsTextLines.GetFilename textLines
660660
661- // CPS projects don't implement IProvideProjectSite and IVSProjectHierarchy
662- // Simple explanation:
663- // Legacy projects have IVSHierarchy and IPRojectSite
664- // CPS Projects and loose script files don't
665661match VsRunningDocumentTable.FindDocumentWithoutLocking( package.RunningDocumentTable, filename) with
666662| Some( hier, _) ->
663+
664+
665+ // Check if the file is in a CPS project or not.
666+ // CPS projects don't implement IProvideProjectSite and IVSProjectHierarchy
667+ // Simple explanation:
668+ // Legacy projects have IVSHierarchy and IProjectSite
669+ // CPS Projects, out-of-project file and script files don't
670+
667671match hierwith
668672| :? IProvideProjectSiteas siteProviderwhen not ( IsScript( filename)) ->
673+
674+ // This is the path for .fs/.fsi files in legacy projects
675+
669676 this.SetupProjectFile( siteProvider, this.Workspace, " SetupNewTextView" )
677+
670678| hwhen not ( IsScript( filename)) ->
679+
671680let docId = this.Workspace.CurrentSolution.GetDocumentIdsWithFilePath( filename) .FirstOrDefault()
672681match docIdwith
673682| null ->
674683if not ( h.IsCapabilityMatch( " CPS" )) then
684+
685+ // This is the path when opening out-of-project .fs/.fsi files in CPS projects
686+
675687let fileContents = VsTextLines.GetFileContents( textLines, textViewAdapter)
676688 this.SetupStandAloneFile( filename, fileContents, this.Workspace, hier)
677689| id->
690+
691+ // This is the path when opening in-project .fs/.fsi files in CPS projects when
692+ // there is already an existing DocumentId for that document in the solution (which
693+ // will normally be the case)
694+ //
695+ // However, it is not clear this call to UpdateProjectInfoWithProjectId is needed, and it seems
696+ // harmful as it will cause a complete recheck of the project every time a view for a file in the
697+ // project is freshly opened.
698+
678699 projectInfoManager.UpdateProjectInfoWithProjectId( id.ProjectId, " SetupNewTextView" , invalidateConfig= true )
679700| _ ->
701+
702+ // This is the path for both in-project and out-of-project .fsx files
703+
680704let fileContents = VsTextLines.GetFileContents( textLines, textViewAdapter)
681705 this.SetupStandAloneFile( filename, fileContents, this.Workspace, hier)
706+
682707| _ -> ()
683708| _ -> ()