2013-04-09 14 views
12

Ich versuche derzeit, überall in einer Lösung zu finden, wo eine bestimmte Aufzählung in eine Zeichenfolge konvertiert wird, ob ToString() explizit aufgerufen wird oder nicht. (Diese werden mit einer Konvertierung mit Enum Beschreibungen ersetzt Verschleierung zu verbessern.)Finden überall wo eine Enum in Zeichenfolge konvertiert wird

Beispiel: Ich möchte Code finden wie string str = "Value: " + SomeEnum.someValue;

Ich habe versucht, anstelle der ENUM selbst mit einem Wrapper-Klasse enthält implizite Konvertierungen in den Enum-Typ und überschreiben ToString() in der Wrapper-Klasse, aber wenn ich versuche, nach Verwendungen der ToString() überschreiben, gibt es mir eine Liste der Orte in der Lösung, wo ToString() für alles (und nur wo es heißt explizit). Die Suche wurde mit ReSharper in Visual Studio durchgeführt.

Gibt es eine andere Möglichkeit, diese Enum-String-Konvertierungen zu finden? Die manuelle Lösung der gesamten Lösung klingt nicht nach viel Spaß.

+7

Roslyn Team habe ich das weiß ich so markiert man es sehen werden. :-) Werden die aktuell veröffentlichten Teile von Roslyn es ermöglichen, den AST nach dieser Art von Konvertierung zu durchsuchen? –

+6

Nur eine Erweiterung dessen, was Sie bereits getan haben, wenn Sie in Ihrer Wrapper-Klasse auch eine 'implizite' Umwandlung in' string' erstellen und sie mit dem '[Obsolete]' Attribut markieren, informieren Sie Compiler-Warnungen/-Fehler überall dort, wo sie benutzt werden http://stackoverflow.com/questions/10585594/how-to-get-find-usages-working-with-implicit-operator-methods Es ist keine Antwort, aber könnte Ihnen im Notfall helfen. –

Antwort

16

Der Trick in Roslyn ist, SemanticModel.GetTypeInfo() zu verwenden und dann die ConvertedType zu überprüfen, um diese Art von impliziten Konvertierungen zu finden.

Ein komplettes Beispiel:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Roslyn.Compilers; 
using Roslyn.Compilers.CSharp; 
using Roslyn.Services; 
using Roslyn.Services.CSharp; 
using Roslyn.Compilers.Common; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var code = @"enum E { V } class { static void Main() { string s = ""Value: "" + E.V; } }"; 
     var doc = Solution.Create(SolutionId.CreateNewId()) 
      .AddCSharpProject("foo", "foo") 
      .AddMetadataReference(MetadataFileReference.CreateAssemblyReference("mscorlib")) 
      .AddDocument("doc.cs", code); 
     var stringType = doc.Project.GetCompilation().GetSpecialType(SpecialType.System_String); 
     var e = doc.Project.GetCompilation().GlobalNamespace.GetTypeMembers("E").Single(); 
     var v = e.GetMembers("V").Single(); 
     var refs = v.FindReferences(doc.Project.Solution); 
     var toStrings = from referencedLocation in refs 
         from r in referencedLocation.Locations 
         let node = GetNode(doc, r.Location) 
         let convertedType = doc.GetSemanticModel().GetTypeInfo(GetNode(doc, r.Location)).ConvertedType 
         where convertedType.Equals(stringType) 
         select r.Location; 
     foreach (var loc in toStrings) 
     { 
      Console.WriteLine(loc); 
     } 
    } 

    static CommonSyntaxNode GetNode(IDocument doc, CommonLocation loc) 
    { 
     return loc.SourceTree.GetRoot().FindToken(loc.SourceSpan.Start).Parent.Parent.Parent; 
    } 
} 
+1

Netter Gebrauch von LINQ dort Kevin. :-) –

+0

Normalerweise bevorzuge ich die Lambda-Syntax, aber in diesem Fall wollte ich wirklich die let-Klauseln zum Debuggen. –

Verwandte Themen