File: DoNotMixAttributesFromDifferentVersionsOfMEFTests.cs
Web Access
Project: src\src\RoslynAnalyzers\Roslyn.Diagnostics.Analyzers\UnitTests\Roslyn.Diagnostics.Analyzers.UnitTests.csproj (Roslyn.Diagnostics.Analyzers.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Testing;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
    Roslyn.Diagnostics.Analyzers.DoNotMixAttributesFromDifferentVersionsOfMEFAnalyzer,
    Roslyn.Diagnostics.CSharp.Analyzers.CSharpDoNotMixAttributesFromDifferentVersionsOfMEFFixer>;
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
    Roslyn.Diagnostics.Analyzers.DoNotMixAttributesFromDifferentVersionsOfMEFAnalyzer,
    Roslyn.Diagnostics.VisualBasic.Analyzers.BasicDoNotMixAttributesFromDifferentVersionsOfMEFFixer>;
 
namespace Roslyn.Diagnostics.Analyzers.UnitTests
{
    public class DoNotMixAttributesFromDifferentVersionsOfMEFTests
    {
        private const string CSharpWellKnownAttributesDefinition = @"
namespace System.Composition
{
    public class ExportAttribute : System.Attribute
    {
        public ExportAttribute(System.Type contractType){ }
    }
 
    public class MetadataAttributeAttribute : System.Attribute
    {
        public MetadataAttributeAttribute() { }
    }
 
    public class ImportAttribute : System.Attribute
    {
        public ImportAttribute() { }
    }
 
    public class ImportingConstructorAttribute : System.Attribute
    {
        public ImportingConstructorAttribute() { }
    }
}
 
[System.Composition.MetadataAttribute]
public class SystemCompositionMetadataAttribute : System.Attribute
{
    public class ExportAttribute : System.Attribute
    {
        public ExportAttribute(System.Type contractType){ }
    }
 
    public class MetadataAttributeAttribute : System.Attribute
    {
        public MetadataAttributeAttribute() { }
    }
 
    public class ImportAttribute : System.Attribute
    {
        public ImportAttribute() { }
    }
 
    public class ImportingConstructorAttribute : System.Attribute
    {
        public ImportingConstructorAttribute() { }
    }
}
 
namespace System.ComponentModel.Composition
{
    public class ExportAttribute : System.Attribute
    {
        public ExportAttribute(System.Type contractType){ }
    }
 
    public class MetadataAttributeAttribute : System.Attribute
    {
        public MetadataAttributeAttribute() { }
    }
 
    public class ImportAttribute : System.Attribute
    {
        public ImportAttribute() { }
    }
 
    public class ImportingConstructorAttribute : System.Attribute
    {
        public ImportingConstructorAttribute() { }
    }
}
 
[System.ComponentModel.Composition.MetadataAttribute]
public class SystemComponentModelCompositionMetadataAttribute : System.Attribute
{
}
";
        private const string BasicWellKnownAttributesDefinition = @"
Namespace System.Composition
	Public Class ExportAttribute
		Inherits System.Attribute
		Public Sub New(contractType As System.Type)
		End Sub
	End Class
 
	Public Class MetadataAttributeAttribute
		Inherits System.Attribute
		Public Sub New()
		End Sub
	End Class
 
    Public Class ImportAttribute
	    Inherits System.Attribute
	    Public Sub New()
	    End Sub
    End Class
 
    Public Class ImportingConstructorAttribute
	    Inherits System.Attribute
	    Public Sub New()
	    End Sub
    End Class
End Namespace
 
<System.Composition.MetadataAttribute> _
Public Class SystemCompositionMetadataAttribute
	Inherits System.Attribute
End Class
 
Namespace System.ComponentModel.Composition
	Public Class ExportAttribute
		Inherits System.Attribute
		Public Sub New(contractType As System.Type)
		End Sub
	End Class
 
    Public Class MetadataAttributeAttribute
		Inherits System.Attribute
		Public Sub New()
		End Sub
	End Class
 
        Public Class ImportAttribute
	    Inherits System.Attribute
	    Public Sub New()
	    End Sub
    End Class
 
    Public Class ImportingConstructorAttribute
	    Inherits System.Attribute
	    Public Sub New()
	    End Sub
    End Class
End Namespace
 
<System.ComponentModel.Composition.MetadataAttribute> _
Public Class SystemComponentModelCompositionMetadataAttribute
	Inherits System.Attribute
End Class
";
 
        #region No Diagnostic Tests
 
        [Fact]
        public async Task NoDiagnosticCases_SingleMefAttributeAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using System;
 
[System.Composition.Export(typeof(C))]
public class C
{
}
 
[System.ComponentModel.Composition.Export(typeof(C2))]
public class C2
{
}
" + CSharpWellKnownAttributesDefinition);
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
<System.Composition.Export(GetType(C))> _
Public Class C
End Class
 
<System.ComponentModel.Composition.Export(GetType(C2))> _
Public Class C2
End Class
" + BasicWellKnownAttributesDefinition);
        }
 
        [Fact]
        public async Task NoDiagnosticCases_SingleMefAttributeAndValidMetadataAttributeAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using System;
 
[System.Composition.Export(typeof(C))]
[SystemCompositionMetadataAttribute]
public class C
{
}
 
[System.ComponentModel.Composition.Export(typeof(C2))]
[SystemComponentModelCompositionMetadataAttribute]
public class C2
{
}
" + CSharpWellKnownAttributesDefinition);
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
<System.Composition.Export(GetType(C))> _
<SystemCompositionMetadataAttribute> _
Public Class C
End Class
 
<System.ComponentModel.Composition.Export(GetType(C2))> _
<SystemComponentModelCompositionMetadataAttribute> _
Public Class C2
End Class
" + BasicWellKnownAttributesDefinition);
        }
 
        [Fact]
        public async Task NoDiagnosticCases_SingleMefAttributeAndAnotherExportAttributeAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using System;
 
[System.Composition.Export(typeof(C)), MyNamespace.Export(typeof(C))]
public class C
{
}
 
[System.ComponentModel.Composition.Export(typeof(C2)), MyNamespace.Export(typeof(C2))]
public class C2
{
}
 
namespace MyNamespace
{
    public class ExportAttribute : System.Attribute
    {
        public ExportAttribute(System.Type contractType){ }
    }
}
" + CSharpWellKnownAttributesDefinition);
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
<System.Composition.Export(GetType(C)), MyNamespace.Export(GetType(C))> _
Public Class C
End Class
 
<System.ComponentModel.Composition.Export(GetType(C2)), MyNamespace.Export(GetType(C2))> _
Public Class C2
End Class
 
Namespace MyNamespace
	Public Class ExportAttribute
		Inherits System.Attribute
		Public Sub New(contractType As System.Type)
		End Sub
	End Class
End Namespace
" + BasicWellKnownAttributesDefinition);
        }
 
        [Fact]
        public async Task NoDiagnosticCases_SingleMefAttributeOnTypeAndValidMefAttributeOnMemberAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using System;
 
