@@ -164,7 +164,7 @@ type internal FSharpProjectOptionsManager
164164 this.AddOrUpdateProject( projectId, ( fun isRefresh ->
165165let extraProjectInfo = Some( box workspace)
166166let tryGetOptionsForReferencedProject f = f|> tryGetOrCreateProjectId|> Option.bind this.TryGetOptionsForProject
167- let referencedProjects , options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite( Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, site.ProjectFileName() , extraProjectInfo, serviceProvider, true )
167+ let referencedProjects , options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite( Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, site.ProjectFileName, extraProjectInfo, serviceProvider, true )
168168let referencedProjectIds = referencedProjects|> Array.choose tryGetOrCreateProjectId
169169 checkerProvider.Checker.InvalidateConfiguration( options, startBackgroundCompileIfAlreadySeen= not isRefresh, userOpName= userOpName+ " .UpdateProjectInfo" )
170170 referencedProjectIds, options))
@@ -231,21 +231,22 @@ type internal FSharpProjectOptionsManager
231231 Some( reporter:> Microsoft .VisualStudio .Shell .Interop .IVsLanguageServiceBuildErrorReporter2 )
232232
233233{ new Microsoft.VisualStudio.FSharp.LanguageService.IProjectSitewith
234- member __.SourceFilesOnDisk () = this.GetProjectInfo( project.FilePath) |> fst
235- member __.DescriptionOfProject () = project.Name
236- member __.CompilerFlags () =
234+ member __.CompilationSourceFiles = this.GetProjectInfo( project.FilePath) |> fst
235+ member __.CompilationOptions =
237236let _ , references , options = this.GetProjectInfo( project.FilePath)
238237 Array.concat[ options; references|> Array.map( fun r -> " -r:" + r)]
239- member __.ProjectFileName () = project.FilePath
238+ member __.CompilationReferences = this.GetProjectInfo( project.FilePath) |> thrd
239+ member site.CompilationBinOutputPath = site.CompilationOptions|> Array.tryPick( fun s -> if s.StartsWith( " -o:" ) then Some s.[ 3 ..] else None)
240+ member __.Description = project.Name
241+ member __.ProjectFileName = project.FilePath
240242member __.AdviseProjectSiteChanges ( _ , _ ) = ()
241243member __.AdviseProjectSiteCleaned ( _ , _ ) = ()
242244member __.AdviseProjectSiteClosed ( _ , _ ) = ()
243245member __.IsIncompleteTypeCheckEnvironment = false
244246member __.TargetFrameworkMoniker = " "
245- member __.ProjectGuid = project.Id.Id.ToString()
247+ member __.ProjectGuid = project.Id.Id.ToString()
246248member __.LoadTime = System.DateTime.Now
247249member __.ProjectProvider = Some iProvideProjectSite
248- member __.AssemblyReferences () = this.GetProjectInfo( project.FilePath) |> thrd
249250member __.BuildErrorReporter with get() = errorReporterand
250251set ( v ) = errorReporter<- v
251252}
@@ -459,17 +460,20 @@ type
459460
460461let theme = package.ComponentModel.DefaultExportProvider.GetExport< ISetThemeColors>() .Value
461462 theme.SetColors()
462-
463- /// Sync the information for the project
464- member __.SyncProject ( project : AbstractProject , projectContext : IWorkspaceProjectContext , site : IProjectSite , workspace , forceUpdate , userOpName ) =
463+
464+ /// Sync the Roslyn information for the project held in 'projectContext' to match the information given by 'site'.
465+ /// Also sync the info in ProjectInfoManager if necessary.
466+ member this.SyncProject ( project : AbstractProject , projectContext : IWorkspaceProjectContext , site : IProjectSite , workspace , forceUpdate , userOpName ) =
465467let wellFormedFilePathSetIgnoreCase ( paths : seq < string >) =
466- HashSet( paths|> Seq.filter isPathWellFormed|> Seq.map( fun s -> try System.IO.Path.GetFullPath( s) with _ -> s), StringComparer.OrdinalIgnoreCase)
467-
468- let updatedFiles = site.SourceFilesOnDisk() |> wellFormedFilePathSetIgnoreCase
469- let originalFiles = project.GetCurrentDocuments() |> Seq.map( fun file -> file.FilePath) |> wellFormedFilePathSetIgnoreCase
468+ HashSet( paths|> Seq.filter isPathWellFormed|> Seq.map( fun s -> try Path.GetFullPath( s) with _ -> s), StringComparer.OrdinalIgnoreCase)
470469
471470let mutable updated = forceUpdate
472471
472+ // Sync the source files in projectContext. Note that these source files are __not__ maintained in order in projectContext
473+ // as edits are made. It seems this is ok because the source file list is only used to drive roslyn per-file checking.
474+ let updatedFiles = site.CompilationSourceFiles|> wellFormedFilePathSetIgnoreCase
475+ let originalFiles = project.GetCurrentDocuments() |> Seq.map( fun file -> file.FilePath) |> wellFormedFilePathSetIgnoreCase
476+
473477for filein updatedFilesdo
474478if not ( originalFiles.Contains( file)) then
475479 projectContext.AddSourceFile( file)
480484 projectContext.RemoveSourceFile( file)
481485 updated<- true
482486
483- let updatedRefs = site.AssemblyReferences () |> wellFormedFilePathSetIgnoreCase
487+ let updatedRefs = site.CompilationReferences |> wellFormedFilePathSetIgnoreCase
484488let originalRefs = project.GetCurrentMetadataReferences() |> Seq.map( fun ref -> ref.FilePath) |> wellFormedFilePathSetIgnoreCase
485489
486490for refin updatedRefsdo
493497 projectContext.RemoveMetadataReference( ref)
494498 updated<- true
495499
500+ // Update the project options association
496501let ok , originalOptions = optionsAssociation.TryGetValue( projectContext)
497- let updatedOptions = site.CompilerFlags ()
502+ let updatedOptions = site.CompilationOptions
498503if not ok|| originalOptions<> updatedOptionsthen
499504
500505// OK, project options have changed, try to fake out Roslyn to convince it to reparse things.
@@ -520,13 +525,12 @@ type
520525let userOpName = userOpName+ " .SetupProjectFile"
521526let rec setup ( site : IProjectSite ) =
522527let projectGuid = Guid( site.ProjectGuid)
523- let projectFileName = site.ProjectFileName()
528+ let projectFileName = site.ProjectFileName
524529let projectDisplayName = projectDisplayNameOf projectFileName
525530
526531let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath( projectFileName, projectDisplayName)
527532
528533if isNull( workspace.ProjectTracker.GetProject projectId) then
529- projectInfoManager.UpdateProjectInfo( tryGetOrCreateProjectId workspace, projectId, site, userOpName)
530534let projectContextFactory = package.ComponentModel.GetService< IWorkspaceProjectContextFactory>();
531535let errorReporter = ProjectExternalErrorReporter( projectId, " FS" , this.SystemServiceProvider)
532536
@@ -542,27 +546,35 @@ type
542546
543547let projectContext =
544548 projectContextFactory.CreateProjectContext(
545- FSharpConstants.FSharpLanguageName, projectDisplayName, projectFileName, projectGuid, hierarchy, null , errorReporter)
549+ FSharpConstants.FSharpLanguageName,
550+ projectDisplayName,
551+ projectFileName,
552+ projectGuid,
553+ hierarchy,
554+ Option.toObj site.CompilationBinOutputPath,
555+ errorReporter)
546556
547557let project = projectContext:?> AbstractProject
548558
549- this.SyncProject( project, projectContext, site, workspace, forceUpdate= false , userOpName= userOpName)
559+ // Sync IProjectSite --> projectContext, and IProjectSite --> ProjectInfoManage
560+ this.SyncProject( project, projectContext, site, workspace, forceUpdate= true , userOpName= userOpName)
550561
551562 site.BuildErrorReporter<- Some( errorReporter:> Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2)
552563
564+ // TODO: consider forceUpdate = false here. forceUpdate=true may be causing repeated computation?
553565 site.AdviseProjectSiteChanges( FSharpConstants.FSharpLanguageServiceCallbackName,
554566 AdviseProjectSiteChanges( fun () -> this.SyncProject( project, projectContext, site, workspace, forceUpdate= true , userOpName= " AdviseProjectSiteChanges." + userOpName)))
567+
555568 site.AdviseProjectSiteClosed( FSharpConstants.FSharpLanguageServiceCallbackName,
556569 AdviseProjectSiteChanges( fun () ->
557570 projectInfoManager.ClearInfoForProject( project.Id)
558571 optionsAssociation.Remove( projectContext) |> ignore
559572 project.Disconnect()))
573+
560574for referencedSitein ProjectSitesAndFiles.GetReferencedProjectSites( site, this.SystemServiceProvider) do
561- let referencedProjectId = setup referencedSite
562- project.AddProjectReference( ProjectReference referencedProjectId)
575+ setup referencedSite
563576
564- projectId
565- setup( siteProvider.GetProjectSite()) |> ignore
577+ setup( siteProvider.GetProjectSite())
566578
567579member this.SetupStandAloneFile ( fileName : string , fileContents : string , workspace : VisualStudioWorkspaceImpl , hier : IVsHierarchy ) =
568580let loadTime = DateTime.Now