@@ -52,6 +52,8 @@ public enum ILNameSyntax
5252
5353 public static class DisassemblerHelpers
5454 {
55+ static readonly char [ ] _validNonLetterIdentifierCharacter = new char [ ] { '_' , '$' , '@' , '?' , '`' , '.' } ;
56+
5557 public static string OffsetToString ( int offset )
5658 {
5759 return string . Format ( "IL_{0:x4}" , offset ) ;
@@ -104,39 +106,39 @@ static string ToInvariantCultureString(object value)
104106 }
105107
106108 static bool IsValidIdentifierCharacter ( char c )
107- {
108- return c == '_' || c == '$' || c == '@' || c == '?' || c == '`' ;
109- }
109+ => char . IsLetterOrDigit ( c ) || _validNonLetterIdentifierCharacter . IndexOf ( c ) >= 0 ;
110110
111111 static bool IsValidIdentifier ( string identifier )
112112 {
113113 if ( string . IsNullOrEmpty ( identifier ) )
114114 return false ;
115- if ( ! ( char . IsLetter ( identifier [ 0 ] ) || IsValidIdentifierCharacter ( identifier [ 0 ] ) ) )
116- {
117- // As a special case, .ctor and .cctor are valid despite starting with a dot
115+
116+ if ( char . IsDigit ( identifier [ 0 ] ) )
117+ return false ;
118+
119+ // As a special case, .ctor and .cctor are valid despite starting with a dot
120+ if ( identifier [ 0 ] == '.' )
118121 return identifier == ".ctor" || identifier == ".cctor" ;
119- }
120- for ( int i = 1 ; i < identifier . Length ; i ++ )
121- {
122- if ( ! ( char . IsLetterOrDigit ( identifier [ i ] ) || IsValidIdentifierCharacter ( identifier [ i ] ) || identifier [ i ] == '.' ) )
123- return false ;
124- }
125- return true ;
122+
123+ if ( identifier . Contains ( ".." ) )
124+ return false ;
125+
126+ if ( Metadata . ILOpCodeExtensions . ILKeywords . Contains ( identifier ) )
127+ return false ;
128+
129+ return identifier . All ( IsValidIdentifierCharacter ) ;
126130 }
127131
128132 public static string Escape ( string identifier )
129133 {
130- if ( IsValidIdentifier ( identifier ) && ! Metadata . ILOpCodeExtensions . ILKeywords . Contains ( identifier ) )
134+ if ( IsValidIdentifier ( identifier ) )
131135 {
132136 return identifier ;
133137 }
134- else
135- {
136- // The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence,
137- // but we follow Microsoft's ILDasm and use \'.
138- return "'" + EscapeString ( identifier ) . Replace ( "'" , "\\ '" ) + "'" ;
139- }
138+
139+ // The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence,
140+ // but we follow Microsoft's ILDasm and use \'.
141+ return $ "'{ EscapeString ( identifier ) . Replace ( "'" , "\\ '" ) } '";
140142 }
141143
142144 public static void WriteParameterReference ( ITextOutput writer , MetadataReader metadata , MethodDefinitionHandle handle , int sequence )
@@ -278,7 +280,7 @@ public static void WriteOperand(ITextOutput writer, string operand)
278280
279281 public static string EscapeString ( string str )
280282 {
281- StringBuilder sb = new StringBuilder ( ) ;
283+ var sb = new StringBuilder ( ) ;
282284 foreach ( char ch in str )
283285 {
284286 switch ( ch )
@@ -317,7 +319,7 @@ public static string EscapeString(string str)
317319 // print control characters and uncommon white spaces as numbers
318320 if ( char . IsControl ( ch ) || char . IsSurrogate ( ch ) || ( char . IsWhiteSpace ( ch ) && ch != ' ' ) )
319321 {
320- sb . Append ( "\\ u" + ( ( int ) ch ) . ToString ( "x4" ) ) ;
322+ sb . AppendFormat ( "\\ u{0:x4}" , ( int ) ch ) ;
321323 }
322324 else
323325 {
0 commit comments