Building language plugin on top of HtmlLanguage

Hi everyone,

I want to build DotHTML language plugin for R# (and Rider of course). The language is based on top of HTML and is similar to Razor. It's used in DotVVM web application framework. The problem is... I have no idea where to start and docs are not very helpful. I'd like to reuse as much of existing solutions as possible (eg. language injections, prefixed HTML elements). I hope you can answer my questions.

1) How to build Lexer

I guess it would be best to use the HtmlCompoundLexer which accepts baseLexer as second parameter. But I can't figure out how should it work. Is the baseLexer supposed to handle just parts that can't be handled by the underlying HtmlLexer? Can such lexer be generated with the CsLex tool? If so, would you mind sharing grammar for Razor lexer as an example?

2) How to handle parts with special meaning

The DotHTML language have some parts with special meaning:

  • Prefixed HTML elements. Similar to Razor tag helpers or ASPX controls.
  • Binding expressions. Special HTML attribute value containing limited C# expression.
  • Directives similar to Razor directives (@model, @using, etc.).

Are there any services I can use to implement these features? How to build custom IntelliSense?

3) How to enable Syntax coloring

Does R# handle syntax coloring in any way? Or does it rely entirely on Visual Studio? How will it work in Rider?

Thank you!

5 comments
Comment actions Permalink
Official comment

Hi Dušan. Firstly, I'd like to manage expectations - writing new language support in ReSharper extensions is a big job. There is a lot to do to get it working, and HTML-like syntax makes it harder, as you want to support both the custom language and the HTML as well. But that's also the same thing that makes it fun! :)

You're right in looking at HtmlCompoundLexer. This is how you work with a custom syntax built on top of HTML, and is how we implement e.g. Razor and WebForms. I've just written about it in the devguide. Annoyingly, deployment is currently broken, so I can't update the web site until after the weekend, but here is the introduction, and here's the details on lexing custom file formats and some notes on extending HTML files.

Our Razor support is built with CsLex, but it's also the most complex lexer we have (Razor is a very complex file format to parse). You can build a simple lexer that handles the "@" directives and then returns a RAW_HTML node (that you define) for the parts that you want parsed as HTML. The template syntax looks very similar to Angular expressions, so I'd suggest taking a look at how the Angular support works (overriding the HTML lexer, as opposed to your custom language lexer). There are some notes on that in the extending HTML files section. And prefixed elements should just be parsed by the normal HTML lexer/parser. You can add validation and code completion and so on after the lexing/parsing is complete.

ReSharper mostly leaves syntax highlighting to Visual Studio. It can add "semantic highlighting", which is used to colour different kinds of identifiers (local variables, method, interfaces, etc.). This is based on the usual ReSharper highlighting mechanism - but instead of returning a highlight attribute that defines a "squiggly" error/warning underline, it returns an attribute that changes the colour of the token's text. This can also be used to provide syntax highlighting. Rider has a similar, but slightly different mechanism - semantic highlighting is still handled in the same way, but there's infrastructure that provides an earlier pass of highlighting for syntax highlighting. You can see this in action in the ShaderLab file support in the Unity plugin (the correct interfaces, and indeed SDK, aren't yet public so there's some nasty base class stuff going on there. That'll go when things are more public).

Regards
Matt

Comment actions Permalink

Hi Matt,

Than you very much. This makes things much more clear. Will try to implement lexer and parser next week.

Regards
Dušan

0
Comment actions Permalink

I've fixed deployment of the docs. Now available here.

0
Comment actions Permalink

Hi there,

It took me a while but I have a working prototype of my language plugin. The next step is to build code completion. How do I extend HTML code completion to provide custom elements and attributes?

Regards
Dušan

0
Comment actions Permalink

You can create an instance of IHtmlDeclaredElementsProvider, which allows you to add new declared elements that represent HTML elements and attributes. The current implementations for IHtmlDeclaredElementsProvider are static - the data comes from embedded resources which list the standard HTML elements and attributes, so you have to be a little bit careful about this. It's a good idea to cache as much data as you can, as these methods are called frequently as you show code completion. There's an example of how to do this in the AngularJs plugin, which also includes a bunch of comments about what's going on. Creating the declared elements is fairly straightforward, too. Here's creating custom HTML elements, and custom HTML attributes.

0

Please sign in to leave a comment.