public class B { }
 
[System.Composition.Export(typeof(C))]
public class C
{
    [System.Composition.ImportingConstructor]
    public C([System.Composition.Import]B b) { }
 
    [System.Composition.Import]
    public B PropertyB { get; }
}
 
[System.ComponentModel.Composition.Export(typeof(C2))]
public class C2
{
    [System.ComponentModel.Composition.ImportingConstructor]
    public C2([System.ComponentModel.Composition.Import]B b) { }
 
    [System.ComponentModel.Composition.Import]
    public B PropertyB { get; }
}
" + CSharpWellKnownAttributesDefinition);
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Public Class B
End Class
 
<System.Composition.Export(GetType(C))> _
Public Class C
	<System.Composition.ImportingConstructor> _
	Public Sub New(<System.Composition.Import> b As B)
	End Sub
 
	<System.Composition.Import> _
	Public ReadOnly Property PropertyB() As B
End Class
 
<System.ComponentModel.Composition.Export(GetType(C2))> _
Public Class C2
	<System.ComponentModel.Composition.ImportingConstructor> _
	Public Sub New(<System.ComponentModel.Composition.Import> b As B)
	End Sub
 
	<System.ComponentModel.Composition.Import> _
	Public ReadOnly Property PropertyB() As B
End Class
" + BasicWellKnownAttributesDefinition);
        }
 
        [Fact]
        public async Task NoDiagnosticCases_UnresolvedTypesAsync()
        {
            await new VerifyCS.Test
            {
                TestState =
                {
                    Sources =
                    {
                        @"
using System;
 
public class B { }
 
[System.{|CS0234:Composition|}.Export(typeof(C))]
public class C
{
    [System.ComponentModel.{|CS0234:Composition|}.Import]
    public B PropertyB { get; }
}
"
                    },
                },
                ReferenceAssemblies = ReferenceAssemblies.Default,
            }.RunAsync();
 
            await new VerifyVB.Test
            {
                TestState =
                {
                    Sources =
                    {
                        @"
Public Class B
End Class
 
<{|BC30002:System.Composition.Export|}(GetType(C))> _
Public Class C
	<{|BC30002:System.ComponentModel.Composition.Import|}> _
	Public ReadOnly Property PropertyB() As B
End Class
"
                    },
                },
                ReferenceAssemblies = ReferenceAssemblies.Default,
            }.RunAsync();
        }
 
        [Fact]
        public async Task NoDiagnosticCases_MultiMefMetadataAttributeAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using System;
 
