Visual Studio 2010 has the new WPF-based code editor with unbelievable opportunities for extensions. There are at least 5 following reasons to get to know this technology.
- The Visual Studio team has created the new WPF-based code editor
- The code editor has simple and clean architecture
- Now MEF included in .NET 4.0 can be used for the Visual Studio extension
- The Editor was designed and implemented with extensibility in mind
- Creating the extensions is now much easier
In this article we will create the extension for Dart syntax highlighting:
Dart Scanner
To implement Dart syntax highlighting, the Lexical analyzer should be created first. The development of Dart language for the Eclipse platform is under way. There is a repository on Google Code, where everything connected with the Dart language and its integration into Eclipse can be found, along with the Dart language syntax that we are going to use to generate the syntax analyzer with ANTLR. After the lexical recognizer is created, we can move to its integration into Visual Studio.
We generate lexical analyzer with the following command:
java -cp antlrworks.jar org.antlr.Tool -o out/Dart.g
Classification for Syntax Highlighting
Dart Content Type Definition
To set our extension module to highlight .dart files only, we should define a new content type that will represent .dart files. To do that we need to use ContentTypeDefinition and FileExtenionToContentTypeDefinition
// Constants.ContentType = "dart"
internal static class DartContentTypeDefinition
{
[Export]
[Name(Constants.ContentType)]
[BaseDefinition("text")]
internal static ContentTypeDefinition ContentTypeDefinition { get; set; }
[Export]
[FileExtension(".dart")]
[ContentType(Constants.ContentType)]
internal static FileExtensionToContentTypeDefinition FileExtensionDefinition { get; set; }
...
Dart Classification Format Definition
When we have a text span matching with a classification type we probably want to define a format for it to visualize its classification.
To do that we have ClassificationFormatDefinition
For example, ClassificationFormatDefinition for key words:
[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = Constants.KeywordClassType)]
[Name("Dart.KeywordClassificationFormat")]
[UserVisible(true)]
[Order(Before = Priority.Default)]
internal sealed class KeywordClassificationFormat : ClassificationFormatDefinition
{
public KeywordClassificationFormat()
{
this.DisplayName = "Dart Keyword";
this.ForegroundColor = Colors.Blue;
}
}
internal static class DartContentTypeDefinition
{
[Export(typeof(ClassificationTypeDefinition))]
[Name(Constants.KeywordClassType)]
internal static ClassificationTypeDefinition KeywordClassificationType { get; set; }
..
Dart Classifier
To implement Dart language highlighting, the following interfaces should be implemented:
Classifier is a core of the highlighting module; it implements IClassifier
class Classifier : IClassifier
{
public event EventHandler ClassificationChanged;
internal Classifier(ITextBuffer buffer, IDartClassificationTypeRegistryService registry)
{
_buffer = buffer;
_registry = registry;
_buffer.Changed += this.OnTextBufferChanged;
}
...
We subscribe to the event ITextBuffer ITextBuffer. Changed to highlight certain part of a code at every change.
public event EventHandler ClassificationChanged;
private void OnTextBufferChanged(object sender, TextContentChangedEventArgs e)
{
ClassificationChanged(this, new ClassificationChangedEventArgs(
new SnapshotSpan(_buffer.CurrentSnapshot, 0, _buffer.CurrentSnapshot.Length)));
}
The objective of this event is the notification about the necessity of highlighting certain part of the text.
The key Classifier method is:
public IList GetClassificationSpans(SnapshotSpan span)
{
var calassificationSpans = new List();
var lexer = new DartLexer(new ANTLRStringStream(_buffer.CurrentSnapshot.GetText(span)));
...
That uses DartLexer for tokens recognition.
The input parameter for this method is a SnapshotSpan instance. Snapshots are new objects in the editor model, their role is to provide a context where the underlying editor context is immutable (a snapshot in a time point). Snapshots are good concepts to exempt developers from coping with asynchronous changes on the content of the editor. The SnapshotSpan here represents the immutable part of the text to classify.
This method returns the list of objects ClassificationSpan. We can receive them with IDartClassificationTypeRegistryService. This is a help-service that was created to provide information about formatting certain tokens.
interface IDartClassificationTypeRegistryService
{
bool TryGetGetClassificationType(int token, out IClassificationType classificationType);
}
Dart Classifier Provider
After the Classifier is created, we only need to implement IclassifierProvider
[Export(typeof(IClassifierProvider))]
[ContentType(Constants.ContentType)]
[Name("Dart Classifier")]
[Order(Before = "default")]
internal class DartClassifierProvider : IClassifierProvider
{
[Import]
internal IDartClassificationTypeRegistryService TypeRegistry { get; set; }
#region IClassifierProvider Members
//returns an instance of the classifier
public IClassifier GetClassifier(ITextBuffer buffer)
{
return buffer.Properties.GetOrCreateSingletonProperty(() => new Classifier(buffer, TypeRegistry));
}
#endregion
}
You can find the examples of how these classes work within a DartLanguage module.
The full source for this article is available on GitHub.
https://github.com/codedrive/dart-syntax
1 Comment:
Thanks for sharing informations
Blog Keperawatan March 5th, 2012 at 8:57 am