Punti di estensione del servizio di linguaggio e dell'editor

L'editor fornisce punti di estensione che è possibile estendere come parti del componente MEF (Managed Extensibility Framework), inclusa la maggior parte delle funzionalità del servizio di linguaggio. Queste sono le categorie principali di punti di estensione:

  • Tipi di contenuto

  • Tipi di classificazione e formati di classificazione

  • Margini e barre di scorrimento

  • Tag

  • Ornamenti

  • Processori del mouse

  • Eliminare i gestori

  • Opzioni

  • IntelliSense

Estendere i tipi di contenuto

I tipi di contenuto sono le definizioni dei tipi di testo gestiti dall'editor, ad esempio "text", "code" o "CSharp". Per definire un nuovo tipo di contenuto, dichiarare una variabile del tipo ContentTypeDefinition e assegnare al nuovo tipo di contenuto un nome univoco. Per registrare il tipo di contenuto con l'editor, esportarlo insieme agli attributi seguenti:

  • NameAttribute è il nome del tipo di contenuto.

  • BaseDefinitionAttribute è il nome del tipo di contenuto da cui deriva questo tipo di contenuto. Un tipo di contenuto può ereditare da più tipi di contenuto.

    Poiché la ContentTypeDefinition classe è sealed, è possibile esportarla senza alcun parametro di tipo.

    Nell'esempio seguente vengono illustrati gli attributi di esportazione in una definizione del tipo di contenuto.

[Export]
[Name("test")]
[BaseDefinition("code")]
[BaseDefinition("projection")]
internal static ContentTypeDefinition TestContentTypeDefinition;

I tipi di contenuto possono essere basati su zero o più tipi di contenuto preesistenti. Questi sono i tipi predefiniti:

  • Any: tipo di contenuto di base. Padre di tutti gli altri tipi di contenuto.

  • Testo: tipo di base per il contenuto non di proiezione. Eredita da "any".

  • Testo non crittografato: per il testo non codificato. Eredita da "text".

  • Codice: per il codice di tutti i tipi. Eredita da "text".

  • Inert: esclude il testo da qualsiasi tipo di gestione. Il testo di questo tipo di contenuto non avrà mai alcuna estensione applicata.

  • Proiezione: per il contenuto dei buffer di proiezione. Eredita da "any".

  • IntelliSense: per il contenuto di IntelliSense. Eredita da "text".

  • Sighelp: guida alla firma. Eredita da "intellisense".

  • Sighelp-doc: documentazione della Guida alla firma. Eredita da "intellisense".

    Questi sono alcuni dei tipi di contenuto definiti da Visual Studio e alcuni dei linguaggi ospitati in Visual Studio:

  • Di base

  • C/C++

  • ConsoleOutput

  • CSharp

  • CSS

  • ENC

  • FindResults

  • F#

  • HTML

  • JScript

  • XAML

  • XML

    Per individuare l'elenco dei tipi di contenuto disponibili, importare , IContentTypeRegistryServiceche gestisce la raccolta di tipi di contenuto per l'editor. Il codice seguente importa questo servizio come proprietà.

[Import]
internal IContentTypeRegistryService ContentTypeRegistryService { get; set; }

Per associare un tipo di contenuto a un'estensione di file, usare FileExtensionToContentTypeDefinition.

Nota

In Visual Studio le estensioni dei nomi di file vengono registrate usando in ProvideLanguageExtensionAttribute un pacchetto del servizio di linguaggio. Associa FileExtensionToContentTypeDefinition un tipo di contenuto MEF a un'estensione di file registrata in questo modo.

Per esportare l'estensione del nome file nella definizione del tipo di contenuto, è necessario includere gli attributi seguenti:

[Export]
[FileExtension(".test")]
[ContentType("test")]
internal static FileExtensionToContentTypeDefinition TestFileExtensionDefinition;

IFileExtensionRegistryService Gestisce le associazioni tra le estensioni di file e i tipi di contenuto.

Estendere i tipi di classificazione e i formati di classificazione

È possibile usare i tipi di classificazione per definire i tipi di testo per cui si desidera fornire una gestione diversa, ad esempio colorando il testo "parola chiave" blu e il testo "commento" verde. Definire un nuovo tipo di classificazione dichiarando una variabile di tipo ClassificationTypeDefinition e assegnando un nome univoco.

