1
+ <Project >
2
+
3
+ <!-- Code Generation -->
4
+
5
+ <PropertyGroup Condition =" '$(MSBuildRuntimeType)' != 'Core'" >
6
+ <RoslynCodeTaskFactoryAssembly Condition =" '$(RoslynCodeTaskFactoryAssembly)' == ''" >$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll</RoslynCodeTaskFactoryAssembly >
7
+ </PropertyGroup >
8
+
9
+ <UsingTask TaskName =" UpdateCurrentDirectoryInSource"
10
+ TaskFactory =" RoslynCodeTaskFactory"
11
+ AssemblyFile =" $(RoslynCodeTaskFactoryAssembly)"
12
+ Condition =" '$(MSBuildRuntimeType)' != 'Core'" >
13
+ <Task >
14
+ <Using Namespace =" System" />
15
+ <Using Namespace =" System.IO" />
16
+ <Using Namespace =" System.Text.RegularExpressions" />
17
+ <Code Type =" Fragment" Language =" cs" >
18
+ <![CDATA[
19
+ // Find project directory
20
+ DirectoryInfo currentDir = new DirectoryInfo(Environment.CurrentDirectory);
21
+ DirectoryInfo projectDir = currentDir;
22
+ while (projectDir != null)
23
+ {
24
+ bool isInProjectDir = projectDir.EnumerateFiles("*.csproj", SearchOption.TopDirectoryOnly).Any();
25
+ if (isInProjectDir)
26
+ break;
27
+
28
+ projectDir = projectDir.Parent;
29
+ }
30
+
31
+ if (projectDir == null)
32
+ {
33
+ Log.LogMessage(MessageImportance.High, "Project directory not found.");
34
+ return false;
35
+ }
36
+
37
+ // Find all the Program.cs files in the project directory
38
+ var programCsFiles =
39
+ projectDir
40
+ .EnumerateFiles("Program.cs", SearchOption.AllDirectories)
41
+ .Where(fi => fi.Directory.FullName != projectDir.FullName)
42
+ .ToArray();
43
+ if (programCsFiles.Length == 0)
44
+ {
45
+ Log.LogMessage(MessageImportance.High, "No Program.cs files found in the project directory.");
46
+ return false;
47
+ }
48
+
49
+ // Update the "Environment.CurrentDirectory = " with the directory name
50
+ foreach (var programCsFile in programCsFiles)
51
+ {
52
+ var cs = File.ReadAllText(programCsFile.FullName);
53
+ var dir = programCsFile.Directory.Name;
54
+ var csNew = Regex.Replace(
55
+ cs,
56
+ "SetCurrentDirectory\\s*\\(.*;",
57
+ "SetCurrentDirectory(Path.Combine(InitialCurrentDirectory, \"" + dir + "\"));");
58
+ if (cs != csNew)
59
+ {
60
+ File.WriteAllText(programCsFile.FullName, csNew);
61
+ Log.LogMessage(MessageImportance.High, "Updated CurrentDirectory in " + programCsFile.FullName);
62
+ }
63
+ }
64
+ ]]>
65
+ </Code >
66
+ </Task >
67
+ </UsingTask >
68
+
69
+ <UsingTask TaskName =" UpdateLaunchSettingsInSource"
70
+ TaskFactory =" RoslynCodeTaskFactory"
71
+ AssemblyFile =" $(RoslynCodeTaskFactoryAssembly)"
72
+ Condition =" '$(MSBuildRuntimeType)' != 'Core'" >
73
+ <Task >
74
+ <!-- System.Memory is needed for ReadOnlySpan<> -->
75
+ <Reference Include =" System.Memory" />
76
+ <Reference Include =" System.Text.Json" />
77
+ <Using Namespace =" System" />
78
+ <Using Namespace =" System.Text.Json" />
79
+ <Using Namespace =" System.Text.Json.Nodes" />
80
+ <Using Namespace =" System.Text.RegularExpressions" />
81
+ <Code Type =" Fragment" Language =" cs" >
82
+ <![CDATA[
83
+ // Find project directory
84
+ DirectoryInfo currentDir = new DirectoryInfo(Environment.CurrentDirectory);
85
+ DirectoryInfo projectDir = currentDir;
86
+ while (projectDir != null)
87
+ {
88
+ bool isInProjectDir = projectDir.EnumerateFiles("*.csproj", SearchOption.TopDirectoryOnly).Any();
89
+ if (isInProjectDir)
90
+ break;
91
+
92
+ projectDir = projectDir.Parent;
93
+ }
94
+
95
+ if (projectDir == null)
96
+ {
97
+ Log.LogMessage(MessageImportance.High, "Project directory not found.");
98
+ return false;
99
+ }
100
+
101
+ var mainProgramText = File.ReadAllText(Path.Combine(projectDir.FullName, "Program.cs"));
102
+ var regexIndent = new Regex(
103
+ @"//\s<codegen-switch>.*?(?<indent>(\r?\n)[ \t]+)//\s</codegen-switch>",
104
+ RegexOptions.Singleline);
105
+
106
+ var matchIndent = regexIndent.Match(mainProgramText);
107
+ string indent = matchIndent.Groups["indent"].Value;
108
+ StringBuilder sb = new StringBuilder();
109
+ sb.Append("// <codegen-switch>");
110
+ sb.Append(indent + "switch (code)");
111
+ sb.Append(indent + "{");
112
+
113
+ // Find all the folders in the project directory, starting with a number
114
+ var exampleDirs =
115
+ projectDir
116
+ .EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
117
+ .Where(di => Char.IsNumber(di.Name[0]))
118
+ .ToArray();
119
+ if (exampleDirs.Length == 0)
120
+ {
121
+ Log.LogMessage(MessageImportance.High, "No example dirs found in the project directory.");
122
+ return false;
123
+ }
124
+
125
+ var launchSettingsJsonPath = Path.Combine(projectDir.FullName, "Properties", "launchSettings.json");
126
+ var launchSettingsJsonText = File.ReadAllText(launchSettingsJsonPath);
127
+ var launchSettingsJsonRoot = JsonSerializer.Deserialize<JsonObject>(launchSettingsJsonText);
128
+ var profiles = launchSettingsJsonRoot["profiles"].AsObject();
129
+ profiles.Clear();
130
+ foreach (var exampleDir in exampleDirs)
131
+ {
132
+ var tokens = exampleDir.Name.Split(' ');
133
+ if (tokens.Length <= 1)
134
+ continue;
135
+ var code = tokens[0];
136
+
137
+ string programFilePath = Path.Combine(exampleDir.FullName, "Program.cs");
138
+ if (!File.Exists(programFilePath))
139
+ continue;
140
+
141
+ var programFile = File.ReadAllText(programFilePath);
142
+ var match = Regex.Match(
143
+ programFile,
144
+ @"(?:partial\s+class\s+Program\s+{\s+void\s+)(?<method>\w+)(?:\s*\()");
145
+ if (!match.Success)
146
+ continue;
147
+
148
+ var methodName = match.Groups["method"].Value;
149
+
150
+ sb.Append(indent + @" case """ + code + @""": " + methodName + "(); return;");
151
+
152
+ var profile = new JsonObject();
153
+ profile.Add("commandName", "Project");
154
+ profile.Add("commandLineArgs", code);
155
+ profiles.Add(exampleDir.Name, profile);
156
+ }
157
+
158
+ sb.Append(indent + "}");
159
+ sb.Append(indent + "// </codegen-switch>");
160
+ var mainProgramTextNew = regexIndent.Replace(mainProgramText, sb.ToString());
161
+ if (mainProgramText != mainProgramTextNew)
162
+ File.WriteAllText(Path.Combine(projectDir.FullName, "Program.cs"), mainProgramTextNew);
163
+
164
+ var launchSettingsJsonTextNew = JsonSerializer.Serialize(launchSettingsJsonRoot, new JsonSerializerOptions() { WriteIndented = true } );
165
+ if (launchSettingsJsonText != launchSettingsJsonTextNew)
166
+ File.WriteAllText(launchSettingsJsonPath, launchSettingsJsonTextNew);
167
+ ]]>
168
+ </Code >
169
+
170
+ </Task >
171
+ </UsingTask >
172
+
173
+ <Target Name =" ModifySources"
174
+ BeforeTargets =" CoreCompile"
175
+ Condition =" '$(MSBuildRuntimeType)' != 'Core'" >
176
+ <UpdateCurrentDirectoryInSource />
177
+ <UpdateLaunchSettingsInSource />
178
+ </Target >
179
+
180
+ <!-- Code Generation -->
181
+
182
+ </Project >
0 commit comments