|
9 | 9 | using System.Threading.Tasks; |
10 | 10 | using Microsoft.CodeAnalysis; |
11 | 11 | using Microsoft.CodeAnalysis.Shared.Extensions; |
| 12 | +using Microsoft.CodeAnalysis.Shared.Utilities; |
12 | 13 | using Microsoft.CodeAnalysis.Test.Utilities; |
13 | 14 | using Microsoft.CodeAnalysis.Text; |
14 | 15 | using Roslyn.Test.Utilities; |
@@ -784,6 +785,174 @@ void Method((C a, int b) t) |
784 | 785 | Assert.True(method.Parameters[0].Type.IsTupleType); |
785 | 786 | } |
786 | 787 |
|
| 788 | + [Fact, WorkItem(14365, "https://github.com/dotnet/roslyn/issues/14365")] |
| 789 | + public void TestErrorType_CSharp() |
| 790 | + { |
| 791 | + var source = @" |
| 792 | +class C |
| 793 | +{ |
| 794 | + int i { get; } |
| 795 | +}"; |
| 796 | + |
| 797 | + // We don't add metadata references, so even `int` will be an error type. |
| 798 | + var compilation1 = GetCompilation(source, LanguageNames.CSharp, "File1.cs", Array.Empty<MetadataReference>()); |
| 799 | + var compilation2 = GetCompilation(source, LanguageNames.CSharp, "File2.cs", Array.Empty<MetadataReference>()); |
| 800 | + |
| 801 | + var symbol = (IPropertySymbol)GetAllSymbols( |
| 802 | + compilation1.GetSemanticModel(compilation1.SyntaxTrees.Single()), |
| 803 | + n => n is CSharp.Syntax.PropertyDeclarationSyntax).Single(); |
| 804 | + |
| 805 | + var propType = symbol.Type; |
| 806 | + Assert.Equal(SymbolKind.ErrorType, propType.Kind); |
| 807 | + |
| 808 | + // Ensure we don't crash getting these symbol keys. |
| 809 | + var id = SymbolKey.CreateString(propType); |
| 810 | + Assert.NotNull(id); |
| 811 | + |
| 812 | + // Validate that if the client does ask to resolve locations that we |
| 813 | + // do not crash if those locations cannot be found. |
| 814 | + var found = SymbolKey.ResolveString(id, compilation2).GetAnySymbol(); |
| 815 | + Assert.NotNull(found); |
| 816 | + |
| 817 | + Assert.Equal(propType.Name, found.Name); |
| 818 | + Assert.Equal(propType.Kind, found.Kind); |
| 819 | + |
| 820 | + var method = (IErrorTypeSymbol)found; |
| 821 | + Assert.True(SymbolEquivalenceComparer.Instance.Equals(propType, found)); |
| 822 | + } |
| 823 | + |
| 824 | + [Fact, WorkItem(14365, "https://github.com/dotnet/roslyn/issues/14365")] |
| 825 | + public void TestErrorType_VB() |
| 826 | + { |
| 827 | + var source = @" |
| 828 | +class C |
| 829 | + public readonly property i as integer |
| 830 | +end class"; |
| 831 | + |
| 832 | + // We don't add metadata references, so even `int` will be an error type. |
| 833 | + var compilation1 = GetCompilation(source, LanguageNames.VisualBasic, "File1.vb", Array.Empty<MetadataReference>()); |
| 834 | + var compilation2 = GetCompilation(source, LanguageNames.VisualBasic, "File2.vb", Array.Empty<MetadataReference>()); |
| 835 | + |
| 836 | + var symbol = (IPropertySymbol)GetAllSymbols( |
| 837 | + compilation1.GetSemanticModel(compilation1.SyntaxTrees.Single()), |
| 838 | + n => n is VisualBasic.Syntax.PropertyStatementSyntax).Single(); |
| 839 | + |
| 840 | + var propType = symbol.Type; |
| 841 | + Assert.Equal(SymbolKind.ErrorType, propType.Kind); |
| 842 | + |
| 843 | + // Ensure we don't crash getting these symbol keys. |
| 844 | + var id = SymbolKey.CreateString(propType); |
| 845 | + Assert.NotNull(id); |
| 846 | + |
| 847 | + // Validate that if the client does ask to resolve locations that we |
| 848 | + // do not crash if those locations cannot be found. |
| 849 | + var found = SymbolKey.ResolveString(id, compilation2).GetAnySymbol(); |
| 850 | + Assert.NotNull(found); |
| 851 | + |
| 852 | + Assert.Equal(propType.Name, found.Name); |
| 853 | + Assert.Equal(propType.Kind, found.Kind); |
| 854 | + |
| 855 | + var method = (IErrorTypeSymbol)found; |
| 856 | + Assert.True(SymbolEquivalenceComparer.Instance.Equals(propType, found)); |
| 857 | + } |
| 858 | + |
| 859 | + [Fact, WorkItem(14365, "https://github.com/dotnet/roslyn/issues/14365")] |
| 860 | + public void TestErrorTypeInNestedNamespace() |
| 861 | + { |
| 862 | + var source1 = @" |
| 863 | +public class C |
| 864 | +{ |
| 865 | + public System.Collections.IEnumerable I { get; } |
| 866 | +}"; |
| 867 | + |
| 868 | + var source2 = @" |
| 869 | +class X |
| 870 | +{ |
| 871 | + void M() |
| 872 | + { |
| 873 | + new C().I; |
| 874 | + } |
| 875 | +}"; |
| 876 | + |
| 877 | + // We don't add metadata to the second compilation, so even `System.Collections.IEnumerable` will be an |
| 878 | + // error type. |
| 879 | + var compilation1 = GetCompilation(source1, LanguageNames.CSharp, "File1.cs"); |
| 880 | + var compilation2 = GetCompilation(source2, LanguageNames.CSharp, "File2.cs", |
| 881 | + new[] { compilation1.ToMetadataReference() }); |
| 882 | + |
| 883 | + var symbol = (IPropertySymbol)GetAllSymbols( |
| 884 | + compilation2.GetSemanticModel(compilation2.SyntaxTrees.Single()), |
| 885 | + n => n is CSharp.Syntax.MemberAccessExpressionSyntax).Single(); |
| 886 | + |
| 887 | + var propType = symbol.Type; |
| 888 | + Assert.Equal(SymbolKind.ErrorType, propType.Kind); |
| 889 | + Assert.Equal("Collections", propType.ContainingNamespace.Name); |
| 890 | + Assert.Equal("System", propType.ContainingNamespace.ContainingNamespace.Name); |
| 891 | + |
| 892 | + // Ensure we don't crash getting these symbol keys. |
| 893 | + var id = SymbolKey.CreateString(propType); |
| 894 | + Assert.NotNull(id); |
| 895 | + |
| 896 | + // Validate that if the client does ask to resolve locations that we |
| 897 | + // do not crash if those locations cannot be found. |
| 898 | + var found = SymbolKey.ResolveString(id, compilation2).GetAnySymbol(); |
| 899 | + Assert.NotNull(found); |
| 900 | + |
| 901 | + Assert.Equal(propType.Name, found.Name); |
| 902 | + Assert.Equal(propType.Kind, found.Kind); |
| 903 | + Assert.Equal(propType.ContainingNamespace.Name, found.ContainingNamespace.Name); |
| 904 | + |
| 905 | + var method = (IErrorTypeSymbol)found; |
| 906 | + Assert.True(SymbolEquivalenceComparer.Instance.Equals(propType, found)); |
| 907 | + } |
| 908 | + |
| 909 | + [Fact, WorkItem(14365, "https://github.com/dotnet/roslyn/issues/14365")] |
| 910 | + public void TestErrorTypeInNestedNamespace_VB() |
| 911 | + { |
| 912 | + var source1 = @" |
| 913 | +public class C |
| 914 | + public readonly property I as System.Collections.IEnumerable |
| 915 | +end class"; |
| 916 | + |
| 917 | + var source2 = @" |
| 918 | +class X |
| 919 | + sub M() |
| 920 | + dim y = new C().I; |
| 921 | + end sub |
| 922 | +end class"; |
| 923 | + |
| 924 | + // We don't add metadata to the second compilation, so even `System.Collections.IEnumerable` will be an |
| 925 | + // error type. |
| 926 | + var compilation1 = GetCompilation(source1, LanguageNames.VisualBasic, "File1.vb"); |
| 927 | + var compilation2 = GetCompilation(source2, LanguageNames.VisualBasic, "File2.vb", |
| 928 | + new[] { compilation1.ToMetadataReference() }); |
| 929 | + |
| 930 | + var symbol = (IPropertySymbol)GetAllSymbols( |
| 931 | + compilation2.GetSemanticModel(compilation2.SyntaxTrees.Single()), |
| 932 | + n => n is VisualBasic.Syntax.MemberAccessExpressionSyntax).Single(); |
| 933 | + |
| 934 | + var propType = symbol.Type; |
| 935 | + Assert.Equal(SymbolKind.ErrorType, propType.Kind); |
| 936 | + Assert.Equal("Collections", propType.ContainingNamespace.Name); |
| 937 | + Assert.Equal("System", propType.ContainingNamespace.ContainingNamespace.Name); |
| 938 | + |
| 939 | + // Ensure we don't crash getting these symbol keys. |
| 940 | + var id = SymbolKey.CreateString(propType); |
| 941 | + Assert.NotNull(id); |
| 942 | + |
| 943 | + // Validate that if the client does ask to resolve locations that we |
| 944 | + // do not crash if those locations cannot be found. |
| 945 | + var found = SymbolKey.ResolveString(id, compilation2).GetAnySymbol(); |
| 946 | + Assert.NotNull(found); |
| 947 | + |
| 948 | + Assert.Equal(propType.Name, found.Name); |
| 949 | + Assert.Equal(propType.Kind, found.Kind); |
| 950 | + Assert.Equal(propType.ContainingNamespace.Name, found.ContainingNamespace.Name); |
| 951 | + |
| 952 | + var method = (IErrorTypeSymbol)found; |
| 953 | + Assert.True(SymbolEquivalenceComparer.Instance.Equals(propType, found)); |
| 954 | + } |
| 955 | + |
787 | 956 | [Fact] |
788 | 957 | public void TestFunctionPointerTypeSymbols() |
789 | 958 | { |
@@ -826,9 +995,9 @@ private static void TestRoundTrip(ISymbol symbol, Compilation compilation, Func< |
826 | 995 | } |
827 | 996 | } |
828 | 997 |
|
829 | | - private static Compilation GetCompilation(string source, string language, string path = "") |
| 998 | + private static Compilation GetCompilation(string source, string language, string path = "", MetadataReference[] references = null) |
830 | 999 | { |
831 | | - var references = new[] |
| 1000 | + references ??= new[] |
832 | 1001 | { |
833 | 1002 | MetadataReference.CreateFromFile(typeof(object).Assembly.Location), |
834 | 1003 | MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location) |
|
0 commit comments