Roslyn-Find Неиспользуемые переменные - PullRequest
0 голосов
/ 16 ноября 2018

Я хотел бы получить все неиспользуемые переменные в моем решении, и у меня работает следующий код , за исключением одного сценария .

Например

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;
        }

ОБНОВЛЕНИЕ: Ниже приведен точный код, где мой GetUnusedLocalVariables обнаружил formatters в качестве неиспользуемой переменной.

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 передается как выходной параметр, но егообнаруживается как неиспользованная переменная.

ОБНОВЛЕНИЕ 2: Другой пример:

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

Здесь переменная frozen определяется как неиспользуемая переменная.Мне не удалось получить доступ к свойству "объявление вида" (изображение ниже).Чтобы я мог добавить условие, например,

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

[DeclarationKind]

...