Skip to content

Commit e5bb07e

Browse files
authored
Merge pull request #14 from MORYX-Industry/feature/rework-step-and-states-creation
A step is now considered to live in a dedicated Resource package: Creating a step Soldering would create a package <project>.Resources.Soldering and put all related resource files into that project. States are considered to be added for a certain context, usually a resource. When a context is found (as provided by moryx add states <CONTEXT>), all provided states and a <Context>StateBase will be created inside a States folder next to the file which contains the given context.
2 parents dfcd5dc + 1637c35 commit e5bb07e

38 files changed

+782
-183
lines changed

.github/workflows/.build-and-publish.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@ jobs:
7575
with:
7676
dotnet-version: ${{ needs.Variables.outputs.dotnet_sdk_version }}
7777

78-
- name: ♺ Execute nuget restore
79-
run: nuget restore
80-
if: steps.cache-nuget.outputs.cache-hit != 'true'
81-
8278
- name: 🧰 Setup BuildToolkit
8379
uses: moryx-industry/setup-buildtoolkit@v1
8480

81+
- name: ♺ Execute nuget restore
82+
run: dotnet restore
83+
if: steps.cache-nuget.outputs.cache-hit != 'true'
84+
8585
- name: 🔨 Execute dotnet build
8686
run: |
8787
.\set-version.ps1 -RefName ${{ github.ref_name }} -IsTag ${{ github.ref_type == 'tag' && 1 || 0 }} -BuildNumber ${{ github.run_number }} -CommitHash ${{ github.sha }}

Moryx.Cli.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt
2020
Directory.Build.targets = Directory.Build.targets
2121
EndProjectSection
2222
EndProject
23+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moryx.Cli.Commands.Tests", "src\Tests\Moryx.Cli.Commands.Tests\Moryx.Cli.Commands.Tests.csproj", "{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}"
24+
EndProject
2325
Global
2426
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2527
Debug|Any CPU = Debug|Any CPU
@@ -46,12 +48,17 @@ Global
4648
{F6E69A2A-F183-4A01-8629-CEBBB0417ED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
4749
{F6E69A2A-F183-4A01-8629-CEBBB0417ED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
4850
{F6E69A2A-F183-4A01-8629-CEBBB0417ED6}.Release|Any CPU.Build.0 = Release|Any CPU
51+
{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52+
{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}.Debug|Any CPU.Build.0 = Debug|Any CPU
53+
{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}.Release|Any CPU.ActiveCfg = Release|Any CPU
54+
{4C082129-3A6D-4A72-80DC-8A9D3A71A79F}.Release|Any CPU.Build.0 = Release|Any CPU
4955
EndGlobalSection
5056
GlobalSection(SolutionProperties) = preSolution
5157
HideSolutionNode = FALSE
5258
EndGlobalSection
5359
GlobalSection(NestedProjects) = preSolution
5460
{E65D2591-A889-4F42-A6F5-AECAFB77DBB0} = {6FC4CD2F-8BFA-4EC1-84A9-D3670BA92E4D}
61+
{4C082129-3A6D-4A72-80DC-8A9D3A71A79F} = {6FC4CD2F-8BFA-4EC1-84A9-D3670BA92E4D}
5562
EndGlobalSection
5663
GlobalSection(ExtensibilityGlobals) = postSolution
5764
SolutionGuid = {99BD1616-551D-473A-A6DB-6A9C0F030AB7}

NuGet.Config

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageRestore>
4+
<!-- Allow NuGet to download missing packages -->
5+
<add key="enabled" value="True" />
6+
7+
<!-- Automatically check for missing packages during build in Visual Studio -->
8+
<add key="automatic" value="True" />
9+
</packageRestore>
10+
11+
<packageSources>
12+
<clear />
13+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
14+
</packageSources>
15+
</configuration>

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,31 @@ Adds a product 'name'
2424

2525
moryx add product <NAME>
2626

27+
28+
## `add state`
29+
30+
Adds a 'state machine' to a specified context. It adds a folder `States` next
31+
to the file that contains the context including a `StateBase` and `State` files
32+
for each provided state. The context will be updated to implement `IStateContext`.
33+
34+
Adding further states later is possible and would add the new states and update
35+
the existing `StateBase` accordingly.
36+
37+
_Note_: Adding states to the `States` folder may lead conflicts if you try to
38+
create states for several contexts that live inside the same path. We recommend
39+
to move those 'to be contexts' to separate directories or libraries before
40+
adding state machines in order to maintain a clean project structure.
41+
42+
43+
### Usage
44+
45+
moryx add states <CONTEXT> --states <Comma separated list of states>
46+
47+
Example
48+
49+
moryx add states AssemblingCell --states "Initialing, Running, Testing"
50+
51+
2752

2853
## `add step`
2954

myget.feeds

Whitespace-only changes.

src/Moryx.Cli.Commands/AddResources.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,27 @@ public static class AddResources
99
public static CommandResult Exec(TemplateSettings settings, IEnumerable<string> resources)
1010
{
1111
return CommandBase.Exec(settings, (filenames)
12-
=> resources.Select(resource => AddThing.Exec(
13-
settings,
14-
new AddConfig
12+
=> resources.Select(resource =>
13+
{
14+
var addConfig = new AddConfig
1515
{
1616
SolutionName = settings.AppName,
1717
ThingName = $"{resource}Resource",
1818
Thing = "resource",
19-
ThingPlaceholders =
19+
ThingPlaceholders =
2020
[
21-
Template.Template.ResourcePlaceholder,
21+
Template.Template.ResourcePlaceholder,
2222
Template.Template.ResourcePlaceholder2
2323
],
24-
},
25-
filenames.Resource()
26-
))
27-
.ToArray()
28-
.Flatten());
24+
};
25+
return AddThing.Exec(
26+
settings,
27+
addConfig,
28+
filenames.Resource()
29+
);
30+
})
31+
.ToArray()
32+
.Flatten());
2933
}
3034
}
3135
}