Per registrare il tipo di classificazione con l'editor, esportarlo insieme agli attributi seguenti:

  • NameAttribute: nome del tipo di classificazione.

  • BaseDefinitionAttribute: nome del tipo di classificazione da cui eredita questo tipo di classificazione. Tutti i tipi di classificazione ereditano da "text" e un tipo di classificazione può ereditare da più altri tipi di classificazione.

    Poiché la ClassificationTypeDefinition classe è sealed, è possibile esportarla senza alcun parametro di tipo.

    Nell'esempio seguente vengono illustrati gli attributi di esportazione in una definizione di tipo di classificazione.

[Export]
[Name("csharp.test")]
[BaseDefinition("test")]
internal static ClassificationTypeDefinition CSharpTestDefinition;

IStandardClassificationService fornisce l'accesso alle classificazioni standard. I tipi di classificazione predefiniti includono:

  • "text"

  • "linguaggio naturale" (deriva da "text")

  • "linguaggio formale" (deriva da "text")

  • "string" (deriva da "literal")

  • "character" (deriva da "literal")

  • "numerico" (deriva da "literal")

    Un set di tipi di errore diversi eredita da ErrorTypeDefinition. Includono i tipi di errore seguenti:

  • "errore di sintassi"

  • "errore del compilatore"

  • "altro errore"

  • "warning"

    Per individuare l'elenco dei tipi di classificazione disponibili, importare , IClassificationTypeRegistryServiceche gestisce la raccolta di tipi di classificazione per l'editor. Il codice seguente importa questo servizio come proprietà.

[Import]
internal IClassificationTypeRegistryService ClassificationTypeRegistryService { get; set; }

È possibile definire una definizione di formato di classificazione per il nuovo tipo di classificazione. Derivare una classe da ClassificationFormatDefinition ed esportarla con il tipo EditorFormatDefinition, insieme agli attributi seguenti:

  • NameAttribute: nome del formato.

  • DisplayNameAttribute: nome visualizzato del formato.

  • UserVisibleAttribute: specifica se il formato viene visualizzato nella pagina Tipi di carattere e colori della finestra di dialogo Opzioni .

  • OrderAttribute: priorità del formato. I valori validi provengono da Priority.

  • ClassificationTypeAttribute: nome del tipo di classificazione a cui viene eseguito il mapping di questo formato.

    L'esempio seguente mostra gli attributi di esportazione in una definizione di formato di classificazione.

[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = "test")]
[Name("test")]
[DisplayName("Test")]
[UserVisible(true)]
[Order(After = Priority.Default, Before = Priority.High)]
internal sealed class TestFormat : ClassificationFormatDefinition

Per individuare l'elenco dei formati disponibili, importare , IEditorFormatMapServiceche gestisce la raccolta di formati per l'editor. Il codice seguente importa questo servizio come proprietà.

[Import]
internal IEditorFormatMapService FormatMapService { get; set; }

Estendere i margini e le barre di scorrimento

Margini e barre di scorrimento sono gli elementi di visualizzazione principali dell'editor oltre alla visualizzazione testo stessa. È possibile specificare un numero qualsiasi di margini oltre ai margini standard visualizzati intorno alla visualizzazione testo.

Implementare un'interfaccia IWpfTextViewMargin per definire un margine. È inoltre necessario implementare l'interfaccia IWpfTextViewMarginProvider per creare il margine.

Per registrare il provider di margini con l'editor, è necessario esportare il provider insieme agli attributi seguenti:

  • NameAttribute: nome del margine.

  • OrderAttribute: l'ordine in cui viene visualizzato il margine, rispetto agli altri margini.

    Questi sono i margini predefiniti:

    • "Barra di scorrimento orizzontale wpf"

    • "Barra di scorrimento verticale wpf"

    • "Margine numero riga wpf"

      I margini orizzontali con un attributo order di After="Wpf Horizontal Scrollbar" vengono visualizzati sotto il margine predefinito e i margini orizzontali con un attributo order di Before ="Wpf Horizontal Scrollbar" vengono visualizzati sopra il margine predefinito. I margini verticali destro con un attributo order di After="Wpf Vertical Scrollbar" vengono visualizzati a destra della barra di scorrimento. I margini verticali sinistro con un attributo order di appaiono a sinistra del margine del numero di After="Wpf Line Number Margin" riga (se visibile).

  • MarginContainerAttribute: tipo di margine (sinistro, destro, superiore o inferiore).

  • ContentTypeAttribute: tipo di contenuto (ad esempio, "text" o "code") per cui il margine è valido.

    Nell'esempio seguente vengono illustrati gli attributi di esportazione in un provider di margini per un margine visualizzato a destra del margine del numero di riga.

