Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add potential exceptions when generating doc comment #54894

Merged
merged 10 commits into from
Jul 28, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,72 @@ public void TypingCharacter_Method()
VerifyTypingCharacter(code, expected);
}

[WpfFact, Trait(Traits.Feature, Traits.Features.DocumentationComments)]
[WorkItem(54245, "https://github.com/dotnet/roslyn/issues/54245")]
public void TypingCharacter_Method_WithExceptions()
{
var code =
@"class C
{
//$$
int M<T>(int goo)
{
if (goo < 0) throw new /*leading trivia*/Exception/*trailing trivia*/();
return 0;
}
}";

var expected =
@"class C
{
/// <summary>
/// $$
/// </summary>
/// <typeparam name=""T""></typeparam>
/// <param name=""goo""></param>
/// <returns></returns>
/// <exception cref=""Exception""></exception>
int M<T>(int goo)
{
if (goo < 0) throw new /*leading trivia*/Exception/*trailing trivia*/();
return 0;
}
}";

VerifyTypingCharacter(code, expected);
}

[WpfFact, Trait(Traits.Feature, Traits.Features.DocumentationComments)]
[WorkItem(54245, "https://github.com/dotnet/roslyn/issues/54245")]
public void TypingCharacter_Constructor_WithExceptions()
{
var code =
@"class C
{
//$$
public C(int goo)
{
if (goo < 0) throw new /*leading trivia*/Exception/*trailing trivia*/();
}
}";

var expected =
@"class C
{
/// <summary>
/// $$
/// </summary>
/// <param name=""goo""></param>
/// <exception cref=""Exception""></exception>
public C(int goo)
{
if (goo < 0) throw new /*leading trivia*/Exception/*trailing trivia*/();
}
}";

VerifyTypingCharacter(code, expected);
}

[WpfFact, Trait(Traits.Feature, Traits.Features.DocumentationComments)]
public void TypingCharacter_Method_WithVerbatimParams()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.CodeAnalysis.DocumentationComments;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp.DocumentationComments
{
Expand Down Expand Up @@ -111,22 +112,49 @@ protected override List<string> GetDocumentationCommentStubLines(MemberDeclarati
}
}

if (member.IsKind(SyntaxKind.MethodDeclaration) ||
member.IsKind(SyntaxKind.IndexerDeclaration) ||
member.IsKind(SyntaxKind.DelegateDeclaration) ||
member.IsKind(SyntaxKind.OperatorDeclaration))
if (member.IsKind(
SyntaxKind.MethodDeclaration,
SyntaxKind.IndexerDeclaration,
SyntaxKind.DelegateDeclaration,
SyntaxKind.OperatorDeclaration,
SyntaxKind.ConstructorDeclaration,
SyntaxKind.DestructorDeclaration))
{
var returnType = member.GetMemberType();
if (returnType != null &&
!(returnType.IsKind(SyntaxKind.PredefinedType, out PredefinedTypeSyntax? predefinedType) && predefinedType.Keyword.IsKindOrHasMatchingText(SyntaxKind.VoidKeyword)))
{
list.Add("/// <returns></returns>");
}

foreach (var exceptionType in GetExceptions(member))
{
list.Add(@$"/// <exception cref=""{exceptionType}""></exception>");
}
}

return list;
}

private static IEnumerable<string> GetExceptions(SyntaxNode member)
{
var statements = member.DescendantNodes().Where(n => n.IsKind(SyntaxKind.ThrowExpression, SyntaxKind.ThrowStatement));
foreach (var statement in statements)
{
var expression = statement switch
{
ThrowExpressionSyntax throwExpression => throwExpression.Expression,
ThrowStatementSyntax throwStatement => throwStatement.Expression,
_ => throw ExceptionUtilities.Unreachable
};

if (expression is ObjectCreationExpressionSyntax { Type: TypeSyntax type })
{
yield return type.ToString();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely won't work with generics. But that's likely so niche as to not be relevant.

Is also like it if we filtered it exceptions in an inner scope that are caught before escaping.

}
}
}

protected override SyntaxToken GetTokenToRight(
SyntaxTree syntaxTree, int position, CancellationToken cancellationToken)
{
Expand Down