提交 03d9be86 编写于 作者: C Cyrus Najmabadi

New formalization.

上级 1c0dfda9
......@@ -15,7 +15,7 @@ internal class CSharpCallExpressionWrapper : AbstractCallExpressionWrapper<
BaseArgumentListSyntax>
{
public CSharpCallExpressionWrapper()
: base(CSharpSyntaxFactsService.Instance)
: base(CSharpSyntaxFactsService.Instance, (int)SyntaxKind.DotToken, (int)SyntaxKind.QuestionToken)
{
}
......
......@@ -46,8 +46,8 @@ public async Task TestWithEnoughChunks()
}",
@"class C {
void Bar() {
the.quick.brown()
.fox.jumped();
the.quick.brown().fox
.jumped();
}
}");
}
......@@ -63,8 +63,8 @@ public async Task TestElementAccess()
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3]
.fox.jumped[1][2][3];
the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}");
}
......@@ -75,8 +75,8 @@ public async Task TestUnwrap()
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
[||]the.quick.brown[1, 2, 3]
.fox.jumped[1][2][3];
[||]the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}",
@"class C {
......@@ -99,8 +99,8 @@ public async Task TestWrapAndUnwrap()
}",
@"class C {
void Bar() {
the.quick.brown[1, 2, 3]
.fox.jumped[1][2][3];
the.quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}",
@"class C {
......@@ -121,8 +121,8 @@ public async Task TestChunkMustHaveDottedSection()
}",
@"class C {
void Bar() {
the().quick.brown[1, 2, 3]
.fox.jumped[1][2][3];
the().quick.brown[1, 2, 3].fox
.jumped[1][2][3];
}
}");
}
......@@ -138,8 +138,8 @@ public async Task TrailingNonCallIsNotWrapped()
}",
@"class C {
void Bar() {
the.quick.brown()
.fox.jumped().over;
the.quick.brown().fox
.jumped().over;
}
}");
}
......@@ -156,19 +156,19 @@ public async Task TrailingLongWrapping1()
GetIndentionColumn(35),
@"class C {
void Bar() {
the.quick.brown()
.fox.jumped()
.over.the()
.lazy()
.dog();
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown()
.fox.jumped()
.over.the().lazy()
.dog();
the.quick.brown().fox
.jumped().over
.the().lazy()
.dog();
}
}");
}
......@@ -185,17 +185,18 @@ public async Task TrailingLongWrapping2()
GetIndentionColumn(40),
@"class C {
void Bar() {
the.quick.brown()
.fox.jumped()
.over.the()
.lazy()
.dog();
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox.jumped()
.over.the().lazy().dog();
the.quick.brown().fox
.jumped().over.the()
.lazy().dog();
}
}");
}
......@@ -212,17 +213,86 @@ public async Task TrailingLongWrapping3()
GetIndentionColumn(60),
@"class C {
void Bar() {
the.quick.brown()
.fox.jumped()
.over.the()
.lazy()
.dog();
the.quick.brown().fox
.jumped().over
.the()
.lazy()
.dog();
}
}",
@"class C {
void Bar() {
the.quick.brown().fox.jumped().over.the().lazy()
.dog();
.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();
}
}");
}
[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();
}
}");
}
[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();
}
}");
}
[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();
}
}");
}
......
// 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;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Shared.Extensions;
//using System;
//using System.Collections.Immutable;
//using System.Diagnostics;
//using System.Linq;
//using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis.Editor.Wrapping.CallExpression
{
internal abstract partial class AbstractCallExpressionWrapper<
TExpressionSyntax,
TNameSyntax,
TMemberAccessExpressionSyntax,
TInvocationExpressionSyntax,
TElementAccessExpressionSyntax,
TBaseArgumentListSyntax>
{
/// <summary>
/// A single `.Name` piece of a call-chunk like `.P1.P2.P3(...)`
/// </summary>
private readonly struct MemberChunk
{
public readonly SyntaxToken DotToken;
public readonly TNameSyntax Name;
//namespace Microsoft.CodeAnalysis.Editor.Wrapping.CallExpression
//{
// internal abstract partial class AbstractCallExpressionWrapper<
// TExpressionSyntax,
// TNameSyntax,
// TMemberAccessExpressionSyntax,
// TInvocationExpressionSyntax,
// TElementAccessExpressionSyntax,
// TBaseArgumentListSyntax>
// {
// /// <summary>
// /// A single `.Name` piece of a call-chunk like `.P1.P2.P3(...)`
// /// </summary>
// private readonly struct MemberChunk
// {
// public readonly SyntaxToken DotToken;
// public readonly TNameSyntax Name;
public MemberChunk(SyntaxToken dotToken, TNameSyntax name)
{
DotToken = dotToken;
Name = name;
}
// public MemberChunk(SyntaxToken dotToken, TNameSyntax name)
// {
// DotToken = dotToken;
// Name = name;
// }
/// <summary>
/// The length this name chunk will be once all unnecessary whitespace has been
/// removed from it.
/// </summary>
public int NormalizedLength()
=> DotToken.Width() + Name.Width();
}
// /// <summary>
// /// The length this name chunk will be once all unnecessary whitespace has been
// /// removed from it.
// /// </summary>
// public int NormalizedLength()
// => DotToken.Width() + Name.Width();
// }
/// <summary>
/// A full chunk of complex dotted call expression that we want to be
/// able to wrap as a single unit. It will have the form: `.P1.P2.P3(...)(...)`
/// </summary>
private readonly struct CallChunk
{
public readonly ImmutableArray<MemberChunk> MemberChunks;
public readonly ImmutableArray<TBaseArgumentListSyntax> ArgumentLists;
// /// <summary>
// /// A full chunk of complex dotted call expression that we want to be
// /// able to wrap as a single unit. It will have the form: `.P1.P2.P3(...)(...)`
// /// </summary>
// private readonly struct CallChunk
// {
// public readonly ImmutableArray<MemberChunk> MemberChunks;
// public readonly ImmutableArray<TBaseArgumentListSyntax> ArgumentLists;
public CallChunk(
ImmutableArray<MemberChunk> memberChunks,
ImmutableArray<TBaseArgumentListSyntax> argumentLists)
{
Debug.Assert(memberChunks.Length > 0);
Debug.Assert(argumentLists.Length > 0);
MemberChunks = memberChunks;
ArgumentLists = argumentLists;
}
// public CallChunk(
// ImmutableArray<MemberChunk> memberChunks,
// ImmutableArray<TBaseArgumentListSyntax> argumentLists)
// {
// Debug.Assert(memberChunks.Length > 0);
// Debug.Assert(argumentLists.Length > 0);
// MemberChunks = memberChunks;
// ArgumentLists = argumentLists;
// }
/// <summary>
/// The length this call chunk will be once all unnecessary whitespace has been
/// removed from it.
/// </summary>
public int NormalizedLength()
=> MemberChunks.Sum(c => c.NormalizedLength()) + ArgumentLists.Sum(a => a.Width());
}
}
}
// /// <summary>
// /// The length this call chunk will be once all unnecessary whitespace has been
// /// removed from it.
// /// </summary>
// public int NormalizedLength()
// => MemberChunks.Sum(c => c.NormalizedLength()) + ArgumentLists.Sum(a => a.Width());
// }
// }
//}
// 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;
......@@ -10,6 +12,7 @@
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Editor.Wrapping.CallExpression
{
......@@ -42,7 +45,7 @@ private class CallExpressionCodeActionComputer :
/// 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<CallChunk> _callChunks;
private readonly ImmutableArray<ImmutableArray<SyntaxNodeOrToken>> _chunks;
/// <summary>
/// Trivia to place before a call-chunk when it is wrapped.
......@@ -61,18 +64,18 @@ private class CallExpressionCodeActionComputer :
Document document,
SourceText originalSourceText,
DocumentOptionSet options,
ImmutableArray<CallChunk> callChunks,
ImmutableArray<ImmutableArray<SyntaxNodeOrToken>> chunks,
CancellationToken cancellationToken)
: base(service, document, originalSourceText, options, cancellationToken)
{
_callChunks = callChunks;
_chunks = chunks;
var generator = SyntaxGenerator.GetGenerator(document);
// Both [0] indices are safe here. We can only get here if we had more than
// two call-chunks to wrap. And each call-chunk is required to have at least
// one member-name-chunk.
var indentationString = OriginalSourceText.GetOffset(callChunks[0].MemberChunks[0].DotToken.SpanStart)
var indentationString = OriginalSourceText.GetOffset(chunks[0][0].SpanStart)
.CreateIndentationString(UseTabs, TabSize);
_indentationTrivia = new SyntaxTriviaList(generator.Whitespace(indentationString));
......@@ -101,22 +104,16 @@ private ImmutableArray<Edit> GetWrapEdits(int wrappingColumn)
{
var result = ArrayBuilder<Edit>.GetInstance();
// Deal with the first chunk (it has special behavior because we
// don't want to delete any trivia directly before it).
DeleteAllButLeadingSpacesInCallChunk(result, _callChunks[0]);
// First, normalize the first chunk.
var firstChunk = _chunks[0];
DeleteAllSpacesInChunk(result, firstChunk);
var position = _indentationTrivia.FullSpan.Length + NormalizedWidth(firstChunk);
// The position we're currently at. If adding the next chunk would
// make us go past our preferred wrapping column, then we will wrap
// that chunk.
var position = _indentationTrivia.FullSpan.Length + _callChunks[0].NormalizedLength();
// Now go through all subsequence call chunks and normalize them all.
// Also, wrap any we encounter if we go past the specified wrapping
// column
for (var i = 1; i < _callChunks.Length; i++)
for (var i = 1; i < _chunks.Length; i++)
{
var callChunk = _callChunks[i];
var wrapChunk = position + callChunk.NormalizedLength() >= wrappingColumn;
var chunk = _chunks[i];
var wrapChunk = position + NormalizedWidth(chunk) >= wrappingColumn;
if (wrapChunk)
{
// we're wrapping. So our position is reset to the indentation
......@@ -126,107 +123,166 @@ private ImmutableArray<Edit> GetWrapEdits(int wrappingColumn)
// First, add a newline at the end of the previous arglist, and then
// indent the very first member chunk appropriately.
result.Add(Edit.UpdateBetween(
_callChunks[i - 1].ArgumentLists.Last(), _newlineBeforeOperatorTrivia,
_indentationTrivia, callChunk.MemberChunks[0].DotToken));
// Now, delete all the remaining spaces in this call chunk.
DeleteAllButLeadingSpacesInCallChunk(result, callChunk);
}
else
{
// not wrapping. So just clean up this next call chunk by
// deleting all spaces.
DeleteAllSpacesInCallChunk(result, callChunk);
_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 += callChunk.NormalizedLength();
position += NormalizedWidth(chunk);
}
//// Deal with the first chunk (it has special behavior because we
//// don't want to delete any trivia directly before it).
//DeleteAllButLeadingSpacesInCallChunk(result, _callChunks[0]);
//// The position we're currently at. If adding the next chunk would
//// make us go past our preferred wrapping column, then we will wrap
//// that chunk.
//var position = _indentationTrivia.FullSpan.Length + _callChunks[0].NormalizedLength();
//// Now go through all subsequence call chunks and normalize them all.
//// Also, wrap any we encounter if we go past the specified wrapping
//// column
//for (var i = 1; i < _callChunks.Length; i++)
//{
// var callChunk = _callChunks[i];
// var wrapChunk = position + callChunk.NormalizedLength() >= 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(
// _callChunks[i - 1].ArgumentLists.Last(), _newlineBeforeOperatorTrivia,
// _indentationTrivia, callChunk.MemberChunks[0].DotToken));
// // Now, delete all the remaining spaces in this call chunk.
// DeleteAllButLeadingSpacesInCallChunk(result, callChunk);
// }
// else
// {
// // not wrapping. So just clean up this next call chunk by
// // deleting all spaces.
// DeleteAllSpacesInCallChunk(result, callChunk);
// }
// // Update position based on this chunk we just fixed up.
// position += callChunk.NormalizedLength();
//}
return result.ToImmutableAndFree();
}
private ImmutableArray<Edit> GetUnwrapEdits()
private int NormalizedWidth(ImmutableArray<SyntaxNodeOrToken> chunk)
{
var result = ArrayBuilder<Edit>.GetInstance();
// Deal with the first chunk (it has special behavior because we
// don't want to delete any trivia directly before it).
DeleteAllButLeadingSpacesInCallChunk(result, _callChunks[0]);
// Now, handle all successive call chunks.
for (var i = 1; i < _callChunks.Length; i++)
var width = 0;
foreach (var syntax in chunk)
{
// In successive call chunks we want to delete all the spacing
// in the member chunks unilaterally.
DeleteAllSpacesInCallChunk(result, _callChunks[i]);
width += syntax.IsNode ? syntax.AsNode().Width() : syntax.AsToken().Width();
}
return result.ToImmutableAndFree();
return width;
}
private static void DeleteAllSpacesInCallChunk(ArrayBuilder<Edit> result, CallChunk callChunk)
private ImmutableArray<Edit> GetUnwrapEdits()
{
foreach (var memberChunk in callChunk.MemberChunks)
{
DeleteSpacesInMemberChunk(result, memberChunk);
}
var result = ArrayBuilder<Edit>.GetInstance();
// and then any whitespace before the first arg list and between the rest.
DeleteSpacesInArgumentLists(result, callChunk);
}
var flattened = _chunks.SelectMany(c => c).ToImmutableArray();
/// <summary>
/// Removes all whitespace in the spaces between the elements of this chunk.
/// However no edits will be made before the the first dot in the first member
/// chunk of this call chunk. This is useful for the very first call chunk or
/// any callchunk we're explicitly wrapping.
/// </summary>
private void DeleteAllButLeadingSpacesInCallChunk(ArrayBuilder<Edit> result, CallChunk callChunk)
{
// For the very first member chunk we have, don't make any edits prior
// to it. This is the chunk that contains the dot that we are aligning
// all wrapping to. It should never be touched.
//
// After that first member chunk, remove all whitespace between the
// other member chunks and between the arg list.
// For the very first name chunk in .A.B.C (i.e. `.A` just remove the spaces
// between the dot and the name.
var firstMemberChunk = callChunk.MemberChunks[0];
result.Add(Edit.DeleteBetween(firstMemberChunk.DotToken, firstMemberChunk.Name));
// For all subsequence name chunks in .A.B.C (i.e. `.B.C`) remove any spaces between
// the chunk and the last chunk, and between the dot and the name.
for (var i = 1; i < callChunk.MemberChunks.Length; i++)
{
var memberChunk = callChunk.MemberChunks[i];
DeleteSpacesInMemberChunk(result, memberChunk);
}
DeleteAllSpacesInChunk(result, flattened);
// and then any whitespace before the first arg list and between the rest.
DeleteSpacesInArgumentLists(result, callChunk);
}
//// Deal with the first chunk (it has special behavior because we
//// don't want to delete any trivia directly before it).
//DeleteAllButLeadingSpacesInCallChunk(result, _callChunks[0]);
private static void DeleteSpacesInMemberChunk(ArrayBuilder<Edit> result, MemberChunk memberChunk)
{
result.Add(Edit.DeleteBetween(memberChunk.DotToken.GetPreviousToken(), memberChunk.DotToken));
result.Add(Edit.DeleteBetween(memberChunk.DotToken, memberChunk.Name));
//// Now, handle all successive call chunks.
//for (var i = 1; i < _callChunks.Length; i++)
//{
// // In successive call chunks we want to delete all the spacing
// // in the member chunks unilaterally.
// DeleteAllSpacesInCallChunk(result, _callChunks[i]);
//}
return result.ToImmutableAndFree();
}
private static void DeleteSpacesInArgumentLists(ArrayBuilder<Edit> result, CallChunk callChunk)
private static void DeleteAllSpacesInChunk(
ArrayBuilder<Edit> result, ImmutableArray<SyntaxNodeOrToken> chunk)
{
var argumentLists = callChunk.ArgumentLists;
// Delete the whitespace between the last member name chunk and the first arg list.
result.Add(Edit.DeleteBetween(callChunk.MemberChunks.Last().Name, argumentLists[0]));
// Now delete the whitespace between each arglist.
for (var i = 1; i < argumentLists.Length; i++)
for (int i = 1; i < chunk.Length; i++)
{
result.Add(Edit.DeleteBetween(argumentLists[i - 1], argumentLists[i]));
result.Add(Edit.DeleteBetween(chunk[i - 1], chunk[i]));
}
}
//private static void DeleteAllSpacesInCallChunk(ArrayBuilder<Edit> result, CallChunk callChunk)
//{
// foreach (var memberChunk in callChunk.MemberChunks)
// {
// DeleteSpacesInMemberChunk(result, memberChunk);
// }
// // and then any whitespace before the first arg list and between the rest.
// DeleteSpacesInArgumentLists(result, callChunk);
//}
///// <summary>
///// Removes all whitespace in the spaces between the elements of this chunk.
///// However no edits will be made before the the first dot in the first member
///// chunk of this call chunk. This is useful for the very first call chunk or
///// any callchunk we're explicitly wrapping.
///// </summary>
//private void DeleteAllButLeadingSpacesInCallChunk(ArrayBuilder<Edit> result, CallChunk callChunk)
//{
// // For the very first member chunk we have, don't make any edits prior
// // to it. This is the chunk that contains the dot that we are aligning
// // all wrapping to. It should never be touched.
// //
// // After that first member chunk, remove all whitespace between the
// // other member chunks and between the arg list.
// // For the very first name chunk in .A.B.C (i.e. `.A` just remove the spaces
// // between the dot and the name.
// var firstMemberChunk = callChunk.MemberChunks[0];
// result.Add(Edit.DeleteBetween(firstMemberChunk.DotToken, firstMemberChunk.Name));
// // For all subsequence name chunks in .A.B.C (i.e. `.B.C`) remove any spaces between
// // the chunk and the last chunk, and between the dot and the name.
// for (var i = 1; i < callChunk.MemberChunks.Length; i++)
// {
// var memberChunk = callChunk.MemberChunks[i];
// DeleteSpacesInMemberChunk(result, memberChunk);
// }
// // and then any whitespace before the first arg list and between the rest.
// DeleteSpacesInArgumentLists(result, callChunk);
//}
//private static void DeleteSpacesInMemberChunk(ArrayBuilder<Edit> result, MemberChunk memberChunk)
//{
// result.Add(Edit.DeleteBetween(memberChunk.DotToken.GetPreviousToken(), memberChunk.DotToken));
// result.Add(Edit.DeleteBetween(memberChunk.DotToken, memberChunk.Name));
//}
//private static void DeleteSpacesInArgumentLists(ArrayBuilder<Edit> result, CallChunk callChunk)
//{
// var argumentLists = callChunk.ArgumentLists;
// // Delete the whitespace between the last member name chunk and the first arg list.
// result.Add(Edit.DeleteBetween(callChunk.MemberChunks.Last().Name, argumentLists[0]));
// // Now delete the whitespace between each arglist.
// for (var i = 1; i < argumentLists.Length; i++)
// {
// result.Add(Edit.DeleteBetween(argumentLists[i - 1], argumentLists[i]));
// }
//}
}
}
}
......@@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping.CallExpression
ArgumentListSyntax)
Public Sub New()
MyBase.New(VisualBasicSyntaxFactsService.Instance)
MyBase.New(VisualBasicSyntaxFactsService.Instance, SyntaxKind.DotToken, SyntaxKind.QuestionToken)
End Sub
Public Overrides Function GetNewLineBeforeOperatorTrivia(newLine As SyntaxTriviaList) As SyntaxTriviaList
......
......@@ -41,8 +41,8 @@ end class")
end class",
"class C
sub Bar()
the.quick.brown() _
.fox.jumped()
the.quick.brown().fox _
.jumped()
end sub
end class")
End Function
......@@ -57,8 +57,8 @@ end class")
end class",
"class C
sub Bar()
the.quick.brown() _
.fox.jumped(,)
the.quick.brown().fox _
.jumped(,)
end sub
end class")
End Function
......@@ -68,8 +68,8 @@ end class")
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
[||]the.quick.brown(1, 2, 3) _
.fox.jumped(1)(2)(3)
[||]the.quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class",
"class C
......@@ -91,8 +91,8 @@ end class")
end class",
"class C
sub Bar()
the.quick.brown(1, 2, 3) _
.fox.jumped(1)(2)(3)
the.quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class",
"class C
......@@ -112,8 +112,8 @@ end class")
end class",
"class C
sub Bar()
the().quick.brown(1, 2, 3) _
.fox.jumped(1)(2)(3)
the().quick.brown(1, 2, 3).fox _
.jumped(1)(2)(3)
end sub
end class")
End Function
......@@ -128,8 +128,8 @@ end class")
end class",
"class C
sub Bar()
dim y = the.quick.brown() _
.fox.jumped().over
dim y = the.quick.brown().fox _
.jumped().over
end sub
end class")
End Function
......@@ -145,19 +145,19 @@ end class",
GetIndentionColumn(35),
"class C
sub Bar()
the.quick.brown() _
.fox.jumped() _
.over.the() _
.lazy() _
.dog()
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()
the.quick.brown().fox _
.jumped().over _
.the().lazy() _
.dog()
end sub
end class")
End Function
......@@ -173,17 +173,18 @@ end class",
GetIndentionColumn(40),
"class C
sub Bar()
the.quick.brown() _
.fox.jumped() _
.over.the() _
.lazy() _
.dog()
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()
the.quick.brown().fox _
.jumped().over.the() _
.lazy().dog()
end sub
end class")
End Function
......@@ -199,17 +200,17 @@ end class",
GetIndentionColumn(60),
"class C
sub Bar()
the.quick.brown() _
.fox.jumped() _
.over.the() _
.lazy() _
.dog()
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()
.dog()
end sub
end class")
End Function
......@@ -217,6 +218,26 @@ end class")
<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")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestAlignToThirdDotInWith() As Task
Await TestAllWrappingCasesAsync(
"class C
sub Bar()
with goo
......@@ -227,8 +248,8 @@ end class",
"class C
sub Bar()
with goo
.the.quick.brown() _
.fox.jumped(,)
.the.quick.brown().fox _
.jumped(,)
end with
end sub
end class")
......
......@@ -617,13 +617,34 @@ public bool IsConditionalAccessExpression(SyntaxNode node)
=> node is ConditionalAccessExpressionSyntax;
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;
expression = conditionalAccess.Expression;
operatorToken = conditionalAccess.OperatorToken;
whenNotNull = conditionalAccess.WhenNotNull;
}
public bool IsPostfixUnaryExpression(SyntaxNode node)
=> node is PostfixUnaryExpressionSyntax;
public void GetPartsOfPostfixUnaryExpression(SyntaxNode node, out SyntaxNode operand, out SyntaxToken operatorToken)
{
var expression = (PostfixUnaryExpressionSyntax)node;
operand = expression.Operand;
operatorToken = expression.OperatorToken;
}
public bool IsMemberBindingExpression(SyntaxNode node)
=> node is MemberBindingExpressionSyntax;
public void GetPartsOfMemberBindingExpression(SyntaxNode node, out SyntaxToken operatorToken, out SyntaxNode name)
{
var memberBinding = (MemberBindingExpressionSyntax)node;
operatorToken = memberBinding.OperatorToken;
name = memberBinding.Name;
}
public bool IsPointerMemberAccessExpression(SyntaxNode node)
=> (node as MemberAccessExpressionSyntax)?.Kind() == SyntaxKind.PointerMemberAccessExpression;
......
......@@ -210,7 +210,13 @@ internal interface ISyntaxFactsService : ILanguageService
SyntaxNode GetNameOfAttribute(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);
void GetPartsOfMemberBindingExpression(SyntaxNode node, out SyntaxToken operatorToken, out SyntaxNode name);
bool IsPostfixUnaryExpression(SyntaxNode node);
void GetPartsOfPostfixUnaryExpression(SyntaxNode node, out SyntaxNode operand, out SyntaxToken operatorToken);
bool IsParenthesizedExpression(SyntaxNode node);
SyntaxNode GetExpressionOfParenthesizedExpression(SyntaxNode node);
......
......@@ -173,8 +173,9 @@ public static SyntaxToken GetOperatorTokenOfMemberAccessExpression(this ISyntaxF
}
public static void GetPartsOfMemberAccessExpression(this ISyntaxFactsService syntaxFacts, SyntaxNode node, out SyntaxNode expression, out SyntaxNode name)
{
syntaxFacts.GetPartsOfMemberAccessExpression(node, out expression, out _, out 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);
}
}
......@@ -190,9 +190,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return TypeOf node Is ConditionalAccessExpressionSyntax
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)
expression = conditionalAccess.Expression
operatorToken = conditionalAccess.QuestionMarkToken
whenNotNull = conditionalAccess.WhenNotNull
End Sub
......@@ -1866,5 +1867,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
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 Sub GetPartsOfPostfixUnaryExpression(node As SyntaxNode, ByRef operand As SyntaxNode, ByRef operatorToken As SyntaxToken) Implements ISyntaxFactsService.GetPartsOfPostfixUnaryExpression
Throw ExceptionUtilities.UnexpectedValue(node.Kind())
End Sub
Public Function IsMemberBindingExpression(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsMemberBindingExpression
Return False
End Function
Public Sub GetPartsOfMemberBindingExpression(node As SyntaxNode, ByRef dotToken As SyntaxToken, ByRef name As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfMemberBindingExpression
Throw ExceptionUtilities.UnexpectedValue(node.Kind())
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册