Writing VB.NET custom rule

Hi,
I am trying to write custom rules for VB.NET and while going through documentation(https://docs.sonarqube.org/display/DEV/Adding+Coding+Rules) i came to know about sonarqube-roslyn-sdk so i created a code fix analyzer for VB in visual studio 2017 and then tried to convert that nuget package into jar file using sonarqube-roslyn-sdk but it is not able to convert then i came to know that it has limitation that it is available for c# rules(https://github.com/SonarSource/sonarqube-roslyn-sdk).So can anyone has idea how to write custom rules for VB.NET?

Writing a customer .Net analyzer independent from SonarQube seems like the good way to go. And then very soon you’ll be able to leverage this cool SonarQube functionality: Issues found by Roslyn analysers attached to a VS solution/project should be automatically imported in SonarQube . (at which this Roslyn SDK you found out will ultimately belong the past, as it indeed had quite some limitations)

@NicoB Thank you for your response.
When i explored more about this i came to know that visual basic analyzer has been implemented in SonarC# plugin but my concerned is that vb analyzer which i have written is working fine in visual studio 2017 as i can debug and verify but when i am unit testing it is failing. @Ammo as i can see you areone of the contributor on https://github.com/SonarSource/sonar-csharp/tree/master/sonaranalyzer-dotnet/src/SonarAnalyzer.VisualBasic . Any help will be highly appreciated. Please find below implementation files which check any string values and report diagnostic with unit test file :

Sample_analyzer.cs

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.CodeAnalysis.VisualBasic.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;

namespace Analyzer3
{
[DiagnosticAnalyzer(LanguageNames.VisualBasic)]
public class Analyzer3Analyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = “Analyzer3”;

    private static readonly LocalizableString Title = "Hardcoded value not allowed.";
    private static readonly LocalizableString MessageFormat = "Hardcoded value not allowed.";                      
    private static readonly LocalizableString Description = "Hardcoded value not allowed.";
    private const string Category = "Naming";

    private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: Description);

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

    public override void Initialize(AnalysisContext context)
    {
       
        context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.StringLiteralExpression);
    }

    private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
    {
        
        var stringLiteral = (LiteralExpressionSyntax)context.Node;

        if (stringLiteral != null)
        {
            var diagnostic = Diagnostic.Create(Rule, stringLiteral.GetLocation());

            context.ReportDiagnostic(diagnostic);
        }
    }
}

}

Sample_analyzerUnitTest.cs

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using TestHelper;
using Analyzer3;

namespace Analyzer3.Test
{
[TestClass]
public class UnitTest : CodeFixVerifier
{

    [TestMethod]
    public void TestMethod1()
    {
        var test = @"";

        VerifyCSharpDiagnostic(test);
    }

    [TestMethod]
    public void TestMethod2()
    {
        var test = @"
Imports System

Module Program
Sub Main(args As String())

    Dim a = ""Hello world!""

End Sub

End Module";
var expected = new DiagnosticResult
{
Id = “Analyzer3”,
Message = String.Format(“Hardcoded value not allowed.”),
Severity = DiagnosticSeverity.Warning,
Locations =
new {
new DiagnosticResultLocation(“Test0.vb”, 7, 18)
}
};

        VerifyCSharpDiagnostic(test, expected);
    }

    protected override DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer()
    {
        return new Analyzer3Analyzer();
    }
}

}

Here i am having doubt that whether i should use GetCSharpDiagnosticAnalyzer() or GetBasicDiagnosticAnalyzer().

Hi @vicky,

The code sample you’ve pasted looks like the standard boilerplate test code generated when unfolding a new Roslyn analyzer template, so I’d guess you should be calling VerifyBasicDiagnosticAnalyzer in _TestMethod2 and overriding GetBasicDiagnosticAnalyzer.

However, this forum is specifically about SonarQube/Cloud/Lint, so questions purely about developing Roslyn analyzers are definitely off-topic and are less likely to be answered. A better place to ask would be on a general forum like StackOverflow.

Regards,
Duncan

Hi @duncanp,

Sorry for posting the analyzer question here but i believe that documentation is missing regarding customizing vb.net plugin which requires this analyzer.

Coming to issue i already tried using the methods you mentioned above but it was throwing error: System.IO.FileNotFoundException’ with message 'Could not load file or assembly 'Microsoft.CodeAnalysis.VisualBasic even though i have added this nuget package.

@NicoB You mention that Roslyn SDK will ultimately belong to the past with the implementation of the external issues feature.

While the external issues feature helps in reporting issues from the custom analyzers in VB.NET projects it won’t allow to use Quality Profiles in SonarQube for ruleset management.

For us this would also be an important feature to have as we have custom analyzers for C# and VB.NET and projects in both languages. As long as the SDK doesn’t support VB.NET we won’t be able to use SonarQube as as central place for issue management, documentation and to manage quality gates.