提交 2f11fecb 编写于 作者: C Cyrus Najmabadi

Option and tests.

上级 e2faba7d
......@@ -30,7 +30,7 @@ protected sealed override ImmutableArray<CodeAction> MassageActions(ImmutableArr
protected Task TestAllWrappingCasesAsync(
string input,
Dictionary<OptionKey, object> options,
IDictionary<OptionKey, object> options,
params string[] outputs)
{
var parameters = new TestParameters(options: options);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Editor.CSharp.Wrapping;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
......@@ -13,6 +16,22 @@ public class BinaryWrappingTests : AbstractWrappingTests
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new CSharpWrappingCodeRefactoringProvider();
private IDictionary<OptionKey, object> EndOfLine => Option(
CodeStyleOptions.OperatorPlacementWhenWrapping,
OperatorPlacementWhenWrappingPreference.EndOfLine);
private IDictionary<OptionKey, object> BeginningOfLine => Option(
CodeStyleOptions.OperatorPlacementWhenWrapping,
OperatorPlacementWhenWrappingPreference.BeginningOfLine);
private Task TestEndOfLine(string markup, string expected)
=> TestInRegularAndScript1Async(markup, expected, parameters: new TestParameters(
options: EndOfLine));
private Task TestBeginningOfLine(string markup, string expected)
=> TestInRegularAndScript1Async(markup, expected, parameters: new TestParameters(
options: BeginningOfLine));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestMissingWithSyntaxError()
{
......@@ -89,7 +108,7 @@ public async Task TestMissingWithMultiLineExpr2()
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInIf()
{
await TestInRegularAndScript1Async(
await TestEndOfLine(
@"class C {
void Bar() {
if ([||]i && j) {
......@@ -108,7 +127,7 @@ public async Task TestInIf()
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInIf_IncludingOp()
{
await TestInRegularAndScript1Async(
await TestBeginningOfLine(
@"class C {
void Bar() {
if ([||]i && j) {
......@@ -121,13 +140,13 @@ public async Task TestInIf_IncludingOp()
&& j) {
}
}
}", index: 1);
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInIf2()
{
await TestInRegularAndScript1Async(
await TestEndOfLine(
@"class C {
void Bar() {
if (i[||] && j) {
......@@ -146,7 +165,7 @@ public async Task TestInIf2()
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInIf3()
{
await TestInRegularAndScript1Async(
await TestEndOfLine(
@"class C {
void Bar() {
if (i [||]&& j) {
......@@ -165,7 +184,7 @@ public async Task TestInIf3()
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInIf4()
{
await TestInRegularAndScript1Async(
await TestEndOfLine(
@"class C {
void Bar() {
if (i &&[||] j) {
......@@ -184,7 +203,7 @@ public async Task TestInIf4()
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInIf5()
{
await TestInRegularAndScript1Async(
await TestEndOfLine(
@"class C {
void Bar() {
if (i && [||]j) {
......@@ -201,7 +220,7 @@ public async Task TestInIf5()
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestTwoExprWrappingCases()
public async Task TestTwoExprWrappingCases_End()
{
await TestAllWrappingCasesAsync(
@"class C {
......@@ -210,13 +229,27 @@ public async Task TestTwoExprWrappingCases()
}
}
}",
EndOfLine,
@"class C {
void Bar() {
if (i &&
j) {
}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestTwoExprWrappingCases_Beginning()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
if ([||]i && j) {
}
}
}",
BeginningOfLine,
@"class C {
void Bar() {
if (i
......@@ -227,7 +260,7 @@ public async Task TestTwoExprWrappingCases()
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestThreeExprWrappingCases()
public async Task TestThreeExprWrappingCases_End()
{
await TestAllWrappingCasesAsync(
@"class C {
......@@ -236,6 +269,7 @@ public async Task TestThreeExprWrappingCases()
}
}
}",
EndOfLine,
@"class C {
void Bar() {
if (i &&
......@@ -243,7 +277,20 @@ public async Task TestThreeExprWrappingCases()
k) {
}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestThreeExprWrappingCases_Beginning()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
if ([||]i && j || k) {
}
}
}",
BeginningOfLine,
@"class C {
void Bar() {
if (i
......@@ -255,7 +302,7 @@ public async Task TestThreeExprWrappingCases()
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task Test_AllOptions_NoInitialMatches()
public async Task Test_AllOptions_NoInitialMatches_End()
{
await TestAllWrappingCasesAsync(
@"class C {
......@@ -267,6 +314,7 @@ public async Task Test_AllOptions_NoInitialMatches()
}
}
}",
EndOfLine,
@"class C {
void Bar() {
if (
......@@ -276,6 +324,29 @@ public async Task Test_AllOptions_NoInitialMatches()
}
}
}",
@"class C {
void Bar() {
if (
i && j || k) {
}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task Test_AllOptions_NoInitialMatches_Beginning()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
if (
[||]i &&
j
|| k) {
}
}
}",
BeginningOfLine,
@"class C {
void Bar() {
if (
......@@ -321,7 +392,7 @@ public async Task Test_DoNotOfferExistingOption1()
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task Test_DoNotOfferExistingOption2()
public async Task Test_DoNotOfferExistingOption2_End()
{
await TestAllWrappingCasesAsync(
@"class C {
......@@ -331,6 +402,7 @@ public async Task Test_DoNotOfferExistingOption2()
}
}
}",
EndOfLine,
@"class C {
void Bar() {
if (a &&
......@@ -346,10 +418,30 @@ public async Task Test_DoNotOfferExistingOption2()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task Test_DoNotOfferExistingOption2_Beginning()
{
await TestAllWrappingCasesAsync(
@"class C {
void Bar() {
if ([||]a
&& b) {
}
}
}",
BeginningOfLine,
@"class C {
void Bar() {
if (a && b) {
}
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInLocalInitializer()
{
await TestInRegularAndScript1Async(
await TestEndOfLine(
@"class C {
void Goo() {
var v = [||]a && b && c;
......@@ -367,7 +459,7 @@ public async Task TestInLocalInitializer()
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)]
public async Task TestInField()
{
await TestInRegularAndScript1Async(
await TestEndOfLine(
@"class C {
bool v = [||]a && b && c;
}",
......
......@@ -156,7 +156,7 @@ private async Task<(SyntaxNode root, SyntaxNode rewrittenRoot, TextSpan spanToFo
{
var span = TextSpan.FromBounds(edit.Left.Span.End, edit.Right.Span.Start);
var text = OriginalSourceText.ToString(span);
if (!this.IsSafeToRemove(text))
if (!IsSafeToRemove(text))
{
// editing some piece of non-whitespace trivia. We don't support this.
return default;
......
......@@ -3,6 +3,7 @@
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Options;
......@@ -14,10 +15,11 @@ namespace Microsoft.CodeAnalysis.Editor.Wrapping.BinaryExpression
{
internal partial class AbstractBinaryExpressionWrapper<TBinaryExpressionSyntax> where TBinaryExpressionSyntax : SyntaxNode
{
private class BinaryExpressionCodeActionComputer :
private class BinaryExpressionCodeActionComputer :
AbstractCodeActionComputer<AbstractBinaryExpressionWrapper<TBinaryExpressionSyntax>>
{
private readonly ImmutableArray<SyntaxNodeOrToken> _exprsAndOperators;
private readonly OperatorPlacementWhenWrappingPreference _preference;
private readonly SyntaxTriviaList _indentationTrivia;
private readonly SyntaxTriviaList _newlineBeforeOperatorTrivia;
......@@ -33,6 +35,7 @@ private class BinaryExpressionCodeActionComputer :
: base(service, document, originalSourceText, options, cancellationToken)
{
_exprsAndOperators = exprsAndOperators;
_preference = options.GetOption(CodeStyleOptions.OperatorPlacementWhenWrapping);
var generator = SyntaxGenerator.GetGenerator(document);
var indentationString = OriginalSourceText.GetOffset(binaryExpression.Span.Start)
......@@ -46,8 +49,15 @@ protected override async Task<ImmutableArray<WrappingGroup>> ComputeWrappingGrou
{
var actions = ArrayBuilder<WrapItemsAction>.GetInstance();
actions.Add(await GetWrapCodeActionAsync(includeOperators: false).ConfigureAwait(false));
actions.Add(await GetWrapCodeActionAsync(includeOperators: true).ConfigureAwait(false));
if (_preference == OperatorPlacementWhenWrappingPreference.EndOfLine)
{
actions.Add(await GetWrapCodeActionAsync(includeOperators: false).ConfigureAwait(false));
}
else
{
actions.Add(await GetWrapCodeActionAsync(includeOperators: true).ConfigureAwait(false));
}
actions.Add(await GetUnwrapCodeActionAsync().ConfigureAwait(false));
return ImmutableArray.Create(new WrappingGroup(
......
' 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.CodeStyle
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.Wrapping
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping
......@@ -11,6 +12,20 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Wrapping
Return New VisualBasicWrappingCodeRefactoringProvider()
End Function
Private Function TestEndOfLine(markup As String, expected As String) As Task
Return TestInRegularAndScript1Async(markup, expected, parameters:=New TestParameters(
options:=[Option](
CodeStyleOptions.OperatorPlacementWhenWrapping,
OperatorPlacementWhenWrappingPreference.EndOfLine)))
End Function
Private Function TestBeginningOfLine(markup As String, expected As String) As Task
Return TestInRegularAndScript1Async(markup, expected, parameters:=New TestParameters(
options:=[Option](
CodeStyleOptions.OperatorPlacementWhenWrapping,
OperatorPlacementWhenWrappingPreference.BeginningOfLine)))
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestMissingWithSyntaxError() As Task
Await TestMissingAsync(
......@@ -80,7 +95,7 @@ end class")
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestInIf() As Task
Await TestInRegularAndScript1Async(
Await TestEndOfLine(
"class C
sub Bar()
if ([||]i andalso j)
......@@ -98,7 +113,7 @@ end class")
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestInIf_IncludingOp() As Task
Await TestInRegularAndScript1Async(
Await TestBeginningOfLine(
"class C
sub Bar()
if ([||]i andalso j)
......@@ -111,12 +126,12 @@ end class",
andalso j)
end if
end sub
end class", index:=1)
end class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestInIf2() As Task
Await TestInRegularAndScript1Async(
Await TestEndOfLine(
"class C
sub Bar()
if (i[||] andalso j)
......@@ -134,7 +149,7 @@ end class")
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestInIf3() As Task
Await TestInRegularAndScript1Async(
Await TestEndOfLine(
"class C
sub Bar()
if (i [||]andalso j)
......@@ -152,7 +167,7 @@ end class")
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestInIf4() As Task
Await TestInRegularAndScript1Async(
Await TestEndOfLine(
"class C
sub Bar()
if (i andalso[||] j)
......@@ -170,7 +185,7 @@ end class")
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestInIf5() As Task
Await TestInRegularAndScript1Async(
Await TestEndOfLine(
"class C
sub Bar()
if (i andalso [||]j)
......@@ -329,7 +344,7 @@ end class")
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestInLocalInitializer() As Task
Await TestInRegularAndScript1Async(
Await TestEndOfLine(
"class C
sub Goo()
dim v = [||]a andalso b andalso c
......@@ -346,7 +361,7 @@ end class")
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsWrapping)>
Public Async Function TestInField() As Task
Await TestInRegularAndScript1Async(
Await TestEndOfLine(
"class C
dim v = [||]a andalso b andalso c
end class",
......
......@@ -123,6 +123,16 @@ private static PerLanguageOption<T> CreateOption<T>(OptionGroup group, string na
defaultValue: false,
storageLocations: new RoamingProfileStorageLocation("TextEditor.%LANGUAGE%.Specific.PreferCollectionInitializer_FadeOutCode"));
internal static readonly PerLanguageOption<OperatorPlacementWhenWrappingPreference> OperatorPlacementWhenWrapping =
new PerLanguageOption<OperatorPlacementWhenWrappingPreference>(
nameof(CodeStyleOptions), nameof(OperatorPlacementWhenWrapping),
defaultValue: OperatorPlacementWhenWrappingPreference.BeginningOfLine,
storageLocations:
new EditorConfigStorageLocation<OperatorPlacementWhenWrappingPreference>(
"dotnet_style_operator_placement_when_wrapping",
OperatorPlacementUtilities.Parse,
OperatorPlacementUtilities.GetEditorConfigString));
internal static readonly PerLanguageOption<CodeStyleOption<bool>> PreferCoalesceExpression = CreateOption(
CodeStyleOptionGroups.ExpressionLevelPreferences, nameof(PreferCoalesceExpression),
defaultValue: TrueWithSuggestionEnforcement,
......
// 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;
namespace Microsoft.CodeAnalysis.CodeStyle
{
internal enum OperatorPlacementWhenWrappingPreference
{
BeginningOfLine,
EndOfLine,
}
internal static class OperatorPlacementUtilities
{
private const string end_of_line = "end_of_line";
private const string beginning_of_line = "beginning_of_line";
// Default to beginning_of_line if we don't know the value.
public static string GetEditorConfigString(OperatorPlacementWhenWrappingPreference value)
=> value == OperatorPlacementWhenWrappingPreference.EndOfLine ? end_of_line : beginning_of_line;
public static Optional<OperatorPlacementWhenWrappingPreference> Parse(string optionString)
{
if (CodeStyleHelpers.TryGetCodeStyleValueAndOptionalNotification(
optionString, out var value, out var notificationOpt))
{
switch (value)
{
case end_of_line: return OperatorPlacementWhenWrappingPreference.EndOfLine;
case beginning_of_line: return OperatorPlacementWhenWrappingPreference.BeginningOfLine;
}
}
// Default to beginning_of_line if we get something we don't understand.
return OperatorPlacementWhenWrappingPreference.BeginningOfLine;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册