Skip to content

Commit 68c92f5

Browse files
[WIP] All rules have method, some logic put on rule Element processing
1 parent 865aff3 commit 68c92f5

File tree

188 files changed

+7226
-4466
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

188 files changed

+7226
-4466
lines changed

SysML2.NET.CodeGenerator/Extensions/NamedElementExtensions.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020

2121
namespace SysML2.NET.CodeGenerator.Extensions
2222
{
23+
using System;
2324
using System.Linq;
2425

2526
using uml4net.CommonStructure;
27+
using uml4net.SimpleClassifiers;
2628

2729
/// <summary>
2830
/// Extension class for <see cref="INamedElement"/>
@@ -40,5 +42,36 @@ public static string QueryNamespace(this INamedElement namedElement)
4042
var namespaces = qualifiedNameSpaces.Skip(1).Take(qualifiedNameSpaces.Length - 2);
4143
return string.Join('.', namespaces);
4244
}
45+
46+
/// <summary>
47+
/// Query the fully qualified type name (Namespace + Type name).
48+
/// </summary>
49+
/// <param name="namedElement">The specific <see cref="INamedElement"/>that should have the fully qualified type name computed</param>
50+
/// <param name="namespacePart">A specific namespace part (POCO/DTO distinction)</param>
51+
/// <param name="targetInterface">Asserts if the type should be the interface name or not</param>
52+
/// <returns>The fully qualified type name</returns>
53+
public static string QueryFullyQualifiedTypeName(this INamedElement namedElement, string namespacePart = "POCO", bool targetInterface = true)
54+
{
55+
ArgumentNullException.ThrowIfNull(namedElement);
56+
ArgumentException.ThrowIfNullOrWhiteSpace(namespacePart);
57+
58+
var typeName = "SysML2.NET.Core.";
59+
60+
if (namedElement is not IEnumeration)
61+
{
62+
typeName += $"{namespacePart}.";
63+
}
64+
65+
typeName += namedElement.QueryNamespace();
66+
typeName += ".";
67+
68+
if (namedElement is not IEnumeration && targetInterface)
69+
{
70+
typeName += "I";
71+
}
72+
73+
typeName += namedElement.Name;
74+
return typeName;
75+
}
4376
}
4477
}

SysML2.NET.CodeGenerator/Generators/UmlHandleBarsGenerators/UmlCoreTextualNotationBuilderGenerator.cs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace SysML2.NET.CodeGenerator.Generators.UmlHandleBarsGenerators
2929
using SysML2.NET.CodeGenerator.Grammar.Model;
3030
using SysML2.NET.CodeGenerator.HandleBarHelpers;
3131

