|
// 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.CSharp.CodeFixes.AddInheritdoc;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Testing;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.AddInheritdoc
{
using VerifyCS = CSharpCodeFixVerifier<
EmptyDiagnosticAnalyzer,
AddInheritdocCodeFixProvider>;
[Trait(Traits.Feature, Traits.Features.CodeActionsAddInheritdoc)]
public class AddInheritdocTests
{
private static async Task TestAsync(string initialMarkup, string expectedMarkup)
{
var test = new VerifyCS.Test
{
TestCode = initialMarkup,
FixedCode = expectedMarkup,
CodeActionValidationMode = CodeActionValidationMode.Full,
};
await test.RunAsync();
}
private static async Task TestMissingAsync(string initialMarkup)
=> await VerifyCS.VerifyCodeFixAsync(initialMarkup, initialMarkup);
[Fact]
public async Task AddMissingInheritdocOnOverridenMethod()
{
await TestAsync(
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
}
/// Some doc.
public class Derived: BaseClass
{
public override void {|CS1591:M|}() { }
}
""",
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
}
/// Some doc.
public class Derived: BaseClass
{
/// <inheritdoc/>
public override void M() { }
}
""");
}
[Theory]
[InlineData("public void {|CS1591:OtherMethod|}() { }")]
[InlineData("public void {|CS1591:M|}() { }")]
[InlineData("public new void {|CS1591:M|}() { }")]
public async Task DontOfferOnNotOverridenMethod(string methodDefintion)
{
await TestMissingAsync(
$@"
/// Some doc.
public class BaseClass
{{
/// Some doc.
public virtual void M() {{ }}
}}
/// Some doc.
public class Derived: BaseClass
{{
{methodDefintion}
}}");
}
[Fact]
public async Task AddMissingInheritdocOnImplicitInterfaceMethod()
{
await TestAsync(
"""
/// Some doc.
public interface IInterface
{
/// Some doc.
void M();
}
/// Some doc.
public class MyClass: IInterface
{
public void {|CS1591:M|}() { }
}
""",
"""
/// Some doc.
public interface IInterface
{
/// Some doc.
void M();
}
/// Some doc.
public class MyClass: IInterface
{
/// <inheritdoc/>
public void M() { }
}
""");
}
[Fact]
public async Task DontOfferOnExplicitInterfaceMethod()
{
await TestMissingAsync(
"""
/// Some doc.
public interface IInterface
{
/// Some doc.
void M();
}
/// Some doc.
public class MyClass: IInterface
{
void IInterface.M() { }
}
""");
}
[Fact]
public async Task AddMissingInheritdocOnOverridenProperty()
{
await TestAsync(
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual string P { get; set; }
}
/// Some doc.
public class Derived: BaseClass
{
public override string {|CS1591:P|} { get; set; }
}
""",
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual string P { get; set; }
}
/// Some doc.
public class Derived: BaseClass
{
/// <inheritdoc/>
public override string P { get; set; }
}
""");
}
[Fact]
public async Task AddMissingInheritdocOnImplicitInterfaceProperty()
{
await TestAsync(
"""
/// Some doc.
public interface IInterface
{
/// Some doc.
string P { get; }
}
/// Some doc.
public class MyClass: IInterface
{
public string {|CS1591:P|} { get; }
}
""",
"""
/// Some doc.
public interface IInterface
{
/// Some doc.
string P { get; }
}
/// Some doc.
public class MyClass: IInterface
{
/// <inheritdoc/>
public string P { get; }
}
""");
}
[Fact]
public async Task AddMissingInheritdocOnImplicitInterfaceEvent()
{
await TestAsync(
"""
/// Some doc.
public interface IInterface
{
/// Some doc.
event System.Action SomeEvent;
}
/// Some doc.
public class MyClass: IInterface
{
public event System.Action {|CS1591:SomeEvent|};
void OnSomething() => SomeEvent?.Invoke();
}
""",
"""
/// Some doc.
public interface IInterface
{
/// Some doc.
event System.Action SomeEvent;
}
/// Some doc.
public class MyClass: IInterface
{
/// <inheritdoc/>
public event System.Action SomeEvent;
void OnSomething() => SomeEvent?.Invoke();
}
""");
}
[Fact]
public async Task AddMissingInheritdocTriviaTest_1()
{
await TestAsync(
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
}
/// Some doc.
public class Derived: BaseClass
{
// Comment
public override void {|CS1591:M|}() { }
}
""",
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
}
/// Some doc.
public class Derived: BaseClass
{
/// <inheritdoc/>
// Comment
public override void M() { }
}
""");
}
[Fact]
public async Task AddMissingInheritdocTriviaTest_2()
{
await TestAsync(
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
}
/// Some doc.
public class Derived: BaseClass
{
// Comment 1
/* Comment 2 */ public /* Comment 3 */ override void {|CS1591:M|} /* Comment 4 */ () /* Comment 5 */ { } /* Comment 6 */
}
""",
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
}
/// Some doc.
public class Derived: BaseClass
{
/// <inheritdoc/>
// Comment 1
/* Comment 2 */ public /* Comment 3 */ override void M /* Comment 4 */ () /* Comment 5 */ { } /* Comment 6 */
}
""");
}
[Fact]
public async Task AddMissingInheritdocMethodWithAttribute()
{
await TestAsync(
"""
/// Some doc.
[System.AttributeUsage(System.AttributeTargets.Method)]
public sealed class DummyAttribute: System.Attribute
{
}
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
}
/// Some doc.
public class Derived: BaseClass
{
[Dummy]
public override void {|CS1591:M|}() { }
}
""",
"""
/// Some doc.
[System.AttributeUsage(System.AttributeTargets.Method)]
public sealed class DummyAttribute: System.Attribute
{
}
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
}
/// Some doc.
public class Derived: BaseClass
{
/// <inheritdoc/>
[Dummy]
public override void M() { }
}
""");
}
[Fact]
public async Task AddMissingInheritdocFixAll()
{
await TestAsync(
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
/// Some doc.
public virtual string P { get; }
}
/// Some doc.
public class Derived: BaseClass
{
public override void {|CS1591:M|}() { }
public override string {|CS1591:P|} { get; }
}
""",
"""
/// Some doc.
public class BaseClass
{
/// Some doc.
public virtual void M() { }
/// Some doc.
public virtual string P { get; }
}
/// Some doc.
public class Derived: BaseClass
{
/// <inheritdoc/>
public override void M() { }
/// <inheritdoc/>
public override string P { get; }
}
""");
}
}
}
|