Skip to content

Commit 51b5d9b

Browse files
CopilotbaseTwo
andcommitted
Extract shared code generation tasks into reusable .targets file
Co-authored-by: baseTwo <[email protected]>
1 parent affdf81 commit 51b5d9b

File tree

3 files changed

+186
-342
lines changed

3 files changed

+186
-342
lines changed

Examples/CqlSdkExamples.targets

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
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>

Examples/CqlSdkExamples/CqlSdkExamples.csproj

Lines changed: 1 addition & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -33,182 +33,7 @@
3333
</ItemGroup>
3434

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

21439
</Project>

0 commit comments

Comments
 (0)