SonarSource / sonarqube-roslyn-sdk

SDK for SonarQube Roslyn Analyzer Plugins
GNU Lesser General Public License v3.0
85 stars 43 forks source link

Issue while creating the plugin, SDK is not able to resolve third party Nuget package references #182

Closed ketanmehra30 closed 2 years ago

ketanmehra30 commented 2 years ago

I have created a roslyn analyzer using codeanalysis version 2.8.2 as suggested by documentation. I am filing up the diagnosticDescriptor of my rule using a helper class named DiagnosticBuilder which reads a json file and returns diagnosticDescriptor object. Example: //public const string DiagnosticId = "SF001"; private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.CustomDummyRuleMessage), Resources.ResourceManager, typeof(Resources)); private static readonly DiagnosticDescriptor descriptor = DiagnosticDescriptorBuilder.GetDescriptor(DiagnosticId, MessageFormat.ToString(), true);

Issue:

When I create nuget package which contains the builder class and my analyzers to SDK it throws following error:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Could not instantiate analyzers from 'AnalyzerName', Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

Error: Exception has been thrown by the target of an invocation. [DEBUG] Removed AssemblyResolver from current AppDomain assembly resolution. [WARNING] No analyzers were found in package: AnalyzerName [WARNING] Re-run this generator with /recurse if plugins should be generated for the dependencies of this package.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Where as when I fill the DiagnosticDescriptor constructor directly then SDK successfully creates the JAR file Example: private static readonly DiagnosticDescriptor descriptor = new DiagnosticDescriptor( // Values );

When running the test cases my DiagnosticDescriptor object is being filled correctly and there are no issue then why is SDK not able to instantiate my DiagnosticDescriptor using the helper class (DiagnosticDescriptorBuilder)?

Am I doing something wrong here or overlooked somethng?

duncanp-sonar commented 2 years ago

@ketanmehra30 did you solve the problem?

ketanmehra30 commented 2 years ago

No, Issue is not resolved . Actually I am using NewtonSoft.Json Package to deserialize my json to fill up the descriptor , I debugged the SDK code and found out that my nuget package was not adding references of NewtonSoft.Json in package so sdk was throwing assembly not found error and returning 0 analyzers. To resolve the issue I made sure my package contain reference. After that when I feed my Nuget package to SDK it is throwing following error.

///////////////////////////////////////////////////////////////////////////////////////////////////////////////// [DEBUG] Using version marked as latest. Version was not specified. Using version 1.0.0. [NuGet] Attempting to resolve dependency 'Microsoft.CodeAnalysis.Analyzers (≥ 2.9.8)'. [NuGet] Attempting to resolve dependency 'Microsoft.CodeAnalysis.CSharp (≥ 2.8.2)'. [NuGet] Attempting to resolve dependency 'Microsoft.CodeAnalysis.Common (= 2.8.2)'. [NuGet] Attempting to resolve dependency 'System.AppContext (≥ 4.3.0)'. [NuGet] Attempting to resolve dependency 'System.Collections (≥ 4.3.0)'. [NuGet] Attempting to resolve dependency 'Microsoft.NETCore.Platforms (≥ 1.1.0)'. [WARNING] [NuGet] The current value 'String' type is not compatible with the expected 'System.Int32' type. Failed to install package: Unable to resolve dependency 'Microsoft.NETCore.Platforms (≥ 1.1.0)'. Check that there are released versions of the package, or specify a pre-release version identifier. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

so I saw that my project is build on .net standard 2.0 which has Microsoft.NETCore.Platforms dependency which sdk is not able to find, so I tried changing nuget config file to use v3 , because I thought may be v2 don't contain Microsoft.NETCore.Platforms but it didn't work as after I update the nuget to v3 it even failed to find Microsoft.CodeAnalysis.Analyzers.

Then I tried changing my Project framework from .netstandard 2.0 to .net framework 4.8 which removed the Microsoft.NETCore.Platforms dependency but when I build and feed the nuget package to SDK it throws the same error.

Failed to install package: Unable to resolve dependency 'Microsoft.NETCore.Platforms (≥ 1.1.0)'. Check that there are released versions of the package, or specify a pre-release version identifier.

I Don't know if this got cached somewhere or not, any help will be really appreciated.

duncanp-sonar commented 2 years ago

Cached files: try deleting the folder %TEMP%\.sonarqube.sdk.

Also, check the debug output to see where the tool is looking for NuGet packages e.g.

[DEBUG] Parsed NuGet reference. Id: Analyzer1, version:
[DEBUG] Fetching NuGet config files...
[DEBUG] Enabled package sources:
[DEBUG]     https://www.nuget.org/api/v2/, machine-wide: False
[DEBUG]     C:\LocalNuGetFeed, machine-wide: False
[DEBUG]     D:\localnugetfeed, machine-wide: False
[DEBUG]     C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\, machine-wide: False

Can you successfully run the SDK against a new "empty" analyzer project? i.e. unfold a new analyzer project, build it and run the tool against it. I've just done that. My new project targets .netstandard2 and uses Roslyn v.2.9.8, and the tool handled it.

ketanmehra30 commented 2 years ago

It works fine when I read the data from resx files and fill diagnostic descriptor object or when I pass the values to constructor directly, that's what empty analyzer's do. In my case I am calling another custom class (DiagnosticDescriptorBuilder) to bring this data from JSON file (by using Newtonsoft.Json deserializer) because It is way easier to maintain JSON files and make changes to those files. example:- DiagnosticDescriptor descriptor = DiagnosticDescriptorBuilder.GetDescriptor(ID), this DiagnosticDescriptorBuilder reads the data from json file and returns a DiagnosticDescriptor object, this is where the SDK throws assembly not found errors which I am not sure why it is occuring, I have check the nuget paths and I do have required assemblies.

I have replicated my Issue and upload the project - https://github.com/ketanmehra30/RoslynAnalyzerTest

Code clone link-https://github.com/ketanmehra30/RoslynAnalyzerTest.git

In my replicated project I am creating nuget package using two ways, one is using DemoAnalyzer.Package using which SDK throws error that it cannot instantiate analyzers (because it is unable to resolve NewtonSoft assembly).

//////////////////////////////////////////////////////////////////////// Error: Exception has been thrown by the target of an invocation. [DEBUG] Removed AssemblyResolver from current AppDomain assembly resolution. [WARNING] No analyzers were found in package: DemoAnalyzer [WARNING] Re-run this generator with /recurse if plugins should be generated for the dependencies of this package. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

To resolve above issue, I configure DemoAnalyzer project to create nuget package on build which throws the below error ////////////////////////////////////////////////////////////////////////////// [DEBUG] Using version marked as latest. Version was not specified. Using version 1.0.0. [NuGet] Attempting to resolve dependency 'Microsoft.CodeAnalysis.Analyzers (≥ 2.9.8)'. [NuGet] Attempting to resolve dependency 'Microsoft.CodeAnalysis.CSharp (≥ 2.8.2)'. [NuGet] Attempting to resolve dependency 'Microsoft.CodeAnalysis.Common (= 2.8.2)'. [NuGet] Attempting to resolve dependency 'System.AppContext (≥ 4.3.0)'. [NuGet] Attempting to resolve dependency 'System.Collections (≥ 4.3.0)'. [NuGet] Attempting to resolve dependency 'Microsoft.NETCore.Platforms (≥ 1.1.0)'. [WARNING] [NuGet] The current value 'String' type is not compatible with the expected 'System.Int32' type. Failed to install package: Unable to resolve dependency 'Microsoft.NETCore.Platforms (≥ 1.1.0)'. Check that there are released versions of the package, or specify a pre-release version identifier. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Please correct me if I am wrong but It looks like SDK is not able to resolve any third party Nuget package references which are not related to analyzer.

Please help me rectify the issue, it will be really helpful. Thanks in advance

duncanp-sonar commented 2 years ago

@ketanmehra30 I used your repro solution and go the following error running the SDK:

image

I think this is the first error you referred to in your previous post. Note that the error message says it cannot resolve the Newtonsoft assembly, not the Newtonsoft package.

Your analyzer uses the Newtonsoft assembly, which means it needs to be available when your package is executed. This means your NuGet package needs to either (1) include the Newtonsoft assembly in your .nupkg, or (2) reference it as a package dependency.

This blog post explains one way to achieve (1).

ketanmehra30 commented 2 years ago

This blog post resolved my issue, Thanks a lot for help. Really appreciate it. I have one question regarding the jar file being generated, When I opened JAR file generated from my analyzers the Tags were missing from rules.xml file where as I can see I have passed them via diagnostic description object.

Do I have to Manually Unzip the JAR and edit the rules .xml adding my Tags and Type? is this functionality missing from SDK?

duncanp-sonar commented 2 years ago

The exe doesn't automatically add tags. See here.

If you want to manually add the tags, you should be able to add them to the generated rules template file then re-run the exe: image