Skip to content

Commit 2a9b5ef

Browse files
OmarTawfikKevinRansom
authored andcommitted
Add fsx files to workspaces (#1612)
* Add fsx files to workspaces * Stop passing project output paths to CPS * Read script file contents from memory (on workspace initialization)
1 parent 8b434e0 commit 2a9b5ef

File tree

2 files changed

+68
-34
lines changed

2 files changed

+68
-34
lines changed

vsintegration/src/FSharp.Editor/LanguageService.fs

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ open System.Runtime.InteropServices
88
open System.Linq
99
open System.IO
1010

11+
open Microsoft.FSharp.Compiler.CompileOps
1112
open Microsoft.FSharp.Compiler.SourceCodeServices
1213

1314
open Microsoft.CodeAnalysis
1415
open Microsoft.CodeAnalysis.Editor.Options
1516
open Microsoft.VisualStudio
17+
open Microsoft.VisualStudio.Editor
18+
open Microsoft.VisualStudio.TextManager.Interop
1619
open Microsoft.VisualStudio.LanguageServices
1720
open Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
1821
open Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
@@ -62,47 +65,72 @@ type internal FSharpLanguageService(package : FSharpPackage) =
6265

6366
override this.CreateContext(_,_,_,_,_) = raise(System.NotImplementedException())
6467

65-
override this.SetupNewTextView(view) =
66-
base.SetupNewTextView(view)
67-
let workspace = this.Package.ComponentModel.GetService<VisualStudioWorkspaceImpl>();
68+
override this.SetupNewTextView(textView) =
69+
base.SetupNewTextView(textView)
70+
let workspace = this.Package.ComponentModel.GetService<VisualStudioWorkspaceImpl>()
6871

6972
// FSROSLYNTODO: Hide navigation bars for now. Enable after adding tests
7073
workspace.Options <- workspace.Options.WithChangedOption(NavigationBarOptions.ShowNavigationBar, FSharpCommonConstants.FSharpLanguageName, false)
7174

72-
let (_, buffer) = view.GetBuffer()
73-
let filename = VsTextLines.GetFilename buffer
74-
let result = VsRunningDocumentTable.FindDocumentWithoutLocking(package.RunningDocumentTable,filename)
75-
match result with
76-
| Some (hier, _) ->
77-
match hier with
78-
| :? IProvideProjectSite as siteProvider ->
79-
let site = siteProvider.GetProjectSite()
80-
let projectGuid = Guid(site.ProjectGuid)
81-
let projectFileName = site.ProjectFileName()
82-
let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(projectFileName, projectFileName)
83-
84-
let options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(site, site.ProjectFileName())
85-
if not (optionsCache.ContainsKey(projectId)) then
86-
optionsCache.Add(projectId, options)
87-
88-
if obj.ReferenceEquals(workspace.ProjectTracker.GetProject(projectId), null) then
89-
let projectContextFactory = this.Package.ComponentModel.GetService<IWorkspaceProjectContextFactory>();
90-
let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider)
91-
let outputFlag = site.CompilerFlags() |> Seq.pick(fun flag ->
92-
if flag.StartsWith("-o:") then Some(flag.Substring(3))
93-
else if flag.StartsWith("--out:") then Some(flag.Substring(6))
94-
else None)
95-
let outputPath = if Path.IsPathRooted(outputFlag) then outputFlag else Path.Combine(Path.GetDirectoryName(projectFileName), outputFlag)
96-
97-
let projectContext = projectContextFactory.CreateProjectContext(FSharpCommonConstants.FSharpLanguageName, projectFileName, projectFileName, projectGuid, hier, outputPath, errorReporter)
98-
let project = projectContext :?> AbstractProject
99-
100-
this.SyncProject(project, projectContext, site)
101-
site.AdviseProjectSiteChanges(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> this.SyncProject(project, projectContext, site)))
102-
site.AdviseProjectSiteClosed(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> project.Disconnect()))
75+
match textView.GetBuffer() with
76+
| (VSConstants.S_OK, textLines) ->
77+
let filename = VsTextLines.GetFilename textLines
78+
match VsRunningDocumentTable.FindDocumentWithoutLocking(package.RunningDocumentTable,filename) with
79+
| Some (hier, _) ->
80+
if IsScript(filename) then
81+
let editorAdapterFactoryService = this.Package.ComponentModel.GetService<IVsEditorAdaptersFactoryService>()
82+
let fileContents = VsTextLines.GetFileContents(textLines, editorAdapterFactoryService)
83+
this.SetupStandAloneFile(filename, fileContents, workspace, hier)
84+
else
85+
match hier with
86+
| :? IProvideProjectSite as siteProvider -> this.SetupProjectFile(siteProvider, workspace)
87+
| _ -> ()
10388
| _ -> ()
10489
| _ -> ()
10590

