|
// 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;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class DocumentationCommentIDTests : CSharpTestBase
{
[Fact]
public void AliasSymbol()
{
var source = @"
using A = System.String;
class C { }
";
var comp = CreateCompilation(source);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var syntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<UsingDirectiveSyntax>().Single();
var symbol = model.GetDeclaredSymbol(syntax);
Assert.Equal(SymbolKind.Alias, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void ArrayTypeSymbol()
{
var source = @"
class C
{
C[] f;
}
";
var comp = CreateCompilation(source);
var field = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<FieldSymbol>("f");
var symbol = field.Type;
Assert.Equal(SymbolKind.ArrayType, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void AssemblySymbol()
{
var source = @"
class C
{
}
";
var comp = CreateCompilation(source);
var symbol = comp.SourceAssembly;
Assert.Equal(SymbolKind.Assembly, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void DynamicTypeSymbol()
{
var source = @"
class C
{
dynamic f;
}
";
var comp = CreateCompilation(source);
var field = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<FieldSymbol>("f");
var symbol = field.Type;
Assert.Equal(SymbolKind.DynamicType, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void ErrorTypeSymbol()
{
var source = @"
class C : M.N.O
{
}
";
var comp = CreateCompilation(source);
var type = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
var symbol = type.BaseType();
Assert.Equal(SymbolKind.ErrorType, symbol.Kind);
Assert.Equal("!:M.N.O", symbol.GetDocumentationCommentId());
}
[Fact]
public void EventSymbol()
{
var source = @"
class C
{
event System.Action E;
}
";
var comp = CreateCompilation(source);
var symbol = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<EventSymbol>("E");
Assert.Equal(SymbolKind.Event, symbol.Kind);
Assert.Equal("E:C.E", symbol.GetDocumentationCommentId());
}
[Fact]
public void FieldSymbol()
{
var source = @"
class C
{
int f;
}
";
var comp = CreateCompilation(source);
var symbol = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<FieldSymbol>("f");
Assert.Equal(SymbolKind.Field, symbol.Kind);
Assert.Equal("F:C.f", symbol.GetDocumentationCommentId());
}
[Fact]
public void LabelSymbol()
{
var source = @"
class C
{
void M()
{
LABEL:
goto LABEL;
}
}
";
var comp = CreateCompilation(source);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var syntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<GotoStatementSyntax>().Single().Expression;
var symbol = model.GetSymbolInfo(syntax).Symbol;
Assert.Equal(SymbolKind.Label, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void LocalSymbol()
{
var source = @"
class C
{
void M()
{
int x;
}
}
";
var comp = CreateCompilation(source);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var syntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().Single();
var symbol = model.GetDeclaredSymbol(syntax);
Assert.Equal(SymbolKind.Local, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void MethodSymbol()
{
var source = @"
class C
{
void M()
{
}
}
";
var comp = CreateCompilation(source);
var symbol = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<MethodSymbol>("M");
Assert.Equal(SymbolKind.Method, symbol.Kind);
Assert.Equal("M:C.M", symbol.GetDocumentationCommentId());
}
[Fact]
public void NetModuleSymbol()
{
var source = @"
class C
{
}
";
var comp = CreateCompilation(source);
var symbol = comp.SourceModule;
Assert.Equal(SymbolKind.NetModule, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void NamedTypeSymbol()
{
var source = @"
class C
{
}
";
var comp = CreateCompilation(source);
var symbol = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
Assert.Equal(SymbolKind.NamedType, symbol.Kind);
Assert.Equal("T:C", symbol.GetDocumentationCommentId());
}
[Fact]
public void NamespaceSymbol()
{
var source = @"
class C
{
}
";
var comp = CreateCompilation(source);
var symbol = comp.GlobalNamespace.GetMember<NamespaceSymbol>("System");
Assert.Equal(SymbolKind.Namespace, symbol.Kind);
Assert.Equal("N:System", symbol.GetDocumentationCommentId());
}
[Fact]
public void GlobalNamespaceSymbol()
{
var source = @"
class C
{
}
";
var comp = CreateCompilation(source);
var symbol = comp.GlobalNamespace;
Assert.Equal(SymbolKind.Namespace, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void ParameterSymbol()
{
var source = @"
class C
{
void M(int x)
{
}
}
";
var comp = CreateCompilation(source);
var symbol = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<MethodSymbol>("M").Parameters.Single();
Assert.Equal(SymbolKind.Parameter, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void PointerTypeSymbol()
{
var source = @"
class C
{
unsafe int* f;
}
";
var comp = CreateCompilation(source, options: TestOptions.ReleaseDll);
var field = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<FieldSymbol>("f");
var symbol = field.Type;
Assert.Equal(SymbolKind.PointerType, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void PropertySymbol()
{
var source = @"
class C
{
int P { get; set; }
}
";
var comp = CreateCompilation(source);
var symbol = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C").GetMember<PropertySymbol>("P");
Assert.Equal(SymbolKind.Property, symbol.Kind);
Assert.Equal("P:C.P", symbol.GetDocumentationCommentId());
}
[Fact]
public void RangeVariableSymbol()
{
var source = @"
using System.Linq;
class C
{
void M()
{
var q = from x in p select x;
}
}
";
var comp = CreateCompilationWithMscorlib40AndSystemCore(source);
var tree = comp.SyntaxTrees.Single();
var model = comp.GetSemanticModel(tree);
var syntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<FromClauseSyntax>().Single();
var symbol = model.GetDeclaredSymbol(syntax);
Assert.Equal(SymbolKind.RangeVariable, symbol.Kind);
Assert.Null(symbol.GetDocumentationCommentId());
}
[Fact]
public void TypeParameterSymbol()
{
var source = @"
class C<T>
{
}
";
var comp = CreateCompilation(source);
var type = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
var symbol = type.TypeParameters.Single();
Assert.Equal(SymbolKind.TypeParameter, symbol.Kind);
Assert.Equal("!:T", symbol.GetDocumentationCommentId());
}
[WorkItem(531409, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531409")]
[Fact]
public void ExplicitInterfaceImplementation()
{
var source = @"
interface I<T>
{
void M();
int P { get; set; }
event System.Action E;
}
class C<T> : I<T>
{
void I<T>.M() { }
int I<T>.P { get { return 0; } set { } }
event System.Action I<T>.E { add { } remove { } }
}
";
var comp = CreateCompilation(source);
var type = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
var method = type.GetMembersUnordered().OfType<MethodSymbol>().Single(m => m.MethodKind == MethodKind.ExplicitInterfaceImplementation);
var property = type.GetMembersUnordered().OfType<PropertySymbol>().Single();
var @event = type.GetMembersUnordered().OfType<EventSymbol>().Single();
Assert.Equal("M:C`1.I{T}#M", method.GetDocumentationCommentId());
Assert.Equal("P:C`1.I{T}#P", property.GetDocumentationCommentId());
Assert.Equal("E:C`1.I{T}#E", @event.GetDocumentationCommentId());
}
[Fact]
public void ArgList()
{
var source = @"
class C
{
void M1(__arglist) { }
void M2(int x, __arglist) { }
}
";
var comp = CreateCompilation(source);
var type = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
var method1 = type.GetMember<MethodSymbol>("M1");
var method2 = type.GetMember<MethodSymbol>("M2");
Assert.Equal("M:C.M1()", method1.GetDocumentationCommentId());
Assert.Equal("M:C.M2(System.Int32,)", method2.GetDocumentationCommentId());
}
[WorkItem(547163, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/547163")]
[Fact]
public void NestedGenericTypes()
{
var source = @"
class A<TA1, TA2>
{
class B<TB1, TB2>
{
class C<TC1, TC2>
{
void M<TM1, TM2>(TA1 a1, TA2 a2, TB1 b1, TB2 b2, TC1 c1, TC2 c2, TM1 m1, TM2 m2)
{
}
}
}
}
";
var comp = CreateCompilation(source);
var method = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("A").GetMember<NamedTypeSymbol>("B").GetMember<NamedTypeSymbol>("C").GetMember<MethodSymbol>("M");
Assert.Equal("M:A`2.B`2.C`2.M``2(`0,`1,`2,`3,`4,`5,``0,``1)", method.GetDocumentationCommentId());
}
[Theory]
[CombinatorialData]
public void Generic(NullableContextOptions nullableContextOptions)
{
var source = @"
internal class Test<T> : ICloneable<Test<T>>
{
public Test<T> Clone() => new();
}
internal interface ICloneable<T>
{
T Clone();
}
";
var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(nullableContextOptions));
var method = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("Test").GetMember<MethodSymbol>("Clone").ReturnType;
Assert.Equal("T:Test`1", method.GetDocumentationCommentId());
}
[Theory]
[CombinatorialData]
public void Generic2(NullableContextOptions nullableContextOptions)
{
var source = @"
internal class Test<T> : ICloneable<Test<T?>>
{
public Test<T?> Clone() => new();
}
internal interface ICloneable<T>
{
T Clone();
}
";
var comp = CreateCompilation(source, options: TestOptions.DebugDll.WithNullableContextOptions(nullableContextOptions));
var method = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("Test").GetMember<MethodSymbol>("Clone").ReturnType;
Assert.Equal("T:Test`1", method.GetDocumentationCommentId());
}
}
}
|