FSharp.Compiler.CodeDom


Installation

FSharp.Compiler.CodeDom supports installation via both NuGet and system-wide. NuGet installation allows for basic use of the library within your application or library. A system-wide installation enables any CodeDom-capable program or library to make use of the library, but requires administrator access (on Windows) or write permission to the Mono GAC and machine.config file (on Unix). A system-wide install can coexist with individual NuGet installs.

To perform a system-wide install on Windows, build the library from the command line with build Release. A MSI package will be produced in Installer\Installer\bin\Release. After installation, the library will be available for use.

To perform a system-wide install on Unix, build the library from the command line with build Release. Navigate to SimpleInstaller/bin/Release, and then, as a user with permission to write to the Mono GAC directory (e.g. /usr/lib/mono/gac) and machine.config file (e.g. /etc/mono/4.5/machine.config), run:

1: 
2: 
$ gacutil -i FSharp.Compiler.CodeDom.dll
$ mono /usr/lib/mono/4.5/installutil.exe SimpleInstaller.dll

Uninstallation

On Windows, uninstallation can be performed through Add/Remove Programs, PowerShell, etc.

On Unix, as a user with the aforementioned privileges:

1: 
2: 
$ gacutil -u FSharp.Compiler.CodeDom # from any directory
$ mono /usr/lib/mono/4.5/installutil.exe /uninstall SimpleInstaller.dll

As an alternative to using SimpleInstaller, the FSharp.Compiler.CodeDom line under <system.codedom> can be manually deleted from machine.config.

A note on CodeDom providers

CodeDom provides a mechanism that allows for programs which use CodeDom to generate code for any language for which a provider is installed--the program need not have any knowledge of that language or the existence of a provider. Unfortunately, many programs (including ones from Microsoft!) are poorly written and hard-code a list of supported providers, usually to only C# and VB, destroying much of CodeDom's utility. Properly written programs should always allow the user to specify an arbitrary string (corresponding to a language with a system-registered provider) to be passed to System.CodeDom.Compiler.CodeDomProvider.CreateProvider. This way, there is no need to directly reference assemblies or hard-code providers, as any provider available to the system can be used.

Basic use of the provider (system-wide install)

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
open System.IO
open System.CodeDom

let prov = Compiler.CodeDomProvider.CreateProvider "fs"

let ccu = CodeCompileUnit()
let nsp = CodeNamespace("MyNamespace")
let ty = CodeTypeDeclaration("MyClass")
let meth = CodeEntryPointMethod(Name="Main")
ty.Members.Add meth
nsp.Types.Add(ty) 
ccu.Namespaces.Add(nsp)

let options = Compiler.CodeGeneratorOptions()

let sw = new StringWriter()
prov.GenerateCodeFromCompileUnit(ccu,sw,options)
let code = sw.ToString()

Tutorial

First, reference the assembly (not needed if a system-wide install was done):

1: 
#r "FSharp.Compiler.CodeDom.dll"

Next, create an instance of the provider:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
open System.CodeDom

// if system-wide:
let provider = Compiler.CodeDomProvider.CreateProvider "fs"

// OR, if NuGet:
open FSharp.Compiler.CodeDom
let provider = new FSharpCodeProvider()

// OR, if the clean code provider is desired, regardless of installation type:
open FSharp.Compiler.CodeDom
let provider = new FSharpCleanCodeProvider()

Now, add some Code DOM constructs to a code unit:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let ccu = CodeCompileUnit()
let nsp = CodeNamespace("MyNamespace")
let ty = CodeTypeDeclaration("MyClass")
let meth = CodeEntryPointMethod(Name="Main")
ty.Members.Add meth
nsp.Types.Add(ty) 
ccu.Namespaces.Add(nsp)

Generate the code:

1: 
2: 
3: 
4: 
5: 
let options = Compiler.CodeGeneratorOptions()

let sw = new System.IO.StringWriter()
provider.GenerateCodeFromCompileUnit(ccu,sw,options)
let code = sw.ToString()
namespace System
namespace System.IO
namespace System.CodeDom
val prov : Compiler.CodeDomProvider

Full name: Tutorial.prov
namespace System.CodeDom.Compiler
type CodeDomProvider =
  inherit Component
  member CompileAssemblyFromDom : options:CompilerParameters * [<ParamArray>] compilationUnits:CodeCompileUnit[] -> CompilerResults
  member CompileAssemblyFromFile : options:CompilerParameters * [<ParamArray>] fileNames:string[] -> CompilerResults
  member CompileAssemblyFromSource : options:CompilerParameters * [<ParamArray>] sources:string[] -> CompilerResults
  member CreateCompiler : unit -> ICodeCompiler
  member CreateEscapedIdentifier : value:string -> string
  member CreateGenerator : unit -> ICodeGenerator + 2 overloads
  member CreateParser : unit -> ICodeParser
  member CreateValidIdentifier : value:string -> string
  member FileExtension : string
  member GenerateCodeFromCompileUnit : compileUnit:CodeCompileUnit * writer:TextWriter * options:CodeGeneratorOptions -> unit
  ...

Full name: System.CodeDom.Compiler.CodeDomProvider
Compiler.CodeDomProvider.CreateProvider(language: string) : Compiler.CodeDomProvider
Compiler.CodeDomProvider.CreateProvider(language: string, providerOptions: System.Collections.Generic.IDictionary<string,string>) : Compiler.CodeDomProvider
val ccu : CodeCompileUnit

