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 {