Skip to content

Commit

Permalink
Detect inheritance loops
Browse files Browse the repository at this point in the history
  • Loading branch information
ltrzesniewski committed Oct 29, 2020
1 parent 4585b31 commit 6199630
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/Abc.Zebus.MessageDsl.Tests/MessageDsl/ParsedContractsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,16 @@ public void should_parse_nested_classes()
message.ContainingClasses.ShouldEqual(new TypeName[] { "Foo", "Bar" });
}

[Test]
public void should_detect_inheritance_loops()
{
ParseInvalid(@"Foo() : Foo;");
ParseInvalid(@"Foo() : Bar; [ProtoInclude(1, typeof(Foo))] Bar() : Foo;");
ParseInvalid(@"Foo() : Bar; [ProtoInclude(1, typeof(Foo))] Bar() : Baz; [ProtoInclude(1, typeof(Bar))] Baz() : Foo;");

ParseValid(@"Foo() : Bar; [ProtoInclude(1, typeof(Foo))] Bar();");
}

private static ParsedContracts ParseValid(string definitionText)
{
var contracts = Parse(definitionText);
Expand Down
31 changes: 31 additions & 0 deletions src/Abc.Zebus.MessageDsl/Analysis/AstValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ private void ValidateMessage(MessageDefinition message)

foreach (var baseType in message.BaseTypes)
ValidateType(baseType, message.ParseContext);

ValidateInheritance(message);
}

private void ValidateTags(MessageDefinition message)
Expand Down Expand Up @@ -146,6 +148,35 @@ private void ValidateType(TypeName type, ParserRuleContext? context)
_contracts.AddError(context, "Invalid type: {0}", type.NetType);
}

private void ValidateInheritance(MessageDefinition message)
{
if (message.BaseTypes.Count == 0)
return;

var seenTypes = new HashSet<TypeName>
{
message.Name
};

var currentMessage = message;

while (true)
{
if (currentMessage.BaseTypes.Count == 0)
break;

currentMessage = _contracts.Messages.FirstOrDefault(m => m.Name == currentMessage.BaseTypes[0].NetType);
if (currentMessage is null)
break;

if (!seenTypes.Add(currentMessage.Name))
{
_contracts.AddError(message.ParseContext, "There is a loop in the inheritance chain");
break;
}
}
}

private void DetectDuplicateTypes()
{
var seenTypes = new HashSet<string>();
Expand Down

0 comments on commit 6199630

Please sign in to comment.