未验证 提交 8b7456ac 编写于 作者: J Jason Malinowski 提交者: GitHub

Merge pull request #33643 from emilefokkema/inline-typecheck-with-comments

give CSharpAsAndNullCheckCodeFixProvider more intelligence about removing statements
......@@ -132,6 +132,43 @@ void M()
}");
}
[WorkItem(33345, "https://github.com/dotnet/roslyn/issues/33345")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)]
public async Task TestRemoveNewLinesInSwitchStatement()
{
await TestInRegularAndScriptAsync(
@"class C
{
void M()
{
switch (o)
{
default:
[|var|] x = o as string;
//a comment
if (x != null)
{
}
}
}
}",
@"class C
{
void M()
{
switch (o)
{
default:
//a comment
if (o is string x)
{
}
}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)]
public async Task TestMissingOnNonDeclaration()
{
......@@ -315,6 +352,96 @@ void M()
}");
}
[WorkItem(33345, "https://github.com/dotnet/roslyn/issues/33345")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)]
public async Task TestRemoveNewLines()
{
await TestInRegularAndScriptAsync(
@"class C
{
void M()
{
[|var|] x = o as string;
//suffix comment
if (x != null)
{
}
}
}",
@"class C
{
void M()
{
//suffix comment
if (o is string x)
{
}
}
}");
}
[WorkItem(33345, "https://github.com/dotnet/roslyn/issues/33345")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)]
public async Task TestRemoveNewLinesWhereBlankLineIsNotEmpty()
{
await TestInRegularAndScriptAsync(
@"class C
{
void M()
{
[|var|] x = o as string;
//suffix comment
if (x != null)
{
}
}
}",
@"class C
{
void M()
{
//suffix comment
if (o is string x)
{
}
}
}");
}
[WorkItem(33345, "https://github.com/dotnet/roslyn/issues/33345")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)]
public async Task TestRemoveNewLines2()
{
await TestInRegularAndScriptAsync(
@"class C
{
void M()
{
int a = 0;
[|var|] x = o as string;
//suffix comment
if (x != null)
{
}
}
}",
@"class C
{
void M()
{
int a = 0;
//suffix comment
if (o is string x)
{
}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)]
public async Task InlineTypeCheckComplexCondition1()
{
......
......@@ -201,7 +201,6 @@ void M()
{
void M()
{
if (summaryElement.Content[0] is XmlTextSyntax firstTextPartSyntax && summaryElement.Content[1] is XmlEmptyElementSyntax classReferencePart && summaryElement.Content[2] is XmlTextSyntax secondTextPartSyntax)
{
}
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Composition;
using System.Linq;
using System.Threading;
......@@ -38,22 +39,44 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
SyntaxEditor editor, CancellationToken cancellationToken)
{
var declaratorLocations = new HashSet<Location>();
var statementParentScopes = new HashSet<SyntaxNode>();
void RemoveStatement(StatementSyntax statement)
{
editor.RemoveNode(statement, SyntaxRemoveOptions.KeepUnbalancedDirectives);
if (statement.Parent is BlockSyntax || statement.Parent is SwitchSectionSyntax)
{
statementParentScopes.Add(statement.Parent);
}
}
foreach (var diagnostic in diagnostics)
{
cancellationToken.ThrowIfCancellationRequested();
if (declaratorLocations.Add(diagnostic.AdditionalLocations[0]))
{
AddEdits(editor, diagnostic, cancellationToken);
AddEdits(editor, diagnostic, RemoveStatement, cancellationToken);
}
}
foreach (var parentScope in statementParentScopes)
{
editor.ReplaceNode(parentScope, (newParentScope, syntaxGenerator) =>
{
var firstStatement = newParentScope is BlockSyntax
? ((BlockSyntax)newParentScope).Statements.First()
: ((SwitchSectionSyntax)newParentScope).Statements.First();
return syntaxGenerator.ReplaceNode(newParentScope, firstStatement, firstStatement.WithoutLeadingBlankLinesInTrivia());
});
}
return Task.CompletedTask;
}
private static void AddEdits(
SyntaxEditor editor,
Diagnostic diagnostic,
Action<StatementSyntax> removeStatement,
CancellationToken cancellationToken)
{
var declaratorLocation = diagnostic.AdditionalLocations[0];
......@@ -89,9 +112,14 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
editor.ReplaceNode(
localDeclaration.GetNextStatement(),
(s, g) => s.WithPrependedNonIndentationTriviaFrom(localDeclaration));
removeStatement(localDeclaration);
}
else
{
editor.RemoveNode(declarator, SyntaxRemoveOptions.KeepUnbalancedDirectives);
}
editor.RemoveNode(declarator, SyntaxRemoveOptions.KeepUnbalancedDirectives);
editor.ReplaceNode(comparison, isExpression.WithTriviaFrom(comparison));
}
......
......@@ -13,6 +13,9 @@ namespace Microsoft.CodeAnalysis.CSharp.Extensions
{
internal static class StatementSyntaxExtensions
{
public static StatementSyntax WithoutLeadingBlankLinesInTrivia(this StatementSyntax statement)
=> statement.WithLeadingTrivia(statement.GetLeadingTrivia().WithoutLeadingBlankLines());
public static StatementSyntax GetPreviousStatement(this StatementSyntax statement)
{
if (statement != null)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Extensions
......@@ -47,6 +50,37 @@ public static IEnumerable<SyntaxTrivia> SkipInitialWhitespace(this SyntaxTriviaL
return triviaList.SkipWhile(t => t.Kind() == SyntaxKind.WhitespaceTrivia);
}
private static ImmutableArray<ImmutableArray<SyntaxTrivia>> GetLeadingBlankLines(SyntaxTriviaList triviaList)
{
var result = ArrayBuilder<ImmutableArray<SyntaxTrivia>>.GetInstance();
var currentLine = ArrayBuilder<SyntaxTrivia>.GetInstance();
foreach (var trivia in triviaList)
{
currentLine.Add(trivia);
if (trivia.Kind() == SyntaxKind.EndOfLineTrivia)
{
bool currentLineIsBlank = currentLine.All(t =>
t.Kind() == SyntaxKind.EndOfLineTrivia ||
t.Kind() == SyntaxKind.WhitespaceTrivia);
if (!currentLineIsBlank)
{
break;
}
result.Add(currentLine.ToImmutableAndFree());
currentLine = ArrayBuilder<SyntaxTrivia>.GetInstance();
}
}
return result.ToImmutableAndFree();
}
public static SyntaxTriviaList WithoutLeadingBlankLines(this SyntaxTriviaList triviaList)
{
var triviaInLeadingBlankLines = GetLeadingBlankLines(triviaList).SelectMany(l => l);
return new SyntaxTriviaList(triviaList.Skip(triviaInLeadingBlankLines.Count()));
}
/// <summary>
/// Takes an INCLUSIVE range of trivia from the trivia list.
/// </summary>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册