91+
member this.SetupProjectFile(siteProvider: IProvideProjectSite, workspace: VisualStudioWorkspaceImpl) =
92+
let site = siteProvider.GetProjectSite()
93+
let projectGuid = Guid(site.ProjectGuid)
94+
let projectFileName = site.ProjectFileName()
95+
let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(projectFileName, projectFileName)
96+
97+
let options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(site, site.ProjectFileName())
98+
if not (optionsCache.ContainsKey(projectId)) then
99+
optionsCache.Add(projectId, options)
100+
101+
match workspace.ProjectTracker.GetProject(projectId) with
102+
| null ->
103+
let projectContextFactory = this.Package.ComponentModel.GetService<IWorkspaceProjectContextFactory>();
104+
let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider)
105+
106+
let projectContext = projectContextFactory.CreateProjectContext(FSharpCommonConstants.FSharpLanguageName, projectFileName, projectFileName, projectGuid, siteProvider, null, errorReporter)
107+
let project = projectContext :?> AbstractProject
108+
109+
this.SyncProject(project, projectContext, site)
110+
site.AdviseProjectSiteChanges(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> this.SyncProject(project, projectContext, site)))
111+
site.AdviseProjectSiteClosed(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> project.Disconnect()))
112+
| _ -> ()
113+
114+
member this.SetupStandAloneFile(fileName: string, fileContents: string, workspace: VisualStudioWorkspaceImpl, hier: IVsHierarchy) =
115+
let options = FSharpChecker.Instance.GetProjectOptionsFromScript(fileName, fileContents, DateTime.Now, [| |]) |> Async.RunSynchronously
116+
let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(options.ProjectFileName, options.ProjectFileName)
117+
118+
if not(optionsCache.ContainsKey(projectId)) then
119+
optionsCache.Add(projectId, options)
120+
121+
if obj.ReferenceEquals(workspace.ProjectTracker.GetProject(projectId), null) then
122+
let projectContextFactory = this.Package.ComponentModel.GetService<IWorkspaceProjectContextFactory>();
123+
let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider)
124+
125+
let projectContext = projectContextFactory.CreateProjectContext(FSharpCommonConstants.FSharpLanguageName, options.ProjectFileName, options.ProjectFileName, projectId.Id, hier, null, errorReporter)
126+
projectContext.AddSourceFile(fileName)
127+
128+
let project = projectContext :?> AbstractProject
129+
let document = project.GetCurrentDocumentFromPath(fileName)
130+
131+
document.Closing.Add(fun _ -> project.Disconnect())
132+
133+
106134
and [<Guid(FSharpCommonConstants.packageGuidString)>]
107135
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".fs", 97)>]
108136
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".fsi", 97)>]

vsintegration/src/FSharp.LanguageService/Vs.fs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ open System.Collections
88
open System.Collections.Generic
99
open System.Reflection
1010
open Microsoft.VisualStudio
11+
open Microsoft.VisualStudio.Editor
1112
open Microsoft.VisualStudio.Shell
1213
open Microsoft.VisualStudio.Shell.Interop
1314
open Microsoft.VisualStudio.Text
@@ -177,6 +178,11 @@ module internal VsTextLines =
177178
let GetFilename(buffer : IVsTextLines) =
178179
let ud = (box buffer) :?> IVsUserData
179180
VsUserData.GetBufferMonker(ud)
181+
182+
/// Get the string contents of a given buffer (the current snapshot).
183+
let GetFileContents(buffer: IVsTextBuffer, editorAdaptersFactoryService: IVsEditorAdaptersFactoryService) =
184+
let dataBuffer = editorAdaptersFactoryService.GetDataBuffer(buffer)
185+
dataBuffer.CurrentSnapshot.GetText()
180186

181187

182188
module internal VsRunningDocumentTable =

0 commit comments

Comments
 (0)