public Context From(string source) { var stream = new ANTLRStringStream(source); var lexer = new MessageContractsLexer(stream); var tokens = new CommonTokenStream(lexer); var parser = new MessageContractsParser(tokens) { TreeAdaptor = new CommonTreeAdaptor() }; var program = parser.GetProgram(); var commonTree = (CommonTree)program.Tree; var node = commonTree as CommonErrorNode; if (node != null) { throw new InvalidOperationException(node.ToString()); } var ctx = new Context(); foreach (var child in commonTree.Children) { WalkDeclarations(child, ctx); } return ctx; }
public void WalkDeclarations(ITree tree, Context context) { var t = tree; switch (t.Type) { case MessageContractsLexer.FragmentEntry: var fragmentId = t.GetChild(0).Text; var fragmentType = t.GetChild(1).Text; var fragmentName = t.GetChild(2).Text; context.Fragments[fragmentId] = new Fragment(fragmentType, fragmentName); break; case MessageContractsLexer.ModifierDefinition: var modifier = t.GetChild(0).Text; context.CurrentEntity.Modifiers.Remove(modifier); for (int i = 1; i < t.ChildCount; i++) { context.CurrentEntity.Modifiers.Add(modifier, t.GetChild(i).Text); } break; case MessageContractsLexer.TypeToken: var name = t.GetChild(0).Text; var block = t.GetChild(1); var modifiers = new List<Modifier>(); for (int i = 2; i < t.ChildCount; i++) { var mod = t.GetChild(i).Text; var used = context.CurrentEntity.Modifiers.GetValues(mod); if (null == used || used.Length == 0) { var format = string.Format("Entity '{0}' does not have modifier reference: '{1}'", context.CurrentEntity.Name, mod); throw new InvalidOperationException(format); } foreach (var s in used) { modifiers.Add(new Modifier(mod, s)); } } var message = new Message(name, modifiers); if (modifiers.Any()) { // only commands and events have modifiers foreach (var member in context.Entities.Peek().FixedMembers) { message.Members.Add(member); } } for (int i = 0; i < block.ChildCount; i++) { var members = WalkContractMember(block.GetChild(i), context).ToArray(); message.Members.AddRange(members.Where(m => m.Kind == Member.Kinds.Field)); var stringRepresentations = members.Where(m => m.Kind == Member.Kinds.StringRepresentation).ToArray(); switch (stringRepresentations.Length) { case 0: break; case 1: message.StringRepresentation = stringRepresentations[0].Name; break; default: throw new InvalidOperationException("Only one string representation per message"); } } context.Contracts.Add(message); context.CurrentEntity.Messages.Add(message); break; case MessageContractsLexer.EntityDefinition: var entityName = t.GetChild(0).Text; var entityBlock = t.GetChild(1); var entity = new Entity(entityName); for (int i = 0; i < entityBlock.ChildCount; i++) { entity.FixedMembers.AddRange(WalkContractMember(entityBlock.GetChild(i), context)); } context.PushEntity(entity); for (int i = 2; i < t.ChildCount; i++) { WalkDeclarations(t.GetChild(i), context); } break; case MessageContractsLexer.NamespaceToken: var ns = string.Join(".", t.Children().Select(s => s.Text)); context.CurrentNamespace = ns; break; case MessageContractsLexer.ExternToken: var text = t.GetChild(0).Text; context.CurrentExtern = text; break; case MessageContractsLexer.UsingToken: var us = string.Join(".", t.Children().Select(s => s.Text)); context.Using.Add(us); break; default: throw new InvalidOperationException("Unexpected token: " + t.Text); } }
public void WalkDeclarations(object tree, Context context) { var t = (CommonTree)tree; switch (t.Type) { case MessageContractsLexer.FragmentEntry: var fragmentId = t.GetChild(0).Text; var fragmentType = t.GetChild(1).Text; var fragmentName = t.GetChild(2).Text; context.Fragments[fragmentId] = new Fragment(fragmentType, fragmentName); break; case MessageContractsLexer.ModifierDefinition: Console.WriteLine(t); var modifier = t.GetChild(1).Text; var type = t.GetChild(0).Text; context.CurrentEntity.Modifiers[modifier] = type; break; case MessageContractsLexer.TypeToken: var name = t.GetChild(0).Text; var block = t.GetChild(1); var modifiers = new List<Modifier>(); if (t.ChildCount>2) { var mod = t.GetChild(2).Text; string typeName; if (!context.CurrentEntity.Modifiers.TryGetValue(mod, out typeName)) { var format = string.Format("Entity '{0}' does not have modifier reference: '{1}'", context.CurrentEntity.Name, mod); throw new InvalidOperationException(format); } modifiers.Add(new Modifier(mod, typeName)); } var message = new Message(name, modifiers); if (modifiers.Any()) { // only commands and events have modifiers foreach (var member in context.Entities.Peek().FixedMembers) { message.Members.Add(member); } } for (int i = 0; i < block.ChildCount; i++) { message.Members.AddRange(WalkContractMember(block.GetChild(i), context)); } context.Contracts.Add(message); context.CurrentEntity.Messages.Add(message); break; case MessageContractsLexer.EntityDefinition: var entityName = t.GetChild(0).Text; var entityBlock = t.GetChild(1); var entity = new Entity(entityName); for (int i = 0; i < entityBlock.ChildCount; i++) { entity.FixedMembers.AddRange(WalkContractMember(entityBlock.GetChild(i), context)); } context.Entities.Push(entity); break; default: throw new InvalidOperationException("Unexpected token: " + t.Text); } }
static IEnumerable<Member> WalkContractMember(ITree tree, Context context) { if (tree.Type == MessageContractsLexer.FragmentReference) { var fragmentId = tree.GetChild(0).Text; if (!context.Fragments.ContainsKey(fragmentId)) { throw new InvalidOperationException(string.Format("Unknown fragment '{0}'", fragmentId)); } var fragment = context.Fragments[fragmentId]; yield return new Member(fragment.Type, fragment.Name, fragmentId); yield break; } if (tree.Type == MessageContractsLexer.MemberToken) { var type = tree.GetChild(0).Text; var name = tree.GetChild(1).Text; if (type == "ref") { var match = context.Contracts.Where(c => c.Name == name).ToArray(); if (match.Length == 1) { foreach (var member in match[0].Members) { yield return member; } yield break; } throw new InvalidOperationException(string.Format("Unknown include '{0}'", name)); } yield return (new Member(type, name, name)); yield break; } if (tree.Type == MessageContractsLexer.StringRepresentationToken) { var text = tree.GetChild(0).Text; yield return new Member(null, text, null, Member.Kinds.StringRepresentation); yield break; } throw new InvalidOperationException("Unexpected token: " + tree.Text); }
public void Generate(Context context, IndentedTextWriter outer) { var writer = new CodeWriter(outer); foreach (var source in context.Using.Distinct().OrderBy(s => s)) { writer.WriteLine("using {0};", source); } writer.WriteLine(@" // ReSharper disable PartialTypeWithSinglePart // ReSharper disable UnusedMember.Local"); writer.WriteLine("namespace {0}", context.CurrentNamespace); writer.WriteLine("{"); writer.Indent += 1; if (!string.IsNullOrEmpty(Region)) { writer.WriteLine("#region {0}", Region); } WriteContext(writer, context); if (!string.IsNullOrEmpty(Region)) { writer.WriteLine("#endregion"); } writer.Indent -= 1; writer.WriteLine("}"); }
private void WriteContext(CodeWriter writer, Context context) { foreach (var contract in context.Contracts) { if (contract.InteropData != null) WriteInteropData(writer, contract); writer.Write(ClassNameTemplate, contract.Name, context.CurrentExtern); if (contract.Modifiers.Any()) writer.Write(" : {0}", string.Join(", ", contract.Modifiers.Select(s => s.Interface).ToArray())); writer.WriteLine(); writer.WriteLine("{"); writer.Indent += 1; if (contract.Members.Count > 0) { WriteMembers(contract, writer); writer.WriteLine(); WriteNotSoPrivateAnymoreCtor(writer, contract); writer.Write("public {0} (", contract.Name); WriteParameters(contract, writer); writer.WriteLine(")"); writer.WriteLine("{"); writer.Indent += 1; WriteAssignments(contract, writer); writer.Indent -= 1; writer.WriteLine("}"); } WriteToString(writer, contract); writer.Indent -= 1; writer.WriteLine("}"); } foreach (var entity in context.Entities) { if ((entity.Name ?? "default") == "default") continue; GenerateEntityInterface(entity, writer, "?", "public interface I{0}ApplicationService"); GenerateEntityInterface(entity, writer, "!", "public interface I{0}State"); } }
static IEnumerable<Member> WalkContractMember(ITree tree, Context context) { if (tree.Type == MessageContractsLexer.FragmentReference) { var fragmentId = tree.GetChild(0).Text; if (!context.Fragments.ContainsKey(fragmentId)) { var errorNode = (CommonTree)tree; throw new InvalidOperationException(string.Format("Line: {0}\r\nUnknown fragment: {1}", errorNode.Line, errorNode.Text)); } var fragment = context.Fragments[fragmentId]; yield return new Member(null, fragment.Type, fragment.Name, fragmentId); yield break; } if (tree.Type == MessageContractsLexer.MemberToken || tree.Type == MessageContractsLexer.MemberAnnToken) { string type; string name; string annotation; if (tree.Type == MessageContractsLexer.MemberToken) { type = tree.GetChild(0).Text; name = tree.GetChild(1).Text; annotation = string.Empty; } else { annotation = tree.GetChild(0).Text; type = tree.GetChild(1).Text; name = tree.GetChild(2).Text; } if (type == "ref") { var match = context.Contracts.Where(c => c.Name == name).ToArray(); if (match.Length == 1) { foreach (var member in match[0].Members) { yield return member; } yield break; } throw new InvalidOperationException(string.Format("Unknown include '{0}'", name)); } yield return (new Member(annotation, type, name, name)); yield break; } if (tree.Type == MessageContractsLexer.StringRepresentationToken) { var text = tree.GetChild(0).Text; yield return new Member(null, null, text, null, Member.Kinds.StringRepresentation); yield break; } if (tree.Type == MessageContractsLexer.MemberAnnToken) { //var text = tree.GetChild(0).Text; //yield return new Member(null, text, null, Member.Kinds.StringRepresentation); yield break; } var node = (Antlr.Runtime.Tree.CommonErrorNode) tree; throw new InvalidOperationException(string.Format("Line: {0}\r\nUnknown fragment: {1}", node.start.Line, node.Text)); }
public void Generate(Context context, IndentedTextWriter outer) { var writer = new CodeWriter(outer); if (!string.IsNullOrEmpty(Namespace)) { writer.WriteLine("namespace {0}", Namespace); writer.WriteLine("{"); } writer.Indent += 1; if (!string.IsNullOrEmpty(Region)) { writer.WriteLine("#region {0}", Region); } WriteContext(writer, context); if (!string.IsNullOrEmpty(Region)) { writer.WriteLine("#endregion"); } writer.Indent -= 1; if (!string.IsNullOrEmpty(Namespace)) { writer.WriteLine("}"); } }
private void WriteContext(CodeWriter writer, Context context) { foreach (var contract in context.Contracts) { writer.Write(ClassNameTemplate, contract.Name); if (contract.Modifiers.Any()) { writer.Write(" : {0}", string.Join(", ", contract.Modifiers.Select(s => s.Interface).ToArray())); } writer.WriteLine(); writer.WriteLine("{"); writer.Indent += 1; if (contract.Members.Count > 0) { WriteMembers(contract, writer); writer.WriteLine(PrivateCtorTemplate, contract.Name); writer.Write("public {0} (", contract.Name); WriteParameters(contract, writer); writer.WriteLine(")"); writer.WriteLine("{"); writer.Indent += 1; WriteAssignments(contract, writer); writer.Indent -= 1; writer.WriteLine("}"); } writer.Indent -= 1; writer.WriteLine("}"); } var split = (GenerateInterfaceForEntityWithModifiers ?? "") .Split(new[]{','}, StringSplitOptions.RemoveEmptyEntries); foreach (var entity in context.Entities) { if ((entity.Name??"null") == "null") continue; var matches = entity.Messages.Where(m => m.Modifiers.Select(s =>s.Identifier).Intersect(split).Any()).ToList(); if (matches.Any()) { writer.WriteLine(); writer.WriteLine(TemplateForInterfaceName, entity.Name); writer.WriteLine("{"); writer.Indent += 1; foreach (var contract in matches) { writer.WriteLine(TemplateForInterfaceMember, contract.Name); } writer.Indent -= 1; writer.WriteLine("}"); } } }
private void WriteContext(CodeWriter writer, Context context) { foreach (var contract in context.Contracts) { if (contract.Modifiers.Any()) { if (contract.Modifiers.FirstOrDefault(c => c.Identifier == "!" && c.Interface != "IIdentity") != null) { writer.Write(TemplateForEventInterfaceName, contract.Name, string.Join(", ", contract.Modifiers.Select(s => s.Interface).ToArray())); writer.WriteLine(); writer.WriteLine("{"); writer.Indent += 1; if (contract.Members.Count > 0) { WriteInterfaceMembers(contract, writer); writer.WriteLine(); } writer.Indent -= 1; writer.WriteLine("}"); } } writer.Write(ClassNameTemplate, contract.Name, context.CurrentExtern, string.Empty); //} if (contract.Modifiers.Any()) { if (contract.Modifiers.FirstOrDefault(c => c.Identifier == "!" && c.Interface != "IIdentity") != null) { //writer.Write(" : DomainEvent, {0}", string.Join(", ", contract.Modifiers.Select(s => s.Interface).ToArray())); writer.Write(" : DomainEvent, {0}", string.Format("I{0}", contract.Name)); } //else if (contract.Modifiers.FirstOrDefault(c => c.Identifier == "?" && c.Interface != "IIdentity") != null) //{ // writer.Write(" : DomainCommand, {0}", string.Join(", ", contract.Modifiers.Select(s => s.Interface).ToArray())); //} else { writer.Write(" : {0}", string.Join(", ", contract.Modifiers.Select(s => s.Interface).ToArray())); } } writer.WriteLine(); writer.WriteLine("{"); writer.Indent += 1; if (contract.Members.Count > 0) { WriteMembers(contract, writer); writer.WriteLine(); WritePrivateCtor(writer, contract); if (contract.Modifiers.FirstOrDefault(c => c.Identifier == "!" && c.Interface != "IIdentity") != null) { writer.Write("public {0} (TenancyId tenancyId, int aggregateVersion, ", contract.Name); } else if (contract.Modifiers.FirstOrDefault(c => c.Interface == "DomainCommand") != null) { writer.Write("public {0} (TenancyId tenancyId, int aggregateVersion, ", contract.Name); } else { writer.Write("public {0} (", contract.Name); } WriteParameters(contract, writer); if (contract.Modifiers.FirstOrDefault(c => c.Identifier == "!" && c.Interface != "IIdentity") != null) { writer.WriteLine(") : base(tenancyId, id, aggregateVersion)"); } else if (contract.Modifiers.FirstOrDefault(c => c.Interface == "DomainCommand") != null) { writer.WriteLine(") : base(tenancyId, aggregateVersion)"); } else { writer.WriteLine(")"); } writer.WriteLine("{"); writer.Indent += 1; WriteAssignments(contract, writer); writer.Indent -= 1; writer.WriteLine("}"); } WriteToString(writer, contract); if (contract.Modifiers.FirstOrDefault(c => c.Identifier == "!" && c.Interface == "IIdentity") != null) { writer.WriteLine(@"public override string ToString() {{ return Id.ToString(); }} protected bool Equals({0} other) {{ return Id.Equals(other.Id); }} public override bool Equals(object obj) {{ if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; return Equals(({0}) obj); }} public override int GetHashCode() {{ return Id.GetHashCode(); }} public static bool operator ==({0} a, {0} b) {{ if (ReferenceEquals(a, b)) {{ return true; }} if (((object) a == null) || ((object) b == null)) {{ return false; }} return a.Equals(b); }} public static bool operator !=({0} a, {0} b) {{ return !(a == b); }} public static {0} New() {{ return new {0}(Guid.NewGuid()); }} public static {0} Empty() {{ return new {0}(Guid.Empty); }}", contract.Name); } writer.Indent -= 1; writer.WriteLine("}"); } foreach (var entity in context.Entities) { if ((entity.Name ?? "default") == "default") continue; GenerateEntityInterface(entity, writer, "?", "public interface I{0}Aggregate"); GenerateEntityInterface(entity, writer, "!", "public interface I{0}AggregateState"); } }
public void Generate(Context context, IndentedTextWriter outer) { // Apply templates foreach (var template in context.Templates) { if(String.IsNullOrWhiteSpace(template.Key) || String.IsNullOrWhiteSpace(template.Value)) continue; var propertyInfo = GetType().GetProperty(template.Key); if(propertyInfo == null) continue; try { propertyInfo.SetValue(this, template.Value, null); } catch (Exception) { Console.WriteLine("Error when setting value for template '{0}", template.Key); } } var writer = new CodeWriter(outer); foreach (var source in context.Using.Distinct().OrderBy(s => s)) { writer.WriteLine("using {0};", source); } writer.WriteLine(@" // ReSharper disable PartialTypeWithSinglePart // ReSharper disable UnusedMember.Local"); writer.WriteLine("namespace {0}", context.CurrentNamespace); writer.WriteLine("{"); writer.Indent += 1; if (!string.IsNullOrEmpty(Region)) { writer.WriteLine("#region {0}", Region); } WriteContext(writer, context); if (!string.IsNullOrEmpty(Region)) { writer.WriteLine("#endregion"); } writer.Indent -= 1; writer.WriteLine("}"); }