diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj
index 3b699e680..c164d93eb 100644
--- a/ILSpy/ILSpy.csproj
+++ b/ILSpy/ILSpy.csproj
@@ -114,6 +114,7 @@
+
diff --git a/ILSpy/Languages/CSharpLexer.cs b/ILSpy/Languages/CSharpLexer.cs
new file mode 100644
index 000000000..42bab3925
--- /dev/null
+++ b/ILSpy/Languages/CSharpLexer.cs
@@ -0,0 +1,894 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace ICSharpCode.ILSpy
+{
+ public class LATextReader : TextReader
+ {
+ List buffer;
+ TextReader reader;
+
+ public LATextReader(TextReader reader)
+ {
+ this.buffer = new List();
+ this.reader = reader;
+ }
+
+ public override int Peek()
+ {
+ return Peek(0);
+ }
+
+ public override int Read()
+ {
+ int c = Peek();
+ buffer.RemoveAt(0);
+ return c;
+ }
+
+ public int Peek(int step)
+ {
+ while (step >= buffer.Count) {
+ buffer.Add(reader.Read());
+ }
+
+ if (step < 0)
+ return -1;
+
+ return buffer[step];
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ reader.Dispose();
+ base.Dispose(disposing);
+ }
+ }
+
+ public enum LiteralFormat : byte
+ {
+ None,
+ DecimalNumber,
+ HexadecimalNumber,
+ OctalNumber,
+ StringLiteral,
+ VerbatimStringLiteral,
+ CharLiteral,
+ DateTimeLiteral
+ }
+
+ public class Literal
+ {
+ internal readonly LiteralFormat literalFormat;
+ internal readonly object literalValue;
+ internal readonly string val;
+ internal Literal next;
+
+ public LiteralFormat LiteralFormat {
+ get { return literalFormat; }
+ }
+
+ public object LiteralValue {
+ get { return literalValue; }
+ }
+
+ public string Value {
+ get { return val; }
+ }
+
+ public Literal(string val, object literalValue, LiteralFormat literalFormat)
+ {
+ this.val = val;
+ this.literalValue = literalValue;
+ this.literalFormat = literalFormat;
+ }
+ }
+
+ internal abstract class AbstractLexer
+ {
+ LATextReader reader;
+ int col = 1;
+ int line = 1;
+
+ protected Literal lastToken = null;
+ protected Literal curToken = null;
+ protected Literal peekToken = null;
+
+ string[] specialCommentTags = null;
+ protected StringBuilder sb = new StringBuilder();
+
+ // used for the original value of strings (with escape sequences).
+ protected StringBuilder originalValue = new StringBuilder();
+
+ public bool SkipAllComments { get; set; }
+ public bool EvaluateConditionalCompilation { get; set; }
+ public virtual IDictionary ConditionalCompilationSymbols {
+ get { throw new NotSupportedException(); }
+ }
+
+ protected static IEnumerable GetSymbols(string symbols)
+ {
+ if (!string.IsNullOrEmpty(symbols)) {
+ foreach (string symbol in symbols.Split(';', ' ', '\t')) {
+ string s = symbol.Trim();
+ if (s.Length == 0)
+ continue;
+ yield return s;
+ }
+ }
+ }
+
+ public virtual void SetConditionalCompilationSymbols(string symbols)
+ {
+ throw new NotSupportedException();
+ }
+
+ protected int Line {
+ get {
+ return line;
+ }
+ }
+ protected int Col {
+ get {
+ return col;
+ }
+ }
+
+ protected bool recordRead = false;
+ protected StringBuilder recordedText = new StringBuilder();
+
+ protected int ReaderRead()
+ {
+ int val = reader.Read();
+ if (recordRead && val >= 0)
+ recordedText.Append((char)val);
+ if ((val == '\r' && reader.Peek() != '\n') || val == '\n') {
+ ++line;
+ col = 1;
+ LineBreak();
+ } else if (val >= 0) {
+ col++;
+ }
+ return val;
+ }
+
+ protected int ReaderPeek()
+ {
+ return reader.Peek();
+ }
+
+ protected int ReaderPeek(int step)
+ {
+ return reader.Peek(step);
+ }
+
+ protected void ReaderSkip(int steps)
+ {
+ for (int i = 0; i < steps; i++) {
+ ReaderRead();
+ }
+ }
+
+ protected string ReaderPeekString(int length)
+ {
+ StringBuilder builder = new StringBuilder();
+
+ for (int i = 0; i < length; i++) {
+ int peek = ReaderPeek(i);
+ if (peek != -1)
+ builder.Append((char)peek);
+ }
+
+ return builder.ToString();
+ }
+
+ ///
+ /// The current Token.
+ ///
+ public Literal Token {
+ get {
+ return lastToken;
+ }
+ }
+
+ ///
+ /// The next Token (The after call) .
+ ///
+ public Literal LookAhead {
+ get {
+ return curToken;
+ }
+ }
+
+ ///
+ /// Constructor for the abstract lexer class.
+ ///
+ protected AbstractLexer(TextReader reader)
+ {
+ this.reader = new LATextReader(reader);
+ }
+
+ #region System.IDisposable interface implementation
+ public virtual void Dispose()
+ {
+ reader.Close();
+ reader = null;
+ lastToken = curToken = peekToken = null;
+ sb = originalValue = null;
+ }
+ #endregion
+
+ ///
+ /// Must be called before a peek operation.
+ ///
+ public void StartPeek()
+ {
+ peekToken = curToken;
+ }
+
+ ///
+ /// Gives back the next token. A second call to Peek() gives the next token after the last call for Peek() and so on.
+ ///
+ /// An object.
+ public Literal Peek()
+ {
+ // Console.WriteLine("Call to Peek");
+ if (peekToken.next == null) {
+ peekToken.next = Next();
+ }
+ peekToken = peekToken.next;
+ return peekToken;
+ }
+
+ ///
+ /// Reads the next token and gives it back.
+ ///
+ /// An object.
+ public virtual Literal NextToken()
+ {
+ if (curToken == null) {
+ curToken = Next();
+ //Console.WriteLine(ICSharpCode.NRefactory.Parser.CSharp.Tokens.GetTokenString(curToken.kind) + " -- " + curToken.val + "(" + curToken.kind + ")");
+ return curToken;
+ }
+
+ lastToken = curToken;
+
+ if (curToken.next == null) {
+ curToken.next = Next();
+ }
+
+ curToken = curToken.next;
+ //Console.WriteLine(ICSharpCode.NRefactory.Parser.CSharp.Tokens.GetTokenString(curToken.kind) + " -- " + curToken.val + "(" + curToken.kind + ")");
+ return curToken;
+ }
+
+ protected abstract Literal Next();
+
+ protected static bool IsIdentifierPart(int ch)
+ {
+ if (ch == 95) return true; // 95 = '_'
+ if (ch == -1) return false;
+ return char.IsLetterOrDigit((char)ch); // accept unicode letters
+ }
+
+ protected static bool IsHex(char digit)
+ {
+ return Char.IsDigit(digit) || ('A' <= digit && digit <= 'F') || ('a' <= digit && digit <= 'f');
+ }
+
+ protected int GetHexNumber(char digit)
+ {
+ if (Char.IsDigit(digit)) {
+ return digit - '0';
+ }
+ if ('A' <= digit && digit <= 'F') {
+ return digit - 'A' + 0xA;
+ }
+ if ('a' <= digit && digit <= 'f') {
+ return digit - 'a' + 0xA;
+ }
+ return 0;
+ }
+ protected void LineBreak()
+ {
+ }
+ protected bool HandleLineEnd(char ch)
+ {
+ // Handle MS-DOS or MacOS line ends.
+ if (ch == '\r') {
+ if (reader.Peek() == '\n') { // MS-DOS line end '\r\n'
+ ReaderRead(); // LineBreak (); called by ReaderRead ();
+ return true;
+ } else { // assume MacOS line end which is '\r'
+ LineBreak();
+ return true;
+ }
+ }
+ if (ch == '\n') {
+ LineBreak();
+ return true;
+ }
+ return false;
+ }
+
+ protected void SkipToEndOfLine()
+ {
+ int nextChar;
+ while ((nextChar = reader.Read()) != -1) {
+ if (nextChar == '\r') {
+ if (reader.Peek() == '\n')
+ reader.Read();
+ nextChar = '\n';
+ }
+ if (nextChar == '\n') {
+ ++line;
+ col = 1;
+ break;
+ }
+ }
+ }
+
+ protected string ReadToEndOfLine()
+ {
+ sb.Length = 0;
+ int nextChar;
+ while ((nextChar = reader.Read()) != -1) {
+ char ch = (char)nextChar;
+
+ if (nextChar == '\r') {
+ if (reader.Peek() == '\n')
+ reader.Read();
+ nextChar = '\n';
+ }
+ // Return read string, if EOL is reached
+ if (nextChar == '\n') {
+ ++line;
+ col = 1;
+ return sb.ToString();
+ }
+
+ sb.Append(ch);
+ }
+
+ // Got EOF before EOL
+ string retStr = sb.ToString();
+ col += retStr.Length;
+ return retStr;
+ }
+ }
+
+ internal sealed class Lexer : AbstractLexer
+ {
+ bool isAtLineBegin = true;
+
+ public Lexer(TextReader reader) : base(reader)
+ {
+ }
+
+ protected override Literal Next()
+ {
+ char ch;
+ if (Line == 1 && Col == 1) {
+ isAtLineBegin = true;
+ }
+
+ while (true) {
+ int nextChar = ReaderRead();
+ if (nextChar == -1)
+ break;
+
+ Literal token = null;
+
+ switch (nextChar) {
+ case ' ':
+ case '\t':
+ continue;
+ case '\r':
+ case '\n':
+ HandleLineEnd((char)nextChar);
+ isAtLineBegin = true;
+ continue;
+ case '"':
+ token = ReadString();
+ isAtLineBegin = false;
+ break;
+ case '\'':
+ token = ReadChar();
+ isAtLineBegin = false;
+ break;
+ default:
+ isAtLineBegin = false; // non-ws chars are handled here
+ ch = (char)nextChar;
+ if (Char.IsLetter(ch) || ch == '_' || ch == '\\') {
+ int x = Col - 1; // Col was incremented above, but we want the start of the identifier
+ int y = Line;
+ bool canBeKeyword;
+ string s = ReadIdent(ch, out canBeKeyword);
+ return new Literal(null, null, LiteralFormat.None);
+ } else if (Char.IsDigit(ch)) {
+ token = ReadDigit(ch, Col - 1);
+ }
+ break;
+ }
+
+ // try error recovery (token = null -> continue with next char)
+ if (token != null) {
+ return token;
+ }
+ }
+
+ return new Literal(null, null, LiteralFormat.None);
+ }
+
+ // The C# compiler has a fixed size length therefore we'll use a fixed size char array for identifiers
+ // it's also faster than using a string builder.
+ const int MAX_IDENTIFIER_LENGTH = 512;
+ char[] identBuffer = new char[MAX_IDENTIFIER_LENGTH];
+
+ string ReadIdent(char ch, out bool canBeKeyword)
+ {
+ int peek;
+ int curPos = 0;
+ canBeKeyword = true;
+ while (true) {
+ if (ch == '\\') {
+ peek = ReaderPeek();
+ canBeKeyword = false;
+ string surrogatePair;
+ ReadEscapeSequence(out ch, out surrogatePair);
+ if (surrogatePair != null) {
+ for (int i = 0; i < surrogatePair.Length - 1; i++) {
+ if (curPos < MAX_IDENTIFIER_LENGTH) {
+ identBuffer[curPos++] = surrogatePair[i];
+ }
+ }
+ ch = surrogatePair[surrogatePair.Length - 1];
+ }
+ }
+
+ if (curPos < MAX_IDENTIFIER_LENGTH) {
+ if (ch != '\0') // only add character, if it is valid
+ // prevents \ from being added
+ identBuffer[curPos++] = ch;
+ } else {
+ while (IsIdentifierPart(ReaderPeek())) {
+ ReaderRead();
+ }
+ break;
+ }
+ peek = ReaderPeek();
+ if (IsIdentifierPart(peek) || peek == '\\') {
+ ch = (char)ReaderRead();
+ } else {
+ break;
+ }
+ }
+ return new String(identBuffer, 0, curPos);
+ }
+
+ Literal ReadDigit(char ch, int x)
+ {
+ unchecked { // prevent exception when ReaderPeek() = -1 is cast to char
+ int y = Line;
+ sb.Length = 0;
+ sb.Append(ch);
+ string prefix = null;
+ string suffix = null;
+
+ bool ishex = false;
+ bool isunsigned = false;
+ bool islong = false;
+ bool isfloat = false;
+ bool isdouble = false;
+ bool isdecimal = false;
+
+ char peek = (char)ReaderPeek();
+
+ if (ch == '.') {
+ isdouble = true;
+
+ while (Char.IsDigit((char)ReaderPeek())) { // read decimal digits beyond the dot
+ sb.Append((char)ReaderRead());
+ }
+ peek = (char)ReaderPeek();
+ } else if (ch == '0' && (peek == 'x' || peek == 'X')) {
+ ReaderRead(); // skip 'x'
+ sb.Length = 0; // Remove '0' from 0x prefix from the stringvalue
+ while (IsHex((char)ReaderPeek())) {
+ sb.Append((char)ReaderRead());
+ }
+ if (sb.Length == 0) {
+ sb.Append('0'); // dummy value to prevent exception
+ }
+ ishex = true;
+ prefix = "0x";
+ peek = (char)ReaderPeek();
+ } else {
+ while (Char.IsDigit((char)ReaderPeek())) {
+ sb.Append((char)ReaderRead());
+ }
+ peek = (char)ReaderPeek();
+ }
+
+ Literal nextToken = null; // if we accidently read a 'dot'
+ if (peek == '.') { // read floating point number
+ ReaderRead();
+ peek = (char)ReaderPeek();
+ if (!Char.IsDigit(peek)) {
+ nextToken = new Literal(null, null, LiteralFormat.None);
+ peek = '.';
+ } else {
+ isdouble = true; // double is default
+ sb.Append('.');
+
+ while (Char.IsDigit((char)ReaderPeek())) { // read decimal digits beyond the dot
+ sb.Append((char)ReaderRead());
+ }
+ peek = (char)ReaderPeek();
+ }
+ }
+
+ if (peek == 'e' || peek == 'E') { // read exponent
+ isdouble = true;
+ sb.Append((char)ReaderRead());
+ peek = (char)ReaderPeek();
+ if (peek == '-' || peek == '+') {
+ sb.Append((char)ReaderRead());
+ }
+ while (Char.IsDigit((char)ReaderPeek())) { // read exponent value
+ sb.Append((char)ReaderRead());
+ }
+ isunsigned = true;
+ peek = (char)ReaderPeek();
+ }
+
+ if (peek == 'f' || peek == 'F') { // float value
+ ReaderRead();
+ suffix = "f";
+ isfloat = true;
+ } else if (peek == 'd' || peek == 'D') { // double type suffix (obsolete, double is default)
+ ReaderRead();
+ suffix = "d";
+ isdouble = true;
+ } else if (peek == 'm' || peek == 'M') { // decimal value
+ ReaderRead();
+ suffix = "m";
+ isdecimal = true;
+ } else if (!isdouble) {
+ if (peek == 'u' || peek == 'U') {
+ ReaderRead();
+ suffix = "u";
+ isunsigned = true;
+ peek = (char)ReaderPeek();
+ }
+
+ if (peek == 'l' || peek == 'L') {
+ ReaderRead();
+ peek = (char)ReaderPeek();
+ islong = true;
+ if (!isunsigned && (peek == 'u' || peek == 'U')) {
+ ReaderRead();
+ suffix = "Lu";
+ isunsigned = true;
+ } else {
+ suffix = isunsigned ? "uL" : "L";
+ }
+ }
+ }
+
+ string digit = sb.ToString();
+ string stringValue = prefix + digit + suffix;
+
+ if (isfloat) {
+ float num;
+ if (float.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) {
+ return new Literal(stringValue, num, LiteralFormat.DecimalNumber);
+ } else {
+ return new Literal(stringValue, 0f, LiteralFormat.DecimalNumber);
+ }
+ }
+ if (isdecimal) {
+ decimal num;
+ if (decimal.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) {
+ return new Literal(stringValue, num, LiteralFormat.DecimalNumber);
+ } else {
+ return new Literal(stringValue, 0m, LiteralFormat.DecimalNumber);
+ }
+ }
+ if (isdouble) {
+ double num;
+ if (double.TryParse(digit, NumberStyles.Any, CultureInfo.InvariantCulture, out num)) {
+ return new Literal(stringValue, num, LiteralFormat.DecimalNumber);
+ } else {
+
+ return new Literal(stringValue, 0d, LiteralFormat.DecimalNumber);
+ }
+ }
+
+ // Try to determine a parsable value using ranges.
+ ulong result;
+ if (ishex) {
+ if (!ulong.TryParse(digit, NumberStyles.HexNumber, null, out result)) {
+
+ return new Literal(stringValue.ToString(), 0, LiteralFormat.HexadecimalNumber);
+ }
+ } else {
+ if (!ulong.TryParse(digit, NumberStyles.Integer, null, out result)) {
+
+ return new Literal(stringValue.ToString(), 0, LiteralFormat.DecimalNumber);
+ }
+ }
+
+ if (result > long.MaxValue) {
+ islong = true;
+ isunsigned = true;
+ } else if (result > uint.MaxValue) {
+ islong = true;
+ } else if (islong == false && result > int.MaxValue) {
+ isunsigned = true;
+ }
+
+ Literal token;
+
+ LiteralFormat literalFormat = ishex ? LiteralFormat.HexadecimalNumber : LiteralFormat.DecimalNumber;
+ if (islong) {
+ if (isunsigned) {
+ ulong num;
+ if (ulong.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) {
+ token = new Literal(stringValue, num, literalFormat);
+ } else {
+
+ token = new Literal(stringValue, 0UL, literalFormat);
+ }
+ } else {
+ long num;
+ if (long.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) {
+ token = new Literal(stringValue, num, literalFormat);
+ } else {
+
+ token = new Literal(stringValue, 0L, literalFormat);
+ }
+ }
+ } else {
+ if (isunsigned) {
+ uint num;
+ if (uint.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) {
+ token = new Literal(stringValue, num, literalFormat);
+ } else {
+
+ token = new Literal(stringValue, (uint)0, literalFormat);
+ }
+ } else {
+ int num;
+ if (int.TryParse(digit, ishex ? NumberStyles.HexNumber : NumberStyles.Number, CultureInfo.InvariantCulture, out num)) {
+ token = new Literal(stringValue, num, literalFormat);
+ } else {
+
+ token = new Literal(stringValue, 0, literalFormat);
+ }
+ }
+ }
+ token.next = nextToken;
+ return token;
+ }
+ }
+
+ Literal ReadString()
+ {
+ int x = Col - 1;
+ int y = Line;
+
+ sb.Length = 0;
+ originalValue.Length = 0;
+ originalValue.Append('"');
+ bool doneNormally = false;
+ int nextChar;
+ while ((nextChar = ReaderRead()) != -1) {
+ char ch = (char)nextChar;
+
+ if (ch == '"') {
+ doneNormally = true;
+ originalValue.Append('"');
+ break;
+ }
+
+ if (ch == '\\') {
+ originalValue.Append('\\');
+ string surrogatePair;
+ originalValue.Append(ReadEscapeSequence(out ch, out surrogatePair));
+ if (surrogatePair != null) {
+ sb.Append(surrogatePair);
+ } else {
+ sb.Append(ch);
+ }
+ } else if (HandleLineEnd(ch)) {
+ // call HandleLineEnd to ensure line numbers are still correct after the error
+
+ break;
+ } else {
+ originalValue.Append(ch);
+ sb.Append(ch);
+ }
+ }
+
+ if (!doneNormally) {
+
+ }
+
+ return new Literal(originalValue.ToString(), sb.ToString(), LiteralFormat.StringLiteral);
+ }
+
+ Literal ReadVerbatimString()
+ {
+ sb.Length = 0;
+ originalValue.Length = 0;
+ originalValue.Append("@\"");
+ int nextChar;
+ while ((nextChar = ReaderRead()) != -1) {
+ char ch = (char)nextChar;
+
+ if (ch == '"') {
+ if (ReaderPeek() != '"') {
+ originalValue.Append('"');
+ break;
+ }
+ originalValue.Append("\"\"");
+ sb.Append('"');
+ ReaderRead();
+ } else if (HandleLineEnd(ch)) {
+ sb.Append("\r\n");
+ originalValue.Append("\r\n");
+ } else {
+ sb.Append(ch);
+ originalValue.Append(ch);
+ }
+ }
+
+ if (nextChar == -1) {
+
+ }
+
+ return new Literal(originalValue.ToString(), sb.ToString(), LiteralFormat.VerbatimStringLiteral);
+ }
+
+ readonly char[] escapeSequenceBuffer = new char[12];
+
+ ///
+ /// reads an escape sequence
+ ///
+ /// The character represented by the escape sequence,
+ /// or '\0' if there was an error or the escape sequence represents a character that
+ /// can be represented only be a suggorate pair
+ /// Null, except when the character represented
+ /// by the escape sequence can only be represented by a surrogate pair (then the string
+ /// contains the surrogate pair)
+ /// The escape sequence
+ string ReadEscapeSequence(out char ch, out string surrogatePair)
+ {
+ surrogatePair = null;
+
+ int nextChar = ReaderRead();
+ if (nextChar == -1) {
+ ch = '\0';
+ return String.Empty;
+ }
+ int number;
+ char c = (char)nextChar;
+ int curPos = 1;
+ escapeSequenceBuffer[0] = c;
+ switch (c) {
+ case '\'':
+ ch = '\'';
+ break;
+ case '\"':
+ ch = '\"';
+ break;
+ case '\\':
+ ch = '\\';
+ break;
+ case '0':
+ ch = '\0';
+ break;
+ case 'a':
+ ch = '\a';
+ break;
+ case 'b':
+ ch = '\b';
+ break;
+ case 'f':
+ ch = '\f';
+ break;
+ case 'n':
+ ch = '\n';
+ break;
+ case 'r':
+ ch = '\r';
+ break;
+ case 't':
+ ch = '\t';
+ break;
+ case 'v':
+ ch = '\v';
+ break;
+ case 'u':
+ case 'x':
+ // 16 bit unicode character
+ c = (char)ReaderRead();
+ number = GetHexNumber(c);
+ escapeSequenceBuffer[curPos++] = c;
+
+ for (int i = 0; i < 3; ++i) {
+ if (IsHex((char)ReaderPeek())) {
+ c = (char)ReaderRead();
+ int idx = GetHexNumber(c);
+ escapeSequenceBuffer[curPos++] = c;
+ number = 16 * number + idx;
+ } else {
+ break;
+ }
+ }
+ ch = (char)number;
+ break;
+ case 'U':
+ // 32 bit unicode character
+ number = 0;
+ for (int i = 0; i < 8; ++i) {
+ if (IsHex((char)ReaderPeek())) {
+ c = (char)ReaderRead();
+ int idx = GetHexNumber(c);
+ escapeSequenceBuffer[curPos++] = c;
+ number = 16 * number + idx;
+ } else {
+ break;
+ }
+ }
+ if (number > 0xffff) {
+ ch = '\0';
+ surrogatePair = char.ConvertFromUtf32(number);
+ } else {
+ ch = (char)number;
+ }
+ break;
+ default:
+ ch = '\0';
+ break;
+ }
+ return new String(escapeSequenceBuffer, 0, curPos);
+ }
+
+ Literal ReadChar()
+ {
+ int x = Col - 1;
+ int y = Line;
+ int nextChar = ReaderRead();
+ if (nextChar == -1 || HandleLineEnd((char)nextChar)) {
+ return null;
+ }
+ char ch = (char)nextChar;
+ char chValue = ch;
+ string escapeSequence = String.Empty;
+ if (ch == '\\') {
+ string surrogatePair;
+ escapeSequence = ReadEscapeSequence(out chValue, out surrogatePair);
+ if (surrogatePair != null) {
+
+ }
+ }
+
+ unchecked {
+ if ((char)ReaderRead() != '\'') {
+
+ }
+ }
+ return new Literal("'" + ch + escapeSequence + "'", chValue, LiteralFormat.CharLiteral);
+ }
+ }
+}
diff --git a/ILSpy/SearchPane.cs b/ILSpy/SearchPane.cs
index 18a298d88..850a30822 100644
--- a/ILSpy/SearchPane.cs
+++ b/ILSpy/SearchPane.cs
@@ -288,8 +288,8 @@ namespace ICSharpCode.ILSpy
return new TypeSearchStrategy(terms);
case SearchMode.Member:
return new MemberSearchStrategy(terms);
- //case SearchMode.Literal:
- // return new LiteralSearchStrategy(terms);
+ case SearchMode.Literal:
+ return new LiteralSearchStrategy(terms);
case SearchMode.Method:
return new MemberSearchStrategy(terms, MemberSearchKind.Method);
case SearchMode.Field:
@@ -357,6 +357,6 @@ namespace ICSharpCode.ILSpy
Field,
Property,
Event,
- //Literal
+ Literal
}
}
\ No newline at end of file
diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs
index 24d732536..a351ff680 100644
--- a/ILSpy/SearchStrategies.cs
+++ b/ILSpy/SearchStrategies.cs
@@ -3,8 +3,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Media;
+using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.TreeNodes;
using Mono.Cecil;
+using Code = Mono.Cecil.Cil.Code;
namespace ICSharpCode.ILSpy
{
@@ -53,18 +55,23 @@ namespace ICSharpCode.ILSpy
{
return false;
}
-
+
protected virtual bool MatchName(IMemberDefinition m, Language language)
+ {
+ return IsMatch(t => GetLanguageSpecificName(language, m, regex != null ? fullNameSearch : t.Contains(".")));
+ }
+
+ protected virtual bool IsMatch(Func getText)
{
if (regex != null) {
- return regex.IsMatch(GetLanguageSpecificName(language, m, fullNameSearch));
+ return regex.IsMatch(getText(""));
}
for (int i = 0; i < searchTerm.Length; ++i) {
// How to handle overlapping matches?
var term = searchTerm[i];
if (string.IsNullOrEmpty(term)) continue;
- string text = GetLanguageSpecificName(language, m, term.Contains("."));
+ string text = getText(term);
switch (term[0]) {
case '+': // must contain
term = term.Substring(1);
@@ -153,7 +160,7 @@ namespace ICSharpCode.ILSpy
}
}
}
- /*
+
class LiteralSearchStrategy : AbstractSearchStrategy
{
readonly TypeCode searchTermLiteralType;
@@ -162,13 +169,13 @@ namespace ICSharpCode.ILSpy
public LiteralSearchStrategy(params string[] terms)
: base(terms)
{
- if (1 == searchTerm.Length) {
- var parser = new CSharpParser();
- var pe = parser.ParseExpression(searchTerm[0]) as PrimitiveExpression;
+ if (searchTerm.Length == 1) {
+ var lexer = new Lexer(new LATextReader(new System.IO.StringReader(searchTerm[0])));
+ var value = lexer.NextToken();
- if (pe != null && pe.Value != null) {
- TypeCode peValueType = Type.GetTypeCode(pe.Value.GetType());
- switch (peValueType) {
+ if (value != null && value.LiteralValue != null) {
+ TypeCode valueType = Type.GetTypeCode(value.LiteralValue.GetType());
+ switch (valueType) {
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.Int16:
@@ -178,35 +185,35 @@ namespace ICSharpCode.ILSpy
case TypeCode.Int64:
case TypeCode.UInt64:
searchTermLiteralType = TypeCode.Int64;
- searchTermLiteralValue = CSharpPrimitiveCast.Cast(TypeCode.Int64, pe.Value, false);
+ searchTermLiteralValue = CSharpPrimitiveCast.Cast(TypeCode.Int64, value.LiteralValue, false);
break;
case TypeCode.Single:
case TypeCode.Double:
case TypeCode.String:
- searchTermLiteralType = peValueType;
- searchTermLiteralValue = pe.Value;
+ searchTermLiteralType = valueType;
+ searchTermLiteralValue = value.LiteralValue;
break;
}
}
}
}
- protected override bool IsMatch(FieldDefinition field)
+ protected override bool IsMatch(FieldDefinition field, Language language)
{
return IsLiteralMatch(field.Constant);
}
- protected override bool IsMatch(PropertyDefinition property)
+ protected override bool IsMatch(PropertyDefinition property, Language language)
{
return MethodIsLiteralMatch(property.GetMethod) || MethodIsLiteralMatch(property.SetMethod);
}
- protected override bool IsMatch(EventDefinition ev)
+ protected override bool IsMatch(EventDefinition ev, Language language)
{
return MethodIsLiteralMatch(ev.AddMethod) || MethodIsLiteralMatch(ev.RemoveMethod) || MethodIsLiteralMatch(ev.InvokeMethod);
}
- protected override bool IsMatch(MethodDefinition m)
+ protected override bool IsMatch(MethodDefinition m, Language language)
{
return MethodIsLiteralMatch(m);
}
@@ -228,7 +235,7 @@ namespace ICSharpCode.ILSpy
return searchTermLiteralValue.Equals(val);
default:
// substring search with searchTerm
- return IsMatch(val.ToString());
+ return IsMatch(t => val.ToString());
}
}
@@ -318,13 +325,13 @@ namespace ICSharpCode.ILSpy
}
} else {
foreach (var inst in body.Instructions) {
- if (inst.OpCode.Code == Code.Ldstr && IsMatch((string)inst.Operand))
+ if (inst.OpCode.Code == Code.Ldstr && IsMatch(t => (string)inst.Operand))
return true;
}
}
return false;
}
- }*/
+ }
enum MemberSearchKind
{