Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
As lâmpadas são ícones no editor do Visual Studio que se expandem para exibir um conjunto de ações, por exemplo, correções para problemas identificados pelos analisadores de código internos ou refatoração de código.
Nos editores Visual C# e Visual Basic, você também pode usar a plataforma de compilador .NET ("Roslyn") para escrever e empacotar seus próprios analisadores de código com ações que exibem lâmpadas automaticamente. Para mais informações, consulte:
Como: Escrever um diagnóstico do Visual Basic e correção de código
Outras linguagens, como C++, também fornecem lâmpadas para algumas ações rápidas, como uma sugestão para criar uma implementação de stub dessa função.
Veja como é uma lâmpada. Em um projeto de Visual Basic ou Visual C#, um rabisco vermelho aparece debaixo de um nome de variável quando é considerado inválido. Se passar o rato sobre o identificador inválido, aparece uma lâmpada perto do cursor.
Se clicar na seta para baixo junto à lâmpada, é apresentado um conjunto de ações sugeridas, juntamente com uma pré-visualização da ação selecionada. Nesse caso, ele mostra as alterações que são feitas no seu código se você executar a ação.
Você pode usar lâmpadas para fornecer suas próprias ações sugeridas. Por exemplo, pode-se fornecer ações de modo a mover chavetas para uma nova linha ou para o final da linha anterior. O passo a passo a seguir mostra como criar uma lâmpada que aparece na palavra atual e tem duas ações sugeridas: Converter em maiúsculas e Converter em minúsculas.
Criar um projeto MEF (Managed Extensibility Framework)
Crie um projeto C# VSIX. (Na caixa de diálogo New Project, selecione Visual C# / Extensibilitye, em seguida, VSIX Project.) Nomeie a solução
LightBulbTest.Adicione um modelo de item de Classificador do Editor ao projeto. Para obter mais informações, consulte Criar uma extensão com um modelo de item de editor.
Exclua os arquivos de classe existentes.
Adicione a seguinte referência ao projeto e defina Copy Local como
False:Microsoft.VisualStudio.Language.Intellisense
Adicione um novo arquivo de classe e nomeie-o LightBulbTest.
Adicione o seguinte usando diretivas:
using System; using System.Linq; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Text.Operations; using Microsoft.VisualStudio.Utilities; using System.ComponentModel.Composition; using System.Threading;
Implementar o fornecedor de fonte de lâmpadas
No arquivo de classe LightBulbTest.cs, exclua a classe LightBulbTest. Adicione uma classe chamada TestSuggestedActionsSourceProvider que implementa ISuggestedActionsSourceProvider. Exporte-o com o nome Teste Ações Sugeridas e uma ContentTypeAttribute de "texto".
[Export(typeof(ISuggestedActionsSourceProvider))] [Name("Test Suggested Actions")] [ContentType("text")] internal class TestSuggestedActionsSourceProvider : ISuggestedActionsSourceProviderDentro da classe do provedor de origem, importe o ITextStructureNavigatorSelectorService e adicione-o como uma propriedade.
[Import(typeof(ITextStructureNavigatorSelectorService))] internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }Implemente o método CreateSuggestedActionsSource para retornar um objeto ISuggestedActionsSource. A fonte é discutida na próxima seção.
public ISuggestedActionsSource CreateSuggestedActionsSource(ITextView textView, ITextBuffer textBuffer) { if (textBuffer == null || textView == null) { return null; } return new TestSuggestedActionsSource(this, textView, textBuffer); }
Implementar o ISuggestedActionSource
A fonte de ação sugerida é responsável por coletar o conjunto de ações sugeridas e adicioná-las no contexto certo. Nesse caso, o contexto é a palavra atual e as ações sugeridas são UpperCaseSuggestedAction e LowerCaseSuggestedAction, que serão discutidas na seção a seguir.
Adicione uma classe TestSuggestedActionsSource que implementa ISuggestedActionsSource.
internal class TestSuggestedActionsSource : ISuggestedActionsSourceAdicione campos privados somente leitura para o provedor de fonte de ação sugerido, o buffer de texto e a exibição de texto.
private readonly TestSuggestedActionsSourceProvider m_factory; private readonly ITextBuffer m_textBuffer; private readonly ITextView m_textView;Adicione um construtor que defina os campos privados.
public TestSuggestedActionsSource(TestSuggestedActionsSourceProvider testSuggestedActionsSourceProvider, ITextView textView, ITextBuffer textBuffer) { m_factory = testSuggestedActionsSourceProvider; m_textBuffer = textBuffer; m_textView = textView; }Adicione um método privado que retorna a palavra que está atualmente sob o cursor. O método a seguir examina a localização atual do cursor e pergunta ao navegador de estrutura de texto a extensão da palavra. Se o cursor estiver em uma palavra, o TextExtent será retornado no parâmetro out; caso contrário, o parâmetro
outénulle o método retornafalse.private bool TryGetWordUnderCaret(out TextExtent wordExtent) { ITextCaret caret = m_textView.Caret; SnapshotPoint point; if (caret.Position.BufferPosition > 0) { point = caret.Position.BufferPosition - 1; } else { wordExtent = default(TextExtent); return false; } ITextStructureNavigator navigator = m_factory.NavigatorService.GetTextStructureNavigator(m_textBuffer); wordExtent = navigator.GetExtentOfWord(point); return true; }Implemente o método HasSuggestedActionsAsync. O editor chama esse método para descobrir se a lâmpada deve ser exibida. Esta chamada é feita com frequência, por exemplo, sempre que o cursor se move de uma linha para outra, ou quando o rato passa sobre um sublinhar de erro. É assíncrono para permitir que outras operações da interface do usuário continuem enquanto esse método está funcionando. Na maioria dos casos, esse método precisa executar alguma análise e análise da linha atual, portanto, o processamento pode levar algum tempo.
Nessa implementação, ele obtém o TextExtent de forma assíncrona e determina se a extensão é significativa, como em, se ele tem algum texto diferente de espaço em branco.
public Task<bool> HasSuggestedActionsAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) { return Task.Factory.StartNew(() => { TextExtent extent; if (TryGetWordUnderCaret(out extent)) { // don't display the action if the extent has whitespace return extent.IsSignificant; } return false; }); }Implemente o método GetSuggestedActions, que retorna uma matriz de objetos SuggestedActionSet que contêm os diferentes objetos ISuggestedAction. Este método é invocado quando a lâmpada é expandida.
Advertência
Você deve certificar-se de que as implementações de
HasSuggestedActionsAsync()eGetSuggestedActions()sejam consistentes; ou seja, seHasSuggestedActionsAsync()retornatrue, entãoGetSuggestedActions()deve ter algumas ações para exibir. Em muitos casos,HasSuggestedActionsAsync()é chamado pouco antesGetSuggestedActions(), mas nem sempre é esse o caso. Por exemplo, se o usuário invocar as ações da lâmpada pressionando (CTRL+ .) somenteGetSuggestedActions()será chamado.public IEnumerable<SuggestedActionSet> GetSuggestedActions(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) { TextExtent extent; if (TryGetWordUnderCaret(out extent) && extent.IsSignificant) { ITrackingSpan trackingSpan = range.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive); var upperAction = new UpperCaseSuggestedAction(trackingSpan); var lowerAction = new LowerCaseSuggestedAction(trackingSpan); return new SuggestedActionSet[] { new SuggestedActionSet(new ISuggestedAction[] { upperAction, lowerAction }) }; } return Enumerable.Empty<SuggestedActionSet>(); }Defina um evento
SuggestedActionsChanged.public event EventHandler<EventArgs> SuggestedActionsChanged;Para concluir a implementação, adicione implementações para os métodos
Dispose()eTryGetTelemetryId(). Você não quer fazer telemetria, então basta retornarfalsee definir o GUID comoEmpty.public void Dispose() { } public bool TryGetTelemetryId(out Guid telemetryId) { // This is a sample provider and doesn't participate in LightBulb telemetry telemetryId = Guid.Empty; return false; }
Implementar funcionalidades de lâmpadas
No projeto, adicione uma referência a Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.dll e defina Copy Local como
False.Crie duas classes, a primeira com o nome
UpperCaseSuggestedActione a segunda com o nomeLowerCaseSuggestedAction. Ambas classes implementam ISuggestedAction.internal class UpperCaseSuggestedAction : ISuggestedAction internal class LowerCaseSuggestedAction : ISuggestedActionAmbas as classes são iguais, exceto que uma chama ToUpper e a outra chama ToLower. As etapas a seguir abrangem apenas a classe de ação maiúscula, mas você deve implementar ambas as classes. Use as etapas para implementar a ação em maiúsculas como um padrão para implementar a ação em minúsculas.
Adicione as seguintes diretivas de uso para estas classes:
using Microsoft.VisualStudio.Imaging.Interop; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media;Declare um conjunto de campos privados.
private ITrackingSpan m_span; private string m_upper; private string m_display; private ITextSnapshot m_snapshot;Adicione um construtor que defina os campos.
public UpperCaseSuggestedAction(ITrackingSpan span) { m_span = span; m_snapshot = span.TextBuffer.CurrentSnapshot; m_upper = span.GetText(m_snapshot).ToUpper(); m_display = string.Format("Convert '{0}' to upper case", span.GetText(m_snapshot)); }Implemente o método GetPreviewAsync para que ele exiba a visualização da ação.
public Task<object> GetPreviewAsync(CancellationToken cancellationToken) { var textBlock = new TextBlock(); textBlock.Padding = new Thickness(5); textBlock.Inlines.Add(new Run() { Text = m_upper }); return Task.FromResult<object>(textBlock); }Implemente o método GetActionSetsAsync para que ele retorne uma enumeração SuggestedActionSet vazia.
public Task<IEnumerable<SuggestedActionSet>> GetActionSetsAsync(CancellationToken cancellationToken) { return Task.FromResult<IEnumerable<SuggestedActionSet>>(null); }Implemente as propriedades da seguinte maneira.
public bool HasActionSets { get { return false; } } public string DisplayText { get { return m_display; } } public ImageMoniker IconMoniker { get { return default(ImageMoniker); } } public string IconAutomationText { get { return null; } } public string InputGestureText { get { return null; } } public bool HasPreview { get { return true; } }Implemente o método Invoke substituindo o texto na extensão por seu equivalente em maiúsculas.
public void Invoke(CancellationToken cancellationToken) { m_span.TextBuffer.Replace(m_span.GetSpan(m_snapshot), m_upper); }Advertência
Não se espera que a ação da lâmpada método Invoke mostre a interface do usuário. Se sua ação exibir uma nova interface do usuário (por exemplo, uma caixa de diálogo de visualização ou seleção), não exiba a interface do usuário diretamente de dentro do método Invoke, mas agende para exibir sua interface do usuário depois de retornar de Invoke.
Para concluir a implementação, adicione os métodos
Dispose()eTryGetTelemetryId().public void Dispose() { } public bool TryGetTelemetryId(out Guid telemetryId) { // This is a sample action and doesn't participate in LightBulb telemetry telemetryId = Guid.Empty; return false; }Não se esqueça de fazer a mesma coisa para
LowerCaseSuggestedAction, mudar o texto de exibição para "Converter '{0}' para letras minúsculas" e a chamada ToUpper para ToLower.
Compilar e testar o código
Para testar esse código, crie a solução LightBulbTest e execute-a na instância Experimental.
Crie a solução.
Quando você executa esse projeto no depurador, uma segunda instância do Visual Studio é iniciada.
Crie um arquivo de texto e digite algum texto. Deverá ver uma lâmpada à esquerda do texto.
Aponte para a lâmpada. Você verá uma seta para baixo.
Quando você clica na lâmpada, duas ações sugeridas devem ser exibidas, juntamente com a visualização da ação selecionada.
Se você clicar na primeira ação, todo o texto da palavra atual deverá ser convertido em maiúsculas. Se você clicar na segunda ação, todo o texto deverá ser convertido em minúsculas.