Freigeben über


Unterstützung für verwalteten Code Snippets (Paketframework)

Ein Codeausschnitt handelt es sich um einen Codeabschnitt, der in der Quelldatei eingefügt wird. Der Codeausschnitt selbst ist eine XML-basierte Vorlage mit einem Satz von Feldern. Diese Felder werden hervorgehoben, nachdem der Ausschnitt eingefügt und unterschiedliche Werte aufweisen kann je nach Kontext, in dem der Ausschnitt eingefügt wird. Sofort nach dem der Ausschnitt eingefügt wird, kann der Sprachdienst den Ausschnitt formatieren.

Der Ausschnitt kann in einem speziellen Bearbeitungsmodus eingefügt, der die Felder kann mithilfe des Ausschnitts navigiert werden soll, verwendet die TAB-TASTE. Die Felder können IntelliSense-Format Dropdownmenüs unterstützen. Der Benutzer führt einen Commit für den Ausschnitt zur Quelldatei indem Sie entweder die EINGABETASTE oder die ESC-TASTE eintritt. Um mehr darüber erfahren, finden Sie unter Codeausschnitte.

Unterstützung von verwaltetem Paketframeworks für Codeausschnitte

Das verwaltete Paketframework (MPF) unterstützt die meisten Ausschnitts Funktionen zum Lesen der Vorlage zum Einfügen des Ausschnitts und zum Aktivieren des speziellen Bearbeitungsmodus. Unterstützung durch die ExpansionProvider-Klasse verwaltet.

Wenn die Source-Klasse instanziiert wird, wird die CreateExpansionProvider-Methode in der LanguageService-Klasse aufgerufen, um ein Objekt ExpansionProvider (Beachten Sie, dass die Basis- LanguageService-Klasse immer ein neues ExpansionProvider-Objekt für jedes Source-Objekt zurückgibt).

Das MPF Add-In nicht unterstützt. Eine Funktion zum Add-In ist eine benannte Funktion, die in einer Vorlage Ausschnitts eingebettet und mindestens ein Feld wird auf zurückgibt, dass die Werte abgelegt werden. Die Werte werden vom Sprachdienst selbst durch ein ExpansionFunction-Objekt zurückgegeben. Das Objekt muss vom ExpansionFunction Sprachdienst implementiert werden, um erweiterten Features zu unterstützen.

Unterstützung für Codeausschnitte unterstützen

Um Unterstützung für Codeausschnitte zu aktivieren, müssen Sie bereitstellen oder die Ausschnitte und installieren Sie bereitstellen muss, damit der Benutzer für diese Ausschnitte einfügt. Es gibt drei Schritte zum Aktivieren der Unterstützung für Codeausschnitte:

  1. Die Dateien des Ausschnitts installieren.

  2. Codeausschnitte für den Sprachdienst aktivieren.

  3. Das ExpansionProvider-Objekt aufrufen.

Die Installation Ausschnitts-Dateien

Alle Codeausschnitte für eine Sprache in den Vorlagen werden als XML-Dateien, i. d. R. eine Vorlage Ausschnitts pro Datei gespeichert. Ausführliche Informationen zum XML-Schema, das für Vorlagen Codeausschnitt verwendet wird, finden Sie unter Schemareferenz für Codeausschnitte. Jede Vorlage Ausschnitts mit einer Sprache identifiziert wird. Die Sprach-ID werden in der Registrierung angegeben und werden in das Language-Attribut des <Code> Tags in der Vorlage eingefügt.

Es gibt in der Regel zwei Speicherorten, an denen Ausschnitts vorlagendateien gespeichert werden: 1 (null), in der die Sprache und 2) im Ordner des Benutzers installiert wurde. Diese Adressen werden in die Registrierung hinzugefügt, damit Visual Studio Codeausschnitt-Manager die Codeausschnitte finden kann. Der Ordner des Benutzers befindet, wo der Ausschnitte, die vom Benutzer erstellten gespeicherten.

Das typische Ordner Lay-out für die installierten Ausschnitts vorlagendateien sieht wie folgt aus: [InstallRoot]\[TestLanguage]\ Snippets \ Snippets \[LCID].

[InstallRoot] ist der Ordner, der die Sprache in installiert ist.

[TestLanguage] ist der Name der Sprache als Ordnername.

[LCID] ist die Gebietsschema-ID. Dies ist das lokalisierte Versionen der Ausschnitte gespeichert werden. Beispielsweise ist die Gebietsschema-ID 1033 für Englisch. Daher wird [LCID] bis 1033 ersetzt.

