├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── Diesel.sln ├── Diesel ├── CodeGeneration │ ├── ApplicationServiceGenerator.cs │ ├── CodeDomCompiler.cs │ ├── CodeDomGenerator.cs │ ├── CommandGenerator.cs │ ├── DomainEventGenerator.cs │ ├── DtoGenerator.cs │ ├── EnumGenerator.cs │ ├── EqualityMethodsGenerator.cs │ ├── ExpressionBuilder.cs │ ├── MemberTypeMapper.cs │ ├── ReadOnlyProperty.cs │ ├── SystemTypeMapper.cs │ ├── TypeNameMapper.cs │ ├── ValueObjectSpecification.cs │ └── ValueTypeGenerator.cs ├── Diesel.csproj ├── Diesel.nuspec ├── DieselCompiler.cs ├── Parsing │ ├── AbstractSyntaxTree.cs │ ├── ApplicationServiceDeclaration.cs │ ├── BaseTypes.cs │ ├── CSharp │ │ ├── ArrayType.cs │ │ ├── CSharpGrammar.cs │ │ ├── IStructType.cs │ │ ├── ITypeNode.cs │ │ ├── ITypeNodeVisitor.cs │ │ ├── IValueTypeNode.cs │ │ ├── Identifier.cs │ │ ├── NamespaceName.cs │ │ ├── NullableType.cs │ │ ├── RankSpecifier.cs │ │ ├── RankSpecifiers.cs │ │ ├── ReferenceType.cs │ │ ├── SimpleType.cs │ │ ├── StringReferenceType.cs │ │ └── TypeName.cs │ ├── CommandConventions.cs │ ├── CommandDeclaration.cs │ ├── ConventionsDeclaration.cs │ ├── DomainEventConventions.cs │ ├── DomainEventDeclaration.cs │ ├── DtoDeclaration.cs │ ├── EnumDeclaration.cs │ ├── Grammar.cs │ ├── IConventionsNode.cs │ ├── IDieselExpression.cs │ ├── IDieselExpressionVisitor.cs │ ├── ITreeNode.cs │ ├── ITypeDeclaration.cs │ ├── ITypeDeclarationVisitor.cs │ ├── Keyword.cs │ ├── Namespace.cs │ ├── PropertyDeclaration.cs │ ├── Symbol.cs │ ├── Terminal.cs │ ├── TokenGrammar.cs │ └── ValueTypeDeclaration.cs ├── Properties │ └── AssemblyInfo.cs ├── Transformations │ ├── ApplyDefaults.cs │ ├── FullyQualifiedNameRule.cs │ ├── KnownType.cs │ ├── KnownTypesHarvester.cs │ ├── ModelTransformation.cs │ ├── ModelTransformations.cs │ └── SemanticModel.cs └── packages.config ├── LICENSE.txt ├── README.md ├── TODO.md ├── Test ├── CodeExamples.Designer.cs ├── CodeExamples.resx ├── CodeGeneration │ ├── CodeDomCompilerTest.cs │ ├── EqualityMethodsGeneratorTest.cs │ ├── MemberTypeMapperTest.cs │ ├── SystemTypeMapperTest.cs │ ├── TypeNameMapperTest.cs │ └── ValueObjectSpecificationTest.cs ├── DieselCompilerIntegrationTest.cs ├── Examples │ └── DieselCompilerIntegrationTestCase.txt ├── Generated │ ├── Example.dsl │ ├── GenerateExamples.cs │ └── GenerateExamples.tt ├── GeneratedCommandNestedTypesTest.cs ├── GeneratedCommandTest.cs ├── GeneratedDomainEventTest.cs ├── GeneratedDomainEventWithArrayTest.cs ├── GeneratedDtoTest.cs ├── GeneratedDtoWithNullableNonSystemMemberTypeTest.cs ├── GeneratedEnumTest.cs ├── GeneratedGetHashCodeIntegrationTest.cs ├── GeneratedValueTypeMultiplePropertiesTest.cs ├── GeneratedValueTypeNestedValueTypesTest.cs ├── GeneratedValueTypeTest.cs ├── GeneratedValueTypeWithArrayTest.cs ├── GeneratedValueTypeWithNullableProperty.cs ├── ICommand.cs ├── IDomainEvent.cs ├── ObjectMothers │ ├── BaseTypesObjectMother.cs │ ├── CommandDeclarationObjectMother.cs │ ├── DomainEventDeclarationObjectMother.cs │ ├── DtoDeclarationObjectMother.cs │ ├── EnumDeclarationObjectMother.cs │ ├── PropertyDeclarationObjectMother.cs │ └── ValueTypeDeclarationObjectMother.cs ├── Parsing │ ├── BaseTypesTest.cs │ ├── CSharp │ │ ├── ArrayTypeTest.cs │ │ ├── CSharpGrammarTest.cs │ │ ├── SimpleTypeTest.cs │ │ └── TypeNameTest.cs │ ├── CommandConventionsTest.cs │ ├── ConventionsDeclarationTest.cs │ ├── DomainEventConventionsTest.cs │ ├── GrammarTest.cs │ ├── KeywordTest.cs │ └── TokenGrammarTest.cs ├── Properties │ └── AssemblyInfo.cs ├── Test.csproj ├── TestHelpers │ ├── EqualityTesting.cs │ └── SerializationTesting.cs ├── Transformations │ ├── ApplyDefaultsTest.cs │ └── KnownTypesHarvesterTest.cs └── packages.config ├── packages ├── NUnit.2.6.2 │ ├── NUnit.2.6.2.nupkg │ ├── NUnit.2.6.2.nuspec │ ├── lib │ │ ├── nunit.framework.dll │ │ └── nunit.framework.xml │ └── license.txt ├── Sprache.1.10.0.28 │ ├── Sprache.1.10.0.28.nupkg │ ├── Sprache.1.10.0.28.nuspec │ └── lib │ │ └── net40 │ │ ├── Sprache.XML │ │ ├── Sprache.dll │ │ └── Sprache.pdb └── repositories.config └── publish.ps1 /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | # http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/ 3 | * text=auto 4 | 5 | # Custom for Visual Studio 6 | *.cs diff=csharp 7 | *.sln merge=union 8 | *.csproj merge=union 9 | *.vbproj merge=union 10 | *.fsproj merge=union 11 | *.dbproj merge=union 12 | 13 | # Standard to msysgit 14 | *.doc diff=astextplain 15 | *.DOC diff=astextplain 16 | *.docx diff=astextplain 17 | *.DOCX diff=astextplain 18 | *.dot diff=astextplain 19 | *.DOT diff=astextplain 20 | *.pdf diff=astextplain 21 | *.PDF diff=astextplain 22 | *.rtf diff=astextplain 23 | *.RTF diff=astextplain 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | 11 | [Dd]ebug/ 12 | [Rr]elease/ 13 | x64/ 14 | build/ 15 | [Bb]in/ 16 | [Oo]bj/ 17 | 18 | # MSTest test Results 19 | [Tt]est[Rr]esult*/ 20 | [Bb]uild[Ll]og.* 21 | 22 | *_i.c 23 | *_p.c 24 | *.ilk 25 | *.meta 26 | *.obj 27 | *.pch 28 | *.pdb 29 | *.pgc 30 | *.pgd 31 | *.rsp 32 | *.sbr 33 | *.tlb 34 | *.tli 35 | *.tlh 36 | *.tmp 37 | *.tmp_proj 38 | *.log 39 | *.vspscc 40 | *.vssscc 41 | .builds 42 | *.pidb 43 | *.log 44 | *.scc 45 | 46 | # Visual C++ cache files 47 | ipch/ 48 | *.aps 49 | *.ncb 50 | *.opensdf 51 | *.sdf 52 | *.cachefile 53 | 54 | # Visual Studio profiler 55 | *.psess 56 | *.vsp 57 | *.vspx 58 | 59 | # Guidance Automation Toolkit 60 | *.gpState 61 | 62 | # ReSharper is a .NET coding add-in 63 | _ReSharper*/ 64 | *.[Rr]e[Ss]harper 65 | 66 | # TeamCity is a build add-in 67 | _TeamCity* 68 | 69 | # DotCover is a Code Coverage Tool 70 | *.dotCover 71 | 72 | # NCrunch 73 | *.ncrunch* 74 | .*crunch*.local.xml 75 | 76 | # Installshield output folder 77 | [Ee]xpress/ 78 | 79 | # DocProject is a documentation generator add-in 80 | DocProject/buildhelp/ 81 | DocProject/Help/*.HxT 82 | DocProject/Help/*.HxC 83 | DocProject/Help/*.hhc 84 | DocProject/Help/*.hhk 85 | DocProject/Help/*.hhp 86 | DocProject/Help/Html2 87 | DocProject/Help/html 88 | 89 | # Click-Once directory 90 | publish/ 91 | 92 | # Publish Web Output 93 | *.Publish.xml 94 | *.pubxml 95 | 96 | # NuGet Packages Directory 97 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 98 | #packages/ 99 | 100 | # Windows Azure Build Output 101 | csx 102 | *.build.csdef 103 | 104 | # Windows Store app package directory 105 | AppPackages/ 106 | 107 | # Others 108 | sql/ 109 | *.Cache 110 | ClientBin/ 111 | [Ss]tyle[Cc]op.* 112 | ~$* 113 | *~ 114 | *.dbmdl 115 | *.[Pp]ublish.xml 116 | *.pfx 117 | *.publishsettings 118 | 119 | # RIA/Silverlight projects 120 | Generated_Code/ 121 | 122 | # Backup & report files from converting an old project file to a newer 123 | # Visual Studio version. Backup files are not needed, because we have git ;-) 124 | _UpgradeReport_Files/ 125 | Backup*/ 126 | UpgradeLog*.XML 127 | UpgradeLog*.htm 128 | 129 | # SQL Server files 130 | App_Data/*.mdf 131 | App_Data/*.ldf 132 | 133 | # ========================= 134 | # Windows detritus 135 | # ========================= 136 | 137 | # Windows image file caches 138 | Thumbs.db 139 | ehthumbs.db 140 | 141 | # Folder config file 142 | Desktop.ini 143 | 144 | # Recycle Bin used on file shares 145 | $RECYCLE.BIN/ 146 | 147 | # Mac crap 148 | .DS_Store 149 | 150 | 151 | #Ignore generated nupkg files 152 | *.nupkg -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Version 1.14 2 | * Added support for user-defined (non-system) nullable value type members on data contracts (Commands, Domain Events etc.) 3 | 4 | # Version 1.13 5 | * Generates a ToString method on Value Types returning the value of simple (non-array) properties. 6 | 7 | # Version 1.12 8 | * Adds support for named nullable types in properties, e.g. `DateTime? EndDate`. 9 | 10 | # Version 1.11 11 | * `defconventions` extended to enable configurable base classes and interfaces on Commands. 12 | * Known value type fields are now included in GetHashCode calculation. 13 | 14 | # Version 1.10 15 | * Added support for properties that are uni-dimensional arrays of named types (e.g. `EmployeeNumber[]`). 16 | 17 | # Version 1.9 18 | * Support for single-line comments added (semicolon to end-of-line) 19 | * `defenum` added to generate enumeration DTOs (Data Transfer Objects). 20 | * Properties can now be any type (generator will emit names of custom/non-system types literally) 21 | 22 | # Version 1.8 23 | * `defdto` added to generate DTOs (Data Transfer Objects). 24 | 25 | # Version 1.7 26 | * Support for arrays in value types, commands and domain events. 27 | * Grammar for property specification now follows C# grammar more closely. 28 | 29 | # Version 1.6 30 | * `defdomainevent` added to generate domain event DTOs. 31 | * `defconventions` added to configure the code-generation. For now, just configurable base classes for Domain Events. 32 | 33 | # Version 1.5 34 | * Parser requires entire source file to be valid (before it unintentionally allowed anything to follow the AST). 35 | * Added DataContractSerializer serializability for commands (`defcommand`). 36 | 37 | # Version 1.4 38 | * Support for nullable types in properties introduced (e.g. `defcommand` and `defvaluetype`). 39 | * Support for System types DateTime and Guid in added to properties in `defcommand` and `defvaluetype`. 40 | 41 | # Version 1.3 42 | * `defvaluetype` extended to also accept a list of properties like `defcommand`. 43 | 44 | # Version 1.2 45 | * `defapplicationservice` added, generating a service interface for the associated commands. 46 | 47 | # Version 1.1 48 | * `defvaluetype` adds binary serializability. 49 | * `defcommand` adds serializability. 50 | * `defcommand` now adds DataContract and DataMember attributes for XML serialization. 51 | 52 | # Version 1.0 53 | Initial release. 54 | Includes `namespace`, `defvaluetype` and `defcommand`. 55 | -------------------------------------------------------------------------------- /Diesel.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Diesel", "Diesel\Diesel.csproj", "{199CBCF0-8F94-477B-AC53-31381D6617B2}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{AD8890FF-14EE-4EC4-9D43-22211FCF369D}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A0758857-3B1C-4B7F-AC45-435DE4FEC4E3}" 9 | ProjectSection(SolutionItems) = preProject 10 | CHANGELOG.md = CHANGELOG.md 11 | LICENSE.txt = LICENSE.txt 12 | README.md = README.md 13 | TODO.md = TODO.md 14 | EndProjectSection 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {199CBCF0-8F94-477B-AC53-31381D6617B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {199CBCF0-8F94-477B-AC53-31381D6617B2}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {199CBCF0-8F94-477B-AC53-31381D6617B2}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {199CBCF0-8F94-477B-AC53-31381D6617B2}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {AD8890FF-14EE-4EC4-9D43-22211FCF369D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {AD8890FF-14EE-4EC4-9D43-22211FCF369D}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {AD8890FF-14EE-4EC4-9D43-22211FCF369D}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {AD8890FF-14EE-4EC4-9D43-22211FCF369D}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /Diesel/CodeGeneration/ApplicationServiceGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.CodeDom; 2 | using System.Linq; 3 | using Diesel.Parsing; 4 | 5 | namespace Diesel.CodeGeneration 6 | { 7 | public class ApplicationServiceGenerator : CodeDomGenerator 8 | { 9 | public static CodeTypeDeclaration CreateApplicationServiceInterface(ApplicationServiceDeclaration declaration) 10 | { 11 | var interfaceName = InterfaceNameFor(declaration.Name); 12 | var result = new CodeTypeDeclaration(interfaceName) 13 | { 14 | IsPartial = true, 15 | IsInterface = true, 16 | }; 17 | // Define an "Execute" overload for each command 18 | var commandHandlerMembers = 19 | (from c in declaration.Commands 20 | select (CodeTypeMember)new CodeMemberMethod() 21 | { 22 | Attributes = MemberAttributes.Public, 23 | Name = "Execute", 24 | Parameters = { new CodeParameterDeclarationExpression(c.Name, "command") }, 25 | }).ToArray(); 26 | 27 | result.Members.AddRange(commandHandlerMembers); 28 | return result; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/CodeDomCompiler.cs: -------------------------------------------------------------------------------- 1 | using System.CodeDom; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | using Diesel.Transformations; 5 | 6 | namespace Diesel.CodeGeneration 7 | { 8 | /// 9 | /// Responsible for compiling a instance to CodeDom. 10 | /// 11 | public class CodeDomCompiler 12 | { 13 | private static ConventionsDeclaration DefaultConventions 14 | { 15 | get 16 | { 17 | return new ConventionsDeclaration( 18 | new DomainEventConventions(new BaseTypes(new TypeName[] {})), 19 | new CommandConventions(new BaseTypes(new TypeName[] {}))); 20 | } 21 | } 22 | 23 | /// 24 | /// Compile the model into a CodeDom . 25 | /// 26 | public static CodeCompileUnit Compile(SemanticModel model) 27 | { 28 | var unit = new CodeCompileUnit(); 29 | var conventions = DefaultConventions; 30 | Add(unit, conventions, model); 31 | return unit; 32 | } 33 | 34 | private static void Add(CodeCompileUnit codeCompileUnit, ConventionsDeclaration conventions, SemanticModel model) 35 | { 36 | Add(codeCompileUnit, conventions, model, model.AbstractSyntaxTree); 37 | } 38 | 39 | private static void Add(CodeCompileUnit codeCompileUnit, ConventionsDeclaration conventions, SemanticModel model, AbstractSyntaxTree ast) 40 | { 41 | var userConventions = conventions; 42 | if (ast.Conventions != null) 43 | { 44 | userConventions = conventions.ApplyOverridesFrom(ast.Conventions); 45 | } 46 | foreach (var ns in ast.Namespaces) 47 | { 48 | Add(codeCompileUnit, userConventions, model, ns); 49 | } 50 | } 51 | 52 | 53 | private static void Add(CodeCompileUnit codeCompileUnit, ConventionsDeclaration conventions, SemanticModel model, Namespace declaration) 54 | { 55 | var ns = new CodeNamespace(declaration.Name.Name); 56 | ns.Imports.Add(new CodeNamespaceImport("System")); 57 | codeCompileUnit.Namespaces.Add(ns); 58 | foreach (var typeDeclaration in declaration.Declarations) 59 | { 60 | Add(ns, conventions, model, declaration.Name, (dynamic)typeDeclaration); 61 | } 62 | } 63 | 64 | private static void Add(CodeNamespace ns, ConventionsDeclaration conventions, SemanticModel model, NamespaceName namespaceName, CommandDeclaration declaration) 65 | { 66 | ns.Types.Add(CommandGenerator.CreateCommandDeclaration(model, namespaceName, declaration, conventions.CommandConventions)); 67 | } 68 | 69 | private static void Add(CodeNamespace ns, ConventionsDeclaration conventions, SemanticModel model, NamespaceName namespaceName, DomainEventDeclaration declaration) 70 | { 71 | ns.Types.Add(DomainEventGenerator.CreateDomainEventDeclaration(model, namespaceName, declaration, conventions.DomainEventConventions)); 72 | } 73 | 74 | private static void Add(CodeNamespace ns, ConventionsDeclaration conventions, SemanticModel model, NamespaceName namespaceName, ValueTypeDeclaration declaration) 75 | { 76 | ns.Types.Add(ValueTypeGenerator.CreateValueTypeDeclaration(model, namespaceName, declaration)); 77 | } 78 | 79 | private static void Add(CodeNamespace ns, ConventionsDeclaration conventions, SemanticModel model, NamespaceName namespaceName, DtoDeclaration declaration) 80 | { 81 | ns.Types.Add(DtoGenerator.CreateDtoDeclaration(model, namespaceName, declaration)); 82 | } 83 | 84 | private static void Add(CodeNamespace ns, ConventionsDeclaration conventions, SemanticModel model, NamespaceName namespaceName, EnumDeclaration declaration) 85 | { 86 | ns.Types.Add(EnumGenerator.CreateEnumDeclaration(declaration)); 87 | } 88 | 89 | private static void Add(CodeNamespace ns, ConventionsDeclaration conventions, SemanticModel model, NamespaceName namespaceName, ApplicationServiceDeclaration declaration) 90 | { 91 | ns.Types.Add(ApplicationServiceGenerator.CreateApplicationServiceInterface(declaration)); 92 | foreach (var command in declaration.Commands) 93 | { 94 | Add(ns, conventions, model, namespaceName, command); 95 | } 96 | } 97 | 98 | } 99 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/CommandGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.CodeDom; 2 | using System.Linq; 3 | using Diesel.Parsing; 4 | using Diesel.Parsing.CSharp; 5 | using Diesel.Transformations; 6 | 7 | namespace Diesel.CodeGeneration 8 | { 9 | public class CommandGenerator : CodeDomGenerator 10 | { 11 | public static CodeTypeDeclaration CreateCommandDeclaration( 12 | SemanticModel model, NamespaceName namespaceName, 13 | CommandDeclaration declaration, 14 | CommandConventions conventions) 15 | { 16 | var type = CreateTypeWithValueSemantics( 17 | ValueObjectSpecification.CreateClass( 18 | namespaceName, declaration.Name, 19 | declaration.Properties.ToArray(), 20 | conventions.BaseTypes, 21 | true, false), 22 | model.KnownTypes); 23 | return type; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/DomainEventGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.CodeDom; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Diesel.Parsing; 5 | using Diesel.Parsing.CSharp; 6 | using Diesel.Transformations; 7 | 8 | namespace Diesel.CodeGeneration 9 | { 10 | internal class DomainEventGenerator : CodeDomGenerator 11 | { 12 | public static CodeTypeDeclaration CreateDomainEventDeclaration( 13 | SemanticModel model, NamespaceName namespaceName, 14 | DomainEventDeclaration declaration, 15 | DomainEventConventions conventions) 16 | { 17 | var type = CreateTypeWithValueSemantics( 18 | ValueObjectSpecification.CreateClass( 19 | namespaceName, declaration.Name, 20 | declaration.Properties.ToArray(), 21 | conventions.BaseTypes, 22 | true, true), 23 | model.KnownTypes); 24 | return type; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/DtoGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.CodeDom; 2 | using System.Linq; 3 | using Diesel.Parsing; 4 | using Diesel.Parsing.CSharp; 5 | using Diesel.Transformations; 6 | 7 | namespace Diesel.CodeGeneration 8 | { 9 | public class DtoGenerator : CodeDomGenerator 10 | { 11 | public static CodeTypeDeclaration CreateDtoDeclaration( 12 | SemanticModel model, NamespaceName namespaceName, 13 | DtoDeclaration declaration) 14 | { 15 | return CreateTypeWithValueSemantics( 16 | ValueObjectSpecification.CreateClass( 17 | namespaceName, declaration.Name, 18 | declaration.Properties.ToArray(), 19 | new BaseTypes(new TypeName[0]), 20 | true, true), 21 | model.KnownTypes); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/EnumGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.CodeDom; 2 | using System.Linq; 3 | using System.Reflection; 4 | using System.Runtime.Serialization; 5 | using Diesel.Parsing; 6 | using Diesel.Transformations; 7 | 8 | namespace Diesel.CodeGeneration 9 | { 10 | internal class EnumGenerator : CodeDomGenerator 11 | { 12 | public static CodeTypeDeclaration CreateEnumDeclaration(EnumDeclaration declaration) 13 | { 14 | var result = new CodeTypeDeclaration(declaration.Name) 15 | { 16 | IsStruct = false, 17 | IsEnum = true, 18 | TypeAttributes = TypeAttributes.Public, 19 | }; 20 | 21 | result.CustomAttributes.Add(CreateDataContractAttribute(declaration.Name)); 22 | var fields = declaration.Values.Select(memberName => 23 | (CodeTypeMember)new CodeMemberField() 24 | { 25 | Name = memberName, 26 | CustomAttributes = { CreateEnumMemberAttribute(memberName) } 27 | }); 28 | result.Members.AddRange(fields.ToArray()); 29 | return result; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/ExpressionBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.CodeDom; 3 | using System.Diagnostics.Contracts; 4 | 5 | namespace Diesel.CodeGeneration 6 | { 7 | /// 8 | /// Functions to build CodeDom expressions. 9 | /// 10 | [Pure] 11 | public static class ExpressionBuilder 12 | { 13 | /// 14 | /// For an expression A, return a negation expression, non-A. 15 | /// 16 | [Pure] 17 | public static CodeExpression Negate(CodeExpression expression) 18 | { 19 | return new CodeBinaryOperatorExpression(new CodePrimitiveExpression(false), 20 | CodeBinaryOperatorType.ValueEquality, expression); 21 | } 22 | 23 | /// 24 | /// Return a reference to an instance field on "this". 25 | /// 26 | [Pure] 27 | public static CodeFieldReferenceExpression ThisFieldReference(string fieldName) 28 | { 29 | return new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName); 30 | } 31 | 32 | /// 33 | /// Return a reference to an instance property on "this". 34 | /// 35 | [Pure] 36 | public static CodePropertyReferenceExpression ThisPropertyReference(string propertyName) 37 | { 38 | return PropertyReference(new CodeThisReferenceExpression(), propertyName); 39 | } 40 | 41 | /// 42 | /// Return a reference to an instance property on a variable. 43 | /// 44 | [Pure] 45 | public static CodePropertyReferenceExpression VariablePropertyReference(string variableName, string propertyName) 46 | { 47 | return PropertyReference(new CodeVariableReferenceExpression(variableName), propertyName); 48 | } 49 | 50 | /// 51 | /// Return an reference to a named property. 52 | /// 53 | [Pure] 54 | public static CodePropertyReferenceExpression PropertyReference(CodeExpression instance, string propertyName) 55 | { 56 | return new CodePropertyReferenceExpression(instance, propertyName); 57 | } 58 | 59 | 60 | /// 61 | /// Return an expression comparing an object reference to null. 62 | /// 63 | [Pure] 64 | public static CodeMethodInvokeExpression ObjectReferenceEqualsNull(CodeExpression instanceToCompareToNull) 65 | { 66 | return new CodeMethodInvokeExpression( 67 | new CodeTypeReferenceExpression(typeof(object)), 68 | "ReferenceEquals", 69 | new[] 70 | { 71 | new CodePrimitiveExpression(null), 72 | instanceToCompareToNull 73 | }); 74 | } 75 | 76 | /// 77 | /// Return an expression comparing two expressions a and be with Object.Equals(a,b). 78 | /// 79 | [Pure] 80 | public static CodeExpression ObjectEquals(CodeExpression a, CodeExpression b) 81 | { 82 | return new CodeMethodInvokeExpression( 83 | new CodeTypeReferenceExpression(typeof (Object)), 84 | "Equals", 85 | a, b); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/MemberTypeMapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.Contracts; 4 | using System.Linq; 5 | using Diesel.Parsing.CSharp; 6 | using Diesel.Transformations; 7 | 8 | namespace Diesel.CodeGeneration 9 | { 10 | /// 11 | /// Responsible for mapping AST instances to . 12 | /// 13 | [Pure] 14 | public class MemberTypeMapper 15 | { 16 | /// 17 | /// Map a instance to the 18 | /// corresponding . 19 | /// 20 | [Pure] 21 | public static MemberType MemberTypeFor(NamespaceName namespaceName, ITypeNode type, IEnumerable knownTypes) 22 | { 23 | var visitor = new MemberTypeMapperTypeNodeVisitor(namespaceName, knownTypes); 24 | type.Accept(visitor); 25 | return visitor.MemberType; 26 | } 27 | 28 | private class MemberTypeMapperTypeNodeVisitor : ITypeNodeVisitor 29 | { 30 | private readonly NamespaceName _namespaceName; 31 | private readonly List _knownTypes; 32 | public MemberTypeMapperTypeNodeVisitor(NamespaceName namespaceName, IEnumerable knownTypes) 33 | { 34 | _namespaceName = namespaceName; 35 | _knownTypes = knownTypes.ToList(); 36 | } 37 | 38 | public MemberType MemberType { get; private set; } 39 | 40 | public void Visit(TypeName typeName) 41 | { 42 | if (SystemTypeMapper.IsSystemType(typeName)) 43 | { 44 | ReturnSystemMemberType(typeName); 45 | } 46 | else 47 | { 48 | ReturnNamedMember(typeName); 49 | } 50 | } 51 | 52 | private void ReturnNamedMember(TypeName typeName) 53 | { 54 | var fullName = FullyQualifiedNameRule.For(_namespaceName, typeName); 55 | var knownType = _knownTypes.SingleOrDefault(x => x.FullName == fullName); 56 | var isValueType = knownType != null && knownType.IsValueType; 57 | MemberType = MemberType.CreateForTypeName(typeName, isValueType); 58 | } 59 | 60 | private void ReturnNullableMember(TypeName underlyingTypeName) 61 | { 62 | var fullName = FullyQualifiedNameRule.For(_namespaceName, underlyingTypeName); 63 | var nullableTypeName = new TypeName(TypeNameMapper.TypeNameForNullableType(fullName)); 64 | MemberType = MemberType.CreateForTypeName(nullableTypeName, true); 65 | } 66 | 67 | private void ReturnSystemMemberType(ITypeNode node) 68 | { 69 | MemberType = MemberType.CreateForSystemType(SystemTypeMapper.SystemTypeFor(node)); 70 | } 71 | 72 | public void Visit(StringReferenceType stringReferenceType) 73 | { 74 | ReturnSystemMemberType(stringReferenceType); 75 | } 76 | 77 | public void Visit(ArrayType arrayType) 78 | { 79 | var elementMemberType = MemberTypeFor(_namespaceName, arrayType.Type, _knownTypes); 80 | MemberType = MemberType.CreateForArray(elementMemberType, arrayType.RankSpecifiers); 81 | } 82 | 83 | public void Visit(SimpleType simpleType) 84 | { 85 | ReturnSystemMemberType(simpleType); 86 | } 87 | 88 | public void Visit(NullableType nullableType) 89 | { 90 | if (SystemTypeMapper.IsSystemType(nullableType.Underlying)) 91 | { 92 | ReturnSystemMemberType(nullableType); 93 | } 94 | else 95 | { 96 | var hasResult = false; 97 | var underlyingTypeName = GetUnderlyingTypeName(nullableType); 98 | if (underlyingTypeName != null) 99 | { 100 | if (IsKnownValueType(underlyingTypeName)) 101 | { 102 | ReturnNullableMember(underlyingTypeName); 103 | hasResult = true; 104 | } 105 | } 106 | if (!hasResult) 107 | { 108 | throw new NotImplementedException("Nullable Type members not implemented for unknown, non-system types."); 109 | } 110 | 111 | } 112 | } 113 | 114 | private TypeName GetUnderlyingTypeName(NullableType nullableType) 115 | { 116 | var visitor = new NullableTypeUnderlyingTypeNameVisitor(); 117 | nullableType.Underlying.Accept(visitor); 118 | var underlyingName = visitor.UnderlyingTypeName; 119 | return underlyingName; 120 | } 121 | 122 | private bool IsKnownValueType(TypeName typeName) 123 | { 124 | var fullyQualifiedTypeName = FullyQualifiedNameRule.For(_namespaceName, typeName); 125 | return _knownTypes.Where(x => x.IsValueType).Any(x => x.FullName == fullyQualifiedTypeName); 126 | } 127 | 128 | private class NullableTypeUnderlyingTypeNameVisitor : ITypeNodeVisitor 129 | { 130 | public TypeName UnderlyingTypeName; 131 | 132 | public void Visit(TypeName typeName) 133 | { 134 | UnderlyingTypeName = typeName; 135 | } 136 | 137 | public void Visit(StringReferenceType stringReferenceType) 138 | { 139 | } 140 | 141 | public void Visit(ArrayType arrayType) 142 | { 143 | } 144 | 145 | public void Visit(SimpleType simpleType) 146 | { 147 | } 148 | 149 | public void Visit(NullableType nullableType) 150 | { 151 | } 152 | } 153 | } 154 | } 155 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/ReadOnlyProperty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.CodeDom; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using Diesel.Parsing.CSharp; 6 | 7 | namespace Diesel.CodeGeneration 8 | { 9 | public abstract class Member 10 | { 11 | public String Name { get; private set; } 12 | public MemberType Type { get; private set; } 13 | public IEnumerable Attributes { get; private set; } 14 | 15 | protected Member(string name, MemberType type, IEnumerable attributeDeclarations) 16 | { 17 | Name = name; 18 | Type = type; 19 | Attributes = attributeDeclarations; 20 | } 21 | } 22 | 23 | public class ReadOnlyProperty : Member 24 | { 25 | public BackingField BackingField { get; private set; } 26 | 27 | public ReadOnlyProperty(string name, MemberType type, BackingField backingField, IEnumerable attributeDeclarations) 28 | : base(name, type, attributeDeclarations) 29 | { 30 | BackingField = backingField; 31 | } 32 | } 33 | 34 | public class BackingField : Member 35 | { 36 | public BackingField(string name, MemberType type, IEnumerable attributeDeclarations) 37 | : base(name, type, attributeDeclarations) 38 | { 39 | } 40 | } 41 | 42 | public class MemberType 43 | { 44 | public string FullName { get; private set; } 45 | public bool IsValueType { get; private set; } 46 | 47 | private MemberType(string fullName, bool isValueType) 48 | { 49 | FullName = fullName; 50 | IsValueType = isValueType; 51 | } 52 | 53 | public static MemberType CreateForSystemType(Type type) 54 | { 55 | return new MemberType(type.FullName, type.IsValueType); 56 | } 57 | 58 | public static MemberType CreateForTypeName(TypeName name, bool isValueType) 59 | { 60 | return new MemberType(name.Name, isValueType); 61 | } 62 | 63 | public static MemberType CreateForArray(MemberType elementType, RankSpecifiers rankSpecifiers) 64 | { 65 | var fullName = TypeNameMapper.TypeNameForArray(elementType.FullName, rankSpecifiers); 66 | return new MemberType(fullName, false); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/SystemTypeMapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.Contracts; 3 | using System.Linq; 4 | using Diesel.Parsing.CSharp; 5 | 6 | namespace Diesel.CodeGeneration 7 | { 8 | /// 9 | /// Responsible for mapping instances to instances. 10 | /// 11 | [Pure] 12 | public static class SystemTypeMapper 13 | { 14 | /// 15 | /// Get the for a given . 16 | /// Throws an exception if no corresponding type exists. Use 17 | /// check if the mapping will succeed. 18 | /// 19 | [Pure] 20 | public static System.Type SystemTypeFor(ITypeNode node) 21 | { 22 | var visitor = Visit(node); 23 | if (!visitor.FoundSystemType) throw new ArgumentOutOfRangeException("node", node, "No System type found for TypeNode."); 24 | return visitor.Result; 25 | } 26 | 27 | /// 28 | /// Predicate function to check if a instance 29 | /// represents a system type. 30 | /// 31 | [Pure] 32 | public static bool IsSystemType(ITypeNode node) 33 | { 34 | return Visit(node).FoundSystemType; 35 | } 36 | 37 | [Pure] 38 | private static SystemTypeMapperVisitor Visit(ITypeNode node) 39 | { 40 | var visitor = new SystemTypeMapperVisitor(); 41 | node.Accept(visitor); 42 | return visitor; 43 | } 44 | 45 | private class SystemTypeMapperVisitor : ITypeNodeVisitor 46 | { 47 | public Type Result { get; private set; } 48 | public bool FoundSystemType 49 | { 50 | get { return (null != Result); } 51 | } 52 | 53 | public void Visit(StringReferenceType typeNode) 54 | { 55 | Result = typeof (String); 56 | } 57 | 58 | public void Visit(ArrayType typeNode) 59 | { 60 | Type elementType = SystemTypeFor(typeNode.Type); 61 | Result = Type.GetType(TypeNameMapper.TypeNameForArray(elementType.FullName, typeNode.RankSpecifiers)); 62 | } 63 | 64 | public void Visit(SimpleType typeNode) 65 | { 66 | Result = typeNode.Type; 67 | } 68 | 69 | public void Visit(NullableType typeNode) 70 | { 71 | Type underlying = SystemTypeFor(typeNode.Underlying); 72 | Result = Type.GetType(String.Format("System.Nullable`1[{0}]", underlying.FullName)); 73 | } 74 | 75 | public void Visit(TypeName typeNode) 76 | { 77 | var knownSystemType = TryGetSystemTypeFor(typeNode); 78 | Result = knownSystemType; 79 | } 80 | 81 | private Type TryGetSystemTypeFor(TypeName node) 82 | { 83 | var knownType = Type.GetType(node.Name, false); 84 | if (knownType != null) return knownType; 85 | // TODO: prefix with known imports 86 | var asQualifiedSystemType = String.Format("System.{0}", node.Name); 87 | var knownSystemType = Type.GetType(asQualifiedSystemType, false); 88 | return knownSystemType; 89 | } 90 | 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/TypeNameMapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.Contracts; 3 | using System.Linq; 4 | using Diesel.Parsing.CSharp; 5 | 6 | namespace Diesel.CodeGeneration 7 | { 8 | public static class TypeNameMapper 9 | { 10 | [Pure] 11 | public static string TypeNameForArray(string elementTypeFullName, RankSpecifiers ranks) 12 | { 13 | var rankSpecifiers = (from rank in ranks.Ranks.Reverse() 14 | from rankSpec in 15 | String.Format("[{0}]", 16 | String.Join("", Enumerable.Repeat(',', rank.Dimensions - 1))) 17 | select rankSpec); 18 | return String.Concat(elementTypeFullName, String.Concat(rankSpecifiers)); 19 | } 20 | 21 | [Pure] 22 | public static string TypeNameForNullableType(string underlyingTypeFullName) 23 | { 24 | return String.Format("System.Nullable`1[{0}]", underlyingTypeFullName); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/ValueObjectSpecification.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.Contracts; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | 5 | namespace Diesel.CodeGeneration 6 | { 7 | public class ValueObjectSpecification 8 | { 9 | public bool IsValueType { get; private set; } 10 | public string Name { get; private set; } 11 | public NamespaceName Namespace { get; private set; } 12 | public PropertyDeclaration[] Properties { get; private set; } 13 | public BaseTypes BaseTypes { get; private set; } 14 | public bool IsDataContract { get; private set; } 15 | public bool IsSealed { get; private set; } 16 | 17 | private ValueObjectSpecification(bool isValueType, 18 | NamespaceName namespaceName, string name, 19 | PropertyDeclaration[] properties, 20 | BaseTypes baseTypes, 21 | bool isDataContract, bool isSealed) 22 | { 23 | IsValueType = isValueType; 24 | Namespace = namespaceName; 25 | Name = name; 26 | Properties = properties; 27 | BaseTypes = baseTypes; 28 | IsDataContract = isDataContract; 29 | IsSealed = isSealed; 30 | } 31 | 32 | [Pure] 33 | public static ValueObjectSpecification CreateStruct( 34 | NamespaceName namespaceName, string name, 35 | PropertyDeclaration[] properties, 36 | BaseTypes baseTypes, 37 | bool isDataContract) 38 | { 39 | return new ValueObjectSpecification(true, namespaceName, name, properties, baseTypes, isDataContract, true); 40 | } 41 | 42 | [Pure] 43 | public static ValueObjectSpecification CreateClass( 44 | NamespaceName namespaceName, string name, 45 | PropertyDeclaration[] properties, 46 | BaseTypes baseTypes, 47 | bool isDataContract, bool isSealed) 48 | { 49 | return new ValueObjectSpecification(false, namespaceName, name, properties, baseTypes, isDataContract, isSealed); 50 | } 51 | 52 | } 53 | } -------------------------------------------------------------------------------- /Diesel/CodeGeneration/ValueTypeGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.CodeDom; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Diesel.Parsing; 8 | using Diesel.Parsing.CSharp; 9 | using Diesel.Transformations; 10 | 11 | namespace Diesel.CodeGeneration 12 | { 13 | public class ValueTypeGenerator : CodeDomGenerator 14 | { 15 | public static CodeTypeDeclaration CreateValueTypeDeclaration( 16 | SemanticModel model, NamespaceName namespaceName, 17 | ValueTypeDeclaration declaration) 18 | { 19 | var result = CreateTypeWithValueSemantics( 20 | ValueObjectSpecification.CreateStruct( 21 | namespaceName, declaration.Name, 22 | declaration.Properties.ToArray(), 23 | new BaseTypes(new TypeName[0]), 24 | false), 25 | model.KnownTypes); 26 | if (declaration.Properties.Count() == 1) 27 | { 28 | AddDebuggerDisplayAttribute(declaration, result); 29 | } 30 | AddToString(declaration, result); 31 | return result; 32 | } 33 | 34 | private static void AddToString(ValueTypeDeclaration declaration, CodeTypeDeclaration result) 35 | { 36 | result.Members.Add(CreateToString(declaration.Properties)); 37 | } 38 | 39 | private static void AddDebuggerDisplayAttribute(ValueTypeDeclaration declaration, CodeTypeDeclaration result) 40 | { 41 | var displayTemplate = String.Format("{{{0}}}", declaration.Properties.Single().Name); 42 | result.CustomAttributes.Add(CreateDebuggerDisplayAttribute(displayTemplate)); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Diesel/Diesel.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {199CBCF0-8F94-477B-AC53-31381D6617B2} 8 | Library 9 | Properties 10 | Diesel 11 | Diesel 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\Sprache.1.10.0.28\lib\net40\Sprache.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 123 | -------------------------------------------------------------------------------- /Diesel/Diesel.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/mjul/diesel/blob/master/LICENSE.txt 10 | https://github.com/mjul/diesel/ 11 | 12 | false 13 | $description$ 14 | Please refer to the CHANGELOG.md file at the project web site. 15 | Copyright 2013 16 | DDD DSL CodeDom Compiler Generator 17 | 18 | 19 | -------------------------------------------------------------------------------- /Diesel/DieselCompiler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.CodeDom; 3 | using System.CodeDom.Compiler; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using Diesel.CodeGeneration; 10 | using Diesel.Parsing; 11 | using Diesel.Transformations; 12 | using Sprache; 13 | 14 | namespace Diesel 15 | { 16 | /// 17 | /// Responsible for compiling Diesel source code to C#. 18 | /// 19 | public static class DieselCompiler 20 | { 21 | public static string Compile(string modelSourceCode) 22 | { 23 | var ast = Grammar.Everything.Parse(modelSourceCode); 24 | var semanticModel = ModelTransformations.Transform(ast); 25 | var codeDom = CodeDomCompiler.Compile(semanticModel); 26 | return CompileToSource(codeDom, GetCSharpProvider()); 27 | } 28 | 29 | public static string CompileToSource(CodeCompileUnit actual, CodeDomProvider codeDomProvider) 30 | { 31 | var output = new StringWriter(); 32 | var provider = codeDomProvider; 33 | provider.GenerateCodeFromCompileUnit(actual, output, 34 | new CodeGeneratorOptions { BlankLinesBetweenMembers = true }); 35 | var source = output.GetStringBuilder().ToString(); 36 | return source; 37 | } 38 | 39 | public static CodeDomProvider GetCSharpProvider() 40 | { 41 | return CodeDomProvider.CreateProvider("CSharp"); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Diesel/Parsing/AbstractSyntaxTree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | public class AbstractSyntaxTree : IDieselExpression 6 | { 7 | public ConventionsDeclaration Conventions { get; private set; } 8 | public IEnumerable Namespaces { get; private set; } 9 | 10 | public AbstractSyntaxTree(ConventionsDeclaration conventions, IEnumerable namespaces) 11 | { 12 | Conventions = conventions; 13 | Namespaces = namespaces; 14 | } 15 | 16 | public IEnumerable Children 17 | { 18 | get 19 | { 20 | yield return Conventions; 21 | foreach (var ns in Namespaces) 22 | yield return ns; 23 | } 24 | } 25 | 26 | public void Accept(IDieselExpressionVisitor visitor) 27 | { 28 | visitor.Visit(this); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Diesel/Parsing/ApplicationServiceDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | public class ApplicationServiceDeclaration : TypeDeclaration 6 | { 7 | public IEnumerable Commands { get; private set; } 8 | 9 | public ApplicationServiceDeclaration(string name, IEnumerable commands) 10 | : base(name) 11 | { 12 | Commands = commands; 13 | } 14 | 15 | public override IEnumerable Children 16 | { 17 | get { return Commands; } 18 | } 19 | 20 | public override void Accept(ITypeDeclarationVisitor visitor) 21 | { 22 | visitor.Visit(this); 23 | } 24 | } 25 | 26 | public abstract class TypeDeclaration : ITypeDeclaration 27 | { 28 | public string Name { get; private set; } 29 | protected TypeDeclaration(string name) 30 | { 31 | Name = name; 32 | } 33 | public abstract IEnumerable Children { get; } 34 | 35 | public void Accept(IDieselExpressionVisitor visitor) 36 | { 37 | Accept((ITypeDeclarationVisitor) visitor); 38 | } 39 | 40 | public abstract void Accept(ITypeDeclarationVisitor visitor); 41 | } 42 | } -------------------------------------------------------------------------------- /Diesel/Parsing/BaseTypes.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Diesel.Parsing.CSharp; 5 | 6 | namespace Diesel.Parsing 7 | { 8 | public class BaseTypes : ITreeNode, IEquatable 9 | { 10 | public IEnumerable TypeNames { get; private set; } 11 | 12 | public BaseTypes(IEnumerable baseTypes) 13 | { 14 | TypeNames = baseTypes; 15 | } 16 | 17 | public BaseTypes ApplyOverridesFrom(BaseTypes other) 18 | { 19 | if (other == null) return this; 20 | 21 | var newBaseTypes = new List(); 22 | if (other.TypeNames != null) 23 | { 24 | newBaseTypes.AddRange(other.TypeNames); 25 | } 26 | else 27 | { 28 | if (TypeNames != null) 29 | { 30 | newBaseTypes.AddRange(TypeNames); 31 | } 32 | } 33 | return new BaseTypes(newBaseTypes); 34 | } 35 | 36 | public IEnumerable Children 37 | { 38 | get { return TypeNames; } 39 | } 40 | 41 | public bool Equals(BaseTypes other) 42 | { 43 | if (ReferenceEquals(null, other)) return false; 44 | if (ReferenceEquals(this, other)) return true; 45 | if (this.TypeNames == null && other.TypeNames == null) return true; 46 | if (this.TypeNames == null || other.TypeNames == null) return false; 47 | return Enumerable.SequenceEqual(TypeNames, other.TypeNames); 48 | } 49 | 50 | public override bool Equals(object obj) 51 | { 52 | if (ReferenceEquals(null, obj)) return false; 53 | if (ReferenceEquals(this, obj)) return true; 54 | if (obj.GetType() != this.GetType()) return false; 55 | return Equals((BaseTypes) obj); 56 | } 57 | 58 | public override int GetHashCode() 59 | { 60 | return (TypeNames != null ? TypeNames.GetHashCode() : 0); 61 | } 62 | 63 | public static bool operator ==(BaseTypes left, BaseTypes right) 64 | { 65 | return Equals(left, right); 66 | } 67 | 68 | public static bool operator !=(BaseTypes left, BaseTypes right) 69 | { 70 | return !Equals(left, right); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/ArrayType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Diesel.Parsing.CSharp 5 | { 6 | public class ArrayType : IReferenceType, IEquatable 7 | { 8 | public ITypeNode Type { get; private set; } 9 | public RankSpecifiers RankSpecifiers { get; set; } 10 | 11 | public ArrayType(ITypeNode nonArrayType, RankSpecifiers rankSpecifiers) 12 | { 13 | Type = nonArrayType; 14 | RankSpecifiers = rankSpecifiers; 15 | } 16 | 17 | public void Accept(ITypeNodeVisitor visitor) 18 | { 19 | visitor.Visit(this); 20 | } 21 | 22 | public IEnumerable Children 23 | { 24 | get 25 | { 26 | yield return Type; 27 | yield return RankSpecifiers; 28 | } 29 | } 30 | 31 | public bool Equals(ArrayType other) 32 | { 33 | if (ReferenceEquals(null, other)) return false; 34 | if (ReferenceEquals(this, other)) return true; 35 | return Equals(Type, other.Type) && Equals(RankSpecifiers, other.RankSpecifiers); 36 | } 37 | 38 | public override bool Equals(object obj) 39 | { 40 | if (ReferenceEquals(null, obj)) return false; 41 | if (ReferenceEquals(this, obj)) return true; 42 | if (obj.GetType() != this.GetType()) return false; 43 | return Equals((ArrayType) obj); 44 | } 45 | 46 | public override int GetHashCode() 47 | { 48 | unchecked 49 | { 50 | return ((Type != null ? Type.GetHashCode() : 0)*397) ^ (RankSpecifiers != null ? RankSpecifiers.GetHashCode() : 0); 51 | } 52 | } 53 | 54 | public static bool operator ==(ArrayType left, ArrayType right) 55 | { 56 | return Equals(left, right); 57 | } 58 | 59 | public static bool operator !=(ArrayType left, ArrayType right) 60 | { 61 | return !Equals(left, right); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/IStructType.cs: -------------------------------------------------------------------------------- 1 | namespace Diesel.Parsing.CSharp 2 | { 3 | public interface IStructType : IValueTypeNode 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/ITypeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing.CSharp 4 | { 5 | public interface ITypeNode : ITreeNode 6 | { 7 | void Accept(ITypeNodeVisitor visitor); 8 | } 9 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/ITypeNodeVisitor.cs: -------------------------------------------------------------------------------- 1 | namespace Diesel.Parsing.CSharp 2 | { 3 | /// 4 | /// Visitor interface for TypeNode hierarchy. 5 | /// 6 | public interface ITypeNodeVisitor 7 | { 8 | void Visit(TypeName typeName); 9 | void Visit(StringReferenceType stringReferenceType); 10 | void Visit(ArrayType arrayType); 11 | void Visit(SimpleType simpleType); 12 | void Visit(NullableType nullableType); 13 | } 14 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/IValueTypeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing.CSharp 4 | { 5 | public interface IValueTypeNode : ITypeNode 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/Identifier.cs: -------------------------------------------------------------------------------- 1 | namespace Diesel.Parsing.CSharp 2 | { 3 | public class Identifier : Terminal 4 | { 5 | public string Name { get; private set; } 6 | public Identifier(string name) 7 | { 8 | Name = name; 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/NamespaceName.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace Diesel.Parsing.CSharp 4 | { 5 | [DebuggerDisplay("{Name}")] 6 | public class NamespaceName : Terminal 7 | { 8 | public string Name { get; private set; } 9 | public NamespaceName(string name) 10 | { 11 | Name = name; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/NullableType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Diesel.Parsing.CSharp 5 | { 6 | /// 7 | /// C# "nullable-type" production 8 | /// 9 | public class NullableType : IStructType, IEquatable 10 | { 11 | public ITypeNode Underlying { get; private set; } 12 | 13 | public NullableType(ITypeNode underlying) 14 | { 15 | Underlying = underlying; 16 | } 17 | 18 | public void Accept(ITypeNodeVisitor visitor) 19 | { 20 | visitor.Visit(this); 21 | } 22 | 23 | public IEnumerable Children 24 | { 25 | get { yield return Underlying; } 26 | } 27 | 28 | public bool Equals(NullableType other) 29 | { 30 | if (ReferenceEquals(null, other)) return false; 31 | if (ReferenceEquals(this, other)) return true; 32 | return Equals(Underlying, other.Underlying); 33 | } 34 | 35 | public override bool Equals(object obj) 36 | { 37 | if (ReferenceEquals(null, obj)) return false; 38 | if (ReferenceEquals(this, obj)) return true; 39 | if (obj.GetType() != this.GetType()) return false; 40 | return Equals((NullableType) obj); 41 | } 42 | 43 | public override int GetHashCode() 44 | { 45 | return (Underlying != null ? Underlying.GetHashCode() : 0); 46 | } 47 | 48 | public static bool operator ==(NullableType left, NullableType right) 49 | { 50 | return Equals(left, right); 51 | } 52 | 53 | public static bool operator !=(NullableType left, NullableType right) 54 | { 55 | return !Equals(left, right); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/RankSpecifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Diesel.Parsing.CSharp 4 | { 5 | public class RankSpecifier : Terminal, IEquatable 6 | { 7 | public int Dimensions { get; private set; } 8 | 9 | public RankSpecifier(int dimensions) 10 | { 11 | Dimensions = dimensions; 12 | } 13 | 14 | public bool Equals(RankSpecifier other) 15 | { 16 | if (ReferenceEquals(null, other)) return false; 17 | if (ReferenceEquals(this, other)) return true; 18 | return Dimensions == other.Dimensions; 19 | } 20 | 21 | public override bool Equals(object obj) 22 | { 23 | if (ReferenceEquals(null, obj)) return false; 24 | if (ReferenceEquals(this, obj)) return true; 25 | if (obj.GetType() != this.GetType()) return false; 26 | return Equals((RankSpecifier) obj); 27 | } 28 | 29 | public override int GetHashCode() 30 | { 31 | return Dimensions; 32 | } 33 | 34 | public static bool operator ==(RankSpecifier left, RankSpecifier right) 35 | { 36 | return Equals(left, right); 37 | } 38 | 39 | public static bool operator !=(RankSpecifier left, RankSpecifier right) 40 | { 41 | return !Equals(left, right); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/RankSpecifiers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Diesel.Parsing.CSharp 6 | { 7 | public class RankSpecifiers : ITreeNode, IEquatable 8 | { 9 | public IEnumerable Ranks { get; private set; } 10 | 11 | public RankSpecifiers(IEnumerable rankSpecifiers) 12 | { 13 | Ranks = rankSpecifiers; 14 | } 15 | public IEnumerable Children { get { yield break; } } 16 | 17 | public bool Equals(RankSpecifiers other) 18 | { 19 | if (ReferenceEquals(null, other)) return false; 20 | if (ReferenceEquals(this, other)) return true; 21 | var myRanks = Ranks.ToList(); 22 | var otherRanks = other.Ranks.ToList(); 23 | if (myRanks.Count != otherRanks.Count) return false; 24 | return !Enumerable.Zip(myRanks, otherRanks, (x, y) => (x == y)) 25 | .Any(pairEqual => pairEqual == false); 26 | } 27 | 28 | public override bool Equals(object obj) 29 | { 30 | if (ReferenceEquals(null, obj)) return false; 31 | if (ReferenceEquals(this, obj)) return true; 32 | if (obj.GetType() != this.GetType()) return false; 33 | return Equals((RankSpecifiers) obj); 34 | } 35 | 36 | public override int GetHashCode() 37 | { 38 | return 1; 39 | } 40 | 41 | public static bool operator ==(RankSpecifiers left, RankSpecifiers right) 42 | { 43 | return Equals(left, right); 44 | } 45 | 46 | public static bool operator !=(RankSpecifiers left, RankSpecifiers right) 47 | { 48 | return !Equals(left, right); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/ReferenceType.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing.CSharp 4 | { 5 | /// 6 | /// Marker interface for C# grammar reference-type production nodes. 7 | /// 8 | public interface IReferenceType : ITypeNode 9 | { 10 | } 11 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/SimpleType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Diesel.Parsing.CSharp 5 | { 6 | /// 7 | /// The C# "simple-type" production (simplified, no subtypes for bool, integral and floating) 8 | /// 9 | public class SimpleType : IStructType, IEquatable 10 | { 11 | public Type Type { get; set; } 12 | 13 | public SimpleType(Type type) 14 | { 15 | Type = type; 16 | } 17 | 18 | public void Accept(ITypeNodeVisitor visitor) 19 | { 20 | visitor.Visit(this); 21 | } 22 | 23 | public IEnumerable Children 24 | { 25 | get { yield break; } 26 | } 27 | 28 | public bool Equals(SimpleType other) 29 | { 30 | if (ReferenceEquals(null, other)) return false; 31 | if (ReferenceEquals(this, other)) return true; 32 | return Equals(Type, other.Type); 33 | } 34 | 35 | public override bool Equals(object obj) 36 | { 37 | if (ReferenceEquals(null, obj)) return false; 38 | if (ReferenceEquals(this, obj)) return true; 39 | if (obj.GetType() != this.GetType()) return false; 40 | return Equals((SimpleType) obj); 41 | } 42 | 43 | public override int GetHashCode() 44 | { 45 | return (Type != null ? Type.GetHashCode() : 0); 46 | } 47 | 48 | public static bool operator ==(SimpleType left, SimpleType right) 49 | { 50 | return Equals(left, right); 51 | } 52 | 53 | public static bool operator !=(SimpleType left, SimpleType right) 54 | { 55 | return !Equals(left, right); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/StringReferenceType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Diesel.Parsing.CSharp 5 | { 6 | public class StringReferenceType : IReferenceType, IEquatable 7 | { 8 | public void Accept(ITypeNodeVisitor visitor) 9 | { 10 | visitor.Visit(this); 11 | } 12 | 13 | public IEnumerable Children 14 | { 15 | get { yield break; } 16 | } 17 | 18 | public bool Equals(StringReferenceType other) 19 | { 20 | return true; 21 | } 22 | 23 | public override bool Equals(object obj) 24 | { 25 | if (ReferenceEquals(null, obj)) return false; 26 | if (ReferenceEquals(this, obj)) return true; 27 | if (obj.GetType() != this.GetType()) return false; 28 | return Equals((StringReferenceType) obj); 29 | } 30 | 31 | public override int GetHashCode() 32 | { 33 | return 1; 34 | } 35 | 36 | public static bool operator ==(StringReferenceType left, StringReferenceType right) 37 | { 38 | return Equals(left, right); 39 | } 40 | 41 | public static bool operator !=(StringReferenceType left, StringReferenceType right) 42 | { 43 | return !Equals(left, right); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CSharp/TypeName.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Diesel.Parsing.CSharp 5 | { 6 | [DebuggerDisplay("{Name}")] 7 | public class TypeName : Terminal, IEquatable, ITypeNode, IStructType 8 | { 9 | public string Name { get; private set; } 10 | public TypeName(string name) 11 | { 12 | Name = name; 13 | } 14 | 15 | public bool Equals(TypeName other) 16 | { 17 | if (ReferenceEquals(null, other)) return false; 18 | if (ReferenceEquals(this, other)) return true; 19 | return string.Equals(Name, other.Name); 20 | } 21 | 22 | public override bool Equals(object obj) 23 | { 24 | if (ReferenceEquals(null, obj)) return false; 25 | if (ReferenceEquals(this, obj)) return true; 26 | if (obj.GetType() != this.GetType()) return false; 27 | return Equals((TypeName) obj); 28 | } 29 | 30 | public override int GetHashCode() 31 | { 32 | return (Name != null ? Name.GetHashCode() : 0); 33 | } 34 | 35 | public void Accept(ITypeNodeVisitor visitor) 36 | { 37 | visitor.Visit(this); 38 | } 39 | 40 | public static bool operator ==(TypeName left, TypeName right) 41 | { 42 | return Equals(left, right); 43 | } 44 | 45 | public static bool operator !=(TypeName left, TypeName right) 46 | { 47 | return !Equals(left, right); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CommandConventions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Diesel.Parsing.CSharp; 4 | 5 | namespace Diesel.Parsing 6 | { 7 | public class CommandConventions : IConventionsNode, IEquatable 8 | { 9 | public BaseTypes BaseTypes { get; private set; } 10 | 11 | public CommandConventions(BaseTypes baseTypes) 12 | { 13 | BaseTypes = baseTypes; 14 | } 15 | 16 | public IEnumerable Children 17 | { 18 | get { yield return BaseTypes; } 19 | } 20 | 21 | public CommandConventions ApplyOverridesFrom(CommandConventions other) 22 | { 23 | if (other == null) 24 | return this; 25 | var newBaseTypeConventions = 26 | (BaseTypes ?? new BaseTypes(new TypeName[0])) 27 | .ApplyOverridesFrom(other.BaseTypes); 28 | return new CommandConventions(newBaseTypeConventions); 29 | } 30 | 31 | public bool Equals(CommandConventions other) 32 | { 33 | if (ReferenceEquals(null, other)) return false; 34 | if (ReferenceEquals(this, other)) return true; 35 | return Equals(BaseTypes, other.BaseTypes); 36 | } 37 | 38 | public override bool Equals(object obj) 39 | { 40 | if (ReferenceEquals(null, obj)) return false; 41 | if (ReferenceEquals(this, obj)) return true; 42 | if (obj.GetType() != this.GetType()) return false; 43 | return Equals((CommandConventions) obj); 44 | } 45 | 46 | public override int GetHashCode() 47 | { 48 | return (BaseTypes != null ? BaseTypes.GetHashCode() : 0); 49 | } 50 | 51 | public static bool operator ==(CommandConventions left, CommandConventions right) 52 | { 53 | return Equals(left, right); 54 | } 55 | 56 | public static bool operator !=(CommandConventions left, CommandConventions right) 57 | { 58 | return !Equals(left, right); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Diesel/Parsing/CommandDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | public class CommandDeclaration : TypeDeclaration 6 | { 7 | public IEnumerable Properties { get; private set; } 8 | 9 | public CommandDeclaration(string name, IEnumerable properties) 10 | : base(name) 11 | { 12 | Properties = properties; 13 | } 14 | 15 | public override IEnumerable Children 16 | { 17 | get { return Properties; } 18 | } 19 | 20 | public override void Accept(ITypeDeclarationVisitor visitor) 21 | { 22 | visitor.Visit(this); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Diesel/Parsing/ConventionsDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Diesel.Parsing.CSharp; 5 | 6 | namespace Diesel.Parsing 7 | { 8 | public class ConventionsDeclaration : IDieselExpression, IEquatable 9 | { 10 | public DomainEventConventions DomainEventConventions { get; private set; } 11 | public CommandConventions CommandConventions { get; private set; } 12 | 13 | public ConventionsDeclaration(DomainEventConventions domainEventConventions, 14 | CommandConventions commandConventions) 15 | { 16 | DomainEventConventions = domainEventConventions; 17 | CommandConventions = commandConventions; 18 | } 19 | 20 | public IEnumerable Children 21 | { 22 | get { 23 | if (null != DomainEventConventions) 24 | { 25 | foreach (var d in DomainEventConventions.Children) 26 | yield return d; 27 | } 28 | if (null != CommandConventions) 29 | { 30 | foreach (var d in CommandConventions.Children) 31 | yield return d; 32 | } 33 | } 34 | } 35 | 36 | public void Accept(IDieselExpressionVisitor visitor) 37 | { 38 | visitor.Visit(this); 39 | } 40 | 41 | public ConventionsDeclaration ApplyOverridesFrom(ConventionsDeclaration other) 42 | { 43 | if (other != null) 44 | { 45 | var newDomainEventConventions = 46 | (DomainEventConventions ?? new DomainEventConventions(new BaseTypes(new TypeName[] {}))) 47 | .ApplyOverridesFrom(other.DomainEventConventions); 48 | var newCommandConventions = 49 | (CommandConventions ?? new CommandConventions(new BaseTypes(new TypeName[] {}))) 50 | .ApplyOverridesFrom(other.CommandConventions); 51 | return new ConventionsDeclaration(newDomainEventConventions, newCommandConventions); 52 | } 53 | else 54 | { 55 | return this; 56 | } 57 | } 58 | 59 | public bool Equals(ConventionsDeclaration other) 60 | { 61 | if (ReferenceEquals(null, other)) return false; 62 | if (ReferenceEquals(this, other)) return true; 63 | return Equals(DomainEventConventions, other.DomainEventConventions) && Equals(CommandConventions, other.CommandConventions); 64 | } 65 | 66 | public override bool Equals(object obj) 67 | { 68 | if (ReferenceEquals(null, obj)) return false; 69 | if (ReferenceEquals(this, obj)) return true; 70 | if (obj.GetType() != this.GetType()) return false; 71 | return Equals((ConventionsDeclaration) obj); 72 | } 73 | 74 | public override int GetHashCode() 75 | { 76 | unchecked 77 | { 78 | return ((DomainEventConventions != null ? DomainEventConventions.GetHashCode() : 0)*397) ^ (CommandConventions != null ? CommandConventions.GetHashCode() : 0); 79 | } 80 | } 81 | 82 | public static bool operator ==(ConventionsDeclaration left, ConventionsDeclaration right) 83 | { 84 | return Equals(left, right); 85 | } 86 | 87 | public static bool operator !=(ConventionsDeclaration left, ConventionsDeclaration right) 88 | { 89 | return !Equals(left, right); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Diesel/Parsing/DomainEventConventions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Diesel.Parsing.CSharp; 4 | 5 | namespace Diesel.Parsing 6 | { 7 | public class DomainEventConventions : IConventionsNode, IEquatable 8 | { 9 | public BaseTypes BaseTypes { get; private set; } 10 | 11 | public DomainEventConventions(BaseTypes baseTypes) 12 | { 13 | BaseTypes = baseTypes; 14 | } 15 | 16 | public IEnumerable Children 17 | { 18 | get 19 | { 20 | if (BaseTypes != null) 21 | { 22 | foreach (var treeNode in BaseTypes.Children) 23 | { 24 | yield return treeNode; 25 | } 26 | } 27 | } 28 | } 29 | 30 | public DomainEventConventions ApplyOverridesFrom(DomainEventConventions other) 31 | { 32 | if (null == other) return this; 33 | if (null == BaseTypes) return other; 34 | var newBaseTypes = BaseTypes.ApplyOverridesFrom(other.BaseTypes); 35 | return new DomainEventConventions(newBaseTypes); 36 | } 37 | 38 | 39 | public bool Equals(DomainEventConventions other) 40 | { 41 | if (ReferenceEquals(null, other)) return false; 42 | if (ReferenceEquals(this, other)) return true; 43 | return Equals(BaseTypes, other.BaseTypes); 44 | } 45 | 46 | public override bool Equals(object obj) 47 | { 48 | if (ReferenceEquals(null, obj)) return false; 49 | if (ReferenceEquals(this, obj)) return true; 50 | if (obj.GetType() != this.GetType()) return false; 51 | return Equals((DomainEventConventions) obj); 52 | } 53 | 54 | public override int GetHashCode() 55 | { 56 | return (BaseTypes != null ? BaseTypes.GetHashCode() : 0); 57 | } 58 | 59 | public static bool operator ==(DomainEventConventions left, DomainEventConventions right) 60 | { 61 | return Equals(left, right); 62 | } 63 | 64 | public static bool operator !=(DomainEventConventions left, DomainEventConventions right) 65 | { 66 | return !Equals(left, right); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Diesel/Parsing/DomainEventDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Diesel.Parsing 5 | { 6 | public class DomainEventDeclaration 7 | : TypeDeclaration 8 | { 9 | public IEnumerable Properties { get; private set; } 10 | 11 | public DomainEventDeclaration(string name, IEnumerable properties) 12 | : base(name) 13 | { 14 | Properties = properties; 15 | } 16 | 17 | public override IEnumerable Children 18 | { 19 | get { return Properties; } 20 | } 21 | 22 | public override void Accept(ITypeDeclarationVisitor visitor) 23 | { 24 | visitor.Visit(this); 25 | } 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /Diesel/Parsing/DtoDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | public class DtoDeclaration : TypeDeclaration 6 | { 7 | public IEnumerable Properties { get; private set; } 8 | 9 | public DtoDeclaration(string name, IEnumerable properties) 10 | : base(name) 11 | { 12 | Properties = properties; 13 | } 14 | 15 | public override IEnumerable Children 16 | { 17 | get { return Properties; } 18 | } 19 | 20 | public override void Accept(ITypeDeclarationVisitor visitor) 21 | { 22 | visitor.Visit(this); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Diesel/Parsing/EnumDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | public class EnumDeclaration : TypeDeclaration 6 | { 7 | public IEnumerable Values { get; private set; } 8 | 9 | public EnumDeclaration(string name, IEnumerable values) 10 | :base(name) 11 | { 12 | Values = values; 13 | } 14 | 15 | public override IEnumerable Children 16 | { 17 | get { yield break; } 18 | } 19 | 20 | public override void Accept(ITypeDeclarationVisitor visitor) 21 | { 22 | visitor.Visit(this); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Diesel/Parsing/IConventionsNode.cs: -------------------------------------------------------------------------------- 1 | namespace Diesel.Parsing 2 | { 3 | public interface IConventionsNode : ITreeNode 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Diesel/Parsing/IDieselExpression.cs: -------------------------------------------------------------------------------- 1 | namespace Diesel.Parsing 2 | { 3 | /// 4 | /// Interface for the high-level model nodes. 5 | /// 6 | public interface IDieselExpression : ITreeNode 7 | { 8 | void Accept(IDieselExpressionVisitor visitor); 9 | } 10 | } -------------------------------------------------------------------------------- /Diesel/Parsing/IDieselExpressionVisitor.cs: -------------------------------------------------------------------------------- 1 | namespace Diesel.Parsing 2 | { 3 | public interface IDieselExpressionVisitor : ITypeDeclarationVisitor 4 | { 5 | void Visit(AbstractSyntaxTree node); 6 | void Visit(Namespace node); 7 | void Visit(ConventionsDeclaration node); 8 | } 9 | } -------------------------------------------------------------------------------- /Diesel/Parsing/ITreeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | public interface ITreeNode 6 | { 7 | IEnumerable Children { get; } 8 | } 9 | } -------------------------------------------------------------------------------- /Diesel/Parsing/ITypeDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | /// 6 | /// Common interface for DSL named type declarations. 7 | /// 8 | public interface ITypeDeclaration : IDieselExpression 9 | { 10 | String Name { get; } 11 | void Accept(ITypeDeclarationVisitor visitor); 12 | } 13 | } -------------------------------------------------------------------------------- /Diesel/Parsing/ITypeDeclarationVisitor.cs: -------------------------------------------------------------------------------- 1 | namespace Diesel.Parsing 2 | { 3 | public interface ITypeDeclarationVisitor 4 | { 5 | void Visit(ApplicationServiceDeclaration node); 6 | void Visit(CommandDeclaration node); 7 | void Visit(DtoDeclaration node); 8 | void Visit(DomainEventDeclaration node); 9 | void Visit(EnumDeclaration node); 10 | void Visit(ValueTypeDeclaration node); 11 | } 12 | } -------------------------------------------------------------------------------- /Diesel/Parsing/Keyword.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Diesel.Parsing 5 | { 6 | [DebuggerDisplay(":{Name}")] 7 | public class Keyword : Terminal, IEquatable 8 | { 9 | public string Name { get; private set; } 10 | 11 | public Keyword(string name) 12 | { 13 | Name = name; 14 | } 15 | 16 | public bool Equals(Keyword other) 17 | { 18 | if (ReferenceEquals(null, other)) return false; 19 | if (ReferenceEquals(this, other)) return true; 20 | return string.Equals(Name, other.Name); 21 | } 22 | 23 | public override bool Equals(object obj) 24 | { 25 | if (ReferenceEquals(null, obj)) return false; 26 | if (ReferenceEquals(this, obj)) return true; 27 | if (obj.GetType() != this.GetType()) return false; 28 | return Equals((Keyword) obj); 29 | } 30 | 31 | public override int GetHashCode() 32 | { 33 | return (Name != null ? Name.GetHashCode() : 0); 34 | } 35 | 36 | public static bool operator ==(Keyword left, Keyword right) 37 | { 38 | return Equals(left, right); 39 | } 40 | 41 | public static bool operator !=(Keyword left, Keyword right) 42 | { 43 | return !Equals(left, right); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Diesel/Parsing/Namespace.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Diesel.Parsing.CSharp; 3 | 4 | namespace Diesel.Parsing 5 | { 6 | public class Namespace : IDieselExpression 7 | { 8 | public NamespaceName Name { get; private set; } 9 | public IEnumerable Declarations; 10 | 11 | public Namespace(NamespaceName name, IEnumerable declarations) 12 | { 13 | Name = name; 14 | Declarations = declarations; 15 | } 16 | 17 | public IEnumerable Children 18 | { 19 | get { return Declarations; } 20 | } 21 | 22 | public void Accept(IDieselExpressionVisitor visitor) 23 | { 24 | visitor.Visit(this); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Diesel/Parsing/PropertyDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Diesel.Parsing.CSharp; 4 | 5 | namespace Diesel.Parsing 6 | { 7 | public class PropertyDeclaration : ITreeNode 8 | { 9 | public string Name { get; private set; } 10 | public ITypeNode Type { get; private set; } 11 | 12 | public PropertyDeclaration(string name, ITypeNode type) 13 | { 14 | Name = name; 15 | Type = type; 16 | } 17 | 18 | public IEnumerable Children 19 | { 20 | get { yield break; } 21 | } 22 | 23 | [Obsolete("Move to semantic model")] 24 | public PropertyDeclaration OverrideType(ITypeNode type) 25 | { 26 | return new PropertyDeclaration(Name, type); 27 | } 28 | 29 | [Obsolete("Move to semantic model")] 30 | public PropertyDeclaration OverrideName(string name) 31 | { 32 | return new PropertyDeclaration(name, Type); 33 | } 34 | 35 | } 36 | } -------------------------------------------------------------------------------- /Diesel/Parsing/Symbol.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | public class Symbol : Terminal 6 | { 7 | public string Name { get; set; } 8 | public Symbol(string name) 9 | { 10 | Name = name; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Diesel/Parsing/Terminal.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Diesel.Parsing 4 | { 5 | public abstract class Terminal : ITreeNode 6 | { 7 | public IEnumerable Children 8 | { 9 | get { yield break; } 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Diesel/Parsing/TokenGrammar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Sprache; 4 | 5 | namespace Diesel.Parsing 6 | { 7 | public static class TokenGrammar 8 | { 9 | private static Parser Char(char c, string name) 10 | { 11 | return Parse.Char(c).Named(name); 12 | } 13 | 14 | public static Parser String(string value) 15 | { 16 | return Parse.String(value).Text().Named(value); 17 | } 18 | 19 | public static readonly Parser LeftParen = Char('(', "LeftParen"); 20 | public static readonly Parser RightParen = Char(')', "RightParen"); 21 | public static readonly Parser Letter = Parse.Letter; 22 | public static readonly Parser LetterOrDigit = Parse.LetterOrDigit; 23 | public static readonly Parser Comma = Char(',', "Comma"); 24 | public static readonly Parser Period = Char('.', "Period"); 25 | public static readonly Parser QuestionMark = Char('?', "Question Mark"); 26 | public static readonly Parser Colon = Char(':', "Colon"); 27 | public static readonly Parser Underscore = Char('_', "Underscore"); 28 | 29 | public static readonly Parser LeftCurlyBrace = Char('{', "LeftCurlyBrace"); 30 | public static readonly Parser RightCurlyBrace = Char('}', "RightCurlyBrace"); 31 | public static readonly Parser LeftSquareBracket = Char('[', "LeftSquareBracket"); 32 | public static readonly Parser RightSquareBracket = Char(']', "RightSquareBracket"); 33 | 34 | public static readonly Parser Semicolon = Char(';', "Semicolon"); 35 | 36 | public static readonly Parser CarriageReturn = Char('\u000D' , "CR"); 37 | public static readonly Parser LineFeed = Char('\u000A', "LineFeed"); 38 | public static readonly Parser LineSeparator = Char('\u2028', "LineSeparator"); 39 | public static readonly Parser ParagraphSeparator = Char('\u2029', "ParagraphSeparator"); 40 | 41 | private static readonly char[] NewLineChars = {'\u000D', '\u000A', '\u2028', '\u2029'}; 42 | 43 | public static readonly Parser CarriageReturnLineFeed 44 | = (from cr in CarriageReturn 45 | from lf in LineFeed 46 | select Environment.NewLine); 47 | 48 | public static readonly Parser NewLine = 49 | CarriageReturnLineFeed 50 | .Or(CarriageReturn.Select(c => Environment.NewLine)) 51 | .Or(LineFeed.Select(c => Environment.NewLine)) 52 | .Or(LineSeparator.Select(c => Environment.NewLine)) 53 | .Or(ParagraphSeparator.Select(c => Environment.NewLine)); 54 | 55 | public static readonly Parser RestOfLine = Parse.CharExcept(NewLineChars).Many().Text(); 56 | } 57 | } -------------------------------------------------------------------------------- /Diesel/Parsing/ValueTypeDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Diesel.Parsing 6 | { 7 | public class ValueTypeDeclaration : TypeDeclaration 8 | { 9 | public ValueTypeDeclaration(string name, IEnumerable propertyDeclarations) 10 | : base(name) 11 | { 12 | Properties = propertyDeclarations; 13 | } 14 | 15 | public IEnumerable Properties { get; private set; } 16 | 17 | public override IEnumerable Children 18 | { 19 | get { return Properties; } 20 | } 21 | 22 | public override void Accept(ITypeDeclarationVisitor visitor) 23 | { 24 | visitor.Visit(this); 25 | } 26 | 27 | [Obsolete("Move to semantic model")] 28 | public ValueTypeDeclaration ReplaceProperties(Func function) 29 | { 30 | return new ValueTypeDeclaration(Name, Properties.Select(function)); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Diesel/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Diesel")] 9 | [assembly: AssemblyDescription("Diesel is a DSL toolkit for .NET code generation for DDD")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Martin Jul")] 12 | [assembly: AssemblyProduct("Diesel")] 13 | [assembly: AssemblyCopyright("Copyright © 2013 Martin Jul (www.mjul.com)")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1109a3ba-dbee-432d-a9d5-df153b24fe38")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.15.0")] 36 | [assembly: AssemblyFileVersion("1.15.0.0")] 37 | -------------------------------------------------------------------------------- /Diesel/Transformations/ApplyDefaults.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Diesel.Parsing; 4 | using Diesel.Parsing.CSharp; 5 | 6 | namespace Diesel.Transformations 7 | { 8 | /// 9 | /// Apply defaults to the model specified in the AST. 10 | /// 11 | public class ApplyDefaults : ModelTransformation 12 | { 13 | private static readonly SimpleType DefaultPropertyType = new SimpleType(typeof(Int32)); 14 | private const string DefaultPropertyName = "Value"; 15 | 16 | /// 17 | /// Add the default type and property name to 18 | /// if they have not been specified. 19 | /// 20 | public override ValueTypeDeclaration Transform(ValueTypeDeclaration valueTypeDeclaration) 21 | { 22 | var result = base.Transform(valueTypeDeclaration); 23 | var isSimpleDeclaration = (valueTypeDeclaration.Properties.Count() == 1); 24 | if (isSimpleDeclaration) 25 | { 26 | result = result 27 | .ReplaceProperties(p => (null == p.Type) ? p.OverrideType(DefaultPropertyType) : p) 28 | .ReplaceProperties(p => (null == p.Name) ? p.OverrideName(DefaultPropertyName) : p); 29 | } 30 | return result; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Diesel/Transformations/FullyQualifiedNameRule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.Parsing.CSharp; 3 | 4 | namespace Diesel.Transformations 5 | { 6 | internal class FullyQualifiedNameRule 7 | { 8 | public static string For(NamespaceName namespaceName, TypeName typeName) 9 | { 10 | return For(namespaceName, typeName.Name); 11 | } 12 | 13 | public static string For(NamespaceName namespaceName, String typeName) 14 | { 15 | var isQualified = typeName.Contains("."); 16 | return isQualified 17 | ? typeName 18 | : String.Format("{0}.{1}", namespaceName.Name, typeName); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Diesel/Transformations/KnownType.cs: -------------------------------------------------------------------------------- 1 | namespace Diesel.Transformations 2 | { 3 | /// 4 | /// Represents a known type in the model. 5 | /// 6 | public class KnownType 7 | { 8 | public string FullName { get; private set; } 9 | public bool IsValueType { get; private set; } 10 | 11 | public KnownType(string fullName, bool isValueType) 12 | { 13 | FullName = fullName; 14 | IsValueType = isValueType; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Diesel/Transformations/KnownTypesHarvester.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Diesel.CodeGeneration; 4 | using Diesel.Parsing; 5 | 6 | namespace Diesel.Transformations 7 | { 8 | /// 9 | /// Get all declared types from the . 10 | /// 11 | public class KnownTypesHarvester : IDieselExpressionVisitor 12 | { 13 | private readonly List _knownTypes = new List(); 14 | private readonly Stack _namespaceStack = new Stack(); 15 | 16 | /// 17 | /// Get the known types from the . 18 | /// 19 | /// 20 | /// 21 | public static List GetKnownTypes(AbstractSyntaxTree abstractSyntaxTree) 22 | { 23 | var harvester = new KnownTypesHarvester(); 24 | harvester.Visit(abstractSyntaxTree); 25 | return harvester._knownTypes; 26 | } 27 | 28 | public void Visit(AbstractSyntaxTree node) 29 | { 30 | Visit(node.Conventions); 31 | foreach (var ns in node.Namespaces) 32 | { 33 | _namespaceStack.Push(ns); 34 | ns.Accept(this); 35 | _namespaceStack.Pop(); 36 | } 37 | } 38 | 39 | public void Visit(Namespace node) 40 | { 41 | foreach (var declaration in node.Declarations) 42 | { 43 | declaration.Accept(this); 44 | } 45 | } 46 | 47 | public void Visit(ConventionsDeclaration node) 48 | { 49 | } 50 | 51 | public void Visit(ApplicationServiceDeclaration node) 52 | { 53 | var fullName = FullName(node.Name); 54 | _knownTypes.Add(new KnownType(fullName, false)); 55 | } 56 | 57 | private string FullName(string name) 58 | { 59 | return FullyQualifiedNameRule.For(_namespaceStack.Peek().Name, name); 60 | } 61 | 62 | public void Visit(CommandDeclaration node) 63 | { 64 | var fullName = FullName(node.Name); 65 | _knownTypes.Add(new KnownType(fullName, false)); 66 | } 67 | 68 | public void Visit(DtoDeclaration node) 69 | { 70 | var fullName = FullName(node.Name); 71 | _knownTypes.Add(new KnownType(fullName, false)); 72 | } 73 | 74 | public void Visit(DomainEventDeclaration node) 75 | { 76 | var fullName = FullName(node.Name); 77 | _knownTypes.Add(new KnownType(fullName, false)); 78 | } 79 | 80 | public void Visit(EnumDeclaration node) 81 | { 82 | var fullName = FullName(node.Name); 83 | _knownTypes.Add(new KnownType(fullName, true)); 84 | } 85 | 86 | public void Visit(ValueTypeDeclaration node) 87 | { 88 | var fullName = FullName(node.Name); 89 | _knownTypes.Add(new KnownType(fullName, true)); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Diesel/Transformations/ModelTransformation.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Diesel.Parsing; 3 | 4 | namespace Diesel.Transformations 5 | { 6 | public abstract class ModelTransformation 7 | { 8 | public virtual AbstractSyntaxTree Transform(AbstractSyntaxTree ast) 9 | { 10 | return new AbstractSyntaxTree(Transform(ast.Conventions), ast.Namespaces.Select(Transform)); 11 | } 12 | 13 | private ConventionsDeclaration Transform(ConventionsDeclaration conventions) 14 | { 15 | return conventions; 16 | } 17 | 18 | public virtual Namespace Transform(Namespace ns) 19 | { 20 | return new Namespace(ns.Name, ns.Declarations 21 | .Select(d => Transform((dynamic)d))); 22 | } 23 | 24 | public virtual ValueTypeDeclaration Transform(ValueTypeDeclaration declaration) 25 | { 26 | return declaration; 27 | } 28 | 29 | public virtual CommandDeclaration Transform(CommandDeclaration declaration) 30 | { 31 | return declaration; 32 | } 33 | 34 | public virtual DomainEventDeclaration Transform(DomainEventDeclaration declaration) 35 | { 36 | return declaration; 37 | } 38 | 39 | public virtual DtoDeclaration Transform(DtoDeclaration declaration) 40 | { 41 | return declaration; 42 | } 43 | 44 | public virtual EnumDeclaration Transform(EnumDeclaration declaration) 45 | { 46 | return declaration; 47 | } 48 | 49 | public virtual ApplicationServiceDeclaration Transform(ApplicationServiceDeclaration declaration) 50 | { 51 | return declaration; 52 | } 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /Diesel/Transformations/ModelTransformations.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Diesel.Parsing; 3 | 4 | namespace Diesel.Transformations 5 | { 6 | public static class ModelTransformations 7 | { 8 | public static SemanticModel Transform(AbstractSyntaxTree ast) 9 | { 10 | var transformations = new[] {new ApplyDefaults()}; 11 | var transformedAst = transformations.Aggregate(ast, (a, t) => t.Transform(a)); 12 | return new SemanticModel(transformedAst); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Diesel/Transformations/SemanticModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Diesel.CodeGeneration; 4 | using Diesel.Parsing; 5 | 6 | namespace Diesel.Transformations 7 | { 8 | /// 9 | /// The semantic model of the code being compiled. 10 | /// 11 | public class SemanticModel 12 | { 13 | public AbstractSyntaxTree AbstractSyntaxTree { get; private set; } 14 | 15 | private readonly Lazy> _knownTypes; 16 | public IReadOnlyCollection KnownTypes { get { return _knownTypes.Value; } } 17 | 18 | public SemanticModel(AbstractSyntaxTree abstractSyntaxTree) 19 | { 20 | AbstractSyntaxTree = abstractSyntaxTree; 21 | _knownTypes = new Lazy>( 22 | () => KnownTypesHarvester.GetKnownTypes(abstractSyntaxTree)); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Diesel/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Martin Jul (www.mjul.com) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # Feature Requests 2 | 3 | ## Add DataContract Namespace to generated DTO types 4 | In order to completely control the serialization, allow the user to 5 | specify the DataContract namespace for generated types. 6 | 7 | ## Reference out-of-namespace known types without qualification 8 | The DSL should know all declared types allowed, and be able 9 | to reference them without writing the fully qualified type name. 10 | 11 | ## Declare Bounded Contexts 12 | Commands and Domain Events should then have DataContract namespaces 13 | corresponding to the bounded context's name. 14 | 15 | ## Support for C# keyword Identifiers 16 | Support for Identifiers like `@event` and other reserved C# keywords. 17 | 18 | ## Emit DebuggerDisplay for types with more than one field 19 | Currently, this is emitted only for single-field types. 20 | 21 | ## Configurable DebuggerDisplay on types 22 | Allow a way to configure the DebuggerDisplay on the generated types, e.g. 23 | declaring a way to generate `[DebuggerDisplay("{FirstName} {LastName}")]` 24 | on a value type, `(defvaluetype StudentName (string FirstName, string LastName))`. 25 | 26 | ## Validate model before generation 27 | 28 | ### Validate allowed types in DTO types (Commands, Events, DTOs). 29 | Commands and Domain events should only be able to have properties that are primitive types, 30 | arrays of these or other Data Transfer Objects. 31 | 32 | ### Emit friendly error when code is not generatable 33 | E.g. for multi-dimensional arrays in Equality. 34 | 35 | 36 | ## Multi-dimensional array equality 37 | Currently one single-dimensional arrays are supported when generating equality members. 38 | Implement these, too: 39 | 40 | (namespace TestCases.TypeDeclarations 41 | (defcommand PrintArraySimple2D (int[,] Value)) 42 | (defcommand PrintArraySimpleMulti (int[][,] Value)) 43 | 44 | ## ToString Generation on Value Types for Array properties 45 | Currently, the ToString does not expand and print the values of arrays in the generated ToString 46 | method. Add this (see GeneratedValueTypeWithArrayTest for ToString). 47 | 48 | -------------------------------------------------------------------------------- /Test/CodeExamples.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.18033 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Test.Diesel { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class CodeExamples { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal CodeExamples() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Test.Diesel.CodeExamples", typeof(CodeExamples).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to (namespace Employees 65 | /// (defvaluetype EmployeeNumber int) 66 | /// (defcommand ChangeTelephoneNumber (string TelephoneNumber))) 67 | /// 68 | ///(namespace Clients 69 | /// (defvaluetype ClientId) 70 | /// (defapplicationservice ImportService 71 | /// (defcommand ImportClient (int ClientId, string Name)))) 72 | /// 73 | ///(namespace TestCases.Defvaluetype 74 | /// (defvaluetype InvoiceNumber) 75 | /// (defvaluetype Amount decimal) 76 | /// (defvaluetype LineItemNumber (int Value)) 77 | /// (defvaluetype Name (string FirstName, string LastName)) 78 | /// (defvaluetype SourceMetadata (string Sour [rest of string was truncated]";. 79 | /// 80 | internal static string DieselCompilerIntegrationTestCase { 81 | get { 82 | return ResourceManager.GetString("DieselCompilerIntegrationTestCase", resourceCulture); 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Test/CodeExamples.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | examples\dieselcompilerintegrationtestcase.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 123 | 124 | -------------------------------------------------------------------------------- /Test/CodeGeneration/EqualityMethodsGeneratorTest.cs: -------------------------------------------------------------------------------- 1 | using Diesel.CodeGeneration; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | using NUnit.Framework; 5 | 6 | namespace Test.Diesel.CodeGeneration 7 | { 8 | [TestFixture] 9 | public class EqualityMethodsGeneratorTest 10 | { 11 | 12 | [Test] 13 | public void ComparePropertyValueEqualityExpression_StringReferenceType_ShouldGenerateExpression() 14 | { 15 | var actual = EqualityMethodsGenerator.ComparePropertyValueEqualityExpression( 16 | new PropertyDeclaration("Text", new StringReferenceType()), "other"); 17 | Assert.That(actual, Is.Not.Null); 18 | } 19 | 20 | [Test] 21 | public void ComparePropertyValueEqualityExpression_SimpleType_ShouldGenerateExpression() 22 | { 23 | var actual = EqualityMethodsGenerator.ComparePropertyValueEqualityExpression( 24 | new PropertyDeclaration("Value", new SimpleType(typeof(decimal))), "other"); 25 | Assert.That(actual, Is.Not.Null); 26 | } 27 | 28 | [Test] 29 | public void ComparePropertyValueEqualityExpression_NullableSimpleType_ShouldGenerateExpression() 30 | { 31 | var actual = EqualityMethodsGenerator.ComparePropertyValueEqualityExpression( 32 | new PropertyDeclaration("Value", new NullableType(new SimpleType(typeof(decimal)))), "other"); 33 | Assert.That(actual, Is.Not.Null); 34 | } 35 | 36 | [Test] 37 | public void ComparePropertyValueEqualityExpression_NamedDateTime_ShouldGenerateExpression() 38 | { 39 | var actual = EqualityMethodsGenerator.ComparePropertyValueEqualityExpression( 40 | new PropertyDeclaration("Value", new TypeName("System.DateTime")), "other"); 41 | Assert.That(actual, Is.Not.Null); 42 | } 43 | 44 | [Test] 45 | public void ComparePropertyValueEqualityExpression_ArrayType1D_ShouldGenerateExpression() 46 | { 47 | var actual = EqualityMethodsGenerator.ComparePropertyValueEqualityExpression( 48 | new PropertyDeclaration("Value", 49 | new ArrayType(new SimpleType(typeof(decimal)), 50 | new RankSpecifiers(new[] {new RankSpecifier(1)}))), 51 | "other"); 52 | Assert.That(actual, Is.Not.Null); 53 | } 54 | 55 | 56 | } 57 | } -------------------------------------------------------------------------------- /Test/CodeGeneration/MemberTypeMapperTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.CodeGeneration; 3 | using Diesel.Parsing.CSharp; 4 | using Diesel.Transformations; 5 | using NUnit.Framework; 6 | 7 | namespace Test.Diesel.CodeGeneration 8 | { 9 | [TestFixture] 10 | public class MemberTypeMapperTest 11 | { 12 | [Test] 13 | public void MemberType_ForSystemType_ShouldBeSystemTypeMemberType() 14 | { 15 | var actual = MemberTypeMapper.MemberTypeFor( 16 | new NamespaceName("MyNamespace"), 17 | new SimpleType(typeof(int)), 18 | new KnownType[0]); 19 | 20 | Assert.That(actual.FullName, Is.EqualTo(typeof(int).FullName)); 21 | Assert.That(actual.IsValueType, Is.True); 22 | } 23 | 24 | [Test] 25 | public void MemberType_ForNamedType_ShouldBeNamedTypeMemberType() 26 | { 27 | var actual = MemberTypeMapper.MemberTypeFor( 28 | new NamespaceName("MyNamespace"), 29 | new TypeName("Foo.Bar.SomeType"), 30 | new KnownType[0]); 31 | Assert.That(actual.FullName, Is.EqualTo("Foo.Bar.SomeType")); 32 | } 33 | 34 | 35 | [Test] 36 | public void MemberType_ForArrayOfNamedType_ShouldBeArrayOfNamedTypeMemberType() 37 | { 38 | var elementType = new TypeName("Foo.Bar.SomeType"); 39 | var actual = MemberTypeMapper.MemberTypeFor( 40 | new NamespaceName("MyNamespace"), 41 | new ArrayType(elementType, new RankSpecifiers(new[] { new RankSpecifier(1) })), 42 | new KnownType[0]); 43 | Assert.That(actual.FullName, Is.EqualTo("Foo.Bar.SomeType[]")); 44 | } 45 | 46 | [Test] 47 | public void MemberType_ForNamedType_QualifiedKnownValueType_ShouldSetIsValueType() 48 | { 49 | var actual = MemberTypeMapper.MemberTypeFor( 50 | new NamespaceName("MyNamespace"), 51 | new TypeName("Foo.SomeType"), 52 | new[] { new KnownType("Foo.SomeType", true) }); 53 | Assert.That(actual.IsValueType, Is.True); 54 | } 55 | 56 | [Test] 57 | public void MemberType_ForNamedType_UnqualifiedKnownValueType_ShouldSetIsValueType() 58 | { 59 | var actual = MemberTypeMapper.MemberTypeFor( 60 | new NamespaceName("MyNamespace"), 61 | new TypeName("SomeType"), 62 | new[] { new KnownType("MyNamespace.SomeType", true) }); 63 | Assert.That(actual.IsValueType, Is.True); 64 | } 65 | 66 | 67 | [Test] 68 | public void MemberType_ForNamedType_KnownNonValueType_ShouldNotSetIsValueType() 69 | { 70 | var actual = MemberTypeMapper.MemberTypeFor( 71 | new NamespaceName("MyNamespace"), 72 | new TypeName("Foo.SomeType"), 73 | new[] { new KnownType("Foo.SomeType", false) }); 74 | Assert.That(actual.IsValueType, Is.False); 75 | } 76 | 77 | [Test] 78 | public void MemberType_ForNamedType_UnknownNamedType_ShouldAssumeItIsNotAValueType() 79 | { 80 | var actual = MemberTypeMapper.MemberTypeFor( 81 | new NamespaceName("MyNamespace"), 82 | new TypeName("Foo.SomeType"), 83 | new KnownType[] {}); 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Test/CodeGeneration/SystemTypeMapperTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.CodeGeneration; 3 | using Diesel.Parsing.CSharp; 4 | using NUnit.Framework; 5 | 6 | namespace Test.Diesel.CodeGeneration 7 | { 8 | [TestFixture] 9 | public class SystemTypeMapperTest 10 | { 11 | [Test] 12 | public void SystemTypeFor_ArrayTypeOfSimpleTypeUnidimensional_ShouldMapToType() 13 | { 14 | var actual = SystemTypeMapper.SystemTypeFor(new ArrayType(new SimpleType(typeof (double)), 15 | new RankSpecifiers(new[] {new RankSpecifier(1)}))); 16 | Assert.That(actual, Is.EqualTo(typeof (double[]))); 17 | } 18 | 19 | [Test] 20 | public void SystemTypeFor_ArrayTypeOfSimpleTypeRankTwo_ShouldMapToType() 21 | { 22 | var actual = SystemTypeMapper.SystemTypeFor(new ArrayType(new SimpleType(typeof (double)), 23 | new RankSpecifiers(new[] {new RankSpecifier(2)}))); 24 | Assert.That(actual, Is.EqualTo(typeof (double[,]))); 25 | } 26 | 27 | 28 | [Test] 29 | public void SystemTypeFor_ArrayTypeOfSimpleTypeRankOneTwo_ShouldMapToType() 30 | { 31 | var actual = SystemTypeMapper.SystemTypeFor(new ArrayType(new SimpleType(typeof (float)), 32 | new RankSpecifiers(new[] 33 | { 34 | new RankSpecifier(1), 35 | new RankSpecifier(2) 36 | }))); 37 | Assert.That(actual, Is.EqualTo(typeof(float[][,]))); 38 | } 39 | 40 | 41 | [Test] 42 | public void SystemTypeFor_ArrayTypeOfSimpleTypeRankOneTwoThree_ShouldMapToType() 43 | { 44 | var actual = SystemTypeMapper.SystemTypeFor(new ArrayType(new SimpleType(typeof (float)), 45 | new RankSpecifiers(new[] 46 | { 47 | new RankSpecifier(1), 48 | new RankSpecifier(2), 49 | new RankSpecifier(3) 50 | }))); 51 | Assert.That(actual, Is.EqualTo(typeof(float[][,][,,]))); 52 | } 53 | 54 | 55 | [Test] 56 | public void SystemTypeFor_NullableTypeOfSimpleType_ShouldMapToType() 57 | { 58 | var actual = SystemTypeMapper.SystemTypeFor(new NullableType(new SimpleType(typeof (decimal)))); 59 | Assert.That(actual, Is.EqualTo(typeof (decimal?))); 60 | } 61 | 62 | [Test] 63 | public void SystemTypeFor_SimpleType_ShouldMapToType() 64 | { 65 | var actual = SystemTypeMapper.SystemTypeFor(new SimpleType(typeof(float))); 66 | Assert.That(actual, Is.EqualTo(typeof(float))); 67 | } 68 | 69 | [Test] 70 | public void SystemTypeFor_ReferenceTypeString_ShouldMapToType() 71 | { 72 | var actual = SystemTypeMapper.SystemTypeFor(new StringReferenceType()); 73 | Assert.That(actual, Is.EqualTo(typeof(string))); 74 | } 75 | 76 | [Test] 77 | public void SystemTypeFor_NamedTypeFromSystemNamespaceDateTime_ShouldMapToType() 78 | { 79 | var actual = SystemTypeMapper.SystemTypeFor(new TypeName("DateTime")); 80 | Assert.That(actual, Is.EqualTo(typeof(DateTime))); 81 | } 82 | 83 | [Test] 84 | public void SystemTypeFor_NamedTypeFromSystemNamespaceGuid_ShouldMapToType() 85 | { 86 | var actual = SystemTypeMapper.SystemTypeFor(new TypeName("Guid")); 87 | Assert.That(actual, Is.EqualTo(typeof(Guid))); 88 | } 89 | 90 | [Test] 91 | public void IsSystemType_ForTypeNameTypeNodeKnownType_ShouldBeTrue() 92 | { 93 | var actual = SystemTypeMapper.IsSystemType(new TypeName("Guid")); 94 | Assert.That(actual, Is.True); 95 | } 96 | 97 | [Test] 98 | public void IsSystemType_NonSystemTypes_ShouldBeTrue() 99 | { 100 | var actual = SystemTypeMapper.IsSystemType(new TypeName("Foo.Bar.NotSystemType")); 101 | Assert.That(actual, Is.False); 102 | } 103 | } 104 | } -------------------------------------------------------------------------------- /Test/CodeGeneration/TypeNameMapperTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.CodeGeneration; 3 | using Diesel.Parsing.CSharp; 4 | using NUnit.Framework; 5 | 6 | namespace Test.Diesel.CodeGeneration 7 | { 8 | [TestFixture] 9 | public class TypeNameMapperTest 10 | { 11 | [Test] 12 | public void TypeNameForArray_ArrayTypeOfSimpleTypeUnidimensional_ShouldMapToType() 13 | { 14 | var actual = TypeNameMapper.TypeNameForArray(typeof (double).FullName, 15 | new RankSpecifiers(new[] {new RankSpecifier(1)})); 16 | var correspondingType = Type.GetType(actual); 17 | Assert.That(correspondingType, Is.EqualTo(typeof(double[]))); 18 | } 19 | 20 | [Test] 21 | public void TypeNameForArray_ArrayTypeOfSimpleTypeRankTwo_ShouldMapToType() 22 | { 23 | var actual = TypeNameMapper.TypeNameForArray(typeof (double).FullName, 24 | new RankSpecifiers(new[] {new RankSpecifier(2)})); 25 | var correspondingType = Type.GetType(actual); 26 | Assert.That(correspondingType, Is.EqualTo(typeof(double[,]))); 27 | } 28 | 29 | 30 | [Test] 31 | public void TypeNameForArray_ArrayTypeOfSimpleTypeRankOneTwo_ShouldMapToType() 32 | { 33 | var actual = TypeNameMapper.TypeNameForArray(typeof (float).FullName, 34 | new RankSpecifiers(new[] 35 | { 36 | new RankSpecifier(1), 37 | new RankSpecifier(2) 38 | })); 39 | var correspondingType = Type.GetType(actual); 40 | Assert.That(correspondingType, Is.EqualTo(typeof(float[][,]))); 41 | } 42 | 43 | 44 | [Test] 45 | public void TypeNameForArray_ArrayTypeOfSimpleTypeRankOneTwoThree_ShouldMapToType() 46 | { 47 | var actual = TypeNameMapper.TypeNameForArray(typeof(float).FullName, 48 | new RankSpecifiers(new[] 49 | { 50 | new RankSpecifier(1), 51 | new RankSpecifier(2), 52 | new RankSpecifier(3) 53 | })); 54 | var correspondingType = Type.GetType(actual); 55 | Assert.That(correspondingType, Is.EqualTo(typeof (float[][,][,,]))); 56 | } 57 | 58 | [Test] 59 | public void TypeNameForNullable_NamedType_ShouldMapToType() 60 | { 61 | var actual = TypeNameMapper.TypeNameForNullableType(typeof(int).FullName); 62 | var actualCorrespondingType = Type.GetType(actual); 63 | var expectedCorrespondingType = typeof (Nullable); 64 | Assert.That(actualCorrespondingType, Is.EqualTo(expectedCorrespondingType)); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /Test/CodeGeneration/ValueObjectSpecificationTest.cs: -------------------------------------------------------------------------------- 1 | using Diesel.CodeGeneration; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | using NUnit.Framework; 5 | using Test.Diesel.ObjectMothers; 6 | 7 | namespace Test.Diesel.CodeGeneration 8 | { 9 | [TestFixture] 10 | public class ValueObjectSpecificationTest 11 | { 12 | 13 | [Test] 14 | public void CreateClass_WithBaseTypes_ShouldSetBaseTypes() 15 | { 16 | var ns = new NamespaceName("Foo"); 17 | var properties = PropertyDeclarationObjectMother.FirstLastStringPropertyDeclarations(); 18 | var baseTypes = BaseTypesObjectMother.CreateDieselTestingCommand(); 19 | 20 | var actual = ValueObjectSpecification.CreateClass(ns, "SomeClass", properties, baseTypes, false, false); 21 | 22 | Assert.That(actual.BaseTypes, Is.EqualTo(baseTypes)); 23 | } 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /Test/Examples/DieselCompilerIntegrationTestCase.txt: -------------------------------------------------------------------------------- 1 | (defconventions 2 | :domainevents {:inherit [Test.Diesel.IDomainEvent]} 3 | :commands {:inherit [Test.Diesel.ICommand]}) 4 | 5 | (namespace Employees 6 | (defvaluetype EmployeeNumber int) 7 | (defcommand ChangeTelephoneNumber (string TelephoneNumber))) 8 | 9 | (namespace Clients 10 | (defvaluetype ClientId) 11 | (defapplicationservice ImportService 12 | (defcommand ImportClient (int ClientId, string Name)))) 13 | 14 | (namespace TestCases.PropertyTypeDeclarations 15 | (defcommand PrintInt (int Value)) 16 | (defcommand PrintNullable (float? Value)) 17 | (defcommand PrintArraySimple (int[] Value)) 18 | (defcommand PrintNullableSimple (decimal? Value)) 19 | (defcommand PrintString (string Value)) 20 | (defcommand PrintNamedTypeQualifiedDateTime (System.DateTime Value)) 21 | (defcommand PrintNamedTypeQualifiedGuid (System.Guid Value)) 22 | (defcommand PrintNamedTypeUnqualifiedGuid (Guid Value)) 23 | (defcommand PrintNamedTypeUnqualifiedDecimal (Decimal Value)) 24 | (defcommand PrintNullableNamedTypes (Guid? CorrelationId, System.DateTime? EndDate)) 25 | (defcommand PrintMulti (string Text, int? NullableNumber, string[] SingleDimArray, decimal Decimal, DateTime When))) 26 | 27 | 28 | (namespace TestCases.Defvaluetype 29 | (defvaluetype InvoiceNumber) 30 | (defvaluetype Amount decimal) 31 | (defvaluetype LineItemNumber (int Value)) 32 | (defvaluetype Name (string FirstName, string LastName)) 33 | (defvaluetype SourceMetadata (string Source, int? SourceId)) 34 | (defvaluetype RoleCollection (string[] Roles))) 35 | 36 | 37 | (namespace TestCases.Defcommand 38 | (defcommand PrintString (string Name)) 39 | (defcommand PrintNullable (int? Value)) 40 | (defcommand PrintMultiple (string First, string Last)) 41 | (defcommand PrintDateTime (DateTime OccurredOn)) 42 | (defcommand PrintGuid (Guid SourceId)) 43 | (defcommand PrintArrays (string[] Names, int[] Numbers, Guid[] Guids, DateTime[] Timestamps))) 44 | 45 | (namespace TestCases.Defapplicationservice 46 | (defapplicationservice ImportApplicationService 47 | (defcommand ImportApplicationServiceCommand (Guid Id, string Name)))) 48 | 49 | (namespace TestCases.Defdomainevent 50 | (defdomainevent PaymentReceived (Guid Id, Decimal Amount, String Currency))) 51 | 52 | 53 | (namespace TestCases.Defdto 54 | (defdto EmployeeName (string First, string Last))) 55 | 56 | 57 | (namespace TestCases.Defenum 58 | (defenum State [On Off]) 59 | (defenum StateWithOptionalDelimiter [On, Off])) 60 | 61 | 62 | ; Comment before namespace 63 | (namespace TestCases.Comments 64 | ;; Comment in namespace 65 | (defvaluetype CommentId) 66 | (defapplicationservice CommentService 67 | ; Comment before commands 68 | (defcommand ImportComment (int CommentId, string Name)) 69 | ;; Comment after 70 | ;; Multiple comments after 71 | )) 72 | 73 | 74 | ;; We should be able to add DTOs (objects and enums) to DTOs, Commands and Events 75 | (namespace TestCases.NestedDtos 76 | (defenum Role [Employee Contractor]) 77 | (defdto PersonName (string First, string Last)) 78 | (defdto DtoNestedEnum (Guid Id, Role Role)) 79 | (defdto DtoNestedDto (Guid Id, PersonName Name)) 80 | (defdto DtoNestedNullableEnum (Guid Id, Role? Role)) 81 | (defcommand ImportPersonNestedEnum (string Name, Role Role)) 82 | (defdomainevent PersonImportedNestedEnum (Guid Id, string Name, Role Role)) 83 | (defcommand ImportPersonNestedDto (PersonName Name, Role Role)) 84 | (defdomainevent PersonImportedNestedDto (Guid Id, PersonName Name, Role Role))) 85 | -------------------------------------------------------------------------------- /Test/Generated/Example.dsl: -------------------------------------------------------------------------------- 1 | (defconventions 2 | :commands {:inherit [Test.Diesel.ICommand]} 3 | :domainevents {:inherit [Test.Diesel.IDomainEvent]}) 4 | 5 | (namespace Test.Diesel.Generated 6 | 7 | (defvaluetype EmployeeNumber) 8 | (defvaluetype EmailAddress string) 9 | (defvaluetype EmployeeName (string FirstName, string LastName)) 10 | (defvaluetype EmployeeMetadata (string Source, int? SourceId)) 11 | (defvaluetype EmployeeRatings (int EmployeeNumber, int[] Ratings)) 12 | (defvaluetype EmployeeRoles (int EmployeeNumber, string[] Roles)) 13 | 14 | ;; Value types can contain other value types: 15 | (defvaluetype EmployeeInfo (EmployeeNumber Number, EmployeeName Name, EmailAddress Email)) 16 | (defdomainevent EmployeeImported (Guid Id, int EmployeeNumber, string FirstName, string LastName, int? SourceId)) 17 | 18 | (defdto Name (string First, string Last)) 19 | (defenum Gender [Female Male]) 20 | (defdto NamedPerson (Name Name, Gender? Gender)) 21 | 22 | ;; Service 23 | (defapplicationservice ImportService 24 | (defcommand ImportEmployee (Guid CommandId, int EmployeeNumber, string FirstName, string LastName, int? SourceId)) 25 | (defcommand ImportConsultant (string FirstName, string LastName, string Company))) 26 | 27 | ;; Verify that we can use nested DTOs and enums in commands: 28 | (defcommand ImportEmployeeNestedTypes (Guid CommandId, int EmployeeNumber, Name Name, Gender Gender)) 29 | 30 | (defcommand Foo (DateTime? When)) 31 | 32 | ;; Named array members 33 | (defdomainevent DepartmentImported (Guid Id, Name[] Employees))) 34 | 35 | 36 | -------------------------------------------------------------------------------- /Test/Generated/GenerateExamples.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="true" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.IO" #> 4 | <#@ import namespace="System.Linq" #> 5 | <#@ import namespace="System.Text" #> 6 | <#@ import namespace="System.Collections.Generic" #> 7 | <#@ assembly name="EnvDTE" #> 8 | <#@ import namespace="EnvDTE" #> 9 | <#@ assembly name="$(SolutionDir)Diesel\$(OutDir)Diesel.dll" #> 10 | <#@ import namespace="Diesel" #> 11 | <#@ output extension=".cs" #> 12 | <# 13 | var model = this.Host.ResolvePath("Example.dsl"); 14 | var source = File.ReadAllText(model); 15 | var output = DieselCompiler.Compile(source); 16 | #> 17 | <#= output #> -------------------------------------------------------------------------------- /Test/GeneratedCommandNestedTypesTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using Test.Diesel.Generated; 4 | using Test.Diesel.TestHelpers; 5 | 6 | namespace Test.Diesel 7 | { 8 | [TestFixture] 9 | public class GeneratedCommandNestedDtosTest 10 | { 11 | [Test] 12 | public void EqualsAndGetHashCode() 13 | { 14 | var id = Guid.NewGuid(); 15 | const int number = 1; 16 | var name = new Name("Alice", "Crypto"); 17 | const Gender gender = Gender.Female; 18 | 19 | var a = new ImportEmployeeNestedTypes(id, number, name, gender); 20 | var b = new ImportEmployeeNestedTypes(id, number, name, gender); 21 | var c = new ImportEmployeeNestedTypes(id, number, name, gender); 22 | 23 | var otherId = new ImportEmployeeNestedTypes(Guid.NewGuid(), number, name, gender); 24 | var otherNumber = new ImportEmployeeNestedTypes(id, number + 1, name, gender); 25 | var otherNameNull = new ImportEmployeeNestedTypes(id, number, null, gender); 26 | var otherNameFirst = new ImportEmployeeNestedTypes(id, number, new Name("Bob", "Crypto"), gender); 27 | var otherNameLast = new ImportEmployeeNestedTypes(id, number, new Name("Alice", "Newlywed"), gender); 28 | var otherGender = new ImportEmployeeNestedTypes(id, number, name, Gender.Male); 29 | 30 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, otherId, otherNumber, otherNameNull, otherNameFirst, otherNameLast, otherGender); 31 | EqualityTesting.TestEqualityOperators(a, b, c, otherId, otherNumber, otherNameNull, otherNameFirst, otherNameLast, otherGender); 32 | } 33 | 34 | [Test] 35 | public void Instance_WhenSerializedWithDataContractFormatter_ShouldBeSerializable() 36 | { 37 | var instance = CreateInstance(); 38 | var deserialized = SerializationTesting.SerializeDeserializeWithDataContractSerializer(instance); 39 | Assert.That(deserialized, Is.EqualTo(instance)); 40 | } 41 | 42 | [Test] 43 | public void Instance_WhenSerializedWithBinarySerializer_ShouldBeSerializable() 44 | { 45 | var instance = CreateInstance(); 46 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(instance); 47 | Assert.That(deserialized, Is.EqualTo(instance)); 48 | } 49 | 50 | 51 | private static ImportEmployeeNestedTypes CreateInstance() 52 | { 53 | var id = Guid.NewGuid(); 54 | const int number = 1; 55 | var name = new Name("Alice", "Crypto"); 56 | const Gender gender = Gender.Female; 57 | var instance = new ImportEmployeeNestedTypes(id, number, name, gender); 58 | return instance; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Test/GeneratedCommandTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Runtime.Serialization; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using NUnit.Framework; 9 | using Test.Diesel.Generated; 10 | using Test.Diesel.TestHelpers; 11 | 12 | namespace Test.Diesel 13 | { 14 | [TestFixture] 15 | public class GeneratedCommandTest 16 | { 17 | // Generate the class to test and place it in the Generated folder: 18 | // (defcommand ImportEmployee (Guid CommandId, int EmployeeNumber, string FirstName, string LastName, int? SourceId)) 19 | 20 | private static readonly Guid CommandId = Guid.NewGuid(); 21 | private const int EmployeeNumber = 1; 22 | private const string FirstName = "Alice"; 23 | private const string Lastname = "von Lastname"; 24 | private const int SourceId = 100; 25 | 26 | [Test] 27 | public void Constructor_WithAllValues_ShouldSetProperties() 28 | { 29 | var actual = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, SourceId); 30 | 31 | Assert.That(actual.CommandId, Is.EqualTo(CommandId)); 32 | Assert.That(actual.EmployeeNumber, Is.EqualTo(EmployeeNumber)); 33 | Assert.That(actual.FirstName, Is.EqualTo(FirstName)); 34 | Assert.That(actual.LastName, Is.EqualTo(Lastname)); 35 | Assert.That(actual.SourceId, Is.EqualTo(SourceId)); 36 | } 37 | 38 | [Test] 39 | public void EqualsGetHashCodeAndEqualityOperators() 40 | { 41 | var a = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, SourceId); 42 | var b = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, SourceId); 43 | var c = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, SourceId); 44 | 45 | var otherCommandId = new ImportEmployee(Guid.NewGuid(), EmployeeNumber + 1, FirstName, Lastname, SourceId); 46 | var otherEmployeeNumber = new ImportEmployee(CommandId, EmployeeNumber + 1, FirstName, Lastname, SourceId); 47 | var otherFirstName = new ImportEmployee(CommandId, EmployeeNumber, FirstName + "x", Lastname, SourceId); 48 | var otherFirstNameNull = new ImportEmployee(CommandId, EmployeeNumber, null, Lastname, SourceId); 49 | var otherLastName = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname + "x", SourceId); 50 | var otherLastNameNull = new ImportEmployee(CommandId, EmployeeNumber, FirstName, null, SourceId); 51 | var otherSourceId = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, SourceId + 1); 52 | var otherSourceIdNull = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, null); 53 | 54 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, 55 | otherCommandId, 56 | otherEmployeeNumber, otherFirstName, otherFirstNameNull, 57 | otherLastName, otherLastNameNull, 58 | otherSourceId, otherSourceIdNull); 59 | 60 | EqualityTesting.TestEqualityOperators(a, b, c, 61 | otherEmployeeNumber, otherFirstName, otherFirstNameNull, 62 | otherLastName, otherLastNameNull, 63 | otherSourceId, otherSourceIdNull); 64 | } 65 | 66 | [Test] 67 | public void Instance_WhenSerializedWithBinaryFormatter_ShouldBeSerializable() 68 | { 69 | var instance = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, SourceId); 70 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(instance); 71 | Assert.That(deserialized, Is.EqualTo(instance)); 72 | } 73 | 74 | [Test] 75 | public void Instance_WhenSerializedWithBinaryFormatterNullField_ShouldBeSerializable() 76 | { 77 | var instance = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, null); 78 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(instance); 79 | Assert.That(deserialized, Is.EqualTo(instance)); 80 | } 81 | 82 | [Test] 83 | public void Instance_WhenSerializedWithDataContractFormatter_ShouldBeSerializable() 84 | { 85 | var instance = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, SourceId); 86 | var deserialized = SerializationTesting.SerializeDeserializeWithDataContractSerializer(instance); 87 | Assert.That(deserialized, Is.EqualTo(instance)); 88 | } 89 | 90 | [Test] 91 | public void BackingField_Attributes_ShouldHaveOrderedDataMemberAttributes() 92 | { 93 | var backingFields = typeof (Generated.ImportEmployee).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); 94 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_commandId"), Is.EqualTo(1)); 95 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_employeeNumber"), Is.EqualTo(2)); 96 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_firstName"), Is.EqualTo(3)); 97 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_lastName"), Is.EqualTo(4)); 98 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_sourceId"), Is.EqualTo(5)); 99 | } 100 | 101 | private static object GetDataMemberAttributeOrderValue(FieldInfo[] fields, string fieldName) 102 | { 103 | var employeeNumber = fields.Single(p => p.Name == fieldName); 104 | var dataMemberAttribute = employeeNumber.CustomAttributes 105 | .Single(a => a.AttributeType == typeof (DataMemberAttribute)); 106 | return dataMemberAttribute.NamedArguments.Single(a => a.MemberName == "Order").TypedValue.Value; 107 | } 108 | 109 | [Test] 110 | public void Instance_WhenConventionsDeclareABaseInterface_MustImplementTheInterface() 111 | { 112 | var instance = new ImportEmployee(CommandId, EmployeeNumber, FirstName, Lastname, null); 113 | Assert.That(instance, Is.AssignableTo()); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Test/GeneratedDomainEventTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using System.Runtime.Serialization; 5 | using NUnit.Framework; 6 | using Test.Diesel.Generated; 7 | using Test.Diesel.TestHelpers; 8 | 9 | namespace Test.Diesel 10 | { 11 | [TestFixture] 12 | public class GeneratedDomainEventTest 13 | { 14 | // Generate the class to test and place it in the Generated folder (or use the T4 template) 15 | // (defdomainevent EmployeeImported (Guid Id, int EmployeeNumber, string FirstName, string LastName, int? SourceId)) 16 | 17 | private static readonly Guid Id = Guid.NewGuid(); 18 | private const int EmployeeNumber = 1; 19 | private const string FirstName = "Alice"; 20 | private const string Lastname = "von Lastname"; 21 | private const int SourceId = 100; 22 | 23 | [Test] 24 | public void Constructor_WithAllValues_ShouldSetProperties() 25 | { 26 | var actual = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, SourceId); 27 | 28 | Assert.That(actual.Id, Is.EqualTo(Id)); 29 | Assert.That(actual.EmployeeNumber, Is.EqualTo(EmployeeNumber)); 30 | Assert.That(actual.FirstName, Is.EqualTo(FirstName)); 31 | Assert.That(actual.LastName, Is.EqualTo(Lastname)); 32 | Assert.That(actual.SourceId, Is.EqualTo(SourceId)); 33 | } 34 | 35 | [Test] 36 | public void Type_WithConventionInheritIDomainEvent_ShouldImplementIDomainEventInterface() 37 | { 38 | Assert.That(typeof (IDomainEvent).IsAssignableFrom(typeof (EmployeeImported))); 39 | } 40 | 41 | [Test] 42 | public void Type_ShouldImplementIEquatableInterface() 43 | { 44 | Assert.That(typeof(IEquatable).IsAssignableFrom(typeof(EmployeeImported))); 45 | } 46 | 47 | [Test] 48 | public void EqualsGetHashCodeAndEqualityOperators() 49 | { 50 | var a = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, SourceId); 51 | var b = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, SourceId); 52 | var c = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, SourceId); 53 | 54 | var otherCommandId = new EmployeeImported(Guid.NewGuid(), EmployeeNumber + 1, FirstName, Lastname, SourceId); 55 | var otherEmployeeNumber = new EmployeeImported(Id, EmployeeNumber + 1, FirstName, Lastname, SourceId); 56 | var otherFirstName = new EmployeeImported(Id, EmployeeNumber, FirstName + "x", Lastname, SourceId); 57 | var otherFirstNameNull = new EmployeeImported(Id, EmployeeNumber, null, Lastname, SourceId); 58 | var otherLastName = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname + "x", SourceId); 59 | var otherLastNameNull = new EmployeeImported(Id, EmployeeNumber, FirstName, null, SourceId); 60 | var otherSourceId = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, SourceId + 1); 61 | var otherSourceIdNull = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, null); 62 | 63 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, 64 | otherCommandId, 65 | otherEmployeeNumber, otherFirstName, otherFirstNameNull, 66 | otherLastName, otherLastNameNull, 67 | otherSourceId, otherSourceIdNull); 68 | 69 | EqualityTesting.TestEqualityOperators(a, b, c, 70 | otherEmployeeNumber, otherFirstName, otherFirstNameNull, 71 | otherLastName, otherLastNameNull, 72 | otherSourceId, otherSourceIdNull); 73 | } 74 | 75 | [Test] 76 | public void Instance_WhenSerializedWithBinaryFormatter_ShouldBeSerializable() 77 | { 78 | var instance = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, SourceId); 79 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(instance); 80 | Assert.That(deserialized, Is.EqualTo(instance)); 81 | } 82 | 83 | [Test] 84 | public void Instance_WhenSerializedWithBinaryFormatterNullField_ShouldBeSerializable() 85 | { 86 | var instance = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, null); 87 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(instance); 88 | Assert.That(deserialized, Is.EqualTo(instance)); 89 | } 90 | 91 | [Test] 92 | public void Instance_WhenSerializedWithDataContractFormatter_ShouldBeSerializable() 93 | { 94 | var instance = new EmployeeImported(Id, EmployeeNumber, FirstName, Lastname, SourceId); 95 | var deserialized = SerializationTesting.SerializeDeserializeWithDataContractSerializer(instance); 96 | Assert.That(deserialized, Is.EqualTo(instance)); 97 | } 98 | 99 | [Test] 100 | public void BackingField_Attributes_ShouldHaveOrderedDataMemberAttributes() 101 | { 102 | var backingFields = typeof (Generated.EmployeeImported).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); 103 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_id"), Is.EqualTo(1)); 104 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_employeeNumber"), Is.EqualTo(2)); 105 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_firstName"), Is.EqualTo(3)); 106 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_lastName"), Is.EqualTo(4)); 107 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_sourceId"), Is.EqualTo(5)); 108 | } 109 | 110 | private static object GetDataMemberAttributeOrderValue(FieldInfo[] fields, string fieldName) 111 | { 112 | var employeeNumber = fields.Single(p => p.Name == fieldName); 113 | var dataMemberAttribute = employeeNumber.CustomAttributes 114 | .Single(a => a.AttributeType == typeof (DataMemberAttribute)); 115 | return dataMemberAttribute.NamedArguments.Single(a => a.MemberName == "Order").TypedValue.Value; 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /Test/GeneratedDomainEventWithArrayTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using Test.Diesel.Generated; 4 | using Test.Diesel.TestHelpers; 5 | 6 | namespace Test.Diesel 7 | { 8 | [TestFixture] 9 | public class GeneratedDomainEventWithArrayTest 10 | { 11 | [Test] 12 | public void EqualsGetHashCodeAndEqualityOperators() 13 | { 14 | var id = Guid.NewGuid(); 15 | var aliceAndBob = new[] 16 | { 17 | new Name("Alice", "Crypto"), 18 | new Name("Bob", "Crypto") 19 | }; 20 | var coryAndDan = new[] 21 | { 22 | new Name("Cory", "Crypto"), 23 | new Name("Dan", "Crypto") 24 | }; 25 | 26 | var a = new DepartmentImported(id, aliceAndBob); 27 | var b = new DepartmentImported(id, aliceAndBob); 28 | var c = new DepartmentImported(id, aliceAndBob); 29 | 30 | var otherNamesSameCount = new DepartmentImported(id, coryAndDan); 31 | var otherNamesDifferentCount = new DepartmentImported(id, new[] {aliceAndBob[0]}); 32 | var otherNamesNull= new DepartmentImported(id, null); 33 | var otherNamesSameCountNullElements = new DepartmentImported(id, new Name[] { null,null }); 34 | 35 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, 36 | otherNamesSameCount, 37 | otherNamesDifferentCount, 38 | otherNamesNull, 39 | otherNamesSameCountNullElements); 40 | 41 | EqualityTesting.TestEqualityOperators(a, b, c, 42 | otherNamesSameCount, 43 | otherNamesDifferentCount, 44 | otherNamesNull, 45 | otherNamesSameCountNullElements); 46 | } 47 | 48 | } 49 | } -------------------------------------------------------------------------------- /Test/GeneratedDtoTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using System.Runtime.Serialization; 5 | using NUnit.Framework; 6 | using Test.Diesel.Generated; 7 | using Test.Diesel.TestHelpers; 8 | 9 | namespace Test.Diesel 10 | { 11 | [TestFixture] 12 | public class GeneratedDtoTest 13 | { 14 | // Generate the class to test and place it in the Generated folder (or use the T4 template) 15 | // (defdto Name (string First, string Last)) 16 | 17 | private const string FirstName = "Alice"; 18 | private const string Lastname = "von Lastname"; 19 | 20 | [Test] 21 | public void Constructor_WithAllValues_ShouldSetProperties() 22 | { 23 | var actual = new Name(FirstName, Lastname); 24 | 25 | Assert.That(actual.First, Is.EqualTo(FirstName)); 26 | Assert.That(actual.Last, Is.EqualTo(Lastname)); 27 | } 28 | 29 | [Test] 30 | public void Type_ShouldImplementIEquatableInterface() 31 | { 32 | Assert.That(typeof(IEquatable).IsAssignableFrom(typeof(EmployeeImported))); 33 | } 34 | 35 | [Test] 36 | public void EqualsGetHashCodeAndEqualityOperators() 37 | { 38 | var a = new Name(FirstName, Lastname); 39 | var b = new Name(FirstName, Lastname); 40 | var c = new Name(FirstName, Lastname); 41 | 42 | var otherFirstName = new Name(FirstName + "x", Lastname); 43 | var otherFirstNameNull = new Name(null, Lastname); 44 | var otherLastName = new Name(FirstName, Lastname + "x"); 45 | var otherLastNameNull = new Name(FirstName, null); 46 | 47 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, 48 | otherFirstName, otherFirstNameNull, 49 | otherLastName, otherLastNameNull); 50 | 51 | EqualityTesting.TestEqualityOperators(a, b, c, 52 | otherFirstName, otherFirstNameNull, 53 | otherLastName, otherLastNameNull); 54 | } 55 | 56 | [Test] 57 | public void Instance_WhenSerializedWithBinaryFormatter_ShouldBeSerializable() 58 | { 59 | var instance = new Name(FirstName, Lastname); 60 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(instance); 61 | Assert.That(deserialized, Is.EqualTo(instance)); 62 | } 63 | 64 | [Test] 65 | public void Instance_WhenSerializedWithBinaryFormatterNullField_ShouldBeSerializable() 66 | { 67 | var instance = new Name(FirstName, Lastname); 68 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(instance); 69 | Assert.That(deserialized, Is.EqualTo(instance)); 70 | } 71 | 72 | [Test] 73 | public void Instance_WhenSerializedWithDataContractFormatter_ShouldBeSerializable() 74 | { 75 | var instance = new Name(FirstName, Lastname); 76 | var deserialized = SerializationTesting.SerializeDeserializeWithDataContractSerializer(instance); 77 | Assert.That(deserialized, Is.EqualTo(instance)); 78 | } 79 | 80 | [Test] 81 | public void BackingField_Attributes_ShouldHaveOrderedDataMemberAttributes() 82 | { 83 | var backingFields = typeof(Generated.Name).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField); 84 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_first"), Is.EqualTo(1)); 85 | Assert.That(GetDataMemberAttributeOrderValue(backingFields, "_last"), Is.EqualTo(2)); 86 | } 87 | 88 | private static object GetDataMemberAttributeOrderValue(FieldInfo[] fields, string fieldName) 89 | { 90 | var employeeNumber = fields.Single(p => p.Name == fieldName); 91 | var dataMemberAttribute = employeeNumber.CustomAttributes 92 | .Single(a => a.AttributeType == typeof (DataMemberAttribute)); 93 | return dataMemberAttribute.NamedArguments.Single(a => a.MemberName == "Order").TypedValue.Value; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /Test/GeneratedDtoWithNullableNonSystemMemberTypeTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using System.Runtime.Serialization; 5 | using NUnit.Framework; 6 | using Test.Diesel.Generated; 7 | using Test.Diesel.TestHelpers; 8 | 9 | namespace Test.Diesel 10 | { 11 | /// 12 | /// Here, we are just interested in checking that user-defined (non-system) value types can be 13 | /// used as members on the generated contracts. 14 | /// 15 | [TestFixture] 16 | public class GeneratedDtoWithNullableNonSystemMemberTypeTest 17 | { 18 | [Test] 19 | public void EqualsGetHashCodeAndEqualityOperators() 20 | { 21 | var alice = new Name("Alice", "Crypto"); 22 | var bob = new Name("Bob", "Crypto"); 23 | 24 | var a = new NamedPerson(alice, Gender.Female); 25 | var b = new NamedPerson(alice, Gender.Female); 26 | var c = new NamedPerson(alice, Gender.Female); 27 | 28 | var otherName = new NamedPerson(bob, Gender.Female); 29 | var otherGenderNull = new NamedPerson(alice, null); 30 | var otherGenderMale = new NamedPerson(alice, Gender.Male); 31 | 32 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, 33 | otherName, otherGenderNull, otherGenderMale); 34 | EqualityTesting.TestEqualityOperators(a, b, c, 35 | otherName, otherGenderNull, otherGenderMale); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Test/GeneratedEnumTest.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using NUnit.Framework; 3 | using Test.Diesel.Generated; 4 | using Test.Diesel.TestHelpers; 5 | 6 | namespace Test.Diesel 7 | { 8 | [TestFixture] 9 | public class GeneratedEnumTest 10 | { 11 | [Test] 12 | public void Instance_WhenSerializedWithDataContractFormatter_ShouldBeSerializable() 13 | { 14 | foreach (var instance in System.Enum.GetValues(typeof(Gender)).Cast()) 15 | { 16 | var deserialized = SerializationTesting.SerializeDeserializeWithDataContractSerializer(instance); 17 | Assert.That(deserialized, Is.EqualTo(instance)); 18 | } 19 | } 20 | 21 | [Test] 22 | public void Instance_Values_ShouldBeDistinct() 23 | { 24 | Assert.That(Gender.Female != Gender.Male); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Test/GeneratedGetHashCodeIntegrationTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.CodeDom.Compiler; 3 | using System.Reflection; 4 | using Diesel; 5 | using NUnit.Framework; 6 | 7 | namespace Test.Diesel 8 | { 9 | // Verify that GetHashCode includes model value type fields 10 | // This is not strictly required by its semantics, but 11 | // it verifies that code is generated that uses these fields 12 | // for the GetHashCode calculation. 13 | [TestFixture] 14 | public class GeneratedGetHashCodeIntegrationTest 15 | { 16 | private CompilerResults _compilerResults; 17 | 18 | public object CreateDtoInstance(Guid id, int number, string name, string genderName) 19 | { 20 | Assert.That(_compilerResults, Is.Not.Null); 21 | var genderType = _compilerResults.CompiledAssembly.GetType("Foo.Gender"); 22 | Assert.That(genderType, Is.Not.Null); 23 | object gender = Enum.Parse(genderType, genderName); 24 | Assert.That(gender, Is.Not.Null); 25 | var instance = _compilerResults.CompiledAssembly 26 | .CreateInstance("Foo.ValueObject", false, 27 | BindingFlags.CreateInstance, 28 | null, 29 | new object[] {id, number, name, gender}, 30 | null, null); 31 | return instance; 32 | } 33 | 34 | [TestFixtureSetUp] 35 | public void CompileModel() 36 | { 37 | var dieselSource = "(namespace Foo " + 38 | " (defenum Gender [Female Male]) " + 39 | " (defdto ValueObject (Guid Id, int Number, string Name, Gender Gender)))"; 40 | _compilerResults = Compile(dieselSource); 41 | } 42 | 43 | private static CompilerResults Compile(string dieselSource) 44 | { 45 | var csharpSource = DieselCompiler.Compile(dieselSource); 46 | var csharpCompiler = DieselCompiler.GetCSharpProvider(); 47 | var parameters = new CompilerParameters() 48 | { 49 | GenerateExecutable = false, 50 | GenerateInMemory = true, 51 | IncludeDebugInformation = false, 52 | ReferencedAssemblies = { "System.Runtime.Serialization.dll" } 53 | }; 54 | var result = csharpCompiler.CompileAssemblyFromSource(parameters, csharpSource); 55 | Assert.That(result.Errors, Is.Empty); 56 | return result; 57 | } 58 | 59 | [Test] 60 | public void GetHashCode_OtherValueOfValueTypeField_ShouldChangeHashCode() 61 | { 62 | var id = Guid.NewGuid(); 63 | const int number = 1; 64 | const string name = "Kim Crypto"; 65 | object male = CreateDtoInstance(id, number, name, "Male"); 66 | object female = CreateDtoInstance(id, number, name, "Female"); 67 | 68 | Assert.That(male.GetHashCode() != female.GetHashCode()); 69 | } 70 | 71 | [Test] 72 | public void GetHashCode_OtherValueOfGuidField_ShouldChangeHashCode() 73 | { 74 | const int number = 1; 75 | const string name = "Kim Crypto"; 76 | object a = CreateDtoInstance(Guid.NewGuid(), number, name, "Female"); 77 | object b = CreateDtoInstance(Guid.NewGuid(), number, name, "Female"); 78 | 79 | Assert.That(a.GetHashCode() != b.GetHashCode()); 80 | } 81 | 82 | 83 | [Test] 84 | public void GetHashCode_OtherValueOfIntField_ShouldChangeHashCode() 85 | { 86 | var id = Guid.NewGuid(); 87 | const int number = 1; 88 | const string name = "Kim Crypto"; 89 | var a = CreateDtoInstance(id, number, name, "Female"); 90 | var b = CreateDtoInstance(id, number + 1, name, "Female"); 91 | 92 | Assert.That(a.GetHashCode() != b.GetHashCode()); 93 | } 94 | 95 | } 96 | } -------------------------------------------------------------------------------- /Test/GeneratedValueTypeMultiplePropertiesTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Test.Diesel.TestHelpers; 3 | 4 | namespace Test.Diesel 5 | { 6 | [TestFixture] 7 | public class GeneratedValueTypeMultiplePropertiesTest 8 | { 9 | // Generate the class to test and place it in the Generated folder: 10 | // (defvaluetype EmployeeName (string FirstName, string LastName)) 11 | 12 | [Test] 13 | public void Constructor_WithAllValues_ShouldSetProperties() 14 | { 15 | const string first = "Joe"; 16 | const string last = "User"; 17 | var actual = new Generated.EmployeeName(first, last); 18 | Assert.That(actual.FirstName, Is.EqualTo(first)); 19 | Assert.That(actual.LastName, Is.EqualTo(last)); 20 | } 21 | 22 | [Test] 23 | public void EqualsGetHashCodeAndEqualityOperators() 24 | { 25 | const string first = "Joe"; 26 | const string last = "User"; 27 | 28 | var a = new Generated.EmployeeName(first, last); 29 | var b = new Generated.EmployeeName(first, last); 30 | var c = new Generated.EmployeeName(first, last); 31 | 32 | var otherFirstName = new Generated.EmployeeName(first + "x", last); 33 | var otherLastName = new Generated.EmployeeName(first, "von " + last); 34 | 35 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, otherFirstName, otherLastName); 36 | EqualityTesting.TestEqualityOperators(a, b, c, otherFirstName, otherLastName); 37 | } 38 | 39 | [Test] 40 | public void Instance_WhenSerializedWithBinaryFormatter_ShouldBeSerializable() 41 | { 42 | const int number = 1; 43 | var actual = new Generated.EmployeeNumber(number); 44 | 45 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(actual); 46 | 47 | Assert.That(deserialized, Is.EqualTo(actual)); 48 | Assert.That(actual.Value, Is.EqualTo(number)); 49 | } 50 | 51 | [Test] 52 | public void ToString_MultipleProperties_ShouldReturnAllPropertiesToStringed() 53 | { 54 | const string first = "Joe"; 55 | const string last = "User"; 56 | var actual = new Generated.EmployeeName(first, last).ToString(); 57 | Assert.That(actual, Is.EqualTo("Joe User")); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Test/GeneratedValueTypeNestedValueTypesTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Test.Diesel.Generated; 3 | 4 | namespace Test.Diesel 5 | { 6 | [TestFixture] 7 | public class GeneratedValueTypeNestedValueTypesTest 8 | { 9 | [Test] 10 | public void EqualsAndGetHashCodeAndEqualityOperators() 11 | { 12 | var alice = new EmployeeName("Alice", "Crypto"); 13 | var bob = new EmployeeName("Bob", "Crypto"); 14 | 15 | var aliceNumber = new EmployeeNumber(1); 16 | var bobNumber = new EmployeeNumber(2); 17 | 18 | var aliceEmail = new EmailAddress("alice@crypto.org"); 19 | var bobEmail = new EmailAddress("bob@crypto.org"); 20 | 21 | var a = new EmployeeInfo(aliceNumber, alice, aliceEmail); 22 | var b = new EmployeeInfo(aliceNumber, alice, aliceEmail); 23 | var c = new EmployeeInfo(aliceNumber, alice, aliceEmail); 24 | 25 | var otherNumber = new EmployeeInfo(bobNumber, alice, aliceEmail); 26 | var otherName = new EmployeeInfo(aliceNumber, bob, aliceEmail); 27 | var otherEmail = new EmployeeInfo(aliceNumber, alice, bobEmail); 28 | 29 | TestHelpers.EqualityTesting.TestEqualsAndGetHashCode(a,b,c, otherNumber, otherName, otherEmail); 30 | TestHelpers.EqualityTesting.TestEqualityOperators(a, b, c, otherNumber, otherName, otherEmail); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Test/GeneratedValueTypeTest.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Linq; 3 | using System.Reflection; 4 | using System.Runtime.Serialization; 5 | using NUnit.Framework; 6 | using Test.Diesel.TestHelpers; 7 | 8 | namespace Test.Diesel 9 | { 10 | [TestFixture] 11 | public class GeneratedValueTypeTest 12 | { 13 | // Generate the class to test and place it in the Generated folder: 14 | // (defvaluetype EmployeeNumber int) 15 | 16 | [Test] 17 | public void Constructor_WithAllValues_ShouldSetProperties() 18 | { 19 | const int number = 1; 20 | var actual = new Generated.EmployeeNumber(number); 21 | Assert.That(actual.Value, Is.EqualTo(number)); 22 | } 23 | 24 | [Test] 25 | public void EqualsGetHashCodeAndEqualityOperators() 26 | { 27 | const int number = 1; 28 | 29 | var a = new Generated.EmployeeNumber(number); 30 | var b = new Generated.EmployeeNumber(number); 31 | var c = new Generated.EmployeeNumber(number); 32 | 33 | var otherEmployeeNumber = new Generated.EmployeeNumber(number + 1); 34 | 35 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, otherEmployeeNumber); 36 | 37 | EqualityTesting.TestEqualityOperators(a, b, c, otherEmployeeNumber); 38 | } 39 | 40 | [Test] 41 | public void Instance_WhenSerializedWithBinaryFormatter_ShouldBeSerializable() 42 | { 43 | const int number = 1; 44 | var actual = new Generated.EmployeeNumber(number); 45 | 46 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(actual); 47 | 48 | Assert.That(deserialized, Is.EqualTo(actual)); 49 | Assert.That(actual.Value, Is.EqualTo(number)); 50 | } 51 | 52 | 53 | [Test] 54 | public void Instance_WithSingleField_ShouldHaveDebuggerDisplayAttribute() 55 | { 56 | var actual = typeof (Generated.EmployeeNumber).GetCustomAttribute(); 57 | Assert.That(actual, Is.Not.Null); 58 | Assert.That(actual.Value, Is.EqualTo("{Value}")); 59 | } 60 | 61 | [Test] 62 | public void Instance_WithSingleField_ShouldHaveToString() 63 | { 64 | var actual = typeof(Generated.EmployeeNumber).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public); 65 | Assert.That(actual, Is.Not.Null); 66 | } 67 | 68 | 69 | [Test] 70 | public void ToString_WithSingleField_ShouldReturnValueAsString() 71 | { 72 | const int number = 1; 73 | var actual = new Generated.EmployeeNumber(number).ToString(); 74 | Assert.That(actual, Is.EqualTo("1")); 75 | } 76 | 77 | } 78 | } -------------------------------------------------------------------------------- /Test/GeneratedValueTypeWithArrayTest.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Test.Diesel.TestHelpers; 3 | 4 | namespace Test.Diesel 5 | { 6 | [TestFixture] 7 | public class GeneratedValueTypeWithArrayTest 8 | { 9 | // Generate the class to test and place it in the Generated folder: 10 | // (defvaluetype EmployeeRatings (int EmployeeNumber, int[] Ratings)) 11 | 12 | [Test] 13 | public void Constructor_WithAllValues_ShouldSetProperties() 14 | { 15 | const int number = 1; 16 | var ratings = new [] {1, 2}; 17 | var actual = new Generated.EmployeeRatings(number, ratings); 18 | Assert.That(actual.EmployeeNumber, Is.EqualTo(number)); 19 | Assert.That(actual.Ratings, Is.EqualTo(ratings)); 20 | } 21 | 22 | [Test] 23 | public void EqualsGetHashCodeAndEqualityOperators_TypeWithValueTypeArray_ShouldWork() 24 | { 25 | const int number = 1; 26 | var ratings = new[] { 1, 2 }; 27 | 28 | var a = new Generated.EmployeeRatings(number, ratings); 29 | var b = new Generated.EmployeeRatings(number, new[] {1, 2}); 30 | var c = new Generated.EmployeeRatings(number, new[] {1, 2}); 31 | 32 | var otherEmployeeNumber = new Generated.EmployeeRatings(number + 1, ratings); 33 | var otherRatingsLength = new Generated.EmployeeRatings(number, new[] {1}); 34 | var otherRatingsValues = new Generated.EmployeeRatings(number, new[] {1,3}); 35 | var otherRatingsOrder = new Generated.EmployeeRatings(number, new[] { 2, 1 }); 36 | var otherRatingsNull = new Generated.EmployeeRatings(number, null); 37 | 38 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, otherEmployeeNumber, otherRatingsLength, otherRatingsValues, otherRatingsOrder, otherRatingsNull); 39 | EqualityTesting.TestEqualityOperators(a, b, c, otherEmployeeNumber, otherRatingsLength, otherRatingsValues, otherRatingsOrder, otherRatingsNull); 40 | } 41 | 42 | 43 | [Test] 44 | public void EqualsGetHashCodeAndEqualityOperators_TypeWithStringReferenceTypeArray_ShouldWork() 45 | { 46 | const int number = 1; 47 | var roles = new[] { "tester", "developer" }; 48 | 49 | var a = new Generated.EmployeeRoles(number, roles); 50 | var b = new Generated.EmployeeRoles(number, new[] { "tester", "developer" }); 51 | var c = new Generated.EmployeeRoles(number, roles); 52 | 53 | var otherEmployeeNumber = new Generated.EmployeeRoles(number + 1, roles); 54 | var otherRolesLength = new Generated.EmployeeRoles(number, new[] { "tester" }); 55 | var otherRolesValues = new Generated.EmployeeRoles(number, new[] { "tester", "analyst" }); 56 | 57 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, otherEmployeeNumber, otherRolesLength, otherRolesValues); 58 | EqualityTesting.TestEqualityOperators(a, b, c, otherEmployeeNumber, otherRolesLength, otherRolesValues); 59 | } 60 | 61 | 62 | [Test] 63 | public void Instance_WhenSerializedWithBinaryFormatter_ShouldBeSerializable() 64 | { 65 | const int number = 1; 66 | var roles = new[] { "tester", "developer" }; 67 | var actual = new Generated.EmployeeRoles(number, roles); 68 | 69 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(actual); 70 | 71 | Assert.That(deserialized, Is.EqualTo(actual)); 72 | Assert.That(actual.EmployeeNumber, Is.EqualTo(number)); 73 | Assert.That(actual.Roles, Is.EquivalentTo(roles)); 74 | } 75 | 76 | 77 | [Test, Ignore("Not supported yet - the generator just prints System.String[] when ToString'ing the array")] 78 | public void ToString_ArrayNotNull_ShouldFormatValues() 79 | { 80 | const int number = 1; 81 | var roles = new[] { "tester", "developer" }; 82 | var instance = new Generated.EmployeeRoles(number, roles); 83 | 84 | var actual = instance.ToString(); 85 | 86 | // TODO: update generator to pretty-print array values 87 | Assert.That(actual, Is.EqualTo("1 [tester developer]")); 88 | } 89 | 90 | } 91 | } -------------------------------------------------------------------------------- /Test/GeneratedValueTypeWithNullableProperty.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using Test.Diesel.TestHelpers; 3 | 4 | namespace Test.Diesel 5 | { 6 | [TestFixture] 7 | public class GeneratedValueTypeWithNullableProperty 8 | { 9 | // Generate the class to test and place it in the Generated folder: 10 | // (defvaluetype EmployeeMetadata (string Source, int? SourceId)) 11 | 12 | const string Source = "Legacy system"; 13 | const int SourceId = 1; 14 | 15 | [Test] 16 | public void Constructor_WithAllValues_ShouldSetProperties() 17 | { 18 | var actual = new Generated.EmployeeMetadata(Source, SourceId); 19 | Assert.That(actual.Source, Is.EqualTo(Source)); 20 | Assert.That(actual.SourceId, Is.EqualTo(SourceId)); 21 | } 22 | 23 | [Test] 24 | public void EqualsGetHashCodeAndEqualityOperators() 25 | { 26 | var a = new Generated.EmployeeMetadata(Source, SourceId); 27 | var b = new Generated.EmployeeMetadata(Source, SourceId); 28 | var c = new Generated.EmployeeMetadata(Source, SourceId); 29 | 30 | var otherSource = new Generated.EmployeeMetadata(Source + "x", SourceId); 31 | var otherSourceId = new Generated.EmployeeMetadata(Source, SourceId + 1); 32 | var otherSourceIdNull = new Generated.EmployeeMetadata(Source, null); 33 | 34 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, otherSource, otherSourceId, otherSourceIdNull); 35 | EqualityTesting.TestEqualityOperators(a, b, c, otherSource, otherSourceId, otherSourceIdNull); 36 | } 37 | 38 | [Test] 39 | public void Instance_WhenSerializedWithBinaryFormatter_ShouldBeSerializable() 40 | { 41 | var actual = new Generated.EmployeeMetadata(Source, SourceId); 42 | 43 | var deserialized = SerializationTesting.SerializeDeserializeWithBinaryFormatter(actual); 44 | 45 | Assert.That(deserialized, Is.EqualTo(actual)); 46 | } 47 | 48 | [Test] 49 | public void ToString_NotNull_ShouldFormatValue() 50 | { 51 | var actual = new Generated.EmployeeMetadata("Source", 1).ToString(); 52 | Assert.That(actual, Is.EqualTo("Source 1")); 53 | } 54 | 55 | [Test] 56 | public void ToString_NullableFieldIsNull_ShouldFormatNullValueAsEmpty() 57 | { 58 | var actual = new Generated.EmployeeMetadata("Source", null).ToString(); 59 | Assert.That(actual, Is.EqualTo("Source ")); 60 | } 61 | 62 | } 63 | } -------------------------------------------------------------------------------- /Test/ICommand.cs: -------------------------------------------------------------------------------- 1 | namespace Test.Diesel 2 | { 3 | public interface ICommand 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /Test/IDomainEvent.cs: -------------------------------------------------------------------------------- 1 | namespace Test.Diesel 2 | { 3 | public interface IDomainEvent 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Test/ObjectMothers/BaseTypesObjectMother.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing; 2 | using Diesel.Parsing.CSharp; 3 | 4 | namespace Test.Diesel.ObjectMothers 5 | { 6 | public static class BaseTypesObjectMother 7 | { 8 | public static BaseTypes CreateDieselTestingCommand() 9 | { 10 | return new BaseTypes(new[] {new TypeName("Diesel.Testing.Command") }); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Test/ObjectMothers/CommandDeclarationObjectMother.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | 5 | namespace Test.Diesel.ObjectMothers 6 | { 7 | /// 8 | /// Responsible for creating semantically valid instances for testing. 9 | /// 10 | public class CommandDeclarationObjectMother 11 | { 12 | public static CommandDeclaration CreateImportEmployee() 13 | { 14 | return new CommandDeclaration("ImportEmployee", new[] 15 | { 16 | new PropertyDeclaration("EmployeeNumber", new SimpleType(typeof (Int32))), 17 | new PropertyDeclaration("FirstName", new StringReferenceType()), 18 | new PropertyDeclaration("LastName", new StringReferenceType()) 19 | }); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Test/ObjectMothers/DomainEventDeclarationObjectMother.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | 5 | namespace Test.Diesel.ObjectMothers 6 | { 7 | /// 8 | /// Responsible for creating semantically valid instances for testing. 9 | /// 10 | public static class DomainEventDeclarationObjectMother 11 | { 12 | public static DomainEventDeclaration CreateEmployeeImported() 13 | { 14 | return new DomainEventDeclaration( 15 | "EmployeeImported", 16 | new[] 17 | { 18 | new PropertyDeclaration("Id", 19 | new TypeName("System.Guid")), 20 | new PropertyDeclaration("EmployeeNumber", 21 | new SimpleType(typeof (Int32))), 22 | new PropertyDeclaration("FirstName", new StringReferenceType()), 23 | new PropertyDeclaration("LastName", new StringReferenceType()) 24 | }); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Test/ObjectMothers/DtoDeclarationObjectMother.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing; 2 | using Diesel.Parsing.CSharp; 3 | 4 | namespace Test.Diesel.ObjectMothers 5 | { 6 | /// 7 | /// Responsible for creating semantically valid instances for testing. 8 | /// 9 | public static class DtoDeclarationObjectMother 10 | { 11 | public static DtoDeclaration CreateName() 12 | { 13 | return new DtoDeclaration("Name", 14 | new[] 15 | { 16 | new PropertyDeclaration("First", new StringReferenceType()), 17 | new PropertyDeclaration("Last", new StringReferenceType()), 18 | } 19 | ); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Test/ObjectMothers/EnumDeclarationObjectMother.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing; 2 | 3 | namespace Test.Diesel.ObjectMothers 4 | { 5 | /// 6 | /// Responsible for creating semantically valid instances for testing. 7 | /// 8 | public static class EnumDeclarationObjectMother 9 | { 10 | public static EnumDeclaration CreateRoles() 11 | { 12 | return new EnumDeclaration("Roles", new[] {"Tester", "Developer"}); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Test/ObjectMothers/PropertyDeclarationObjectMother.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing; 2 | using Diesel.Parsing.CSharp; 3 | 4 | namespace Test.Diesel.ObjectMothers 5 | { 6 | public static class PropertyDeclarationObjectMother 7 | { 8 | public static PropertyDeclaration[] FirstLastStringPropertyDeclarations() 9 | { 10 | return new[] 11 | { 12 | new PropertyDeclaration("First", new StringReferenceType()), 13 | new PropertyDeclaration("Last", new StringReferenceType()), 14 | }; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Test/ObjectMothers/ValueTypeDeclarationObjectMother.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | 5 | namespace Test.Diesel.ObjectMothers 6 | { 7 | /// 8 | /// Responsible for creating semantically valid instances for testing. 9 | /// 10 | public static class ValueTypeDeclarationObjectMother 11 | { 12 | public static ValueTypeDeclaration CreateEmployeeNumber() 13 | { 14 | return new ValueTypeDeclaration( 15 | "EmployeeNumber", 16 | new[] 17 | { 18 | new PropertyDeclaration("Value", new SimpleType(typeof (Int32))), 19 | }); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Test/Parsing/BaseTypesTest.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing; 2 | using Diesel.Parsing.CSharp; 3 | using NUnit.Framework; 4 | using Test.Diesel.TestHelpers; 5 | 6 | namespace Test.Diesel.Parsing 7 | { 8 | [TestFixture] 9 | public class BaseTypesTest 10 | { 11 | [Test] 12 | public void ApplyOverrides_Null_ShouldReturnSameInstance() 13 | { 14 | var instance = new BaseTypes(new TypeName[0]); 15 | var actual = instance.ApplyOverridesFrom(null); 16 | Assert.That(actual, Is.SameAs(instance)); 17 | } 18 | 19 | [Test] 20 | public void ApplyOverrides_DifferentBaseTypes_ShouldReturnInstanceWithTheOtherBaseTypes() 21 | { 22 | var typeName = new TypeName("SomeNamespace.IBaseType"); 23 | var otherTypeName = new TypeName("SomeNamespace.IOtherBaseType"); 24 | var instance = new BaseTypes(new[] { typeName }); 25 | var other = new BaseTypes(new[] { otherTypeName }); 26 | var actual = instance.ApplyOverridesFrom(other); 27 | 28 | Assert.That(actual.TypeNames, 29 | Is.EquivalentTo(new[] { otherTypeName })); 30 | } 31 | 32 | [Test] 33 | public void EqualityOperations() 34 | { 35 | var typeNameBaseType = new TypeName("SomeNamespace.IBaseType"); 36 | var typeNameOtherBaseType = new TypeName("SomeNamespace.IOtherBaseType"); 37 | 38 | var a = new BaseTypes(new[] { typeNameBaseType }); 39 | var b = new BaseTypes(new[] { typeNameBaseType }); 40 | var c = new BaseTypes(new[] { typeNameBaseType }); 41 | 42 | var otherTypeName = new BaseTypes(new[] { typeNameOtherBaseType }); 43 | var otherTypeNameLength = new BaseTypes(new[] { typeNameBaseType, typeNameOtherBaseType }); 44 | var otherTypeNameNull = new BaseTypes(null); 45 | 46 | EqualityTesting.TestEqualityOperators(a,b,c, otherTypeName, otherTypeNameLength, otherTypeNameNull); 47 | EqualityTesting.TestEqualityOperators(a,b,c, otherTypeName, otherTypeNameLength, otherTypeNameNull); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Test/Parsing/CSharp/ArrayTypeTest.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing; 2 | using Diesel.Parsing.CSharp; 3 | using NUnit.Framework; 4 | 5 | namespace Test.Diesel.Parsing.CSharp 6 | { 7 | [TestFixture] 8 | public class ArrayTypeTest 9 | { 10 | [Test, Ignore("Move Name to Code-gen phase")] 11 | public void Constructor_UnidimensionalQualifiedType_ShouldSetType() 12 | { 13 | var typeName = new TypeName("System.Guid"); 14 | var actual = new ArrayType(typeName, 15 | new RankSpecifiers(new[] { new RankSpecifier(1) })); 16 | Assert.That(actual.Type, Is.EqualTo(typeName)); 17 | } 18 | 19 | [Test, Ignore("Move Name to Code-gen phase")] 20 | public void Constructor_UnidimensionalSimpleType_ShouldSetName() 21 | { 22 | var actual = new ArrayType(new SimpleType(typeof (int)), new RankSpecifiers(new[] {new RankSpecifier(1)})); 23 | // TODO: Assert.That(actual.Name, Is.EqualTo("System.Int32[]")); 24 | } 25 | 26 | [Test, Ignore("Move Name to Code-gen phase")] 27 | public void Constructor_Bidimensional_ShouldSetName() 28 | { 29 | var actual = new ArrayType(new TypeName("System.Guid"), 30 | new RankSpecifiers(new[] {new RankSpecifier(2)})); 31 | // TODO: Assert.That(actual.Name, Is.EqualTo("System.Guid[,]")); 32 | } 33 | 34 | [Test, Ignore("Move Name to Code-gen phase")] 35 | public void Constructor_HigherOrder_ShouldSetName() 36 | { 37 | var actual = new ArrayType(new TypeName("System.Guid"), 38 | new RankSpecifiers(new[] 39 | { 40 | new RankSpecifier(1), 41 | new RankSpecifier(2), 42 | new RankSpecifier(3) 43 | })); 44 | // TODO: Assert.That(actual.Name, Is.EqualTo("System.Int32[][,][,,]")); 45 | } 46 | 47 | 48 | [Test] 49 | public void EqualsAndGetHashCode() 50 | { 51 | var a = new ArrayType(new SimpleType(typeof(int)), new RankSpecifiers(new[] { new RankSpecifier(1) })); 52 | var b = new ArrayType(new SimpleType(typeof(int)), new RankSpecifiers(new[] { new RankSpecifier(1) })); 53 | var c = new ArrayType(new SimpleType(typeof(int)), new RankSpecifiers(new[] { new RankSpecifier(1) })); 54 | 55 | var otherType = new ArrayType(new SimpleType(typeof(decimal)), new RankSpecifiers(new[] { new RankSpecifier(1) })); 56 | var otherDimensions = new ArrayType(new SimpleType(typeof(int)), new RankSpecifiers(new[] { new RankSpecifier(2) })); 57 | var otherRanks = new ArrayType(new SimpleType(typeof(int)), new RankSpecifiers(new[] { new RankSpecifier(1), new RankSpecifier(2) })); 58 | 59 | TestHelpers.EqualityTesting.TestEqualsAndGetHashCode(a,b,c, otherType, otherDimensions, otherRanks); 60 | TestHelpers.EqualityTesting.TestEqualityOperators(a,b,c, otherType, otherDimensions, otherRanks); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Test/Parsing/CSharp/SimpleTypeTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.Parsing.CSharp; 3 | using NUnit.Framework; 4 | 5 | namespace Test.Diesel.Parsing.CSharp 6 | { 7 | [TestFixture] 8 | public class SimpleTypeTest 9 | { 10 | [Test] 11 | public void Constructor_WithType_ShouldSetName() 12 | { 13 | var actual = new SimpleType(typeof(Int32)); 14 | Assert.That(actual.Type, Is.EqualTo(typeof(Int32))); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Test/Parsing/CSharp/TypeNameTest.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing.CSharp; 2 | using NUnit.Framework; 3 | using Test.Diesel.TestHelpers; 4 | 5 | namespace Test.Diesel.Parsing.CSharp 6 | { 7 | [TestFixture] 8 | public class TypeNameTest 9 | { 10 | [Test] 11 | public void EqualityOperations() 12 | { 13 | var a = new TypeName("name"); 14 | var b = new TypeName("name"); 15 | var c = new TypeName("name"); 16 | 17 | var otherName = new TypeName("other name"); 18 | 19 | EqualityTesting.TestEqualsAndGetHashCode(a,b,c, otherName); 20 | EqualityTesting.TestEqualityOperators(a,b,c, otherName); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Test/Parsing/CommandConventionsTest.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing; 2 | using Diesel.Parsing.CSharp; 3 | using NUnit.Framework; 4 | using Test.Diesel.TestHelpers; 5 | 6 | namespace Test.Diesel.Parsing 7 | { 8 | [TestFixture] 9 | public class CommandConventionsTest 10 | { 11 | [Test] 12 | public void EqualityMethods() 13 | { 14 | var baseTypes = new BaseTypes(new[] {new TypeName("SomeNamespace.IContract")}); 15 | var anotherContractBaseTypes = new BaseTypes(new[] { new TypeName("SomeNamespace.IAnotherContract") }); 16 | 17 | var a = new CommandConventions(baseTypes); 18 | var b = new CommandConventions(baseTypes); 19 | var c = new CommandConventions(baseTypes); 20 | 21 | var otherBaseTypes = new CommandConventions(anotherContractBaseTypes); 22 | 23 | EqualityTesting.TestEqualsAndGetHashCode(a,b,c, otherBaseTypes); 24 | EqualityTesting.TestEqualityOperators(a, b, c, otherBaseTypes); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Test/Parsing/ConventionsDeclarationTest.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | using NUnit.Framework; 5 | using Test.Diesel.TestHelpers; 6 | 7 | namespace Test.Diesel.Parsing 8 | { 9 | [TestFixture] 10 | public class ConventionsDeclarationTest 11 | { 12 | [Test] 13 | public void ApplyOverrides_WithNullConventions_ShouldReturnEqualInstance() 14 | { 15 | var domainEventsConventions = new DomainEventConventions(new BaseTypes(new TypeName[] {})); 16 | var commandConventions = new CommandConventions(new BaseTypes(new TypeName[] {})); 17 | var instance = new ConventionsDeclaration(domainEventsConventions, commandConventions); 18 | 19 | var actual = instance.ApplyOverridesFrom(new ConventionsDeclaration(null, null)); 20 | 21 | Assert.That(actual, Is.EqualTo(instance)); 22 | } 23 | 24 | [Test] 25 | public void ApplyOverrides_WithNewDomainEventConventions_ShouldReturnNewInstanceWithThese() 26 | { 27 | var domainEventsConventions = new DomainEventConventions(new BaseTypes(new TypeName[] { })); 28 | var commandConventions = new CommandConventions(new BaseTypes(new TypeName[] { })); 29 | var instance = new ConventionsDeclaration(domainEventsConventions, commandConventions); 30 | 31 | var newDomainEventsConventions = new DomainEventConventions( 32 | new BaseTypes(new[] {new TypeName("SomeNamespace.IDomainEvent")})); 33 | 34 | var actual = instance.ApplyOverridesFrom(new ConventionsDeclaration(newDomainEventsConventions, null)); 35 | 36 | Assert.That(actual, Is.Not.SameAs(instance)); 37 | Assert.That(actual.DomainEventConventions, Is.EqualTo(newDomainEventsConventions)); 38 | Assert.That(actual.CommandConventions, Is.EqualTo(commandConventions)); 39 | } 40 | 41 | 42 | [Test] 43 | public void ApplyOverrides_WithNewCommandConventions_ShouldReturnNewInstanceWithThese() 44 | { 45 | var domainEventsConventions = new DomainEventConventions(new BaseTypes(new TypeName[] { })); 46 | var commandConventions = new CommandConventions(new BaseTypes(new TypeName[] { })); 47 | var instance = new ConventionsDeclaration(domainEventsConventions, commandConventions); 48 | 49 | var newCommandConventions = new CommandConventions( 50 | new BaseTypes(new[] {new TypeName("SomeNamespace.ICommand")})); 51 | 52 | var actual = instance.ApplyOverridesFrom(new ConventionsDeclaration(null, newCommandConventions)); 53 | 54 | Assert.That(actual, Is.Not.SameAs(instance)); 55 | Assert.That(actual.DomainEventConventions, Is.EqualTo(domainEventsConventions)); 56 | Assert.That(actual.CommandConventions, Is.EqualTo(newCommandConventions)); 57 | } 58 | 59 | [Test] 60 | public void EqualityOperations() 61 | { 62 | var domainEventsConventions = new DomainEventConventions(new BaseTypes(new TypeName[] { })); 63 | var commandConventions = new CommandConventions(new BaseTypes(new TypeName[] { })); 64 | 65 | var a = new ConventionsDeclaration(domainEventsConventions, commandConventions); 66 | var b = new ConventionsDeclaration(domainEventsConventions, commandConventions); 67 | var c = new ConventionsDeclaration(domainEventsConventions, commandConventions); 68 | 69 | var otherDomainEvents = new ConventionsDeclaration( 70 | new DomainEventConventions(new BaseTypes(new[] { new TypeName("Some.BaseType") })), 71 | commandConventions); 72 | var otherCommands = new ConventionsDeclaration( 73 | domainEventsConventions, 74 | new CommandConventions(new BaseTypes(new[] { new TypeName("Some.BaseType") }))); 75 | 76 | EqualityTesting.TestEqualsAndGetHashCode(a,b,c, otherDomainEvents, otherCommands); 77 | EqualityTesting.TestEqualityOperators(a,b,c, otherDomainEvents, otherCommands); 78 | } 79 | 80 | } 81 | } -------------------------------------------------------------------------------- /Test/Parsing/DomainEventConventionsTest.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using Diesel.Parsing; 3 | using Diesel.Parsing.CSharp; 4 | using NUnit.Framework; 5 | using Test.Diesel.TestHelpers; 6 | 7 | namespace Test.Diesel.Parsing 8 | { 9 | [TestFixture] 10 | public class DomainEventConventionsTest 11 | { 12 | [Test] 13 | public void Override_WithNull_ShouldReturnSameInstance() 14 | { 15 | var instance = new DomainEventConventions(new BaseTypes(new TypeName[] { })); 16 | var actual = instance.ApplyOverridesFrom(null); 17 | Assert.That(actual, Is.SameAs(instance)); 18 | } 19 | 20 | [Test] 21 | public void Override_WithEmptyBaseTypes_ShouldReturnInstanceWithEmptyBaseTypes() 22 | { 23 | var instance = new DomainEventConventions( 24 | new BaseTypes(new[] { new TypeName("Foo.EventBase") })); 25 | var actual = instance.ApplyOverridesFrom( 26 | new DomainEventConventions(new BaseTypes(new TypeName[] { }))); 27 | Assert.That(actual.BaseTypes, Is.EqualTo(new BaseTypes(new TypeName[0]))); 28 | } 29 | 30 | [Test] 31 | public void Override_WithNewBaseTypes_ShouldReturnInstanceWithNewBaseTypes() 32 | { 33 | var instance = new DomainEventConventions( 34 | new BaseTypes(new[] { new TypeName("Foo.EventBase") })); 35 | 36 | var actual = instance.ApplyOverridesFrom( 37 | new DomainEventConventions( 38 | new BaseTypes( 39 | new[] 40 | { 41 | new TypeName("Bar.EventBase"), 42 | new TypeName("Bar.IDomainEvent") 43 | }))); 44 | Assert.That(actual.BaseTypes.TypeNames.Count(), Is.EqualTo(2)); 45 | Assert.That(actual.BaseTypes.TypeNames.SingleOrDefault(x => x.Name == "Bar.EventBase"), Is.Not.Null); 46 | Assert.That(actual.BaseTypes.TypeNames.SingleOrDefault(x => x.Name == "Bar.IDomainEvent"), Is.Not.Null); 47 | } 48 | 49 | [Test] 50 | public void EqualityMethods() 51 | { 52 | var baseTypes = new BaseTypes(new[] {new TypeName("SomeNamespace.IContract")}); 53 | var anotherContractBaseTypes = new BaseTypes(new[] { new TypeName("SomeNamespace.IAnotherContract") }); 54 | 55 | var a = new DomainEventConventions(baseTypes); 56 | var b = new DomainEventConventions(baseTypes); 57 | var c = new DomainEventConventions(baseTypes); 58 | 59 | var otherBaseTypes = new DomainEventConventions(anotherContractBaseTypes); 60 | 61 | EqualityTesting.TestEqualsAndGetHashCode(a,b,c, otherBaseTypes); 62 | EqualityTesting.TestEqualityOperators(a, b, c, otherBaseTypes); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Test/Parsing/KeywordTest.cs: -------------------------------------------------------------------------------- 1 | using Diesel.Parsing; 2 | using NUnit.Framework; 3 | using Test.Diesel.TestHelpers; 4 | 5 | namespace Test.Diesel.Parsing 6 | { 7 | [TestFixture] 8 | public class KeywordTest 9 | { 10 | [Test] 11 | public void EqualsAndGetHashCodeAndEquality() 12 | { 13 | var a = new Keyword("a"); 14 | var b = new Keyword("a"); 15 | var c = new Keyword("a"); 16 | 17 | var otherName = new Keyword("b"); 18 | 19 | EqualityTesting.TestEqualsAndGetHashCode(a, b, c, otherName); 20 | EqualityTesting.TestEqualityOperators(a, b, c, otherName); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Test/Parsing/TokenGrammarTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Diesel.Parsing; 3 | using NUnit.Framework; 4 | using Sprache; 5 | 6 | namespace Test.Diesel.Parsing 7 | { 8 | [TestFixture] 9 | public class TokenGrammarTest 10 | { 11 | [Test] 12 | public void RestOfLine_EmptyString_ShouldReturnEmptyString() 13 | { 14 | var actual = TokenGrammar.RestOfLine.Parse(""); 15 | Assert.That(actual, Is.EqualTo("")); 16 | } 17 | 18 | [Test] 19 | public void RestOfLine_JustNewLine_ShouldReturnEmptyString() 20 | { 21 | var actual = TokenGrammar.RestOfLine.Parse(Environment.NewLine); 22 | Assert.That(actual, Is.EqualTo("")); 23 | } 24 | 25 | [Test] 26 | public void RestOfLine_TextAndNewLine_ShouldReturnText() 27 | { 28 | var actual = TokenGrammar.RestOfLine.Parse("Text" + Environment.NewLine); 29 | Assert.That(actual, Is.EqualTo("Text")); 30 | } 31 | 32 | [Test] 33 | public void RestOfLine_TextAndEndOfFile_ShouldReturnText() 34 | { 35 | var actual = TokenGrammar.RestOfLine.Parse("Text"); 36 | Assert.That(actual, Is.EqualTo("Text")); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Diesel.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Diesel")] 13 | [assembly: AssemblyCopyright("Copyright © 2013 Martin Jul (www.mjul.com)")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d07b7ea9-d628-43e2-88b2-970001f0dd1c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Test/TestHelpers/EqualityTesting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NUnit.Framework; 7 | 8 | namespace Test.Diesel.TestHelpers 9 | { 10 | public class EqualityTesting 11 | { 12 | 13 | /// 14 | /// Check that Equals and GetHashCode are well behaved with Value semantics. 15 | /// Given three equal but different instances and a number of unequal instances, 16 | /// verify the Equals behaves correctly: 17 | /// The Equals relation must be Reflexive, Transitive and Symmetrical. 18 | /// 19 | /// The type under test. 20 | /// An instance 21 | /// Another instance, with the same values as a. 22 | /// Another instance, with the same values as a and b. 23 | /// These should not equal a, b and c. 24 | /// It is recommended to supply one per property on the type T, 25 | /// and have only one property per instance differ from the values of the 26 | /// same properties on a, b and c. 27 | public static void TestEqualsAndGetHashCode(T a, T b, T c, params T[] unequalInstances) 28 | { 29 | // Reflexive 30 | Assert.AreEqual(a, a, "Expected A=A"); 31 | 32 | // Transitivity 33 | Assert.AreEqual(a, b, "Expected A=B"); 34 | Assert.AreEqual(b, c, "Expected B=C"); 35 | Assert.AreEqual(a, c, "Expected A=C"); 36 | 37 | // Symmetrical 38 | Assert.AreEqual(b, a, "Expected B=A"); 39 | Assert.AreNotEqual(a, null, "Expected a != null"); 40 | Assert.AreNotEqual(null, a, "Expected null != a"); 41 | 42 | var otherType = new Object(); 43 | Assert.AreNotEqual(a, otherType, "Expected a != object of other type."); 44 | 45 | for (int i = 0; i < unequalInstances.Length; i++) 46 | { 47 | T unequalInstance = unequalInstances[i]; 48 | Assert.AreNotEqual(a, unequalInstance, "Expected a != unequal instances (index {0})", i); 49 | Assert.DoesNotThrow(() => unequalInstance.GetHashCode(), "Expected GetHashCode to not raise exception for unequal instances (index {0})", i); 50 | } 51 | 52 | Assert.AreEqual(a.GetHashCode(), b.GetHashCode(), "Expected equal hashcode when objects are equal."); 53 | } 54 | 55 | public static void TestEqualityOperators(T a, T b, T c, params T[] unequalInstances) 56 | { 57 | // we don't know if the operators are defined on generic type T, so we use dynamic 58 | dynamic da = a; 59 | dynamic db = b; 60 | dynamic dc = c; 61 | 62 | // Reflexive 63 | // ReSharper disable EqualExpressionComparison 64 | Assert.IsTrue(da == da, "Expected A=A"); 65 | // ReSharper restore EqualExpressionComparison 66 | 67 | // Transitivity 68 | Assert.IsTrue(da == db, "Expected A=B"); 69 | Assert.IsTrue(db == dc, "Expected B=C"); 70 | Assert.IsTrue(da == dc, "Expected A=C"); 71 | 72 | // Symmetrical 73 | Assert.IsTrue(db == da, "Expected B=A"); 74 | Assert.IsTrue(da != null, "Expected a != null"); 75 | Assert.IsTrue(null != da, "Expected null != a"); 76 | 77 | Assert.IsFalse(da == null, "Expected not (A == null)"); 78 | Assert.IsFalse(null == da, "Expected not (null == A)"); 79 | 80 | var otherType = new Object(); 81 | Assert.AreNotEqual(a, otherType, "Expected a != object of other type."); 82 | 83 | for (int i = 0; i < unequalInstances.Length; i++) 84 | { 85 | dynamic unequal = unequalInstances[i]; 86 | Assert.IsTrue(da != unequal, "Expected a != unequal instances (index {0})", i); 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Test/TestHelpers/SerializationTesting.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Runtime.Serialization; 3 | using System.Runtime.Serialization.Formatters.Binary; 4 | using System.Runtime.Serialization.Formatters.Soap; 5 | using System.Xml; 6 | using System.Xml.Serialization; 7 | using Test.Diesel.Generated; 8 | 9 | namespace Test.Diesel.TestHelpers 10 | { 11 | public class SerializationTesting 12 | { 13 | public static T SerializeDeserializeWithSoapFormatter(T graph) 14 | { 15 | return SerializeDeserialize(graph, new SoapFormatter()); 16 | } 17 | 18 | public static T SerializeDeserializeWithBinaryFormatter(T graph) 19 | { 20 | return SerializeDeserialize(graph, new BinaryFormatter()); 21 | } 22 | 23 | public static T SerializeDeserializeWithXmlSerializer(T data) 24 | { 25 | var serializer = new XmlSerializer(typeof(T)); 26 | TextWriter textWriter = new StringWriter(); 27 | serializer.Serialize(textWriter, data); 28 | var serialized = textWriter.ToString(); 29 | var deserialized = (T) serializer.Deserialize(new StringReader(serialized)); 30 | return deserialized; 31 | } 32 | 33 | private static T SerializeDeserialize(T graph, IFormatter formatter) 34 | { 35 | var ms = new MemoryStream(); 36 | formatter.Serialize(ms, graph); 37 | ms.Position = 0; 38 | var deserialized = (T)formatter.Deserialize(ms); 39 | return deserialized; 40 | } 41 | 42 | public static T SerializeDeserializeWithDataContractSerializer(T data) 43 | { 44 | var serializer = new DataContractSerializer(typeof (T)); 45 | var stringWriter = new StringWriter(); 46 | serializer.WriteObject(new XmlTextWriter(stringWriter), data); 47 | var serialized = stringWriter.ToString(); 48 | var deserialized = (T)serializer.ReadObject(new XmlTextReader(new StringReader(serialized))); 49 | return deserialized; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Test/Transformations/ApplyDefaultsTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Diesel; 4 | using Diesel.Parsing; 5 | using Diesel.Parsing.CSharp; 6 | using Diesel.Transformations; 7 | using NUnit.Framework; 8 | 9 | namespace Test.Diesel.Transformations 10 | { 11 | [TestFixture] 12 | public class ApplyDefaultsTest 13 | { 14 | [Test] 15 | public void ApplyDefaults_ValueTypeDeclarationWithNullType_ShouldSetTypeToInt32() 16 | { 17 | var valueTypeDeclaration = new ValueTypeDeclaration("EmployeeNumber", 18 | new[] {new PropertyDeclaration(null, null)}); 19 | var actualDeclaration = 20 | (ValueTypeDeclaration) ApplyDefaultsOnSingleDeclarationNamespace(valueTypeDeclaration); 21 | Assert.That(actualDeclaration.Name, Is.EqualTo(valueTypeDeclaration.Name)); 22 | Assert.That(actualDeclaration.Properties.Single().Type, Is.EqualTo(new SimpleType(typeof (Int32)))); 23 | } 24 | 25 | [Test] 26 | public void ApplyDefaults_ValueTypeDeclarationWithNullPropertyName_ShouldSetPropertyName() 27 | { 28 | var valueTypeDeclaration = new ValueTypeDeclaration("EmployeeNumber", 29 | new[] { new PropertyDeclaration(null, null) }); 30 | var actualDeclaration = 31 | (ValueTypeDeclaration)ApplyDefaultsOnSingleDeclarationNamespace(valueTypeDeclaration); 32 | Assert.That(actualDeclaration.Properties.Single().Name, Is.EqualTo("Value")); 33 | } 34 | 35 | [Test] 36 | public void ApplyDefaults_ValueTypeDeclarationWithType_ShouldNotModifyNameOrType() 37 | { 38 | var valueTypeDeclaration = new ValueTypeDeclaration("Name", 39 | new[] {new PropertyDeclaration("FullName", new StringReferenceType())}); 40 | var actualDeclaration = 41 | (ValueTypeDeclaration) ApplyDefaultsOnSingleDeclarationNamespace(valueTypeDeclaration); 42 | var actualProperty = actualDeclaration.Properties.Single(); 43 | Assert.That(actualProperty.Name, Is.EqualTo("FullName")); 44 | Assert.That(actualProperty.Type, Is.EqualTo(new StringReferenceType())); 45 | } 46 | 47 | private static ITypeDeclaration ApplyDefaultsOnSingleDeclarationNamespace(TypeDeclaration valueTypeDeclaration) 48 | { 49 | var input = new AbstractSyntaxTree(null, 50 | new[] 51 | { 52 | new Namespace(new NamespaceName("Test"), 53 | new[] {valueTypeDeclaration}) 54 | }); 55 | var actual = ModelTransformations.Transform(input); 56 | var actualDeclaration = (ValueTypeDeclaration) actual.AbstractSyntaxTree.Namespaces.Single().Declarations.Single(); 57 | return actualDeclaration; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Test/Transformations/KnownTypesHarvesterTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Diesel.Parsing; 7 | using Diesel.Parsing.CSharp; 8 | using Diesel.Transformations; 9 | using NUnit.Framework; 10 | using Test.Diesel.ObjectMothers; 11 | 12 | namespace Test.Diesel.Transformations 13 | { 14 | [TestFixture] 15 | public class KnownTypesHarvesterTest 16 | { 17 | [Test] 18 | public void Harvester_WithEnum_ShouldReturnEnumAsValueType() 19 | { 20 | AssertCorrectlyGetsKnownTypes("MyNamespace.Declarations", EnumDeclarationObjectMother.CreateRoles(), 21 | "MyNamespace.Declarations.Roles", true); 22 | } 23 | 24 | [Test] 25 | public void Harvester_WithDto_ShouldReturnDtoAsNonValueType() 26 | { 27 | AssertCorrectlyGetsKnownTypes("MyNamespace.Declarations", DtoDeclarationObjectMother.CreateName(), 28 | "MyNamespace.Declarations.Name", false); 29 | } 30 | 31 | [Test] 32 | public void Harvester_WithCommand_ShouldReturnCommandAsNonValueType() 33 | { 34 | AssertCorrectlyGetsKnownTypes("MyNamespace.Declarations", CommandDeclarationObjectMother.CreateImportEmployee(), 35 | "MyNamespace.Declarations.ImportEmployee", false); 36 | } 37 | 38 | [Test] 39 | public void Harvester_WithDomainEvent_ShouldReturnDomainEventAsNonValueType() 40 | { 41 | AssertCorrectlyGetsKnownTypes("MyNamespace.Declarations", DomainEventDeclarationObjectMother.CreateEmployeeImported(), 42 | "MyNamespace.Declarations.EmployeeImported", false); 43 | } 44 | 45 | [Test] 46 | public void Harvester_WithValueType_ShouldReturnValueTypeAsValueType() 47 | { 48 | AssertCorrectlyGetsKnownTypes("MyNamespace.Declarations", ValueTypeDeclarationObjectMother.CreateEmployeeNumber(), 49 | "MyNamespace.Declarations.EmployeeNumber", true); 50 | } 51 | 52 | 53 | private AbstractSyntaxTree CreateAbstractSyntaxTreeWith(string ns, params TypeDeclaration[] declarations) 54 | { 55 | return new AbstractSyntaxTree(null, new[] 56 | { 57 | new Namespace(new NamespaceName(ns), declarations) 58 | }); 59 | } 60 | 61 | private void AssertCorrectlyGetsKnownTypes(string namespaceName, TypeDeclaration typeDeclaration, 62 | string expectedFullName, bool expectedIsValueType) 63 | { 64 | var ast = CreateAbstractSyntaxTreeWith(namespaceName, typeDeclaration); 65 | var actual = KnownTypesHarvester.GetKnownTypes(ast); 66 | 67 | var actualKnownType = actual.Single(); 68 | Assert.That(actualKnownType.FullName, Is.EqualTo(expectedFullName)); 69 | Assert.That(actualKnownType.IsValueType, Is.EqualTo(expectedIsValueType)); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Test/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/NUnit.2.6.2/NUnit.2.6.2.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjul/diesel/b05bfb4028355a882d73eb96973a4208ac9401d8/packages/NUnit.2.6.2/NUnit.2.6.2.nupkg -------------------------------------------------------------------------------- /packages/NUnit.2.6.2/NUnit.2.6.2.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | NUnit 5 | 2.6.2 6 | NUnit 7 | Charlie Poole 8 | Charlie Poole 9 | http://nunit.org/nuget/license.html 10 | http://nunit.org/ 11 | http://nunit.org/nuget/nunit_32x32.png 12 | false 13 | NUnit features a fluent assert syntax, parameterized, generic and theory tests and is user-extensible. A number of runners, both from the NUnit project and by third parties, are able to execute NUnit tests. 14 | 15 | Version 2.6 is the seventh major release of this well-known and well-tested programming tool. 16 | 17 | This package includes only the framework assembly. You will need to install the NUnit.Runners package unless you are using a third-party runner. 18 | NUnit is a unit-testing framework for all .Net languages with a strong TDD focus. 19 | Version 2.6 is the seventh major release of NUnit. 20 | 21 | Unlike earlier versions, this package includes only the framework assembly. You will need to install the NUnit.Runners package unless you are using a third-party runner. 22 | 23 | The nunit.mocks assembly is now provided by the NUnit.Mocks package. The pnunit.framework assembly is provided by the pNUnit package. 24 | 25 | en-US 26 | test testing tdd framework fluent assert theory plugin addin 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /packages/NUnit.2.6.2/lib/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjul/diesel/b05bfb4028355a882d73eb96973a4208ac9401d8/packages/NUnit.2.6.2/lib/nunit.framework.dll -------------------------------------------------------------------------------- /packages/NUnit.2.6.2/license.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjul/diesel/b05bfb4028355a882d73eb96973a4208ac9401d8/packages/NUnit.2.6.2/license.txt -------------------------------------------------------------------------------- /packages/Sprache.1.10.0.28/Sprache.1.10.0.28.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjul/diesel/b05bfb4028355a882d73eb96973a4208ac9401d8/packages/Sprache.1.10.0.28/Sprache.1.10.0.28.nupkg -------------------------------------------------------------------------------- /packages/Sprache.1.10.0.28/Sprache.1.10.0.28.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sprache 5 | 1.10.0.28 6 | Sprache 7 | Nicholas Blumhardt and Contributors 8 | Nicholas Blumhardt and Contributors 9 | https://github.com/sprache/Sprache/blob/master/licence.txt 10 | https://github.com/sprache/Sprache 11 | false 12 | Sprache is a simple, lightweight library for constructing parsers directly in C# code. 13 | 14 | Copyright Sprache Contributors 2013 15 | 16 | Parser Parsers Monad 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /packages/Sprache.1.10.0.28/lib/net40/Sprache.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjul/diesel/b05bfb4028355a882d73eb96973a4208ac9401d8/packages/Sprache.1.10.0.28/lib/net40/Sprache.dll -------------------------------------------------------------------------------- /packages/Sprache.1.10.0.28/lib/net40/Sprache.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjul/diesel/b05bfb4028355a882d73eb96973a4208ac9401d8/packages/Sprache.1.10.0.28/lib/net40/Sprache.pdb -------------------------------------------------------------------------------- /packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /publish.ps1: -------------------------------------------------------------------------------- 1 | Push-Location -Path Diesel 2 | & NuGet pack Diesel.csproj -IncludeReferencedProjects 3 | Pop-Location 4 | Write-Host -ForegroundColor Cyan "Ready. Publish with:" 5 | Write-Host -ForegroundColor Yellow " NuGet push " 6 | --------------------------------------------------------------------------------