Skip to content

Commit

Permalink
Re-add Execute/Debug in Interactive context menu (#1913)
Browse files Browse the repository at this point in the history
* Hook F# Interactive menu commands into language service

Rudimentary implementation

* Refactor

* Refactor again for better robustness
  • Loading branch information
dungpa authored and dsyme committed Dec 4, 2016
1 parent 30d197e commit 4b8aafd
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
6 changes: 6 additions & 0 deletions vsintegration/src/FSharp.Editor/FSharp.Editor.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Link>QuickInfo\QuickInfoProvider.fs</Link>
</Compile>
<Compile Include="ContentType.fs" />
<Compile Include="FsiCommandService.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(FSharpSourcesRoot)\fsharp\FSharp.Core\FSharp.Core.fsproj">
Expand All @@ -91,6 +92,11 @@
<Name>FSharp.LanguageService.Compiler</Name>
<Private>True</Private>
</ProjectReference>
<ProjectReference Include="..\FSharp.VS.FSI\FSharp.VS.FSI.fsproj">
<Name>FSharp.VS.FSI</Name>
<Project>{991dcf75-c2eb-42b6-9a0d-aa1d2409d519}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib" />
Expand Down
87 changes: 87 additions & 0 deletions vsintegration/src/FSharp.Editor/FsiCommandService.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
namespace Microsoft.VisualStudio.FSharp.Editor

open System
open Microsoft.VisualStudio.Text.Editor
open Microsoft.VisualStudio.OLE.Interop
open System.ComponentModel.Composition
open Microsoft.VisualStudio
open Microsoft.VisualStudio.Editor
open Microsoft.VisualStudio.TextManager.Interop
open Microsoft.VisualStudio.Utilities
open Microsoft.VisualStudio.Shell
open Microsoft.VisualStudio.Shell.Interop
open Microsoft.VisualStudio.FSharp.Interactive
open EnvDTE

type FsiCommandFilter(serviceProvider: System.IServiceProvider) =
let projectSystemPackage =
lazy(
let shell = serviceProvider.GetService(typeof<SVsShell>) :?> IVsShell
let packageToBeLoadedGuid = ref (Guid "{91a04a73-4f2c-4e7c-ad38-c1a68e7da05c}") // FSharp ProjectSystem guid
match shell.LoadPackage packageToBeLoadedGuid with
| VSConstants.S_OK, pkg ->
pkg :?> Package
| _ -> null)

let mutable nextTarget = null

member x.AttachToViewAdapter (viewAdapter: IVsTextView) =
match viewAdapter.AddCommandFilter x with
| VSConstants.S_OK, next ->
nextTarget <- next
| errorCode, _ ->
ErrorHandler.ThrowOnFailure errorCode |> ignore

interface IOleCommandTarget with
member x.Exec (pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut) =
if pguidCmdGroup = VSConstants.VsStd11 then
if nCmdId = uint32 VSConstants.VSStd11CmdID.ExecuteSelectionInInteractive then
Hooks.OnMLSend projectSystemPackage.Value FsiEditorSendAction.ExecuteSelection null null
elif nCmdId = uint32 VSConstants.VSStd11CmdID.ExecuteLineInInteractive then
Hooks.OnMLSend projectSystemPackage.Value FsiEditorSendAction.ExecuteLine null null
VSConstants.S_OK
elif pguidCmdGroup = Guids.guidInteractive then
if nCmdId = uint32 Guids.cmdIDDebugSelection then
Hooks.OnMLSend projectSystemPackage.Value FsiEditorSendAction.DebugSelection null null
VSConstants.S_OK
elif isNotNull nextTarget then
nextTarget.Exec(&pguidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut)
else
VSConstants.E_FAIL

member x.QueryStatus (pguidCmdGroup, cCmds, prgCmds, pCmdText) =
if pguidCmdGroup = VSConstants.VsStd11 then
for i = 0 to int cCmds-1 do
if prgCmds.[i].cmdID = uint32 VSConstants.VSStd11CmdID.ExecuteSelectionInInteractive then
prgCmds.[i].cmdf <- uint32 (OLECMDF.OLECMDF_SUPPORTED ||| OLECMDF.OLECMDF_ENABLED)
elif prgCmds.[i].cmdID = uint32 VSConstants.VSStd11CmdID.ExecuteLineInInteractive then
prgCmds.[i].cmdf <- uint32 (OLECMDF.OLECMDF_SUPPORTED ||| OLECMDF.OLECMDF_ENABLED ||| OLECMDF.OLECMDF_DEFHIDEONCTXTMENU)
VSConstants.S_OK
elif pguidCmdGroup = Guids.guidInteractive then
for i = 0 to int cCmds-1 do
if prgCmds.[i].cmdID = uint32 Guids.cmdIDDebugSelection then
let dbgState = Hooks.GetDebuggerState projectSystemPackage.Value
if dbgState = FsiDebuggerState.AttachedNotToFSI then
prgCmds.[i].cmdf <- uint32 OLECMDF.OLECMDF_INVISIBLE
else
prgCmds.[i].cmdf <- uint32 (OLECMDF.OLECMDF_SUPPORTED ||| OLECMDF.OLECMDF_ENABLED)
VSConstants.S_OK
elif isNotNull nextTarget then
nextTarget.QueryStatus(&pguidCmdGroup, cCmds, prgCmds, pCmdText)
else
VSConstants.E_FAIL

[<Export(typeof<IWpfTextViewCreationListener>)>]
[<ContentType("F#")>]
[<TextViewRole(PredefinedTextViewRoles.PrimaryDocument)>]
type FsiCommandFilterProvider [<ImportingConstructor>]
([<Import(typeof<SVsServiceProvider>)>] serviceProvider: System.IServiceProvider,
editorFactory: IVsEditorAdaptersFactoryService) =
interface IWpfTextViewCreationListener with
member __.TextViewCreated(textView) =
match editorFactory.GetViewAdapter(textView) with
| null -> ()
| textViewAdapter ->
let commandFilter = FsiCommandFilter serviceProvider
commandFilter.AttachToViewAdapter textViewAdapter

1 change: 1 addition & 0 deletions vsintegration/src/FSharp.VS.FSI/AssemblyInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ open Microsoft.VisualStudio.Shell

[<assembly: AssemblyCulture("")>]

[<assembly: InternalsVisibleTo("FSharp.Editor, PublicKey=002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293")>]
[<assembly: InternalsVisibleTo("FSharp.LanguageService, PublicKey=002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293")>]
[<assembly: InternalsVisibleTo("FSharp.LanguageService.Base, PublicKey=002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293")>]
[<assembly: InternalsVisibleTo("FSharp.ProjectSystem.FSharp, PublicKey=002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293")>]
Expand Down

0 comments on commit 4b8aafd

Please sign in to comment.