[Export(typeof(IWpfTextViewMarginProvider))]
[Name("TestMargin")]
[Order(Before = "Wpf Line Number Margin")]
[MarginContainer(PredefinedMarginNames.Left)]
[ContentType("text")]

Estendere i tag

I tag sono un modo per associare i dati a diversi tipi di testo. In molti casi, i dati associati vengono visualizzati come effetto visivo, ma non tutti i tag hanno una presentazione visiva. È possibile definire il proprio tipo di tag implementando ITag. È inoltre necessario implementare ITagger<T> per specificare i tag per un determinato set di intervalli di testo e un oggetto ITaggerProvider per fornire il tagger. È necessario esportare il provider di tagger insieme agli attributi seguenti:

  • ContentTypeAttribute: tipo di contenuto (ad esempio, "text" o "code") per cui il tag è valido.

  • TagTypeAttribute: tipo di tag.

    L'esempio seguente mostra gli attributi di esportazione in un provider di tagger.

<CodeContentPlaceHolder>8 I tipi di tag seguenti sono incorporati:

[Import]
internal IViewTagAggregatorFactoryService ViewTagAggregatorFactoryService { get; set; }

Tag e MarkerFormatDefinitions

È possibile estendere la MarkerFormatDefinition classe per definire l'aspetto di un tag. È necessario esportare la classe (come EditorFormatDefinition)con gli attributi seguenti:

  • NameAttribute: nome utilizzato per fare riferimento a questo formato

  • UserVisibleAttribute: in questo modo il formato viene visualizzato nell'interfaccia utente

    Nel costruttore si definiscono il nome visualizzato e l'aspetto del tag. BackgroundColor definisce il colore di riempimento e ForegroundColor definisce il colore del bordo. DisplayName è il nome localizzabile della definizione di formato.

    Di seguito è riportato un esempio di definizione di formato:

[Export(typeof(EditorFormatDefinition))]
[Name("MarkerFormatDefinition/HighlightWordFormatDefinition")]
[UserVisible(true)]
internal class HighlightWordFormatDefinition : MarkerFormatDefinition
{
    public HighlightWordFormatDefinition()
    {
        this.BackgroundColor = Colors.LightBlue;
        this.ForegroundColor = Colors.DarkBlue;
        this.DisplayName = "Highlight Word";
        this.ZOrder = 5;
    }
}

Per applicare questa definizione di formato a un tag, fare riferimento al nome impostato nell'attributo name della classe (non il nome visualizzato).

Nota

Per un esempio di MarkerFormatDefinition, vedere la classe HighlightWordFormatDefinition in Procedura dettagliata: Evidenziazione del testo.

Estendere le decorazioni

Gli oggetti decorativi definiscono gli effetti visivi che possono essere aggiunti al testo visualizzato in una visualizzazione testo o alla visualizzazione testo stessa. È possibile definire la propria decorazione come qualsiasi tipo di UIElement.

Nella classe di adornamento è necessario dichiarare un oggetto AdornmentLayerDefinition. Per registrare il livello di adornamento, esportarlo insieme agli attributi seguenti:

  • NameAttribute: nome della decorazione.

  • OrderAttribute: l'ordinamento della decorazione rispetto ad altri livelli di adornamento. La classe PredefinedAdornmentLayers definisce quattro livelli predefiniti: Selection, Outlining, Caret e Text.

    L'esempio seguente mostra gli attributi di esportazione in una definizione del livello di adornamento.

[Export]
[Name("TestEmbeddedAdornment")]
[Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)]
internal AdornmentLayerDefinition testLayerDefinition;

È necessario creare una seconda classe che implementa IWpfTextViewCreationListener e gestisce il relativo TextViewCreated evento creando un'istanza dello strumento decorativo. È necessario esportare questa classe insieme agli attributi seguenti:

  • ContentTypeAttribute: tipo di contenuto (ad esempio, "text" o "code") per cui l'elemento decorativo è valido.

  • TextViewRoleAttribute: tipo di visualizzazione testo per cui questa struttura è valida. La classe PredefinedTextViewRoles ha il set di ruoli di visualizzazione testo predefiniti. Ad esempio, Document viene usato principalmente per le visualizzazioni di testo dei file. Interactive viene usato per le visualizzazioni di testo che un utente può modificare o spostarsi usando un mouse e una tastiera. Esempi di Interactive visualizzazioni sono la visualizzazione testo dell'editor e la finestra Output .

    Nell'esempio seguente vengono illustrati gli attributi di esportazione nel provider di strumenti decorativi.

