33

Próbuję rozpocząć pracę z rozszerzeniami Visual Studio (2010) i mam problemy ze znalezieniem odpowiednich materiałów. Mam SDK, ale załączone próbki wydają się być takie jak adorners, windows i ikony.Rozszerzenie edytora tekstu w Visual Studio

Próbuję utworzyć rozszerzenie, które będzie działało bezpośrednio z edytorem tekstu (w celu alfabetowania wszystkich nazw metod w klasie, lub na przykład ustawiania wielkich liter na stałe), ale nie mogę znaleźć wersji demonstracyjnej dla ten rodzaj funkcjonalności, a nawet samouczek.

Czy ktoś wie, gdzie mogę znaleźć tego rodzaju rzeczy?

+0

@ Pac-Man: Niestety musiałem umieścić go na tylnym palniku (ze względu na brak zasobów wyszukiwania), więc nigdy nie dość się do tego. Jeśli kiedykolwiek to rozgryję, dam ci znać. W przypadku małych operacji zauważyłem, że pisanie makr działa całkiem dobrze. –

+0

@ Pac-Man: To byłoby naprawdę najlepsze. Czuję twój ból o rzeczach MSDN (czasami). Niestety sądzę, że to rozszerzenie jest jedną z tych "czarnych sztuk". –

+0

Mam nadzieję, że mój link w odpowiedzi, którą zamieściłem, może ci pomóc. Te tutoriale wyjaśniają mi wszystko, co muszę wiedzieć o dodatkach VS, mimo że brakuje zrzutów ekranu. –

Odpowiedz

54

miałem dokładnie to samo pytanie, a teraz przeglądałem web kilka godzin, dopóki nie była w stanie zrozumieć i wyjaśnić, jak trzeba zacząć od takiego rozszerzenia.

W poniższym przykładzie utworzymy małe i głupie rozszerzenie, które zawsze doda "Hello" na początku pliku kodu, gdy dokonano edycji. Jest to bardzo proste, ale powinno dać ci pomysł, jak kontynuować rozwój tej rzeczy.

Ostrzegam: Musisz całkowicie przeanalizować pliki kodu - Visual Studio nie daje żadnych informacji o tym, gdzie są klasy, metody lub cokolwiek i co zawierają. Jest to największa przeszkoda, którą należy podjąć, wykonując narzędzie do formatowania kodu i nie będzie ona uwzględniona w tej odpowiedzi. [*]

Dla osób, które pominęły tę odpowiedź, należy najpierw pobrać i zainstalować pakiet Visual Studio SDK lub nie znajdzie typu projektu wspomnianego w kroku pierwszym.

Tworzenie projektu

  1. zacząć od stworzenia nowego projektu typu "Visual C#> Rozszerzenia> VSIX Projektu" (widoczny tylko wtedy, gdy wybrany .NET Framework 4 w ramach docelowego). Należy pamiętać, że może być konieczne wybranie typu projektu "Edytor klasyfikatora" zamiast typu "Projekt VSIX", aby go uruchomić, s. komentarz poniżej.

  2. Po utworzeniu projektu zostanie otwarty plik "source.extension.vsixmanifest", umożliwiający skonfigurowanie nazwy produktu, autora, wersji, opisu, ikony i tak dalej. Myślę, że ten krok jest dość samowystarczający, możesz teraz zamknąć zakładkę i przywrócić ją później, otwierając plik vsixmanifest.

Tworzenie klasy słuchacza, aby otrzymywać powiadomienia o edytorze tekstu np kreacji

