Defining custom regions in TypeScript files and preserving their content during CodeSmith template based code generation

I am looking to do some TypeScript code generation with CodeSmith and I’d like to use PreserveMerge merging strategy(preserve merge preserves your custom code within generated code between regenerations). CodeSmith’s merging mechanism is powerful and flexible (besides preserve it supports insert merge strategy as well. But if you feel constrained then feel free to create your own merging strategy). Out of the box it supports C#, VB.NET, XML and T-SQL start region and end region notation. This is a problem for TypeScript because, it can’t use any of those with TypeScript files hence I have to define my own start and end region keywords.

So I came up with

/// #region [Name]

and

/// #endregion

notations – TypeScript will ignore them (as comments) and they are explicit enough. Nothing Earth shattering but they should do the job for me.

Definining new region keywords for CodeSmith

Now I have to update CodeSmith with my these new TypeScript region keywords.

CodeSmith uses regular expressions for searching region keywords. They are defined in registry under the key HKEY_CURRENT_USER\Software\CodeSmith\<VERSION>\LanguageRegionDefinition. Here is a C# definition

image

The definition consists of LanguageKeys, RegionStartRegex and RegionEndRegex. Pretty much self-explanatory.

Here is my TypeScript entry under next available number 4 (also attached to this post):

LanguageKeys: Typescript|TS
RegionStartRegex: ^[ \t]*///[ \t]*\#region(?:[ \t]*(?<name>[^\r\n]*))?[ \t]*\r?\n
RegionEndRegex: ^[ \t]*///[ \t]*\#endregion[ \t]*\r?\n

Creating the node 4 as a sibling to other region definitions does the trick. Note: LanguageKeys is important when you set the merge strategy (you can use any of strings that are pipe delimited: either TypeScript or TS in my case).

Using regions in TypeScript generated code

Let’s create a very simple proof of concept (the project is attached to this post).

First create new console project and then add a CodeSmith template for TypeScript code. As a TargetLanguage you could put "TypeScript” even though CodeSmith doesn’t really know how to syntax color it. It is just a hint for CodeSmith. Place one or more region delimiters within template (mine is really simple one, just to show the concept), here is my template:

<%@ Template Language="C#" TargetLanguage="TypeScript" Debug="False" %>

module RegionTest {
  function tubo(){
    var i = 5;
    /// #region Test
    /// #endregion
  }
}

Add CodeSmith project file and add the above template as an output. In the Edit Output settings set the proper output file name (test.ts in my case), Merge type as “PreserveRegions” and Initialization string as “RegionNameRegex=.*;” or “RegionNameRegex=.*;Language=TypeScript;” if you didn’t set it as TargetLanguage (it defaults to template’s TargetLanguage when not defined). RegionNameRegex gives you a chance to use only selected region names for preserve strategy – in my case any name or no name will do. Below are my Edit Output settings.

image

Generate the code, the output content should appear just like the template definition since there is no real code generation.

Add custom code within the Test region in generated test.ts file (not in template), like:

/// #region Test
alert ("wow, this is really a persistent alert");
/// #endregion

And generate the code once more. If everything is in place the new output should have persisted the custom code of the Test region.

 

Conclusion

To enable CodeSmith’s PreserveRegion merging strategy in an unsuported TypeScript language I had to add a registry key and that’s it. The simplicity of making a language supported in this case shows the CodeSmith flexibility and power and the CodeSmith’s use or registry shows bad practice Smile they should really use files instead of registry (hint).

TestPreserve.zip (20.95 kb)

typescrip-regions.reg (614.00 bytes)

How to compile MvvmCross v3 sources

As you well know, or you might not, MvvmCross is a cross platform MVVM framework supporting many platforms, such as Android and iOS (both through Xamarin), WPF, WinRT, WP7. Feature worth drooling.

Now, AFAIK there are two versions available. v2 (aka vNext) which is supposedly stable and v3 which is work in progress but holds many improvements. Here is how to get v3 sources compiled for Android (I didn’t test others) in case you run into problems like me.

  1. head to Github repository for v3 branch (optionally)
  2. use git clone –b v3 git://github.com/slodge/MvvmCross.git do fetch sources
  3. open MvvmCross_All.sln solution (using Visual Studio 2012) which references all projects for all platforms. If you don’t have Touch support (or others) Visual Studio will let you know. You can safely ignore those warnings.
  4. build solution. If it does consider yourself lucky, otherwise continue reading.
  5. If you get something like

Error 172 Exception while loading assemblies: System.IO.FileNotFoundException: Could not load assembly 'Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'. Perhaps it doesn't exist in the Mono for Android profile?
File name: 'Newtonsoft.Json.dll'

then there is a problem with build process. My guess is that it happens because portable class libraries, which Newtonsoft.Json.dll is, aren’t officially supported by Xamarin. Yet.

The workaround is to get Newtonsoft.Json sources (use PCL csproj version), include the project into solution and replace the reference in Plugins\Cirrious\Json\Cirrious.MvvmCross.Plugins.Json project with the Newtonsof.Json project itself.

Now you can run samples, at least I did – tested with Samples\Tutorial\Tutorial.UI.Droid.

There is another build error you might encounter (in general for Xamarin.Android). Sometimes the build process yields a ton of senseless errors (can’t find classes, interfaces, etc.) even though the code should compile. Try building again – most of the times it builds without errors the second time.

If you are interested into MvvmCross project make sure you read Stuart’s blog (creator of MvvmCross).

I have to test it a bit now, so more blog posts on the topic might follow.

Have fun with MVVM everywhere.