Roslyn Refactor查找方法的引用

时间:2018-04-03 17:36:51

标签: c# roslyn

作为我正在研究的重构项目的一部分,我需要用正确的调用替换对Obsolete方法的调用。这适用于其他电话,但我遇到了当前问题。

我需要将所有调用替换为以下内容:

[Obsolete("use string.IsNullOrWhiteSpace instead of this extension")]
public static bool IsNullOrWhiteSpace(this string s)
{
    return string.IsNullOrWhiteSpace(s);
}

使用框架中的简单string.IsNullOrWhiteSpace(string here)。运行时它确实有效,它修复了它找到的所有实例。我无法解释的是它没有识别的200多个实例。

以下是两个未找到的示例,这个示例来自同一个类。

public static string TrimToUpper(this string s)
{
    return !IsNullOrWhiteSpace(s) ? s.Trim().ToUpperInvariant() : s;
}

我想也许是因为这个方法是直接调用的,但就找到引用而言,这对我来说没有意义。第二个例子很简单,如果在同一个解决方案的项目中的另一个类中if (enterpriseCode.IsNullOrWhiteSpace())第一个过去检测到其他几个实例,但不是这个实例。

以下是我用来查找我想要替换的方法的所有引用的代码:

public sealed class ReferenceFinder
{  
    public ReferenceFinder(string solutionPath)
    {
        SolutionInfo = GetSolutionInfo(solutionPath).GetAwaiter().GetResult();
    } 
    public ReferenceTree RetreiveSolutionReferences(string typeName, string methodName)
        => new ReferenceTree(typeName, methodName, GetReferenceLocationsByProject(GetReferenceSymbols(GetTypeSymbols(typeName), methodName)));
    private IEnumerable<INamedTypeSymbol> GetTypeSymbols(string typeName)
        => SolutionInfo.ProjectInfo.Select(pi => pi.Compilation.GetTypeByMetadataName(typeName)).Where(x => x != null);
    private IEnumerable<ReferencedSymbol> FindConstructorReferences(INamedTypeSymbol symbol)
        => symbol.Constructors.SelectMany(c => SymbolFinder.FindReferencesAsync(c, SolutionInfo.Solution).Result);
    private IEnumerable<ReferencedSymbol> FindMethodReferences(INamedTypeSymbol symbol, string methodName)
        => symbol.GetMembers(methodName).SelectMany(m => SymbolFinder.FindReferencesAsync(m, SolutionInfo.Solution).Result);
    private IEnumerable<ReferencedSymbol> GetReferenceSymbols(IEnumerable<INamedTypeSymbol> symbols, string methodName)
        => symbols.SelectMany(x => x.Name == methodName ? FindConstructorReferences(x) : FindMethodReferences(x, methodName));
    private ILookup<Project, ReferenceLocation> GetReferenceLocationsByProject(IEnumerable<ReferencedSymbol> symbols)
        => symbols.SelectMany(x => x.Locations).Distinct().ToLookup(x => x.Document.Project);
    private async Task<SolutionInfo> GetSolutionInfo(string path)
    {
        using (var workspace = MSBuildWorkspace.Create())
        {
            var solution = await workspace.OpenSolutionAsync(path);
            var compilations = await Task.WhenAll(solution.Projects.Select(async x => (x, await x.GetCompilationAsync())).AsEnumerable());
            return new SolutionInfo((solution, compilations));
        }
    }

    public readonly SolutionInfo SolutionInfo;
}

我正在通过RetreiveSolutionReferencs以下&#34; DVWorkshop.StringExtensions&#34; (要替换的方法的类和命名空间)&#34; IsNullOrWhiteSpace&#34; (替换的方法)。

我甚至写了一个简短的方法来试一试,看看有什么参考文献被提取。

        public void GetReferencesForSpecificProject(string typeName, string methodName, string projectName)
    {
        var pi = SolutionInfo.ProjectInfo.First(x => x.Project.Name == projectName);
        var symbol = pi.Compilation.GetTypeByMetadataName(typeName);

        var members = symbol.GetMembers(methodName).ToList();
        var rList = new List<IEnumerable<ReferenceLocation>>();
        var cList = new List<IEnumerable<Location>>();
        foreach (var m in members)
        {
            var referenceLocations = SymbolFinder.FindReferencesAsync(m, SolutionInfo.Solution).Result.SelectMany(r => r.Locations);
            var callerLocations = SymbolFinder.FindCallersAsync(m, SolutionInfo.Solution).Result.SelectMany(r => r.Locations);

            rList.Add(referenceLocations);
            cList.Add(callerLocations);
        }
    }

我在引用和调用者集合中看到了几个位置,但是还不够,并且它们都没有用于我传入的项目&#34;应用程序&#34;即使我看到调用并转到定义也会将我带到我的方法中。

是什么原因导致我错过对方法的引用?

0 个答案:

没有答案