Następny musimy słuchać, gdy edytor tekstu został utworzony w Visual Studio i wiążą nasz kod formatowania narzędzie do niego. Edytor tekstu w VS2010 jest instancją IWpfTextView.

  1. Dodaj nową klasę do naszego projektu i nadaj mu nazwę TextViewCreationListener. Ta klasa musi implementować interfejs Microsoft.VisualStudio.Text.Editor.IWpfTextViewCreationListener. Musisz dodać odniesienie do Microsoft.VisualStudio.Text.UI.Wpf do twojego projektu. Biblioteka DLL zespołu znajduje się w katalogu Visual Studio SDK pod numerem VisualStudioIntegration \ Common \ Assemblies \ v4.0.

  2. Należy wdrożyć metodę interfejsu TextViewCreated. Ta metoda ma parametr określający instancję edytora tekstu, który został utworzony. Stworzymy nową klasę formatowania kodu, do której ta instancja zostanie przekazana później.

  3. Musimy uczynić klasę TextViewCreationListener widoczną dla Visual Studio, określając atrybut [Export(typeof(IWpfTextViewCreationListener))]. Dodaj odniesienie do System.ComponentModel.Composition do swojego projektu dla atrybutu Export.

  4. Dodatkowo, musimy określić, z jakim rodzajem plików program do formatowania kodu powinien być związany z edytorem tekstu. Chcemy tylko formatować pliki kodu, a nie pliki tekstowe, więc dodajemy atrybut [ContentType("code")] do klasy odbiornika. Do tego celu należy dodać odniesienie do obiektu Microsoft.VisualStudio.CoreUtility.

  5. Ponadto, chcemy tylko zmienić edytowalny kod, a nie kolory i ozdoby wokół niego (jak widać w przykładowych projektach), więc dodajemy atrybut [TextViewRole(PredefinedTextViewRoles.Editable)] do klasy. Ponownie potrzebujesz nowego odniesienia, tym razem do Microsoft.VisualStudio.Text.UI.

  6. Oznacz klasę jako wewnętrzną zapieczętowaną. Przynajmniej to moja rekomendacja. Teraz twoja klasa powinna wyglądać podobnie do tego:

    [ContentType("code")] 
    [Export(typeof(IWpfTextViewCreationListener))] 
    [TextViewRole(PredefinedTextViewRoles.Editable)] 
    internal sealed class TextViewCreationListener : IWpfTextViewCreationListener 
    { 
        public void TextViewCreated(IWpfTextView textView) 
        { 
        } 
    } 
    

Tworzenie klasy dla kodu formatowania

