Skip to content

Commit

Permalink
Add parameter discards
Browse files Browse the repository at this point in the history
  • Loading branch information
ltrzesniewski committed Jan 10, 2024
1 parent 66f2ad2 commit 4b78cdc
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 6 deletions.
13 changes: 11 additions & 2 deletions docs/Syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,24 @@ ErrorsDetected(int entityId, Error[] errors);

ProtoBuf tags are assigned implicitly by default, in increasing order.

:warning: It is dangerous to add/remove/move message members without taking their tags into consideration. Tags define the wire format of the message.
> [!WARNING]
> It is dangerous to add/remove/move message members without taking their tags into consideration. Tags define the wire format of the message.
>
> When removing a member, replace it with a discard (`_`) to preserve the tags of the following ones and to document the fact that a member has been removed.
Tags can be redefined using the `[N]` syntax, where `N` is the desired tag number:

```C#
Foo(int a, [4] int b, int c);
```

Implicit tag numbering resumes after an explicitly defined tag. The tags for the previous example will be:
Which is equivalent to:

```C#
Foo(int a, _, _, int b, int c);
```

Implicit tag numbering resumes after an explicitly defined tag. The tags for the previous examples will be:

- `a`: 1
- `b`: 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,41 @@ public void should_split_on_incomplete_message(string firstLine)
contracts.Messages[1].Name.ShouldEqualOneOf("Bar", "Baz");
}

[Test]
public void should_handle_parameter_discards()
{
var contracts = ParseValid("Foo(int bar, _, int baz)");
var message = contracts.Messages.ExpectedSingle();
message.Parameters.Count.ShouldEqual(2);
message.Parameters[0].Name.ShouldEqual("bar");
message.Parameters[0].Tag.ShouldEqual(1);
message.Parameters[1].Name.ShouldEqual("baz");
message.Parameters[1].Tag.ShouldEqual(3);
}

[Test]
public void should_handle_tag_collisions_in_discards()
{
ParseInvalid("Foo(int bar, _, [2] int baz)");
ParseValid("Foo(int bar, _, [3] int baz)");
}

[Test]
public void should_accept_discards_between_optional_parameters()
{
ParseValid("Foo(int a = 1, _, int c = 3)");
}

[Test]
[TestCase("Foo(int a, _, _, int d)")]
[TestCase("Foo(int a, _, int c, _)")]
[TestCase("Foo(_)")]
[TestCase("Foo(_, _)")]
public void should_accept_discards(string message)
{
ParseValid(message);
}

private static ParsedContracts ParseValid(string definitionText)
{
var contracts = Parse(definitionText);
Expand Down Expand Up @@ -761,7 +796,7 @@ private static ParsedContracts Parse(string definitionText)
Console.WriteLine("ERROR: {0}", error);

foreach (var message in contracts.Messages)
Console.WriteLine($"MESSAGE: {message}");
Console.WriteLine($"MESSAGE: {message}({string.Join(", ", message.Parameters.Select(p => $"[{p.Tag}] {p}"))})");

return contracts;
}
Expand Down
10 changes: 9 additions & 1 deletion src/Abc.Zebus.MessageDsl.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{A0123301
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
..\README.md = ..\README.md
..\.github\workflows\build.yml = ..\.github\workflows\build.yml
EndProjectSection
EndProject
Expand All @@ -25,6 +24,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Abc.Zebus.MessageDsl.Genera
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Abc.Zebus.MessageDsl.Generator.Tests", "Abc.Zebus.MessageDsl.Generator.Tests\Abc.Zebus.MessageDsl.Generator.Tests.csproj", "{97EB9627-0DA3-4A81-90EE-F30772A36E40}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{A8144077-4186-4CC3-BEA9-A2EB6B6A39CC}"
ProjectSection(SolutionItems) = preProject
..\docs\Syntax.md = ..\docs\Syntax.md
..\docs\BuildTimeCodeGen.md = ..\docs\BuildTimeCodeGen.md
..\README.md = ..\README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -66,4 +72,6 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0373CC03-AD01-4AC4-9117-30ED1E5CB6ED}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
EndGlobal
11 changes: 11 additions & 0 deletions src/Abc.Zebus.MessageDsl/Analysis/AstCreationVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ public AstCreationVisitor(ParsedContracts contracts)
{
try
{
if (context.discard is not null)
{
return new ParameterDefinition
{
Name = "_",
Type = new TypeName(null),
IsDiscarded = true,
ParseContext = context
};
}

_currentParameter = new ParameterDefinition
{
Name = GetId(context.paramName),
Expand Down
15 changes: 15 additions & 0 deletions src/Abc.Zebus.MessageDsl/Analysis/AstProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ public void PostProcess()
}
}

public void Cleanup()
{
foreach (var message in _contracts.Messages)
RemoveDiscardedParameters(message);
}

private static void AddInterfaces(MessageDefinition message)
{
switch (message.Type)
Expand Down Expand Up @@ -129,4 +135,13 @@ private static void SetInheritanceModifier(MessageDefinition message)
? InheritanceModifier.None
: InheritanceModifier.Sealed;
}

private static void RemoveDiscardedParameters(MessageDefinition message)
{
for (var i = message.Parameters.Count - 1; i >= 0; --i)
{
if (message.Parameters[i].IsDiscarded)
message.Parameters.RemoveAt(i);
}
}
}
6 changes: 6 additions & 0 deletions src/Abc.Zebus.MessageDsl/Analysis/AstValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ private void ValidateMessage(MessageDefinition message)

