Roslyn Code Analysis возвращает ложные ошибки сборки из безошибочного решения - PullRequest
1 голос
/ 04 ноября 2019

Я пытаюсь использовать Roslyn для анализа очень простого решения на C #, консольного приложения с простой скелетной программой:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CA5
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Приведенный выше код создается без ошибок в VS 2019 Preview. Для такого простого решения / программы я ожидал, что Roslyn CA будет работать без сбоев, однако компиляция Roslyn возвращает ошибки, большинство из которых связано с нераспознанным типом.

Мой код CA такой:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;

namespace CA5X
{
    class Program
    {
        static void Main(string[] args)
        {
            const string path = @"C:\Utils\CA5\CA5.sln";

            var props = new Dictionary<string, string>();
            props["CheckForSystemRuntimeDependency"] = "true";
            MSBuildWorkspace buildWorkspace = MSBuildWorkspace.Create(props);

            Solution solutionToAnalyze = buildWorkspace.OpenSolutionAsync(path).Result;
            foreach (Microsoft.CodeAnalysis.Project sProject in solutionToAnalyze.Projects)
            {
                Compilation sCompilation = sProject.GetCompilationAsync().Result;
                var errors = sCompilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error); 

                Console.WriteLine("COUNT:  " + errors.Count().ToString());

                foreach (Microsoft.CodeAnalysis.Diagnostic diagnostic in errors)
                {
                    Console.WriteLine(diagnostic.GetMessage());
                }

            }
        }
    }
}

Диагностика, полученная после компиляции, такова:

The type or namespace name 'AssemblyTitleAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyTitle' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyDescriptionAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyDescription' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyConfigurationAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyConfiguration' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyCompanyAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyCompany' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyProductAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyProduct' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyCopyrightAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyCopyright' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyTrademarkAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyTrademark' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyCultureAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyCulture' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'ComVisibleAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'ComVisible' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'GuidAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'Guid' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyVersionAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyVersion' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyFileVersionAttribute' could not be found (are you missing a using directive or an assembly reference?)
The type or namespace name 'AssemblyFileVersion' could not be found (are you missing a using directive or an assembly reference?)
Predefined type 'System.String' is not defined or imported
The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
Predefined type 'System.Object' is not defined or imported
Predefined type 'System.String' is not defined or imported
Predefined type 'System.Void' is not defined or imported
'object' does not contain a constructor that takes 0 arguments

Я могу только догадываться, что это происходит из-за некоторых проблем конфигурации, но с таким количеством версий .NET и таким количеством версий VS невозможно попробоватьвсе комбинации.

Ответы [ 2 ]

1 голос
/ 06 ноября 2019

Если вы настроили свой проект на использование MSBuildLocator, как показано ниже, он сможет загрузить ваш проект:

SampleRoslynTool.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net472</TargetFramework>
    <LangVersion>Latest</LangVersion>
  </PropertyGroup>

   <ItemGroup>
    <PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="2.9.7" PrivateAssets="all" />
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="3.3.1" />
    <PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="3.3.1" />
    <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="3.3.1" />
  </ItemGroup>

</Project>

Program.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.Text;

namespace SampleRoslynTool
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // Attempt to set the version of MSBuild.
            var visualStudioInstances = MSBuildLocator.QueryVisualStudioInstances().ToArray();
            var instance = visualStudioInstances.Length == 1
                // If there is only one instance of MSBuild on this machine, set that as the one to use.
                ? visualStudioInstances[0]
                // Handle selecting the version of MSBuild you want to use.
                : SelectVisualStudioInstance(visualStudioInstances);

            Console.WriteLine($"Using MSBuild at '{instance.MSBuildPath}' to load projects.");

            // NOTE: Be sure to register an instance with the MSBuildLocator 
            //       before calling MSBuildWorkspace.Create()
            //       otherwise, MSBuildWorkspace won't MEF compose.
            MSBuildLocator.RegisterInstance(instance);

            using (var workspace = MSBuildWorkspace.Create())
            {
                // Print message for WorkspaceFailed event to help diagnosing project load failures.
                workspace.WorkspaceFailed += (o, e) => Console.WriteLine(e.Diagnostic.Message);

                var solutionPath = args[0];
                Console.WriteLine($"Loading solution '{solutionPath}'");

                // Attach progress reporter so we print projects as they are loaded.
                var solution = await workspace.OpenSolutionAsync(solutionPath, new ConsoleProgressReporter());
                Console.WriteLine($"Finished loading solution '{solutionPath}'");

                // TODO: Do analysis on the projects in the loaded solution
            }
        }

        private static VisualStudioInstance SelectVisualStudioInstance(VisualStudioInstance[] visualStudioInstances)
        {
            Console.WriteLine("Multiple installs of MSBuild detected please select one:");
            for (int i = 0; i < visualStudioInstances.Length; i++)
            {
                Console.WriteLine($"Instance {i + 1}");
                Console.WriteLine($"    Name: {visualStudioInstances[i].Name}");
                Console.WriteLine($"    Version: {visualStudioInstances[i].Version}");
                Console.WriteLine($"    MSBuild Path: {visualStudioInstances[i].MSBuildPath}");
            }

            while (true)
            {
                var userResponse = Console.ReadLine();
                if (int.TryParse(userResponse, out int instanceNumber) &&
                    instanceNumber > 0 &&
                    instanceNumber <= visualStudioInstances.Length)
                {
                    return visualStudioInstances[instanceNumber - 1];
                }
                Console.WriteLine("Input not accepted, try again.");
            }
        }

        private class ConsoleProgressReporter : IProgress<ProjectLoadProgress>
        {
            public void Report(ProjectLoadProgress loadProgress)
            {
                var projectDisplay = Path.GetFileName(loadProgress.FilePath);
                if (loadProgress.TargetFramework != null)
                {
                    projectDisplay += $" ({loadProgress.TargetFramework})";
                }

                Console.WriteLine($"{loadProgress.Operation,-15} {loadProgress.ElapsedTime,-15:m\\:ss\\.fffffff} {projectDisplay}");
            }
        }
    }
}
0 голосов
/ 12 ноября 2019

Я хотел бы поблагодарить вас за предложения.

В конце концов я обнаружил, что проблема была вызвана путанным использованием пакетов nuget. Мой проект изначально был нацелен на DotNet Framework 4.5.2, затем я добавил несколько пакетов nuget, VS автоматически переключился на 4.7.2 и у меня была неправильная комбинация библиотек. Поскольку у меня не было опыта использования nuget, я не осознавал, что можно также выбрать конкретную версию, совместимую с целевым фреймом DotNet.

С достаточной тщательностью мне удалось создать правильную комбинацию пакетов, затем все заработало.

...