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

Fixed cross project references #5284

Merged
merged 1 commit into from
Jul 3, 2018
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ type internal FSharpProjectOptionsManager
member this.ComputeSingleFileOptions (tryGetOrCreateProjectId, fileName, loadTime, fileContents) =
async {
let extraProjectInfo = Some(box workspace)
let tryGetOptionsForReferencedProject f = f |> tryGetOrCreateProjectId |> Option.bind this.TryGetOptionsForProject |> Option.map(fun (_, _, projectOptions) -> projectOptions)
if SourceFile.MustBeSingleFileProject(fileName) then
// NOTE: we don't use a unique stamp for single files, instead comparing options structurally.
// This is because we repeatedly recompute the options.
Expand All @@ -159,12 +158,12 @@ type internal FSharpProjectOptionsManager
// compiled and #r will refer to files on disk
let referencedProjectFileNames = [| |]
let site = ProjectSitesAndFiles.CreateProjectSiteForScript(fileName, referencedProjectFileNames, options)
let deps, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, (tryGetOrCreateProjectId fileName), fileName, options.ExtraProjectInfo, Some projectOptionsTable)
let deps, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, site, serviceProvider, (tryGetOrCreateProjectId fileName), fileName, options.ExtraProjectInfo, Some projectOptionsTable)
let parsingOptions, _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions(projectOptions)
return (deps, parsingOptions, projectOptions)
else
let site = ProjectSitesAndFiles.ProjectSiteOfSingleFile(fileName)
let deps, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, (tryGetOrCreateProjectId fileName), fileName, extraProjectInfo, Some projectOptionsTable)
let deps, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, site, serviceProvider, (tryGetOrCreateProjectId fileName), fileName, extraProjectInfo, Some projectOptionsTable)
let parsingOptions, _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions(projectOptions)
return (deps, parsingOptions, projectOptions)
}
Expand All @@ -174,8 +173,7 @@ type internal FSharpProjectOptionsManager
Logger.Log LogEditorFunctionId.LanguageService_UpdateProjectInfo
projectOptionsTable.AddOrUpdateProject(projectId, (fun isRefresh ->
let extraProjectInfo = Some(box workspace)
let tryGetOptionsForReferencedProject f = f |> tryGetOrCreateProjectId |> Option.bind this.TryGetOptionsForProject |> Option.map(fun (_, _, projectOptions) -> projectOptions)
let referencedProjects, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, site, serviceProvider, Some(projectId), site.ProjectFileName, extraProjectInfo, Some projectOptionsTable)
let referencedProjects, projectOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(Settings.LanguageServicePerformance.EnableInMemoryCrossProjectReferences, site, serviceProvider, Some(projectId), site.ProjectFileName, extraProjectInfo, Some projectOptionsTable)
if invalidateConfig then checkerProvider.Checker.InvalidateConfiguration(projectOptions, startBackgroundCompileIfAlreadySeen = not isRefresh, userOpName = userOpName + ".UpdateProjectInfo")
let referencedProjectIds = referencedProjects |> Array.choose tryGetOrCreateProjectId
let parsingOptions, _ = checkerProvider.Checker.GetParsingOptionsFromProjectOptions(projectOptions)
Expand Down Expand Up @@ -610,7 +608,7 @@ type internal FSharpLanguageService(package : FSharpPackage) =
optionsAssociation.Remove(projectContext) |> ignore
project.Disconnect()))

for referencedSite in ProjectSitesAndFiles.GetReferencedProjectSites(site, this.SystemServiceProvider, Some (this.Workspace :>obj), Some projectInfoManager.FSharpOptions ) do
for referencedSite in ProjectSitesAndFiles.GetReferencedProjectSites(Some projectId, site, this.SystemServiceProvider, Some (this.Workspace :>obj), Some projectInfoManager.FSharpOptions ) do
setup referencedSite

setup (siteProvider.GetProjectSite())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,23 +221,25 @@ type internal ProjectSitesAndFiles() =
| _ -> None
| Some _ -> None

static let rec referencedProvideProjectSites(projectSite:IProjectSite, serviceProvider:System.IServiceProvider, extraProjectInfo:obj option, projectOptionsTable:FSharpProjectOptionsTable option) =
static let rec referencedProvideProjectSites(projectIdOpt: ProjectId option, projectSite:IProjectSite, serviceProvider:System.IServiceProvider, extraProjectInfo:obj option, projectOptionsTable:FSharpProjectOptionsTable option) =
let getReferencesForSolutionService (solutionService:IVsSolution) =
[|
match referencedProjects projectSite, extraProjectInfo with
| None, Some (:? VisualStudioWorkspaceImpl as workspace) when not (isNull workspace.CurrentSolution)->
let path = projectSite.ProjectFileName
if not (String.IsNullOrWhiteSpace(path)) then
let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(path, projectDisplayNameOf path)
let project = workspace.CurrentSolution.GetProject(projectId)
if not (isNull project) then
for reference in project.ProjectReferences do
let project = workspace.CurrentSolution.GetProject(reference.ProjectId)
if not (isNull project) && project.Language = FSharpConstants.FSharpLanguageName then
let siteProvider = provideProjectSiteProvider (workspace, project, serviceProvider, projectOptionsTable)
let referenceProject = workspace.ProjectTracker.GetProject(reference.ProjectId)
let outputPath = referenceProject.BinOutputPath
yield Some projectId, project.FilePath, outputPath, siteProvider
match projectIdOpt with
| Some(projectId) ->
let project = workspace.CurrentSolution.GetProject(projectId)
if not (isNull project) then
for reference in project.ProjectReferences do
let project = workspace.CurrentSolution.GetProject(reference.ProjectId)
if not (isNull project) && project.Language = FSharpConstants.FSharpLanguageName then
let siteProvider = provideProjectSiteProvider (workspace, project, serviceProvider, projectOptionsTable)
let referenceProject = workspace.ProjectTracker.GetProject(reference.ProjectId)
let outputPath = referenceProject.BinOutputPath
yield Some project.Id, project.FilePath, outputPath, siteProvider
| _ -> ()

| (Some references), _ ->
for p in references do
Expand All @@ -255,26 +257,33 @@ type internal ProjectSitesAndFiles() =
| None -> ()
}