Full name: Tutorial.ccu
Multiple items
type CodeCompileUnit =
  inherit CodeObject
  new : unit -> CodeCompileUnit
  member AssemblyCustomAttributes : CodeAttributeDeclarationCollection
  member EndDirectives : CodeDirectiveCollection
  member Namespaces : CodeNamespaceCollection
  member ReferencedAssemblies : StringCollection
  member StartDirectives : CodeDirectiveCollection

Full name: System.CodeDom.CodeCompileUnit

--------------------
CodeCompileUnit() : unit
val nsp : CodeNamespace

Full name: Tutorial.nsp
Multiple items
type CodeNamespace =
  inherit CodeObject
  new : unit -> CodeNamespace + 1 overload
  member Comments : CodeCommentStatementCollection
  member Imports : CodeNamespaceImportCollection
  member Name : string with get, set
  member Types : CodeTypeDeclarationCollection
  event PopulateComments : EventHandler
  event PopulateImports : EventHandler
  event PopulateTypes : EventHandler

Full name: System.CodeDom.CodeNamespace

--------------------
CodeNamespace() : unit
CodeNamespace(name: string) : unit
val ty : CodeTypeDeclaration

Full name: Tutorial.ty
Multiple items
type CodeTypeDeclaration =
  inherit CodeTypeMember
  new : unit -> CodeTypeDeclaration + 1 overload
  member BaseTypes : CodeTypeReferenceCollection
  member IsClass : bool with get, set
  member IsEnum : bool with get, set
  member IsInterface : bool with get, set
  member IsPartial : bool with get, set
  member IsStruct : bool with get, set
  member Members : CodeTypeMemberCollection
  member TypeAttributes : TypeAttributes with get, set
  member TypeParameters : CodeTypeParameterCollection
  ...

Full name: System.CodeDom.CodeTypeDeclaration

--------------------
CodeTypeDeclaration() : unit
CodeTypeDeclaration(name: string) : unit
val meth : CodeEntryPointMethod

Full name: Tutorial.meth
Multiple items
type CodeEntryPointMethod =
  inherit CodeMemberMethod
  new : unit -> CodeEntryPointMethod

Full name: System.CodeDom.CodeEntryPointMethod

--------------------
CodeEntryPointMethod() : unit
property CodeTypeDeclaration.Members: CodeTypeMemberCollection
CodeTypeMemberCollection.Add(value: CodeTypeMember) : int
property CodeNamespace.Types: CodeTypeDeclarationCollection
CodeTypeDeclarationCollection.Add(value: CodeTypeDeclaration) : int
property CodeCompileUnit.Namespaces: CodeNamespaceCollection
CodeNamespaceCollection.Add(value: CodeNamespace) : int
val options : Compiler.CodeGeneratorOptions

Full name: Tutorial.options
Multiple items
type CodeGeneratorOptions =
  new : unit -> CodeGeneratorOptions
  member BlankLinesBetweenMembers : bool with get, set
  member BracingStyle : string with get, set
  member ElseOnClosing : bool with get, set
  member IndentString : string with get, set
  member Item : string -> obj with get, set
  member VerbatimOrder : bool with get, set

Full name: System.CodeDom.Compiler.CodeGeneratorOptions

--------------------
Compiler.CodeGeneratorOptions() : unit
val sw : StringWriter

Full name: Tutorial.sw
Multiple items
type StringWriter =
  inherit TextWriter
  new : unit -> StringWriter + 3 overloads
  member Close : unit -> unit
  member Encoding : Encoding
  member GetStringBuilder : unit -> StringBuilder
  member ToString : unit -> string
  member Write : value:char -> unit + 2 overloads

Full name: System.IO.StringWriter

--------------------
StringWriter() : unit
StringWriter(formatProvider: System.IFormatProvider) : unit
StringWriter(sb: System.Text.StringBuilder) : unit
StringWriter(sb: System.Text.StringBuilder, formatProvider: System.IFormatProvider) : unit
Compiler.CodeDomProvider.GenerateCodeFromCompileUnit(compileUnit: CodeCompileUnit, writer: TextWriter, options: Compiler.CodeGeneratorOptions) : unit
val code : string

Full name: Tutorial.code
StringWriter.ToString() : string
val provider : Compiler.CodeDomProvider

Full name: Tutorial.provider
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
namespace FSharp.Compiler
namespace FSharp.Compiler.CodeDom
val provider : FSharpCodeProvider

Full name: Tutorial.provider
Multiple items
type FSharpCodeProvider =
  inherit CodeDomProvider
  new : unit -> FSharpCodeProvider

Full name: FSharp.Compiler.CodeDom.FSharpCodeProvider

--------------------
new : unit -> FSharpCodeProvider
val provider : FSharpCleanCodeProvider

Full name: Tutorial.provider
Multiple items
type FSharpCleanCodeProvider =
  inherit CodeDomProvider
  new : unit -> FSharpCleanCodeProvider
  override CreateCompiler : unit -> ICodeCompiler
  override CreateGenerator : unit -> ICodeGenerator
  override FileExtension : string

Full name: FSharp.Compiler.CodeDom.FSharpCleanCodeProvider

--------------------
new : unit -> FSharpCleanCodeProvider
Fork me on GitHub