未验证 提交 90627079 编写于 作者: J Joey Robichaud 提交者: GitHub

Merge pull request #39419 from JoeRobich/fix-command-text

Remove shortcircuit of status query for commands with handlers.
......@@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Commanding;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor.Commanding.Commands;
using Microsoft.VisualStudio.Utilities;
using Roslyn.Utilities;
......@@ -42,28 +43,32 @@ internal class FindReferencesCommandHandler : ICommandHandler<FindReferencesComm
public CommandState GetCommandState(FindReferencesCommandArgs args)
{
return CommandState.Unspecified;
var (_, service) = GetDocumentAndService(args.SubjectBuffer.CurrentSnapshot);
return service != null
? CommandState.Available
: CommandState.Unavailable;
}
public bool ExecuteCommand(FindReferencesCommandArgs args, CommandExecutionContext context)
{
var subjectBuffer = args.SubjectBuffer;
// Get the selection that user has in our buffer (this also works if there
// is no selection and the caret is just at a single position). If we
// can't get the selection, or there are multiple spans for it (i.e. a
// box selection), then don't do anything.
var snapshotSpans = args.TextView.Selection.GetSnapshotSpansOnBuffer(args.SubjectBuffer);
var snapshotSpans = args.TextView.Selection.GetSnapshotSpansOnBuffer(subjectBuffer);
if (snapshotSpans.Count == 1)
{
var selectedSpan = snapshotSpans[0];
var snapshot = args.SubjectBuffer.CurrentSnapshot;
var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();
var (document, service) = GetDocumentAndService(subjectBuffer.CurrentSnapshot);
if (document != null)
{
// Do a find-refs at the *start* of the selection. That way if the
// user has selected a symbol that has another symbol touching it
// on the right (i.e. Goo++ ), then we'll do the find-refs on the
// symbol selected, not the symbol following.
if (TryExecuteCommand(selectedSpan.Start, document, context))
if (TryExecuteCommand(selectedSpan.Start, document, service, context))
{
return true;
}
......@@ -73,16 +78,20 @@ public bool ExecuteCommand(FindReferencesCommandArgs args, CommandExecutionConte
return false;
}
private bool TryExecuteCommand(int caretPosition, Document document, CommandExecutionContext context)
private (Document, IFindUsagesService) GetDocumentAndService(ITextSnapshot snapshot)
{
var streamingService = document.GetLanguageService<IFindUsagesService>();
var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();
return (document, document?.GetLanguageService<IFindUsagesService>());
}
private bool TryExecuteCommand(int caretPosition, Document document, IFindUsagesService findUsagesService, CommandExecutionContext context)
{
// See if we're running on a host that can provide streaming results.
// We'll both need a FAR service that can stream results to us, and
// a presenter that can accept streamed results.
if (streamingService != null && _streamingPresenter != null)
if (findUsagesService != null && _streamingPresenter != null)
{
_ = StreamingFindReferencesAsync(document, caretPosition, streamingService, _streamingPresenter);
_ = StreamingFindReferencesAsync(document, caretPosition, findUsagesService, _streamingPresenter);
return true;
}
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.OrganizeImports;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.OLE.Interop;
using Roslyn.Utilities;
......@@ -18,19 +15,7 @@ public int QueryStatus(ref Guid pguidCmdGroup, uint commandCount, OLECMD[] prgCm
// TODO: We'll need to extend the command handler interfaces at some point when we have commands that
// require enabling/disabling at some point. For now, we just enable the few that we care about.
if (pguidCmdGroup == VSConstants.VSStd2K)
{
return QueryVisualStudio2000Status(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
else if (pguidCmdGroup == Guids.CSharpGroupId)
{
return QueryCSharpGroupStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
else if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97)
{
return QueryVisualStudio97Status(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
else if (pguidCmdGroup == VSConstants.VsStd14)
if (pguidCmdGroup == VSConstants.VsStd14)
{
return QueryVisualStudio2014Status(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
......@@ -38,10 +23,6 @@ public int QueryStatus(ref Guid pguidCmdGroup, uint commandCount, OLECMD[] prgCm
{
return QueryAppCommandStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
else if (pguidCmdGroup == Guids.RoslynGroupId)
{
return QueryRoslynGroupStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
else
{
return NextCommandTarget.QueryStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
......@@ -74,109 +55,5 @@ private int QueryVisualStudio2014Status(ref Guid pguidCmdGroup, uint commandCoun
return NextCommandTarget.QueryStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
}
private int QueryVisualStudio97Status(ref Guid pguidCmdGroup, uint commandCount, OLECMD[] prgCmds, IntPtr commandText)
{
switch ((VSConstants.VSStd97CmdID)prgCmds[0].cmdID)
{
case VSConstants.VSStd97CmdID.GotoDefn:
case VSConstants.VSStd97CmdID.FindReferences:
case VSConstants.VSStd97CmdID.SyncClassView:
prgCmds[0].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
return VSConstants.S_OK;
default:
return NextCommandTarget.QueryStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
}
private int QueryCSharpGroupStatus(ref Guid pguidCmdGroup, uint commandCount, OLECMD[] prgCmds, IntPtr commandText)
{
switch (prgCmds[0].cmdID)
{
case ID.CSharpCommands.OrganizeRemoveAndSort:
case ID.CSharpCommands.ContextOrganizeRemoveAndSort:
prgCmds[0].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
return VSConstants.S_OK;
default:
return NextCommandTarget.QueryStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
}
private int QueryRoslynGroupStatus(ref Guid pguidCmdGroup, uint commandCount, OLECMD[] prgCmds, IntPtr commandText)
{
switch (prgCmds[0].cmdID)
{
case ID.RoslynCommands.GoToImplementation:
prgCmds[0].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
return VSConstants.S_OK;
default:
return NextCommandTarget.QueryStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
}
private int QueryVisualStudio2000Status(ref Guid pguidCmdGroup, uint commandCount, OLECMD[] prgCmds, IntPtr commandText)
{
switch ((VSConstants.VSStd2KCmdID)prgCmds[0].cmdID)
{
case VSConstants.VSStd2KCmdID.FORMATDOCUMENT:
prgCmds[0].cmdf = (uint)(OLECMDF.OLECMDF_ENABLED | OLECMDF.OLECMDF_SUPPORTED);
return VSConstants.S_OK;
default:
return NextCommandTarget.QueryStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
}
private int QuerySortAndRemoveUnusedUsingsStatus(ref Guid pguidCmdGroup, uint commandCount, OLECMD[] prgCmds, IntPtr commandText)
{
var textBuffer = GetSubjectBufferContainingCaret();
if (textBuffer != null)
{
if (CodeAnalysis.Workspace.TryGetWorkspace(textBuffer.AsTextContainer(), out var workspace))
{
var organizeImportsService = workspace.Services.GetLanguageServices(textBuffer).GetService<IOrganizeImportsService>();
if (organizeImportsService != null)
{
SetText(commandText, organizeImportsService.SortAndRemoveUnusedImportsDisplayStringWithAccelerator);
}
}
}
return NextCommandTarget.QueryStatus(ref pguidCmdGroup, commandCount, prgCmds, commandText);
}
private static unsafe void SetText(IntPtr pCmdTextInt, string text)
{
var pText = (OLECMDTEXT*)pCmdTextInt;
// If, for some reason, we don't get passed an array, we should just bail
if (pText->cwBuf == 0)
{
return;
}
fixed (char* pinnedText = text)
{
var src = pinnedText;
var dest = (char*)(&pText->rgwz);
// Don't copy too much, and make sure to reserve space for the terminator
var length = Math.Min(text.Length, (int)pText->cwBuf - 1);
for (var i = 0; i < length; i++)
{
*dest++ = *src++;
}
// Add terminating NUL
*dest = '\0';
pText->cwActual = (uint)length;
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册