Eine zusätzliche Datei muss angegeben werden und ist eine Indexdatei, i. d. R. aufgerufen SnippetsIndex.xml oder ExpansionsIndex.xml (Sie können jedes gültige Dateinamen beendet sind in .xml). Diese Datei wird normalerweise im [InstallRoot]\[TestLanguage] Ordner gespeichert und den genauen Speicherort des Ausschnitts Ordner sowie der Sprach-ID und GUID des Sprachdiensts angibt, der die Ausschnitte verwendet. Der vollständige Pfad der Indexdatei wird in die Registrierung abgelegt, wie weiter unten beschrieben, wenn die Registrierungseinträge „Installation“. Im Folgenden ein Beispiel für eine SnippetsIndex.xml-Datei:

<?xml version="1.0" encoding="utf-8" ?>
<SnippetCollection>
    <Language Lang="Testlanguage" Guid="{b614a40a-80d9-4fac-a6ad-fc2868fff7cd}">
        <SnippetDir>
            <OnOff>On</OnOff>
            <Installed>true</Installed>
            <Locale>1033</Locale>
            <DirPath>%InstallRoot%\TestLanguage\Snippets\%LCID%\Snippets\</DirPath>
            <LocalizedName>Snippets</LocalizedName>
        </SnippetDir>
    </Language>
</SnippetCollection>

Das <Language> Tag gibt die Sprach-ID (das Lang-Attribut) und der Sprachdienst GUIDs.

In diesem Beispiel wird davon ausgegangen, dass Sie den Ordner Sprachdienst in Visual Studio-Installations installiert haben. Das aktuelle ID. %LCID% wird durch das Gebietsschema des Benutzers ersetzt Mehrere <SnippetDir> Tags können hinzugefügt werden, und zwar jeweils eines für jedes Distinct Verzeichnis und Gebietsschema. Außerdem kann ein Unterordner des Ausschnitts enthalten, von denen jeder in der Indexdatei mit dem <SnippetSubDir> Tag identifiziert wird, das in einem <SnippetDir> Tag eingebettet ist.

Benutzer können eigene Ausschnitte für die Sprache erstellen. Diese Einstellungen werden normalerweise im Ordner des Benutzers, z. B. [TestDocs]\ Codeausschnitte \[TestLanguage]\ Test-Codeausschnitte gespeichert, wobei [TestDocs] der Speicherort des Veröffentlichungsordners Einstellungen des Benutzers für Visual Studio ist.

Die folgenden Ersetzungen Elemente können im Pfad abgelegt werden, der im <DirPath> Tag in der Indexdatei gespeichert wird.

Element

Beschreibung

%LCID%

Gebietsschema-ID.

%InstallRoot%

Ordner Stamm installations Visual Studio zum Beispiel C:\Program Files\Microsoft- Visual Studio 8.

%ProjDir%

Ordner, der das aktuelle Projekt enthält.

%ProjItem%

Ordner, der das aktuelle Projektelement enthält.

%TestDocs%

Ordner im Ordner Einstellungen des Benutzers zum Beispiel C:\Documents and Settings\[Benutzername]\ Eigene Dateien \ Visual Studio \ 8.

Codeausschnitte für den Sprachdienst aktivieren

Sie können Codeausschnitte für den Sprachdienst aktivieren, indem Sie das Attribut auf ProvideLanguageCodeExpansionAttribute VSPackages hinzufügen (siehe Wenn Sie einen Sprachdienst registrieren (Managed Paketframework) für Details). Die ShowRoots und SearchPaths-Parameter sind optional, aber Sie sollten den SearchPaths benannten Parameter einschließen, um Codeausschnitt-Manager über den Speicherort der Ausschnitte zu informieren.

Im Folgenden finden Sie ein Beispiel dafür, wie dieses Attribut verwendet wird:

