Skip to content
This repository was archived by the owner on Dec 23, 2024. It is now read-only.

Commit

Permalink
Add fsx files to workspaces (dotnet#1612)
Browse files Browse the repository at this point in the history
* Add fsx files to workspaces

* Stop passing project output paths to CPS

* Read script file contents from memory (on workspace initialization)
  • Loading branch information
OmarTawfik authored and KevinRansom committed Oct 15, 2016
1 parent 8b434e0 commit 2a9b5ef
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 34 deletions.
96 changes: 62 additions & 34 deletions vsintegration/src/FSharp.Editor/LanguageService.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ open System.Runtime.InteropServices
open System.Linq
open System.IO

open Microsoft.FSharp.Compiler.CompileOps
open Microsoft.FSharp.Compiler.SourceCodeServices

open Microsoft.CodeAnalysis
open Microsoft.CodeAnalysis.Editor.Options
open Microsoft.VisualStudio
open Microsoft.VisualStudio.Editor
open Microsoft.VisualStudio.TextManager.Interop
open Microsoft.VisualStudio.LanguageServices
open Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService
open Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
Expand Down Expand Up @@ -62,47 +65,72 @@ type internal FSharpLanguageService(package : FSharpPackage) =

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

override this.SetupNewTextView(view) =
base.SetupNewTextView(view)
let workspace = this.Package.ComponentModel.GetService<VisualStudioWorkspaceImpl>();
override this.SetupNewTextView(textView) =
base.SetupNewTextView(textView)
let workspace = this.Package.ComponentModel.GetService<VisualStudioWorkspaceImpl>()

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

let (_, buffer) = view.GetBuffer()
let filename = VsTextLines.GetFilename buffer
let result = VsRunningDocumentTable.FindDocumentWithoutLocking(package.RunningDocumentTable,filename)
match result with
| Some (hier, _) ->
match hier with
| :? IProvideProjectSite as siteProvider ->
let site = siteProvider.GetProjectSite()
let projectGuid = Guid(site.ProjectGuid)
let projectFileName = site.ProjectFileName()
let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(projectFileName, projectFileName)

let options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(site, site.ProjectFileName())
if not (optionsCache.ContainsKey(projectId)) then
optionsCache.Add(projectId, options)

if obj.ReferenceEquals(workspace.ProjectTracker.GetProject(projectId), null) then
let projectContextFactory = this.Package.ComponentModel.GetService<IWorkspaceProjectContextFactory>();
let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider)
let outputFlag = site.CompilerFlags() |> Seq.pick(fun flag ->
if flag.StartsWith("-o:") then Some(flag.Substring(3))
else if flag.StartsWith("--out:") then Some(flag.Substring(6))
else None)
let outputPath = if Path.IsPathRooted(outputFlag) then outputFlag else Path.Combine(Path.GetDirectoryName(projectFileName), outputFlag)

let projectContext = projectContextFactory.CreateProjectContext(FSharpCommonConstants.FSharpLanguageName, projectFileName, projectFileName, projectGuid, hier, outputPath, errorReporter)
let project = projectContext :?> AbstractProject

this.SyncProject(project, projectContext, site)
site.AdviseProjectSiteChanges(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> this.SyncProject(project, projectContext, site)))
site.AdviseProjectSiteClosed(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> project.Disconnect()))
match textView.GetBuffer() with
| (VSConstants.S_OK, textLines) ->
let filename = VsTextLines.GetFilename textLines
match VsRunningDocumentTable.FindDocumentWithoutLocking(package.RunningDocumentTable,filename) with
| Some (hier, _) ->
if IsScript(filename) then
let editorAdapterFactoryService = this.Package.ComponentModel.GetService<IVsEditorAdaptersFactoryService>()
let fileContents = VsTextLines.GetFileContents(textLines, editorAdapterFactoryService)
this.SetupStandAloneFile(filename, fileContents, workspace, hier)
else
match hier with
| :? IProvideProjectSite as siteProvider -> this.SetupProjectFile(siteProvider, workspace)
| _ -> ()
| _ -> ()
| _ -> ()

member this.SetupProjectFile(siteProvider: IProvideProjectSite, workspace: VisualStudioWorkspaceImpl) =
let site = siteProvider.GetProjectSite()
let projectGuid = Guid(site.ProjectGuid)
let projectFileName = site.ProjectFileName()
let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(projectFileName, projectFileName)

let options = ProjectSitesAndFiles.GetProjectOptionsForProjectSite(site, site.ProjectFileName())
if not (optionsCache.ContainsKey(projectId)) then
optionsCache.Add(projectId, options)

match workspace.ProjectTracker.GetProject(projectId) with
| null ->
let projectContextFactory = this.Package.ComponentModel.GetService<IWorkspaceProjectContextFactory>();
let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider)

let projectContext = projectContextFactory.CreateProjectContext(FSharpCommonConstants.FSharpLanguageName, projectFileName, projectFileName, projectGuid, siteProvider, null, errorReporter)
let project = projectContext :?> AbstractProject

this.SyncProject(project, projectContext, site)
site.AdviseProjectSiteChanges(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> this.SyncProject(project, projectContext, site)))
site.AdviseProjectSiteClosed(FSharpCommonConstants.FSharpLanguageServiceCallbackName, AdviseProjectSiteChanges(fun () -> project.Disconnect()))
| _ -> ()

member this.SetupStandAloneFile(fileName: string, fileContents: string, workspace: VisualStudioWorkspaceImpl, hier: IVsHierarchy) =
let options = FSharpChecker.Instance.GetProjectOptionsFromScript(fileName, fileContents, DateTime.Now, [| |]) |> Async.RunSynchronously
let projectId = workspace.ProjectTracker.GetOrCreateProjectIdForPath(options.ProjectFileName, options.ProjectFileName)

if not(optionsCache.ContainsKey(projectId)) then
optionsCache.Add(projectId, options)

if obj.ReferenceEquals(workspace.ProjectTracker.GetProject(projectId), null) then
let projectContextFactory = this.Package.ComponentModel.GetService<IWorkspaceProjectContextFactory>();
let errorReporter = ProjectExternalErrorReporter(projectId, "FS", this.SystemServiceProvider)

let projectContext = projectContextFactory.CreateProjectContext(FSharpCommonConstants.FSharpLanguageName, options.ProjectFileName, options.ProjectFileName, projectId.Id, hier, null, errorReporter)
projectContext.AddSourceFile(fileName)

let project = projectContext :?> AbstractProject
let document = project.GetCurrentDocumentFromPath(fileName)

document.Closing.Add(fun _ -> project.Disconnect())


and [<Guid(FSharpCommonConstants.packageGuidString)>]
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".fs", 97)>]
[<ProvideEditorExtension(FSharpCommonConstants.editorFactoryGuidString, ".fsi", 97)>]
Expand Down
6 changes: 6 additions & 0 deletions vsintegration/src/FSharp.LanguageService/Vs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ open System.Collections
open System.Collections.Generic
open System.Reflection
open Microsoft.VisualStudio
open Microsoft.VisualStudio.Editor
open Microsoft.VisualStudio.Shell
open Microsoft.VisualStudio.Shell.Interop
open Microsoft.VisualStudio.Text
Expand Down Expand Up @@ -177,6 +178,11 @@ module internal VsTextLines =
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 =
Expand Down

0 comments on commit 2a9b5ef

Please sign in to comment.