[System.ComponentModel.Composition.Export(typeof(C)), MyNamespace.MultiMefMetadataAttribute]
public class C
{
}
 
namespace MyNamespace
{
    [System.ComponentModel.Composition.MetadataAttribute, System.Composition.MetadataAttribute]
    public class MultiMefMetadataAttribute : System.Attribute
    {
    }
}
" + CSharpWellKnownAttributesDefinition);
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
<System.ComponentModel.Composition.Export(GetType(C)), MyNamespace.MultiMefMetadataAttribute> _
Public Class C
End Class
 
Namespace MyNamespace
    <System.ComponentModel.Composition.MetadataAttribute, System.Composition.MetadataAttribute> _
	Public Class MultiMefMetadataAttribute
		Inherits System.Attribute
	End Class
End Namespace
" + BasicWellKnownAttributesDefinition);
        }
 
        #endregion
 
        #region Diagnostic Tests
 
        [Fact]
        public async Task DiagnosticCases_BadMetadataAttributeAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using System;
 
[System.Composition.Export(typeof(C))]
[SystemComponentModelCompositionMetadataAttribute]
public class C
{
}
 
[System.ComponentModel.Composition.Export(typeof(C2))]
[SystemCompositionMetadataAttribute]
public class C2
{
}
" + CSharpWellKnownAttributesDefinition,
    // Test0.cs(5,2): warning RS0006: Attribute 'SystemComponentModelCompositionMetadataAttribute' comes from a different version of MEF than the export attribute on 'C'
    GetCSharpResultAt(5, 2, "SystemComponentModelCompositionMetadataAttribute", "C"),
    // Test0.cs(11,2): warning RS0006: Attribute 'SystemCompositionMetadataAttribute' comes from a different version of MEF than the export attribute on 'C2'
    GetCSharpResultAt(11, 2, "SystemCompositionMetadataAttribute", "C2"));
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
<System.Composition.Export(GetType(C))> _
<SystemComponentModelCompositionMetadataAttribute> _
Public Class C
End Class
 
<System.ComponentModel.Composition.Export(GetType(C2))> _
<SystemCompositionMetadataAttribute> _
Public Class C2
End Class
" + BasicWellKnownAttributesDefinition,
    // Test0.vb(5,2): warning RS0006: Attribute 'SystemComponentModelCompositionMetadataAttribute' comes from a different version of MEF than the export attribute on 'C'
    GetBasicResultAt(5, 2, "SystemComponentModelCompositionMetadataAttribute", "C"),
    // Test0.vb(10,2): warning RS0006: Attribute 'SystemCompositionMetadataAttribute' comes from a different version of MEF than the export attribute on 'C2'
    GetBasicResultAt(10, 2, "SystemCompositionMetadataAttribute", "C2"));
        }
 
        [Fact]
        public async Task DiagnosticCases_BadMefAttributeOnMemberAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using System;
 
public class B { }
 
[System.Composition.Export(typeof(C))]
public class C
{
    [System.ComponentModel.Composition.ImportingConstructor]
    public C([System.Composition.Import]B b) { }
 
    [System.ComponentModel.Composition.Import]
    public B PropertyB { get; }
}
 
[System.ComponentModel.Composition.Export(typeof(C2))]
public class C2
{
    [System.Composition.ImportingConstructor]
    public C2([System.ComponentModel.Composition.Import]B b) { }
 
    [System.Composition.Import]
    public B PropertyB { get; }
}
" + CSharpWellKnownAttributesDefinition,
    // Test0.cs(9,6): warning RS0006: Attribute 'ImportingConstructorAttribute' comes from a different version of MEF than the export attribute on 'C'
    GetCSharpResultAt(9, 6, "ImportingConstructorAttribute", "C"),
    // Test0.cs(12,6): warning RS0006: Attribute 'ImportAttribute' comes from a different version of MEF than the export attribute on 'C'
    GetCSharpResultAt(12, 6, "ImportAttribute", "C"),
    // Test0.cs(19,6): warning RS0006: Attribute 'ImportingConstructorAttribute' comes from a different version of MEF than the export attribute on 'C2'
    GetCSharpResultAt(19, 6, "ImportingConstructorAttribute", "C2"),
    // Test0.cs(22,6): warning RS0006: Attribute 'ImportAttribute' comes from a different version of MEF than the export attribute on 'C2'
    GetCSharpResultAt(22, 6, "ImportAttribute", "C2")
);
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Public Class B
End Class
 