[ProvideLanguageCodeExpansion(
         typeof(TestSnippetLanguageService),
         "Test Snippet Language",          // Name of language used as registry key
         0,                               // Resource ID of localized name of language service
         "Test Snippet Language",        // Name of Language attribute in snippet template
         @"%InstallRoot%\Test Snippet Language\Snippets\%LCID%\SnippetsIndex.xml",  // Path to snippets index
         SearchPaths = @"%InstallRoot%\Test Snippet Language\Snippets\%LCID%\")]    // Path to snippets

Durch Aufrufen Erweiterungs-Anbieter

Die Sprachen dienststeuerungen das Einfügen von beliebigem Codeausschnitts als auch das Einfügen von Methoden aufgerufen wird.

Durch Aufrufen Erweiterungs-Anbieter für Codeausschnitte

Es gibt zwei Möglichkeiten, den Hersteller der das Add-In aufzurufen: mithilfe eines Menübefehls oder mithilfe einer Verknüpfung über eine Vervollständigungsliste angezeigt.

Wenn Sie einen Codeausschnitt mithilfe eines Menübefehls einfügen

Um einen Menübefehl zu verwendende den Browser Ausschnitts anzuzeigen, fügen Sie einen Menübefehl hinzu, und rufen dann die DisplayExpansionBrowser-Methode in der ExpansionProvider-Schnittstelle als Reaktion auf den Menübefehl an.

  1. Hinzufügen eines Befehls und der .vsct-Datei eine Schaltfläche hinzu. Sie können in Anweisungen für Exemplarische Vorgehensweise: Wenn Sie einen Menübefehl mit der Visual Studio-Paket-Vorlage erstellenFall finden.

  2. Leiten Sie eine Klasse von der ViewFilter-Klasse, und überschreiben Sie die QueryCommandStatus-Methode, um Unterstützung für den neuen Menübefehl anzugeben. Dieses Beispiel ermöglicht immer den Menübefehl.

    using Microsoft.VisualStudio.Package;
    
    namespace TestLanguagePackage
    {
        class TestViewFilter : ViewFilter
        {
            public TestViewFilter(CodeWindowManager mgr, IVsTextView view)
                : base(mgr, view)
            {
            }
    
            protected override int QueryCommandStatus(ref Guid guidCmdGroup,
                                                      uint nCmdId)
            {
                int hr = base.QueryCommandStatus(ref guidCmdGroup, nCmdId);
                // If the base class did not recognize the command then
                // see if we can handle the command.
                if (hr == (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_UNKNOWNGROUP)
                {
                    if (guidCmdGroup == GuidList.guidTestLanguagePackageCmdSet)
                    {
                        if (nCmdId == PkgCmdIDList.InvokeCodeSnippetsBrowser)
                        {
                            hr = (int)(OLECMDF.OLECMDF_SUPPORTED | OLECMDF.OLECMDF_ENABLED);
                        }
                    }
                }
                return hr;
            }
        }
    }
    
  3. Überschreiben Sie die HandlePreExec-Methode in der ViewFilter-Klasse, um das ExpansionProvider-Objekt und die DisplayExpansionBrowser-Methode für dieses Objekt aufgerufen wird.

    using Microsoft.VisualStudio.Package;
    
    namespace TestLanguagePackage
    {
        class TestViewFilter : ViewFilter
        {
            public override bool HandlePreExec(ref Guid guidCmdGroup,
                                               uint nCmdId,
                                               uint nCmdexecopt,
                                               IntPtr pvaIn,
                                               IntPtr pvaOut)
            {
                if (base.HandlePreExec(ref guidCmdGroup,
                                       nCmdId,
                                       nCmdexecopt,
                                       pvaIn,
                                       pvaOut))
                {
                    // Base class handled the command.  Do nothing more here.
                    return true;
                }
    
                if (guidCmdGroup == GuidList.guidTestLanguagePackageCmdSet)
                {
                    if (nCmdId == PkgCmdIDList.InvokeCodeSnippetsBrowser)
                    {
                        ExpansionProvider ep = this.GetExpansionProvider();
                        if (this.TextView != null && ep != null)
                        {
                            bool bDisplayed = ep.DisplayExpansionBrowser(
                                this.TextView,
                                "TestLanguagePackage Snippet:",
                                null,
                                false,
                                null,
                                false);
                        }
                        return true;   // Handled the command.
                    }
                }
                return false;   // Did not handle the command.
            }
        }
    }
    

    Die folgenden Methoden in der ExpansionProvider-Klasse werden von Visual Studio in der angegebenen Reihenfolge während des Prozesses beim Einfügen des Ausschnitts aufgerufen:

  4. OnItemChosen

  5. IsValidKind

  6. OnBeforeInsertion

  7. FormatSpan

  8. OnAfterInsertion

    Nachdem die OnAfterInsertion-Methode aufgerufen wird, ist der Ausschnitt eingefügt und das ExpansionProvider-Objekt ist in einem speziellen Bearbeitungsmodus, der zum Ändern eines Ausschnitts verwendet wird, der gerade eingefügt wurde.

Wenn Sie einen Codeausschnitt mit einer Verknüpfung einfügen

Implementierung einer Verknüpfung aus der Vervollständigungsliste beteiligter ist wesentlich beim Implementieren eines Menübefehls. Sie müssen zuerst vervollständigungsliste Ausschnitts verknüpfungen der IntelliSense-Wort hinzufügen. Dann müssen Sie erkennen, wann verknüpfungsname aufgrund des Abschlusses eines Ausschnitts eingefügt wurde. Abschließend müssen Sie den Namen und Pfad des Ausschnitts mithilfe des Verknüpfungsnamens zu empfangen und diese Informationen InsertNamedExpansion-Methode für die ExpansionProvider-Methode übergeben.

Um Ausschnittsverknüpfungen der Wortvervollständigungsliste hinzuzufügen, fügen Sie sie dem Declarations-Objekt in der AuthoringScope-Klasse hinzu. Sie müssen sicherstellen, dass Sie die Verknüpfung als Name des Ausschnitts identifizieren können. Ein entsprechendes Beispiel finden Sie unter Exemplarische Vorgehensweise: Eine Liste der installierten Codeausschnitten (Managed Paketframework) abrufen.

Sie können das Einfügen des Codeausschnitts in der Verknüpfung OnAutoComplete-Methode der Declarations-Klasse erkennen. Da der Name des Ausschnitts bereits in die Quelldatei eingefügt wurde, muss er gelöscht werden, wenn die Erweiterung eingefügt wird. Die InsertNamedExpansion-Methode akzeptiert eine Spanne, die den Punkt der Einfügung für den Ausschnitt beschreibt. wenn die Spanne den vollständigen Namen des Ausschnitts in der Quelldatei enthalten ist, wird dieser durch den Ausschnitt ersetzt.

Im Folgenden finden Sie eine Version einer Klasse, die die angegebene Declarations Einfügen von Ausschnitts ein Verknüpfungsname behandelt. Andere Methoden in der Declarations-Klasse ist aus Gründen der Übersichtlichkeit weggelassen. Beachten Sie, dass der Konstruktor dieser Klasse ein LanguageService-Objekt akzeptiert. Dies kann sich von der Version des AuthoringScope-Objekts übergeben werden (z. B. leitete die Implementierung möglicherweise der AuthoringScope-Klasse das LanguageService-Objekt in seinem Konstruktor erstellen und dieses Objekt an den TestDeclarations-Klassenkonstruktor weiter).

[C#]
using Microsoft.VisualStudio.Package;
using Microsoft.VisualStudio.TextManager.Interop;

namespace TestLanguagePackage
{
    internal class TestDeclarations : Declarations
    {
        private ArrayList       declarations;
        private LanguageService languageService;
        private TextSpan        commitSpan;

        public TestDeclarations(LanguageService langService)
            : base()
        {
            languageService = langService;
            declarations = new ArrayList();
        }

        // This method is used to add declarations to the internal list.
        public void AddDeclaration(TestDeclaration declaration)
        {
            declarations.Add(declaration);
        }

        

        // This method is called to get the string to commit to the source buffer.
        // Note that the initial extent is only what the user has typed so far.
        public override string OnCommit(IVsTextView textView,
                                        string textSoFar,
                                        char commitCharacter,
                                        int index,
                                        ref TextSpan initialExtent)
        {
            // We intercept this call only to get the initial extent
            // of what was committed to the source buffer.
            commitSpan = initialExtent;

            return base.OnCommit(textView,
                                 textSoFar,
                                 commitCharacter,
                                 index,
                                 ref initialExtent);
        }

        // This method is called after the string has been committed to the source buffer.
        public override char OnAutoComplete(IVsTextView textView,
                                            string committedText,
                                            char commitCharacter,
                                            int index)
        {
            TestDeclaration item = declarations[index] as TestDeclaration;
            if (item != null)
            {
                // In this example, TestDeclaration identifies types with a string.
                // You can choose a different approach.
                if (item.Type == "snippet")
                {
                    Source src = languageService.GetSource(textView);
                    if (src != null)
                    {
                        ExpansionProvider ep = src.GetExpansionProvider();
                        if (ep != null)
                        {
                            string title;
                            string path;
                            int commitLength = commitSpan.iEndIndex - commitSpan.iStartIndex;
                            if (commitLength < committedText.Length)
                            {
                                // Replace everything that was inserted
                                // so calculate the span of the full
                                // insertion, taking into account what
                                // was inserted when the commitSpan
                                // was obtained in the first place.
                                commitSpan.iEndIndex += (committedText.Length - commitLength);
                            }

                            if (ep.FindExpansionByShortcut(textView,
                                                           committedText,
                                                           commitSpan,
                                                           true,
                                                           out title,
                                                           out path))
                            {
                                ep.InsertNamedExpansion(textView,
                                                        title,
                                                        path,
                                                        commitSpan,
                                                        false);
                            }
                        }
                    }
                }
            }
            return '\0';
        }
    }
}

Wenn der Sprachdienst den Verknüpfungsnamen abruft, ruft er die FindExpansionByShortcut-Methode auf, um den Dateinamen, und der Name des Codeausschnitts. Der Sprachdienst ruft dann die InsertNamedExpansion-Methode in der ExpansionProvider-Klasse, um den Codeausschnitt einzufügen. Die folgenden Methoden werden von Visual Studio in der angegebenen Reihenfolge in der ExpansionProvider-Klasse während des Prozesses beim Einfügen des Ausschnitts aufgerufen:

  1. IsValidKind

  2. OnBeforeInsertion

  3. FormatSpan

  4. OnAfterInsertion

Weitere Informationen zum Abrufen einer Liste der installierten Codeausschnitte für den Sprachdienst finden Sie unter Exemplarische Vorgehensweise: Eine Liste der installierten Codeausschnitten (Managed Paketframework) abrufen.

Die ExpansionFunctions-Klasse implementieren

Eine Funktion zum Add-In ist eine benannte Funktion, die in einer Vorlage Ausschnitts eingebettet und mindestens ein Feld wird auf zurückgibt, dass die Werte abgelegt werden. Um das Add-In im Sprachdienst Funktionen zu unterstützen, müssen Sie eine Klasse von der ExpansionFunction-Klasse ableiten und die GetCurrentValue-Methode implementieren. Sie müssen die CreateExpansionFunction-Methode in der LanguageService-Klasse dann überschreiben, um eine neue Instanziierung der Version der ExpansionFunction Feature Extensions für jede Klasse zurückzugeben, die Sie unterstützen. Wenn Sie eine Liste der möglichen Werte aus einer Funktion für Add-Ins unterstützen, müssen Sie die GetIntellisenseList-Methode in der ExpansionFunction-Klasse ebenfalls überschreiben, um eine Liste dieser Werte zurückzugeben.

Eine Erweiterung, die Argumente akzeptiert oder andere Felder zugreifen muss, sollte nicht mit einem bearbeitbaren Feld zugeordnet sind, da der Hersteller Add-In möglicherweise nicht vollständig initialisiert hätte, wenn die Funktion für Add-Ins aufgerufen wird. Daher ist das Feature für die Erweiterung nicht auf den Wert der Argumente oder eines anderen Felds.

Beispiel

Im Folgenden ein Beispiel dafür, wie eine einfache Erweiterung GetName-Funktion, die aufgerufen wird, implementiert würde. Diese Funktion wird eine Anzahl von Basisklassen in einen Namen an, der jedes Mal, wenn das Feature für Add-Ins instanziiert wird (die jedes Mal auf den zugeordneten Codeausschnitt eingefügt wird, ist).

using Microsoft.VisualStudio.Package;

namespace TestLanguagePackage
{
    public class TestLanguageService : LanguageService
    {
        private int classNameCounter = 0;

        public override ExpansionFunction CreateExpansionFunction(
            ExpansionProvider provider,
            string functionName)
        {
            ExpansionFunction function = null;
            if (functionName == "GetName")
            {
                ++classNameCounter;
                function = new TestGetNameExpansionFunction(provider, classNameCounter);
            }
            return function;
        }
    }

    internal class TestGetNameExpansionFunction : ExpansionFunction
    {
        private int nameCount;

        TestGetNameExpansionFunction(ExpansionProvider provider, int counter)
            : base(provider)
        {
            nameCount = counter;
        }

        public override string GetCurrentValue()
        {
            string name = "TestClass";
            name += nameCount.ToString();
            return name;
        }
    }
}

Siehe auch

Aufgaben

Exemplarische Vorgehensweise: Eine Liste der installierten Codeausschnitten (Managed Paketframework) abrufen

Konzepte

Wenn Sie einen Sprachdienst registrieren (Managed Paketframework)

Weitere Ressourcen

Sprachendienst-Funktionen (Managed Paketframework)

Codeausschnitte