32+
using uml4net.CommonStructure;
3233
using uml4net.Extensions;
3334
using uml4net.HandleBars;
3435
using uml4net.StructuredClassifiers;
@@ -104,11 +105,11 @@ public override Task GenerateAsync(XmiReaderResult xmiReaderResult, DirectoryInf
104105
public async Task GenerateAsync(XmiReaderResult xmiReaderResult, TextualNotationSpecification textualNotationSpecification, DirectoryInfo outputDirectory)
105106
{
106107
await this.GenerateBuilderClasses(xmiReaderResult, textualNotationSpecification, outputDirectory);
107-
await this.GenerateBuilderFacade(xmiReaderResult, outputDirectory);
108+
// await this.GenerateBuilderFacade(xmiReaderResult, outputDirectory);
108109
}
109110

110111
/// <summary>
111-
/// Generates Textual Notation builder classes for each concrete <see cref="IClass"/>
112+
/// Generates Textual Notation builder classes for each <see cref="IClass"/> targeted by a rule
112113
/// </summary>
113114
/// <param name="xmiReaderResult">
114115
/// the <see cref="XmiReaderResult"/> that contains the UML model to generate from
@@ -131,7 +132,7 @@ private Task GenerateBuilderClasses(XmiReaderResult xmiReaderResult, TextualNota
131132
}
132133

133134
/// <summary>
134-
/// Generates Textual Notation builder classes for each concrete <see cref="IClass"/>
135+
/// Generates Textual Notation builder classes for each <see cref="IClass"/> targeted by a rule
135136
/// </summary>
136137
/// <param name="xmiReaderResult">
137138
/// the <see cref="XmiReaderResult"/> that contains the UML model to generate from
@@ -147,17 +148,39 @@ private async Task GenerateBuilderClassesInternal(XmiReaderResult xmiReaderResul
147148
{
148149
var template = this.Templates[BuilderTemplateName];
149150

150-
var classes = xmiReaderResult.QueryContainedAndImported("SysML")
151-
.SelectMany(x => x.PackagedElement.OfType<IClass>())
152-
.Where(x => !x.IsAbstract)
151+
var namedElements = xmiReaderResult.QueryContainedAndImported("SysML")
152+
.SelectMany(x => x.PackagedElement.OfType<INamedElement>())
153153
.ToList();
154154

155-
foreach (var umlClass in classes)
155+
var rulesGroupedByType = textualNotationSpecification.Rules
156+
.Where(x => !string.IsNullOrWhiteSpace(x.TargetElementName) && namedElements.Any(n => n.Name == x.TargetElementName))
157+
.GroupBy(x => x.TargetElementName).ToDictionary(x => x.Key, x => x.ToList());
158+
159+
foreach (var nonTargetingRule in textualNotationSpecification.Rules.Where(x => string.IsNullOrWhiteSpace(x.TargetElementName)))
160+
{
161+
var matchingClass = namedElements.SingleOrDefault(x => x.Name == nonTargetingRule.RuleName);
162+
163+
if (matchingClass != null)
164+
{
165+
if (rulesGroupedByType.TryGetValue(matchingClass.Name, out var existingRules))
166+
{
167+
existingRules.Add(nonTargetingRule);
168+
}
169+
else
170+
{
171+
rulesGroupedByType[matchingClass.Name] = [nonTargetingRule];
172+
}
173+
}
174+
}
175+
176+
foreach (var rulesPerType in rulesGroupedByType)
156177
{
157-
var generatedBuilder = template(new {ClassContext = umlClass, Rules = textualNotationSpecification.Rules});
178+
var targetClassContext = namedElements.Single(x => x.Name == rulesPerType.Key);
179+
180+
var generatedBuilder = template(new {Context = targetClassContext, Rules = rulesPerType.Value, AllRules = textualNotationSpecification.Rules});
158181
generatedBuilder = this.CodeCleanup(generatedBuilder);
159182

160-
var fileName = $"{umlClass.Name.CapitalizeFirstLetter()}TextualNotationBuilder.cs";
183+
var fileName = $"{targetClassContext.Name.CapitalizeFirstLetter()}TextualNotationBuilder.cs";
161184

162185
await WriteAsync(generatedBuilder, outputDirectory, fileName);
163186
}

SysML2.NET/TextualNotation/ITextualNotationBuilderFacade.cs renamed to SysML2.NET.CodeGenerator/Grammar/Model/Alternatives.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// -------------------------------------------------------------------------------------------------
2-
// <copyright file="ITextualNotationBuilderFacade.cs" company="Starion Group S.A.">
2+
// <copyright file="Alternatives.cs" company="Starion Group S.A.">
33
//
44
// Copyright 2022-2026 Starion Group S.A.
55
//
@@ -18,20 +18,20 @@
1818
// </copyright>
1919
// ------------------------------------------------------------------------------------------------
2020

21-
namespace SysML2.NET.TextualNotation
21+
namespace SysML2.NET.CodeGenerator.Grammar
2222
{
23-
using SysML2.NET.Core.POCO.Root.Elements;
23+
using System.Collections.Generic;
24+
25+
using SysML2.NET.CodeGenerator.Grammar.Model;
2426

2527
/// <summary>
26-
/// The <see cref="ITextualNotationBuilderFacade"/> provides access to built textual notation for <see cref="IElement" /> via <see cref="TextualNotationBuilder{TElement}" />
28+
/// Provides mapping data class for the alternative grammar part
2729
/// </summary>
28-
public interface ITextualNotationBuilderFacade
30+
public class Alternatives
2931
{
3032
/// <summary>
31-
/// Queries the Textual Notation of an <see cref="IElement"/>
33+
/// Gets a collection of <see cref="RuleElement" /> that is part of the <see cref="Alternatives" />
3234
/// </summary>
33-
/// <param name="element">The <see cref="IElement"/> to built textual notation from</param>
34-
/// <returns>The built textual notation string</returns>
35-
string QueryTextualNotationOfElement(IElement element);
35+
public List<RuleElement> Elements { get; } = [];
3636
}
3737
}

SysML2.NET.CodeGenerator/Grammar/Model/AssignmentElement.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ public class AssignmentElement: RuleElement
4343
/// <summary>
4444
/// Gets or sets an optional prefix
4545
/// </summary>
46-
public string Prefix { get; set; }
46+
public string Prefix { get; set; }
4747
}
4848
}

SysML2.NET.CodeGenerator/Grammar/Model/GroupElement.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ namespace SysML2.NET.CodeGenerator.Grammar.Model
2828
public class GroupElement: RuleElement
2929
{
3030
/// <summary>
31-
/// All <see cref="RuleElement"/> that are part of the group
31+
/// Gets the collection <see cref="Alternatives"/> that are part of the <see cref="GroupElement" />
3232
/// </summary>
33-
public List<RuleElement> Elements { get; } = [];
33+
public List<Alternatives> Alternatives { get; } = [];
3434
}
3535
}

SysML2.NET.CodeGenerator/Grammar/Model/TextualNotationRule.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ public class TextualNotationRule
4343
public RuleParameter Parameter { get; set; }
4444

4545
/// <summary>
46-
/// Gets the collection of defined <see cref="RuleElement" />
46+
/// Gets or sets the raw string that declares the rule
4747
/// </summary>
48-
public List<RuleElement> Elements { get; } = [];
48+
public string RawRule { get; set; }
4949

5050
/// <summary>
51-
/// Gets or sets the raw string that declares the rule
51+
/// Gets or the collection of <see cref="Alternatives"/> defined by the rule
5252
/// </summary>
53-
public string RawRule { get; set; }
53+
public List<Alternatives> Alternatives { get; } = [];
5454
}
5555
}

