@@ -19,18 +19,22 @@ public CsProjUpdateResult UpdateCsProjPropertyValues(string csProjFilePath)
19
19
var propertyGroups = csProjXmlDoc . Descendants ( "PropertyGroup" ) . ToList ( ) ;
20
20
21
21
var targetFrameworkUpdates = new CsprojUpdateTracker (
22
- " TargetFramework" ,
22
+ CsprojUpdateTracker . TargetFramework ,
23
23
UpdateOptions . DotNetTargetFramework ,
24
+ addIfElementNotFound : false ,
24
25
skipStartsWithValues : [ "netstandard" ] ) ; //Project is set to .NET Standard are there for a reason, don't change it
25
26
var langUpdates = new CsprojUpdateTracker (
26
- "LangVersion" ,
27
- UpdateOptions . DotNetLangVersion ) ;
27
+ CsprojUpdateTracker . LangVersion ,
28
+ UpdateOptions . DotNetLangVersion ,
29
+ addIfElementNotFound : true ) ;
28
30
var enableNETAnalyzersUpdates = new CsprojUpdateTracker (
29
- "EnableNETAnalyzers" ,
30
- UpdateOptions . EnableNetAnalyzers . ToString ( ) . ToLower ( ) ) ;
31
+ CsprojUpdateTracker . EnableNETAnalyzers ,
32
+ UpdateOptions . EnableNetAnalyzers . ToString ( ) . ToLower ( ) ,
33
+ addIfElementNotFound : true ) ;
31
34
var enforceCodeStyleInBuildUpdates = new CsprojUpdateTracker (
32
- "EnforceCodeStyleInBuild" ,
33
- UpdateOptions . EnforceCodeStyleInBuild . ToString ( ) . ToLower ( ) ) ;
35
+ CsprojUpdateTracker . EnforceCodeStyleInBuild ,
36
+ UpdateOptions . EnforceCodeStyleInBuild . ToString ( ) . ToLower ( ) ,
37
+ addIfElementNotFound : true ) ;
34
38
35
39
UpdateOrAddCsProjValues (
36
40
csProjXmlDoc ,
@@ -55,7 +59,14 @@ private void UpdateOrAddCsProjValues(XDocument csProjXmlDoc, List<XElement> prop
55
59
{
56
60
foreach ( var update in updates )
57
61
{
58
- UpdateCsprojValue ( propertyGroupElement , update ) ;
62
+ if ( update . ElementName == CsprojUpdateTracker . TargetFramework )
63
+ {
64
+ UpdateTargetFrameworkValue ( propertyGroupElement , update ) ;
65
+ }
66
+ else
67
+ {
68
+ UpdateCsprojValue ( propertyGroupElement , update ) ;
69
+ }
59
70
}
60
71
}
61
72
@@ -121,24 +132,97 @@ private void UpdateCsprojValue(XElement childElm, CsprojUpdateTracker updateTrac
121
132
}
122
133
}
123
134
135
+ private void UpdateTargetFrameworkValue ( XElement childElm , CsprojUpdateTracker updateTracker )
136
+ {
137
+ var element = childElm . Element ( CsprojUpdateTracker . TargetFramework ) ;
138
+ if ( string . IsNullOrEmpty ( element ? . Value ) )
139
+ {
140
+ //If there's no TargetFramework, maybe the project has a TargetFrameworks element
141
+ UpdateTargetFrameworksValue ( childElm , updateTracker ) ;
142
+ }
143
+ else if ( string . Equals ( element . Value , updateTracker . NewValue ) )
144
+ {
145
+ updateTracker . SetResults . Add ( CsprojValueUpdateResultType . AlreadyHasCorrectValue ) ;
146
+ }
147
+ else if ( updateTracker . SkipStartsWithValues . Any ( x => element . Value . StartsWith ( x ) ) )
148
+ {
149
+ Logger . Information ( $ "Skipping { updateTracker . ElementName } update because value '{ element . Value } ' starts with one of these: { string . Join ( ", " , updateTracker . SkipStartsWithValues ) } ") ;
150
+ updateTracker . SetResults . Add ( CsprojValueUpdateResultType . HasSkipValue ) ;
151
+ }
152
+ else
153
+ {
154
+ Logger . Information ( $ "Updating { updateTracker . ElementName } from '{ element . Value } ' to '{ updateTracker . NewValue } '") ;
155
+ element . Value = updateTracker . NewValue ;
156
+
157
+ updateTracker . SetResults . Add ( CsprojValueUpdateResultType . Updated ) ;
158
+ }
159
+ }
160
+
161
+ private void UpdateTargetFrameworksValue ( XElement childElm , CsprojUpdateTracker updateTracker )
162
+ {
163
+ //TargetFrameworks can appear multiple times in a csproj file, so we need to update all of them
164
+ var elements = childElm . Elements ( CsprojUpdateTracker . TargetFrameworks ) ;
165
+ if ( ! elements . Any ( ) )
166
+ {
167
+ updateTracker . SetResults . Add ( CsprojValueUpdateResultType . NotFound ) ;
168
+ return ;
169
+ }
170
+
171
+ foreach ( var element in elements )
172
+ {
173
+ //TargetFrameworks are a string like "net8.0-android;net8.0-ios;"
174
+ //We want to update the first part of the string, so we need to split on the dash
175
+ var newElementString = "" ;
176
+ var existingValues = element . Value . Split ( ";" ) ;
177
+ foreach ( var existingValue in existingValues )
178
+ {
179
+ var split = existingValue . Split ( "-" ) ;
180
+ if ( split . Length == 2 )
181
+ {
182
+ newElementString += $ "{ updateTracker . NewValue } -{ split [ 1 ] } ;";
183
+ }
184
+ else
185
+ {
186
+ //As a just in case, just add the existing value and don't make any changes
187
+ newElementString += $ "{ existingValue } ;";
188
+ }
189
+ }
190
+
191
+ newElementString = newElementString . TrimEnd ( ';' ) ; //Remove the last semicolon
192
+
193
+ Logger . Information ( $ "Updating { updateTracker . ElementName } from '{ element . Value } ' to '{ newElementString } '") ;
194
+ element . Value = newElementString ;
195
+
196
+ updateTracker . SetResults . Add ( CsprojValueUpdateResultType . Updated ) ;
197
+ }
198
+ }
199
+
124
200
public class CsprojUpdateTracker
125
201
{
126
- public CsprojUpdateTracker ( string elementName , string newValue )
127
- : this ( elementName , newValue , ImmutableArray < string > . Empty )
202
+ public const string TargetFramework = "TargetFramework" ;
203
+ public const string TargetFrameworks = "TargetFrameworks" ;
204
+ public const string LangVersion = "LangVersion" ;
205
+ public const string EnableNETAnalyzers = "EnableNETAnalyzers" ;
206
+ public const string EnforceCodeStyleInBuild = "EnforceCodeStyleInBuild" ;
207
+
208
+ public CsprojUpdateTracker ( string elementName , string newValue , bool addIfElementNotFound )
209
+ : this ( elementName , newValue , addIfElementNotFound , ImmutableArray < string > . Empty )
128
210
{
129
211
}
130
212
131
- public CsprojUpdateTracker ( string elementName , string newValue , ImmutableArray < string > skipStartsWithValues )
213
+ public CsprojUpdateTracker ( string elementName , string newValue , bool addIfElementNotFound , ImmutableArray < string > skipStartsWithValues )
132
214
{
133
215
ElementName = elementName ;
134
216
NewValue = newValue ;
135
217
SkipStartsWithValues = skipStartsWithValues ;
218
+ AddIfElementNotFound = addIfElementNotFound ;
136
219
SetResults = new List < CsprojValueUpdateResultType > ( ) ;
137
220
}
138
221
139
222
public string ElementName { get ; }
140
223
public string NewValue { get ; }
141
224
public ImmutableArray < string > SkipStartsWithValues { get ; }
225
+ public bool AddIfElementNotFound { get ; }
142
226
143
227
public List < CsprojValueUpdateResultType > SetResults { get ; }
144
228
@@ -160,7 +244,7 @@ public CsprojValueUpdateResultType GetFinalResult()
160
244
161
245
public bool ShouldAddElement ( )
162
246
{
163
- return SetResults . All ( x => x == CsprojValueUpdateResultType . NotFound ) ;
247
+ return AddIfElementNotFound && SetResults . All ( x => x == CsprojValueUpdateResultType . NotFound ) ;
164
248
}
165
249
}
166
250
}
0 commit comments