/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Core/CodeAnalysisTest/Diagnostics/SuppressMessageTargetSymbolResolverTests.cs
1 460 строк
36 KB
Jan Jones
Check type parameter index bounds when parsing `DocumentationCommentId` (#65457)
18 ноя 2022, 22:01
Не верифицирован
18 ноя 2022, 22:01
e71aa37
Код
Авторство
О чём код?
// 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. #nullable disable using System.Linq; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.VisualBasic; using Microsoft.CodeAnalysis.VisualBasic.UnitTests; using Roslyn.Test.Utilities; using Xunit; using System.Collections.Generic; using System.Collections.Immutable; namespace Microsoft.CodeAnalysis.UnitTests.Diagnostics { public class SuppressMessageTargetSymbolResolverTests { [Fact] public void TestResolveGlobalNamespace1() { VerifyNamespaceResolution("namespace $$N {}", LanguageNames.CSharp, false, "N"); } [Fact] public void TestResolveGlobalNamespace2() { VerifyNamespaceResolution(@" Namespace $$N End Namespace", LanguageNames.VisualBasic, false, "N"); } [Fact] public void TestResolveNestedNamespace1() { VerifyNamespaceResolution(@" namespace A { namespace B.$$C { } } ", LanguageNames.CSharp, false, "A.B.C"); } [Fact] public void TestResolveNestedNamespace2() { VerifyNamespaceResolution(@" Namespace A Namespace B.$$C End Namespace End Namespace ", LanguageNames.VisualBasic, false, "A.B.C"); } [Fact] public void TestResolveNamespaceWithSameNameAsGenericInterface1() { VerifyNamespaceResolution(@" namespace $$IGoo { } interface IGoo<T> { } ", LanguageNames.CSharp, false, "IGoo"); } [Fact] public void TestResolveNamespaceWithSameNameAsGenericInterface2() { VerifyNamespaceResolution(@" Namespace $$IGoo End Namespace Interface IGoo(Of T) End Interface ", LanguageNames.VisualBasic, false, "IGoo"); } [Fact] public void TestDontPartiallyResolveNamespace1() { VerifyNoNamespaceResolution(@" namespace A { namespace B { } } ", LanguageNames.CSharp, false, "A+B", "A#B"); } [Fact] public void TestDontPartiallyResolveNamespace2() { VerifyNoNamespaceResolution(@" Namespace A Namespace B End Namespace End Namespace ", LanguageNames.VisualBasic, false, "A+B", "A#B"); } [Fact] public void TestResolveGlobalType1() { VerifyTypeResolution("class $$C {}", LanguageNames.CSharp, false, "C"); } [Fact] public void TestResolveGlobalType2() { VerifyTypeResolution(@" Class $$C End Class", LanguageNames.VisualBasic, false, "C"); } [Fact] public void TestResolveModule() { VerifyTypeResolution(@" Module $$C End Module", LanguageNames.VisualBasic, false, "C"); } [Fact] public void TestResolveTypeInModule() { VerifyTypeResolution(@" Module M Class $$C End Class End Module", LanguageNames.VisualBasic, false, "M+C"); } [Fact] public void TestDontPartiallyResolveTypeInModule() { VerifyNoTypeResolution(@" Module M Class C End Class End Module", LanguageNames.VisualBasic, false, "M.C"); } [Fact] public void TestNestedTypesInModule() { VerifyTypeResolution(@" Module M Class C Structure $$D End Structure End Class End Module", LanguageNames.VisualBasic, false, "M+C+D"); } [Fact] public void TestResolveTypeInNamespace1() { VerifyTypeResolution(@" namespace N1.N2 { class $$C { } } ", LanguageNames.CSharp, false, "N1.N2.C"); } [Fact] public void TestResolveTypeInNamespace2() { VerifyTypeResolution(@" Namespace N1.N2 Class $$C End Class End Namespace ", LanguageNames.VisualBasic, false, "N1.N2.C"); } [Fact] public void TestResolveTypeNestedInGlobalType1() { VerifyTypeResolution(@" class C { interface $$D { } } ", LanguageNames.CSharp, false, "C+D"); } [Fact] public void TestResolveTypeNestedInGlobalType2() { VerifyTypeResolution(@" Class C Public Delegate Sub $$D() End Class ", LanguageNames.VisualBasic, false, "C+D"); } [Fact] public void TestResolveNestedType1() { VerifyTypeResolution(@" namespace N { class C { class D { class $$E { } } } } ", LanguageNames.CSharp, false, "N.C+D+E"); } [Fact] public void TestResolveNestedType2() { VerifyTypeResolution(@" Namespace N Class C Class D Class $$E End Class End Class End Class End Namespace ", LanguageNames.VisualBasic, false, "N.C+D+E"); } [Fact] public void TestResolveGenericType1() { VerifyTypeResolution(@" class D<T> { } class $$D<T1, T2, T3> { } ", LanguageNames.CSharp, false, "D`3"); } [Fact] public void TestResolveGenericType2() { VerifyTypeResolution(@" Class D(Of T) End Class Class $$D(Of T1, T2, T3) End Class ", LanguageNames.VisualBasic, false, "D`3"); } [Fact] public void TestDontResolveGenericType1() { VerifyNoTypeResolution(@" class D<T1, T2, T3> { } ", LanguageNames.CSharp, false, "D"); } [Fact] public void TestDontResolveGenericType2() { VerifyNoTypeResolution(@" Class D(Of T1, T2, T3) End Class ", LanguageNames.VisualBasic, false, "D"); } [Fact] public void TestResolveRootNamespace() { VerifyTypeResolution(@" Module M Class $$C End Class End Module ", LanguageNames.VisualBasic, true, "RootNamespace.M+C"); } [Fact] public void TestDontPartiallyResolveType1() { VerifyNoTypeResolution(@" class A { class B { } } ", LanguageNames.CSharp, false, "A.B"); } [Fact] public void TestDontPartiallyResolveType2() { VerifyNoTypeResolution(@" Class A Class B End Class End Class ", LanguageNames.VisualBasic, false, "A.B"); } [Fact] public void TestResolveField1() { VerifyMemberResolution(@" class C { string $$s; } ", LanguageNames.CSharp, false, "C.#s", "C.s"); } [Fact] public void TestResolveField2() { VerifyMemberResolution(@" Class C Dim $$s As String End Class ", LanguageNames.VisualBasic, false, "C.#s", "C.s"); } [Fact, WorkItem(1141257, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1141257")] public void TestResolveEnumFieldWithoutName() { var source = @" enum E { $$, } "; var syntaxTree = CreateSyntaxTree(source, LanguageNames.CSharp); var compilation = CreateCompilation(syntaxTree, LanguageNames.CSharp, ""); _ = SuppressMessageAttributeState.ResolveTargetSymbols(compilation, "E.", SuppressMessageAttributeState.TargetScope.Member); } [Fact] public void TestResolveProperty1() { VerifyMemberResolution(@" class C { public string $$StringProperty { get; set; } } ", LanguageNames.CSharp, false, "C.#StringProperty", "C.StringProperty"); } [Fact] public void TestResolveProperty2() { VerifyMemberResolution(@" Class C Public Property $$StringProperty Get End Get Set End Set End Property End Class ", LanguageNames.VisualBasic, false, "C.#StringProperty", "C.StringProperty"); } [Fact] public void TestResolveEvent1() { VerifyMemberResolution(@" class C { public event System.EventHandler<int> $$E; } ", LanguageNames.CSharp, false, "e:C.#E", "C.E"); } [Fact] public void TestResolveEvent2() { VerifyMemberResolution(@" Class C Public Event $$E As System.EventHandler(Of Integer) End Class ", LanguageNames.VisualBasic, false, "e:C.#E", "C.E"); } [Fact] public void TestDontResolveNonEvent1() { VerifyNoMemberResolution(@" public class C { public int E; } ", LanguageNames.CSharp, false, "e:C.E"); } [Fact] public void TestDontResolveNonEvent2() { VerifyNoMemberResolution(@" Public Class C Public Dim E As Integer End Class ", LanguageNames.VisualBasic, false, "e:C.E"); } [Fact] public void TestResolvePropertySetMethod1() { VerifyMemberResolution(@" class C { public string StringProperty { get; $$set; } } ", LanguageNames.CSharp, false, "C.#set_StringProperty(System.String)", "C.set_StringProperty(System.String):System.Void"); } [Fact] public void TestResolvePropertySetMethod2() { VerifyMemberResolution(@" Class C Public Property StringProperty As String Get End Get $$Set End Set End Property End Class ", LanguageNames.VisualBasic, false, "C.#set_StringProperty(System.String)", "C.set_StringProperty(System.String):System.Void"); } [Fact] public void TestResolveEventAddMethod() { VerifyMemberResolution(@" class C { public delegate void Del(int x); public event Del E { $$add { } remove { } } } ", LanguageNames.CSharp, false, "C.#add_E(C.Del)", "C.add_E(C.Del):System.Void"); } [Fact] public void TestResolveEventRemoveMethod() { VerifyMemberResolution(@" class C { public delegate void Del(int x); public event Del E { add { } $$remove { } } } ", LanguageNames.CSharp, false, "C.#remove_E(C.Del)", "C.remove_E(C.Del):System.Void"); } [Fact] public void TestResolveVoidMethod1() { VerifyMemberResolution(@" class C { void Goo() {} void $$Goo(int x) {} void Goo(string x) {} } ", LanguageNames.CSharp, false, "C.#Goo(System.Int32)", "C.Goo(System.Int32):System.Void"); } [Fact] public void TestResolveVoidMethod2() { VerifyMemberResolution(@" Class C Sub Goo() End Sub Sub $$Goo(ByVal x as Integer) End Sub Sub Goo(ByVal x as String) End Sub End Class ", LanguageNames.VisualBasic, false, "C.#Goo(System.Int32)", "C.Goo(System.Int32):System.Void"); } [Fact] public void TestResolveMethod1() { VerifyMemberResolution(@" class C { void Goo() {} string Goo(int x) {} string $$Goo(string x) {} } ", LanguageNames.CSharp, false, "C.#Goo(System.String)", "C.Goo(System.String):System.String"); } [Fact] public void TestResolveMethod2() { VerifyMemberResolution(@" Class C Sub Goo() End Sub Function Goo(ByVal x As Integer) As String End Function Function $$Goo(ByVal x As String) As String End Function End Class ", LanguageNames.VisualBasic, false, "C.#Goo(System.String)", "C.Goo(System.String):System.String"); } [Fact] public void TestResolveOverloadedGenericMethod1() { VerifyMemberResolution(@" class C { int Goo<T>(T x) {} int $$Goo<T>(T x, params T[] y) {} } ", LanguageNames.CSharp, false, "C.#Goo`1(!!0,!!0[])", "C.Goo(T,T[]):System.Int32"); VerifyMemberResolution(@" class C { int [|Goo|]<T>(T x) {} int [|Goo|]<T>(T x, T y) {} } ", LanguageNames.CSharp, false, "C.Goo():System.Int32"); } [Fact] public void TestResolveOverloadedGenericMethod2() { VerifyMemberResolution(@" Class C Function Goo(Of T)(ByVal x As T) As Integer End Function Function $$Goo(Of T)(ByVal x As T, ByVal y as T()) As Integer End Function End Class ", LanguageNames.VisualBasic, false, "C.#Goo`1(!!0,!!0[])", "C.Goo(T,T[]):System.Int32"); VerifyMemberResolution(@" Class C Function [|Goo|](Of T)(ByVal x As T) As Integer End Function Function [|Goo|](Of T)(ByVal x As T, ByVal y As T) As Integer End Function End Class ", LanguageNames.VisualBasic, false, "C.Goo():System.Int32"); } [Fact] public void TestResolveMethodOverloadedOnArity1() { VerifyMemberResolution(@" interface I { void M<T>(); void $$M<T1, T2>(); } ", LanguageNames.CSharp, false, "I.#M`2()"); VerifyMemberResolution(@" interface I { void [|M|]<T>(); void [|M|]<T1, T2>(); } ", LanguageNames.CSharp, false, "I.M():System.Void"); } [Fact] public void TestResolveMethodOverloadedOnArity2() { VerifyMemberResolution(@" Interface I Sub M(Of T) Sub $$M(Of T1, T2) End Interface ", LanguageNames.VisualBasic, false, "I.#M`2()"); VerifyMemberResolution(@" Interface I Sub [|M|](Of T) Sub [|M|](Of T1, T2) End Interface ", LanguageNames.VisualBasic, false, "I.M():System.Void"); } [Fact] public void TestResolveConstructor1() { VerifyMemberResolution(@" class C { $$C() {} } ", LanguageNames.CSharp, false, "C.#.ctor()", "C..ctor()"); } [Fact] public void TestResolveConstructor2() { VerifyMemberResolution(@" Class C Sub $$New() End Sub End Class ", LanguageNames.VisualBasic, false, "C.#.ctor()", "C..ctor()"); } [Fact] public void TestResolveStaticConstructor1() { VerifyMemberResolution(@" class C { static $$C() {} } ", LanguageNames.CSharp, false, "C.#.cctor()", "C..cctor()"); } [Fact] public void TestResolveStaticConstructor2() { VerifyMemberResolution(@" Class C Shared Sub $$New() End Sub End Class ", LanguageNames.VisualBasic, false, "C.#.cctor()", "C..cctor()"); } [Fact] public void TestResolveSimpleOperator1() { VerifyMemberResolution(@" class C { public static bool operator $$==(C a, C b) { return true; } } ", LanguageNames.CSharp, false, "C.#op_Equality(C,C)", "C.op_Equality(C,C):System.Boolean"); } [Fact] public void TestResolveSimpleOperator2() { VerifyMemberResolution(@" Class C Public Shared Operator $$+(a as C, b as C) As Boolean return true End Operator End Class ", LanguageNames.VisualBasic, false, "C.#op_Addition(C,C)", "C.op_Addition(C,C):System.Boolean"); } [Fact] public void TestResolveIndexer1() { VerifyMemberResolution(@" class C { public C $$this[int i, string j] { get { return this; } } public C this[string i] { get { return this; } } } ", LanguageNames.CSharp, false, "C.#Item[System.Int32,System.String]", "C.Item[System.Int32,System.String]"); } [Fact] public void TestResolveIndexer2() { VerifyMemberResolution(@" Class C Public Default ReadOnly Property $$Item(i As Integer, j As String) As C Get Return Me End Get End Property Public Default ReadOnly Property Item(i As String) As C Get Return Me End Get End Property End Class ", LanguageNames.VisualBasic, false, "C.#Item[System.Int32,System.String]", "C.Item[System.Int32,System.String]"); } [Fact] public void TestResolveIndexerAccessorMethod() { VerifyMemberResolution(@" class C { public C this[int i] { get { return this; } } public C this[string i] { $$get { return this; } } } ", LanguageNames.CSharp, false, "C.#get_Item(System.String)", "C.get_Item(System.String):C"); } [Fact] public void TestResolveExplicitOperator() { VerifyMemberResolution(@" class C { public static explicit operator $$bool(C c) { return C == null; } public static explicit operator string(C c) { return string.Empty; } } ", LanguageNames.CSharp, false, "C.#op_Explicit(C):System.Boolean", "C.op_Explicit(C):System.Boolean"); } [Fact] public void TestResolveMethodWithComplexParameterTypes1() { VerifyMemberResolution(@" class C { public unsafe static bool $$IsComplex<T0, T1>(int* a, ref int b, ref T0 c, T1[] d) { return true; } } ", LanguageNames.CSharp, false, "C.#IsComplex`2(System.Int32*,System.Int32&,!!0&,!!1[])", "C.IsComplex(System.Int32*,System.Int32&,T0&,T1[]):System.Boolean"); } [Fact] public void TestResolveMethodWithComplexParameterTypes2() { VerifyMemberResolution(@" Class C Public Shared Function $$IsComplex(Of T0, T1)(a As Integer, ByRef b As Integer, ByRef c As T0, d As T1()) As Boolean Return True End Function End Class", LanguageNames.VisualBasic, false, "C.#IsComplex`2(System.Int32,System.Int32&,!!0&,!!1[])", "C.IsComplex(System.Int32,System.Int32&,T0&,T1[]):System.Boolean"); } [Fact] public void TestFinalize1() { VerifyMemberResolution(@" class A { ~$$A() { } } ", LanguageNames.CSharp, false, "A.#Finalize()", "A.Finalize():System.Void"); } [Fact] public void TestFinalize2() { VerifyMemberResolution(@" Class A Protected Overrides Sub $$Finalize() Try Finally MyBase.Finalize() End Try End Sub End Class ", LanguageNames.VisualBasic, false, "A.#Finalize()", "A.Finalize():System.Void"); } [Fact] public void TestResolveMethodWithComplexReturnType1() { VerifyMemberResolution(@" class C { public static T[][][,,][,] $$GetComplex<T>() { return null; } } ", LanguageNames.CSharp, false, "C.#GetComplex`1()", "C.GetComplex():T[,][,,][][]"); } [Fact] public void TestResolveMethodWithComplexReturnType2() { VerifyMemberResolution(@" Class C Public Shared Function $$GetComplex(Of T)() As T()()(,,)(,) Return Nothing End Function End Class ", LanguageNames.VisualBasic, false, "C.#GetComplex`1()", "C.GetComplex():T[,][,,][][]"); } [Fact] public void TestResolveMethodWithGenericParametersAndReturnTypeFromContainingClass1() { VerifyMemberResolution(@" public class C<T0> { public class D<T1> { public T3 $$M<T2, T3>(T0 a, T1 b, T2 c) { return default(T3); } } } ", LanguageNames.CSharp, false, "C`1+D`1.#M`2(!0,!1,!!0)", "C`1+D`1.M(T0,T1,T2):T3"); } [Fact] public void TestResolveMethodWithGenericParametersAndReturnTypeFromContainingClass2() { VerifyMemberResolution(@" Public Class C(Of T0) Public Class D(Of T1) Public Function $$M(Of T2, T3)(a As T0, b As T1, c As T2) As T3 Return Nothing End Function End Class End Class ", LanguageNames.VisualBasic, false, "C`1+D`1.#M`2(!0,!1,!!0)", "C`1+D`1.M(T0,T1,T2):T3"); } [Fact] public void TestResolveIndexerWithGenericParametersTypeFromContainingClass1() { VerifyMemberResolution(@" public class C<T0> { public class D<T1> { public T0 $$this[T1 a] { get { return default(T0); } } } } ", LanguageNames.CSharp, false, "C`1+D`1.#Item[!1]", "C`1+D`1.Item[!1]:!0"); } [Fact] public void TestResolveIndexerWithGenericParametersTypeFromContainingClass2() { VerifyMemberResolution(@" Public Class C(Of T0) Public Class D(Of T1) Public Default ReadOnly Property $$Item(a As T1) As T0 Get Return Nothing End Get End Property End Class End Class ", LanguageNames.VisualBasic, false, "C`1+D`1.#Item[!1]", "C`1+D`1.Item[!1]:!0"); } [Fact] public void TestResolveMethodOnOutParameter1() { VerifyMemberResolution(@" class C { void M0(int x) { } void $$M1(out int x) { x = 1; } } ", LanguageNames.CSharp, false, "C.#M1(System.Int32&)", "C.M1(System.Int32&):System.Void"); } [Fact] public void TestResolveMethodOnOutParameter2() { VerifyMemberResolution(@" Class C Private Sub M0(x As Integer) End Sub Private Sub $$M1(ByRef x As Integer) x = 1 End Sub End Class ", LanguageNames.VisualBasic, false, "C.#M1(System.Int32&)", "C.M1(System.Int32&):System.Void"); } [Fact] public void TestResolveMethodWithInstantiatedGenericParameterAndReturnType1() { VerifyMemberResolution(@" class G<T0,T1> { } class C<T3> { G<int,int> $$M<T4>(G<double, double> g, G<T3, T4[]> h) { } } ", LanguageNames.CSharp, false, "C.#M`1(G`2<System.Double,System.Double>,G`2<!0,!!0[]>)", "C.M(G`2<System.Double,System.Double>,G`2<T3,T4[]>):G`2<System.Int32,System.Int32>"); } [Fact] public void TestResolveMethodWithInstantiatedGenericParameterAndReturnType2() { VerifyMemberResolution(@" Class G(Of T0, T1) End Class Class C(Of T3) Private Function $$M(Of T4)(g As G(Of Double, Double), h As G(Of T3, T4())) As G(Of Integer, Integer) End Function End Class ", LanguageNames.VisualBasic, false, "C.#M`1(G`2<System.Double,System.Double>,G`2<!0,!!0[]>)", "C.M(G`2<System.Double,System.Double>,G`2<T3,T4[]>):G`2<System.Int32,System.Int32>"); } [Fact] public void TestResolveEscapedName1() { VerifyMemberResolution(@" namespace @namespace { class @class { int $$@if; } } ", LanguageNames.CSharp, false, "namespace.class.if"); } [Fact] public void TestResolveEscapedName2() { VerifyMemberResolution(@" Namespace [Namespace] Class [Class] Private $$[If] As Integer End Class End Namespace ", LanguageNames.VisualBasic, false, "Namespace.Class.If"); } [Fact] public void TestResolveMethodIgnoresConvention1() { VerifyMemberResolution(@" class C { string $$Goo(string x) {} } ", LanguageNames.CSharp, false, "C.#[vararg]Goo(System.String)", "C.#[cdecl]Goo(System.String)", "C.#[fastcall]Goo(System.String)", "C.#[stdcall]Goo(System.String)", "C.#[thiscall]Goo(System.String)"); } [Fact] public void TestResolveMethodIgnoresConvention2() { VerifyMemberResolution(@" Class C Private Function $$Goo(x As String) As String End Function End Class ", LanguageNames.VisualBasic, false, "C.#[vararg]Goo(System.String)", "C.#[cdecl]Goo(System.String)", "C.#[fastcall]Goo(System.String)", "C.#[stdcall]Goo(System.String)", "C.#[thiscall]Goo(System.String)"); } [Fact] public void TestNoResolutionForMalformedNames1() { VerifyNoMemberResolution(@" public class C<T0> { public class D<T4> { int @namespace; public T3 M<T2, T3>(T0 a, T4 b, T2 c) { return null; } } } ", LanguageNames.CSharp, false, "C`1+D`1.#M`2(!0,!1,!!0", // Missing close paren "C`1+D`1.M`2(T0,T4,T2):", // Missing return type "C`1+D`1.M`2(T0,T4,T2", // Missing close paren "C`1+D`1+M`2(T0,T4,T2)", // '+' instead of '.' delimiter "C`1.D`1.M`2(T0,T4,T2)", // '.' instead of '+' delimiter "C`1+D`1.@namespace", // Escaped name "C`1+D`1.#[blah]M`2(!0,!1,!!0)"); // Invalid calling convention } [Fact] public void TestNoResolutionForMalformedNames2() { VerifyNoMemberResolution(@" Public Class C(Of T0) Public Class D(Of T1) Private [Namespace] As Integer Public Function M(Of T2, T3)(a As T0, b As T1, c As T2) As T3 Return Nothing End Function End Class End Class ", LanguageNames.VisualBasic, false, "C`1+D`1.#M`2(!0,!1,!!0", // Missing close paren "C`1+D`1.M`2(T0,T1,T2):", // Missing return type "C`1+D`1.M`2(T0,T1,T2", // Missing close paren "C`1+D`1+M`2(T0,T1,T2)", // '+' instead of '.' delimiter "C`1.D`1.M`2(T0,T1,T2)", // '.' instead of '+' delimiter "C`1+D`1.[Namespace]", // Escaped name "C`1+D`1.#[blah]M`2(!0,!1,!!0)"); // Invalid calling convention } [Fact, WorkItem(65396, "https://github.com/dotnet/roslyn/issues/65396")] public void TestNoResolutionForMalformedNames3() { var names = new[] { "C.#M`1(G`2<!1,!!0[]>)", // Wrong class type index "C.#M`1(G`2<!0,!!1[]>)", // Wrong method type index }; VerifyNoMemberResolution(""" class G<T0,T1> { } class C<T3> { G<int,int> M<T4>(G<T3, T4[]> g) { } } """, LanguageNames.CSharp, false, names); VerifyNoMemberResolution(""" Class G(Of T0, T1) End Class Class C(Of T3) Private Function M(Of T4)(g As G(Of T3, T4())) As G(Of Integer, Integer) End Function End Class """, LanguageNames.VisualBasic, false, names); } private static void VerifyNamespaceResolution(string markup, string language, bool rootNamespace, params string[] fxCopFullyQualifiedNames) { string rootNamespaceName = ""; if (rootNamespace) { rootNamespaceName = "RootNamespace"; } VerifyResolution(markup, fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope.Namespace, language, rootNamespaceName); } private static void VerifyNoNamespaceResolution(string markup, string language, bool rootNamespace, params string[] fxCopFullyQualifiedNames) { string rootNamespaceName = ""; if (rootNamespace) { rootNamespaceName = "RootNamespace"; } VerifyNoResolution(markup, fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope.Namespace, language, rootNamespaceName); } private static void VerifyTypeResolution(string markup, string language, bool rootNamespace, params string[] fxCopFullyQualifiedNames) { string rootNamespaceName = ""; if (rootNamespace) { rootNamespaceName = "RootNamespace"; } VerifyResolution(markup, fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope.Type, language, rootNamespaceName); } private static void VerifyNoTypeResolution(string markup, string language, bool rootNamespace, params string[] fxCopFullyQualifiedNames) { string rootNamespaceName = ""; if (rootNamespace) { rootNamespaceName = "RootNamespace"; } VerifyNoResolution(markup, fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope.Type, language, rootNamespaceName); } private static void VerifyMemberResolution(string markup, string language, bool rootNamespace, params string[] fxCopFullyQualifiedNames) { string rootNamespaceName = ""; if (rootNamespace) { rootNamespaceName = "RootNamespace"; } VerifyResolution(markup, fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope.Member, language, rootNamespaceName); } private static void VerifyNoMemberResolution(string markup, string language, bool rootNamespace, params string[] fxCopFullyQualifiedNames) { string rootNamespaceName = ""; if (rootNamespace) { rootNamespaceName = "RootNamespace"; } VerifyNoResolution(markup, fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope.Member, language, rootNamespaceName); } private static void VerifyResolution(string markup, string[] fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope scope, string language, string rootNamespace) { // Parse out the span containing the declaration of the expected symbol MarkupTestFile.GetPositionAndSpans(markup, out var source, out var pos, out IDictionary<string, ImmutableArray<TextSpan>> spans); Assert.True(pos != null || spans.Count > 0, "Must specify a position or spans marking expected symbols for resolution"); // Get the expected symbol from the given position var syntaxTree = CreateSyntaxTree(source, language); var compilation = CreateCompilation(syntaxTree, language, rootNamespace); var model = compilation.GetSemanticModel(syntaxTree); var expectedSymbols = new List<ISymbol>(); bool shouldResolveSingleSymbol = pos != null; if (shouldResolveSingleSymbol) { expectedSymbols.Add(GetSymbolAtPosition(model, pos.Value)); } else { foreach (var span in spans.Values.First()) { expectedSymbols.Add(GetSymbolAtPosition(model, span.Start)); } } // Resolve the symbol based on each given FxCop fully-qualified name foreach (var fxCopName in fxCopFullyQualifiedNames) { var symbols = SuppressMessageAttributeState.ResolveTargetSymbols(compilation, fxCopName, scope); if (shouldResolveSingleSymbol) { var expectedSymbol = expectedSymbols.Single(); if (symbols.Count() > 1) { Assert.True(false, string.Format("Expected to resolve FxCop fully-qualified name '{0}' to '{1}': got multiple symbols:\r\n{2}", fxCopName, expectedSymbol, string.Join("\r\n", symbols))); } var symbol = symbols.SingleOrDefault(); Assert.True(expectedSymbol == symbol, string.Format("Failed to resolve FxCop fully-qualified name '{0}' to symbol '{1}': got '{2}'", fxCopName, expectedSymbol, symbol)); } else { foreach (var symbol in symbols) { Assert.True(expectedSymbols.Contains(symbol), string.Format("Failed to resolve FxCop fully-qualified name '{0}' to symbols:\r\n{1}\r\nResolved to unexpected symbol '{2}'", fxCopName, string.Join("\r\n", expectedSymbols), symbol)); } } } } private static ISymbol GetSymbolAtPosition(SemanticModel model, int pos) { var token = model.SyntaxTree.GetRoot().FindToken(pos); Assert.NotNull(token.Parent); var location = token.GetLocation(); var q = from node in token.Parent.AncestorsAndSelf() let candidate = model.GetDeclaredSymbol(node) where candidate != null && candidate.Locations.Contains(location) select candidate; var symbol = q.FirstOrDefault(); Assert.NotNull(symbol); return symbol; } private static void VerifyNoResolution(string source, string[] fxCopFullyQualifiedNames, SuppressMessageAttributeState.TargetScope scope, string language, string rootNamespace) { var compilation = CreateCompilation(source, language, rootNamespace); foreach (var fxCopName in fxCopFullyQualifiedNames) { var symbols = SuppressMessageAttributeState.ResolveTargetSymbols(compilation, fxCopName, scope); Assert.True(symbols.FirstOrDefault() == null, string.Format("Did not expect FxCop fully-qualified name '{0}' to resolve to any symbol: resolved to:\r\n{1}", fxCopName, string.Join("\r\n", symbols))); } } private static Compilation CreateCompilation(SyntaxTree syntaxTree, string language, string rootNamespace) { string projectName = "TestProject"; if (language == LanguageNames.CSharp) { return CSharpCompilation.Create( projectName, syntaxTrees: new[] { syntaxTree }, references: new[] { TestBase.MscorlibRef }); } else { return VisualBasicCompilation.Create( projectName, options: new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary, rootNamespace: rootNamespace), syntaxTrees: new[] { syntaxTree }, references: new[] { TestBase.MscorlibRef }); } } private static Compilation CreateCompilation(string source, string language, string rootNamespace) { return CreateCompilation(CreateSyntaxTree(source, language), language, rootNamespace); } private static SyntaxTree CreateSyntaxTree(string source, string language) { string fileName = language == LanguageNames.CSharp ? "Test.cs" : "Test.vb"; return language == LanguageNames.CSharp ? CSharpTestSource.Parse(source, path: fileName) : BasicTestSource.Parse(source, path: fileName); } } }