SysML2.NET.CodeGenerator/Grammar/TextualNotationSpecificationVisitor.cs

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public override object VisitRule_definition(kebnfParser.Rule_definitionContext c
5454
{
5555
RuleName = context.name.Text,
5656
TargetElementName = context.target_ast?.Text,
57-
RawRule = context.GetText()
57+
RawRule = context.GetText().Trim()
5858
};
5959

6060
if (string.IsNullOrWhiteSpace(rule.RuleName))
@@ -71,18 +71,18 @@ public override object VisitRule_definition(kebnfParser.Rule_definitionContext c
7171
};
7272
}
7373

74-
rule.Elements.AddRange((List<RuleElement>)this.Visit(context.rule_body));
74+
rule.Alternatives.AddRange((IEnumerable<Alternatives>)this.Visit(context.rule_body));
7575
return rule;
7676
}
7777

7878
/// <summary>
7979
/// Visit a parse tree produced by <see cref="kebnfParser.AlternativesContext"/>.
8080
/// </summary>
8181
/// <param name="context">The parse tree.</param>
82-
/// <return>The visitor result, as a collection of <see cref="RuleElement" /></return>
82+
/// <return>The visitor result, as an <see cref="Alternatives"/></return>
8383
public override object VisitAlternatives(kebnfParser.AlternativesContext context)
8484
{
85-
return context.alternative().Select(a => (Alternatives)this.Visit(a)).SelectMany(x => x.Elements.Where(e => e!=null)).ToList();
85+
return context.alternative().Select(a => (Alternatives)this.Visit(a));
8686
}
8787

8888
/// <summary>
@@ -93,7 +93,7 @@ public override object VisitAlternatives(kebnfParser.AlternativesContext context
9393
public override object VisitAlternative(kebnfParser.AlternativeContext context)
9494
{
9595
var alternatives = new Alternatives();
96-
alternatives.Elements.AddRange(context.element().Select(e => (RuleElement)this.Visit(e)));
96+
alternatives.Elements.AddRange(context.element().Select(e => (RuleElement)this.Visit(e)).Where(x => x != null));
9797
return alternatives;
9898
}
9999

@@ -106,7 +106,7 @@ public override object VisitAssignment(kebnfParser.AssignmentContext context)
106106
{
107107
return new AssignmentElement()
108108
{
109-
Property = context.property.GetText(),
109+
Property = context.property.GetText().Split(".")[^1],
110110
Operator = context.op.Text,
111111
Suffix = context.suffix?.GetText(),
112112
Value = (RuleElement)this.Visit(context.content),
@@ -131,10 +131,6 @@ public override object VisitNon_parsing_assignment(kebnfParser.Non_parsing_assig
131131

132132
/// <summary>
133133
/// Visit a parse tree produced by <see cref="kebnfParser.value_literal"/>.
134-
/// <para>
135-
/// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
136-
/// on <paramref name="context"/>.
137-
/// </para>
138134
/// </summary>
139135
/// <param name="context">The parse tree.</param>
140136
/// <return>The visitor result.</return>
@@ -153,12 +149,13 @@ public override object VisitValue_literal(kebnfParser.Value_literalContext conte
153149
/// <return>The visitor result, as <see cref="GroupElement"/>.</return>
154150
public override object VisitGroup(kebnfParser.GroupContext context)
155151
{
156-
var group = new GroupElement()
152+
var group = new GroupElement
157153
{
158154
Suffix = context.suffix?.GetText(),
159155
};
156+
157+
group.Alternatives.AddRange((IEnumerable<Alternatives>)this.Visit(context.alternatives()));
160158

161-
group.Elements.AddRange((List<RuleElement>)this.Visit(context.alternatives()));
162159
return group;
163160
}
164161

@@ -189,16 +186,5 @@ public override object VisitNon_terminal(kebnfParser.Non_terminalContext context
189186
Suffix = context.suffix?.GetText()
190187
};
191188
}
192-
193-
/// <summary>
194-
/// Provides mapping data class for the alternative grammar part
195-
/// </summary>
196-
private class Alternatives
197-
{
198-
/// <summary>
199-
/// Gets a collection of <see cref="RuleElement" /> that is part of the <see cref="Alternatives" />
200-
/// </summary>
201-
public List<RuleElement> Elements { get; } = [];
202-
}
203189
}
204190
}

SysML2.NET.CodeGenerator/HandleBarHelpers/NamedElementHelper.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ public static void RegisterNamedElementHelper(this IHandlebars handlebars)
5252

5353
writer.WriteSafeString(namedElement.QueryNamespace());
5454
});
55+
56+
handlebars.RegisterHelper("NamedElement.WriteFullyQualifiedTypeName", (writer, _, arguments) =>
57+
{
58+
if (arguments[0] is not INamedElement namedElement)
59+
{
60+
throw new ArgumentException("supposed to be INamedElement");
61+
}
62+
63+
writer.WriteSafeString(namedElement.QueryFullyQualifiedTypeName());
64+
});
5565
}
5666
}
5767
}

0 commit comments

Comments
 (0)