@@ -106,14 +106,18 @@ private List<EnumTypeMember> BuildApiVersionEnumValuesForBackwardCompatibility(L
106106 return currentApiVersions ;
107107 }
108108
109- var currentVersionNames = new HashSet < string > ( currentApiVersions . Select ( v => v . Name ) , StringComparer . OrdinalIgnoreCase ) ;
109+ var currentVersionsLookup = currentApiVersions . ToDictionary ( v => v . Name , StringComparer . OrdinalIgnoreCase ) ;
110110 var allMembers = new List < EnumTypeMember > ( currentApiVersions . Count + lastContractFields . Count ) ;
111- allMembers . AddRange ( currentApiVersions ) ;
112-
113111 bool addedPreviousApiVersion = false ;
112+
113+ // First, add all missing backward compatibility versions in their original order
114114 foreach ( var field in lastContractFields )
115115 {
116- if ( ! currentVersionNames . Contains ( field . Name ) )
116+ if ( currentVersionsLookup . TryGetValue ( field . Name , out var existingMember ) )
117+ {
118+ allMembers . Add ( existingMember ) ;
119+ }
120+ else
117121 {
118122 var ( versionPrefix , versionSeparator ) = ExtractVersionFormatInfo ( field . Name , currentApiVersions ) ;
119123 string enumValue = field . Name . ToApiVersionValue ( versionPrefix , versionSeparator ) ;
@@ -127,7 +131,15 @@ private List<EnumTypeMember> BuildApiVersionEnumValuesForBackwardCompatibility(L
127131 return currentApiVersions ;
128132 }
129133
130- SortApiVersions ( allMembers ) ;
134+ var processedNames = new HashSet < string > ( lastContractFields . Select ( f => f . Name ) , StringComparer . OrdinalIgnoreCase ) ;
135+ // Then, add new versions in the wire order
136+ foreach ( var currentVersion in currentApiVersions )
137+ {
138+ if ( ! processedNames . Contains ( currentVersion . Name ) )
139+ {
140+ allMembers . Add ( currentVersion ) ;
141+ }
142+ }
131143
132144 for ( int i = 0 ; i < allMembers . Count ; i ++ )
133145 {
@@ -145,59 +157,6 @@ private List<EnumTypeMember> BuildApiVersionEnumValuesForBackwardCompatibility(L
145157 return allMembers ;
146158 }
147159
148- private static void SortApiVersions ( List < EnumTypeMember > allMembers )
149- {
150- allMembers . Sort ( ( x , y ) =>
151- {
152- // Extract base names and version types
153- var ( xBase , xType , xPrereleaseNumber ) = ParseVersionInfo ( x . Name ) ;
154- var ( yBase , yType , yPreReleaseNumber ) = ParseVersionInfo ( y . Name ) ;
155-
156- // First compare base names
157- int baseComparison = string . Compare ( xBase , yBase , StringComparison . OrdinalIgnoreCase ) ;
158- if ( baseComparison != 0 )
159- {
160- return baseComparison ;
161- }
162-
163- // If base names are equal, and version types are equal, compare prerelease numbers
164- if ( xType == yType )
165- {
166- return xPrereleaseNumber . CompareTo ( yPreReleaseNumber ) ;
167- }
168-
169- return xType . CompareTo ( yType ) ;
170- } ) ;
171-
172- static ( string BaseName , VersionType VersionType , int PrereleaseNumber ) ParseVersionInfo ( string name )
173- {
174- // Common patterns for Beta/Preview versions
175- string [ ] versionIndicators = [ "_Beta" , "_Preview" ] ;
176-
177- foreach ( var indicator in versionIndicators )
178- {
179- int index = name . IndexOf ( indicator , StringComparison . OrdinalIgnoreCase ) ;
180- if ( index >= 0 )
181- {
182- string baseName = name . Substring ( 0 , index ) . Trim ( '_' ) ;
183- return ( baseName , Enum . Parse < VersionType > ( indicator . TrimStart ( '_' ) ) ,
184- int . TryParse ( name . Substring ( index + indicator . Length ) . Trim ( '_' ) , out int prereleaseNumber ) ? prereleaseNumber : 0 ) ;
185- }
186- }
187-
188- // No version indicator found, it's a GA version
189- return ( name , VersionType . GA , 0 ) ;
190- }
191- }
192-
193- private enum VersionType
194- {
195- Beta ,
196- // Beta and Preview should never occur in the same enum, but handle it gracefully
197- Preview ,
198- GA
199- }
200-
201160 private static ( string ? Prefix , char ? Separator ) ExtractVersionFormatInfo ( string previousVersion , List < EnumTypeMember > currentApiVersions )
202161 {
203162 if ( currentApiVersions . Count == 0 )
@@ -206,18 +165,19 @@ private static (string? Prefix, char? Separator) ExtractVersionFormatInfo(string
206165 }
207166
208167 bool previousVersionIsDateFormat = IsDateFormat ( previousVersion ) ;
168+ string ? versionPrefix = null ;
169+ char ? separator = null ;
209170
210171 // validate if any current version is also a date format, if so follow the same format
211172 if ( previousVersionIsDateFormat )
212173 {
213174 EnumTypeMember ? dateFormatVersion = currentApiVersions . FirstOrDefault ( v => v . Value is string apiValue && IsDateFormat ( apiValue ) ) ;
214175 if ( dateFormatVersion ? . Value is string apiValue )
215176 {
216- string ? versionPrefix = apiValue . StartsWith ( "v" , StringComparison . InvariantCultureIgnoreCase )
177+ versionPrefix = apiValue . StartsWith ( "v" , StringComparison . InvariantCultureIgnoreCase )
217178 ? apiValue [ 0 ] . ToString ( )
218179 : null ;
219- char ? separator = ExtractApiVersionSeparator ( apiValue ) ;
220- return ( versionPrefix , separator ) ;
180+ separator = ExtractApiVersionSeparator ( apiValue ) ;
221181 }
222182 }
223183 else
@@ -226,15 +186,26 @@ private static (string? Prefix, char? Separator) ExtractVersionFormatInfo(string
226186 EnumTypeMember ? nonDateVersion = currentApiVersions . FirstOrDefault ( v => v . Value is string apiValue && ! IsDateFormat ( apiValue ) ) ;
227187 if ( nonDateVersion ? . Value is string currentVersionValue )
228188 {
229- string ? versionPrefix = currentVersionValue . StartsWith ( "v" , StringComparison . InvariantCultureIgnoreCase )
189+ versionPrefix = currentVersionValue . StartsWith ( "v" , StringComparison . InvariantCultureIgnoreCase )
230190 ? currentVersionValue [ 0 ] . ToString ( )
231191 : null ;
232- char ? separator = ExtractApiVersionSeparator ( currentVersionValue ) ;
233- return ( versionPrefix , separator ) ;
192+ separator = ExtractApiVersionSeparator ( currentVersionValue ) ;
234193 }
235194 }
236195
237- return ( null , null ) ;
196+ if ( ! previousVersionIsDateFormat && versionPrefix == null && IsSingleDigitVersion ( previousVersion ) )
197+ {
198+ versionPrefix = "v" ;
199+ }
200+
201+ return ( versionPrefix , separator ) ;
202+ }
203+
204+ private static bool IsSingleDigitVersion ( string version )
205+ {
206+ return version . Length == 2
207+ && version . StartsWith ( "v" , StringComparison . InvariantCultureIgnoreCase )
208+ && char . IsDigit ( version [ 1 ] ) ;
238209 }
239210
240211 private static bool IsDateFormat ( string version )
0 commit comments