Roslyn查找未使用的变量

时间:2018-11-16 06:32:47

标签: c# roslyn

我想在我的解决方案中获取所有未使用的变量,并且我有下面的代码正在工作,除了一种情况

例如

Int64 num;
Int64.TryParse("1234", out num);

我的代码还将num变量检测为未使用的变量。我如何避免这种情况?有什么建议么。

代码:

public async Task<List<Location>> GetUnusedLocalVariables(Solution solution)
        {
            List<Location> locations = new List<Location>();
            foreach (var pjt in solution.Projects)
            {
                var compilation = await pjt.GetCompilationAsync();
                foreach (var tree in compilation.SyntaxTrees)
                {
                    var methods = tree.GetRoot().DescendantNodesAndSelf().OfType<MethodDeclarationSyntax>().Where(x => x.IsKind(SyntaxKind.MethodDeclaration));
                    foreach (var method in methods)
                    {
                        if (method.Body == null) continue;
                        var dataFlow = compilation.GetSemanticModel(tree).AnalyzeDataFlow(method.Body);
                        var variablesDeclared = dataFlow.VariablesDeclared.Where(x => x.Kind.ToString() == "Local");
                        var variablesRead = dataFlow.ReadInside.Union(dataFlow.ReadOutside);
                        var unused = variablesDeclared.Except(variablesRead);
                        if (unused.Any())
                        {
                            foreach (var unusedVar in unused)
                            {
                                var foreachStatements = method.DescendantNodes().OfType<ForEachStatementSyntax>().Where(x => x.Identifier.Text == unusedVar.Name).ToList();
                                if (foreachStatements?.Count > 0) continue;
                                locations.Add(unusedVar.Locations.First());
                            }
                        }
                    }
                }
            }
            return locations;
        }

更新: 以下是我的GetUnusedLocalVariablesformatters检测为未使用变量的确切代码。

HelpPageSampleGenerator.cs(我的Web api项目中的自动生成的代码)

public virtual Type ResolveHttpRequestMessageType(ApiDescription api)
        {
            string controllerName = api.ActionDescriptor.ControllerDescriptor.ControllerName;
            string actionName = api.ActionDescriptor.ActionName;
            IEnumerable<string> parameterNames = api.ParameterDescriptions.Select(p => p.Name);
            Collection<MediaTypeFormatter> formatters;
            return ResolveType(api, controllerName, actionName, parameterNames, SampleDirection.Request, out formatters);
        }

public virtual Type ResolveType(ApiDescription api, string controllerName, string actionName, IEnumerable<string> parameterNames, SampleDirection sampleDirection, out Collection<MediaTypeFormatter> formatters)
        {
            if (!Enum.IsDefined(typeof(SampleDirection), sampleDirection))
            {
                throw new InvalidEnumArgumentException("sampleDirection", (int)sampleDirection, typeof(SampleDirection));
            }
            if (api == null)
            {
                throw new ArgumentNullException("api");
            }
            Type type;
            if (ActualHttpMessageTypes.TryGetValue(new HelpPageSampleKey(sampleDirection, controllerName, actionName, parameterNames), out type) ||
                ActualHttpMessageTypes.TryGetValue(new HelpPageSampleKey(sampleDirection, controllerName, actionName, new[] { "*" }), out type))
            {
                // Re-compute the supported formatters based on type
                Collection<MediaTypeFormatter> newFormatters = new Collection<MediaTypeFormatter>();
                foreach (var formatter in api.ActionDescriptor.Configuration.Formatters)
                {
                    if (IsFormatSupported(sampleDirection, formatter, type))
                    {
                        newFormatters.Add(formatter);
                    }
                }
                formatters = newFormatters;
            }
            else
            {
                switch (sampleDirection)
                {
                    case SampleDirection.Request:
                        ApiParameterDescription requestBodyParameter = api.ParameterDescriptions.FirstOrDefault(p => p.Source == ApiParameterSource.FromBody);
                        type = requestBodyParameter == null ? null : requestBodyParameter.ParameterDescriptor.ParameterType;
                        formatters = api.SupportedRequestBodyFormatters;
                        break;
                    case SampleDirection.Response:
                    default:
                        type = api.ResponseDescription.ResponseType ?? api.ResponseDescription.DeclaredType;
                        formatters = api.SupportedResponseFormatters;
                        break;
                }
            }

            return type;
        }

我不确定为什么将formatters作为out参数传递,但是将其检测为未使用的变量。

更新2: 另一个示例:

if (statusBar.IsFrozen(out int frozen) == 0)
{
    statusBar.SetText(statusBarText);
}

此处将变量frozen检测为未使用的变量。 我无法访问属性“ DeclarationKind”(下图)。这样我就可以添加条件,

if(unusedVar.DeclarationKind=="OutVariable") continue;

[DeclarationKind]

0 个答案:

没有答案