Dalej musimy klasę obsługi logiki kodu formatowania, metod i tak dalej sortowania. Ponownie, w tym przykładzie po prostu doda "Hello" do początku pliku, gdy tylko zostanie dokonana zmiana.

  1. Dodaj nową klasę o nazwie do swojego projektu.

  2. Dodaj konstruktora, który przyjmuje jeden argument IWpfTextView. Pamiętajmy, że chcieliśmy przekazać utworzoną instancję edytora do tej klasy formatowania w metodzie TextViewCreated naszej klasy nasłuchującej (wystarczy dodać do niej metodę new Formatter(textView);).

  3. Zapisz przekazaną instancję w zmiennej członkowskiej. Będzie to przydatne podczas późniejszego formatowania kodu (na przykład w celu pobrania pozycji karetki). Również związać się Changed i PostChanged wydarzenia własności instancji edytora TextBuffer:

    public Formatter(IWpfTextView view) 
    { 
        _view = view; 
        _view.TextBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(TextBuffer_Changed); 
        _view.TextBuffer.PostChanged += new EventHandler(TextBuffer_PostChanged); 
    } 
    
  4. Changed wydarzenie nazywa każdym razem, gdy zmiana została wykonana (np wpisując char, kod tapetowania lub programmatical zmianami). Ponieważ reaguje również na zmiany programistyczne, używam określenia bool określającego, czy nasze rozszerzenie lub użytkownik/cokolwiek innego zmienia kod w tej chwili i wywołują moją niestandardową metodę FormatCode() tylko wtedy, gdy nasze rozszerzenie nie jest jeszcze edytowane.W przeciwnym razie będziesz rekursywnie wywołać tę metodę, która będzie katastrofy Visual Studio:

    private void TextBuffer_Changed(object sender, TextContentChangedEventArgs e) 
    { 
        if (!_isChangingText) 
        { 
         _isChangingText = true; 
         FormatCode(e); 
        } 
    } 
    
  5. Musimy przywrócić tę zmienną składową bool w procedurze obsługi zdarzenia PostChanged ponownie false.

  6. Przełóżmy zdarzenia zdarzeń Changed do naszej niestandardowej metody FormatCode, ponieważ zawierają one zmiany między ostatnią edycją a teraz. Te zmiany są przechowywane w tablicy e.Changes typu INormalizedTextChangeCollection (np. Link na końcu mojego posta, aby uzyskać więcej informacji na temat tego typu). Przeszukujemy wszystkie te zmiany i wywołujemy naszą niestandardową metodę HandleChange z nowym tekstem, który ta edycja stworzyła.

    private void FormatCode(TextContentChangedEventArgs e) 
    { 
        if (e.Changes != null) 
        { 
         for (int i = 0; i < e.Changes.Count; i++) 
         { 
          HandleChange(e.Changes[0].NewText); 
         } 
        } 
    } 
    
  7. W metodzie HandleChange mogliśmy faktycznie skanowania dla słów kluczowych, aby obsłużyć te w specyficzny sposób (pamiętaj, masz do analizowania kodu na siebie!) - ale tutaj po prostu tępo dodać „Hello” do początek pliku do celów testowych. Na przykład. musimy zmienić TextBuffer naszej instancji edytora. Aby to zrobić, musimy stworzyć obiekt, którym możemy manipulować tekstem i później zastosować zmiany. Kod jest dość self-wyjaśniając:

    private void HandleChange(string newText) 
    { 
        ITextEdit edit = _view.TextBuffer.CreateEdit(); 
        edit.Insert(0, "Hello"); 
        edit.Apply(); 
    } 
    

Kompilując ten dodatek, eksperymentalny ula Visual Studio uruchamia się tylko z naszego rozszerzenia załadowany. Utwórz nowy plik C# i zacznij pisać, aby zobaczyć wyniki.

Mam nadzieję, że daje to pewne pomysły na kontynuowanie tego tematu. Muszę to teraz zbadać.

Gorąco polecam dokumentację modelu tekstowego edytora w MSDN, aby uzyskać wskazówki, jak można to zrobić i tamto. http://msdn.microsoft.com/en-us/library/dd885240.aspx#textmodel


Przypisy

[*] Należy zauważyć, że Visual Studio 2015 lub nowszy pochodzą z Rosyln Compiler Platformy, która rzeczywiście już analizuje C# i VB.NET pliki dla ciebie (i prawdopodobnie innych wcześniej - również zainstalowane języki) i ujawnia ich hierarchiczną strukturę składni, ale nie jestem jeszcze ekspertem w tym temacie, aby udzielić odpowiedzi na temat korzystania z tych nowych usług. Podstawowy postęp uruchamiania rozszerzenia edytora pozostaje taki sam jak opisany w tej odpowiedzi. Należy pamiętać, że - w przypadku korzystania z tych usług - użytkownik zostanie uzależniony od programu Visual Studio 2015+, a rozszerzenie nie będzie działać we wcześniejszych wersjach.

+0

Zbudowałem program zgodnie ze specyfikacją. To nie działa. Włączyłem trochę rejestrowania i nie są wywoływane żadne metody. Jakieś pomysły? –

+3

Mam to działa przy użyciu typu projektu "Editor Classifier", zamiast typu projektu VISX. Twoje demo i moje rozszerzenie działają doskonale. –

+0

@Mike Christian: OK, nie mogę sprawdzić, dlaczego typ projektu VISX nie działał poprawnie, ale dodałem notatkę do typu projektu w mojej odpowiedzi. –

Powiązane problemy