diff --git a/vsintegration/src/FSharp.Editor/Common/RoslynHelpers.fs b/vsintegration/src/FSharp.Editor/Common/RoslynHelpers.fs index a1c7b8f5734..feb1e89e57a 100644 --- a/vsintegration/src/FSharp.Editor/Common/RoslynHelpers.fs +++ b/vsintegration/src/FSharp.Editor/Common/RoslynHelpers.fs @@ -14,6 +14,7 @@ open Microsoft.FSharp.Compiler open Microsoft.FSharp.Compiler.Layout open Microsoft.FSharp.Compiler.SourceCodeServices open Microsoft.FSharp.Compiler.Range +open Microsoft.VisualStudio.FSharp.LanguageService [] module internal RoslynHelpers = diff --git a/vsintegration/src/FSharp.Editor/Common/Vs.fs b/vsintegration/src/FSharp.Editor/Common/Vs.fs index 526166f05d6..33fd16e6930 100644 --- a/vsintegration/src/FSharp.Editor/Common/Vs.fs +++ b/vsintegration/src/FSharp.Editor/Common/Vs.fs @@ -3,84 +3,16 @@ namespace Microsoft.VisualStudio.FSharp.Editor open System -open System.Runtime.InteropServices open Microsoft.VisualStudio -open Microsoft.VisualStudio.Editor open Microsoft.VisualStudio.Shell.Interop open Microsoft.VisualStudio.TextManager.Interop /// Helper methods for interoperating with COM -module internal Com = - let ThrowOnFailure0(hr) = - ErrorHandler.ThrowOnFailure(hr) |> ignore - - let ThrowOnFailure1(hr,res) = - ErrorHandler.ThrowOnFailure(hr) |> ignore; - res - - let ThrowOnFailure2(hr,res1,res2) = - ErrorHandler.ThrowOnFailure(hr) |> ignore; - res1,res2 - - let ThrowOnFailure3(hr,res1,res2,res3) = - ErrorHandler.ThrowOnFailure(hr) |> ignore; - res1,res2,res3 - - let ThrowOnFailure4(hr,res1,res2,res3,res4) = - ErrorHandler.ThrowOnFailure(hr) |> ignore; - res1,res2,res3,res4 - +module internal Com = let Succeeded hr = // REVIEW: Not the correct check for succeeded hr = VSConstants.S_OK -module internal VsUserData = - - let vsBufferMoniker = Guid("978A8E17-4DF8-432A-9623-D530A26452BC") - - // This is the file name of the buffer. - let GetBufferMonker(ud:IVsUserData) : string = - downcast Com.ThrowOnFailure1(ud.GetData(ref vsBufferMoniker)) - -module internal VsTextLines = - /// Get the length of the given line. - let LengthOfLine (buffer:IVsTextBuffer) (line:int) : int = - Com.ThrowOnFailure1(buffer.GetLengthOfLine(line)) - - /// Get the text for a particular line. - let LineText (buffer:IVsTextLines) line = - Com.ThrowOnFailure1(buffer.GetLineText(line, 0, line, LengthOfLine buffer line)) - - /// Get the color state - let TextColorState (buffer:IVsTextLines) : IVsTextColorState= unbox(box(buffer)) - - /// Get the filename of the given buffer (via IVsUserData). Not all buffers have a file. This will be an exception. - let GetFilename(buffer : IVsTextLines) = - let ud = (box buffer) :?> IVsUserData - VsUserData.GetBufferMonker(ud) - - /// Get the string contents of a given buffer (the current snapshot). - let GetFileContents(buffer: IVsTextBuffer, editorAdaptersFactoryService: IVsEditorAdaptersFactoryService) = - let dataBuffer = editorAdaptersFactoryService.GetDataBuffer(buffer) - dataBuffer.CurrentSnapshot.GetText() - -module internal VsRunningDocumentTable = - let FindDocumentWithoutLocking(rdt:IVsRunningDocumentTable, url:string) : (IVsHierarchy * IVsTextLines) option = - let (hr:int, hier:IVsHierarchy, _itemid:uint32, unkData:IntPtr, _cookie:uint32) = rdt.FindAndLockDocument(uint32 _VSRDTFLAGS.RDT_NoLock, url) - try - if Com.Succeeded(hr) then - let bufferObject = - if unkData=IntPtr.Zero then null - else Marshal.GetObjectForIUnknown(unkData) - let buffer = - match bufferObject with - | :? IVsTextLines as tl -> tl - | _ -> null - Some(hier, buffer) - else None - finally - if IntPtr.Zero <> unkData then Marshal.Release(unkData)|>ignore - [] module internal ServiceProviderExtensions = type internal System.IServiceProvider with diff --git a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj index 2563745eadc..0f11702c665 100644 --- a/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj +++ b/vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj @@ -32,6 +32,8 @@ + + true Microsoft.VisualStudio.FSharp.Editor.SR @@ -40,11 +42,11 @@ - + @@ -52,8 +54,6 @@ - - @@ -107,6 +107,11 @@ {DED3BBD7-53F4-428A-8C9F-27968E768605} FSharp.Core + + FSharp.LanguageService + {ee85aab7-cda0-4c4e-bda0-a64ccc413e3f} + True + FSharp.LanguageService.Base {1c5c163c-37ea-4a3c-8ccc-0d34b74bf8ef} @@ -127,6 +132,8 @@ {991dcf75-c2eb-42b6-9a0d-aa1d2409d519} True + + @@ -139,6 +146,8 @@ + + $(FSharpSourcesRoot)\..\packages\EnvDTE.8.0.1\lib\net10\EnvDTE.dll True @@ -147,10 +156,6 @@ $(FSharpSourcesRoot)\..\packages\EnvDTE80.8.0.1\lib\net10\EnvDTE80.dll True - - $(FSharpSourcesRoot)\..\packages\VSSDK.VSLangProj.7.0.4\lib\net20\VSLangProj.dll - True - $(FSharpSourcesRoot)\..\packages\Microsoft.VisualStudio.Threading.$(MicrosoftVisualStudioThreadingVersion)\lib\net45\Microsoft.VisualStudio.Threading.dll diff --git a/vsintegration/src/FSharp.Editor/LanguageService/IProjectSite.fs b/vsintegration/src/FSharp.Editor/LanguageService/IProjectSite.fs deleted file mode 100644 index 71d53fe406f..00000000000 --- a/vsintegration/src/FSharp.Editor/LanguageService/IProjectSite.fs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -namespace Microsoft.VisualStudio.FSharp.Editor - -open System.Runtime.InteropServices - -/// Narrow abstraction over the project system. -type internal AdviseProjectSiteChanges = delegate of unit -> unit - -[] -type internal IProvideProjectSite = - abstract GetProjectSite : unit -> IProjectSite - -/// Represents known F#-specific information about a project. -and internal IProjectSite = - - /// List of files in the project. In the correct order. - abstract CompilationSourceFiles : 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 - - /// The name of the project file. - abstract ProjectFileName : string - - /// Register for notifications for when the above change - 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 - - // Register for notifications when project is closed. - abstract AdviseProjectSiteClosed : callbackOwnerKey: string * AdviseProjectSiteChanges -> unit - - /// A user-friendly description of the project. Used only for developer/DEBUG tooltips and such. - abstract Description : string - - /// The error list task reporter - abstract BuildErrorReporter : Microsoft.VisualStudio.Shell.Interop.IVsLanguageServiceBuildErrorReporter2 option with get, set - - /// False type resolution errors are invalid. This occurs with orphaned source files. The prior - /// type checking state is unknown. In this case we don't want to squiggle the type checking files. - abstract IsIncompleteTypeCheckEnvironment : bool - - /// target framework moniker - abstract TargetFrameworkMoniker : string - - /// Project Guid - abstract ProjectGuid : string - - /// timestamp the site was last loaded - abstract LoadTime : System.DateTime - - abstract ProjectProvider : IProvideProjectSite option \ No newline at end of file diff --git a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs index 8741f48e95c..1686e96a3d5 100644 --- a/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs +++ b/vsintegration/src/FSharp.Editor/LanguageService/LanguageService.fs @@ -23,7 +23,8 @@ open Microsoft.FSharp.Compiler.CompileOps open Microsoft.FSharp.Compiler.SourceCodeServices open Microsoft.VisualStudio open Microsoft.VisualStudio.Editor -open Microsoft.VisualStudio.FSharp.Editor.SiteProvider +open Microsoft.VisualStudio.FSharp.LanguageService +open Microsoft.VisualStudio.FSharp.LanguageService.SiteProvider open Microsoft.VisualStudio.TextManager.Interop open Microsoft.VisualStudio.LanguageServices open Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService diff --git a/vsintegration/src/FSharp.Editor/LanguageService/ProjectSitesAndFiles.fs b/vsintegration/src/FSharp.Editor/LanguageService/ProjectSitesAndFiles.fs deleted file mode 100644 index 6c5a2c61cb8..00000000000 --- a/vsintegration/src/FSharp.Editor/LanguageService/ProjectSitesAndFiles.fs +++ /dev/null @@ -1,323 +0,0 @@ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. - -module internal rec Microsoft.VisualStudio.FSharp.Editor.SiteProvider - -open System -open System.IO -open System.Collections.Concurrent -open System.Diagnostics - -open Microsoft.FSharp.Compiler.SourceCodeServices -open Microsoft.CodeAnalysis -open Microsoft.VisualStudio -open Microsoft.VisualStudio.LanguageServices -open Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem -open Microsoft.VisualStudio.LanguageServices.Implementation.TaskList -open Microsoft.VisualStudio.Shell.Interop -open Microsoft.VisualStudio.TextManager.Interop - -open VSLangProj - -/// An additional interface that an IProjectSite object can implement to indicate it has an FSharpProjectOptions -/// already available, so we don't have to recreate it -type private IHaveCheckOptions = - abstract OriginalCheckOptions : unit -> string[] * FSharpProjectOptions - -let projectDisplayNameOf projectFileName = - if String.IsNullOrWhiteSpace projectFileName then projectFileName - else Path.GetFileNameWithoutExtension projectFileName - -/// A value and a function to recompute/refresh the value. The function is passed a flag indicating if a refresh is happening. -type Refreshable<'T> = 'T * (bool -> 'T) - -/// Convert from FSharpProjectOptions into IProjectSite. -type private ProjectSiteOfScriptFile(filename:string, referencedProjectFileNames, checkOptions: FSharpProjectOptions) = - interface IProjectSite with - override __.Description = sprintf "Script Closure at Root %s" filename - override __.CompilationSourceFiles = checkOptions.SourceFiles - override __.CompilationOptions = checkOptions.OtherOptions - override __.CompilationReferences = - checkOptions.OtherOptions - |> Array.choose (fun flag -> if flag.StartsWith("-r:") then Some flag.[3..] else None) - override __.CompilationBinOutputPath = None - override __.ProjectFileName = checkOptions.ProjectFileName - override __.BuildErrorReporter with get() = None and set _ = () - override __.AdviseProjectSiteChanges(_,_) = () - override __.AdviseProjectSiteCleaned(_,_) = () - override __.AdviseProjectSiteClosed(_,_) = () - override __.IsIncompleteTypeCheckEnvironment = checkOptions.IsIncompleteTypeCheckEnvironment - override __.TargetFrameworkMoniker = "" - override __.ProjectGuid = "" - override __.LoadTime = checkOptions.LoadTime - override __.ProjectProvider = None - - interface IHaveCheckOptions with - override __.OriginalCheckOptions() = (referencedProjectFileNames, checkOptions) - - override __.ToString() = sprintf "ProjectSiteOfScriptFile(%s)" filename - -/// An orphan file project is a .fs, .ml, .fsi, .mli that is not associated with a .fsproj. -/// By design, these are never going to typecheck because there is no affiliated references. -/// We show many squiggles in this case because they're not particularly informational. -type private ProjectSiteOfSingleFile(sourceFile) = - // CompilerFlags() gets called a lot, so pre-compute what we can - static let compilerFlags = - let flags = ["--noframework";"--warn:3"] - let assumeDotNetFramework = true - let defaultReferences = - [ for r in CompilerEnvironment.DefaultReferencesForOrphanSources(assumeDotNetFramework) do - yield sprintf "-r:%s%s" r (if r.EndsWith(".dll",StringComparison.OrdinalIgnoreCase) then "" else ".dll") ] - (flags @ defaultReferences) - |> List.toArray - |> Array.choose (fun flag -> if flag.StartsWith("-r:") then Some flag.[3..] elif flag.StartsWith("--reference:") then Some flag.[12..] else None) - - let projectFileName = sourceFile + ".orphan.fsproj" - - interface IProjectSite with - override __.Description = projectFileName - override __.CompilationSourceFiles = [|sourceFile|] - override __.CompilationOptions = compilerFlags - override __.CompilationReferences = compilerFlags - override __.CompilationBinOutputPath = None - override __.ProjectFileName = projectFileName - override __.BuildErrorReporter with get() = None and set _v = () - override __.AdviseProjectSiteChanges(_,_) = () - override __.AdviseProjectSiteCleaned(_,_) = () - override __.AdviseProjectSiteClosed(_,_) = () - override __.IsIncompleteTypeCheckEnvironment = true - override __.TargetFrameworkMoniker = "" - override __.ProjectGuid = "" - override __.LoadTime = new DateTime(2000,1,1) // any constant time is fine, orphan files do not interact with reloading based on update time - override __.ProjectProvider = None - - override __.ToString() = sprintf "ProjectSiteOfSingleFile(%s)" sourceFile - -/// Manage Storage of FSharpProjectOptions the options for a project -type internal FSharpProjectOptionsTable () = - - // A table of information about projects, excluding single-file projects. - let projectTable = ConcurrentDictionary>() - let commandLineOptions = new ConcurrentDictionary() - - /// Re-fetch all of the options for everything that references projectId - let refreshInfoForProjectsThatReferenceThisProject (projectId:ProjectId) = - for KeyValue(otherProjectId, ((referencedProjectIds, _parsingOptions, _site, _options), refresh)) in projectTable.ToArray() do - for referencedProjectId in referencedProjectIds do - if referencedProjectId = projectId then - projectTable.[otherProjectId] <- (refresh true, refresh) - - /// Add or update a project in the project table - member __.AddOrUpdateProject(projectId:ProjectId, refresh) = - projectTable.[projectId] <- (refresh false, refresh) - refreshInfoForProjectsThatReferenceThisProject(projectId) - - /// Clear a project from the project table - member __.ClearInfoForProject(projectId:ProjectId) = - projectTable.TryRemove(projectId) |> ignore - refreshInfoForProjectsThatReferenceThisProject projectId - - /// Get the options for a project - member __.TryGetOptionsForProject(projectId:ProjectId) = - match projectTable.TryGetValue(projectId) with - | true, ((_referencedProjects, parsingOptions, site, projectOptions), _) -> Some (parsingOptions, site, projectOptions) - | _ -> None - - /// Given a projectId return the most recent set of command line options for it - member __.GetCommandLineOptionsWithProjectId(projectId:ProjectId) = - match commandLineOptions.TryGetValue projectId with - | true, (sources, references, options) -> sources, references, options - | _ -> [||], [||], [||] - - /// Store the command line options for a projectId - member __.SetOptionsWithProjectId(projectId:ProjectId, sourcePaths:string[], referencePaths:string[], options:string[]) = - commandLineOptions.[projectId] <- (sourcePaths, referencePaths, options) - - -let internal provideProjectSiteProvider(workspace:VisualStudioWorkspaceImpl, project:Project, serviceProvider:System.IServiceProvider, projectOptionsTable:FSharpProjectOptionsTable option) = - let hier = workspace.GetHierarchy(project.Id) - let getCommandLineOptionsWithProjectId (projectId) = - match projectOptionsTable with - | Some (options) -> options.GetCommandLineOptionsWithProjectId(projectId) - | None -> [||], [||], [||] - { - new IProvideProjectSite with - member x.GetProjectSite() = - let fst (a, _, _) = a - let snd (_, b, _) = b - let mutable errorReporter = - let reporter = ProjectExternalErrorReporter(project.Id, "FS", serviceProvider) - Some(reporter:> IVsLanguageServiceBuildErrorReporter2) - - { - new IProjectSite with - member __.Description = project.Name - member __.CompilationSourceFiles = getCommandLineOptionsWithProjectId(project.Id) |> fst - member __.CompilationOptions = - let _,references,options = getCommandLineOptionsWithProjectId(project.Id) - Array.concat [options; references |> Array.map(fun r -> "-r:" + r)] - member __.CompilationReferences = getCommandLineOptionsWithProjectId(project.Id) |> snd - member site.CompilationBinOutputPath = site.CompilationOptions |> Array.tryPick (fun s -> if s.StartsWith("-o:") then Some s.[3..] else None) - member __.ProjectFileName = project.FilePath - member __.AdviseProjectSiteChanges(_,_) = () - member __.AdviseProjectSiteCleaned(_,_) = () - member __.AdviseProjectSiteClosed(_,_) = () - member __.IsIncompleteTypeCheckEnvironment = false - member __.TargetFrameworkMoniker = "" - member __.ProjectGuid = project.Id.Id.ToString() - member __.LoadTime = System.DateTime.Now - member __.ProjectProvider = Some (x) - member __.BuildErrorReporter with get () = errorReporter and set (v) = errorReporter <- v - } - interface IVsHierarchy with - member __.SetSite(psp) = hier.SetSite(psp) - member __.GetSite(psp) = hier.GetSite(ref psp) - member __.QueryClose(pfCanClose)= hier.QueryClose(ref pfCanClose) - member __.Close() = hier.Close() - member __.GetGuidProperty(itemid, propid, pguid) = hier.GetGuidProperty(itemid, propid, ref pguid) - member __.SetGuidProperty(itemid, propid, rguid) = hier.SetGuidProperty(itemid, propid, ref rguid) - member __.GetProperty(itemid, propid, pvar) = hier.GetProperty(itemid, propid, ref pvar) - member __.SetProperty(itemid, propid, var) = hier.SetProperty(itemid, propid, var) - member __.GetNestedHierarchy(itemid, iidHierarchyNested, ppHierarchyNested, pitemidNested) = - hier.GetNestedHierarchy(itemid, ref iidHierarchyNested, ref ppHierarchyNested, ref pitemidNested) - member __.GetCanonicalName(itemid, pbstrName) = hier.GetCanonicalName(itemid, ref pbstrName) - member __.ParseCanonicalName(pszName, pitemid) = hier.ParseCanonicalName(pszName, ref pitemid) - member __.Unused0() = hier.Unused0() - member __.AdviseHierarchyEvents(pEventSink, pdwCookie) = hier.AdviseHierarchyEvents(pEventSink, ref pdwCookie) - member __.UnadviseHierarchyEvents(dwCookie) = hier.UnadviseHierarchyEvents(dwCookie) - member __.Unused1() = hier.Unused1() - member __.Unused2() = hier.Unused2() - member __.Unused3() = hier.Unused3() - member __.Unused4() = hier.Unused4() - } - -/// Information about projects, open files and other active artifacts in visual studio. -/// Keeps track of the relationship between IVsTextLines buffers, IFSharpSource_DEPRECATED objects, IProjectSite objects and FSharpProjectOptions -[] -type internal ProjectSitesAndFiles() = - static let mutable stamp = 0L - - static let fullOutputAssemblyPath (p:EnvDTE.Project) = - let getProperty tag = - try Some (p.Properties.[tag].Value.ToString()) with _ -> None - getProperty "FullPath" - |> Option.bind (fun fullPath -> - (try Some (p.ConfigurationManager.ActiveConfiguration.Properties.["OutputPath"].Value.ToString()) with _ -> None) - |> Option.bind (fun outputPath -> - getProperty "OutputFileName" - |> Option.map (fun outputFileName -> Path.Combine(fullPath, outputPath, outputFileName)))) - |> Option.bind (fun path -> try Some (Path.GetFullPath path) with _ -> None) - - static let referencedProjects (projectSite:IProjectSite) = - match projectSite.ProjectProvider with - | None -> None - | Some (:? IVsHierarchy as hier) -> - match hier.GetProperty(VSConstants.VSITEMID_ROOT, int __VSHPROPID.VSHPROPID_ExtObject) with - | VSConstants.S_OK, (:? EnvDTE.Project as p) when not (isNull p) -> - Some ((p.Object :?> VSLangProj.VSProject).References - |> Seq.cast - |> Seq.choose (fun r -> - Option.ofObj r - |> Option.bind (fun r -> try Option.ofObj r.SourceProject with _ -> None)) ) - | _ -> None - | Some _ -> None - - static let rec referencedProvideProjectSites(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 - - | (Some references), _ -> - for p in references do - match solutionService.GetProjectOfUniqueName(p.UniqueName) with - | VSConstants.S_OK, (:? IProvideProjectSite as ps) -> - yield None, p.FileName, (fullOutputAssemblyPath p) |> Option.defaultValue "", ps - | _ -> () - | None, _ -> () - |] - let solutionService = try Some (serviceProvider.GetService(typeof) :?> IVsSolution) with _ -> None - seq { match solutionService with - | Some solutionService -> - for reference in getReferencesForSolutionService solutionService do - yield reference - | None -> () - } - - static let rec referencedProjectsOf(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable, useUniqueStamp) = - [| 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, useUniqueStamp) |> snd - | Some options -> options - yield projectFileName, (outputPath, referencedProjectOptions) |] - - and getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, projectId, fileName, extraProjectInfo, projectOptionsTable, useUniqueStamp) = - let referencedProjectFileNames, referencedProjectOptions = - if enableInMemoryCrossProjectReferences then - referencedProjectsOf(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, extraProjectInfo, projectOptionsTable, useUniqueStamp) - |> Array.unzip - else [| |], [| |] - let option = - let newOption () = { - ProjectFileName = projectSite.ProjectFileName - SourceFiles = projectSite.CompilationSourceFiles - OtherOptions = projectSite.CompilationOptions - ReferencedProjects = referencedProjectOptions - IsIncompleteTypeCheckEnvironment = projectSite.IsIncompleteTypeCheckEnvironment - UseScriptResolutionRules = SourceFile.MustBeSingleFileProject fileName - LoadTime = projectSite.LoadTime - UnresolvedReferences = None - OriginalLoadReferences = [] - ExtraProjectInfo=extraProjectInfo - Stamp = if useUniqueStamp then (stamp <- stamp + 1L; Some stamp) else None - } - match projectId, projectOptionsTable with - | Some id, Some optionsTable -> - // Get options from cache - match optionsTable.TryGetOptionsForProject(id) with - | Some (_parsingOptions, _site, projectOptions) -> - if projectSite.CompilationSourceFiles <> projectOptions.SourceFiles || - projectSite.CompilationOptions <> projectOptions.OtherOptions || - referencedProjectOptions <> projectOptions.ReferencedProjects then - newOption() - else - projectOptions - | _ -> newOption() - | _ -> newOption() - referencedProjectFileNames, option - - /// Construct a project site for a single file. May be a single file project (for scripts) or an orphan project site (for everything else). - static member ProjectSiteOfSingleFile(filename:string) : IProjectSite = - if SourceFile.MustBeSingleFileProject(filename) then - Debug.Assert(false, ".fsx or .fsscript should have been treated as implicit project") - 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) - |> 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, useUniqueStamp) = - match projectSite with - | :? IHaveCheckOptions as hco -> hco.OriginalCheckOptions() - | _ -> getProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, tryGetOptionsForReferencedProject, projectSite, serviceProvider, projectId, filename, extraProjectInfo, projectOptionsTable, useUniqueStamp) - - /// Create project site for these project options - static member CreateProjectSiteForScript (filename, referencedProjectFileNames, checkOptions) = - ProjectSiteOfScriptFile (filename, referencedProjectFileNames, checkOptions) :> IProjectSite \ No newline at end of file diff --git a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs index fab0c09c4e2..9e91f0c052c 100644 --- a/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs +++ b/vsintegration/src/FSharp.ProjectSystem.FSharp/Project.fs @@ -1471,7 +1471,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem member __.TargetFrameworkMoniker = x.GetTargetFrameworkMoniker() member __.ProjectGuid = x.GetProjectGuid() member __.LoadTime = creationTime - member __.ProjectProvider = Some (x :> Microsoft.VisualStudio.FSharp.LanguageService.IProvideProjectSite) + member __.ProjectProvider = Some (x :> IProvideProjectSite) } @@ -1507,7 +1507,7 @@ namespace rec Microsoft.VisualStudio.FSharp.ProjectSystem member __.TargetFrameworkMoniker = targetFrameworkMoniker member __.ProjectGuid = x.GetProjectGuid() member __.LoadTime = creationTime - member __.ProjectProvider = Some (x :> Microsoft.VisualStudio.FSharp.LanguageService.IProvideProjectSite) + member __.ProjectProvider = Some (x :> IProvideProjectSite) } // let the language service ask us questions diff --git a/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs b/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs index 91246194721..21b290c3819 100644 --- a/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs +++ b/vsintegration/tests/Salsa/FSharpLanguageServiceTestable.fs @@ -113,7 +113,7 @@ type internal FSharpLanguageServiceTestable() as this = serviceProvider <- None /// Respond to project settings changes - member this.OnProjectSettingsChanged(site: Microsoft.VisualStudio.FSharp.LanguageService.IProjectSite) = + member this.OnProjectSettingsChanged(site:IProjectSite) = // The project may have changed its references. These would be represented as 'dependency files' of each source file. Each source file will eventually start listening // for changes to those dependencies, at which point we'll get OnDependencyFileCreateOrDelete notifications. Until then, though, we just 'make a note' that this project is out of date. bgRequests.AddOutOfDateProjectFileName(site.ProjectFileName) @@ -126,7 +126,7 @@ type internal FSharpLanguageServiceTestable() as this = | None -> () /// Respond to project being cleaned/rebuilt (any live type providers in the project should be refreshed) - member this.OnProjectCleaned(projectSite:Microsoft.VisualStudio.FSharp.LanguageService.IProjectSite) = + member this.OnProjectCleaned(projectSite:IProjectSite) = let enableInMemoryCrossProjectReferences = true let _, checkOptions = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(enableInMemoryCrossProjectReferences, (fun _ -> None), projectSite, serviceProvider.Value, None(*projectId*), "" ,None, None, false) this.FSharpChecker.NotifyProjectCleaned(checkOptions) |> Async.RunSynchronously @@ -147,12 +147,12 @@ type internal FSharpLanguageServiceTestable() as this = match result with | Some(hier,_) -> match hier with - | :? Microsoft.VisualStudio.FSharp.LanguageService.IProvideProjectSite as siteProvider -> + | :? IProvideProjectSite as siteProvider -> let site = siteProvider.GetProjectSite() site.AdviseProjectSiteChanges(FSharpConstants.FSharpLanguageServiceCallbackName, - new Microsoft.VisualStudio.FSharp.LanguageService.AdviseProjectSiteChanges(fun () -> this.OnProjectSettingsChanged(site))) + new AdviseProjectSiteChanges(fun () -> this.OnProjectSettingsChanged(site))) site.AdviseProjectSiteCleaned(FSharpConstants.FSharpLanguageServiceCallbackName, - new Microsoft.VisualStudio.FSharp.LanguageService.AdviseProjectSiteChanges(fun () -> this.OnProjectCleaned(site))) + new AdviseProjectSiteChanges(fun () -> this.OnProjectCleaned(site))) | _ -> // This can happen when the file is in a solution folder or in, say, a C# project. ()