[Export(typeof(IWpfTextViewCreationListener))]
[ContentType("csharp")]
[TextViewRole(PredefinedTextViewRoles.Document)]
internal sealed class TestAdornmentProvider : IWpfTextViewCreationListener

Uno spazio negoziale è uno che occupa lo spazio allo stesso livello del testo. Per creare questo tipo di strumento decorativo, è necessario definire una classe di tag che eredita da SpaceNegotiatingAdornmentTag, che definisce la quantità di spazio occupata dall'adornamento.

Come per tutte le decorazioni, è necessario esportare la definizione del livello di adornazione.

[Export]
[Name("TestAdornment")]
[Order(After = DefaultAdornmentLayers.Text)]
internal AdornmentLayerDefinition testAdornmentLayer;

Per creare un'istanza dello strumento decorativo per la negoziazione dello spazio, è necessario creare una classe che implementa ITaggerProvider, oltre alla classe che implementa IWpfTextViewCreationListener (come con altri tipi di oggetti decorativi).

Per registrare il provider di tagger, è necessario esportarlo insieme agli attributi seguenti:

  • ContentTypeAttribute: tipo di contenuto (ad esempio, "text" o "code") per il quale la decorazione è valida.

  • TextViewRoleAttribute: tipo di visualizzazione testo per cui questo tag o strumento decorativo è valido. La classe PredefinedTextViewRoles ha il set di ruoli di visualizzazione testo predefiniti. Ad esempio, Document viene usato principalmente per le visualizzazioni di testo dei file. Interactive viene usato per le visualizzazioni di testo che un utente può modificare o spostarsi usando un mouse e una tastiera. Esempi di Interactive visualizzazioni sono la visualizzazione testo dell'editor e la finestra Output .

  • TagTypeAttribute: tipo di tag o adornamento definito. È necessario aggiungere un secondo TagTypeAttribute per SpaceNegotiatingAdornmentTag.

    L'esempio seguente mostra gli attributi di esportazione nel provider di tagger per un tag di adornamento negoziale.

[Export(typeof(ITaggerProvider))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
[TagType(typeof(SpaceNegotiatingAdornmentTag))]
[TagType(typeof(TestSpaceNegotiatingTag))]
internal sealed class TestTaggerProvider : ITaggerProvider

Estensione dei processori del mouse

È possibile aggiungere una gestione speciale per l'input del mouse. Creare una classe che eredita da MouseProcessorBase ed eseguire l'override degli eventi del mouse per l'input da gestire. È inoltre necessario implementarlo IMouseProcessorProvider in una seconda classe ed esportarlo insieme a ContentTypeAttribute che specifica il tipo di contenuto (ad esempio, "text" o "code") per il quale il gestore del mouse è valido.

L'esempio seguente mostra gli attributi di esportazione in un provider del processore del mouse.

[Export(typeof(IMouseProcessorProvider))]
[Name("test mouse processor")]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Interactive)]
internal sealed class TestMouseProcessorProvider : IMouseProcessorProvider

Estendere i gestori di rilascio

È possibile personalizzare il comportamento dei gestori di rilascio per tipi specifici di testo creando una classe che implementa IDropHandler e una seconda classe che implementa IDropHandlerProvider per creare il gestore di rilascio. È necessario esportare il gestore di rilascio insieme agli attributi seguenti:

  • DropFormatAttribute: formato di testo per il quale il gestore di rilascio è valido. I formati seguenti vengono gestiti in ordine di priorità dal più alto al più basso:

    1. Qualsiasi formato personalizzato

    2. Filedrop

    3. EnhancedMetafile

    4. Waveaudio

    5. Riff

    6. Dif

    7. Impostazioni locali

    8. Tavolozza

    9. PenData

    10. Serializable

    11. SimbolicoLink

    12. Xaml

    13. XamlPackage

    14. Tiff

    15. Bitmap

    16. Dib

    17. MetafilePicture

    18. CSV

    19. System.String

    20. Formato HTML

    21. Unicodetext

    22. OEMText

    23. Testo

  • NameAttribute: nome del gestore di rilascio.

  • OrderAttribute: l'ordinamento del gestore di rilascio prima o dopo il gestore di rilascio predefinito. Il gestore di rilascio predefinito per Visual Studio è denominato "DefaultFileDropHandler".

    Nell'esempio seguente vengono illustrati gli attributi di esportazione in un provider del gestore di rilascio.

[Export(typeof(IDropHandlerProvider))]
[DropFormat("Text")]
[Name("TestDropHandler")]
[Order(Before="DefaultFileDropHandler")]
internal class TestDropHandlerProvider : IDropHandlerProvider

