İzlenecek yol: Ampul önerilerini görüntüleme
Ampuller, Visual Studio düzenleyicisinde yerleşik kod çözümleyicileri veya kod yeniden düzenleme tarafından tanımlanan sorunlara yönelik düzeltmeler gibi bir dizi eylemi görüntüleyecek şekilde genişletilen simgelerdir.
Visual C# ve Visual Basic düzenleyicilerinde, ampulleri otomatik olarak görüntüleyen eylemlerle kendi kod çözümleyicilerinizi yazmak ve paketlemek için .NET Derleyici Platformu'nu ("Roslyn") de kullanabilirsiniz. Daha fazla bilgi için bkz.
Nasıl Yapılır: Visual Basic tanılama ve kod düzeltmesi yazma
C++ gibi diğer diller de bu işlevin saplama uygulamasını oluşturma önerisi gibi bazı hızlı işlemler için ampuller sağlar.
Ampul şöyle görünür. Visual Basic veya Visual C# projesinde, geçersiz olduğunda değişken adının altında kırmızı dalgalı bir dalgalı çizgi görünür. Fareyle geçersiz tanımlayıcının üzerine gelirseniz imlecin yanında bir ampul görünür.
Ampulün yanındaki aşağı oka tıklarsanız, seçilen eylemin önizlemesiyle birlikte bir dizi önerilen eylem görüntülenir. Bu durumda, eylemi yürütürseniz kodunuzda yapılan değişiklikleri gösterir.
Ampulleri kendi önerilen eylemlerinizi sağlamak için kullanabilirsiniz. Örneğin, küme ayraçlarını açma küme ayraçlarını yeni bir satıra taşımaya veya önceki satırın sonuna taşımaya yönelik eylemler sağlayabilirsiniz. Aşağıdaki kılavuzda, geçerli sözcükte görünen ve iki önerilen eylem içeren bir ampulün nasıl oluşturulacağı gösterilmektedir: Büyük harfe dönüştür ve Küçük harfe dönüştür.
Yönetilen Genişletilebilirlik Çerçevesi (MEF) projesi oluşturma
C# VSIX projesi oluşturun. (Yeni Proje iletişim kutusu, Visual C# / Genişletilebilirlik'i ve ardından VSIX Projesi'ni seçin.) Çözümü
LightBulbTest
olarak adlandırın.Projeye bir Düzenleyici Sınıflandırıcısı öğesi şablonu ekleyin. Daha fazla bilgi için bkz . Düzenleyici öğesi şablonuyla uzantı oluşturma.
Varolan sınıf dosyalarını silin.
Projeye aşağıdaki başvuruyu ekleyin ve Yerel Kopyala'yı olarak
False
ayarlayın:Microsoft.VisualStudio.Language.Intellisense
Yeni bir sınıf dosyası ekleyin ve dosyayı LightBulbTest olarak adlandırnın.
Aşağıdaki kullanım yönergelerini ekleyin:
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;
Ampul kaynak sağlayıcısını uygulama
LightBulbTest.cs sınıf dosyasında LightBulbTest sınıfını silin. uygulayan ISuggestedActionsSourceProviderTestSuggestedActionsSourceProvider adlı bir sınıf ekleyin. Test Önerilen Eylemlerinin Adı ve ContentTypeAttribute "metin" ile dışarı aktarın.
[Export(typeof(ISuggestedActionsSourceProvider))] [Name("Test Suggested Actions")] [ContentType("text")] internal class TestSuggestedActionsSourceProvider : ISuggestedActionsSourceProvider
Kaynak sağlayıcı sınıfının içinde öğesini içeri aktarın ITextStructureNavigatorSelectorService ve bir özellik olarak ekleyin.
[Import(typeof(ITextStructureNavigatorSelectorService))] internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
CreateSuggestedActionsSource Bir ISuggestedActionsSource nesne döndürmek için yöntemini uygulayın. Kaynak, sonraki bölümde ele alınmıştı.
public ISuggestedActionsSource CreateSuggestedActionsSource(ITextView textView, ITextBuffer textBuffer) { if (textBuffer == null || textView == null) { return null; } return new TestSuggestedActionsSource(this, textView, textBuffer); }
ISuggestedActionSource'ı uygulama
Önerilen eylem kaynağı, önerilen eylemler kümesini toplamak ve bunları doğru bağlamda eklemekle sorumludur. Bu durumda bağlam geçerli sözcük ve önerilen eylemler aşağıdaki bölümde açıklanan UpperCaseSuggestedAction ve LowerCaseSuggestedAction'dır.
uygulayan ISuggestedActionsSourcebir TestSuggestedActionsSource sınıfı ekleyin.
internal class TestSuggestedActionsSource : ISuggestedActionsSource
Önerilen eylem kaynağı sağlayıcısı, metin arabelleği ve metin görünümü için özel, salt okunur alanlar ekleyin.
private readonly TestSuggestedActionsSourceProvider m_factory; private readonly ITextBuffer m_textBuffer; private readonly ITextView m_textView;
Özel alanları ayarlayan bir oluşturucu ekleyin.
public TestSuggestedActionsSource(TestSuggestedActionsSourceProvider testSuggestedActionsSourceProvider, ITextView textView, ITextBuffer textBuffer) { m_factory = testSuggestedActionsSourceProvider; m_textBuffer = textBuffer; m_textView = textView; }
İmlecin altında bulunan sözcüğü döndüren özel bir yöntem ekleyin. Aşağıdaki yöntem imlecin geçerli konumuna bakar ve metin yapısı gezgininden sözcüğün kapsamını sorar. İmleç bir sözcüğün üzerindeyse out TextExtent parametresinde döndürülür; aksi takdirde
out
parametresi olurnull
ve yöntemi döndürürfalse
.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; }
HasSuggestedActionsAsync yöntemini uygulayın. Düzenleyici ampulün görüntülenip görüntülenmeyeceğini öğrenmek için bu yöntemi çağırır. Bu çağrı genellikle yapılır, örneğin, imleç bir satırdan diğerine geçtiğinde veya fare bir hata dalgalı çizginin üzerine geldiğinde. Bu yöntem çalışırken diğer ui işlemlerinin devam edebilmesi için zaman uyumsuzdur. Çoğu durumda, bu yöntemin geçerli satırın ayrıştırması ve analizini gerçekleştirmesi gerekir, bu nedenle işlem biraz zaman alabilir.
Bu uygulamada, zaman uyumsuz olarak TextExtent alır ve kapsamın önemli olup olmadığını belirler, örneğin, boşluk dışında bir metni olup olmadığını.
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; }); }
GetSuggestedActions Farklı ISuggestedAction nesneleri içeren bir nesne dizisi SuggestedActionSet döndüren yöntemini uygulayın. Ampul genişletildiğinde bu yöntem çağrılır.
Uyarı
ve uygulamalarının
HasSuggestedActionsAsync()
tutarlı olduğundan emin olmalısınız; yani döndürürseHasSuggestedActionsAsync()
true
,GetSuggestedActions()
görüntülenecek bazı eylemleriGetSuggestedActions()
olmalıdır. Çoğu durumda,HasSuggestedActionsAsync()
hemen önceGetSuggestedActions()
çağrılır, ancak her zaman böyle değildir. Örneğin, kullanıcı ampul eylemlerini yalnızcaGetSuggestedActions()
(CTRL+ .) tuşlarına basarak çağırırsa çağrılır.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>(); }
Bir
SuggestedActionsChanged
olay tanımlayın.public event EventHandler<EventArgs> SuggestedActionsChanged;
Uygulamayı tamamlamak için ve
TryGetTelemetryId()
yöntemlerineDispose()
yönelik uygulamalar ekleyin. Telemetri yapmak istemediğiniz için guid değerini döndürerekfalse
olarak ayarlamanız gerekirEmpty
.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; }
Ampul eylemlerini uygulama
Projede, Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.dll dosyasına bir başvuru ekleyin ve Yerel Kopyala'yı olarak
False
ayarlayın.İlk ve ikinci adlı
UpperCaseSuggestedAction
LowerCaseSuggestedAction
iki sınıf oluşturun. Her iki sınıf da uygular ISuggestedAction.internal class UpperCaseSuggestedAction : ISuggestedAction internal class LowerCaseSuggestedAction : ISuggestedAction
Bir çağrı ve diğer ToLowerçağrıları ToUpper dışında her iki sınıf da birbirine benzer. Aşağıdaki adımlar yalnızca büyük harf eylem sınıfını kapsar, ancak her iki sınıfı da uygulamanız gerekir. Büyük harf eylemini küçük harf eylemini uygulamak için bir desen olarak uygulama adımlarını kullanın.
Bu sınıflar için aşağıdaki using yönergelerini ekleyin:
using Microsoft.VisualStudio.Imaging.Interop; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media;
Bir dizi özel alan bildirin.
private ITrackingSpan m_span; private string m_upper; private string m_display; private ITextSnapshot m_snapshot;
Alanları ayarlayan bir oluşturucu ekleyin.
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)); }
Eylemin önizlemesini GetPreviewAsync görüntülemesi için yöntemini uygulayın.
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); }
GetActionSetsAsync boş bir SuggestedActionSet numaralandırma döndürmek için yöntemini uygulayın.
public Task<IEnumerable<SuggestedActionSet>> GetActionSetsAsync(CancellationToken cancellationToken) { return Task.FromResult<IEnumerable<SuggestedActionSet>>(null); }
Özellikleri aşağıdaki gibi uygulayın.
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; } }
span içindeki Invoke metni büyük harf eşdeğeriyle değiştirerek yöntemini uygulayın.
public void Invoke(CancellationToken cancellationToken) { m_span.TextBuffer.Replace(m_span.GetSpan(m_snapshot), m_upper); }
Uyarı
Ampul eylemi Invoke yönteminin kullanıcı arabirimini göstermesi beklenmiyor. Eyleminiz yeni bir kullanıcı arabirimi (örneğin bir önizleme veya seçim iletişim kutusu) getirirse, kullanıcı arabirimini doğrudan Invoke yönteminin içinden görüntülemeyin, bunun yerine Invoke'tan döndükten sonra kullanıcı arabiriminizi görüntülemek için zamanlayın.
Uygulamayı tamamlamak için ve
TryGetTelemetryId()
yöntemlerini ekleyinDispose()
.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; }
Görüntüleme metnini "'' küçük harfe dönüştür{0}" olarak ve çağrısı ToUpper ToLowerolarak değiştirmek için
LowerCaseSuggestedAction
de aynı şeyi yapmayı unutmayın.
Kodu derleme ve test etme
Bu kodu test etmek için LightBulbTest çözümünü derleyin ve Deneysel örnekte çalıştırın.
Çözümü oluşturun.
Bu projeyi hata ayıklayıcıda çalıştırdığınızda, Visual Studio'nun ikinci bir örneği başlatılır.
Bir metin dosyası oluşturun ve metin yazın. Metnin solunda bir ampul görmeniz gerekir.
Ampulün üzerine gelin. Aşağı ok görmeniz gerekir.
Ampule tıkladığınızda, seçilen eylemin önizlemesiyle birlikte iki önerilen eylem görüntülenmelidir.
İlk eyleme tıklarsanız, geçerli sözcükteki tüm metin büyük harfe dönüştürülmelidir. İkinci eyleme tıklarsanız, tüm metin küçük harfe dönüştürülmelidir.