<System.Composition.Export(GetType(C))> _
Public Class C
	<System.ComponentModel.Composition.ImportingConstructor> _
	Public Sub New(<System.Composition.Import> b As B)
	End Sub
 
	<System.ComponentModel.Composition.Import> _
	Public ReadOnly Property PropertyB() As B
End Class
 
<System.ComponentModel.Composition.Export(GetType(C2))> _
Public Class C2
	<System.Composition.ImportingConstructor> _
	Public Sub New(<System.ComponentModel.Composition.Import> b As B)
	End Sub
 
	<System.Composition.Import> _
	Public ReadOnly Property PropertyB() As B
End Class
" + BasicWellKnownAttributesDefinition,
    // Test0.vb(7,3): warning RS0006: Attribute 'ImportingConstructorAttribute' comes from a different version of MEF than the export attribute on 'C'
    GetBasicResultAt(7, 3, "ImportingConstructorAttribute", "C"),
    // Test0.vb(11,3): warning RS0006: Attribute 'ImportAttribute' comes from a different version of MEF than the export attribute on 'C'
    GetBasicResultAt(11, 3, "ImportAttribute", "C"),
    // Test0.vb(17,3): warning RS0006: Attribute 'ImportingConstructorAttribute' comes from a different version of MEF than the export attribute on 'C2'
    GetBasicResultAt(17, 3, "ImportingConstructorAttribute", "C2"),
    // Test0.vb(21,3): warning RS0006: Attribute 'ImportAttribute' comes from a different version of MEF than the export attribute on 'C2'
    GetBasicResultAt(21, 3, "ImportAttribute", "C2")
);
        }
 
        [Fact]
        public async Task DiagnosticCases_BadMefAttributeOnParameterAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using System;
 
public class B { }
 
[System.Composition.Export(typeof(C))]
public class C
{
    [System.Composition.ImportingConstructor]
    public C([System.ComponentModel.Composition.Import]B b) { }
 
    [System.Composition.Import]
    public B PropertyB { get; }
}
 
[System.ComponentModel.Composition.Export(typeof(C2))]
public class C2
{
    [System.ComponentModel.Composition.ImportingConstructor]
    public C2([System.Composition.Import]B b) { }
 
    [System.ComponentModel.Composition.Import]
    public B PropertyB { get; }
}
" + CSharpWellKnownAttributesDefinition,
    // Test0.cs(10,15): warning RS0006: Attribute 'ImportAttribute' comes from a different version of MEF than the export attribute on 'C'
    GetCSharpResultAt(10, 15, "ImportAttribute", "C"),
    // Test0.cs(20,16): warning RS0006: Attribute 'ImportAttribute' comes from a different version of MEF than the export attribute on 'C2'
    GetCSharpResultAt(20, 16, "ImportAttribute", "C2"));
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Public Class B
End Class
 
<System.Composition.Export(GetType(C))> _
Public Class C
	<System.Composition.ImportingConstructor> _
	Public Sub New(<System.ComponentModel.Composition.Import> b As B)
	End Sub
 
	<System.Composition.Import> _
	Public ReadOnly Property PropertyB() As B
End Class
 
<System.ComponentModel.Composition.Export(GetType(C2))> _
Public Class C2
	<System.ComponentModel.Composition.ImportingConstructor> _
	Public Sub New(<System.Composition.Import> b As B)
	End Sub
 
	<System.ComponentModel.Composition.Import> _
	Public ReadOnly Property PropertyB() As B
End Class
" + BasicWellKnownAttributesDefinition,
    // Test0.vb(8,18): warning RS0006: Attribute 'ImportAttribute' comes from a different version of MEF than the export attribute on 'C'
    GetBasicResultAt(8, 18, "ImportAttribute", "C"),
    // Test0.vb(18,18): warning RS0006: Attribute 'ImportAttribute' comes from a different version of MEF than the export attribute on 'C2'
    GetBasicResultAt(18, 18, "ImportAttribute", "C2"));
        }
 
        #endregion
 
        private static DiagnosticResult GetCSharpResultAt(int line, int column, string attributeName, string typeName) =>
#pragma warning disable RS0030 // Do not use banned APIs
            VerifyCS.Diagnostic()
                .WithLocation(line, column)
#pragma warning restore RS0030 // Do not use banned APIs
                .WithArguments(attributeName, typeName);
 
        private static DiagnosticResult GetBasicResultAt(int line, int column, string attributeName, string typeName) =>
#pragma warning disable RS0030 // Do not use banned APIs
            VerifyVB.Diagnostic()
                .WithLocation(line, column)
#pragma warning restore RS0030 // Do not use banned APIs
                .WithArguments(attributeName, typeName);
    }
}