Estensione delle opzioni dell'editor

È possibile definire opzioni valide solo in un determinato ambito, ad esempio in una visualizzazione testo. L'editor fornisce questo set di opzioni predefinite: opzioni dell'editor, opzioni di visualizzazione e opzioni di visualizzazione di Windows Presentation Foundation (WPF). Queste opzioni sono disponibili in DefaultOptions, DefaultTextViewOptionse DefaultWpfViewOptions.

Per aggiungere una nuova opzione, derivare una classe da una di queste classi di definizione di opzione:

[Export(typeof(EditorOptionDefinition))]
internal sealed class TestOption : EditorOptionDefinition<bool>

Estendere IntelliSense

IntelliSense è un termine generale per un gruppo di funzionalità che forniscono informazioni sul testo strutturato e sul completamento delle istruzioni. Queste funzionalità includono il completamento delle istruzioni, la Guida alla firma, le informazioni rapide e le lampadine. Il completamento dell'istruzione consente agli utenti di digitare correttamente una parola chiave del linguaggio o un nome membro. La Guida alla firma visualizza la firma o le firme per il metodo appena digitato dall'utente. Le informazioni rapide visualizzano una firma completa per un tipo o un nome di membro quando il mouse si posiziona su di esso. La lampadina fornisce azioni aggiuntive per determinati identificatori in determinati contesti, ad esempio ridenominazione di tutte le occorrenze di una variabile dopo la ridenominazione di un'occorrenza.

La progettazione di una funzionalità IntelliSense è molto identica in tutti i casi:

  • Un broker IntelliSense è responsabile del processo complessivo.

  • Una sessione IntelliSense rappresenta la sequenza di eventi tra il trigger del relatore e il commit o l'annullamento della selezione. La sessione viene in genere attivata da alcuni movimenti dell'utente.

  • Un controller IntelliSense è responsabile della decisione dell'avvio e della fine della sessione. Decide anche quando eseguire il commit delle informazioni e quando la sessione deve essere annullata.

  • Un'origine IntelliSense fornisce il contenuto e decide la corrispondenza migliore.

  • Un relatore IntelliSense è responsabile della visualizzazione del contenuto.

    Nella maggior parte dei casi, è consigliabile fornire almeno un'origine e un controller. È anche possibile fornire un relatore se si vuole personalizzare lo schermo.

Implementare un'origine IntelliSense

Per personalizzare un'origine, è necessario implementare una o più interfacce di origine seguenti:

Importante

ISmartTagSource è stato deprecato a favore di ISuggestedActionsSource.

Inoltre, è necessario implementare un provider dello stesso tipo:

Importante

ISmartTagSourceProvider è stato deprecato a favore di ISuggestedActionsSourceProvider.

È necessario esportare il provider insieme agli attributi seguenti:

  • NameAttribute: nome dell'origine.

  • ContentTypeAttribute: tipo di contenuto (ad esempio, "text" o "code") a cui si applica l'origine.

  • OrderAttribute: l'ordine in cui deve essere visualizzata l'origine (rispetto ad altre origini).

  • Nell'esempio seguente vengono illustrati gli attributi di esportazione in un provider di origine di completamento.

Export(typeof(ICompletionSourceProvider))]
[Name(" Test Statement Completion Provider")]
[Order(Before = "default")]
[ContentType("text")]
internal class TestCompletionSourceProvider : ICompletionSourceProvider

Per altre informazioni sull'implementazione di origini IntelliSense, vedere le procedure dettagliate seguenti:

Implementare un controller IntelliSense

Per personalizzare un controller, è necessario implementare l'interfaccia IIntellisenseController . Inoltre, è necessario implementare un provider di controller insieme agli attributi seguenti:

  • NameAttribute: nome del controller.

  • ContentTypeAttribute: tipo di contenuto (ad esempio, "text" o "code") a cui si applica il controller.

  • OrderAttribute: l'ordine in cui deve essere visualizzato il controller (rispetto ad altri controller).

    Nell'esempio seguente vengono illustrati gli attributi di esportazione in un provider di controller di completamento.

Export(typeof(IIntellisenseControllerProvider))]
[Name(" Test Controller Provider")]
[Order(Before = "default")]
[ContentType("text")]
internal class TestIntellisenseControllerProvider : IIntellisenseControllerProvider

Per altre informazioni sull'uso dei controller IntelliSense, vedere le procedure dettagliate seguenti: