|
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
Microsoft.CodeQuality.CSharp.Analyzers.Maintainability.CSharpMakeTypesInternal,
Microsoft.CodeQuality.CSharp.Analyzers.Maintainability.CSharpMakeTypesInternalFixer>;
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability.BasicMakeTypesInternal,
Microsoft.CodeQuality.VisualBasic.Analyzers.Maintainability.BasicMakeTypesInternalFixer>;
namespace Microsoft.CodeQuality.Analyzers.Maintainability.UnitTests
{
public sealed class MakeTypesInternalTests
{
private static readonly IEnumerable<OutputKind> ExecutableOutputKinds =
[
OutputKind.ConsoleApplication,
OutputKind.WindowsRuntimeApplication,
OutputKind.WindowsApplication
];
public static readonly TheoryData<OutputKind> DiagnosticTriggeringOutputKinds = new(ExecutableOutputKinds);
public static readonly TheoryData<OutputKind> NonDiagnosticTriggeringOutputKinds = new(Enum.GetValues<OutputKind>().Except(ExecutableOutputKinds));
[Theory]
[MemberData(nameof(NonDiagnosticTriggeringOutputKinds))]
public async Task LibraryCode_NoDiagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind, "public class MyService {}");
await VerifyVbAsync(outputKind, "Public Class MyService\nEnd Class");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task ApplicationCode_Diagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public class [|Program|]
{
public static void Main() {}
}
""",
"""
internal class Program
{
public static void Main() {}
}
""");
await VerifyVbAsync(outputKind,
"""
Public Class [|Program|]
Public Shared Sub Main()
End Sub
End Class
""",
"""
Friend Class Program
Public Shared Sub Main()
End Sub
End Class
""");
}
[Theory]
[MemberData(nameof(NonDiagnosticTriggeringOutputKinds))]
public async Task MultipleTypes_LibraryCode_NoDiagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public class MyTests {}
internal class MyService {}
public class MyValidator {}
""");
await VerifyVbAsync(outputKind,
"""
Public Class MyTests
End Class
Friend Class MyService
End Class
Public Class MyValidator
End Class
""");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task MultipleTypes_ApplicationCode_Diagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public class [|Program|]
{
public static void Main() {}
}
internal class MyService {}
public class [|MyValidator|] {}
""",
"""
internal class Program
{
public static void Main() {}
}
internal class MyService {}
internal class MyValidator {}
""");
await VerifyVbAsync(outputKind,
"""
Public Class [|Program|]
Public Shared Sub Main()
End Sub
End Class
Friend Class MyService
End Class
Public Class [|MyValidator|]
End Class
""",
"""
Friend Class Program
Public Shared Sub Main()
End Sub
End Class
Friend Class MyService
End Class
Friend Class MyValidator
End Class
""");
}
[Theory]
[MemberData(nameof(NonDiagnosticTriggeringOutputKinds))]
public async Task MultipleDifferentTypes_LibraryCode_NoDiagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public class MyTests {}
public abstract class MyBaseType {}
public struct MyValueType {}
public interface IValidator {}
public enum Types {}
""");
await VerifyVbAsync(outputKind,
"""
Public Class MyTests
End Class
Public MustInherit Class MyBaseType
End Class
Public Structure MyValueType
End Structure
Public Interface IValidator
End Interface
Public Enum Types
None
End Enum
""");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task MultipleDifferentTypes_ApplicationCode_Diagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public class [|Program|]
{
public static void Main() {}
}
public abstract class [|MyBaseType|] {}
public struct [|MyValueType|] {}
public interface [|IValidator|] {}
public record [|Person|];
public enum [|Types|] {}
""",
"""
internal class Program
{
public static void Main() {}
}
internal abstract class MyBaseType {}
internal struct MyValueType {}
internal interface IValidator {}
internal record Person;
internal enum Types {}
""");
await VerifyVbAsync(outputKind,
"""
Public Class [|Program|]
Public Shared Sub Main()
End Sub
End Class
Public MustInherit Class [|MyBaseType|]
End Class
Public Structure [|MyValueType|]
End Structure
Public Interface [|IValidator|]
End Interface
Public Enum [|Types|]
None
End Enum
""",
"""
Friend Class Program
Public Shared Sub Main()
End Sub
End Class
Friend MustInherit Class MyBaseType
End Class
Friend Structure MyValueType
End Structure
Friend Interface IValidator
End Interface
Friend Enum Types
None
End Enum
""");
}
[Theory]
[InlineData(OutputKind.DynamicallyLinkedLibrary)]
[InlineData(OutputKind.WindowsRuntimeMetadata)]
public Task Records_LibraryCode_NoDiagnostic(OutputKind outputKind)
{
return VerifyCsAsync(outputKind, @"public record Person;");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public Task Records_ApplicationCode_Diagnostic(OutputKind outputKind)
{
return VerifyCsAsync(outputKind,
"""
public class [|Program|]
{
public static void Main() {}
}
public record [|Person|];
""",
"""
internal class Program
{
public static void Main() {}
}
internal record Person;
""");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task NoModifier_ApplicationCode_NoDiagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
class Program
{
public static void Main() {}
}
class MyService {}
sealed class MyValidator {}
""");
await VerifyVbAsync(outputKind,
"""
Class Program
Public Shared Sub Main()
End Sub
End Class
Class MyService
End Class
NotInheritable Class MyValidator
End Class
""");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task MultipleModifiers_ApplicationCode_Diagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public class [|Program|]
{
public static void Main() {}
}
public sealed class [|MyService|] {}
public abstract partial class [|MyValidator|] {}
public partial interface [|IValidator|] {}
""",
"""
internal class Program
{
public static void Main() {}
}
internal sealed class MyService {}
internal abstract partial class MyValidator {}
internal partial interface IValidator {}
""");
await VerifyVbAsync(outputKind,
"""
Public Class [|Program|]
Public Shared Sub Main()
End Sub
End Class
Public NotInheritable Class [|MyService|]
End Class
Public Partial MustInherit Class [|MyValidator|]
End Class
Public Partial Interface [|IValidator|]
End Interface
""",
"""
Friend Class Program
Public Shared Sub Main()
End Sub
End Class
Friend NotInheritable Class MyService
End Class
Friend Partial MustInherit Class MyValidator
End Class
Friend Partial Interface IValidator
End Interface
""");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task MultipleUnorderedModifiers_ApplicationCode_Diagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public class [|Program|]
{
public static void Main() {}
}
sealed public class [|MyService|] {}
""",
"""
internal class Program
{
public static void Main() {}
}
sealed internal class MyService {}
""");
await VerifyVbAsync(outputKind,
"""
Public Class [|Program|]
Public Shared Sub Main()
End Sub
End Class
NotInheritable Public Class [|MyService|]
End Class
""",
"""
Friend Class Program
Public Shared Sub Main()
End Sub
End Class
NotInheritable Friend Class MyService
End Class
""");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task NestedTypes_ApplicationCode_NoDiagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
class Program
{
public static void Main() {}
public struct [|MyValueType|]
{
public class [|Nested|] {}
}
}
""",
"""
class Program
{
public static void Main() {}
internal struct MyValueType
{
internal class Nested {}
}
}
""");
await VerifyVbAsync(outputKind,
"""
Class Program
Public Shared Sub Main()
End Sub
Public Structure [|MyValueType|]
Public Class [|Nested|]
End Class
End Structure
End Class
""",
"""
Class Program
Public Shared Sub Main()
End Sub
Friend Structure MyValueType
Friend Class Nested
End Class
End Structure
End Class
""");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task ProtectedTypes_ApplicationCode_NoDiagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
class Program
{
public static void Main() {}
protected abstract class MyService {}
}
""");
await VerifyVbAsync(outputKind,
"""
Class Program
Public Shared Sub Main()
End Sub
Protected MustInherit Class MyService
End Class
End Class
""");
}
[Theory]
[MemberData(nameof(NonDiagnosticTriggeringOutputKinds))]
public async Task Delegates_LibraryCode_NoDiagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public delegate int GetValue(string s);
public delegate void Print(object x);
public delegate bool Match();
""");
await VerifyVbAsync(outputKind,
"""
Imports System
Public Delegate Function GetValue(s As String) As Int32
Public Delegate Sub Print(x As Object)
Public Delegate Function Match() As Boolean
""");
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task Delegates_ApplicationCode_Diagnostic(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
public delegate int [|GetValue|](string s);
public delegate void [|Print|](object x);
public delegate bool [|Match|]();
internal delegate char GetFirst(string s);
class Program {
public static void Main() {}
}
""",
"""
internal delegate int GetValue(string s);
internal delegate void Print(object x);
internal delegate bool Match();
internal delegate char GetFirst(string s);
class Program {
public static void Main() {}
}
""");
await VerifyVbAsync(outputKind,
"""
Imports System
Public Delegate Function [|GetValue|](s As String) As Int32
Public Delegate Sub [|Print|](x As Object)
Public Delegate Function [|Match|]() As Boolean
Friend Delegate Function GetFirst(s As String) As Char
Class Program
Public Shared Sub Main()
End Sub
End Class
""",
"""
Imports System
Friend Delegate Function GetValue(s As String) As Int32
Friend Delegate Sub Print(x As Object)
Friend Delegate Function Match() As Boolean
Friend Delegate Function GetFirst(s As String) As Char
Class Program
Public Shared Sub Main()
End Sub
End Class
""");
}
[Theory]
[InlineData("DynamicallyLinkedLibrary", OutputKind.DynamicallyLinkedLibrary)]
[InlineData("ConsoleApplication", OutputKind.ConsoleApplication)]
[InlineData("ConsoleApplication,DynamicallyLinkedLibrary", OutputKind.DynamicallyLinkedLibrary)]
[InlineData("WindowsApplication", OutputKind.WindowsApplication)]
[InlineData("WindowsRuntimeApplication", OutputKind.WindowsRuntimeApplication)]
[InlineData("ConsoleApplication,WindowsApplication", OutputKind.WindowsApplication)]
[InlineData("ConsoleApplication,WindowsApplication,WindowsRuntimeApplication",
OutputKind.WindowsRuntimeApplication)]
public async Task CompilationOptions_Diagnostic(string optionsText, OutputKind outputKind)
{
await new VerifyCS.Test
{
TestCode = """
public class [|Program|]
{
public static void Main() {}
}
""",
FixedCode = """
internal class Program
{
public static void Main() {}
}
""",
TestState =
{
OutputKind = outputKind,
AnalyzerConfigFiles =
{
("/.editorconfig",
$"""
root = true
[*]
dotnet_code_quality.CA1515.output_kind = {optionsText}
""")
}
},
LanguageVersion = LanguageVersion.CSharp10
}.RunAsync();
await new VerifyVB.Test
{
TestCode = """
Public Class [|Program|]
Public Shared Sub Main()
End Sub
End Class
""",
FixedCode = """
Friend Class Program
Public Shared Sub Main()
End Sub
End Class
""",
TestState =
{
OutputKind = outputKind,
AnalyzerConfigFiles =
{
("/.editorconfig",
$"""
root = true
[*]
dotnet_code_quality.CA1515.output_kind = {optionsText}
""")
}
},
}.RunAsync();
}
[Theory]
[InlineData("ConsoleApplication", OutputKind.DynamicallyLinkedLibrary)]
[InlineData("DynamicallyLinkedLibrary", OutputKind.ConsoleApplication)]
[InlineData("WindowsApplication", OutputKind.ConsoleApplication)]
[InlineData("WindowsRuntimeApplication", OutputKind.ConsoleApplication)]
[InlineData("ConsoleApplication,WindowsApplication", OutputKind.WindowsRuntimeApplication)]
[InlineData("ConsoleApplication,WindowsApplication,WindowsRuntimeApplication",
OutputKind.DynamicallyLinkedLibrary)]
public async Task CompilationOptions_NoDiagnostic(string optionsText, OutputKind outputKind)
{
await new VerifyCS.Test
{
TestCode = """
public class Program
{
public static void Main() {}
}
""",
TestState =
{
OutputKind = outputKind,
AnalyzerConfigFiles =
{
("/.editorconfig",
$"""
root = true
[*]
dotnet_code_quality.CA1515.output_kind = {optionsText}
""")
}
},
LanguageVersion = LanguageVersion.CSharp10
}.RunAsync();
await new VerifyVB.Test
{
TestCode = """
Public Class Program
Public Shared Sub Main()
End Sub
End Class
""",
TestState =
{
OutputKind = outputKind,
AnalyzerConfigFiles =
{
("/.editorconfig",
$"""
root = true
[*]
dotnet_code_quality.CA1515.output_kind = {optionsText}
""")
}
},
}.RunAsync();
}
[Theory]
[MemberData(nameof(DiagnosticTriggeringOutputKinds))]
public async Task Trivia(OutputKind outputKind)
{
await VerifyCsAsync(outputKind,
"""
// This is the entry point class.
public class [|Program|]
{
public static void Main() {}
}
""",
"""
// This is the entry point class.
internal class Program
{
public static void Main() {}
}
""");
await VerifyVbAsync(outputKind,
"""
' This is the entry point class.
Public Class [|Program|]
Public Shared Sub Main()
End Sub
End Class
""",
"""
' This is the entry point class.
Friend Class Program
Public Shared Sub Main()
End Sub
End Class
""");
}
private Task VerifyCsAsync(OutputKind outputKind, string testCode, string fixedCode = null)
{
return new VerifyCS.Test
{
TestCode = testCode,
FixedCode = fixedCode!,
TestState = { OutputKind = outputKind },
LanguageVersion = LanguageVersion.CSharp10
}.RunAsync();
}
private Task VerifyVbAsync(OutputKind outputKind, string testCode, string fixedCode = null)
{
return new VerifyVB.Test
{
TestCode = testCode,
FixedCode = fixedCode!,
TestState = { OutputKind = outputKind }
}.RunAsync();
}
}
} |