提交 74c477c8 编写于 作者: C CyrusNajmabadi

Add specialized formatting for teh equals expressions we create.

上级 f5fe0503
......@@ -129,6 +129,7 @@
<Compile Include="AddPackage\InstallPackageDirectlyCodeAction.cs" />
<Compile Include="AddConstructorParametersFromMembers\State.cs" />
<Compile Include="GenerateConstructorFromMembers\GenerateConstructorWithDialogCodeAction.cs" />
<Compile Include="GenerateEqualsAndGetHashCodeFromMembers\FormatLargeBinaryExpressionRule.cs" />
<Compile Include="GenerateEqualsAndGetHashCodeFromMembers\GenerateEqualsAndHashWithDialogCodeAction.cs" />
<Compile Include="PickMembers\IPickMembersService.cs" />
<Compile Include="PickMembers\PickMembersResult.cs" />
......
// 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.Collections.Generic;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers
{
internal partial class GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider
{
private partial class GenerateEqualsAndGetHashCodeAction : CodeAction
{
private class FormatLargeBinaryExpressionRule : AbstractFormattingRule
{
private ISyntaxFactsService _syntaxFacts;
public FormatLargeBinaryExpressionRule(ISyntaxFactsService syntaxFacts)
{
_syntaxFacts = syntaxFacts;
}
public override AdjustNewLinesOperation GetAdjustNewLinesOperation(
SyntaxToken previousToken, SyntaxToken currentToken, OptionSet optionSet, NextOperation<AdjustNewLinesOperation> nextOperation)
{
if (_syntaxFacts.IsLogicalAndExpression(previousToken.Parent))
{
return FormattingOperations.CreateAdjustNewLinesOperation(1, AdjustNewLinesOption.PreserveLines);
}
return nextOperation.Invoke();
}
public override void AddIndentBlockOperations(
List<IndentBlockOperation> list, SyntaxNode node, OptionSet optionSet, NextAction<IndentBlockOperation> nextOperation)
{
if (_syntaxFacts.IsReturnStatement(node))
{
list.Add(FormattingOperations.CreateRelativeIndentBlockOperation(
node.GetFirstToken(),
node.GetFirstToken().GetNextToken(),
node.GetLastToken(),
indentationDelta: 1,
option: IndentBlockOption.RelativePosition));
return;
}
nextOperation.Invoke(list);
}
}
}
}
}
\ No newline at end of file
......@@ -7,6 +7,9 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Formatting.Rules;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
......@@ -14,8 +17,10 @@ namespace Microsoft.CodeAnalysis.GenerateEqualsAndGetHashCodeFromMembers
{
internal partial class GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider
{
private class GenerateEqualsAndGetHashCodeAction : CodeAction
private partial class GenerateEqualsAndGetHashCodeAction : CodeAction
{
private static readonly SyntaxAnnotation s_specializedFormattingAnnotation = new SyntaxAnnotation();
private readonly bool _generateEquals;
private readonly bool _generateGetHashCode;
private readonly GenerateEqualsAndGetHashCodeFromMembersCodeRefactoringProvider _service;
......@@ -60,13 +65,21 @@ protected override async Task<Document> GetChangedDocumentAsync(CancellationToke
var syntaxTree = await _document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
return await CodeGenerator.AddMemberDeclarationsAsync(
var newDocument = await CodeGenerator.AddMemberDeclarationsAsync(
_document.Project.Solution,
_containingType,
members,
new CodeGenerationOptions(contextLocation: syntaxTree.GetLocation(_textSpan)),
cancellationToken)
.ConfigureAwait(false);
cancellationToken).ConfigureAwait(false);
var rules = new List<IFormattingRule> { new FormatLargeBinaryExpressionRule(_document.GetLanguageService<ISyntaxFactsService>()) };
rules.AddRange(Formatter.GetDefaultFormattingRules(_document));
var formattedDocument = await Formatter.FormatAsync(
newDocument, s_specializedFormattingAnnotation,
options: null, rules: rules, cancellationToken: cancellationToken).ConfigureAwait(false);
return formattedDocument;
}
private async Task<IMethodSymbol> CreateGetHashCodeMethodAsync(CancellationToken cancellationToken)
......@@ -80,7 +93,8 @@ private async Task<IMethodSymbol> CreateEqualsMethodAsync(CancellationToken canc
{
var compilation = await _document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
return _document.GetLanguageService<SyntaxGenerator>().CreateEqualsMethod(
compilation, _containingType, _selectedMembers, cancellationToken);
compilation, _containingType, _selectedMembers,
s_specializedFormattingAnnotation, cancellationToken);
}
public override string Title
......
......@@ -231,9 +231,10 @@ public bool IsLockStatement(SyntaxNode node)
}
public bool IsUsingStatement(SyntaxNode node)
{
return node is UsingStatementSyntax;
}
=> node.Kind() == SyntaxKind.UsingStatement;
public bool IsReturnStatement(SyntaxNode node)
=> node.Kind() == SyntaxKind.ReturnStatement;
public bool IsThisConstructorInitializer(SyntaxToken token)
{
......@@ -1806,6 +1807,9 @@ public void GetPartsOfConditionalExpression(SyntaxNode node, out SyntaxNode cond
public SyntaxNode WalkDownParentheses(SyntaxNode node)
=> (node as ExpressionSyntax)?.WalkDownParentheses() ?? node;
public bool IsLogicalAndExpression(SyntaxNode node)
=> node.Kind() == SyntaxKind.LogicalAndExpression;
public bool IsLogicalNotExpression(SyntaxNode node)
=> node.Kind() == SyntaxKind.LogicalNotExpression;
......
......@@ -75,6 +75,7 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsExpressionOfAwaitExpression(SyntaxNode node);
SyntaxNode GetExpressionOfAwaitExpression(SyntaxNode node);
bool IsLogicalAndExpression(SyntaxNode node);
bool IsLogicalNotExpression(SyntaxNode node);
SyntaxNode GetOperandOfPrefixUnaryExpression(SyntaxNode node);
......@@ -164,6 +165,7 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsForEachStatement(SyntaxNode node);
bool IsLockStatement(SyntaxNode node);
bool IsUsingStatement(SyntaxNode node);
bool IsReturnStatement(SyntaxNode node);
bool IsLocalDeclarationStatement(SyntaxNode node);
bool IsDeclaratorOfLocalDeclarationStatement(SyntaxNode declator, SyntaxNode localDeclarationStatement);
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
......@@ -23,9 +24,12 @@ internal static partial class ICodeDefinitionFactoryExtensions
Compilation compilation,
INamedTypeSymbol containingType,
IList<ISymbol> symbols,
SyntaxAnnotation statementAnnotation,
CancellationToken cancellationToken)
{
var statements = CreateEqualsMethodStatements(factory, compilation, containingType, symbols, cancellationToken);
var statements = CreateEqualsMethodStatements(
factory, compilation, containingType, symbols, cancellationToken);
statements = statements.SelectAsArray(s => s.WithAdditionalAnnotations(statementAnnotation));
return CodeGenerationSymbolFactory.CreateMethodSymbol(
attributes: null,
......@@ -40,7 +44,7 @@ internal static partial class ICodeDefinitionFactoryExtensions
statements: statements);
}
private static IList<SyntaxNode> CreateEqualsMethodStatements(
private static ImmutableArray<SyntaxNode> CreateEqualsMethodStatements(
SyntaxGenerator factory,
Compilation compilation,
INamedTypeSymbol containingType,
......@@ -48,11 +52,11 @@ internal static partial class ICodeDefinitionFactoryExtensions
CancellationToken cancellationToken)
{
var iequatableType = compilation.GetTypeByMetadataName("System.IEquatable`1");
var statements = new List<SyntaxNode>();
var statements = ArrayBuilder<SyntaxNode>.GetInstance();
var parts = StringBreaker.BreakIntoWordParts(containingType.Name);
string localName = "v";
for (int i = parts.Count - 1; i >= 0; i--)
var localName = "v";
for (var i = parts.Count - 1; i >= 0; i--)
{
var p = parts[i];
if (char.IsLetter(containingType.Name[p.Start]))
......@@ -120,7 +124,8 @@ internal static partial class ICodeDefinitionFactoryExtensions
foreach (var member in members)
{
var symbolNameExpression = factory.IdentifierName(member.Name);
var thisSymbol = factory.MemberAccessExpression(factory.ThisExpression(), symbolNameExpression).WithAdditionalAnnotations(Simplification.Simplifier.Annotation);
var thisSymbol = factory.MemberAccessExpression(factory.ThisExpression(), symbolNameExpression)
.WithAdditionalAnnotations(Simplification.Simplifier.Annotation);
var otherSymbol = factory.MemberAccessExpression(localNameExpression, symbolNameExpression);
#if false
......@@ -161,7 +166,7 @@ internal static partial class ICodeDefinitionFactoryExtensions
statements.Add(factory.ReturnStatement(
expressions.Aggregate(factory.LogicalAndExpression)));
return statements;
return statements.ToImmutableAndFree();
}
private static bool ImplementsIEquatable(ITypeSymbol memberType, INamedTypeSymbol iequatableType)
......
......@@ -205,7 +205,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function
Public Function IsUsingStatement(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsUsingStatement
Return TypeOf node Is UsingStatementSyntax
Return node.Kind() = SyntaxKind.UsingStatement
End Function
Public Function IsReturnStatement(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsReturnStatement
Return node.Kind() = SyntaxKind.ReturnStatement
End Function
Public Function IsThisConstructorInitializer(token As SyntaxToken) As Boolean Implements ISyntaxFactsService.IsThisConstructorInitializer
......@@ -1607,6 +1611,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return If(TryCast(node, ExpressionSyntax)?.WalkDownParentheses(), node)
End Function
Public Function IsLogicalAndExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLogicalAndExpression
Return node.IsKind(SyntaxKind.AndAlsoExpression)
End Function
Public Function IsLogicalNotExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsLogicalNotExpression
Return node.IsKind(SyntaxKind.NotExpression)
End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册