Sono un po 'in ritardo alla festa, ma hey, perché non gettare i miei 2 centesimi in
Come si è spiegato nella sua interrogazione, il progetto ha due parti fondamentali:.
- Trovare le classi che implementano
IDisposable
- Evidenziando loro
il primo è di gran lunga la più difficile, ma non impossibile. Un approccio basato su elenco di parole è probabilmente il più semplice, anche se dovrebbe essere possibile con Roslyn per capire al volo quali classi ereditano lo IDisposible
.
Si potrebbe anche sempre ricorrere al caricamento del file .exe/.dll compilato del progetto in background dopo una compilazione e capire quali sono i tipi lì, ma si dovrebbe comunque scrivere un codice di colla magica per capire cosa nomi di classi brevi nel codice si riferiscono a quali sono le attuali classi complete nell'assembly.
La seconda parte, evidenziando, è abbastanza facile una volta che si sa come farlo (è utile che abbia trascorso gli ultimi mesi a lavorare a tempo pieno sull'estensione del VS). Naturalmente, con Visual Studio, nulla è così semplice come sembra (nonostante gli sforzi di Microsoft per cercare di renderlo di facile utilizzo). Quindi, ho creato un'estensione di esempio che mette in evidenza solo le classi denominate "Stream" all'interno di file C# per iniziare.
Il codice in questione è al di sotto, e la piena project source is on GitHub). Si inizia con un fornitore di classificazione-tagger:
[Export(typeof(ITaggerProvider))]
[ContentType("CSharp")]
[TagType(typeof(ClassificationTag))]
[Name("HighlightDisposableTagger")]
public class HighlightDisposableTaggerProvider : ITaggerProvider
{
[Import]
private IClassificationTypeRegistryService _classificationRegistry = null;
[Import]
private IClassifierAggregatorService _classifierAggregator = null;
private bool _reentrant;
public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
{
if (_reentrant)
return null;
try {
_reentrant = true;
var classifier = _classifierAggregator.GetClassifier(buffer);
return new HighlightDisposableTagger(buffer, _classificationRegistry, classifier) as ITagger<T>;
}
finally {
_reentrant = false;
}
}
}
Poi il tagger stesso:
public class HighlightDisposableTagger : ITagger<ClassificationTag>
{
private const string DisposableFormatName = "HighlightDisposableFormat";
[Export]
[Name(DisposableFormatName)]
public static ClassificationTypeDefinition DisposableFormatType = null;
[Export(typeof(EditorFormatDefinition))]
[Name(DisposableFormatName)]
[ClassificationType(ClassificationTypeNames = DisposableFormatName)]
[UserVisible(true)]
public class DisposableFormatDefinition : ClassificationFormatDefinition
{
public DisposableFormatDefinition()
{
DisplayName = "Disposable Format";
ForegroundColor = Color.FromRgb(0xFF, 0x00, 0x00);
}
}
public event EventHandler<SnapshotSpanEventArgs> TagsChanged = delegate { };
private ITextBuffer _subjectBuffer;
private ClassificationTag _tag;
private IClassifier _classifier;
private bool _reentrant;
public HighlightDisposableTagger(ITextBuffer subjectBuffer, IClassificationTypeRegistryService typeService, IClassifier classifier)
{
_subjectBuffer = subjectBuffer;
var classificationType = typeService.GetClassificationType(DisposableFormatName);
_tag = new ClassificationTag(classificationType);
_classifier = classifier;
}
public IEnumerable<ITagSpan<ClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans)
{
if (_reentrant) {
return Enumerable.Empty<ITagSpan<ClassificationTag>>();
}
var tags = new List<ITagSpan<ClassificationTag>>();
try {
_reentrant = true;
foreach (var span in spans) {
if (span.IsEmpty)
continue;
foreach (var token in _classifier.GetClassificationSpans(span)) {
if (token.ClassificationType.IsOfType(/*PredefinedClassificationTypeNames.Identifier*/ "User Types")) {
// TODO: Somehow figure out if this refers to a class which implements IDisposable
if (token.Span.GetText() == "Stream") {
tags.Add(new TagSpan<ClassificationTag>(token.Span, _tag));
}
}
}
}
return tags;
}
finally {
_reentrant = false;
}
}
}
ho testato solo questo su VS2010, ma dovrebbe funzionare per VS2013 troppo (l'unica cosa che potrebbe essere diverso è il nome della classificazione di classe, ma è facile da scoprire con un breakpoint ben piazzato). Non ho mai scritto un'estensione per VS2012, quindi non posso commentare su questo, ma so che è abbastanza vicino a VS2013 per molti aspetti.
Questo sarebbe meraviglioso. – TyCobb
Ho scaricato il codice dell'interno e l'ho eseguito localmente, sembra che funzioni correttamente per me. L'unica differenza che posso pensare è che sto correndo in VS2012 rispetto al 2010, quindi ho dovuto rifare un progetto e copiare il codice. il tuo vsixmanifest non ha funzionato bene sul mio computer, forse l'aggiornamento 2010-> 2012 l'ha rotto in qualche modo –
Vedi i miei aggiornamenti sul testo del tooltip. Sto fraintendendo cosa sia un editor di classificatore? –