SixPairs

March 31, 2012

Highlight Classifier for Visual Studio Editor

Filed under: VS Editor — Tags: — Ceyhun Ciper @ 23:48

Sometimes you just want to see the data in a C# file:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.Utilities;
 
namespace Microsoft.VisualStudio.Text.Classification
{
	public static class Definitions
	{
		[Export(typeof(ClassificationTypeDefinition))]
		[Name("hilite-data")]
		internal static ClassificationTypeDefinition CTD;
 
		[Export(typeof(EditorFormatDefinition))]
		[ClassificationType(ClassificationTypeNames = "hilite-data")]
		[Name("hilite-data")]
		[DisplayName("Highlight Data")]
		[UserVisible(true)]
		[Order(Before = Priority.High)]
		internal sealed class CFD : ClassificationFormatDefinition
		{
			public CFD()
			{
				this.ForegroundColor = System.Windows.Media.Colors.LightGray;
			}
		}
 
		public static bool IsToBeHilited(this string classification)
		{
			var hilites = new[] { "string", "comment" };
			return hilites.Contains(classification.ToLower());
		}
	}
 
	[Export(typeof(IClassifierProvider))]
	[ContentType("CSharp")]
	internal sealed class HiliteDataClassifierProvider : IClassifierProvider
	{
		[Import]
		IClassificationTypeRegistryService ctrs = null;
		[Import]
		internal IClassifierAggregatorService AggregatorService = null;
 
		internal static bool ignoreRequest = false;
 
		public IClassifier GetClassifier(ITextBuffer textBuffer)
		{
			if (ignoreRequest)
				return null;
 
			try
			{
				ignoreRequest = true;
				return textBuffer.Properties.GetOrCreateSingletonProperty(
					() => new HiliteDataClassifier(AggregatorService.GetClassifier(textBuffer), ctrs));
			}
			finally
			{
				ignoreRequest = false;
			}
		}
	}
 
	internal sealed class HiliteDataClassifier : IClassifier
	{
		private IClassifier aggregator;
		private IClassificationTypeRegistryService ctrs;
 
		public HiliteDataClassifier(IClassifier aggregator, IClassificationTypeRegistryService ctrs)
		{
			this.aggregator = aggregator;
			this.ctrs = ctrs;
		}
 
		public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
		{
			var classifiedSpans =
				from cs in aggregator.GetClassificationSpans(span)
				let c = cs.ClassificationType.Classification
				where c.IsToBeHilited()
				select cs.Span;
 
			NormalizedSnapshotSpanCollection ignored = new NormalizedSnapshotSpanCollection(classifiedSpans);
			NormalizedSnapshotSpanCollection request = new NormalizedSnapshotSpanCollection(span);
 
			var spansToIgnore = NormalizedSnapshotSpanCollection.Difference(request, ignored);
 
			IClassificationType ct = ctrs.GetClassificationType("hilite-data");
 
			return spansToIgnore.Select(s => new ClassificationSpan(s, ct)).ToList();
		}
 
		public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
	}
}

 

This is for my own consumption (being a blog and what not); use it at your own peril.

2 Comments »

  1. Nice article. But I have difficulties trying it out. Is this is full code? If no where could I get full code.

    Comment by getoncpp — July 19, 2013 @ 07:29

    • No, I am afraid this is not the whole project; I recommend you study the editor extensibility articles on MSDN and play with the VSSDK samples.

      Comment by Ceyhun Ciper — July 25, 2013 @ 21:06


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.