src/Moryx.Cli.Commands/AddStates.cs

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using Moryx.Cli.Template.StateBaseTemplate;
55
using Moryx.Cli.Template.Exceptions;
66
using Moryx.Cli.Template.StateTemplate;
7+
using Moryx.Cli.Template.Components;
8+
using Moryx.AbstractionLayer.Resources;
79

810
namespace Moryx.Cli.Commands
911
{
@@ -19,16 +21,17 @@ internal static CommandResult Exec(TemplateSettings settings, string resource, I
1921

2022
private static CommandResult Add(TemplateSettings settings, List<string> cleanedResourceNames, string resource, IEnumerable<string> states)
2123
{
22-
if (!ResourceExists(settings, resource))
24+
var resourceFile = FindResource(settings, resource);
25+
if (string.IsNullOrEmpty(resourceFile))
2326
{
24-
return CommandResult.WithError($"Resource `{resource}` not found. Make sure that a `{resource}.cs` exists in the project.");
27+
return CommandResult.WithError($"`{resource}` not found. Make sure that a type `{resource}` exists in the project.");
2528
}
2629

2730
var projectFileNames = cleanedResourceNames.InitialProjects();
28-
var StateBaseFileName = cleanedResourceNames.StateBaseFile();
31+
var stateBaseFileName = cleanedResourceNames.StateBaseFile();
2932

30-
var dictionary = Template.Template.PrepareFileStructure(settings.AppName, StateBaseFileName, projectFileNames);
31-
var targetPath = Path.Combine(settings.TargetDirectory, "src", $"{settings.AppName}.Resources", resource);
33+
var dictionary = Template.Template.PrepareFileStructure(settings.AppName, stateBaseFileName, projectFileNames);
34+
var targetPath = Path.Combine(Path.GetDirectoryName(resourceFile)!, "States");
3235
var newStateBaseFileName = Path.Combine(targetPath, $"{resource}StateBase.cs");
3336

3437
if (!File.Exists(newStateBaseFileName))
@@ -44,13 +47,14 @@ private static CommandResult Add(TemplateSettings settings, List<string> cleaned
4447
{
4548
{ Template.Template.AppPlaceholder, settings.AppName },
4649
{ Template.Template.StateBasePlaceholder, $"{resource}StateBase" },
50+
{ Template.Template.CellPlaceholder, $"{resource}" },
4751
{ Template.Template.ResourcePlaceholder, resource },
4852
});
4953

50-
if(!states.Any())
54+
if (!states.Any())
5155
{
52-
states =
53-
[
56+
states =
57+
[
5458
"Idle",
5559
"ReadyToWork",
5660
"Running",
@@ -92,6 +96,7 @@ private static CommandResult Add(TemplateSettings settings, List<string> cleaned
9296
{ Template.Template.AppPlaceholder, settings.AppName },
9397
{ Template.Template.StatePlaceholder, stateType },
9498
{ Template.Template.ResourcePlaceholder, resource },
99+
{ Template.Template.CellPlaceholder, resource },
95100
{ Template.Template.StateBasePlaceholder, $"{resource}StateBase" },
96101
});
97102

@@ -114,7 +119,7 @@ private static CommandResult Add(TemplateSettings settings, List<string> cleaned
114119

115120
UpdateResource(
116121
settings,
117-
resource,
122+
resource,
118123
success => msg.Add(success),
119124
warning => warnings.Add(warning));
120125

@@ -123,51 +128,69 @@ private static CommandResult Add(TemplateSettings settings, List<string> cleaned
123128

124129
private static void UpdateResource(TemplateSettings settings, string resource, Action<string> onSuccess, Action<string> onWarning)
125130
{
126-
var dir = Path.Combine(settings.TargetDirectory, "src", $"{settings.AppName}.Resources");
127-
var files = Directory.GetFiles(
128-
dir,
129-
$"{resource}.cs",
130-
new EnumerationOptions
131-
{
132-
ReturnSpecialDirectories = false,
133-
RecurseSubdirectories = true
134-
});
135-
if(files.Length == 0)
136-
{
137-
onWarning($"Filename `{resource}.cs` not found. Could not update resource.");
138-
return;
139-
}
140-
if (files.Length > 1)
131+
var candidate = FindResource(settings, resource);
132+
133+
if (string.IsNullOrEmpty(candidate))
141134
{
142-
onWarning($"Filename `{resource}.cs` is ambiguous. Could not update resource.");
135+
onWarning($"Type `{resource}` not found. Could not update resource.");
143136
return;
144137
}
145-
var filename = files.Single();
146138

147139
try
148140
{
149-
var template = StateTemplate.FromFile(filename);
150-
template = template.ImplementIStateContext(resource);
151-
template.SaveToFile(filename);
152-
onSuccess($"Updated `{resource}.cs`");
141+
var template = StateTemplate.FromFile(candidate);
142+
template = template.ImplementIStateContext(resource);
143+
template.SaveToFile(candidate);
144+
onSuccess($"Updated `{Path.GetFileName(candidate)}`");
153145
}
154146
catch (Exception)
155147
{
156-
onWarning($"Failed to update `{resource}.cs`");
148+
onWarning($"Failed to update `{Path.GetFileName(candidate)}`");
157149
}
158150
}
159151

160-
private static bool ResourceExists(TemplateSettings settings, string resource)
152+
private static string FindResource(TemplateSettings settings, string resourceName)
161153
{
154+
var dir = Path.Combine(settings.TargetDirectory, "src");
162155
var files = Directory.GetFiles(
163-
Path.Combine(settings.TargetDirectory),
164-
$"{resource}.cs",
156+
dir,
157+
$"*.cs",
165158
new EnumerationOptions
166159
{
167160
ReturnSpecialDirectories = false,
168161
RecurseSubdirectories = true
169-
});
170-
return files.Length > 0;
162+
})
163+
.AsEnumerable();
164+
165+
var promisingCandidate = files.FirstOrDefault(f => f.EndsWith($"{resourceName}.cs"));
166+
if (!string.IsNullOrEmpty(promisingCandidate))
167+
{
168+
files = files.Prepend(promisingCandidate);
169+
}
170+
171+
var candidate = string.Empty;
172+
foreach (var file in files)
173+
{
174+
if (ContainsType(file, resourceName))
175+
{
176+
candidate = file;
177+
break;
178+
}
179+
}
180+
return candidate;
181+
}
182+
183+
private static bool ContainsType(string filename, string typeName)
184+
{
185+
try
186+
{
187+
var file = CSharpFile.FromFile(filename);
188+
return file.Types.Any(t => t == typeName);
189+
}
190+
catch
191+
{
192+
return false;
193+
}
171194
}
172195
}
173196
}

src/Moryx.Cli.Commands/AddStep.cs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,49 @@
1-
using Moryx.Cli.Template;
1+
using Microsoft.Build.Construction;
2+
using Microsoft.CodeAnalysis;
3+
using Microsoft.CodeAnalysis.MSBuild;
4+
using Moryx.Cli.Commands.Components;
5+
using Moryx.Cli.Template;
26
using Moryx.Cli.Template.Models;
7+
using Moryx.Configuration;
8+
using System.Diagnostics;
39

410
namespace Moryx.Cli.Commands
511
{
612
public static class AddStep
713
{
814
public static CommandResult Exec(TemplateSettings settings, string step)
915
{
10-
return CommandBase.Exec(settings, (filenames)
11-
=> AddThing.Exec(
16+
return CommandBase.Exec(settings, (filenames) =>
17+
{
18+
var addConfig = new AddConfig
19+
{
20+
SolutionName = settings.AppName,
21+
ThingName = step,
22+
Thing = "step",
23+
ThingPlaceholders = [Template.Template.StepPlaceholder],
24+
};
25+
var namespacePlaceholder = new Dictionary<string, string> {
26+
27+
{ $"{Template.Template.AppPlaceholder}.Resources", $"{settings.AppName}.Resources.{step}" },
28+
{ $"{settings.AppName}.Resources", $"{settings.AppName}.Resources.{step}" }
29+
};
30+
var replacements = new StringReplacements(addConfig)
31+
.AddFileNamePatterns(namespacePlaceholder)
32+
.AddContentPatterns(namespacePlaceholder)
33+
;
34+
35+
return AddThing.Exec(
1236
settings,
13-
new AddConfig
37+
addConfig,
38+
filenames.Step(),
39+
(createdFiles) =>
1440
{
15-
SolutionName = settings.AppName,
16-
ThingName = step,
17-
Thing = "step",
18-
ThingPlaceholders = [Template.Template.StepPlaceholder],
41+
var projectFileName = createdFiles.FirstOrDefault(f => f.EndsWith(".csproj"));
42+
SolutionFileManipulation.AddProjectToSolution(settings, projectFileName);
1943
},
20-
filenames.Step()
21-
));
44+
replacements
45+
);
46+
});
2247
}
2348
}
2449
}

src/Moryx.Cli.Commands/AddSteps.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,9 @@ public static class AddSteps
99
public static CommandResult Exec(TemplateSettings settings, IEnumerable<string> cells)
1010
{
1111
return CommandBase.Exec(settings, (filenames)
12-
=> cells.Select(step => AddThing.Exec(
12+
=> cells.Select(step => AddStep.Exec(
1313
settings,
14-
new AddConfig
15-
{
16-
SolutionName = settings.AppName,
17-
ThingName = step,
18-
Thing = "step",
19-
ThingPlaceholders = [Template.Template.StepPlaceholder],
20-
},
21-
filenames.Step()
14+
step
2215
))
2316
.ToArray()
2417
.Flatten());

0 commit comments

Comments
 (0)