İzlenecek yol: Deyim tamamlamayı görüntüleme
Tamamlama sağlamak istediğiniz tanımlayıcıları tanımlayıp bir tamamlama oturumu tetikleyerek dil tabanlı deyim tamamlama uygulayabilirsiniz. Deyim tamamlama işlemini bir dil hizmeti bağlamında tanımlayabilir, kendi dosya adı uzantınızı ve içerik türünüzü tanımlayabilir ve ardından yalnızca bu tür için tamamlama işlemini görüntüleyebilirsiniz. Alternatif olarak, var olan bir içerik türü için tamamlanmayı tetikleyebilirsiniz; örneğin, "düz metin". Bu kılavuzda, metin dosyalarının içerik türü olan "düz metin" içerik türü için deyim tamamlamanın nasıl tetiklendiği gösterilir. "Metin" içerik türü, kod ve XML dosyaları da dahil olmak üzere diğer tüm içerik türlerinin atasıdır.
Deyim tamamlama işlemi genellikle belirli karakterler yazılarak tetikler; örneğin, "using" gibi bir tanımlayıcının başlangıcı yazılarak. Seçim yapmak için genellikle Ara Çubuğu, Sekme veya Enter tuşuna basılarak kapatılır. Tuş vuruşları ( IOleCommandTarget arabirim) için bir komut işleyicisi ve arabirimi uygulayan IVsTextViewCreationListener bir işleyici sağlayıcısı kullanarak karakter yazarken tetikleyen IntelliSense özelliklerini uygulayabilirsiniz. Tamamlamaya katılan tanımlayıcıların listesi olan tamamlanma kaynağını oluşturmak için arabirimini ve bir tamamlama kaynağı sağlayıcısını (ICompletionSourceProviderarabirim) uygulayınICompletionSource. Sağlayıcılar Yönetilen Genişletilebilirlik Çerçevesi (MEF) bileşen parçalarıdır. Kaynak ve denetleyici sınıflarını dışarı aktarmak ve hizmetleri ve aracıları içeri aktarmak, örneğin, metin arabelleğinde gezinmeyi ITextStructureNavigatorSelectorServiceetkinleştiren ve ICompletionBrokertamamlama oturumunu tetikleyen ' den sorumludur.
Bu izlenecek yol, sabit kodlanmış bir tanımlayıcı kümesi için deyim tamamlamanın nasıl uygulandığını gösterir. Tam uygulamalarda, dil hizmeti ve dil belgeleri bu içeriği sağlamakla sorumludur.
MEF Projesi Oluşturma
MEF projesi oluşturmak için
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ü
CompletionTest
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şvuruları ekleyin ve CopyLocal öğesinin olarak
false
ayarlandığından emin olun:Microsoft.VisualStudio.Editor
Microsoft.VisualStudio.Language.Intellisense
Microsoft.visualstudio.ole
Microsoft.VisualStudio.Shell.15.0
Microsoft.VisualStudio.Shell.Immutable.10.0
Microsoft.VisualStudio.TextManager.Interop
Tamamlanma kaynağını uygulama
Kullanıcı bir tanımlayıcının ilk harfleri gibi bir tamamlama tetikleyicisi yazdığında, tamamlanma kaynağı tanımlayıcı kümesini toplamak ve içeriği tamamlama penceresine eklemekle sorumludur. Bu örnekte, tanımlayıcılar ve açıklamaları yönteminde AugmentCompletionSession sabit kodlanmıştır. Gerçek dünya kullanımlarının çoğunda, tamamlama listesini doldurmak için belirteçleri almak için dilinizin ayrıştırıcısını kullanırsınız.
Tamamlanma kaynağını uygulamak için
Bir sınıf dosyası ekleyin ve adını verin
TestCompletionSource
.Şu içeri aktarmaları ekleyin:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.Composition; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Operations; using Microsoft.VisualStudio.Utilities;
için sınıf bildirimini
TestCompletionSource
, uygulamasının gerçekleştirileceği ICompletionSourceşekilde değiştirin:Kaynak sağlayıcı, metin arabelleği ve nesne listesi Completion (tamamlama oturumuna katılacak tanımlayıcılara karşılık gelen) için özel alanlar ekleyin:
Kaynak sağlayıcıyı ve arabelleği ayarlayan bir oluşturucu ekleyin. sınıfı
TestCompletionSourceProvider
sonraki adımlarda tanımlanır:Bağlam içinde AugmentCompletionSession sağlamak istediğiniz tamamlamaları içeren bir tamamlama kümesi ekleyerek yöntemini uygulayın. Her tamamlama kümesi bir tamamlama kümesi Completion içerir ve tamamlama penceresinin bir sekmesine karşılık gelir. (Visual Basic projelerinde tamamlama penceresi sekmelerinin adı Ortak ve Tümü.)
FindTokenSpanAtPosition
yöntemi bir sonraki adımda tanımlanır.void ICompletionSource.AugmentCompletionSession(ICompletionSession session, IList<CompletionSet> completionSets) { List<string> strList = new List<string>(); strList.Add("addition"); strList.Add("adaptation"); strList.Add("subtraction"); strList.Add("summation"); m_compList = new List<Completion>(); foreach (string str in strList) m_compList.Add(new Completion(str, str, str, null, null)); completionSets.Add(new CompletionSet( "Tokens", //the non-localized title of the tab "Tokens", //the display title of the tab FindTokenSpanAtPosition(session.GetTriggerPoint(m_textBuffer), session), m_compList, null)); }
İmlecin konumundan geçerli sözcüğü bulmak için aşağıdaki yöntem kullanılır:
private ITrackingSpan FindTokenSpanAtPosition(ITrackingPoint point, ICompletionSession session) { SnapshotPoint currentPoint = (session.TextView.Caret.Position.BufferPosition) - 1; ITextStructureNavigator navigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(m_textBuffer); TextExtent extent = navigator.GetExtentOfWord(currentPoint); return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive); }
Dispose()
Yöntemini uygulayın:
Tamamlanma kaynağı sağlayıcısını uygulama
Tamamlanma kaynağı sağlayıcısı, tamamlanma kaynağının örneğini oluşturan MEF bileşen bölümüdür.
Tamamlanma kaynağı sağlayıcısını uygulamak için
uygulayan ICompletionSourceProvideradlı
TestCompletionSourceProvider
bir sınıf ekleyin. Bu sınıfı "düz metin" ve NameAttribute "test tamamlama" ile ContentTypeAttribute dışarı aktarın.Tamamlanma kaynağındaki geçerli sözcüğü bulan bir ITextStructureNavigatorSelectorServiceöğesini içeri aktarın.
TryCreateCompletionSource Tamamlanma kaynağının örneğini görüntülemek için yöntemini uygulayın.
Tamamlama komut işleyici sağlayıcısını uygulama
Tamamlama komut işleyicisi sağlayıcısı, bir IVsTextViewCreationListenermetin görünümü oluşturma olayını dinleyen ve bir görünümünden görünümü dönüştüren (komutun Visual Studio kabuğunun komut zincirine eklenmesini sağlayan) 'ITextViewden IVsTextViewtüretilir. Bu sınıf bir MEF dışarı aktarması olduğundan, komut işleyicisinin kendisi için gerekli olan hizmetleri içeri aktarmak için de kullanabilirsiniz.
Tamamlama komut işleyici sağlayıcısını uygulamak için
adlı
TestCompletionCommandHandler
bir dosya ekleyin.Bunları kullanarak yönergelerini ekleyin:
using System; using System.ComponentModel.Composition; using System.Runtime.InteropServices; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Editor; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.TextManager.Interop; using Microsoft.VisualStudio.Utilities;
uygulayan IVsTextViewCreationListeneradlı
TestCompletionHandlerProvider
bir sınıf ekleyin. Bu sınıfı bir "belirteç tamamlama işleyicisi", "ContentTypeAttributedüz metin" ve bir TextViewRoleAttribute ile dışarı NameAttribute aktarınEditable.IVsEditorAdaptersFactoryServicestandart Visual Studio hizmetlerine erişim sağlayan bir IVsTextView ' den , ve ICompletionBrokerSVsServiceProvider 'ye ITextViewdönüştürmeyi etkinleştiren öğesini içeri aktarın.
Komut işleyicisini VsTextViewCreated örneklemek için yöntemini uygulayın.
public void VsTextViewCreated(IVsTextView textViewAdapter) { ITextView textView = AdapterService.GetWpfTextView(textViewAdapter); if (textView == null) return; Func<TestCompletionCommandHandler> createCommandHandler = delegate() { return new TestCompletionCommandHandler(textViewAdapter, textView, this); }; textView.Properties.GetOrCreateSingletonProperty(createCommandHandler); }
Tamamlama komut işleyicisini uygulama
Deyim tamamlama tuş vuruşları tarafından tetiklendiğinden, tamamlama oturumunu IOleCommandTarget tetikleyen, işleyen ve kapatan tuş vuruşlarını almak ve işlemek için arabirimini uygulamanız gerekir.
Tamamlama komut işleyicisini uygulamak için
uygulayan IOleCommandTargetadlı
TestCompletionCommandHandler
bir sınıf ekleyin:Sonraki komut işleyicisi (komutu geçirdiğiniz), metin görünümü, komut işleyici sağlayıcısı (çeşitli hizmetlere erişimi etkinleştirir) ve bir tamamlama oturumu için özel alanlar ekleyin:
Metin görünümünü ve sağlayıcı alanlarını ayarlayan ve komutu komut zincirine ekleyen bir oluşturucu ekleyin:
QueryStatus komutunu geçirerek yöntemini uygulayın:
Exec yöntemini uygulayın. Bu yöntem bir tuş vuruşu aldığında aşağıdakilerden birini yapmalıdır:
Karakterin arabelleğe yazılmasına izin verin ve ardından tamamlanmayı tetikleyin veya filtreleyin. (Yazdırma karakterleri bunu yapar.)
Tamamlama işlemini gerçekleştirin, ancak karakterin arabelleğe yazılmasına izin verme. (Boşluk, Sekme tuşuna basın ve Bir tamamlama oturumu görüntülendiğinde Enter bunu yapın.)
Komutun sonraki işleyiciye geçirilmesine izin verin. (Diğer tüm komutlar.)
Bu yöntem kullanıcı arabirimini görüntüleyebileceğinden, otomasyon bağlamında çağrılmadığından emin olmak için çağrısı IsInAutomationFunction yapın:
public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider)) { return m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); } //make a copy of this so we can look at it after forwarding some commands uint commandID = nCmdID; char typedChar = char.MinValue; //make sure the input is a char before getting it if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR) { typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn); } //check for a commit character if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB || (char.IsWhiteSpace(typedChar) || char.IsPunctuation(typedChar))) { //check for a selection if (m_session != null && !m_session.IsDismissed) { //if the selection is fully selected, commit the current session if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected) { m_session.Commit(); //also, don't add the character to the buffer return VSConstants.S_OK; } else { //if there is no selection, dismiss the session m_session.Dismiss(); } } } //pass along the command so the char is added to the buffer int retVal = m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); bool handled = false; if (!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar)) { if (m_session == null || m_session.IsDismissed) // If there is no active session, bring up completion { this.TriggerCompletion(); m_session.Filter(); } else //the completion session is already active, so just filter { m_session.Filter(); } handled = true; } else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE //redo the filter if there is a deletion || commandID == (uint)VSConstants.VSStd2KCmdID.DELETE) { if (m_session != null && !m_session.IsDismissed) m_session.Filter(); handled = true; } if (handled) return VSConstants.S_OK; return retVal; }
Bu kod, tamamlama oturumunu tetikleyen özel bir yöntemdir:
private bool TriggerCompletion() { //the caret must be in a non-projection location SnapshotPoint? caretPoint = m_textView.Caret.Position.Point.GetPoint( textBuffer => (!textBuffer.ContentType.IsOfType("projection")), PositionAffinity.Predecessor); if (!caretPoint.HasValue) { return false; } m_session = m_provider.CompletionBroker.CreateCompletionSession (m_textView, caretPoint.Value.Snapshot.CreateTrackingPoint(caretPoint.Value.Position, PointTrackingMode.Positive), true); //subscribe to the Dismissed event on the session m_session.Dismissed += this.OnSessionDismissed; m_session.Start(); return true; }
Sonraki örnek, olay aboneliğini Dismissed kaldıran özel bir yöntemdir:
Kodu derleme ve test etme
Bu kodu test etmek için CompletionTest çözümünü derleyin ve deneysel örnekte çalıştırın.
CompletionTest çözümünü derlemek ve test etmek için
Çö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 "ekle" sözcüğünü içeren bir metin yazın.
Önce "a" ve sonra "d" yazdığınızda, "toplama" ve "uyarlama" içeren bir liste görünmelidir. Eklemenin seçili olduğuna dikkat edin. Başka bir "d" yazdığınızda, listede yalnızca seçili olan "toplama" bulunmalıdır. Ara Çubuğu, Sekme veya Enter tuşuna basarak "toplama" işlemi yapabilir veya Esc veya başka bir tuş yazarak listeyi kapatabilirsiniz.