static let rec referencedProjectsOf(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable) =
[| for (projectId, projectFileName, outputPath, projectSiteProvider) in referencedProvideProjectSites (projectSite, serviceProvider, extraProjectInfo, projectOptionsTable) do
let referencedProjectOptions =
// Lookup may not succeed if the project has not been established yet
// In this case we go and compute the options recursively.
match tryGetOptionsForReferencedProject projectFileName with
| None -> getProjectOptionsForProjectSite (enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSiteProvider.GetProjectSite(), serviceProvider, projectId, projectFileName, extraProjectInfo, projectOptionsTable) |> snd
| Some options -> options
yield projectFileName, (outputPath, referencedProjectOptions) |]

and getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, projectId, fileName, extraProjectInfo, projectOptionsTable) =
static let rec referencedProjectsOf(projectIdOpt, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable) =
[| for (projectIdOpt, projectFileName, outputPath, _projectSiteProvider) in referencedProvideProjectSites (projectIdOpt, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable) do
let referencedProjectOptionsOpt =
projectOptionsTable
|> Option.bind (fun x ->
match projectIdOpt with
| Some(projectId) -> x.TryGetOptionsForProject(projectId)
| _ -> None
)
|> Option.map (fun (_, _, options) -> options)

match referencedProjectOptionsOpt with
| Some(referencedProjectOptions) ->
yield projectFileName, (outputPath, referencedProjectOptions)
| _ -> ()
|]

and getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, projectSite, serviceProvider, projectIdOpt, fileName, extraProjectInfo, projectOptionsTable) =
let referencedProjectFileNames, referencedProjectOptions =
if enableInMemoryCrossProjectReferences then
referencedProjectsOf(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable)
referencedProjectsOf(projectIdOpt, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable)
|> Array.unzip
else [| |], [| |]
let option =
let newOption () = {
ProjectFileName = projectSite.ProjectFileName
ProjectId = projectId |> Option.map (fun x -> x.ToFSharpProjectIdString())
ProjectId = projectIdOpt |> Option.map (fun x -> x.ToFSharpProjectIdString())
SourceFiles = projectSite.CompilationSourceFiles
OtherOptions = projectSite.CompilationOptions
ReferencedProjects = referencedProjectOptions
Expand All @@ -286,7 +295,7 @@ type internal ProjectSitesAndFiles() =
ExtraProjectInfo=extraProjectInfo
Stamp = (stamp <- stamp + 1L; Some stamp)
}
match projectId, projectOptionsTable with
match projectIdOpt, projectOptionsTable with
| Some id, Some optionsTable ->
// Get options from cache
match optionsTable.TryGetOptionsForProject(id) with
Expand All @@ -308,16 +317,16 @@ type internal ProjectSitesAndFiles() =
failwith ".fsx or .fsscript should have been treated as implicit project"
new ProjectSiteOfSingleFile(filename) :> IProjectSite

static member GetReferencedProjectSites(projectSite:IProjectSite, serviceProvider:System.IServiceProvider, extraProjectInfo, projectOptions) =
referencedProvideProjectSites (projectSite, serviceProvider, extraProjectInfo, projectOptions)
static member GetReferencedProjectSites(projectIdOpt, projectSite:IProjectSite, serviceProvider:System.IServiceProvider, extraProjectInfo, projectOptions) =
referencedProvideProjectSites (projectIdOpt, projectSite, serviceProvider, extraProjectInfo, projectOptions)
|> Seq.map (fun (_, _, _, ps) -> ps.GetProjectSite())
|> Seq.toArray

/// Create project options for this project site.
static member GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite:IProjectSite, serviceProvider, projectId, filename, extraProjectInfo, projectOptionsTable) =
static member GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, projectSite:IProjectSite, serviceProvider, projectId, filename, extraProjectInfo, projectOptionsTable) =
match projectSite with
| :? IHaveCheckOptions as hco -> hco.OriginalCheckOptions()
| _ -> getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, projectId, filename, extraProjectInfo, projectOptionsTable)
| _ -> getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, projectSite, serviceProvider, projectId, filename, extraProjectInfo, projectOptionsTable)

/// Create project site for these project options
static member CreateProjectSiteForScript (filename, referencedProjectFileNames, checkOptions) =
Expand Down