未验证 提交 b68dba2a 编写于 作者: D David Poeschl 提交者: GitHub

Merge pull request #28391 from dotnet/merges/dev15.8-preview4-vs-deps-to-dev15.8.x-vs-deps

Merge dev15.8-preview4-vs-deps to dev15.8.x-vs-deps
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings.UseExplicitOrImplicitType
{
public abstract class AbstractUseTypeRefactoringTests : AbstractCSharpCodeActionTest
{
private readonly CodeStyleOption<bool> onWithNone = new CodeStyleOption<bool>(true, NotificationOption.None);
private readonly CodeStyleOption<bool> offWithNone = new CodeStyleOption<bool>(false, NotificationOption.None);
private readonly CodeStyleOption<bool> onWithSilent = new CodeStyleOption<bool>(true, NotificationOption.Silent);
private readonly CodeStyleOption<bool> offWithSilent = new CodeStyleOption<bool>(false, NotificationOption.Silent);
private readonly CodeStyleOption<bool> onWithInfo = new CodeStyleOption<bool>(true, NotificationOption.Suggestion);
private readonly CodeStyleOption<bool> offWithInfo = new CodeStyleOption<bool>(false, NotificationOption.Suggestion);
private readonly CodeStyleOption<bool> onWithWarning = new CodeStyleOption<bool>(true, NotificationOption.Warning);
private readonly CodeStyleOption<bool> offWithWarning = new CodeStyleOption<bool>(false, NotificationOption.Warning);
private readonly CodeStyleOption<bool> offWithError = new CodeStyleOption<bool>(false, NotificationOption.Error);
private readonly CodeStyleOption<bool> onWithError = new CodeStyleOption<bool>(true, NotificationOption.Error);
protected IDictionary<OptionKey, object> PreferExplicitTypeWithError() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithError),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithError),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithError));
protected IDictionary<OptionKey, object> PreferImplicitTypeWithError() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithError),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithError),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithError));
protected IDictionary<OptionKey, object> PreferExplicitTypeWithWarning() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithWarning),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithWarning),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithWarning));
protected IDictionary<OptionKey, object> PreferImplicitTypeWithWarning() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithWarning),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithWarning),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithWarning));
protected IDictionary<OptionKey, object> PreferExplicitTypeWithInfo() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithInfo));
protected IDictionary<OptionKey, object> PreferImplicitTypeWithInfo() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithInfo));
protected IDictionary<OptionKey, object> PreferExplicitTypeWithSilent() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithSilent));
protected IDictionary<OptionKey, object> PreferImplicitTypeWithSilent() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithSilent));
protected IDictionary<OptionKey, object> PreferExplicitTypeWithNone() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithNone),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithNone),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithNone));
protected IDictionary<OptionKey, object> PreferImplicitTypeWithNone() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithNone),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithNone),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithNone));
}
}
// 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.CSharp.CodeRefactorings.UseExplicitType;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings.UseExplicitType
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings.UseExplicitOrImplicitType
{
[Trait(Traits.Feature, Traits.Features.CodeActionsUseExplicitType)]
public class UseExplicitTypeRefactoringTests : AbstractCSharpCodeActionTest
public class UseExplicitTypeRefactoringTests : AbstractUseTypeRefactoringTests
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new UseExplicitTypeCodeRefactoringProvider();
private readonly CodeStyleOption<bool> onWithSilent = new CodeStyleOption<bool>(true, NotificationOption.Silent);
private readonly CodeStyleOption<bool> offWithSilent = new CodeStyleOption<bool>(false, NotificationOption.Silent);
private readonly CodeStyleOption<bool> onWithInfo = new CodeStyleOption<bool>(true, NotificationOption.Suggestion);
private readonly CodeStyleOption<bool> offWithInfo = new CodeStyleOption<bool>(false, NotificationOption.Suggestion);
private IDictionary<OptionKey, object> PreferExplicitTypeWithInfo() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithInfo));
private IDictionary<OptionKey, object> PreferExplicitTypeWithSilent() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithSilent));
private IDictionary<OptionKey, object> PreferImplicitTypeWithInfo() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithInfo));
private IDictionary<OptionKey, object> PreferImplicitTypeWithSilent() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithSilent));
[Fact]
public async Task TestIntLocalDeclaration()
{
......@@ -65,9 +36,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptAsync(code, expected, options: PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithInfo());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -91,7 +60,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -106,9 +75,7 @@ static void Main()
}
}";
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code);
}
[Fact]
......@@ -124,9 +91,7 @@ static void Main()
}";
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code);
}
[Fact]
......@@ -165,7 +130,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -189,7 +154,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -203,7 +168,7 @@ static void Main()
var[||] i = null;
}
}";
await TestMissingInRegularAndScriptAsync(code, options: PreferImplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code);
}
[Fact]
......@@ -227,7 +192,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -251,7 +216,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -275,9 +240,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptAsync(code, expected, options: PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithInfo());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -292,7 +255,7 @@ static void Main()
}
}";
await TestMissingInRegularAndScriptAsync(code, options: PreferImplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code);
}
[Fact, WorkItem(26923, "https://github.com/dotnet/roslyn/issues/26923")]
......@@ -313,15 +276,42 @@ void Method(List<int> var)
}";
// We never want to get offered here under any circumstances.
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code);
}
private async Task TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(string initialMarkup, string expectedMarkup)
{
// Enabled because the diagnostic is disabled
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferExplicitTypeWithNone());
// Enabled because the diagnostic is checking for the other direction
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferImplicitTypeWithNone());
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferImplicitTypeWithInfo());
// Disabled because the diagnostic will report it instead
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithSilent()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithInfo()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithWarning()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithError()));
// Currently this refactoring is still enabled in cases where it would cause a warning or error
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferImplicitTypeWithWarning());
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferImplicitTypeWithError());
}
private Task TestMissingInRegularAndScriptAsync(string initialMarkup, IDictionary<OptionKey, object> options)
private async Task TestMissingInRegularAndScriptAsync(string initialMarkup)
{
return TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: options));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithNone()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithNone()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithSilent()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithSilent()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithInfo()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithInfo()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithWarning()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithWarning()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithError()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithError()));
}
}
}
// 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.CSharp.CodeRefactorings.UseImplicitType;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings.UseExplicitType
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings.UseExplicitOrImplicitType
{
[Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
public class UseImplicitTypeRefactoringTests : AbstractCSharpCodeActionTest
public class UseImplicitTypeRefactoringTests : AbstractUseTypeRefactoringTests
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new UseImplicitTypeCodeRefactoringProvider();
private readonly CodeStyleOption<bool> onWithSilent = new CodeStyleOption<bool>(true, NotificationOption.Silent);
private readonly CodeStyleOption<bool> offWithSilent = new CodeStyleOption<bool>(false, NotificationOption.Silent);
private readonly CodeStyleOption<bool> onWithInfo = new CodeStyleOption<bool>(true, NotificationOption.Suggestion);
private readonly CodeStyleOption<bool> offWithInfo = new CodeStyleOption<bool>(false, NotificationOption.Suggestion);
private IDictionary<OptionKey, object> PreferExplicitTypeWithInfo() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithInfo));
private IDictionary<OptionKey, object> PreferImplicitTypeWithInfo() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithInfo),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithInfo));
private IDictionary<OptionKey, object> PreferExplicitTypeWithSilent() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, offWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, offWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, offWithSilent));
private IDictionary<OptionKey, object> PreferImplicitTypeWithSilent() => OptionsSet(
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWherePossible, onWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, onWithSilent),
SingleOption(CSharpCodeStyleOptions.UseImplicitTypeForIntrinsicTypes, onWithSilent));
[Fact]
public async Task TestIntLocalDeclaration()
{
......@@ -65,10 +36,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptAsync(code, expected, options: PreferExplicitTypeWithSilent());
await TestInRegularAndScriptAsync(code, expected, options: PreferExplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithInfo());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -92,7 +60,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -107,10 +75,7 @@ static void Main()
}
}";
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code);
}
[Fact]
......@@ -126,10 +91,7 @@ static void Main()
}";
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code);
}
[Fact]
......@@ -168,7 +130,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -192,7 +154,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -216,7 +178,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -240,7 +202,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact]
......@@ -264,9 +226,7 @@ static void Main()
}
}";
await TestInRegularAndScriptAsync(code, expected, options: PreferImplicitTypeWithSilent());
await TestInRegularAndScriptAsync(code, expected, options: PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithInfo());
await TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(code, expected);
}
[Fact, WorkItem(26923, "https://github.com/dotnet/roslyn/issues/26923")]
......@@ -287,15 +247,42 @@ static void Main(string[] args)
}";
// We never want to get offered here under any circumstances.
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithSilent());
await TestMissingInRegularAndScriptAsync(code, PreferImplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code, PreferExplicitTypeWithInfo());
await TestMissingInRegularAndScriptAsync(code);
}
private async Task TestInRegularAndScriptWhenDiagnosticNotAppliedAsync(string initialMarkup, string expectedMarkup)
{
// Enabled because the diagnostic is disabled
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferImplicitTypeWithNone());
// Enabled because the diagnostic is checking for the other direction
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferExplicitTypeWithNone());
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferExplicitTypeWithSilent());
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferExplicitTypeWithInfo());
// Disabled because the diagnostic will report it instead
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithSilent()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithInfo()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithWarning()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithError()));
// Currently this refactoring is still enabled in cases where it would cause a warning or error
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferExplicitTypeWithWarning());
await TestInRegularAndScriptAsync(initialMarkup, expectedMarkup, options: PreferExplicitTypeWithError());
}
private Task TestMissingInRegularAndScriptAsync(string initialMarkup, IDictionary<OptionKey, object> options)
private async Task TestMissingInRegularAndScriptAsync(string initialMarkup)
{
return TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: options));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithNone()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithNone()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithSilent()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithSilent()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithInfo()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithInfo()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithWarning()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithWarning()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferImplicitTypeWithError()));
await TestMissingInRegularAndScriptAsync(initialMarkup, parameters: new TestParameters(options: PreferExplicitTypeWithError()));
}
}
}
......@@ -3,11 +3,11 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.PreferFrameworkType;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.Analyzers;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.PreferFrameworkType;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
......
......@@ -412,9 +412,9 @@ private System.Int32 F(System.Int32 p1, System.Int16 p2)
using System;
class ProgramA
{
private int x = 0;
private int y = 0;
private int z = 0;
private Int32 x = 0;
private Int32 y = 0;
private Int32 z = 0;
private System.Int32 F(System.Int32 p1, System.Int16 p2)
{
......@@ -432,9 +432,9 @@ private System.Int32 F(System.Int32 p1, System.Int16 p2)
using System;
class ProgramA2
{
private int x = 0;
private int y = 0;
private int z = 0;
private Int32 x = 0;
private Int32 y = 0;
private Int32 z = 0;
private System.Int32 F(System.Int32 p1, System.Int16 p2)
{
......@@ -454,9 +454,9 @@ private System.Int32 F(System.Int32 p1, System.Int16 p2)
using System;
class ProgramA3
{
private int x = 0;
private int y = 0;
private int z = 0;
private Int32 x = 0;
private Int32 y = 0;
private Int32 z = 0;
private System.Int32 F(System.Int32 p1, System.Int16 p2)
{
......
......@@ -1539,8 +1539,10 @@ static void M()
[|var|] n1 = new C();
}
}";
await TestMissingInRegularAndScriptAsync(source,
new TestParameters(options: ExplicitTypeSilentEnforcement()));
await TestDiagnosticInfoAsync(source,
options: ExplicitTypeSilentEnforcement(),
diagnosticId: IDEDiagnosticIds.UseExplicitTypeDiagnosticId,
diagnosticSeverity: DiagnosticSeverity.Hidden);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
......
......@@ -1524,8 +1524,10 @@ static void M()
[|C|] n1 = new C();
}
}";
await TestMissingInRegularAndScriptAsync(source,
new TestParameters(options: ImplicitTypeSilentEnforcement()));
await TestDiagnosticInfoAsync(source,
options: ImplicitTypeSilentEnforcement(),
diagnosticId: IDEDiagnosticIds.UseImplicitTypeDiagnosticId,
diagnosticSeverity: DiagnosticSeverity.Hidden);
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitType)]
......
......@@ -8,12 +8,9 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeCleanup;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames;
using Microsoft.CodeAnalysis.CSharp.TypeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.CSharp;
using Microsoft.CodeAnalysis.Diagnostics.SimplifyTypeNames;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Options;
......@@ -87,6 +84,7 @@ static void Main(string[] args)
return AssertCodeCleanupResult(expected, code,
(CodeCleanupOptions.AreCodeCleanupRulesConfigured, enabled: true),
(CodeCleanupOptions.SortImports, enabled: true),
(CodeCleanupOptions.ApplyImplicitExplicitTypePreferences, enabled: false),
(CodeCleanupOptions.AddAccessibilityModifiers, enabled: false));
}
......
......@@ -888,9 +888,9 @@ void Handler(object sender, EventArgs args)
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsQualifyMemberAccess)]
public async Task QualifyMemberAccessNotPresentOnNotificationOptionSilent()
public async Task QualifyMemberAccessOnNotificationOptionSilent()
{
await TestMissingAsyncWithOptionAndNotificationOption(
await TestAsyncWithOptionAndNotificationOption(
@"class Class
{
int Property { get; set; };
......@@ -900,6 +900,15 @@ void M()
[|Property|] = 1;
}
}",
@"class Class
{
int Property { get; set; };
void M()
{
this.Property = 1;
}
}",
CodeStyleOptions.QualifyPropertyAccess, NotificationOption.Silent);
}
......
// 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.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.QuickInfo;
using Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo;
using Microsoft.CodeAnalysis.Editor.UnitTests.QuickInfo;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.QuickInfo;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Text;
using Moq;
using Roslyn.Test.Utilities;
using Xunit;
......@@ -287,8 +292,10 @@ private QuickInfoProvider CreateProvider(TestWorkspace workspace)
Assert.NotEqual(0, info.RelatedSpans.Length);
var tabSize = document.Project.Solution.Workspace.Options.GetOption(Microsoft.CodeAnalysis.Formatting.FormattingOptions.TabSize, document.Project.Language);
var text = await document.GetTextAsync();
var spans = IndentationHelper.GetSpansWithAlignedIndentation(text, info.RelatedSpans, tabSize);
var actualText = string.Concat(spans.Select(s => text.GetSubText(s).ToString()));
var classifiedSpans = info.RelatedSpans.Select(s => new ClassifiedSpan(ClassificationTypeNames.Text, s));
var spans = IndentationHelper.GetSpansWithAlignedIndentation(text, classifiedSpans.ToImmutableArray(), tabSize);
var actualText = string.Concat(spans.Select(s => text.GetSubText(s.TextSpan).ToString()));
Assert.Equal(expectedContent, actualText);
}
......
......@@ -1189,9 +1189,9 @@ static void Main(string[] args)
[WorkItem(995168, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/995168"), WorkItem(1073099, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1073099")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsSimplifyTypeNames)]
public async Task SimplifyToPredefinedTypeNameShouldNotBeOfferedInsideNameOf4()
public async Task SimplifyToPredefinedTypeNameShouldBeOfferedInsideFunctionCalledNameOf()
{
await TestMissingInRegularAndScriptAsync(
await TestInRegularAndScriptAsync(
@"using System;
class Program
......@@ -1201,6 +1201,20 @@ static void Main(string[] args)
var x = nameof(typeof([|Int32|]));
}
static string nameof(Type t)
{
return string.Empty;
}
}",
@"using System;
class Program
{
static void Main(string[] args)
{
var x = nameof(typeof(int));
}
static string nameof(Type t)
{
return string.Empty;
......
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
......@@ -23,21 +24,41 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithSilentEnforcement));
private IDictionary<OptionKey, object> UseExpressionBodyForAccessors_BlockBodyForProperties_DisabledDiagnostic =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None)),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None)));
private IDictionary<OptionKey, object> UseExpressionBodyForAccessors_ExpressionBodyForProperties =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement));
private IDictionary<OptionKey, object> UseExpressionBodyForAccessors_ExpressionBodyForProperties_DisabledDiagnostic =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None)),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None)));
private IDictionary<OptionKey, object> UseBlockBodyForAccessors_ExpressionBodyForProperties =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement));
private IDictionary<OptionKey, object> UseBlockBodyForAccessors_ExpressionBodyForProperties_DisabledDiagnostic =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None)),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None)));
private IDictionary<OptionKey, object> UseBlockBodyForAccessors_BlockBodyForProperties =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithSilentEnforcement));
private IDictionary<OptionKey, object> UseBlockBodyForAccessors_BlockBodyForProperties_DisabledDiagnostic =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None)),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None)));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUpdatePropertyIfPropertyWantsBlockAndAccessorWantsExpression()
{
......@@ -74,6 +95,46 @@ int Goo
}", parameters: new TestParameters(options: UseExpressionBodyForAccessors_ExpressionBodyForProperties));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
int Goo
{
get
{
return [||]Bar();
}
}
}",
@"class C
{
int Goo => Bar();
}", parameters: new TestParameters(options: UseExpressionBodyForAccessors_BlockBodyForProperties_DisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody2()
{
await TestInRegularAndScript1Async(
@"class C
{
int Goo
{
get
{
return [||]Bar();
}
}
}",
@"class C
{
int Goo => Bar();
}", parameters: new TestParameters(options: UseExpressionBodyForAccessors_ExpressionBodyForProperties_DisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesAndInBlockBody()
{
......@@ -127,6 +188,36 @@ public async Task TestNotOfferedIfUserPrefersBlockBodiesAndInExpressionBody()
}", parameters: new TestParameters(options: UseBlockBodyForAccessors_ExpressionBodyForProperties));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
int Goo { get => [||]Bar(); }
}",
@"class C
{
int Goo => Bar();
}", parameters: new TestParameters(options: UseBlockBodyForAccessors_BlockBodyForProperties_DisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody2()
{
await TestInRegularAndScript1Async(
@"class C
{
int Goo { get => [||]Bar(); }
}",
@"class C
{
int Goo => Bar();
}", parameters: new TestParameters(options: UseBlockBodyForAccessors_ExpressionBodyForProperties_DisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedForPropertyIfUserPrefersBlockPropertiesAndHasBlockProperty()
{
......
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
......@@ -20,9 +21,15 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
private IDictionary<OptionKey, object> UseExpressionBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement);
private IDictionary<OptionKey, object> UseExpressionBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None));
private IDictionary<OptionKey, object> UseBlockBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, CSharpCodeStyleOptions.NeverWithSilentEnforcement);
private IDictionary<OptionKey, object> UseBlockBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedConstructors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
{
......@@ -36,6 +43,23 @@ public C()
}", parameters: new TestParameters(options: UseExpressionBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
public C()
{
[||]Bar();
}
}",
@"class C
{
public C() => Bar();
}", parameters: new TestParameters(options: UseExpressionBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesAndInBlockBody()
{
......@@ -76,6 +100,23 @@ public async Task TestNotOfferedIfUserPrefersBlockBodiesAndInExpressionBody()
}", parameters: new TestParameters(options: UseBlockBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
public C() => [||]Bar();
}",
@"class C
{
public C()
{
Bar();
}
}", parameters: new TestParameters(options: UseBlockBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesAndInExpressionBody()
{
......
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
......@@ -20,9 +21,15 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
private IDictionary<OptionKey, object> UseExpressionBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement);
private IDictionary<OptionKey, object> UseExpressionBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None));
private IDictionary<OptionKey, object> UseBlockBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.NeverWithSilentEnforcement);
private IDictionary<OptionKey, object> UseBlockBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
{
......@@ -36,6 +43,23 @@ public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
}", parameters: new TestParameters(options: UseExpressionBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
public static implicit operator bool(C c1)
{
[||]Bar();
}
}",
@"class C
{
public static implicit operator bool(C c1) => Bar();
}", parameters: new TestParameters(options: UseExpressionBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesAndInBlockBody()
{
......@@ -76,6 +100,23 @@ public async Task TestNotOfferedIfUserPrefersBlockBodiesAndInExpressionBody()
}", parameters: new TestParameters(options: UseBlockBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
public static implicit operator bool(C c1) => [||]Bar();
}",
@"class C
{
public static implicit operator bool(C c1)
{
return Bar();
}
}", parameters: new TestParameters(options: UseBlockBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesAndInExpressionBody()
{
......
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
......@@ -21,9 +22,15 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
private IDictionary<OptionKey, object> UseExpressionBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement);
private IDictionary<OptionKey, object> UseExpressionBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None));
private IDictionary<OptionKey, object> UseBlockBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, CSharpCodeStyleOptions.NeverWithSilentEnforcement);
private IDictionary<OptionKey, object> UseBlockBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedIndexers, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
{
......@@ -40,6 +47,26 @@ public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
}", parameters: new TestParameters(options: UseExpressionBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
int this[int i]
{
get
{
[||]return Bar();
}
}
}",
@"class C
{
int this[int i] => Bar();
}", parameters: new TestParameters(options: UseExpressionBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesAndInBlockBody()
{
......@@ -86,6 +113,26 @@ public async Task TestNotOfferedIfUserPrefersBlockBodiesAndInExpressionBody()
}", parameters: new TestParameters(options: UseBlockBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
int this[int i] => [||]Bar();
}",
@"class C
{
int this[int i]
{
get
{
return Bar();
}
}
}", parameters: new TestParameters(options: UseBlockBodyDisabledDiagnostic));
}
[WorkItem(20363, "https://github.com/dotnet/roslyn/issues/20363")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesAndInExpressionBody()
......
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
......@@ -20,9 +21,15 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
private IDictionary<OptionKey, object> UseExpressionBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement);
private IDictionary<OptionKey, object> UseExpressionBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None));
private IDictionary<OptionKey, object> UseBlockBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.NeverWithSilentEnforcement);
private IDictionary<OptionKey, object> UseBlockBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
{
......@@ -36,6 +43,23 @@ void Goo()
}", parameters: new TestParameters(options: UseExpressionBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
void Goo()
{
[||]Bar();
}
}",
@"class C
{
void Goo() => Bar();
}", parameters: new TestParameters(options: UseExpressionBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesAndInBlockBody()
{
......@@ -76,6 +100,23 @@ public async Task TestNotOfferedIfUserPrefersBlockBodiesAndInExpressionBody()
}", parameters: new TestParameters(options: UseBlockBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
void Goo() => [||]Bar();
}",
@"class C
{
void Goo()
{
Bar();
}
}", parameters: new TestParameters(options: UseBlockBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesAndInExpressionBody()
{
......
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
......@@ -20,9 +21,15 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
private IDictionary<OptionKey, object> UseExpressionBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement);
private IDictionary<OptionKey, object> UseExpressionBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None));
private IDictionary<OptionKey, object> UseBlockBody =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, CSharpCodeStyleOptions.NeverWithSilentEnforcement);
private IDictionary<OptionKey, object> UseBlockBodyDisabledDiagnostic =>
this.Option(CSharpCodeStyleOptions.PreferExpressionBodiedOperators, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
{
......@@ -36,6 +43,23 @@ public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
}", parameters: new TestParameters(options: UseExpressionBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
public static bool operator +(C c1, C c2)
{
[||]Bar();
}
}",
@"class C
{
public static bool operator +(C c1, C c2) => Bar();
}", parameters: new TestParameters(options: UseExpressionBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesAndInBlockBody()
{
......@@ -76,6 +100,23 @@ public async Task TestNotOfferedIfUserPrefersBlockBodiesAndInExpressionBody()
}", parameters: new TestParameters(options: UseBlockBody));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
public static bool operator +(C c1, C c2) => [||]Bar();
}",
@"class C
{
public static bool operator +(C c1, C c2)
{
return Bar();
}
}", parameters: new TestParameters(options: UseBlockBodyDisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesAndInExpressionBody()
{
......
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.UseExpressionBody;
......@@ -24,21 +25,41 @@ protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspa
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithSilentEnforcement));
private IDictionary<OptionKey, object> UseExpressionBodyForAccessors_BlockBodyForProperties_DisabledDiagnostic =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None)),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None)));
private IDictionary<OptionKey, object> UseExpressionBodyForAccessors_ExpressionBodyForProperties =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement));
private IDictionary<OptionKey, object> UseExpressionBodyForAccessors_ExpressionBodyForProperties_DisabledDiagnostic =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None)),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None)));
private IDictionary<OptionKey, object> UseBlockBodyForAccessors_ExpressionBodyForProperties =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.WhenPossibleWithSilentEnforcement));
private IDictionary<OptionKey, object> UseBlockBodyForAccessors_ExpressionBodyForProperties_DisabledDiagnostic =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None)),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.WhenPossible, NotificationOption.None)));
private IDictionary<OptionKey, object> UseBlockBodyForAccessors_BlockBodyForProperties =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, CSharpCodeStyleOptions.NeverWithSilentEnforcement),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, CSharpCodeStyleOptions.NeverWithSilentEnforcement));
private IDictionary<OptionKey, object> UseBlockBodyForAccessors_BlockBodyForProperties_DisabledDiagnostic =>
OptionsSet(
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None)),
this.SingleOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties, new CodeStyleOption<ExpressionBodyPreference>(ExpressionBodyPreference.Never, NotificationOption.None)));
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestNotOfferedIfUserPrefersExpressionBodiesAndInBlockBody()
{
......@@ -55,6 +76,26 @@ int Goo
}", parameters: new TestParameters(options: UseExpressionBodyForAccessors_ExpressionBodyForProperties));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesWithoutDiagnosticAndInBlockBody()
{
await TestInRegularAndScript1Async(
@"class C
{
int Goo
{
get
{
[||]return Bar();
}
}
}",
@"class C
{
int Goo => Bar();
}", parameters: new TestParameters(options: UseExpressionBodyForAccessors_ExpressionBodyForProperties_DisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestUpdateAccessorIfAccessWantsBlockAndPropertyWantsExpression()
{
......@@ -154,6 +195,46 @@ public async Task TestNotOfferedIfUserPrefersBlockBodiesAndInExpressionBody2()
}", parameters: new TestParameters(options: UseBlockBodyForAccessors_BlockBodyForProperties));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody()
{
await TestInRegularAndScript1Async(
@"class C
{
int Goo => [||]Bar();
}",
@"class C
{
int Goo
{
get
{
return Bar();
}
}
}", parameters: new TestParameters(options: UseExpressionBodyForAccessors_BlockBodyForProperties_DisabledDiagnostic));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersBlockBodiesWithoutDiagnosticAndInExpressionBody2()
{
await TestInRegularAndScript1Async(
@"class C
{
int Goo => [||]Bar();
}",
@"class C
{
int Goo
{
get
{
return Bar();
}
}
}", parameters: new TestParameters(options: UseBlockBodyForAccessors_BlockBodyForProperties_DisabledDiagnostic));
}
[WorkItem(20363, "https://github.com/dotnet/roslyn/issues/20363")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExpressionBody)]
public async Task TestOfferedIfUserPrefersExpressionBodiesAndInExpressionBody()
......
// 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.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.FindUsages;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
namespace Microsoft.CodeAnalysis.Editor.FindUsages
{
......@@ -80,13 +77,8 @@ private static TextSpan GetLineSpanForReference(SourceText sourceText, TextSpan
private static async Task<ImmutableArray<ClassifiedSpan>> GetClassifiedSpansAsync(
Document document, TextSpan narrowSpan, TextSpan widenedSpan, CancellationToken cancellationToken)
{
var result = await GetClassifiedSpansAsync(document, narrowSpan, widenedSpan, WorkspaceClassificationDelegationService.Instance, cancellationToken).ConfigureAwait(false);
if (!result.IsDefault)
{
return result;
}
result = await GetClassifiedSpansAsync(document, narrowSpan, widenedSpan, EditorClassificationDelegationService.Instance, cancellationToken).ConfigureAwait(false);
var result = await EditorClassifier.GetClassifiedSpansAsync(
document, widenedSpan, cancellationToken).ConfigureAwait(false);
if (!result.IsDefault)
{
return result;
......@@ -100,194 +92,5 @@ private static TextSpan GetLineSpanForReference(SourceText sourceText, TextSpan
new ClassifiedSpan(ClassificationTypeNames.Text, narrowSpan),
new ClassifiedSpan(ClassificationTypeNames.Text, TextSpan.FromBounds(narrowSpan.End, widenedSpan.End)));
}
private static async Task<ImmutableArray<ClassifiedSpan>> GetClassifiedSpansAsync<TClassificationService>(
Document document, TextSpan narrowSpan, TextSpan widenedSpan,
IClassificationDelegationService<TClassificationService> delegationService,
CancellationToken cancellationToken) where TClassificationService : class, ILanguageService
{
var classificationService = document.GetLanguageService<TClassificationService>();
if (classificationService == null)
{
return default;
}
// Call out to the individual language to classify the chunk of text around the
// reference. We'll get both the syntactic and semantic spans for this region.
// Because the semantic tags may override the semantic ones (for example,
// "DateTime" might be syntactically an identifier, but semantically a struct
// name), we'll do a later merging step to get the final correct list of
// classifications. For tagging, normally the editor handles this. But as
// we're producing the list of Inlines ourselves, we have to handles this here.
var syntaxSpans = ListPool<ClassifiedSpan>.Allocate();
var semanticSpans = ListPool<ClassifiedSpan>.Allocate();
try
{
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
await delegationService.AddSyntacticClassificationsAsync(
classificationService, document, widenedSpan, syntaxSpans, cancellationToken).ConfigureAwait(false);
await delegationService.AddSemanticClassificationsAsync(
classificationService, document, widenedSpan, semanticSpans, cancellationToken).ConfigureAwait(false);
var classifiedSpans = MergeClassifiedSpans(
syntaxSpans, semanticSpans, widenedSpan, sourceText);
return classifiedSpans;
}
finally
{
ListPool<ClassifiedSpan>.Free(syntaxSpans);
ListPool<ClassifiedSpan>.Free(semanticSpans);
}
}
private static ImmutableArray<ClassifiedSpan> MergeClassifiedSpans(
List<ClassifiedSpan> syntaxSpans, List<ClassifiedSpan> semanticSpans,
TextSpan widenedSpan, SourceText sourceText)
{
// The spans produced by the language services may not be ordered
// (indeed, this happens with semantic classification as different
// providers produce different results in an arbitrary order). Order
// them first before proceeding.
Order(syntaxSpans);
Order(semanticSpans);
// It's possible for us to get classified spans that occur *before*
// or after the span we want to present. This happens because the calls to
// AddSyntacticClassificationsAsync and AddSemanticClassificationsAsync
// may return more spans than the range asked for. While bad form,
// it's never been a requirement that implementation not do that.
// For example, the span may be the non-full-span of a node, but the
// classifiers may still return classifications for leading/trailing
// trivia even if it's out of the bounds of that span.
//
// To deal with that, we adjust all spans so that they don't go outside
// of the range we care about.
AdjustSpans(syntaxSpans, widenedSpan);
AdjustSpans(semanticSpans, widenedSpan);
// The classification service will only produce classifications for
// things it knows about. i.e. there will be gaps in what it produces.
// Fill in those gaps so we have *all* parts of the span
// classified properly.
var filledInSyntaxSpans = ArrayBuilder<ClassifiedSpan>.GetInstance();
var filledInSemanticSpans = ArrayBuilder<ClassifiedSpan>.GetInstance();
try
{
FillInClassifiedSpanGaps(sourceText, widenedSpan.Start, syntaxSpans, filledInSyntaxSpans);
FillInClassifiedSpanGaps(sourceText, widenedSpan.Start, semanticSpans, filledInSemanticSpans);
// Now merge the lists together, taking all the results from syntaxParts
// unless they were overridden by results in semanticParts.
return MergeParts(filledInSyntaxSpans, filledInSemanticSpans);
}
finally
{
filledInSyntaxSpans.Free();
filledInSemanticSpans.Free();
}
}
private static void Order(List<ClassifiedSpan> syntaxSpans)
=> syntaxSpans.Sort((s1, s2) => s1.TextSpan.Start - s2.TextSpan.Start);
private static void AdjustSpans(List<ClassifiedSpan> spans, TextSpan widenedSpan)
{
for (var i = 0; i < spans.Count; i++)
{
var span = spans[i];
// Make sure the span actually intersects 'widenedSpan'. If it
// does not, just put in an empty length span. It will get ignored later
// when we walk through this list.
var intersection = span.TextSpan.Intersection(widenedSpan);
if (i > 0 && intersection != null)
{
if (spans[i - 1].TextSpan.End > intersection.Value.Start)
{
// This span isn't strictly after the previous span. Ignore it.
intersection = null;
}
}
var newSpan = new ClassifiedSpan(span.ClassificationType,
intersection ?? new TextSpan());
spans[i] = newSpan;
}
}
private static void FillInClassifiedSpanGaps(
SourceText sourceText, int startPosition,
List<ClassifiedSpan> classifiedSpans, ArrayBuilder<ClassifiedSpan> result)
{
foreach (var span in classifiedSpans)
{
// Ignore empty spans. We can get those when the classification service
// returns spans outside of the range of the span we asked to classify.
if (span.TextSpan.Length == 0)
{
continue;
}
// If there is space between this span and the last one, then add a space.
if (startPosition != span.TextSpan.Start)
{
result.Add(new ClassifiedSpan(ClassificationTypeNames.Text,
TextSpan.FromBounds(
startPosition, span.TextSpan.Start)));
}
result.Add(span);
startPosition = span.TextSpan.End;
}
}
private static ImmutableArray<ClassifiedSpan> MergeParts(
ArrayBuilder<ClassifiedSpan> syntaxParts,
ArrayBuilder<ClassifiedSpan> semanticParts)
{
// Take all the syntax parts. However, if any have been overridden by a
// semantic part, then choose that one.
var finalParts = ArrayBuilder<ClassifiedSpan>.GetInstance();
var lastReplacementIndex = 0;
for (int i = 0, n = syntaxParts.Count; i < n; i++)
{
var syntaxPartAndSpan = syntaxParts[i];
// See if we can find a semantic part to replace this syntax part.
var replacementIndex = semanticParts.FindIndex(
lastReplacementIndex, t => t.TextSpan == syntaxPartAndSpan.TextSpan);
// Take the semantic part if it's just 'text'. We want to keep it if
// the semantic classifier actually produced an interesting result
// (as opposed to it just being a 'gap' classification).
var part = replacementIndex >= 0 && !IsClassifiedAsText(semanticParts[replacementIndex])
? semanticParts[replacementIndex]
: syntaxPartAndSpan;
finalParts.Add(part);
if (replacementIndex >= 0)
{
// If we found a semantic replacement, update the lastIndex.
// That way we can start searching from that point instead
// of checking all the elements each time.
lastReplacementIndex = replacementIndex + 1;
}
}
return finalParts.ToImmutableAndFree();
}
private static bool IsClassifiedAsText(ClassifiedSpan partAndSpan)
{
// Don't take 'text' from the semantic parts. We'll get those for the
// spaces between the actual interesting semantic spans, and we don't
// want them to override actual good syntax spans.
return partAndSpan.ClassificationType == ClassificationTypeNames.Text;
}
}
}
// 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.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.Editor
{
internal static class EditorClassifier
{
/// <summary>
/// Classifies the provided <paramref name="span"/> in the given <paramref name="document"/>.
/// This will first try to do this using an appropriate <see cref="IClassificationService"/>
/// if it can be found, followed by an appropriate <see cref="IEditorClassificationService"/>
/// if that can be found. <see cref="ImmutableArray{T}.IsDefault"/> will be returned if this
/// fails.
/// </summary>
public static async Task<ImmutableArray<ClassifiedSpan>> GetClassifiedSpansAsync(
Document document, TextSpan span, CancellationToken cancellationToken)
{
var result = await GetClassifiedSpansAsync(
WorkspaceClassificationDelegationService.Instance,
document, span, cancellationToken).ConfigureAwait(false);
if (!result.IsDefault)
{
return result;
}
result = await GetClassifiedSpansAsync(
EditorClassificationDelegationService.Instance,
document, span, cancellationToken).ConfigureAwait(false);
if (!result.IsDefault)
{
return result;
}
return default;
}
private static async Task<ImmutableArray<ClassifiedSpan>> GetClassifiedSpansAsync<TClassificationService>(
IClassificationDelegationService<TClassificationService> delegationService,
Document document, TextSpan widenedSpan, CancellationToken cancellationToken) where TClassificationService : class, ILanguageService
{
var classificationService = document.GetLanguageService<TClassificationService>();
if (classificationService == null)
{
return default;
}
// Call out to the individual language to classify the chunk of text around the
// reference. We'll get both the syntactic and semantic spans for this region.
// Because the semantic tags may override the semantic ones (for example,
// "DateTime" might be syntactically an identifier, but semantically a struct
// name), we'll do a later merging step to get the final correct list of
// classifications. For tagging, normally the editor handles this. But as
// we're producing the list of Inlines ourselves, we have to handles this here.
var syntaxSpans = ListPool<ClassifiedSpan>.Allocate();
var semanticSpans = ListPool<ClassifiedSpan>.Allocate();
try
{
var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
await delegationService.AddSyntacticClassificationsAsync(
classificationService, document, widenedSpan, syntaxSpans, cancellationToken).ConfigureAwait(false);
await delegationService.AddSemanticClassificationsAsync(
classificationService, document, widenedSpan, semanticSpans, cancellationToken).ConfigureAwait(false);
var classifiedSpans = MergeClassifiedSpans(
syntaxSpans, semanticSpans, widenedSpan, sourceText);
return classifiedSpans;
}
finally
{
ListPool<ClassifiedSpan>.Free(syntaxSpans);
ListPool<ClassifiedSpan>.Free(semanticSpans);
}
}
private static ImmutableArray<ClassifiedSpan> MergeClassifiedSpans(
List<ClassifiedSpan> syntaxSpans, List<ClassifiedSpan> semanticSpans,
TextSpan widenedSpan, SourceText sourceText)
{
// The spans produced by the language services may not be ordered
// (indeed, this happens with semantic classification as different
// providers produce different results in an arbitrary order). Order
// them first before proceeding.
Order(syntaxSpans);
Order(semanticSpans);
// It's possible for us to get classified spans that occur *before*
// or after the span we want to present. This happens because the calls to
// AddSyntacticClassificationsAsync and AddSemanticClassificationsAsync
// may return more spans than the range asked for. While bad form,
// it's never been a requirement that implementation not do that.
// For example, the span may be the non-full-span of a node, but the
// classifiers may still return classifications for leading/trailing
// trivia even if it's out of the bounds of that span.
//
// To deal with that, we adjust all spans so that they don't go outside
// of the range we care about.
AdjustSpans(syntaxSpans, widenedSpan);
AdjustSpans(semanticSpans, widenedSpan);
// The classification service will only produce classifications for
// things it knows about. i.e. there will be gaps in what it produces.
// Fill in those gaps so we have *all* parts of the span
// classified properly.
var filledInSyntaxSpans = ArrayBuilder<ClassifiedSpan>.GetInstance();
var filledInSemanticSpans = ArrayBuilder<ClassifiedSpan>.GetInstance();
try
{
FillInClassifiedSpanGaps(sourceText, widenedSpan.Start, syntaxSpans, filledInSyntaxSpans);
FillInClassifiedSpanGaps(sourceText, widenedSpan.Start, semanticSpans, filledInSemanticSpans);
// Now merge the lists together, taking all the results from syntaxParts
// unless they were overridden by results in semanticParts.
return MergeParts(filledInSyntaxSpans, filledInSemanticSpans);
}
finally
{
filledInSyntaxSpans.Free();
filledInSemanticSpans.Free();
}
}
private static void Order(List<ClassifiedSpan> syntaxSpans)
=> syntaxSpans.Sort((s1, s2) => s1.TextSpan.Start - s2.TextSpan.Start);
private static void AdjustSpans(List<ClassifiedSpan> spans, TextSpan widenedSpan)
{
for (var i = 0; i < spans.Count; i++)
{
var span = spans[i];
// Make sure the span actually intersects 'widenedSpan'. If it
// does not, just put in an empty length span. It will get ignored later
// when we walk through this list.
var intersection = span.TextSpan.Intersection(widenedSpan);
if (i > 0 && intersection != null)
{
if (spans[i - 1].TextSpan.End > intersection.Value.Start)
{
// This span isn't strictly after the previous span. Ignore it.
intersection = null;
}
}
var newSpan = new ClassifiedSpan(span.ClassificationType,
intersection ?? new TextSpan());
spans[i] = newSpan;
}
}
private static void FillInClassifiedSpanGaps(
SourceText sourceText, int startPosition,
List<ClassifiedSpan> classifiedSpans, ArrayBuilder<ClassifiedSpan> result)
{
foreach (var span in classifiedSpans)
{
// Ignore empty spans. We can get those when the classification service
// returns spans outside of the range of the span we asked to classify.
if (span.TextSpan.Length == 0)
{
continue;
}
// If there is space between this span and the last one, then add a space.
if (startPosition != span.TextSpan.Start)
{
result.Add(new ClassifiedSpan(ClassificationTypeNames.Text,
TextSpan.FromBounds(
startPosition, span.TextSpan.Start)));
}
result.Add(span);
startPosition = span.TextSpan.End;
}
}
private static ImmutableArray<ClassifiedSpan> MergeParts(
ArrayBuilder<ClassifiedSpan> syntaxParts,
ArrayBuilder<ClassifiedSpan> semanticParts)
{
// Take all the syntax parts. However, if any have been overridden by a
// semantic part, then choose that one.
var finalParts = ArrayBuilder<ClassifiedSpan>.GetInstance();
var lastReplacementIndex = 0;
for (int i = 0, n = syntaxParts.Count; i < n; i++)
{
var syntaxPartAndSpan = syntaxParts[i];
// See if we can find a semantic part to replace this syntax part.
var replacementIndex = semanticParts.FindIndex(
lastReplacementIndex, t => t.TextSpan == syntaxPartAndSpan.TextSpan);
// Take the semantic part if it's just 'text'. We want to keep it if
// the semantic classifier actually produced an interesting result
// (as opposed to it just being a 'gap' classification).
var part = replacementIndex >= 0 && !IsClassifiedAsText(semanticParts[replacementIndex])
? semanticParts[replacementIndex]
: syntaxPartAndSpan;
finalParts.Add(part);
if (replacementIndex >= 0)
{
// If we found a semantic replacement, update the lastIndex.
// That way we can start searching from that point instead
// of checking all the elements each time.
lastReplacementIndex = replacementIndex + 1;
}
}
return finalParts.ToImmutableAndFree();
}
private static bool IsClassifiedAsText(ClassifiedSpan partAndSpan)
{
// Don't take 'text' from the semantic parts. We'll get those for the
// spaces between the actual interesting semantic spans, and we don't
// want them to override actual good syntax spans.
return partAndSpan.ClassificationType == ClassificationTypeNames.Text;
}
}
}
......@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
......@@ -186,6 +187,7 @@ private CompletionProvider GetCompletionProvider(CompletionItem item)
}
transaction.Complete();
Logger.Log(FunctionId.Intellisense_Completion_Commit, KeyValueLogMessage.NoProperty);
}
// Let the completion rules know that this item was committed.
......
// 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.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.QuickInfo;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Adornments;
......@@ -14,7 +20,11 @@ namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.QuickInfo
{
internal static class IntellisenseQuickInfoBuilder
{
internal static IntellisenseQuickInfoItem BuildItem(ITrackingSpan trackingSpan, CodeAnalysisQuickInfoItem quickInfoItem)
internal static async Task<IntellisenseQuickInfoItem> BuildItemAsync(ITrackingSpan trackingSpan,
CodeAnalysisQuickInfoItem quickInfoItem,
ITextSnapshot snapshot,
Document document,
CancellationToken cancellationToken)
{
// Build the first line of QuickInfo item, the images and the Description section should be on the first line with Wrapped style
var glyphs = quickInfoItem.Tags.GetGlyphs();
......@@ -47,6 +57,27 @@ internal static IntellisenseQuickInfoItem BuildItem(ITrackingSpan trackingSpan,
quickInfoItem.Sections.Where(s => s.Kind != QuickInfoSectionKinds.Description)
.Select(BuildClassifiedTextElement));
// build text for RelatedSpan
if (quickInfoItem.RelatedSpans.Any())
{
var classifiedSpanList = new List<ClassifiedSpan>();
foreach (var span in quickInfoItem.RelatedSpans)
{
var classifiedSpans = await EditorClassifier.GetClassifiedSpansAsync(document, span, cancellationToken).ConfigureAwait(false);
classifiedSpanList.AddRange(classifiedSpans);
}
var tabSize = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.TabSize, document.Project.Language);
var text = await document.GetTextAsync().ConfigureAwait(false);
var spans = IndentationHelper.GetSpansWithAlignedIndentation(text, classifiedSpanList.ToImmutableArray(), tabSize);
var textRuns = spans.Select(s => new ClassifiedTextRun(s.ClassificationType, snapshot.GetText(s.TextSpan.ToSpan())));
if (textRuns.Any())
{
elements.Add(new ClassifiedTextElement(textRuns));
}
}
var content = new ContainerElement(
ContainerElementStyle.Stacked,
elements);
......@@ -59,6 +90,5 @@ private static ClassifiedTextElement BuildClassifiedTextElement(QuickInfoSection
return new ClassifiedTextElement(section.TaggedParts.Select(
part => new ClassifiedTextRun(part.Tag.ToClassificationTypeName(), part.Text)));
}
}
}
......@@ -59,7 +59,7 @@ public async Task<IntellisenseQuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickIn
{
var textVersion = snapshot.Version;
var trackingSpan = textVersion.CreateTrackingSpan(item.Span.ToSpan(), SpanTrackingMode.EdgeInclusive);
return IntellisenseQuickInfoBuilder.BuildItem(trackingSpan, item);
return await IntellisenseQuickInfoBuilder.BuildItemAsync(trackingSpan, item, snapshot, document, cancellationToken).ConfigureAwait(false);
}
return null;
......
......@@ -14,7 +14,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
Public Class IntellisenseQuickInfoBuilderTests
<WpfFact, Trait(Traits.Feature, Traits.Features.QuickInfo)>
Public Sub BuildQuickInfoItem()
Public Async Sub BuildQuickInfoItem()
Dim codeAnalysisQuickInfoItem _
= QuickInfoItem.Create(New Text.TextSpan(0, 0), ImmutableArray.Create({"Method", "Public"}),
......@@ -56,7 +56,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.IntelliSense
.DefaultValue = DefaultValue.Mock
}
Dim intellisenseQuickInfo = IntellisenseQuickInfoBuilder.BuildItem(trackingSpan.Object, codeAnalysisQuickInfoItem)
Dim intellisenseQuickInfo = Await IntellisenseQuickInfoBuilder.BuildItemAsync(trackingSpan.Object, codeAnalysisQuickInfoItem, Nothing, Nothing, Threading.CancellationToken.None)
Assert.NotNull(intellisenseQuickInfo)
......
......@@ -3,10 +3,10 @@
Option Strict On
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeFixes.PreferFrameworkType
Imports Microsoft.CodeAnalysis.CodeStyle
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.PreferFrameworkType
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.Analyzers
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.PreferFrameworkTypeTests
......
......@@ -346,9 +346,9 @@ End Class]]>
<Document><![CDATA[
Imports System
Class ProgramA
Dim x As Integer = 0
Dim y As Integer = 0
Dim z As Integer = 0
Dim x As Int32 = 0
Dim y As Int32 = 0
Dim z As Int32 = 0
Private Function F(p1 As System.Int32, p2 As System.Int16) As System.Int32
Dim i1 As System.Int32 = Me.x
......@@ -364,9 +364,9 @@ End Class]]>
<Document><![CDATA[
Imports System
Class ProgramA2
Dim x As Integer = 0
Dim y As Integer = 0
Dim z As Integer = 0
Dim x As Int32 = 0
Dim y As Int32 = 0
Dim z As Int32 = 0
Private Function F(p1 As System.Int32, p2 As System.Int16) As System.Int32
Dim i1 As System.Int32 = Me.x
......@@ -385,9 +385,9 @@ End Class]]>
<Document><![CDATA[
Imports System
Class ProgramA3
Dim x As Integer = 0
Dim y As Integer = 0
Dim z As Integer = 0
Dim x As Int32 = 0
Dim y As Int32 = 0
Dim z As Int32 = 0
Private Function F(p1 As System.Int32, p2 As System.Int16) As System.Int32
Dim i1 As System.Int32 = Me.x
......
......@@ -434,9 +434,10 @@ CodeStyleOptions.QualifyEventAccess)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsQualifyMemberAccess)>
Public Async Function QualifyMemberAccessNotPresentOnNotificationOptionSilent() As Task
Await TestMissingAsyncWithOptionAndNotification(
Public Async Function QualifyMemberAccessOnNotificationOptionSilent() As Task
Await TestAsyncWithOptionAndNotification(
"Class C : Property I As Integer : Sub M() : [|I|] = 1 : End Sub : End Class",
"Class C : Property I As Integer : Sub M() : Me.I = 1 : End Sub : End Class",
CodeStyleOptions.QualifyPropertyAccess, NotificationOption.Silent)
End Function
......
......@@ -2417,7 +2417,7 @@ End Module
Dim parameters2 As New TestParameters()
Using workspace = CreateWorkspaceFromFile(source.ToString(), parameters2)
workspace.ApplyOptions(PreferIntrinsicPredefinedTypeEverywhere())
Dim diagnostics = (Await GetDiagnosticsAsync(workspace, parameters2)).Where(Function(d) d.Id = IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId)
Dim diagnostics = (Await GetDiagnosticsAsync(workspace, parameters2)).Where(Function(d) d.Id = IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId)
Assert.Equal(1, diagnostics.Count)
End Using
......
......@@ -43,8 +43,7 @@ internal class CSharpCodeCleanupService : ICodeCleanupService
private static ImmutableArray<Tuple<PerLanguageOption<bool>, ImmutableArray<string>>> GetCodeCleanupOptionMapping()
{
return ImmutableArray.Create<Tuple<PerLanguageOption<bool>, ImmutableArray<string>>>
(
return ImmutableArray.Create(
Tuple.Create(
CodeCleanupOptions.ApplyImplicitExplicitTypePreferences,
ImmutableArray.Create(IDEDiagnosticIds.UseImplicitTypeDiagnosticId,
......@@ -57,8 +56,7 @@ internal class CSharpCodeCleanupService : ICodeCleanupService
),
Tuple.Create(
CodeCleanupOptions.ApplyLanguageFrameworkTypePreferences,
ImmutableArray.Create(IDEDiagnosticIds.PreferFrameworkTypeInDeclarationsDiagnosticId,
IDEDiagnosticIds.PreferFrameworkTypeInMemberAccessDiagnosticId)
ImmutableArray.Create(IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId)
),
Tuple.Create(
CodeCleanupOptions.AddRemoveBracesForSingleLineControlStatements,
......
......@@ -69,7 +69,7 @@ public override async Task ComputeRefactoringsAsync(CodeRefactoringContext conte
}
var typeStyle = AnalyzeTypeName(declaredType, semanticModel, optionSet, cancellationToken);
if (typeStyle.IsStylePreferred && typeStyle.Severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) < ReportDiagnostic.Hidden)
if (typeStyle.IsStylePreferred && typeStyle.Severity != ReportDiagnostic.Suppress)
{
// the analyzer would handle this. So we do not.
return;
......
......@@ -4,7 +4,7 @@
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.PreferFrameworkType;
using Microsoft.CodeAnalysis.PreferFrameworkType;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.Analyzers
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
......@@ -9,8 +7,8 @@
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.SimplifyTypeNames;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.SimplifyTypeNames;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames
......@@ -93,13 +91,23 @@ private static bool IsCrefCandidate(SyntaxNode node)
return node is QualifiedCrefSyntax;
}
protected sealed override bool CanSimplifyTypeNameExpressionCore(SemanticModel model, SyntaxNode node, OptionSet optionSet, out TextSpan issueSpan, out string diagnosticId, CancellationToken cancellationToken)
protected sealed override bool CanSimplifyTypeNameExpressionCore(
SemanticModel model, SyntaxNode node, OptionSet optionSet,
out TextSpan issueSpan, out string diagnosticId, out bool inDeclaration,
CancellationToken cancellationToken)
{
return CanSimplifyTypeNameExpression(model, node, optionSet, out issueSpan, out diagnosticId, cancellationToken);
return CanSimplifyTypeNameExpression(
model, node, optionSet,
out issueSpan, out diagnosticId, out inDeclaration,
cancellationToken);
}
internal override bool CanSimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, OptionSet optionSet, out TextSpan issueSpan, out string diagnosticId, CancellationToken cancellationToken)
internal override bool CanSimplifyTypeNameExpression(
SemanticModel model, SyntaxNode node, OptionSet optionSet,
out TextSpan issueSpan, out string diagnosticId, out bool inDeclaration,
CancellationToken cancellationToken)
{
inDeclaration = false;
issueSpan = default;
diagnosticId = IDEDiagnosticIds.SimplifyNamesDiagnosticId;
......@@ -138,11 +146,13 @@ internal override bool CanSimplifyTypeNameExpression(SemanticModel model, Syntax
// set proper diagnostic ids.
if (replacementSyntax.HasAnnotations(nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration)))
{
diagnosticId = IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId;
inDeclaration = true;
diagnosticId = IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId;
}
else if (replacementSyntax.HasAnnotations(nameof(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess)))
{
diagnosticId = IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId;
inDeclaration = false;
diagnosticId = IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId;
}
else if (expression.Kind() == SyntaxKind.SimpleMemberAccessExpression)
{
......
// 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.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Utilities;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.TypeStyle
......@@ -62,9 +58,7 @@ private void HandleVariableDeclaration(SyntaxNodeAnalysisContext context)
var typeStyle = Helper.AnalyzeTypeName(
declaredType, semanticModel, optionSet, cancellationToken);
if (!typeStyle.IsStylePreferred ||
typeStyle.Severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) >= ReportDiagnostic.Hidden ||
!typeStyle.CanConvert())
if (!typeStyle.IsStylePreferred || !typeStyle.CanConvert())
{
return;
}
......
......@@ -26,11 +26,10 @@ protected override string GetTitle(string diagnosticId, string nodeText)
switch (diagnosticId)
{
case IDEDiagnosticIds.SimplifyNamesDiagnosticId:
case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId:
case IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId:
return string.Format(CSharpFeaturesResources.Simplify_name_0, nodeText);
case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId:
case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId:
return string.Format(CSharpFeaturesResources.Simplify_member_access_0, nodeText);
case IDEDiagnosticIds.RemoveQualificationDiagnosticId:
......
......@@ -5,7 +5,6 @@
using System.Linq;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -82,12 +81,15 @@ protected virtual Location GetDiagnosticLocation(TDeclaration declaration)
public bool CanOfferUseExpressionBody(
OptionSet optionSet, TDeclaration declaration, bool forAnalyzer)
{
var preference = optionSet.GetOption(this.Option).Value;
var currentOptionValue = optionSet.GetOption(Option);
var preference = currentOptionValue.Value;
var userPrefersExpressionBodies = preference != ExpressionBodyPreference.Never;
var analyzerDisabled = currentOptionValue.Notification.Severity == ReportDiagnostic.Suppress;
// If the user likes expression bodies, then we offer expression bodies from the diagnostic analyzer.
// If the user does not like expression bodies then we offer expression bodies from the refactoring provider.
if (userPrefersExpressionBodies == forAnalyzer)
// If the analyzer is disabled completely, the refactoring is enabled in both directions.
if (userPrefersExpressionBodies == forAnalyzer || (!forAnalyzer && analyzerDisabled))
{
var expressionBody = this.GetExpressionBody(declaration);
if (expressionBody == null)
......@@ -156,8 +158,10 @@ protected virtual Location GetDiagnosticLocation(TDeclaration declaration)
public (bool canOffer, bool fixesError) CanOfferUseBlockBody(
OptionSet optionSet, TDeclaration declaration, bool forAnalyzer)
{
var preference = optionSet.GetOption(this.Option).Value;
var currentOptionValue = optionSet.GetOption(Option);
var preference = currentOptionValue.Value;
var userPrefersBlockBodies = preference == ExpressionBodyPreference.Never;
var analyzerDisabled = currentOptionValue.Notification.Severity == ReportDiagnostic.Suppress;
var expressionBodyOpt = this.GetExpressionBody(declaration);
var canOffer = expressionBodyOpt?.TryConvertToBlock(
......@@ -197,7 +201,9 @@ protected virtual Location GetDiagnosticLocation(TDeclaration declaration)
// If the user likes block bodies, then we offer block bodies from the diagnostic analyzer.
// If the user does not like block bodies then we offer block bodies from the refactoring provider.
return (userPrefersBlockBodies == forAnalyzer, fixesError: false);
// If the analyzer is disabled completely, the refactoring is enabled in both directions.
canOffer = userPrefersBlockBodies == forAnalyzer || (!forAnalyzer && analyzerDisabled);
return (canOffer, fixesError: false);
}
public TDeclaration Update(
......
......@@ -31,7 +31,7 @@ public UseExpressionBodyCodeFixProvider()
}
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> diagnostic.Severity != DiagnosticSeverity.Hidden ||
=> !diagnostic.IsSuppressed ||
diagnostic.Properties.ContainsKey(UseExpressionBodyDiagnosticAnalyzer.FixesError);
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
......
......@@ -30,7 +30,7 @@ public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(IDEDiagnosticIds.UseLocalFunctionDiagnosticId);
protected override bool IncludeDiagnosticDuringFixAll(Diagnostic diagnostic)
=> diagnostic.Severity != DiagnosticSeverity.Hidden && !diagnostic.IsSuppressed;
=> !diagnostic.IsSuppressed;
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
......
......@@ -15,10 +15,13 @@ internal static class IDEDiagnosticIds
public const string AddQualificationDiagnosticId = "IDE0009";
public const string PopulateSwitchDiagnosticId = "IDE0010";
public const string AddBracesDiagnosticId = "IDE0011";
public const string PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId = "IDE0012";
public const string PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId = "IDE0013";
public const string PreferFrameworkTypeInDeclarationsDiagnosticId = "IDE0014";
public const string PreferFrameworkTypeInMemberAccessDiagnosticId = "IDE0015";
// IDE0012-IDE0015 deprecated and replaced with PreferBuiltInOrFrameworkTypeDiagnosticId (IDE0049)
// public const string PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId = "IDE0012";
// public const string PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId = "IDE0013";
// public const string PreferFrameworkTypeInDeclarationsDiagnosticId = "IDE0014";
// public const string PreferFrameworkTypeInMemberAccessDiagnosticId = "IDE0015";
public const string UseThrowExpressionDiagnosticId = "IDE0016";
public const string UseObjectInitializerDiagnosticId = "IDE0017";
public const string InlineDeclarationDiagnosticId = "IDE0018";
......@@ -72,6 +75,9 @@ internal static class IDEDiagnosticIds
public const string RemoveUnnecessaryParenthesesDiagnosticId = "IDE0047";
public const string AddRequiredParenthesesDiagnosticId = "IDE0048";
public const string PreferBuiltInOrFrameworkTypeDiagnosticId = "IDE0049";
// Analyzer error Ids
public const string AnalyzerChangedId = "IDE1001";
public const string AnalyzerDependencyConflictId = "IDE1002";
......
......@@ -2,7 +2,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
......@@ -118,7 +117,7 @@ void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
var namingStyleRules = namingPreferences.Rules;
if (!namingStyleRules.TryGetApplicableRule(symbol, out var applicableRule) ||
applicableRule.EnforcementLevel.WithDefaultSeverity(DiagnosticSeverity.Hidden) >= ReportDiagnostic.Hidden)
applicableRule.EnforcementLevel == ReportDiagnostic.Suppress)
{
return null;
}
......
......@@ -6,34 +6,31 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.PreferFrameworkType
namespace Microsoft.CodeAnalysis.PreferFrameworkType
{
[ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic,
Name = PredefinedCodeFixProviderNames.PreferFrameworkType), Shared]
internal class PreferFrameworkTypeCodeFixProvider : SyntaxEditorBasedCodeFixProvider
{
public const string EquivalenceKey = nameof(EquivalenceKey);
public const string DeclarationsEquivalenceKey = nameof(DeclarationsEquivalenceKey);
public const string MemberAccessEquivalenceKey = nameof(MemberAccessEquivalenceKey);
public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(
IDEDiagnosticIds.PreferFrameworkTypeInDeclarationsDiagnosticId,
IDEDiagnosticIds.PreferFrameworkTypeInMemberAccessDiagnosticId);
public sealed override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(
IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId);
public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostic = context.Diagnostics[0];
var equivalenceKey = diagnostic.Properties[EquivalenceKey];
context.RegisterCodeFix(
new PreferFrameworkTypeCodeAction(
c => this.FixAsync(context.Document, context.Diagnostics[0], c),
equivalenceKey),
context.Diagnostics);
if (diagnostic.Properties.ContainsKey(PreferFrameworkTypeConstants.PreferFrameworkType))
{
context.RegisterCodeFix(
new PreferFrameworkTypeCodeAction(
c => this.FixAsync(context.Document, diagnostic, c)),
context.Diagnostics);
}
return Task.CompletedTask;
}
......@@ -60,13 +57,13 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
}
protected override bool IncludeDiagnosticDuringFixAll(FixAllState state, Diagnostic diagnostic)
=> diagnostic.Properties[EquivalenceKey] == state.CodeActionEquivalenceKey;
=> diagnostic.Properties.ContainsKey(PreferFrameworkTypeConstants.PreferFrameworkType);
private class PreferFrameworkTypeCodeAction : CodeAction.DocumentChangeAction
{
public PreferFrameworkTypeCodeAction(
Func<CancellationToken, Task<Document>> createChangedDocument, string equivalenceKey)
: base(FeaturesResources.Use_framework_type, createChangedDocument, equivalenceKey)
Func<CancellationToken, Task<Document>> createChangedDocument)
: base(FeaturesResources.Use_framework_type, createChangedDocument, FeaturesResources.Use_framework_type)
{
}
}
......
// 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;
namespace Microsoft.CodeAnalysis.PreferFrameworkType
{
internal static class PreferFrameworkTypeConstants
{
public const string PreferFrameworkType = nameof(PreferFrameworkType);
public static readonly ImmutableDictionary<string, string> Properties =
ImmutableDictionary<string, string>.Empty.Add(PreferFrameworkType, "");
}
}
// 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 Microsoft.CodeAnalysis.CodeFixes.PreferFrameworkType;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
namespace Microsoft.CodeAnalysis.Diagnostics.PreferFrameworkType
namespace Microsoft.CodeAnalysis.PreferFrameworkType
{
internal abstract class PreferFrameworkTypeDiagnosticAnalyzerBase<TSyntaxKind, TExpressionSyntax, TPredefinedTypeSyntax> :
AbstractCodeStyleDiagnosticAnalyzer
......@@ -13,13 +13,8 @@ internal abstract class PreferFrameworkTypeDiagnosticAnalyzerBase<TSyntaxKind, T
where TExpressionSyntax : SyntaxNode
where TPredefinedTypeSyntax : TExpressionSyntax
{
private static readonly ImmutableDictionary<string, string> DeclarationsEquivalenceKey = ImmutableDictionary<string, string>.Empty.Add(
PreferFrameworkTypeCodeFixProvider.EquivalenceKey, PreferFrameworkTypeCodeFixProvider.DeclarationsEquivalenceKey);
private static readonly ImmutableDictionary<string, string> MemberAccessEquivalenceKey = ImmutableDictionary<string, string>.Empty.Add(
PreferFrameworkTypeCodeFixProvider.EquivalenceKey, PreferFrameworkTypeCodeFixProvider.MemberAccessEquivalenceKey);
protected PreferFrameworkTypeDiagnosticAnalyzerBase()
: base(IDEDiagnosticIds.PreferFrameworkTypeInDeclarationsDiagnosticId,
: base(IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Use_framework_type), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Use_framework_type), FeaturesResources.ResourceManager, typeof(FeaturesResources)))
{
......@@ -87,14 +82,16 @@ protected void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
return;
}
// earlier we did a context insensitive check to see if this style was preferred in *any* context at all.
// now, we have to make a context sensitive check to see if options settings for our context requires us to report a diagnostic.
if (ShouldReportDiagnostic(predefinedTypeNode, optionSet, language,
out var severity, out var properties))
out var diagnosticSeverity))
{
context.ReportDiagnostic(DiagnosticHelper.Create(
Descriptor, predefinedTypeNode.GetLocation(),
severity, additionalLocations: null, properties));
diagnosticSeverity, additionalLocations: null,
PreferFrameworkTypeConstants.Properties));
}
}
......@@ -102,8 +99,8 @@ protected void AnalyzeNode(SyntaxNodeAnalysisContext context)
/// Detects the context of this occurrence of predefined type and determines if we should report it.
/// </summary>
private bool ShouldReportDiagnostic(
TPredefinedTypeSyntax predefinedTypeNode, OptionSet optionSet, string language,
out ReportDiagnostic severity, out ImmutableDictionary<string, string> properties)
TPredefinedTypeSyntax predefinedTypeNode, OptionSet optionSet,
string language, out ReportDiagnostic severity)
{
// we have a predefined type syntax that is either in a member access context or a declaration context.
// check the appropriate option and determine if we should report a diagnostic.
......@@ -113,7 +110,6 @@ protected void AnalyzeNode(SyntaxNodeAnalysisContext context)
var optionValue = optionSet.GetOption(option, language);
severity = optionValue.Notification.Severity;
properties = isMemberAccessOrCref ? MemberAccessEquivalenceKey : DeclarationsEquivalenceKey;
return OptionSettingPrefersFrameworkType(optionValue, severity);
}
......@@ -132,6 +128,6 @@ private bool IsFrameworkTypePreferred(OptionSet optionSet, PerLanguageOption<Cod
/// </summary>
/// <remarks>if predefined type is not preferred, it implies the preference is framework type.</remarks>
private static bool OptionSettingPrefersFrameworkType(CodeStyleOption<bool> optionValue, ReportDiagnostic severity)
=> !optionValue.Value && severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) < ReportDiagnostic.Hidden;
=> !optionValue.Value && severity != ReportDiagnostic.Suppress;
}
}
......@@ -121,19 +121,20 @@ private void AnalyzeOperation(OperationAnalysisContext context, IOperation opera
var optionValue = optionSet.GetOption(applicableOption, context.Operation.Syntax.Language);
var shouldOptionBePresent = optionValue.Value;
var isQualificationPresent = IsAlreadyQualifiedMemberAccess(simpleName);
if (shouldOptionBePresent && !isQualificationPresent)
var severity = optionValue.Notification.Severity;
if (!shouldOptionBePresent || severity == ReportDiagnostic.Suppress)
{
var severity = optionValue.Notification.Severity;
if (severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) < ReportDiagnostic.Hidden)
{
context.ReportDiagnostic(DiagnosticHelper.Create(
Descriptor,
GetLocation(operation),
severity,
additionalLocations: null,
properties: null));
}
return;
}
if (!IsAlreadyQualifiedMemberAccess(simpleName))
{
context.ReportDiagnostic(DiagnosticHelper.Create(
Descriptor,
GetLocation(operation),
severity,
additionalLocations: null,
properties: null));
}
}
......
......@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
......@@ -18,25 +19,29 @@ internal static class IndentationHelper
/// This operation will potentially split spans that cover multiple lines into separate spans.
/// </summary>
/// <param name="text"></param>
/// <param name="spans">The initial set of spans to align.</param>
/// <param name="classifiedSpans">The initial set of spans to align.</param>
/// <param name="tabSize">The number of spaces to </param>
/// <returns></returns>
public static ImmutableArray<TextSpan> GetSpansWithAlignedIndentation(
public static ImmutableArray<ClassifiedSpan> GetSpansWithAlignedIndentation(
SourceText text,
ImmutableArray<TextSpan> spans,
ImmutableArray<ClassifiedSpan> classifiedSpans,
int tabSize)
{
if (!spans.IsDefault && spans.Length > 0)
if (!classifiedSpans.IsDefault && classifiedSpans.Length > 0)
{
// We need to figure out the shortest indentation level of the exposed lines. We'll
// then remove that indentation from all lines.
var indentationColumn = DetermineIndentationColumn(text, spans, tabSize);
var indentationColumn = DetermineIndentationColumn(text, classifiedSpans, tabSize);
var adjustedSpans = new List<TextSpan>();
string spanClassificationType = null;
var adjustedClassifiedSpans = new List<ClassifiedSpan>();
for (var i = 0; i < spans.Length; i++)
for (var i = 0; i < classifiedSpans.Length; i++)
{
var span = spans[i];
var classifiedSpan = classifiedSpans[i];
spanClassificationType = classifiedSpan.ClassificationType;
var span = classifiedSpan.TextSpan;
var startLineNumber = text.Lines.GetLineFromPosition(span.Start).LineNumber;
var endLineNumber = text.Lines.GetLineFromPosition(span.End).LineNumber;
......@@ -52,7 +57,7 @@ internal static class IndentationHelper
var spanBeforeDeletion = TextSpan.FromBounds(span.Start, Math.Min(span.End, deletion.Start));
if (spanBeforeDeletion.Length > 0)
{
adjustedSpans.Add(spanBeforeDeletion);
adjustedClassifiedSpans.Add(new ClassifiedSpan(spanClassificationType, spanBeforeDeletion));
}
}
......@@ -64,28 +69,28 @@ internal static class IndentationHelper
if (span.Length > 0)
{
adjustedSpans.Add(span);
adjustedClassifiedSpans.Add(new ClassifiedSpan(spanClassificationType, span));
}
}
return adjustedSpans.ToImmutableArray();
return adjustedClassifiedSpans.ToImmutableArray();
}
else
{
return ImmutableArray<TextSpan>.Empty;
return ImmutableArray<ClassifiedSpan>.Empty;
}
}
private static int DetermineIndentationColumn(
SourceText text,
ImmutableArray<TextSpan> spans,
ImmutableArray<ClassifiedSpan> spans,
int tabSize)
{
int? indentationColumn = null;
foreach (var span in spans)
{
var startLineNumber = text.Lines.GetLineFromPosition(span.Start).LineNumber;
var endLineNumber = text.Lines.GetLineFromPosition(span.End).LineNumber;
var startLineNumber = text.Lines.GetLineFromPosition(span.TextSpan.Start).LineNumber;
var endLineNumber = text.Lines.GetLineFromPosition(span.TextSpan.End).LineNumber;
// If the span starts after the first non-whitespace of the first line, we'll
// exclude that line to avoid throwing off the calculation. Otherwise, the
......@@ -102,7 +107,7 @@ internal static class IndentationHelper
// Without throwing out the first line in the example above, the indentation column
// used will be 4, rather than 8.
var startLineFirstNonWhitespace = text.Lines[startLineNumber].GetFirstNonWhitespacePosition();
if (startLineFirstNonWhitespace.HasValue && startLineFirstNonWhitespace.Value < span.Start)
if (startLineFirstNonWhitespace.HasValue && startLineFirstNonWhitespace.Value < span.TextSpan.Start)
{
startLineNumber++;
}
......
......@@ -7,7 +7,6 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.SimplifyTypeNames;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Options;
......@@ -36,8 +35,7 @@ internal abstract partial class AbstractSimplifyTypeNamesCodeFixProvider<TSyntax
IDEDiagnosticIds.SimplifyNamesDiagnosticId,
IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId,
IDEDiagnosticIds.RemoveQualificationDiagnosticId,
IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId,
IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId);
IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId);
private SyntaxNode GetNodeToSimplify(SyntaxNode root, SemanticModel model, TextSpan span, OptionSet optionSet, out string diagnosticId, CancellationToken cancellationToken)
{
......@@ -122,7 +120,8 @@ private bool CanSimplifyTypeNameExpression(SemanticModel model, SyntaxNode node,
{
diagnosticId = null;
if (!_analyzer.IsCandidate(node) ||
!_analyzer.CanSimplifyTypeNameExpression(model, node, optionSet, out var issueSpan, out diagnosticId, cancellationToken))
!_analyzer.CanSimplifyTypeNameExpression(
model, node, optionSet, out var issueSpan, out diagnosticId, out var inDeclaration, cancellationToken))
{
return false;
}
......
......@@ -4,13 +4,14 @@
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.QualifyMemberAccess;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics.SimplifyTypeNames
namespace Microsoft.CodeAnalysis.SimplifyTypeNames
{
internal abstract class SimplifyTypeNamesDiagnosticAnalyzerBase<TLanguageKindEnum> : DiagnosticAnalyzer, IBuiltInAnalyzer where TLanguageKindEnum : struct
{
......@@ -43,32 +44,26 @@ internal abstract class SimplifyTypeNamesDiagnosticAnalyzerBase<TLanguageKindEnu
isEnabledByDefault: true,
customTags: DiagnosticCustomTags.Unnecessary);
private static readonly DiagnosticDescriptor s_descriptorPreferIntrinsicTypeInDeclarations = new DiagnosticDescriptor(IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId,
s_localizableTitleSimplifyNames,
s_localizableMessage,
DiagnosticCategory.Style,
DiagnosticSeverity.Hidden,
isEnabledByDefault: true,
customTags: DiagnosticCustomTags.Unnecessary);
private static readonly DiagnosticDescriptor s_descriptorPreferIntrinsicTypeInMemberAccess = new DiagnosticDescriptor(IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId,
s_localizableTitleSimplifyNames,
s_localizableMessage,
DiagnosticCategory.Style,
DiagnosticSeverity.Hidden,
isEnabledByDefault: true,
customTags: DiagnosticCustomTags.Unnecessary);
private static readonly DiagnosticDescriptor s_descriptorPreferBuiltinOrFrameworkType = new DiagnosticDescriptor(IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId,
s_localizableTitleSimplifyNames,
s_localizableMessage,
DiagnosticCategory.Style,
DiagnosticSeverity.Hidden,
isEnabledByDefault: true,
customTags: DiagnosticCustomTags.Unnecessary);
internal abstract bool IsCandidate(SyntaxNode node);
internal abstract bool CanSimplifyTypeNameExpression(SemanticModel model, SyntaxNode node, OptionSet optionSet, out TextSpan issueSpan, out string diagnosticId, CancellationToken cancellationToken);
internal abstract bool CanSimplifyTypeNameExpression(
SemanticModel model, SyntaxNode node, OptionSet optionSet,
out TextSpan issueSpan, out string diagnosticId, out bool inDeclaration,
CancellationToken cancellationToken);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
= ImmutableArray.Create(
s_descriptorSimplifyNames,
s_descriptorSimplifyMemberAccess,
s_descriptorRemoveThisOrMe,
s_descriptorPreferIntrinsicTypeInDeclarations,
s_descriptorPreferIntrinsicTypeInMemberAccess);
s_descriptorPreferBuiltinOrFrameworkType);
private readonly ImmutableArray<TLanguageKindEnum> _kindsOfInterest;
......@@ -98,7 +93,10 @@ public sealed override void Initialize(AnalysisContext context)
protected abstract void AnalyzeNode(SyntaxNodeAnalysisContext context);
protected abstract bool CanSimplifyTypeNameExpressionCore(SemanticModel model, SyntaxNode node, OptionSet optionSet, out TextSpan issueSpan, out string diagnosticId, CancellationToken cancellationToken);
protected abstract bool CanSimplifyTypeNameExpressionCore(
SemanticModel model, SyntaxNode node, OptionSet optionSet,
out TextSpan issueSpan, out string diagnosticId, out bool inDeclaration,
CancellationToken cancellationToken);
protected abstract string GetLanguageName();
......@@ -113,7 +111,10 @@ protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode nod
return false;
}
if (!CanSimplifyTypeNameExpressionCore(model, node, optionSet, out var issueSpan, out string diagnosticId, cancellationToken))
if (!CanSimplifyTypeNameExpressionCore(
model, node, optionSet,
out var issueSpan, out var diagnosticId, out var inDeclaration,
cancellationToken))
{
return false;
}
......@@ -142,18 +143,15 @@ protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode nod
(descriptor, severity) = GetRemoveQualificationDiagnosticDescriptor(model, node, optionSet, cancellationToken);
break;
case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId:
option = CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration;
(descriptor, severity) = GetApplicablePredefinedTypeDiagnosticDescriptor(
IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId, option, optionSet);
break;
case IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId:
option = inDeclaration
? CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration
: CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess;
descriptor = s_descriptorPreferBuiltinOrFrameworkType;
case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId:
option = CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess;
(descriptor, severity) = GetApplicablePredefinedTypeDiagnosticDescriptor(
IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId, option, optionSet);
var optionValue = optionSet.GetOption(option, GetLanguageName());
severity = optionValue.Notification.Severity;
break;
default:
throw ExceptionUtilities.UnexpectedValue(diagnosticId);
}
......@@ -171,31 +169,6 @@ protected bool TrySimplifyTypeNameExpression(SemanticModel model, SyntaxNode nod
return true;
}
private (DiagnosticDescriptor descriptor, ReportDiagnostic severity) GetApplicablePredefinedTypeDiagnosticDescriptor<T>(string id, PerLanguageOption<T> option, OptionSet optionSet) where T : CodeStyleOption<bool>
{
var optionValue = optionSet.GetOption(option, GetLanguageName());
DiagnosticDescriptor descriptor = null;
if (optionValue.Notification.Severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) < ReportDiagnostic.Hidden)
{
switch (id)
{
case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId:
descriptor = s_descriptorPreferIntrinsicTypeInDeclarations;
break;
case IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId:
descriptor = s_descriptorPreferIntrinsicTypeInMemberAccess;
break;
default:
throw ExceptionUtilities.UnexpectedValue(id);
}
}
return (descriptor, optionValue.Notification.Severity);
}
private (DiagnosticDescriptor descriptor, ReportDiagnostic severity) GetRemoveQualificationDiagnosticDescriptor(SemanticModel model, SyntaxNode node, OptionSet optionSet, CancellationToken cancellationToken)
{
var symbolInfo = model.GetSymbolInfo(node, cancellationToken);
......
// 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.Reflection;
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
......@@ -41,7 +39,7 @@ private void AnalyzeOperation(OperationAnalysisContext context)
var option = optionSet.GetOption(CodeStyleOptions.PreferExplicitTupleNames, context.Compilation.Language);
var severity = option.Notification.Severity;
if (severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) >= ReportDiagnostic.Hidden)
if (severity == ReportDiagnostic.Suppress)
{
return;
}
......
......@@ -2,7 +2,7 @@
Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Diagnostics.PreferFrameworkType
Imports Microsoft.CodeAnalysis.PreferFrameworkType
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics.Analyzers
......
......@@ -4,8 +4,8 @@ Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.CodeStyle
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Diagnostics.SimplifyTypeNames
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.SimplifyTypeNames
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
......@@ -57,11 +57,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames
Return node IsNot Nothing AndAlso IsNodeKindInteresting(node)
End Function
Protected Overrides Function CanSimplifyTypeNameExpressionCore(model As SemanticModel, node As SyntaxNode, optionSet As OptionSet, ByRef issueSpan As TextSpan, ByRef diagnosticId As String, cancellationToken As CancellationToken) As Boolean
Return CanSimplifyTypeNameExpression(model, node, optionSet, issueSpan, diagnosticId, cancellationToken)
Protected Overrides Function CanSimplifyTypeNameExpressionCore(
model As SemanticModel, node As SyntaxNode, optionSet As OptionSet,
ByRef issueSpan As TextSpan, ByRef diagnosticId As String, ByRef inDeclaration As Boolean,
cancellationToken As CancellationToken) As Boolean
Return CanSimplifyTypeNameExpression(
model, node, optionSet, issueSpan, diagnosticId, inDeclaration, cancellationToken)
End Function
Friend Overrides Function CanSimplifyTypeNameExpression(model As SemanticModel, node As SyntaxNode, optionSet As OptionSet, ByRef issueSpan As TextSpan, ByRef diagnosticId As String, cancellationToken As CancellationToken) As Boolean
Friend Overrides Function CanSimplifyTypeNameExpression(
model As SemanticModel, node As SyntaxNode, optionSet As OptionSet,
ByRef issueSpan As TextSpan, ByRef diagnosticId As String, ByRef inDeclaration As Boolean,
cancellationToken As CancellationToken) As Boolean
issueSpan = Nothing
diagnosticId = IDEDiagnosticIds.SimplifyNamesDiagnosticId
......@@ -77,9 +84,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames
' set proper diagnostic ids.
If replacementSyntax.HasAnnotations(NameOf(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration)) Then
diagnosticId = IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId
inDeclaration = True
diagnosticId = IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId
ElseIf replacementSyntax.HasAnnotations(NameOf(CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess)) Then
diagnosticId = IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId
inDeclaration = False
diagnosticId = IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId
ElseIf expression.Kind = SyntaxKind.SimpleMemberAccessExpression Then
Dim memberAccess = DirectCast(expression, MemberAccessExpressionSyntax)
Dim method = model.GetMemberGroup(expression)
......
......@@ -21,11 +21,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.SimplifyTypeNames
Protected Overrides Function GetTitle(simplifyDiagnosticId As String, nodeText As String) As String
Select Case simplifyDiagnosticId
Case IDEDiagnosticIds.SimplifyNamesDiagnosticId,
IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInDeclarationsDiagnosticId
IDEDiagnosticIds.PreferBuiltInOrFrameworkTypeDiagnosticId
Return String.Format(VBFeaturesResources.Simplify_name_0, nodeText)
Case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId,
IDEDiagnosticIds.PreferIntrinsicPredefinedTypeInMemberAccessDiagnosticId
Case IDEDiagnosticIds.SimplifyMemberAccessDiagnosticId
Return String.Format(VBFeaturesResources.Simplify_member_access_0, nodeText)
Case IDEDiagnosticIds.RemoveQualificationDiagnosticId
......
......@@ -25,6 +25,11 @@ internal sealed class AnalyzerFileWatcherService
private readonly IVsFileChangeEx _fileChangeService;
private readonly Dictionary<string, FileChangeTracker> _fileChangeTrackers = new Dictionary<string, FileChangeTracker>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Holds a list of assembly modified times that we can use to detect a file change prior to the <see cref="FileChangeTracker"/> being in place.
/// Once it's in place and subscribed, we'll remove the entry because any further changes will be detected that way.
/// </summary>
private readonly Dictionary<string, DateTime> _assemblyUpdatedTimesUtc = new Dictionary<string, DateTime>(StringComparer.OrdinalIgnoreCase);
private readonly object _guard = new object();
......@@ -47,27 +52,6 @@ internal sealed class AnalyzerFileWatcherService
_updateSource = hostDiagnosticUpdateSource;
_fileChangeService = (IVsFileChangeEx)serviceProvider.GetService(typeof(SVsFileChangeEx));
}
internal void ErrorIfAnalyzerAlreadyLoaded(ProjectId projectId, string analyzerPath)
{
DateTime loadedAssemblyUpdateTimeUtc;
lock (_guard)
{
if (!_assemblyUpdatedTimesUtc.TryGetValue(analyzerPath, out loadedAssemblyUpdateTimeUtc))
{
return;
}
}
DateTime? fileUpdateTimeUtc = GetLastUpdateTimeUtc(analyzerPath);
if (fileUpdateTimeUtc != null &&
loadedAssemblyUpdateTimeUtc != fileUpdateTimeUtc)
{
RaiseAnalyzerChangedWarning(projectId, analyzerPath);
}
}
internal void RemoveAnalyzerAlreadyLoadedDiagnostics(ProjectId projectId, string analyzerPath)
{
_updateSource.ClearDiagnosticsForProject(projectId, Tuple.Create(s_analyzerChangedErrorId, analyzerPath));
......@@ -101,7 +85,7 @@ private void RaiseAnalyzerChangedWarning(ProjectId projectId, string analyzerPat
}
}
internal void AddPath(string filePath)
internal void TrackFilePathAndReportErrorIfChanged(string filePath, ProjectId projectId)
{
lock (_guard)
{
......@@ -114,11 +98,39 @@ internal void AddPath(string filePath)
_fileChangeTrackers.Add(filePath, tracker);
}
DateTime? fileUpdateTime = GetLastUpdateTimeUtc(filePath);
DateTime assemblyUpdatedTime;
if (fileUpdateTime.HasValue)
if (_assemblyUpdatedTimesUtc.TryGetValue(filePath, out assemblyUpdatedTime))
{
DateTime? currentFileUpdateTime = GetLastUpdateTimeUtc(filePath);
if (currentFileUpdateTime != null)
{
if (currentFileUpdateTime != assemblyUpdatedTime)
{
RaiseAnalyzerChangedWarning(projectId, filePath);
}
// If the the tracker is in place, at this point we can stop checking any further for this assembly
if (tracker.PreviousCallToStartFileChangeHasAsynchronouslyCompleted)
{
_assemblyUpdatedTimesUtc.Remove(filePath);
}
}
}
else
{
_assemblyUpdatedTimesUtc[filePath] = fileUpdateTime.Value;
// We don't have an assembly updated time. This means we either haven't ever checked it, or we have a file watcher in place.
// If the file watcher is in place, then nothing further to do. Otherwise we'll add the update time to the map for future checking
if (!tracker.PreviousCallToStartFileChangeHasAsynchronouslyCompleted)
{
DateTime? currentFileUpdateTime = GetLastUpdateTimeUtc(filePath);
if (currentFileUpdateTime != null)
{
_assemblyUpdatedTimesUtc[filePath] = currentFileUpdateTime.Value;
}
}
}
}
}
......
......@@ -40,6 +40,12 @@ internal sealed class DiagnosticProgressReporter
_taskCenterService = (IVsTaskStatusCenterService)serviceProvider.GetService(typeof(SVsTaskStatusCenterService));
_diagnosticService = diagnosticService;
_options = new TaskHandlerOptions()
{
Title = ServicesVSResources.Live_code_analysis,
ActionsAfterCompletion = CompletionActions.None
};
var crawlerService = workspace.Services.GetService<ISolutionCrawlerService>();
var reporter = crawlerService.GetProgressReporter(workspace);
......@@ -48,12 +54,6 @@ internal sealed class DiagnosticProgressReporter
// no event unsubscription since it will remain alive until VS shutdown
reporter.ProgressChanged += OnSolutionCrawlerProgressChanged;
_diagnosticService.DiagnosticsUpdated += OnDiagnosticsUpdated;
_options = new TaskHandlerOptions()
{
Title = ServicesVSResources.Live_code_analysis,
ActionsAfterCompletion = CompletionActions.None
};
}
private void OnDiagnosticsUpdated(object sender, DiagnosticsUpdatedArgs e)
......
......@@ -61,8 +61,7 @@ public void AddAnalyzerReference(string analyzerAssemblyFullPath)
if (File.Exists(analyzerAssemblyFullPath))
{
GetAnalyzerFileWatcherService().AddPath(analyzerAssemblyFullPath);
GetAnalyzerFileWatcherService().ErrorIfAnalyzerAlreadyLoaded(Id, analyzerAssemblyFullPath);
GetAnalyzerFileWatcherService().TrackFilePathAndReportErrorIfChanged(analyzerAssemblyFullPath, projectId: Id);
}
else
{
......
......@@ -5,6 +5,8 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
......@@ -82,7 +84,7 @@ private class StandardTextDocument : ForegroundThreadAffinitizedObject, IVisualS
// The project system does not tell us the CodePage specified in the proj file, so
// we use null to auto-detect.
_doNotAccessDirectlyLoader = new FileTextLoader(documentKey.Moniker, defaultEncoding: null);
_doNotAccessDirectlyLoader = new FileChangeTrackingTextLoader(_fileChangeTracker, new FileTextLoader(documentKey.Moniker, defaultEncoding: null));
// If we aren't already open in the editor, then we should create a file change notification
if (openTextBuffer == null)
......@@ -135,7 +137,6 @@ public TextLoader Loader
{
get
{
_fileChangeTracker.EnsureSubscription();
return _doNotAccessDirectlyLoader;
}
}
......@@ -237,6 +238,33 @@ public uint GetItemId()
return Project.Hierarchy.TryGetItemId(_itemMoniker);
}
/// <summary>
/// A wrapper for a <see cref="TextLoader"/> that ensures we are watching file contents prior to reading the file.
/// </summary>
private sealed class FileChangeTrackingTextLoader : TextLoader
{
private readonly FileChangeTracker _fileChangeTracker;
private readonly TextLoader _innerTextLoader;
public FileChangeTrackingTextLoader(FileChangeTracker fileChangeTracker, TextLoader innerTextLoader)
{
_fileChangeTracker = fileChangeTracker;
_innerTextLoader = innerTextLoader;
}
public override Task<TextAndVersion> LoadTextAndVersionAsync(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken)
{
_fileChangeTracker.EnsureSubscription();
return _innerTextLoader.LoadTextAndVersionAsync(workspace, documentId, cancellationToken);
}
internal override TextAndVersion LoadTextAndVersionSynchronously(Workspace workspace, DocumentId documentId, CancellationToken cancellationToken)
{
_fileChangeTracker.EnsureSubscription();
return _innerTextLoader.LoadTextAndVersionSynchronously(workspace, documentId, cancellationToken);
}
}
}
}
}
......@@ -67,6 +67,18 @@ public string FilePath
get { return _filePath; }
}
/// <summary>
/// Returns true if a previous call to <see cref="StartFileChangeListeningAsync"/> has completed.
/// </summary>
public bool PreviousCallToStartFileChangeHasAsynchronouslyCompleted
{
get
{
var cookie = _fileChangeCookie;
return cookie != s_none && cookie.IsValueCreated;
}
}
public void AssertUnsubscription()
{
// We must have been disposed properly.
......
......@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Execution;
using Microsoft.CodeAnalysis.Host;
......@@ -31,7 +32,7 @@ internal partial class VisualStudioMetadataReference
internal sealed class Snapshot : PortableExecutableReference, ISupportTemporaryStorage
{
private readonly VisualStudioMetadataReferenceManager _provider;
private readonly DateTime _timestamp;
private readonly Lazy<DateTime> _timestamp;
private Exception _error;
internal Snapshot(VisualStudioMetadataReferenceManager provider, MetadataReferenceProperties properties, string fullPath)
......@@ -40,20 +41,29 @@ internal Snapshot(VisualStudioMetadataReferenceManager provider, MetadataReferen
Contract.Requires(Properties.Kind == MetadataImageKind.Assembly);
_provider = provider;
try
{
_timestamp = FileUtilities.GetFileTimeStamp(this.FilePath);
}
catch (IOException e)
{
// Reading timestamp of a file might fail.
// Let's remember the failure and report it to the compiler when it asks for metadata.
_error = e;
}
_timestamp = new Lazy<DateTime>(() => {
try
{
return FileUtilities.GetFileTimeStamp(this.FilePath);
}
catch (IOException e)
{
// Reading timestamp of a file might fail.
// Let's remember the failure and report it to the compiler when it asks for metadata.
// We could let the Lazy hold onto this (since it knows how to rethrow exceptions), but
// our support of GetStorages needs to gracefully handle the case where we have no timestamp.
// If Lazy had a "IsValueFaulted" we could be cleaner here.
_error = e;
return DateTime.MinValue;
}
}, LazyThreadSafetyMode.PublicationOnly);
}
protected override Metadata GetMetadataImpl()
{
// Fetch the timestamp first, so as to populate _error if needed
var timestamp = _timestamp.Value;
if (_error != null)
{
throw _error;
......@@ -61,7 +71,7 @@ protected override Metadata GetMetadataImpl()
try
{
return _provider.GetMetadata(this.FilePath, _timestamp);
return _provider.GetMetadata(this.FilePath, timestamp);
}
catch (Exception e) when (SaveMetadataReadingException(e))
{
......@@ -98,7 +108,7 @@ private string GetDebuggerDisplay()
public IEnumerable<ITemporaryStreamStorage> GetStorages()
{
return _provider.GetStorages(this.FilePath, _timestamp);
return _provider.GetStorages(this.FilePath, _timestamp.Value);
}
}
}
......
......@@ -48,14 +48,17 @@ void Method()
var analyzerType = typeof(CSharpUseExplicitTypeDiagnosticAnalyzer);
var analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType);
Assert.True(analyzerResult.IsEmpty);
var diagnostics = analyzerResult.SemanticLocals[analyzerResult.DocumentIds.First()];
Assert.Equal(IDEDiagnosticIds.UseExplicitTypeDiagnosticId, diagnostics[0].Id);
Assert.Equal(DiagnosticSeverity.Hidden, diagnostics[0].Severity);
// set option
workspace.Options = workspace.Options.WithChangedOption(CSharpCodeStyleOptions.UseImplicitTypeWhereApparent, new CodeStyleOption<bool>(false, NotificationOption.Suggestion));
analyzerResult = await AnalyzeAsync(workspace, workspace.CurrentSolution.ProjectIds.First(), analyzerType);
var diagnostics = analyzerResult.SemanticLocals[analyzerResult.DocumentIds.First()];
diagnostics = analyzerResult.SemanticLocals[analyzerResult.DocumentIds.First()];
Assert.Equal(IDEDiagnosticIds.UseExplicitTypeDiagnosticId, diagnostics[0].Id);
Assert.Equal(DiagnosticSeverity.Info, diagnostics[0].Severity);
}
}
......
......@@ -18,16 +18,17 @@ internal struct TypeStyleResult
private readonly CancellationToken _cancellationToken;
/// <summary>
/// Whether or not converting would transition the code to the style the user prefers. i.e.
/// if the user likes 'var' for everything, and you have 'int i = 0' then IsStylePreffered
/// will be true. however, if the user likes 'var' for everything and you have 'var i = 0',
/// then it's still possible to convert that, it would just be 'false' for IsStylePreferred
/// because it goes against the user's preferences.
///
/// In general, most features should only convert the type if IsStylePreferred is true. The
/// one exception is the refactoring, which is explicitly there to still let people convert
/// things quickly, even if it's going against their stated style.
/// Whether or not converting would transition the code to the style the user prefers. i.e. if the user likes
/// <c>var</c> for everything, and you have <c>int i = 0</c> then <see cref="IsStylePreferred"/> will be
/// <see langword="true"/>. However, if the user likes <c>var</c> for everything and you have <c>var i = 0</c>,
/// then it's still possible to convert that, it would just be <see langword="false"/> for
/// <see cref="IsStylePreferred"/> because it goes against the user's preferences.
/// </summary>
/// <remarks>
/// <para>In general, most features should only convert the type if <see cref="IsStylePreferred"/> is
/// <see langword="true"/>. The one exception is the refactoring, which is explicitly there to still let people
/// convert things quickly, even if it's going against their stated style.</para>
/// </remarks>
public readonly bool IsStylePreferred;
public readonly ReportDiagnostic Severity;
......
......@@ -98,6 +98,7 @@ public static bool TryParseNotification(string value, out NotificationOption not
notification = NotificationOption.None;
return true;
case EditorConfigSeverityStrings.Refactoring:
case EditorConfigSeverityStrings.Silent:
notification = NotificationOption.Silent;
return true;
......
......@@ -31,7 +31,7 @@ public DiagnosticSeverity Value
}
public static readonly NotificationOption None = new NotificationOption(WorkspacesResources.None, ReportDiagnostic.Suppress);
public static readonly NotificationOption Silent = new NotificationOption(WorkspacesResources.None, ReportDiagnostic.Hidden);
public static readonly NotificationOption Silent = new NotificationOption(WorkspacesResources.Refactoring_Only, ReportDiagnostic.Hidden);
public static readonly NotificationOption Suggestion = new NotificationOption(WorkspacesResources.Suggestion, ReportDiagnostic.Info);
public static readonly NotificationOption Warning = new NotificationOption(WorkspacesResources.Warning, ReportDiagnostic.Warn);
public static readonly NotificationOption Error = new NotificationOption(WorkspacesResources.Error, ReportDiagnostic.Error);
......
......@@ -416,6 +416,7 @@ internal enum FunctionId
RemoteHostService_SynchronizeTextAsync,
SymbolFinder_Solution_Pattern_FindSourceDeclarationsAsync,
SymbolFinder_Project_Pattern_FindSourceDeclarationsAsync
SymbolFinder_Project_Pattern_FindSourceDeclarationsAsync,
Intellisense_Completion_Commit,
}
}
......@@ -52,6 +52,7 @@ private static ReportDiagnostic ParseEnforcementLevel(string ruleSeverity)
case EditorConfigSeverityStrings.None:
return ReportDiagnostic.Suppress;
case EditorConfigSeverityStrings.Refactoring:
case EditorConfigSeverityStrings.Silent:
return ReportDiagnostic.Hidden;
......
......@@ -5,6 +5,7 @@ namespace Microsoft.CodeAnalysis
internal static class EditorConfigSeverityStrings
{
public const string None = "none";
public const string Refactoring = "refactoring";
public const string Silent = "silent";
public const string Suggestion = "suggestion";
public const string Warning = "warning";
......
......@@ -1052,6 +1052,15 @@ internal class WorkspacesResources {
}
}
/// <summary>
/// Looks up a localized string similar to Refactoring Only.
/// </summary>
internal static string Refactoring_Only {
get {
return ResourceManager.GetString("Refactoring_Only", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Removed:.
/// </summary>
......
......@@ -616,4 +616,7 @@
<data name="Changing_document_property_is_not_supported" xml:space="preserve">
<value>Changing document properties is not supported</value>
</data>
<data name="Refactoring_Only" xml:space="preserve">
<value>Refactoring Only</value>
</data>
</root>
\ No newline at end of file
......@@ -7,6 +7,11 @@
<target state="translated">Došlo k chybě při čtení zadaného konfiguračního souboru: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">Symbol {0} nepochází ze zdroje.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">Beim Lesen der angegebenen Konfigurationsdatei ist ein Fehler aufgetreten: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">Symbol "{0}" ist nicht aus Quelle.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">Error al leer el archivo de configuración especificado: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">El símbolo "{0}" no procede del código fuente.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">Une erreur s'est produite lors de la lecture du fichier de configuration spécifié : {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">Le symbole "{0}" ne provient pas de la source.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">Si è verificato un errore durante la lettura del file di configurazione specificato: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">Il simbolo "{0}" non proviene dall'origine.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">指定した構成ファイルの読み取り中にエラーが発生しました: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">シンボル "{0}" は、ソースからではありません。</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">지정한 구성 파일을 읽는 동안 오류가 발생했습니다({0}).</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">"{0}" 기호가 소스에 없습니다.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">Wystąpił błąd podczas odczytywania określonego pliku konfiguracji: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">Symbol „{0}” nie pochodzi ze źródła.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">Ocorreu um erro ao ler o arquivo de configuração especificado: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">Símbolo "{0}" não é da fonte.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">Произошла ошибка при чтении указанного файла конфигурации: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">Символ "{0}" не из источника.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">Belirtilen yapılandırma dosyası okunurken bir hata oluştu: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">"{0}" sembolü kaynağa ait değil.</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">读取指定的配置文件时出错: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">符号“{0}”不是来自源。</target>
......
......@@ -7,6 +7,11 @@
<target state="translated">讀取指定的組態檔時發生錯誤: {0}</target>
<note />
</trans-unit>
<trans-unit id="Refactoring_Only">
<source>Refactoring Only</source>
<target state="new">Refactoring Only</target>
<note />
</trans-unit>
<trans-unit id="Symbol_0_is_not_from_source">
<source>Symbol "{0}" is not from source.</source>
<target state="translated">符號 "{0}" 非來自來源。</target>
......
......@@ -14,12 +14,14 @@ public class EditorConfigCodeStyleParserTests
{
[Theory]
[InlineData("true:none", true, ReportDiagnostic.Suppress)]
[InlineData("true:refactoring", true, ReportDiagnostic.Hidden)]
[InlineData("true:silent", true, ReportDiagnostic.Hidden)]
[InlineData("true:suggestion", true, ReportDiagnostic.Info)]
[InlineData("true:warning", true, ReportDiagnostic.Warn)]
[InlineData("true:error", true, ReportDiagnostic.Error)]
[InlineData("true", false, ReportDiagnostic.Hidden)]
[InlineData("false:none", false, ReportDiagnostic.Suppress)]
[InlineData("false:refactoring", false, ReportDiagnostic.Hidden)]
[InlineData("false:silent", false, ReportDiagnostic.Hidden)]
[InlineData("false:suggestion", false, ReportDiagnostic.Info)]
[InlineData("false:warning", false, ReportDiagnostic.Warn)]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册