A Sample CodeProvider for CodeDom

Code: Microsoft with modifications by Nigel Perry, University of Canterbury

Text and Grammar: Nigel Perry

Introduction

The System.CodeDom namespace defines an abstract language. This language has no defined concrete representation, a program in the language is represented by a tree of CodeDom objects, which corresponds to a parse tree in a compiler for a conventional language.

The semantics of the language are defined implicitly as a subset of C#.

The System.CodeDom.Compiler namespaces defines classes and interfaces for using CodeDom trees.

A CodeDom generator is a translator/compiler which converts the abstract program represented by a CodeDom tree into some concrete language; such as C#, Visual Basic, or Mondrian. The interface ICodeGenerator defines the methods for converting CodeDom trees to concrete language code.

A CodeDom compiler converts the abstract program into an assembly. This is usually done by first using a CodeDom generator and then compiling the resultant concrete language program with an appropriate compiler. The interface ICodeCompiler defines the methods for compiling CodeDom trees to assemblies.

A CodeDom snippet is a piece of unstructured text which may occur in the abstract program and a few defined locations where a particular kind of construct is expected. These are: a complete compilation unit; a member of type; a statement; and an expression. It is assumed that the unstructed text is an appropriate fragment of real language program text which a CodeDom generator or compiler can process as needed and insert into the generated real language program or assembly.

CodeDom is used by a number of tools, in particular ASP.NET and Visual Studio.NET, to construct abstract programs. These tools then use CodeDomProviders to convert these abstract programs into concrete langauges. CodeDomProviders for C#, Visual Basic and JScript are supplied by Microsoft. CodeDomProviders may be written for other languages. ASP.NET for example can support code from any language with a CodeDomProvider being embedded in a web page.

CodeDom supports a collection of abstract languages: a CodeDom Core language and a number of extensions to the Core. Extensions can be combined in any reasonable manner. CodeDom generators indicate their ability to support the various extensions through a flag enumeration GeneratorSupport.

IMPORTANT: A CodeDom generator or compiler intended for use by ASP.NET only needs to support the CodeDom Subset, which is the CodeDom Core with some additional semantic restrictions.

A full grammar for the CodeDom language can be found in CodeDom Grammar.

CodeDomProvider Code Sample

The sample code implements a CodeDomProvider for C# under the language tag "Sample". This language tag is used by tools, such as ASP.NET, to locate and use the correct CodeDomProvider.

The sample consists of the following files:

SampleProvider.cs This is the top level class and implements CodeDomProvider
SampleCompiler.cs This implements ICodeCompiler. The methods in here take CodeDom trees, or concrete language code in files or strings, and compile them to assemblies. To generate concrete code from a CodeDom tree the methods use SampleGenerator.
SampleGenerator.cs This implements ICodeGenerator. The methods in here take CodeDom trees and translate them into C# code. The conversion process is fairly straightforward, and is a recursive walk down the tree generating code as it goes. For each node class CodeX in CodeDom there is a corresponding GenerateX method in this class.
Identifier.cs This class provides methods for checking identifiers. Also included here checks for keywords, these are needed as in CodeDom an identifier in the abstract language may be the same as a keyword in concrete language. In such cases the generator must escape or translate the identifier when generating concrete code.
CurrentTypeInfo.cs This is a utlity class designed to simplify the determination of the kind of type a CodeTypeDeclaration describes. This CodeDom node may represent a class, interface, enumeration or struct declaration; while its subclass CodeTypeDelegate represents delegates.
CompileUtils.cs This class provides utility routines for calling external language compilers and parsing the compiler output for error messages.
StringUtils.cs This class provides a number of useful utility methods on strings.
FixedStringLookup.cs This utility class provides a quick way for looking up a string in a specially structured collection of strings. It is used to support keyword lookup.

Comments are provided in the code to explain its purpose, and the code should be read in conjunction with the CodeDom Grammar to understand the structure of the tree and purpose of the nodes within it.

Compiling And Testing The Sample

A Visual Studio.Net project is supplied to compile the sample files. This produces an assembly SampleProvider.dll. To test this out with ASP.NET you need:

If you have IIS configured to run on your development machine you may test the sample by publishing the directory "ASPDemo" and opening the file "//localhost/ASPDemo/DemoCS.aspx" in Internet Explorer.

The Configuration File

The sample configuration file contains:

<configuration>
    <system.web>
        <compilation debug="true">
            <compilers>
                <compiler language="Sample" extension=".cs" type="SampleCodeDom.SampleProvider,SampleProvider" />
            </compilers>                   
        </compilation>
    </system.web>
</configuration>

This specifies the language "Sample" is handled by the CodeDomProvider SampleCodeDom.SampleProvider in the assembly SampleProvider. Any other languages will be handled according to the system-wide ASP.NET configuration.

The Sample ASP.NET File

The sample file DemoCS.aspx contains:

<%@ Page Language="Sample" %>
<script runat="server">
	static int Square(int x) { return x * x; }	
</script>
<html>
<body>
<p>Very simple test of Sample CodeDom Provider.</p>
<p>The Answer is: <%= Square(7) %>.</p>
</body>
</html>

This shows a trival example of embedding C# in a web page to calculate squares!

Hint: When testing your CodeDomProvider edit your .aspx file for every test, any change will do. If you don't do this a page reload in Internet Explorer will not cause ASP.NET to recompile your page - IIS thinks it knows the answer and returns it from its cache.