未验证 提交 471fce45 编写于 作者: J Joey Robichaud 提交者: GitHub

Merge pull request #31951 from CyrusNajmabadi/fluentWrapping

Add new refactoring feature to wrap chains of fluent calls.
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CodeRefactorings; using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.Editor.Wrapping.SeparatedSyntaxList; using Microsoft.CodeAnalysis.CSharp.Editor.Wrapping.SeparatedSyntaxList;
using Microsoft.CodeAnalysis.Editor.CSharp.Wrapping.BinaryExpression; using Microsoft.CodeAnalysis.Editor.CSharp.Wrapping.BinaryExpression;
using Microsoft.CodeAnalysis.Editor.CSharp.Wrapping.ChainedExpression;
using Microsoft.CodeAnalysis.Editor.Wrapping; using Microsoft.CodeAnalysis.Editor.Wrapping;
namespace Microsoft.CodeAnalysis.Editor.CSharp.Wrapping namespace Microsoft.CodeAnalysis.Editor.CSharp.Wrapping
...@@ -16,7 +17,8 @@ internal class CSharpWrappingCodeRefactoringProvider : AbstractWrappingCodeRefac ...@@ -16,7 +17,8 @@ internal class CSharpWrappingCodeRefactoringProvider : AbstractWrappingCodeRefac
ImmutableArray.Create<ISyntaxWrapper>( ImmutableArray.Create<ISyntaxWrapper>(
new CSharpArgumentWrapper(), new CSharpArgumentWrapper(),
new CSharpParameterWrapper(), new CSharpParameterWrapper(),
new CSharpBinaryExpressionWrapper()); new CSharpBinaryExpressionWrapper(),
new CSharpChainedExpressionWrapper());
[ImportingConstructor] [ImportingConstructor]
public CSharpWrappingCodeRefactoringProvider() public CSharpWrappingCodeRefactoringProvider()
......
// 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 Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Indentation;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editor.Wrapping.ChainedExpression;
namespace Microsoft.CodeAnalysis.Editor.CSharp.Wrapping.ChainedExpression
{
internal class CSharpChainedExpressionWrapper :
AbstractChainedExpressionWrapper<NameSyntax, BaseArgumentListSyntax>
{
public CSharpChainedExpressionWrapper()
: base(CSharpIndentationService.Instance, CSharpSyntaxFactsService.Instance)
{
}
protected override SyntaxTriviaList GetNewLineBeforeOperatorTrivia(SyntaxTriviaList newLine)
=> newLine;
}
}
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Wrapping namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Wrapping
{ {
public class BinaryWrappingTests : AbstractWrappingTests public class BinaryExpressionWrappingTests : AbstractWrappingTests
{ {
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters) protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new CSharpWrappingCodeRefactoringProvider(); => new CSharpWrappingCodeRefactoringProvider();
......
// 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.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Editor.CSharp.Wrapping;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Wrapping
{
public class ChainedExpressionWrappingTests : AbstractWrappingTests
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new CSharpWrappingCodeRefactoringProvider();
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestMissingWithSyntaxError()
{
await TestMissingAsync(
@"class C {
void Bar() {
[||]the.quick().brown.fox(,);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestMissingWithoutEnoughChunks()
{
await TestMissingAsync(
@"class C {
void Bar() {
[||]the.quick();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestWithEnoughChunks()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown().fox.jumped();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestGenericNames()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown<int>().fox.jumped<string, bool>();
}
}",
@"class C {
void Bar() {
the.quick.brown<int>().fox
.jumped<string, bool>();
}
}",
@"class C {
void Bar() {
the.quick.brown<int>().fox
.jumped<string, bool>();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestElementAccess()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown[1, 2, 3].fox.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestUnwrap()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3].fox.jumped[1][2][3];
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestWrapAndUnwrap()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.
brown[1, 2, 3]
.fox.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3].fox.jumped[1][2][3];
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestChunkMustHaveDottedSection()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the().quick.brown[1, 2, 3].fox.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the().quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}",
@"class C {
void Bar() {
the().quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TrailingNonCallIsNotWrapped()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown().fox.jumped().over;
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over;
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TrailingLongWrapping1()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown().fox.jumped().over.the().lazy().dog();
}
}",
GetIndentionColumn(35),
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over.the()
.lazy().dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over
.the().lazy()
.dog();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TrailingLongWrapping2()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown().fox.jumped().over.the().lazy().dog();
}
}",
GetIndentionColumn(40),
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over.the().lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over.the()
.lazy().dog();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TrailingLongWrapping3()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown().fox.jumped().over.the().lazy().dog();
}
}",
GetIndentionColumn(60),
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox.jumped().over.the().lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox.jumped().over.the().lazy()
.dog();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInConditionalAccess()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
the?.[||]quick.brown().fox.jumped();
}
}",
@"class C {
void Bar() {
the?.quick.brown().fox
.jumped();
}
}",
@"class C {
void Bar() {
the?.quick.brown().fox
.jumped();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInConditionalAccess2()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
the?.[||]quick.brown()?.fox.jumped();
}
}",
@"class C {
void Bar() {
the?.quick.brown()?.fox
.jumped();
}
}",
@"class C {
void Bar() {
the?.quick.brown()?.fox
.jumped();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInConditionalAccess3()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
the?.[||]quick.brown()?.fox().jumped();
}
}",
@"class C {
void Bar() {
the?.quick.brown()?.fox()
.jumped();
}
}",
@"class C {
void Bar() {
the?.quick.brown()?.fox()
.jumped();
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInConditionalAccess4()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the?.quick().brown()?.fox().jumped();
}
}",
@"class C {
void Bar() {
the?.quick()
.brown()?.fox()
.jumped();
}
}");
}
}
}
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
namespace Microsoft.CodeAnalysis.Editor.Wrapping.BinaryExpression namespace Microsoft.CodeAnalysis.Editor.Wrapping.BinaryExpression
{ {
internal partial class AbstractBinaryExpressionWrapper<TBinaryExpressionSyntax> where TBinaryExpressionSyntax : SyntaxNode internal partial class AbstractBinaryExpressionWrapper<TBinaryExpressionSyntax>
{ {
private class BinaryExpressionCodeActionComputer : private class BinaryExpressionCodeActionComputer :
AbstractCodeActionComputer<AbstractBinaryExpressionWrapper<TBinaryExpressionSyntax>> AbstractCodeActionComputer<AbstractBinaryExpressionWrapper<TBinaryExpressionSyntax>>
...@@ -21,6 +21,11 @@ private class BinaryExpressionCodeActionComputer : ...@@ -21,6 +21,11 @@ private class BinaryExpressionCodeActionComputer :
private readonly ImmutableArray<SyntaxNodeOrToken> _exprsAndOperators; private readonly ImmutableArray<SyntaxNodeOrToken> _exprsAndOperators;
private readonly OperatorPlacementWhenWrappingPreference _preference; private readonly OperatorPlacementWhenWrappingPreference _preference;
/// <summary>
/// trivia to place at the end of a node prior to a chunk that is wrapped.
/// For C# this will just be a newline. For VB this will include a line-
/// continuation character.
/// </summary>
private readonly SyntaxTriviaList _newlineBeforeOperatorTrivia; private readonly SyntaxTriviaList _newlineBeforeOperatorTrivia;
/// <summary> /// <summary>
......
// 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.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.Editor.Wrapping.ChainedExpression
{
/// <summary>
/// Finds and wraps 'chained' expressions. For the purpose of this feature, a chained
/// expression is built out of 'chunks' where each chunk is of the form
///
/// <code>
/// . name (arglist) remainder
/// </code>
///
/// So, if there are two or more of these like:
///
/// <code>
/// . name1 (arglist1) remainder1 . name2 (arglist2) remainder2
/// </code>
///
/// Then this will be wrapped such that the dots align like so:
///
/// <code>
/// . name1 (arglist1) remainder1
/// . name2 (arglist2) remainder2
/// </code>
///
/// Note: for the sake of simplicity, (arglist) is used both for the argument list of
/// an InvocationExpression and an ElementAccessExpression.
///
/// 'remainder' is all the postfix expression that can follow <c>. name (arglist)</c>. i.e.
/// member-access expressions, conditional-access expressions, etc. Effectively, anything
/// the language allows at this point as long as it doesn't start another 'chunk' itself.
///
/// This approach gives an intuitive wrapping algorithm that matches the common way
/// many wrap dotted invocations, while also effectively not limiting the wrapper to
/// only simple forms like <c>.a(...).b(...).c(...)</c>.
/// </summary>
internal abstract partial class AbstractChainedExpressionWrapper<
TNameSyntax,
TBaseArgumentListSyntax> : AbstractSyntaxWrapper
where TNameSyntax : SyntaxNode
where TBaseArgumentListSyntax : SyntaxNode
{
private readonly ISyntaxFactsService _syntaxFacts;
private readonly int _dotToken;
private readonly int _questionToken;
protected AbstractChainedExpressionWrapper(
Indentation.IIndentationService indentationService,
ISyntaxFactsService syntaxFacts) : base(indentationService)
{
_syntaxFacts = syntaxFacts;
_dotToken = syntaxFacts.SyntaxKinds.DotToken;
_questionToken = syntaxFacts.SyntaxKinds.QuestionToken;
}
/// <summary>
/// Gets the language specific trivia that should be inserted before an operator if the
/// user wants to wrap the operator to the next line. For C# this is a simple newline-trivia.
/// For VB, this will be a line-continuation char (<c>_</c>), followed by a newline.
/// </summary>
protected abstract SyntaxTriviaList GetNewLineBeforeOperatorTrivia(SyntaxTriviaList newLine);
public sealed override async Task<ICodeActionComputer> TryCreateComputerAsync(
Document document, int position, SyntaxNode node, CancellationToken cancellationToken)
{
// We have to be on a chain part. If not, there's nothing to do here at all.
if (!IsDecomposableChainPart(node))
{
return null;
}
// Has to be the topmost chain part. If we're not on the topmost, then just
// bail out here. Our caller will continue walking upwards until it hits the
// topmost node.
if (IsDecomposableChainPart(node.Parent))
{
return null;
}
// We're at the top of something that looks like it could be part of a chained
// expression. Break it into the individual chunks. We need to have at least
// two chunks or this to be worth wrapping.
//
// i.e. if we only have <c>this.Goo(...)</c> there's nothing to wrap. However, we can
// wrap when we have <c>this.Goo(...).Bar(...)</c>.
var chunks = GetChainChunks(node);
if (chunks.Length <= 1)
{
return null;
}
// If any of these chunk parts are unformattable, then we don't want to offer anything
// here as we may make formatting worse for this construct.
foreach (var chunk in chunks)
{
var unformattable = await ContainsUnformattableContentAsync(
document, chunk, cancellationToken).ConfigureAwait(false);
if (unformattable)
{
return null;
}
}
// Looks good. Create the action computer which will actually determine
// the set of wrapping options to provide.
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
return new CallExpressionCodeActionComputer(
this, document, sourceText, options, chunks, cancellationToken);
}
private ImmutableArray<ImmutableArray<SyntaxNodeOrToken>> GetChainChunks(SyntaxNode node)
{
// First, just take the topmost chain node and break into the individual
// nodes and tokens we want to treat as individual elements. i.e. an
// element that would be kept together. For example, the arg-list of an
// invocation is an element we do not want to ever break-up/wrap.
var pieces = ArrayBuilder<SyntaxNodeOrToken>.GetInstance();
Decompose(node, pieces);
// Now that we have the pieces, find 'chunks' similar to the form:
//
// . Name (...) Remainder...
//
// These will be the chunks that are wrapped and aligned on that dot.
//
// Here 'remainder' is everything up to the next <c>. Name (...)</c> chunk.
var chunks = ArrayBuilder<ImmutableArray<SyntaxNodeOrToken>>.GetInstance();
BreakPiecesIntoChunks(pieces, chunks);
pieces.Free();
return chunks.ToImmutableAndFree();
}
private void BreakPiecesIntoChunks(
ArrayBuilder<SyntaxNodeOrToken> pieces,
ArrayBuilder<ImmutableArray<SyntaxNodeOrToken>> chunks)
{
// Have to look for the first chunk after the first piece. i.e. if the pieces
// starts with <c>.Foo().Bar().Baz()</c> then the chunks would be <c>.Bar()</c>
// and <c>.Baz()</c>.
//
// However, if we had <c>this.Foo().Bar().Baz()</c> then the chunks would be
// <c>.Foo()</c> <c>.Bar()</c> and <c>.Baz()</c>.
//
// Note: the only way to get the <c>.Foo().Bar().Baz()</c> case today is in VB in
// a 'with' statement. if we have that, we don't want to wrap it into:
//
// <code>
// with ...
// .Foo()
// .Bar()
// .Baz()
// </code>
//
// Instead, we want to create
//
// <code>
// with ...
// .Foo().Bar()
// .Baz()
// </code>
var currentChunkStart = FindNextChunkStart(pieces, firstChunk: true, index: 1);
if (currentChunkStart < 0)
{
return;
}
while (true)
{
// Look for the next chunk starting after the current chunk we're on.
var nextChunkStart = FindNextChunkStart(pieces, firstChunk: false, index: currentChunkStart + 1);
if (nextChunkStart < 0)
{
// No next chunk after the current one. The current chunk just
// extends to the end of the pieces.
chunks.Add(GetSubRange(pieces, currentChunkStart, end: pieces.Count));
return;
}
// Had a chunk after this one. Record the current chunk, move to the start
// of the next one, and then keep going.
chunks.Add(GetSubRange(pieces, currentChunkStart, end: nextChunkStart));
currentChunkStart = nextChunkStart;
}
}
/// <summary>
/// Looks for the next sequence of <c>. Name (ArgList)</c>. Note, except for the first
/// chunk, this cannot be of the form <c>? . Name (ArgList)</c> as we do not want to
/// wrap before a dot in a <c>?.</c> form. This doesn't matter for the first chunk as
/// we won't be wrapping that one.
/// </summary>
private int FindNextChunkStart(
ArrayBuilder<SyntaxNodeOrToken> pieces, bool firstChunk, int index)
{
for (var i = index; i < pieces.Count; i++)
{
if (IsToken(_dotToken, pieces, i) &&
IsNode<TNameSyntax>(pieces, i + 1) &&
IsNode<TBaseArgumentListSyntax>(pieces, i + 2))
{
if (firstChunk ||
!IsToken(_questionToken, pieces, i - 1))
{
return i;
}
}
}
// Couldn't find the start of another chunk.
return -1;
}
private bool IsNode<TNode>(ArrayBuilder<SyntaxNodeOrToken> pieces, int index)
=> index < pieces.Count &&
pieces[index] is var piece &&
piece.IsNode &&
piece.AsNode() is TNode;
private bool IsToken(int tokenKind, ArrayBuilder<SyntaxNodeOrToken> pieces, int index)
=> index < pieces.Count &&
pieces[index] is var piece &&
piece.IsToken &&
piece.AsToken().RawKind == tokenKind;
private ImmutableArray<SyntaxNodeOrToken> GetSubRange(
ArrayBuilder<SyntaxNodeOrToken> pieces, int start, int end)
{
var result = ArrayBuilder<SyntaxNodeOrToken>.GetInstance(end - start);
for (var i = start; i < end; i++)
{
result.Add(pieces[i]);
}
return result.ToImmutableAndFree();
}
private bool IsDecomposableChainPart(SyntaxNode node)
{
// This is the effective set of language constructs that can 'chain'
// off of a call <c>.M(...)</c>. They are:
//
// 1. <c>.Name</c> or <c>->Name</c>. i.e. <c>.M(...).Name</c>
// 2. <c>(...)</c>. i.e. <c>.M(...)(...)</c>
// 3. <c>[...]</c>. i.e. <c>.M(...)[...]</c>
// 4. <c>++</c>, </c>--</c>, </c>!</c>. i.e. <c>.M(...)++</c>
// 5. <c>?</c>. i.e. <c>.M(...)?. ...</c> or <c>.M(...)?[...]</c>
// '5' handles both the ConditionalAccess and MemberBinding cases below.
if (node != null)
{
return _syntaxFacts.IsAnyMemberAccessExpression(node)
|| _syntaxFacts.IsInvocationExpression(node)
|| _syntaxFacts.IsElementAccessExpression(node)
|| _syntaxFacts.IsPostfixUnaryExpression(node)
|| _syntaxFacts.IsConditionalAccessExpression(node)
|| _syntaxFacts.IsMemberBindingExpression(node);
}
return false;
}
/// <summary>
/// Recursively walks down <paramref name="node"/> decomposing it into the individual
/// tokens and nodes we want to look for chunks in.
/// </summary>
private void Decompose(SyntaxNode node, ArrayBuilder<SyntaxNodeOrToken> pieces)
{
// Ignore null nodes, they are never relevant when building up the sequence of
// pieces in this chained expression.
if (node is null)
{
return;
}
// We've hit some node that can't be decomposed further (like an argument list,
// or name node). Just add directly to the pieces list.
if (!IsDecomposableChainPart(node))
{
pieces.Add(node);
return;
}
// For everything else that is a chain part, just decompose into its constituent
// parts and add to the pieces array.
foreach (var child in node.ChildNodesAndTokens())
{
if (child.IsNode)
{
Decompose(child.AsNode(), pieces);
}
else
{
pieces.Add(child.AsToken());
}
}
}
}
}
// 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.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Wrapping.ChainedExpression
{
internal abstract partial class AbstractChainedExpressionWrapper<
TNameSyntax,
TBaseArgumentListSyntax>
{
/// <summary>
/// Responsible for actually computing the set of potential wrapping options
/// for chained expressions. The three options we offer are basically
/// 1. wrap-each. Each chunk will be wrapped and aligned with the first chunk.
/// 2. wrap-long. The same as '1', except a chunk will only be wrapped
/// if it would go past the preferred wrapping column.
/// 3. Unwrap. All the chunks will be placed on a single line.
///
/// Note: These three options are always computed and returned. The caller
/// is the one that ends up eliminating any if they would be redundant. i.e.
/// if wrap-long produces the same results as wrap-each, then the caller will
/// filter it out.
/// </summary>
private class CallExpressionCodeActionComputer :
AbstractCodeActionComputer<AbstractChainedExpressionWrapper<TNameSyntax, TBaseArgumentListSyntax>>
{
/// <summary>
/// The chunks to normalize and wrap. The first chunk will be normalized,
/// but not wrapped. Successive chunks will be normalized and wrapped
/// appropriately depending on if this is wrap-each or wrap-long.
/// </summary>
private readonly ImmutableArray<ImmutableArray<SyntaxNodeOrToken>> _chunks;
/// <summary>
/// trivia to place at the end of a node prior to a chunk that is wrapped.
/// For C# this will just be a newline. For VB this will include a line-
/// continuation character.
/// </summary>
private readonly SyntaxTriviaList _newlineBeforeOperatorTrivia;
/// <summary>
/// The indent trivia to insert if we are trying to align wrapped chunks with the
/// first period of the original chunk.
/// </summary>
private readonly SyntaxTriviaList _firstPeriodIndentationTrivia;
/// <summary>
/// The indent trivia to insert if we are trying to simply smart-indent all wrapped
/// chunks.
/// </summary>
private readonly SyntaxTriviaList _smartIndentTrivia;
public CallExpressionCodeActionComputer(
AbstractChainedExpressionWrapper<TNameSyntax, TBaseArgumentListSyntax> service,
Document document,
SourceText originalSourceText,
DocumentOptionSet options,
ImmutableArray<ImmutableArray<SyntaxNodeOrToken>> chunks,
CancellationToken cancellationToken)
: base(service, document, originalSourceText, options, cancellationToken)
{
_chunks = chunks;
var generator = SyntaxGenerator.GetGenerator(document);
// Both [0][0] indices are safe here. We can only get here if we had more than
// two chunks to wrap. And each chunk is required to have at least three elements
// (i.e. <c>. name (arglist)</c>).
var firstPeriod = chunks[0][0];
_firstPeriodIndentationTrivia = new SyntaxTriviaList(generator.Whitespace(
OriginalSourceText.GetOffset(firstPeriod.SpanStart).CreateIndentationString(UseTabs, TabSize)));
_smartIndentTrivia = new SyntaxTriviaList(generator.Whitespace(
this.GetSmartIndentationAfter(firstPeriod)));
_newlineBeforeOperatorTrivia = service.GetNewLineBeforeOperatorTrivia(NewLineTrivia);
}
protected override async Task<ImmutableArray<WrappingGroup>> ComputeWrappingGroupsAsync()
{
var actions = ArrayBuilder<WrapItemsAction>.GetInstance();
await AddWrapCodeActionAsync(actions).ConfigureAwait(false);
await AddUnwrapCodeActionAsync(actions).ConfigureAwait(false);
await AddWrapLongCodeActionAsync(actions).ConfigureAwait(false);
return ImmutableArray.Create(new WrappingGroup(isInlinable: true, actions.ToImmutableAndFree()));
}
// Pass 0 as the wrapping column as we effectively always want to wrap each chunk
// Not just when the chunk would go past the wrapping column.
private async Task AddWrapCodeActionAsync(ArrayBuilder<WrapItemsAction> actions)
{
actions.Add(await TryCreateCodeActionAsync(GetWrapEdits(wrappingColumn: 0, align: false), FeaturesResources.Wrapping, FeaturesResources.Wrap_call_chain).ConfigureAwait(false));
actions.Add(await TryCreateCodeActionAsync(GetWrapEdits(wrappingColumn: 0, align: true), FeaturesResources.Wrapping, FeaturesResources.Wrap_and_align_call_chain).ConfigureAwait(false));
}
private async Task AddUnwrapCodeActionAsync(ArrayBuilder<WrapItemsAction> actions)
{
actions.Add(await TryCreateCodeActionAsync(GetUnwrapEdits(), FeaturesResources.Wrapping, FeaturesResources.Unwrap_call_chain).ConfigureAwait(false));
}
private async Task AddWrapLongCodeActionAsync(ArrayBuilder<WrapItemsAction> actions)
{
actions.Add(await TryCreateCodeActionAsync(GetWrapEdits(WrappingColumn, align: false), FeaturesResources.Wrapping, FeaturesResources.Wrap_long_call_chain).ConfigureAwait(false));
actions.Add(await TryCreateCodeActionAsync(GetWrapEdits(WrappingColumn, align: true), FeaturesResources.Wrapping, FeaturesResources.Wrap_and_align_long_call_chain).ConfigureAwait(false));
}
private ImmutableArray<Edit> GetWrapEdits(int wrappingColumn, bool align)
{
var result = ArrayBuilder<Edit>.GetInstance();
// First, normalize the first chunk.
var firstChunk = _chunks[0];
DeleteAllSpacesInChunk(result, firstChunk);
var indentationTrivia = align ? _firstPeriodIndentationTrivia : _smartIndentTrivia;
// Our starting position is at the end of the first chunk. That position
// is effectively the start of the first period, plus the length of the
// normalized first chuck.
var position = _firstPeriodIndentationTrivia.FullSpan.Length + NormalizedWidth(firstChunk);
// Now, go to each subsequent chunk. If keeping it on the current line would
// cause us to go past the requested wrapping column, then wrap it and proceed.
for (var i = 1; i < _chunks.Length; i++)
{
var chunk = _chunks[i];
var wrapChunk = position + NormalizedWidth(chunk) >= wrappingColumn;
if (wrapChunk)
{
// we're wrapping. So our position is reset to the indentation
// on the next line.
position = indentationTrivia.FullSpan.Length;
// First, add a newline at the end of the previous arglist, and then
// indent the very first member chunk appropriately.
result.Add(Edit.UpdateBetween(
_chunks[i - 1].Last(), _newlineBeforeOperatorTrivia,
indentationTrivia, chunk[0]));
}
// Now, delete all the remaining spaces in this call chunk.
DeleteAllSpacesInChunk(result, chunk);
// Update position based on this chunk we just fixed up.
position += NormalizedWidth(chunk);
}
return result.ToImmutableAndFree();
}
private int NormalizedWidth(ImmutableArray<SyntaxNodeOrToken> chunk)
=> chunk.Sum(s => s.IsNode ? s.AsNode().Width() : s.AsToken().Width());
private ImmutableArray<Edit> GetUnwrapEdits()
{
var result = ArrayBuilder<Edit>.GetInstance();
// Flatten all the chunks into one long list. Then delete all the spaces
// between each piece in that full list.
var flattened = _chunks.SelectMany(c => c).ToImmutableArray();
DeleteAllSpacesInChunk(result, flattened);
return result.ToImmutableAndFree();
}
private static void DeleteAllSpacesInChunk(
ArrayBuilder<Edit> result, ImmutableArray<SyntaxNodeOrToken> chunk)
{
for (var i = 1; i < chunk.Length; i++)
{
result.Add(Edit.DeleteBetween(chunk[i - 1], chunk[i]));
}
}
}
}
}
...@@ -110,7 +110,7 @@ private async Task AddWrappingGroups(ArrayBuilder<WrappingGroup> result) ...@@ -110,7 +110,7 @@ private async Task AddWrappingGroups(ArrayBuilder<WrappingGroup> result)
result.Add(await GetWrapLongGroupAsync().ConfigureAwait(false)); result.Add(await GetWrapLongGroupAsync().ConfigureAwait(false));
} }
#region unwrap all #region unwrap group
private async Task<WrappingGroup> GetUnwrapGroupAsync() private async Task<WrappingGroup> GetUnwrapGroupAsync()
{ {
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.Editor.Wrapping.ChainedExpression
Imports Microsoft.CodeAnalysis.VisualBasic.Indentation
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping.ChainedExpression
Friend Class VisualBasicChainedExpressionWrapper
Inherits AbstractChainedExpressionWrapper(Of NameSyntax, ArgumentListSyntax)
Public Sub New()
MyBase.New(VisualBasicIndentationService.WithoutParameterAlignmentInstance, VisualBasicSyntaxFactsService.Instance)
End Sub
Protected Overrides Function GetNewLineBeforeOperatorTrivia(newLine As SyntaxTriviaList) As SyntaxTriviaList
Return newLine.InsertRange(0, {SyntaxFactory.WhitespaceTrivia(" "), SyntaxFactory.LineContinuationTrivia("_")})
End Function
End Class
End Namespace
...@@ -4,6 +4,7 @@ Imports System.Collections.Immutable ...@@ -4,6 +4,7 @@ Imports System.Collections.Immutable
Imports System.Composition Imports System.Composition
Imports Microsoft.CodeAnalysis.CodeRefactorings Imports Microsoft.CodeAnalysis.CodeRefactorings
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping.BinaryExpression Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping.BinaryExpression
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping.ChainedExpression
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping.SeparatedSyntaxList Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping.SeparatedSyntaxList
Imports Microsoft.CodeAnalysis.Editor.Wrapping Imports Microsoft.CodeAnalysis.Editor.Wrapping
...@@ -16,7 +17,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping ...@@ -16,7 +17,8 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping
ImmutableArray.Create(Of ISyntaxWrapper)( ImmutableArray.Create(Of ISyntaxWrapper)(
New VisualBasicArgumentWrapper(), New VisualBasicArgumentWrapper(),
New VisualBasicParameterWrapper(), New VisualBasicParameterWrapper(),
New VisualBasicBinaryExpressionWrapper()) New VisualBasicBinaryExpressionWrapper(),
New VisualBasicChainedExpressionWrapper())
<ImportingConstructor> <ImportingConstructor>
Public Sub New() Public Sub New()
......
...@@ -6,7 +6,7 @@ Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping ...@@ -6,7 +6,7 @@ Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping
Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Options
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping
Public Class BinaryWrappingTests Public Class BinaryExpressionWrappingTests
Inherits AbstractWrappingTests Inherits AbstractWrappingTests
Protected Overrides Function CreateCodeRefactoringProvider(workspace As Workspace, parameters As TestParameters) As CodeRefactoringProvider Protected Overrides Function CreateCodeRefactoringProvider(workspace As Workspace, parameters As TestParameters) As CodeRefactoringProvider
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.CodeRefactorings
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping
Public Class ChainedExpressionWrappingTests
Inherits AbstractWrappingTests
Protected Overrides Function CreateCodeRefactoringProvider(workspace As Workspace, parameters As TestParameters) As CodeRefactoringProvider
Return New VisualBasicWrappingCodeRefactoringProvider()
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestMissingWithSyntaxError() As Task
Await TestMissingAsync(
"class C
sub Bar()
[||]the.quick().brown.fox(
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestMissingWithoutEnoughChunks() As Task
Await TestMissingAsync(
"class C
sub Bar()
[||]the.quick()
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestWithEnoughChunks() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the.quick.brown().fox.jumped()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped()
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestOkWithOmittedargs() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the.quick.brown().fox.jumped(,)
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped(,)
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped(,)
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestUnwrap() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the.quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class",
"class C
sub Bar()
the.quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class",
"class C
sub Bar()
the.quick.brown(1, 2, 3).fox.jumped(1)(2)(3)
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestWrapAndUnwrap() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the.quick.
brown(1, 2, 3) _
.fox.jumped(1)(2)(3)
end sub
end class",
"class C
sub Bar()
the.quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class",
"class C
sub Bar()
the.quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class",
"class C
sub Bar()
the.quick.brown(1, 2, 3).fox.jumped(1)(2)(3)
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestChunkMustHaveDottedSection() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the().quick.brown(1, 2, 3).fox.jumped(1)(2)(3)
end sub
end class",
"class C
sub Bar()
the().quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class",
"class C
sub Bar()
the().quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TrailingNonCallIsNotWrapped() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
dim y = [||]the.quick.brown().fox.jumped().over
end sub
end class",
"class C
sub Bar()
dim y = the.quick.brown().fox _
.jumped().over
end sub
end class",
"class C
sub Bar()
dim y = the.quick.brown().fox _
.jumped().over
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TrailingLongWrapping1() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the.quick.brown().fox.jumped().over.the().lazy().dog()
end sub
end class",
GetIndentionColumn(35),
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over _
.the() _
.lazy() _
.dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over _
.the() _
.lazy() _
.dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over.the() _
.lazy().dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over _
.the().lazy() _
.dog()
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TrailingLongWrapping2() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the.quick.brown().fox.jumped().over.the().lazy().dog()
end sub
end class",
GetIndentionColumn(40),
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over _
.the() _
.lazy() _
.dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over _
.the() _
.lazy() _
.dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over.the().lazy() _
.dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over.the() _
.lazy().dog()
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TrailingLongWrapping3() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the.quick.brown().fox.jumped().over.the().lazy().dog()
end sub
end class",
GetIndentionColumn(60),
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over _
.the() _
.lazy() _
.dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox _
.jumped().over _
.the() _
.lazy() _
.dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox.jumped().over.the().lazy() _
.dog()
end sub
end class",
"class C
sub Bar()
the.quick.brown().fox.jumped().over.the().lazy() _
.dog()
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestAlignToSecondDotInWith() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
with goo
[||].the().quick.brown().fox.jumped(,)
end with
end sub
end class",
"class C
sub Bar()
with goo
.the().quick.brown().fox _
.jumped(,)
end with
end sub
end class",
"class C
sub Bar()
with goo
.the().quick.brown().fox _
.jumped(,)
end with
end sub
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestAlignToThirdDotInWith() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
with goo
[||].the.quick.brown().fox.jumped(,)
end with
end sub
end class",
"class C
sub Bar()
with goo
.the.quick.brown().fox _
.jumped(,)
end with
end sub
end class",
"class C
sub Bar()
with goo
.the.quick.brown().fox _
.jumped(,)
end with
end sub
end class")
End Function
End Class
End Namespace
...@@ -3936,6 +3936,15 @@ internal class FeaturesResources { ...@@ -3936,6 +3936,15 @@ internal class FeaturesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Unwrap call chain.
/// </summary>
internal static string Unwrap_call_chain {
get {
return ResourceManager.GetString("Unwrap_call_chain", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Unwrap expression. /// Looks up a localized string similar to Unwrap expression.
/// </summary> /// </summary>
...@@ -4651,6 +4660,15 @@ internal class FeaturesResources { ...@@ -4651,6 +4660,15 @@ internal class FeaturesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Wrap and align call chain.
/// </summary>
internal static string Wrap_and_align_call_chain {
get {
return ResourceManager.GetString("Wrap_and_align_call_chain", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Wrap and align expression. /// Looks up a localized string similar to Wrap and align expression.
/// </summary> /// </summary>
...@@ -4660,6 +4678,24 @@ internal class FeaturesResources { ...@@ -4660,6 +4678,24 @@ internal class FeaturesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Wrap and align long call chain.
/// </summary>
internal static string Wrap_and_align_long_call_chain {
get {
return ResourceManager.GetString("Wrap_and_align_long_call_chain", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Wrap call chain.
/// </summary>
internal static string Wrap_call_chain {
get {
return ResourceManager.GetString("Wrap_call_chain", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Wrap every argument. /// Looks up a localized string similar to Wrap every argument.
/// </summary> /// </summary>
...@@ -4696,6 +4732,15 @@ internal class FeaturesResources { ...@@ -4696,6 +4732,15 @@ internal class FeaturesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Wrap long call chain.
/// </summary>
internal static string Wrap_long_call_chain {
get {
return ResourceManager.GetString("Wrap_long_call_chain", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Wrap long parameter list. /// Looks up a localized string similar to Wrap long parameter list.
/// </summary> /// </summary>
......
...@@ -1595,6 +1595,15 @@ This version used in: {2}</value> ...@@ -1595,6 +1595,15 @@ This version used in: {2}</value>
<data name="Use_expression_body_for_local_functions" xml:space="preserve"> <data name="Use_expression_body_for_local_functions" xml:space="preserve">
<value>Use expression body for local functions</value> <value>Use expression body for local functions</value>
</data> </data>
<data name="Unwrap_call_chain" xml:space="preserve">
<value>Unwrap call chain</value>
</data>
<data name="Wrap_call_chain" xml:space="preserve">
<value>Wrap call chain</value>
</data>
<data name="Wrap_long_call_chain" xml:space="preserve">
<value>Wrap long call chain</value>
</data>
<data name="Pull_0_up_to_1" xml:space="preserve"> <data name="Pull_0_up_to_1" xml:space="preserve">
<value>Pull '{0}' up to '{1}'</value> <value>Pull '{0}' up to '{1}'</value>
</data> </data>
...@@ -1669,4 +1678,10 @@ This version used in: {2}</value> ...@@ -1669,4 +1678,10 @@ This version used in: {2}</value>
<data name="DisposableFieldsShouldBeDisposedDescription" xml:space="preserve"> <data name="DisposableFieldsShouldBeDisposedDescription" xml:space="preserve">
<value>A type that implements System.IDisposable declares fields that are of types that also implement IDisposable. The Dispose method of the field is not called by the Dispose method of the declaring type. To fix a violation of this rule, call Dispose on fields that are of types that implement IDisposable if you are responsible for allocating and releasing the unmanaged resources held by the field.</value> <value>A type that implements System.IDisposable declares fields that are of types that also implement IDisposable. The Dispose method of the field is not called by the Dispose method of the declaring type. To fix a violation of this rule, call Dispose on fields that are of types that implement IDisposable if you are responsible for allocating and releasing the unmanaged resources held by the field.</value>
</data> </data>
<data name="Wrap_and_align_call_chain" xml:space="preserve">
<value>Wrap and align call chain</value>
</data>
<data name="Wrap_and_align_long_call_chain" xml:space="preserve">
<value>Wrap and align long call chain</value>
</data>
</root> </root>
\ No newline at end of file
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Zrušit zalomení seznamu argumentů</target> <target state="translated">Zrušit zalomení seznamu argumentů</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">Zrušit zalomení výrazu</target> <target state="translated">Zrušit zalomení výrazu</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Upozornění: Změna oboru názvů může vést k vytvoření neplatného kódu a změnit význam kódu.</target> <target state="translated">Upozornění: Změna oboru názvů může vést k vytvoření neplatného kódu a změnit význam kódu.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Zalomit každý argument</target> <target state="translated">Zalomit každý argument</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Zalomit dlouhý seznam argumentů</target> <target state="translated">Zalomit dlouhý seznam argumentů</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Zalomit dlouhý seznam parametrů</target> <target state="translated">Zalomit dlouhý seznam parametrů</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Argumentliste entpacken</target> <target state="translated">Argumentliste entpacken</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">Ausdruck umschließen</target> <target state="translated">Ausdruck umschließen</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Warnung: Durch die Änderung des Namespaces kann der Code ungültig werden oder seine Bedeutung verändern.</target> <target state="translated">Warnung: Durch die Änderung des Namespaces kann der Code ungültig werden oder seine Bedeutung verändern.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Jedes Argument umschließen</target> <target state="translated">Jedes Argument umschließen</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Lange Argumentliste umschließen</target> <target state="translated">Lange Argumentliste umschließen</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Lange Parameterliste umschließen</target> <target state="translated">Lange Parameterliste umschließen</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Desajustar la lista de argumentos</target> <target state="translated">Desajustar la lista de argumentos</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">Desajustar la expresión</target> <target state="translated">Desajustar la expresión</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Advertencia: si cambia Cambiar el espacio de nombres puede producir código inválido y cambiar el significado del código.</target> <target state="translated">Advertencia: si cambia Cambiar el espacio de nombres puede producir código inválido y cambiar el significado del código.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Ajustar todos los argumentos</target> <target state="translated">Ajustar todos los argumentos</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Desajustar la lista larga de argumentos</target> <target state="translated">Desajustar la lista larga de argumentos</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Ajustar la lista larga de parámetros</target> <target state="translated">Ajustar la lista larga de parámetros</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Exclure du wrapper la liste d'arguments</target> <target state="translated">Exclure du wrapper la liste d'arguments</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">Exclure l'expression du wrapper</target> <target state="translated">Exclure l'expression du wrapper</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Avertissement : Le changement d’espace de noms peut produire du code non valide et changer la signification du code.</target> <target state="translated">Avertissement : Le changement d’espace de noms peut produire du code non valide et changer la signification du code.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Inclure dans un wrapper chaque argument</target> <target state="translated">Inclure dans un wrapper chaque argument</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Inclure dans un wrapper la liste d'arguments longue</target> <target state="translated">Inclure dans un wrapper la liste d'arguments longue</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Wrapper la longue liste de paramètres</target> <target state="translated">Wrapper la longue liste de paramètres</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Annulla ritorno a capo per l'elenco di argomenti</target> <target state="translated">Annulla ritorno a capo per l'elenco di argomenti</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">Annulla ritorno a capo per l'espressione</target> <target state="translated">Annulla ritorno a capo per l'espressione</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Avviso: la modifica dello spazio dei nomi può comportare la creazione di codice non valido e modificare il significato del codice.</target> <target state="translated">Avviso: la modifica dello spazio dei nomi può comportare la creazione di codice non valido e modificare il significato del codice.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Imposta ritorno a capo per ogni argomento</target> <target state="translated">Imposta ritorno a capo per ogni argomento</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Imposta ritorno a capo per elenco di argomenti lungo</target> <target state="translated">Imposta ritorno a capo per elenco di argomenti lungo</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Imposta ritorno a capo per elenco di parametri lungo</target> <target state="translated">Imposta ritorno a capo per elenco di parametri lungo</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">引数リストの折り返しを解除</target> <target state="translated">引数リストの折り返しを解除</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">式の折り返しを解除</target> <target state="translated">式の折り返しを解除</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">警告: 名前空間を変更すると無効なコードが生成され、コードの意味が変更される可能性があります。</target> <target state="translated">警告: 名前空間を変更すると無効なコードが生成され、コードの意味が変更される可能性があります。</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">すべての引数を折り返します</target> <target state="translated">すべての引数を折り返します</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">長い引数リストを折り返します</target> <target state="translated">長い引数リストを折り返します</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">長いパラメーター リストを折り返します</target> <target state="translated">長いパラメーター リストを折り返します</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">인수 목록 줄 바꿈 조정</target> <target state="translated">인수 목록 줄 바꿈 조정</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">식 줄 바꿈 조정</target> <target state="translated">식 줄 바꿈 조정</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">경고: 네임스페이스를 변경하면 잘못된 코드가 발생하고 코드 의미가 변경될 수 있습니다.</target> <target state="translated">경고: 네임스페이스를 변경하면 잘못된 코드가 발생하고 코드 의미가 변경될 수 있습니다.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">모든 인수 줄 바꿈</target> <target state="translated">모든 인수 줄 바꿈</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">긴 인수 목록 줄 바꿈</target> <target state="translated">긴 인수 목록 줄 바꿈</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">긴 매개 변수 목록 줄 바꿈</target> <target state="translated">긴 매개 변수 목록 줄 바꿈</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Odpakuj listę argumentów</target> <target state="translated">Odpakuj listę argumentów</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">Odpakuj wyrażenie</target> <target state="translated">Odpakuj wyrażenie</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Ostrzeżenie: Zmiana przestrzeni nazw może skutkować nieprawidłowym kodem i zmianą jego znaczenia.</target> <target state="translated">Ostrzeżenie: Zmiana przestrzeni nazw może skutkować nieprawidłowym kodem i zmianą jego znaczenia.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Opakuj każdy argument</target> <target state="translated">Opakuj każdy argument</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Opakuj długą listę argumentów</target> <target state="translated">Opakuj długą listę argumentów</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Opakuj długą listę parametrów</target> <target state="translated">Opakuj długą listę parametrów</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Desencapsular a lista de argumentos</target> <target state="translated">Desencapsular a lista de argumentos</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">Desencapsular a expressão</target> <target state="translated">Desencapsular a expressão</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Aviso: a alteração do namespace pode produzir código inválido e mudar o significado do código.</target> <target state="translated">Aviso: a alteração do namespace pode produzir código inválido e mudar o significado do código.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Encapsular cada argumento</target> <target state="translated">Encapsular cada argumento</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Encapsular a lista de argumentos longa</target> <target state="translated">Encapsular a lista de argumentos longa</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Encapsular a lista de parâmetros longa</target> <target state="translated">Encapsular a lista de parâmetros longa</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Развернуть список аргументов</target> <target state="translated">Развернуть список аргументов</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">Развернуть выражение</target> <target state="translated">Развернуть выражение</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Предупреждение: изменение пространства имен может привести к появлению недопустимого кода и к изменению значения кода.</target> <target state="translated">Предупреждение: изменение пространства имен может привести к появлению недопустимого кода и к изменению значения кода.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Свернуть каждый аргумент</target> <target state="translated">Свернуть каждый аргумент</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Свернуть длинный список аргументов</target> <target state="translated">Свернуть длинный список аргументов</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Свернуть длинный список параметров</target> <target state="translated">Свернуть длинный список параметров</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">Bağımsız değişken listesinin sarmalamasını kaldır</target> <target state="translated">Bağımsız değişken listesinin sarmalamasını kaldır</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">İfadenin sarmalamasını kaldır</target> <target state="translated">İfadenin sarmalamasını kaldır</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">Uyarı: Ad alanının değiştirilmesi geçersiz kod oluşturabilir ve kodun anlamını değiştirebilir.</target> <target state="translated">Uyarı: Ad alanının değiştirilmesi geçersiz kod oluşturabilir ve kodun anlamını değiştirebilir.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">Her bağımsız değişkeni sarmala</target> <target state="translated">Her bağımsız değişkeni sarmala</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">Uzun bağımsız değişken listesini sarmala</target> <target state="translated">Uzun bağımsız değişken listesini sarmala</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">Uzun parametre listesini sarmala</target> <target state="translated">Uzun parametre listesini sarmala</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">展开参数列表</target> <target state="translated">展开参数列表</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">展开表达式</target> <target state="translated">展开表达式</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">警告: 更改命名空间可能会产生无效的代码并更改代码的含义。</target> <target state="translated">警告: 更改命名空间可能会产生无效的代码并更改代码的含义。</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">包装每个参数</target> <target state="translated">包装每个参数</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">包装长参数列表</target> <target state="translated">包装长参数列表</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">包装长参数列表</target> <target state="translated">包装长参数列表</target>
......
...@@ -447,6 +447,11 @@ ...@@ -447,6 +447,11 @@
<target state="translated">將引數清單取消換行</target> <target state="translated">將引數清單取消換行</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Unwrap_call_chain">
<source>Unwrap call chain</source>
<target state="new">Unwrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Unwrap_expression"> <trans-unit id="Unwrap_expression">
<source>Unwrap expression</source> <source>Unwrap expression</source>
<target state="translated">將運算式取消換行</target> <target state="translated">將運算式取消換行</target>
...@@ -532,11 +537,26 @@ ...@@ -532,11 +537,26 @@
<target state="translated">警告: 變更命名空間可能會產生無效的程式碼及變更程式碼意義。</target> <target state="translated">警告: 變更命名空間可能會產生無效的程式碼及變更程式碼意義。</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_call_chain">
<source>Wrap and align call chain</source>
<target state="new">Wrap and align call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_and_align_expression"> <trans-unit id="Wrap_and_align_expression">
<source>Wrap and align expression</source> <source>Wrap and align expression</source>
<target state="new">Wrap and align expression</target> <target state="new">Wrap and align expression</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_and_align_long_call_chain">
<source>Wrap and align long call chain</source>
<target state="new">Wrap and align long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_call_chain">
<source>Wrap call chain</source>
<target state="new">Wrap call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_every_argument"> <trans-unit id="Wrap_every_argument">
<source>Wrap every argument</source> <source>Wrap every argument</source>
<target state="translated">包裝每個引數</target> <target state="translated">包裝每個引數</target>
...@@ -557,6 +577,11 @@ ...@@ -557,6 +577,11 @@
<target state="translated">包裝長引數清單</target> <target state="translated">包裝長引數清單</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Wrap_long_call_chain">
<source>Wrap long call chain</source>
<target state="new">Wrap long call chain</target>
<note />
</trans-unit>
<trans-unit id="Wrap_long_parameter_list"> <trans-unit id="Wrap_long_parameter_list">
<source>Wrap long parameter list</source> <source>Wrap long parameter list</source>
<target state="translated">將長參數清單換行</target> <target state="translated">將長參數清單換行</target>
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.CSharp.CodeGeneration; using Microsoft.CodeAnalysis.CSharp.CodeGeneration;
using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.LanguageServices;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.LanguageServices;
...@@ -38,6 +39,8 @@ public SyntaxTrivia ElasticMarker ...@@ -38,6 +39,8 @@ public SyntaxTrivia ElasticMarker
public SyntaxTrivia ElasticCarriageReturnLineFeed public SyntaxTrivia ElasticCarriageReturnLineFeed
=> SyntaxFactory.ElasticCarriageReturnLineFeed; => SyntaxFactory.ElasticCarriageReturnLineFeed;
public ISyntaxKindsService SyntaxKinds { get; } = CSharpSyntaxKindsService.Instance;
protected override IDocumentationCommentService DocumentationCommentService protected override IDocumentationCommentService DocumentationCommentService
=> CSharpDocumentationCommentService.Instance; => CSharpDocumentationCommentService.Instance;
...@@ -618,13 +621,20 @@ public bool IsConditionalAccessExpression(SyntaxNode node) ...@@ -618,13 +621,20 @@ public bool IsConditionalAccessExpression(SyntaxNode node)
=> node is ConditionalAccessExpressionSyntax; => node is ConditionalAccessExpressionSyntax;
public void GetPartsOfConditionalAccessExpression( public void GetPartsOfConditionalAccessExpression(
SyntaxNode node, out SyntaxNode expression, out SyntaxNode whenNotNull) SyntaxNode node, out SyntaxNode expression, out SyntaxToken operatorToken, out SyntaxNode whenNotNull)
{ {
var conditionalAccess = (ConditionalAccessExpressionSyntax)node; var conditionalAccess = (ConditionalAccessExpressionSyntax)node;
expression = conditionalAccess.Expression; expression = conditionalAccess.Expression;
operatorToken = conditionalAccess.OperatorToken;
whenNotNull = conditionalAccess.WhenNotNull; whenNotNull = conditionalAccess.WhenNotNull;
} }
public bool IsPostfixUnaryExpression(SyntaxNode node)
=> node is PostfixUnaryExpressionSyntax;
public bool IsMemberBindingExpression(SyntaxNode node)
=> node is MemberBindingExpressionSyntax;
public bool IsPointerMemberAccessExpression(SyntaxNode node) public bool IsPointerMemberAccessExpression(SyntaxNode node)
=> (node as MemberAccessExpressionSyntax)?.Kind() == SyntaxKind.PointerMemberAccessExpression; => (node as MemberAccessExpressionSyntax)?.Kind() == SyntaxKind.PointerMemberAccessExpression;
...@@ -1426,6 +1436,13 @@ public bool IsNumericLiteral(SyntaxToken token) ...@@ -1426,6 +1436,13 @@ public bool IsNumericLiteral(SyntaxToken token)
public bool IsCharacterLiteral(SyntaxToken token) public bool IsCharacterLiteral(SyntaxToken token)
=> token.Kind() == SyntaxKind.CharacterLiteralToken; => token.Kind() == SyntaxKind.CharacterLiteralToken;
public void GetPartsOfInvocationExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxNode argumentList)
{
var invocation = (InvocationExpressionSyntax)node;
expression = invocation.Expression;
argumentList = invocation.ArgumentList;
}
public SeparatedSyntaxList<SyntaxNode> GetArgumentsOfInvocationExpression(SyntaxNode invocationExpression) public SeparatedSyntaxList<SyntaxNode> GetArgumentsOfInvocationExpression(SyntaxNode invocationExpression)
=> GetArgumentsOfArgumentList((invocationExpression as InvocationExpressionSyntax)?.ArgumentList); => GetArgumentsOfArgumentList((invocationExpression as InvocationExpressionSyntax)?.ArgumentList);
...@@ -1564,13 +1581,11 @@ public bool IsSimpleAssignmentStatement(SyntaxNode statement) ...@@ -1564,13 +1581,11 @@ public bool IsSimpleAssignmentStatement(SyntaxNode statement)
public SyntaxNode GetNameOfMemberAccessExpression(SyntaxNode memberAccessExpression) public SyntaxNode GetNameOfMemberAccessExpression(SyntaxNode memberAccessExpression)
=> ((MemberAccessExpressionSyntax)memberAccessExpression).Name; => ((MemberAccessExpressionSyntax)memberAccessExpression).Name;
public SyntaxToken GetOperatorTokenOfMemberAccessExpression(SyntaxNode memberAccessExpression) public void GetPartsOfMemberAccessExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxToken operatorToken, out SyntaxNode name)
=> ((MemberAccessExpressionSyntax)memberAccessExpression).OperatorToken;
public void GetPartsOfMemberAccessExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxNode name)
{ {
var memberAccess = (MemberAccessExpressionSyntax)node; var memberAccess = (MemberAccessExpressionSyntax)node;
expression = memberAccess.Expression; expression = memberAccess.Expression;
operatorToken = memberAccess.OperatorToken;
name = memberAccess.Name; name = memberAccess.Name;
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // 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.Composition; using System.Composition;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.LanguageServices;
namespace Microsoft.CodeAnalysis.CSharp.LanguageServices namespace Microsoft.CodeAnalysis.CSharp.LanguageServices
{ {
[ExportLanguageService(typeof(ISyntaxKindsService), LanguageNames.CSharp), Shared] internal sealed class CSharpSyntaxKindsService : AbstractSyntaxKindsService
internal sealed class CSharpSyntaxKindsService : ISyntaxKindsService
{ {
[ImportingConstructor] public static readonly CSharpSyntaxKindsService Instance = new CSharpSyntaxKindsService();
public CSharpSyntaxKindsService()
private CSharpSyntaxKindsService()
{ {
} }
public int IfKeyword => (int)SyntaxKind.IfKeyword; public override int DotToken => (int)SyntaxKind.DotToken;
public int LogicalAndExpression => (int)SyntaxKind.LogicalAndExpression; public override int QuestionToken => (int)SyntaxKind.QuestionToken;
public int LogicalOrExpression => (int)SyntaxKind.LogicalOrExpression;
public override int IfKeyword => (int)SyntaxKind.IfKeyword;
public override int LogicalAndExpression => (int)SyntaxKind.LogicalAndExpression;
public override int LogicalOrExpression => (int)SyntaxKind.LogicalOrExpression;
} }
} }
// 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.Composition;
using Microsoft.CodeAnalysis.CSharp.LanguageServices;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServices;
namespace Microsoft.CodeAnalysis.CSharp
{
[ExportLanguageServiceFactory(typeof(ISyntaxKindsService), LanguageNames.CSharp), Shared]
internal class CSharpSyntaxKindsServiceFactory : ILanguageServiceFactory
{
public ILanguageService CreateLanguageService(HostLanguageServices languageServices)
=> CSharpSyntaxKindsService.Instance;
}
}
...@@ -17,6 +17,8 @@ internal interface ISyntaxFactsService : ILanguageService ...@@ -17,6 +17,8 @@ internal interface ISyntaxFactsService : ILanguageService
SyntaxTrivia ElasticMarker { get; } SyntaxTrivia ElasticMarker { get; }
SyntaxTrivia ElasticCarriageReturnLineFeed { get; } SyntaxTrivia ElasticCarriageReturnLineFeed { get; }
ISyntaxKindsService SyntaxKinds { get; }
bool SupportsIndexingInitializer(ParseOptions options); bool SupportsIndexingInitializer(ParseOptions options);
bool SupportsThrowExpression(ParseOptions options); bool SupportsThrowExpression(ParseOptions options);
...@@ -129,7 +131,7 @@ internal interface ISyntaxFactsService : ILanguageService ...@@ -129,7 +131,7 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsInvocationExpression(SyntaxNode node); bool IsInvocationExpression(SyntaxNode node);
bool IsExpressionOfInvocationExpression(SyntaxNode node); bool IsExpressionOfInvocationExpression(SyntaxNode node);
SyntaxNode GetExpressionOfInvocationExpression(SyntaxNode node); void GetPartsOfInvocationExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxNode argumentList);
SyntaxNode GetExpressionOfExpressionStatement(SyntaxNode node); SyntaxNode GetExpressionOfExpressionStatement(SyntaxNode node);
...@@ -187,8 +189,7 @@ internal interface ISyntaxFactsService : ILanguageService ...@@ -187,8 +189,7 @@ internal interface ISyntaxFactsService : ILanguageService
/// may return the expression in the surrounding With-statement. /// may return the expression in the surrounding With-statement.
/// </summary> /// </summary>
SyntaxNode GetExpressionOfMemberAccessExpression(SyntaxNode node, bool allowImplicitTarget = false); SyntaxNode GetExpressionOfMemberAccessExpression(SyntaxNode node, bool allowImplicitTarget = false);
SyntaxToken GetOperatorTokenOfMemberAccessExpression(SyntaxNode node); void GetPartsOfMemberAccessExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxToken operatorToken, out SyntaxNode name);
void GetPartsOfMemberAccessExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxNode name);
SyntaxNode GetTargetOfMemberBinding(SyntaxNode node); SyntaxNode GetTargetOfMemberBinding(SyntaxNode node);
...@@ -213,7 +214,10 @@ internal interface ISyntaxFactsService : ILanguageService ...@@ -213,7 +214,10 @@ internal interface ISyntaxFactsService : ILanguageService
SyntaxNode GetNameOfAttribute(SyntaxNode node); SyntaxNode GetNameOfAttribute(SyntaxNode node);
bool IsConditionalAccessExpression(SyntaxNode node); bool IsConditionalAccessExpression(SyntaxNode node);
void GetPartsOfConditionalAccessExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxNode whenNotNull); void GetPartsOfConditionalAccessExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxToken operatorToken, out SyntaxNode whenNotNull);
bool IsMemberBindingExpression(SyntaxNode node);
bool IsPostfixUnaryExpression(SyntaxNode node);
bool IsParenthesizedExpression(SyntaxNode node); bool IsParenthesizedExpression(SyntaxNode node);
SyntaxNode GetExpressionOfParenthesizedExpression(SyntaxNode node); SyntaxNode GetExpressionOfParenthesizedExpression(SyntaxNode node);
......
...@@ -66,6 +66,13 @@ public static bool IsRegularOrDocumentationComment(this ISyntaxFactsService synt ...@@ -66,6 +66,13 @@ public static bool IsRegularOrDocumentationComment(this ISyntaxFactsService synt
syntaxFacts.GetPartsOfAssignmentStatement(statement, out left, out _, out right); syntaxFacts.GetPartsOfAssignmentStatement(statement, out left, out _, out right);
} }
public static SyntaxNode GetExpressionOfInvocationExpression(
this ISyntaxFactsService syntaxFacts, SyntaxNode node)
{
syntaxFacts.GetPartsOfInvocationExpression(node, out var expression, out _);
return expression;
}
public static SyntaxNode Unparenthesize( public static SyntaxNode Unparenthesize(
this ISyntaxFactsService syntaxFacts, SyntaxNode node) this ISyntaxFactsService syntaxFacts, SyntaxNode node)
{ {
...@@ -162,5 +169,17 @@ public static SyntaxNode GetExpressionOfConditionalAccessExpression(this ISyntax ...@@ -162,5 +169,17 @@ public static SyntaxNode GetExpressionOfConditionalAccessExpression(this ISyntax
syntaxFacts.GetPartsOfConditionalAccessExpression(node, out var expression, out _); syntaxFacts.GetPartsOfConditionalAccessExpression(node, out var expression, out _);
return expression; return expression;
} }
public static SyntaxToken GetOperatorTokenOfMemberAccessExpression(this ISyntaxFactsService syntaxFacts, SyntaxNode node)
{
syntaxFacts.GetPartsOfMemberAccessExpression(node, out _, out var operatorToken, out _);
return operatorToken;
}
public static void GetPartsOfMemberAccessExpression(this ISyntaxFactsService syntaxFacts, SyntaxNode node, out SyntaxNode expression, out SyntaxNode name)
=> syntaxFacts.GetPartsOfMemberAccessExpression(node, out expression, out _, out name);
public static void GetPartsOfConditionalAccessExpression(this ISyntaxFactsService syntaxFacts, SyntaxNode node, out SyntaxNode expression, out SyntaxNode whenNotNull)
=> syntaxFacts.GetPartsOfConditionalAccessExpression(node, out expression, out _, out whenNotNull);
} }
} }
...@@ -4,8 +4,15 @@ ...@@ -4,8 +4,15 @@
namespace Microsoft.CodeAnalysis.LanguageServices namespace Microsoft.CodeAnalysis.LanguageServices
{ {
/// <summary>
/// Provides a uniform view of SyntaxKinds over C# and VB for constructs they have
/// in common.
/// </summary>
internal interface ISyntaxKindsService : ILanguageService internal interface ISyntaxKindsService : ILanguageService
{ {
int DotToken { get; }
int QuestionToken { get; }
int IfKeyword { get; } int IfKeyword { get; }
/// <summary> /// <summary>
...@@ -18,4 +25,15 @@ internal interface ISyntaxKindsService : ILanguageService ...@@ -18,4 +25,15 @@ internal interface ISyntaxKindsService : ILanguageService
/// </summary> /// </summary>
int LogicalOrExpression { get; } int LogicalOrExpression { get; }
} }
internal abstract class AbstractSyntaxKindsService : ISyntaxKindsService
{
public abstract int DotToken { get; }
public abstract int QuestionToken { get; }
public abstract int IfKeyword { get; }
public abstract int LogicalAndExpression { get; }
public abstract int LogicalOrExpression { get; }
}
} }
...@@ -5,30 +5,16 @@ Imports System.Composition ...@@ -5,30 +5,16 @@ Imports System.Composition
Imports System.Text Imports System.Text
Imports System.Threading Imports System.Threading
Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.LanguageServices Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration Imports Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery
Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts
Namespace Microsoft.CodeAnalysis.VisualBasic Namespace Microsoft.CodeAnalysis.VisualBasic
<ExportLanguageServiceFactory(GetType(ISyntaxFactsService), LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicSyntaxFactsServiceFactory
Implements ILanguageServiceFactory
<ImportingConstructor>
Public Sub New()
End Sub
Public Function CreateLanguageService(languageServices As HostLanguageServices) As ILanguageService Implements ILanguageServiceFactory.CreateLanguageService
Return VisualBasicSyntaxFactsService.Instance
End Function
End Class
Friend Class VisualBasicSyntaxFactsService Friend Class VisualBasicSyntaxFactsService
Inherits AbstractSyntaxFactsService Inherits AbstractSyntaxFactsService
Implements ISyntaxFactsService Implements ISyntaxFactsService
...@@ -62,6 +48,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -62,6 +48,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get End Get
End Property End Property
Public ReadOnly Property SyntaxKinds As ISyntaxKindsService = VisualBasicSyntaxKindsService.Instance Implements ISyntaxFactsService.SyntaxKinds
Protected Overrides ReadOnly Property DocumentationCommentService As IDocumentationCommentService Protected Overrides ReadOnly Property DocumentationCommentService As IDocumentationCommentService
Get Get
Return VisualBasicDocumentationCommentService.Instance Return VisualBasicDocumentationCommentService.Instance
...@@ -194,9 +182,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -194,9 +182,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return TypeOf node Is ConditionalAccessExpressionSyntax Return TypeOf node Is ConditionalAccessExpressionSyntax
End Function End Function
Public Sub GetPartsOfConditionalAccessExpression(node As SyntaxNode, ByRef expression As SyntaxNode, ByRef whenNotNull As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfConditionalAccessExpression Public Sub GetPartsOfConditionalAccessExpression(node As SyntaxNode, ByRef expression As SyntaxNode, ByRef operatorToken As SyntaxToken, ByRef whenNotNull As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfConditionalAccessExpression
Dim conditionalAccess = DirectCast(node, ConditionalAccessExpressionSyntax) Dim conditionalAccess = DirectCast(node, ConditionalAccessExpressionSyntax)
expression = conditionalAccess.Expression expression = conditionalAccess.Expression
operatorToken = conditionalAccess.QuestionMarkToken
whenNotNull = conditionalAccess.WhenNotNull whenNotNull = conditionalAccess.WhenNotNull
End Sub End Sub
...@@ -1542,10 +1531,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1542,10 +1531,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return DirectCast(memberAccessExpression, MemberAccessExpressionSyntax).Name Return DirectCast(memberAccessExpression, MemberAccessExpressionSyntax).Name
End Function End Function
Public Function GetOperatorTokenOfMemberAccessExpression(memberAccessExpression As SyntaxNode) As SyntaxToken Implements ISyntaxFactsService.GetOperatorTokenOfMemberAccessExpression
Return DirectCast(memberAccessExpression, MemberAccessExpressionSyntax).OperatorToken
End Function
Public Function GetIdentifierOfSimpleName(node As SyntaxNode) As SyntaxToken Implements ISyntaxFactsService.GetIdentifierOfSimpleName Public Function GetIdentifierOfSimpleName(node As SyntaxNode) As SyntaxToken Implements ISyntaxFactsService.GetIdentifierOfSimpleName
Return DirectCast(node, SimpleNameSyntax).Identifier Return DirectCast(node, SimpleNameSyntax).Identifier
End Function End Function
...@@ -1596,10 +1581,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1596,10 +1581,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return node IsNot Nothing AndAlso TryCast(node.Parent, MemberAccessExpressionSyntax)?.Expression Is node Return node IsNot Nothing AndAlso TryCast(node.Parent, MemberAccessExpressionSyntax)?.Expression Is node
End Function End Function
Public Function GetExpressionOfInvocationExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfInvocationExpression
Return DirectCast(node, InvocationExpressionSyntax).Expression
End Function
Public Function GetExpressionOfAwaitExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfAwaitExpression Public Function GetExpressionOfAwaitExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfAwaitExpression
Return DirectCast(node, AwaitExpressionSyntax).Expression Return DirectCast(node, AwaitExpressionSyntax).Expression
End Function End Function
...@@ -1667,7 +1648,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1667,7 +1648,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return node.Kind() = SyntaxKind.OrElseExpression Return node.Kind() = SyntaxKind.OrElseExpression
End Function End Function
Public Function IsTupleExpression(node As syntaxnode) As Boolean Implements ISyntaxFactsService.IsTupleExpression Public Function IsTupleExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsTupleExpression
Return node.Kind() = SyntaxKind.TupleExpression Return node.Kind() = SyntaxKind.TupleExpression
End Function End Function
...@@ -1692,9 +1673,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1692,9 +1673,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return DirectCast(node, UnaryExpressionSyntax).OperatorToken Return DirectCast(node, UnaryExpressionSyntax).OperatorToken
End Function End Function
Public Sub GetPartsOfMemberAccessExpression(node As SyntaxNode, ByRef expression As SyntaxNode, ByRef name As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfMemberAccessExpression Public Sub GetPartsOfMemberAccessExpression(node As SyntaxNode, ByRef expression As SyntaxNode, ByRef operatorToken As SyntaxToken, ByRef name As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfMemberAccessExpression
Dim memberAccess = DirectCast(node, MemberAccessExpressionSyntax) Dim memberAccess = DirectCast(node, MemberAccessExpressionSyntax)
expression = memberAccess.Expression expression = memberAccess.Expression
operatorToken = memberAccess.OperatorToken
name = memberAccess.Name name = memberAccess.Name
End Sub End Sub
...@@ -1957,6 +1939,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1957,6 +1939,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return MyBase.SpansPreprocessorDirective(tokens) Return MyBase.SpansPreprocessorDirective(tokens)
End Function End Function
Public Sub GetPartsOfInvocationExpression(node As SyntaxNode, ByRef expression As SyntaxNode, ByRef argumentList As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfInvocationExpression
Dim invocation = DirectCast(node, InvocationExpressionSyntax)
expression = invocation.Expression
argumentList = invocation.ArgumentList
End Sub
Public Function IsPostfixUnaryExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsPostfixUnaryExpression
' Does not exist in VB.
Return False
End Function
Public Function IsMemberBindingExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsMemberBindingExpression
' Does not exist in VB.
Return False
End Function
Public Function GetContainingPropertyDeclaration(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetContainingPropertyDeclaration Public Function GetContainingPropertyDeclaration(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetContainingPropertyDeclaration
Return node.GetAncestor(Of PropertyStatementSyntax) Return node.GetAncestor(Of PropertyStatementSyntax)
End Function End Function
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.LanguageServices
Namespace Microsoft.CodeAnalysis.VisualBasic
<ExportLanguageServiceFactory(GetType(ISyntaxFactsService), LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicSyntaxFactsServiceFactory
Implements ILanguageServiceFactory
<ImportingConstructor>
Public Sub New()
End Sub
Public Function CreateLanguageService(languageServices As HostLanguageServices) As ILanguageService Implements ILanguageServiceFactory.CreateLanguageService
Return VisualBasicSyntaxFactsService.Instance
End Function
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition Imports System.Composition
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.LanguageServices Imports Microsoft.CodeAnalysis.LanguageServices
Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageServices Namespace Microsoft.CodeAnalysis.VisualBasic.LanguageServices
<ExportLanguageService(GetType(ISyntaxKindsService), LanguageNames.VisualBasic), [Shared]>
Friend NotInheritable Class VisualBasicSyntaxKindsService Friend NotInheritable Class VisualBasicSyntaxKindsService
Implements ISyntaxKindsService Inherits AbstractSyntaxKindsService
<ImportingConstructor> Public Shared ReadOnly Instance As New VisualBasicSyntaxKindsService()
Public Sub New()
Private Sub New()
End Sub End Sub
Public ReadOnly Property IfKeyword As Integer = SyntaxKind.IfKeyword Implements ISyntaxKindsService.IfKeyword Public Overrides ReadOnly Property DotToken As Integer = SyntaxKind.DotToken
Public ReadOnly Property LogicalAndExpression As Integer = SyntaxKind.AndAlsoExpression Implements ISyntaxKindsService.LogicalAndExpression Public Overrides ReadOnly Property QuestionToken As Integer = SyntaxKind.QuestionToken
Public ReadOnly Property LogicalOrExpression As Integer = SyntaxKind.OrElseExpression Implements ISyntaxKindsService.LogicalOrExpression
Public Overrides ReadOnly Property IfKeyword As Integer = SyntaxKind.IfKeyword
Public Overrides ReadOnly Property LogicalAndExpression As Integer = SyntaxKind.AndAlsoExpression
Public Overrides ReadOnly Property LogicalOrExpression As Integer = SyntaxKind.OrElseExpression
End Class End Class
End Namespace End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.VisualBasic.LanguageServices
Namespace Microsoft.CodeAnalysis.VisualBasic
<ExportLanguageServiceFactory(GetType(ISyntaxKindsService), LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicSyntaxKindsServiceFactory
Implements ILanguageServiceFactory
Public Function CreateLanguageService(languageServices As HostLanguageServices) As ILanguageService Implements ILanguageServiceFactory.CreateLanguageService
Return VisualBasicSyntaxKindsService.Instance
End Function
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册