foreach (var param in message.Parameters)
{
if (param.IsDiscarded)
continue;

var errorContext = param.ParseContext ?? message.ParseContext;

if (!paramNames.Add(param.Name))
Expand All @@ -62,6 +65,9 @@ private void ValidateMessage(MessageDefinition message)
var param = message.Parameters[i];
var errorContext = param.ParseContext ?? message.ParseContext;

if (param.IsDiscarded)
continue;

if (string.IsNullOrEmpty(param.DefaultValue))
requiredParameterSeen = true;
else if (requiredParameterSeen)
Expand Down
5 changes: 4 additions & 1 deletion src/Abc.Zebus.MessageDsl/Ast/ParameterDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class ParameterDefinition : AstNode, INamedNode
public bool IsWritableProperty { get; set; }
public AttributeSet Attributes { get; private set; } = new();

internal bool IsDiscarded { get; set; }

public FieldRules Rules
{
get
Expand Down Expand Up @@ -48,9 +50,10 @@ public ParameterDefinition Clone()
IsMarkedOptional = IsMarkedOptional,
DefaultValue = DefaultValue,
Attributes = Attributes.Clone(),
IsDiscarded = IsDiscarded,
ParseContext = ParseContext
};

public override string ToString()
=> $"{Type} {Name}";
=> IsDiscarded ? "_" : $"{Type} {Name}";
}
1 change: 1 addition & 0 deletions src/Abc.Zebus.MessageDsl/Ast/ParsedContracts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ internal void Process()
processor.PostProcess();

new AstValidator(this).Validate();
processor.Cleanup();
}

public void AddError(string message)
Expand Down
8 changes: 7 additions & 1 deletion src/Abc.Zebus.MessageDsl/Dsl/MessageContracts.g4
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ parameterList

parameterDefinition
: attributes typeName paramName=id optionalModifier='?'? ('=' defaultValue=literalValue)?
| discard=DISCARD
;

typeParamConstraintList
Expand Down Expand Up @@ -240,7 +241,8 @@ KW_SEALED : 'sealed';
KW_ABSTRACT : 'abstract';

ID
: [a-zA-Z_][a-zA-Z0-9_]*
: [a-zA-Z][a-zA-Z0-9_]*
| '_' [a-zA-Z0-9_]+
;

STRING
Expand All @@ -261,6 +263,10 @@ SEP
: ';'
;
DISCARD
: '_'
;
fragment HEX
: [0-9A-Fa-f]
;
Expand Down

0 comments on commit 4b78cdc

Please sign in to comment.