Skip to content

Commit

Permalink
Implement Go To Definition - Native command.
Browse files Browse the repository at this point in the history
Fixes #4
Fixes #8
  • Loading branch information
SLaks committed Aug 27, 2014
1 parent 6ce75a4 commit 7e9aa7f
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 11 deletions.
12 changes: 3 additions & 9 deletions Ref12.Tests/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System;
using System.Globalization;
using System.Windows.Threading;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using SLaks.Ref12;

namespace Ref12.Tests {
static class Extensions {
Expand All @@ -17,13 +16,8 @@ public static SnapshotSpan FindSpan(this ITextView textView, string search) {
throw new ArgumentException("String " + search + " occurs multiple times. Please use a unique string");
return new SnapshotSpan(textView.TextBuffer.CurrentSnapshot, startIndex, search.Length);
}

public static void Execute(this IVsTextView textView, Enum commandId, IntPtr inHandle = default(IntPtr), IntPtr outHandle = default(IntPtr)) {
Execute((IOleCommandTarget)textView, commandId, inHandle, outHandle);
}
public static void Execute(this IOleCommandTarget target, Enum commandId, IntPtr inHandle = default(IntPtr), IntPtr outHandle = default(IntPtr)) {
var c = commandId.GetType().GUID;
ErrorHandler.ThrowOnFailure(target.Exec(ref c, Convert.ToUInt32(commandId, CultureInfo.InvariantCulture), 0, inHandle, outHandle));
public static void Execute(this IVsTextView textView, Enum commandId, uint execOptions = 0, IntPtr inHandle = default(IntPtr), IntPtr outHandle = default(IntPtr)) {
((IOleCommandTarget)textView).Execute(commandId, execOptions, inHandle, outHandle);
}


Expand Down
3 changes: 2 additions & 1 deletion Ref12/Commands/CommandTargetBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal abstract class CommandTargetBase<TCommandEnum> : IOleCommandTarget wher

public Guid CommandGroup { get; set; }
public ReadOnlyCollection<uint> CommandIds { get; private set; }
protected IOleCommandTarget NextTarget { get { return nextCommandTarget; } }

public CommandTargetBase(IVsTextView adapter, ITextView textView, params TCommandEnum[] commandIds) : this(adapter, textView, typeof(TCommandEnum).GUID, Array.ConvertAll(commandIds, e => Convert.ToUInt32(e))) { }
public CommandTargetBase(IVsTextView adapter, ITextView textView, Guid commandGroup, params uint[] commandIds) {
Expand Down Expand Up @@ -41,7 +42,7 @@ public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pv
return nextCommandTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
}

public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) {
public virtual int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) {
if (pguidCmdGroup != CommandGroup)
return nextCommandTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);

Expand Down
34 changes: 34 additions & 0 deletions Ref12/Commands/GoToDefintionNativeCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;

namespace SLaks.Ref12.Commands {
class GoToDefintionNativeCommand : CommandTargetBase<Ref12Command> {
public GoToDefintionNativeCommand(IVsTextView adapter, IWpfTextView textView) : base(adapter, textView, Ref12Command.GoToDefinitionNative) {
}
protected override bool Execute(Ref12Command commandId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
NextTarget.Execute(VSConstants.VSStd97CmdID.GotoDefn, nCmdexecopt, pvaIn, pvaOut);
return true;
}

protected override bool IsEnabled() {
// We override QueryStatus directly to pass the raw arguments
// to the inner command, so this method will never be called.
throw new NotImplementedException();
}
public override int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText) {
if (pguidCmdGroup != CommandGroup || cCmds != 1 || prgCmds[0].cmdID != CommandIds[0])
return NextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
var innerGuid = typeof(VSConstants.VSStd97CmdID).GUID;
var innerCommands = new[] { new OLECMD {
cmdID = (uint)VSConstants.VSStd97CmdID.GotoDefn,
cmdf=prgCmds[0].cmdf
} };
int result = NextTarget.QueryStatus(ref innerGuid, 1, innerCommands, pCmdText);
prgCmds[0].cmdf = innerCommands[0].cmdf;
return result;
}
}
}
4 changes: 4 additions & 0 deletions Ref12/Commands/TextViewListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public async void SubjectBuffersConnected(IWpfTextView textView, ConnectionReaso
if (!TextDocumentFactoryService.TryGetTextDocument(textView.TextDataModel.DocumentBuffer, out document))
return;

// Register the native command first, so that it ends up earlier in
// the command chain than our interceptor. This prevents the native
// comand from being intercepted too.
textView.Properties.GetOrCreateSingletonProperty(() => new GoToDefintionNativeCommand(textViewAdapter, textView));
textView.Properties.GetOrCreateSingletonProperty(() => new GoToDefinitionInterceptor(ReferenceProviders, ServiceProvider, textViewAdapter, textView, document));
}
public void SubjectBuffersDisconnected(IWpfTextView textView, ConnectionReason reason, Collection<ITextBuffer> subjectBuffers) {
Expand Down
10 changes: 9 additions & 1 deletion Ref12/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System;
using System.Globalization;
using System.Linq;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Projection;

namespace SLaks.Ref12 {
static class Extensions {
public static class Extensions {
public static SnapshotPoint? GetCaretPoint(this ITextView textView, Predicate<ITextSnapshot> match) {
CaretPosition position = textView.Caret.Position;
SnapshotSpan? snapshotSpan = textView.BufferGraph.MapUpOrDownToFirstMatch(new SnapshotSpan(position.BufferPosition, 0), match);
Expand All @@ -24,5 +27,10 @@ static class Extensions {
private static bool IsSourceBuffer(IProjectionBufferBase top, ITextBuffer bottom) {
return top.SourceBuffers.Contains(bottom) || top.SourceBuffers.Any((ITextBuffer tb) => tb is IProjectionBufferBase && IsSourceBuffer((IProjectionBufferBase)tb, bottom));
}

public static void Execute(this IOleCommandTarget target, Enum commandId, uint execOptions = 0, IntPtr inHandle = default(IntPtr), IntPtr outHandle = default(IntPtr)) {
var c = commandId.GetType().GUID;
ErrorHandler.ThrowOnFailure(target.Exec(ref c, Convert.ToUInt32(commandId, CultureInfo.InvariantCulture), execOptions, inHandle, outHandle));
}
}
}
1 change: 1 addition & 0 deletions Ref12/Ref12.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Commands\CommandTargetBase.cs" />
<Compile Include="Commands\GoToDefintionNativeCommand.cs" />
<Compile Include="Commands\GoToDefinitionInterceptor.cs" />
<Compile Include="Commands\TextViewListener.cs" />
<Compile Include="Extensions.cs" />
Expand Down

0 comments on commit 7e9aa7f

Please sign in to comment.