@@ -16,10 +16,6 @@ open Microsoft.FSharp.Compiler.SourceCodeServices
1616/// already available, so we don't have to recreate it
1717type private IHaveCheckOptions =
1818abstract OriginalCheckOptions : unit -> FSharpProjectOptions
19-
20- [<ComImport; InterfaceType( ComInterfaceType.InterfaceIsIUnknown); Guid( " ad98f020-bad0-0000-0000-abc037459871" ) >]
21- type internal IProvideProjectSite =
22- abstract GetProjectSite : unit -> IProjectSite
2319
2420/// Convert from FSharpProjectOptions into IProjectSite.
2521type private ProjectSiteOfScriptFile ( filename : string , checkOptions : FSharpProjectOptions ) =
@@ -37,6 +33,7 @@ type private ProjectSiteOfScriptFile(filename:string, checkOptions : FSharpProje
3733override this.TargetFrameworkMoniker = " "
3834override this.ProjectGuid = " "
3935override this.LoadTime = checkOptions.LoadTime
36+ override this.ProjectProvider = None
4037
4138interface IHaveCheckOptionswith
4239override this.OriginalCheckOptions () = checkOptions
@@ -70,6 +67,7 @@ type private ProjectSiteOfSingleFile(sourceFile) =
7067override this.TargetFrameworkMoniker = " "
7168override this.ProjectGuid = " "
7269override this.LoadTime = new DateTime( 2000 , 1 , 1 ) // any constant time is fine, orphan files do not interact with reloading based on update time
70+ override this.ProjectProvider = None
7371
7472/// Information about projects, open files and other active artifacts in visual studio.
7573/// Keeps track of the relationship between IVsTextLines buffers, IFSharpSource objects, IProjectSite objects and FSharpProjectOptions
@@ -83,6 +81,64 @@ type internal ProjectSitesAndFiles() =
8381 Some( siteFactory.GetProjectSite())
8482| _ -> None
8583
84+ static let fullOutputAssemblyPath ( p : EnvDTE.Project ) =
85+ let getProperty tag =
86+ try Some( p.Properties.[ tag]. Value.ToString()) with _ -> None
87+ getProperty" FullPath"
88+ |> Option.bind( fun fullPath ->
89+ ( try Some( p.ConfigurationManager.ActiveConfiguration.Properties.[ " OutputPath" ]. Value.ToString()) with _ -> None)
90+ |> Option.bind( fun outputPath ->
91+ getProperty" OutputFileName"
92+ |> Option.map( fun outputFileName -> Path.Combine( fullPath, outputPath, outputFileName))))
93+ |> Option.bind( fun path -> try Some( Path.GetFullPath path) with _ -> None)
94+
95+ static let referencedProjects ( projectSite : IProjectSite ) =
96+ match projectSite.ProjectProviderwith
97+ | None-> Seq.empty
98+ | Some(:? IVsHierarchyas hier) ->
99+ match hier.GetProperty( VSConstants.VSITEMID_ ROOT, int__ VSHPROPID.VSHPROPID_ ExtObject) with
100+ | VSConstants.S_ OK, (:? EnvDTE.Projectas p) ->
101+ ( p.Object:?> VSLangProj.VSProject) .References
102+ |> Seq.cast< VSLangProj.Reference>
103+ |> Seq.choose( fun r ->
104+ Option.ofObj r
105+ |> Option.bind( fun r -> try Option.ofObj r.SourceProjectwith _ -> None))
106+ | _ -> Seq.empty
107+ | Some_ -> Seq.empty
108+
109+ static let rec referencedProvideProjectSites ( projectSite : IProjectSite , serviceProvider : System.IServiceProvider ) =
110+ let solutionService =
111+ try Some( serviceProvider.GetService( typeof< SVsSolution>) :?> IVsSolution) with _ -> None
112+ match solutionServicewith
113+ | Some solutionService->
114+ referencedProjects projectSite
115+ |> Seq.choose( fun p ->
116+ match solutionService.GetProjectOfUniqueName( p.UniqueName) with
117+ | VSConstants.S_ OK, (:? IProvideProjectSiteas ps) ->
118+ Some( p, ps)
119+ | _ -> None)
120+ | None-> Seq.empty
121+
122+ static let rec referencedProjectsOf ( projectSite : IProjectSite , fileName , extraProjectInfo , serviceProvider : System.IServiceProvider ) =
123+ referencedProvideProjectSites( projectSite, serviceProvider)
124+ |> Seq.choose( fun ( p , ps ) ->
125+ fullOutputAssemblyPath p
126+ |> Option.map( fun path ->
127+ path, getProjectOptionsForProjectSite( ps.GetProjectSite(), fileName, extraProjectInfo, serviceProvider))
128+ )
129+ |> Seq.toArray
130+
131+ and getProjectOptionsForProjectSite ( projectSite : IProjectSite , fileName , extraProjectInfo , serviceProvider ) =
132+ { ProjectFileName= projectSite.ProjectFileName()
133+ ProjectFileNames= projectSite.SourceFilesOnDisk()
134+ OtherOptions= projectSite.CompilerFlags()
135+ ReferencedProjects= referencedProjectsOf( projectSite, fileName, extraProjectInfo, serviceProvider)
136+ IsIncompleteTypeCheckEnvironment= projectSite.IsIncompleteTypeCheckEnvironment
137+ UseScriptResolutionRules= SourceFile.MustBeSingleFileProject fileName
138+ LoadTime= projectSite.LoadTime
139+ UnresolvedReferences= None
140+ ExtraProjectInfo= extraProjectInfo}
141+
86142/// Construct a project site for a single file. May be a single file project (for scripts) or an orphan project site (for everything else).
87143static member ProjectSiteOfSingleFile ( filename : string ) : IProjectSite =
88144if SourceFile.MustBeSingleFileProject( filename) then
@@ -158,23 +214,19 @@ type internal ProjectSitesAndFiles() =
158214member art.FindOwningProject ( rdt : IVsRunningDocumentTable , filename ) =
159215match art.TryFindOwningProject( rdt, filename) with
160216| Some site-> site
161- | None-> ProjectSitesAndFiles.ProjectSiteOfSingleFile( filename)
217+ | None-> ProjectSitesAndFiles.ProjectSiteOfSingleFile( filename)
218+
219+ static member GetReferencedProjectSites ( projectSite : IProjectSite , serviceProvider : System.IServiceProvider ) =
220+ referencedProvideProjectSites( projectSite, serviceProvider)
221+ |> Seq.map( fun ( _ , ps ) -> ps.GetProjectSite())
222+ |> Seq.toArray
162223
163224/// Create project options for this project site.
164- static member GetProjectOptionsForProjectSite ( projectSite : IProjectSite , filename , extraProjectInfo ) =
165-
225+ static member GetProjectOptionsForProjectSite ( projectSite : IProjectSite , filename , extraProjectInfo , serviceProvider : System.IServiceProvider ) =
166226match projectSitewith
167227| :? IHaveCheckOptionsas hco-> hco.OriginalCheckOptions()
168- | _ ->
169- { ProjectFileName= projectSite.ProjectFileName()
170- ProjectFileNames= projectSite.SourceFilesOnDisk()
171- OtherOptions= projectSite.CompilerFlags()
172- ReferencedProjects= [| |]
173- IsIncompleteTypeCheckEnvironment= projectSite.IsIncompleteTypeCheckEnvironment
174- UseScriptResolutionRules= SourceFile.MustBeSingleFileProject( filename)
175- LoadTime= projectSite.LoadTime
176- UnresolvedReferences= None
177- ExtraProjectInfo= extraProjectInfo}
228+ | _ ->
229+ getProjectOptionsForProjectSite( projectSite, filename, extraProjectInfo, serviceProvider)
178230
179231/// Create project site for these project options
180232static member CreateProjectSiteForScript ( filename , checkOptions ) = ProjectSiteOfScriptFile( filename, checkOptions) :> IProjectSite