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

Add fsx files to workspaces #1612

Merged
merged 3 commits into from
Oct 15, 2016
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
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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be handling exceptions from reading files on disk?

Should it get the text from the in-editor file, since it's in the RDT now.

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