Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 3033 - make project references known to Roslyn (note: requires Roslyn fix) #3499

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions VisualFSharp.sln
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26403.7
VisualStudioVersion = 15.0.26730.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Private", "src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj", "{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.VS.FSI", "vsintegration\src\FSharp.VS.FSI\FSharp.VS.FSI.fsproj", "{991DCF75-C2EB-42B6-9A0D-AA1D2409D519}"
ProjectSection(ProjectDependencies) = postProject
{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3} = {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{2E4D67B4-522D-4CF7-97E4-BA940F0B18F3} = {2E4D67B4-522D-4CF7-97E4-BA940F0B18F3}
EndProjectSection
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Server.Shared", "src\fsharp\FSharp.Compiler.Server.Shared\FSharp.Compiler.Server.Shared.fsproj", "{D5870CF0-ED51-4CBC-B3D7-6F56DA84AC06}"
EndProject
Expand Down Expand Up @@ -142,6 +142,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FSharp.Compiler.Service.tes
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TestTP", "tests\service\data\TestTP\TestTP.fsproj", "{FF76BD3C-5E0A-4752-B6C3-044F6E15719B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceFile", "vsintegration\ItemTemplates\ResourceFile\ResourceFile.csproj", "{0385564F-07B4-4264-AB8A-17C393E9140C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -574,6 +576,14 @@ Global
{FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Release|Any CPU.Build.0 = Release|Any CPU
{FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Release|x86.ActiveCfg = Release|Any CPU
{FF76BD3C-5E0A-4752-B6C3-044F6E15719B}.Release|x86.Build.0 = Release|Any CPU
{0385564F-07B4-4264-AB8A-17C393E9140C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0385564F-07B4-4264-AB8A-17C393E9140C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0385564F-07B4-4264-AB8A-17C393E9140C}.Debug|x86.ActiveCfg = Debug|Any CPU
{0385564F-07B4-4264-AB8A-17C393E9140C}.Debug|x86.Build.0 = Debug|Any CPU
{0385564F-07B4-4264-AB8A-17C393E9140C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0385564F-07B4-4264-AB8A-17C393E9140C}.Release|Any CPU.Build.0 = Release|Any CPU
{0385564F-07B4-4264-AB8A-17C393E9140C}.Release|x86.ActiveCfg = Release|Any CPU
{0385564F-07B4-4264-AB8A-17C393E9140C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -639,5 +649,9 @@ Global
{887630A3-4B1D-40EA-B8B3-2D842E9C40DB} = {35636A82-401A-4C3A-B2AB-EB7DC5E9C268}
{35636A82-401A-4C3A-B2AB-EB7DC5E9C268} = {F7876C9B-FB6A-4EFB-B058-D6967DB75FB2}
{FF76BD3C-5E0A-4752-B6C3-044F6E15719B} = {35636A82-401A-4C3A-B2AB-EB7DC5E9C268}
{0385564F-07B4-4264-AB8A-17C393E9140C} = {F6DAEE9A-8BE1-4C4A-BC83-09215517C7DA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {48EDBBBE-C8EE-4E3C-8B19-97184A487B37}
EndGlobalSection
EndGlobal
60 changes: 36 additions & 24 deletions vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ type internal FSharpProjectOptionsManager
this.AddOrUpdateProject(projectId, (fun isRefresh ->
let extraProjectInfo = Some(box workspace)
let tryGetOptionsForReferencedProject f = f |> tryGetOrCreateProjectId |> Option.bind this.TryGetOptionsForProject
let referencedProjects, options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, site.ProjectFileName(), extraProjectInfo, serviceProvider, true)
let referencedProjects, options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, site.ProjectFileName, extraProjectInfo, serviceProvider, true)
let referencedProjectIds = referencedProjects |> Array.choose tryGetOrCreateProjectId
checkerProvider.Checker.InvalidateConfiguration(options, startBackgroundCompileIfAlreadySeen = not isRefresh, userOpName= userOpName + ".UpdateProjectInfo")
referencedProjectIds, options))
Expand Down Expand Up @@ -231,21 +231,22 @@ type internal FSharpProjectOptionsManager
Some(reporter:> Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2)

{new Microsoft.VisualStudio.FSharp.LanguageService.IProjectSite with
member __.SourceFilesOnDisk() = this.GetProjectInfo(project.FilePath) |> fst
member __.DescriptionOfProject() = project.Name
member __.CompilerFlags() =
member __.CompilationSourceFiles = this.GetProjectInfo(project.FilePath) |> fst
member __.CompilationOptions =
let _,references,options = this.GetProjectInfo(project.FilePath)
Array.concat [options; references |> Array.map(fun r -> "-r:" + r)]
member __.ProjectFileName() = project.FilePath
member __.CompilationReferences = this.GetProjectInfo(project.FilePath) |> thrd
member site.CompilationBinOutputPath = site.CompilationOptions |> Array.tryPick (fun s -> if s.StartsWith("-o:") then Some s.[3..] else None)
member __.Description = project.Name
member __.ProjectFileName = project.FilePath
member __.AdviseProjectSiteChanges(_,_) = ()
member __.AdviseProjectSiteCleaned(_,_) = ()
member __.AdviseProjectSiteClosed(_,_) = ()
member __.IsIncompleteTypeCheckEnvironment = false
member __.TargetFrameworkMoniker = ""
member __.ProjectGuid = project.Id.Id.ToString()
member __.ProjectGuid = project.Id.Id.ToString()
member __.LoadTime = System.DateTime.Now
member __.ProjectProvider = Some iProvideProjectSite
member __.AssemblyReferences() = this.GetProjectInfo(project.FilePath) |> thrd
member __.BuildErrorReporter with get () = errorReporter and
set (v) = errorReporter <- v
}
Expand Down Expand Up @@ -459,17 +460,20 @@ type

let theme = package.ComponentModel.DefaultExportProvider.GetExport<ISetThemeColors>().Value
theme.SetColors()

/// Sync the information for the project
member __.SyncProject(project: AbstractProject, projectContext: IWorkspaceProjectContext, site: IProjectSite, workspace, forceUpdate, userOpName) =

/// Sync the Roslyn information for the project held in 'projectContext' to match the information given by 'site'.
/// Also sync the info in ProjectInfoManager if necessary.
member this.SyncProject(project: AbstractProject, projectContext: IWorkspaceProjectContext, site: IProjectSite, workspace, forceUpdate, userOpName) =
let wellFormedFilePathSetIgnoreCase (paths: seq<string>) =
HashSet(paths |> Seq.filter isPathWellFormed |> Seq.map (fun s -> try System.IO.Path.GetFullPath(s) with _ -> s), StringComparer.OrdinalIgnoreCase)

let updatedFiles = site.SourceFilesOnDisk() |> wellFormedFilePathSetIgnoreCase
let originalFiles = project.GetCurrentDocuments() |> Seq.map (fun file -> file.FilePath) |> wellFormedFilePathSetIgnoreCase
HashSet(paths |> Seq.filter isPathWellFormed |> Seq.map (fun s -> try Path.GetFullPath(s) with _ -> s), StringComparer.OrdinalIgnoreCase)

let mutable updated = forceUpdate

// Sync the source files in projectContext. Note that these source files are __not__ maintained in order in projectContext
// as edits are made. It seems this is ok because the source file list is only used to drive roslyn per-file checking.
let updatedFiles = site.CompilationSourceFiles |> wellFormedFilePathSetIgnoreCase
let originalFiles = project.GetCurrentDocuments() |> Seq.map (fun file -> file.FilePath) |> wellFormedFilePathSetIgnoreCase

for file in updatedFiles do
if not(originalFiles.Contains(file)) then
projectContext.AddSourceFile(file)
Expand All @@ -480,7 +484,7 @@ type
projectContext.RemoveSourceFile(file)
updated <- true

let updatedRefs = site.AssemblyReferences() |> wellFormedFilePathSetIgnoreCase
let updatedRefs = site.CompilationReferences |> wellFormedFilePathSetIgnoreCase
let originalRefs = project.GetCurrentMetadataReferences() |> Seq.map (fun ref -> ref.FilePath) |> wellFormedFilePathSetIgnoreCase

for ref in updatedRefs do
Expand All @@ -493,8 +497,9 @@ type
projectContext.RemoveMetadataReference(ref)
updated <- true

// Update the project options association
let ok,originalOptions = optionsAssociation.TryGetValue(projectContext)
let updatedOptions = site.CompilerFlags()
let updatedOptions = site.CompilationOptions
if not ok || originalOptions <> updatedOptions then

// OK, project options have changed, try to fake out Roslyn to convince it to reparse things.
Expand All @@ -520,13 +525,12 @@ type
let userOpName = userOpName + ".SetupProjectFile"
let rec setup (site: IProjectSite) =
let projectGuid = Guid(site.ProjectGuid)
let projectFileName = site.ProjectFileName()
let projectFileName = site.ProjectFileName
let projectDisplayName = projectDisplayNameOf projectFileName

let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(projectFileName, projectDisplayName)

if isNull (workspace.ProjectTracker.GetProject projectId) then
projectInfoManager.UpdateProjectInfo(tryGetOrCreateProjectId workspace, projectId, site, userOpName)
let projectContextFactory = package.ComponentModel.GetService<IWorkspaceProjectContextFactory>();
let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider)

Expand All @@ -542,27 +546,35 @@ type

let projectContext =
projectContextFactory.CreateProjectContext(
FSharpConstants.FSharpLanguageName, projectDisplayName, projectFileName, projectGuid, hierarchy, null, errorReporter)
FSharpConstants.FSharpLanguageName,
projectDisplayName,
projectFileName,
projectGuid,
hierarchy,
Option.toObj site.CompilationBinOutputPath,
errorReporter)

let project = projectContext :?> AbstractProject

this.SyncProject(project, projectContext, site, workspace, forceUpdate=false, userOpName=userOpName)
// Sync IProjectSite --> projectContext, and IProjectSite --> ProjectInfoManage
this.SyncProject(project, projectContext, site, workspace, forceUpdate=true, userOpName=userOpName)

site.BuildErrorReporter <- Some (errorReporter :> Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2)

// TODO: consider forceUpdate = false here. forceUpdate=true may be causing repeated computation?
site.AdviseProjectSiteChanges(FSharpConstants.FSharpLanguageServiceCallbackName,
AdviseProjectSiteChanges(fun () -> this.SyncProject(project, projectContext, site, workspace, forceUpdate=true, userOpName="AdviseProjectSiteChanges."+userOpName)))

site.AdviseProjectSiteClosed(FSharpConstants.FSharpLanguageServiceCallbackName,
AdviseProjectSiteChanges(fun () ->
projectInfoManager.ClearInfoForProject(project.Id)
optionsAssociation.Remove(projectContext) |> ignore
project.Disconnect()))

for referencedSite in ProjectSitesAndFiles.GetReferencedProjectSites (site, this.SystemServiceProvider) do
let referencedProjectId = setup referencedSite
project.AddProjectReference(ProjectReference referencedProjectId)
setup referencedSite

projectId
setup (siteProvider.GetProjectSite()) |> ignore
setup (siteProvider.GetProjectSite())

member this.SetupStandAloneFile(fileName: string, fileContents: string, workspace: VisualStudioWorkspaceImpl, hier: IVsHierarchy) =
let loadTime = DateTime.Now
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ type internal FSharpLanguageServiceBackgroundRequests_DEPRECATED
let projectSite = ProjectSitesAndFiles.CreateProjectSiteForScript(fileName, referencedProjectFileNames, checkOptions)
{ ProjectSite = projectSite
CheckOptions = checkOptions
ProjectFileName = projectSite.ProjectFileName()
ProjectFileName = projectSite.ProjectFileName
FSharpChecker = checker
Colorizer = lazy getColorizer(view) }
Some data
Expand All @@ -109,7 +109,7 @@ type internal FSharpLanguageServiceBackgroundRequests_DEPRECATED
let projectSite = getProjectSitesAndFiles().FindOwningProject_DEPRECATED(rdt,fileName)
let enableInMemoryCrossProjectReferences = true
let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, fileName, None, getServiceProvider(), false)
let projectFileName = projectSite.ProjectFileName()
let projectFileName = projectSite.ProjectFileName
let data =
{ ProjectSite = projectSite
CheckOptions = checkOptions
Expand Down
2 changes: 1 addition & 1 deletion vsintegration/src/FSharp.LanguageService/FSharpSource.fs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ type internal FSharpSource_DEPRECATED(service:LanguageService_DEPRECATED, textLi
[|
match iSource.ProjectSite with
| Some pi ->
yield! pi.CompilerFlags () |> Array.filter(fun flag -> flag.StartsWith("--define:"))
yield! pi.CompilationOptions |> Array.filter(fun flag -> flag.StartsWith("--define:"))
| None -> ()
yield "--noframework"

Expand Down
25 changes: 16 additions & 9 deletions vsintegration/src/FSharp.LanguageService/IProjectSite.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,32 @@ type internal IProvideProjectSite =
and internal IProjectSite =

/// List of files in the project. In the correct order.
abstract SourceFilesOnDisk : unit -> string[]
abstract CompilationSourceFiles : string[]

/// Flags that the compiler would need to understand how to compile.
abstract CompilerFlags : unit -> string[]
/// Flags that the compiler would need to understand how to compile. Includes '-r'
/// options but not source files
abstract CompilationOptions : string[]

/// The normalized '-r:' assembly references, without the '-r:'
abstract CompilationReferences : string []

/// The '-o:' output bin path, without the '-o:'
abstract CompilationBinOutputPath : string option

/// Register for notifications for when the above change
abstract AdviseProjectSiteChanges : (*callbackOwnerKey*)string * AdviseProjectSiteChanges -> unit
abstract AdviseProjectSiteChanges : callbackOwnerKey: string * AdviseProjectSiteChanges -> unit

/// Register for notifications when project is cleaned/rebuilt (and thus any live TypeProviders should be refreshed)
abstract AdviseProjectSiteCleaned : (*callbackOwnerKey*)string * AdviseProjectSiteChanges -> unit
abstract AdviseProjectSiteCleaned : callbackOwnerKey: string * AdviseProjectSiteChanges -> unit

// Register for notifications when project is closed.
abstract AdviseProjectSiteClosed : (*callbackOwnerKey*)string * AdviseProjectSiteChanges -> unit
abstract AdviseProjectSiteClosed : callbackOwnerKey: string * AdviseProjectSiteChanges -> unit

/// A user-friendly description of the project. Used only for developer/DEBUG tooltips and such.
abstract DescriptionOfProject : unit -> string
abstract Description : string

/// The name of the project file.
abstract ProjectFileName : unit -> string
abstract ProjectFileName : string

/// The error list task reporter
abstract BuildErrorReporter : Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2 option with get, set
Expand All @@ -55,4 +62,4 @@ and internal IProjectSite =

abstract ProjectProvider : IProvideProjectSite option

abstract AssemblyReferences : unit -> string []

Loading