提交 2588515f 编写于 作者: B Basoundr_ms

Bugfix 987373

Introduce an option, ShouldUseFormattingSpanCollapse,  to tell the formatting engine if it should collapse the formatting spans if there are more than 30 spans to be formatted(Collapsing involes taking the a bunch of spans and returning one span whose startingPoint is startingPoint of the first span and the ending point is the endpoint of the last span in the bunch). The default value is to not collapse

There are few CodeFix Provider which act on the whole document for which the formatting engine will collapse the spans to one span.

In order  to improve telemetry, I have introduced some new CodeActions instead of using the generic Document/SolutionChangeCodeAction (changeset 1317739)
上级 7014b8bc
......@@ -41,15 +41,15 @@ public IFormattingResult Format(SyntaxNode node, IEnumerable<TextSpan> spans, Op
}
// check what kind of formatting strategy to use
if (ShouldUseCollapsedFormattingSpan(spansToFormat))
if (AllowDisjointSpanMerging(spansToFormat, options.GetOption(FormattingOptions.AllowDisjointSpanMerging)))
{
return FormatCollapsedSpan(node, options, rules, spansToFormat, cancellationToken);
return FormatMergedSpan(node, options, rules, spansToFormat, cancellationToken);
}
return FormatIndividually(node, options, rules, spansToFormat, cancellationToken);
}
private IFormattingResult FormatCollapsedSpan(
private IFormattingResult FormatMergedSpan(
SyntaxNode node, OptionSet options, IEnumerable<IFormattingRule> rules, IList<TextSpan> spansToFormat, CancellationToken cancellationToken)
{
var spanToFormat = TextSpan.FromBounds(spansToFormat[0].Start, spansToFormat[spansToFormat.Count - 1].End);
......@@ -62,7 +62,7 @@ public IFormattingResult Format(SyntaxNode node, IEnumerable<TextSpan> spans, Op
// more expensive case
var result = Format(node, options, rules, pair.Item1, pair.Item2, cancellationToken);
return CreateAggregatedFormattingResult(node, new List<AbstractFormattingResult>(1) { result }, SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance, spansToFormat));
return CreateAggregatedFormattingResult(node, new List<AbstractFormattingResult>(1) { result }, SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance, spanToFormat));
}
private IFormattingResult FormatIndividually(
......@@ -95,8 +95,14 @@ public IFormattingResult Format(SyntaxNode node, IEnumerable<TextSpan> spans, Op
return CreateAggregatedFormattingResult(node, results);
}
private bool ShouldUseCollapsedFormattingSpan(IList<TextSpan> list)
private bool AllowDisjointSpanMerging(IList<TextSpan> list, bool shouldUseFormattingSpanCollapse)
{
// If the user is specific about the formatting specific spans then honor users settings
if (!shouldUseFormattingSpanCollapse)
{
return false;
}
// most common case. it is either just formatting a whole file, a selection or some generate XXX refactoring.
if (list.Count <= 3)
{
......
......@@ -8,6 +8,7 @@ public static class FormattingOptions
{
internal const string TabFeatureName = "Tab";
internal const string InternalTabFeatureName = "InternalTab";
internal const string FormattingFeatureName = "Formatting";
// All Languages
#if MEF
......@@ -28,7 +29,7 @@ public static class FormattingOptions
#if MEF
[ExportOption]
#endif
public static readonly PerLanguageOption<IndentStyle> SmartIndent = new PerLanguageOption<IndentStyle>(TabFeatureName, "SmartIndent", defaultValue: IndentStyle.Smart);
public static readonly PerLanguageOption<IndentStyle> SmartIndent = new PerLanguageOption<IndentStyle>(FormattingFeatureName, "SmartIndent", defaultValue: IndentStyle.Smart);
#if MEF
[ExportOption]
......@@ -38,12 +39,17 @@ public static class FormattingOptions
#if MEF
[ExportOption]
#endif
public static readonly PerLanguageOption<string> NewLine = new PerLanguageOption<string>(TabFeatureName, "NewLine", defaultValue: "\r\n");
public static readonly PerLanguageOption<string> NewLine = new PerLanguageOption<string>(FormattingFeatureName, "NewLine", defaultValue: "\r\n");
#if MEF
[ExportOption]
#endif
internal static readonly PerLanguageOption<bool> DebugMode = new PerLanguageOption<bool>(InternalTabFeatureName, "DebugMode", defaultValue: false);
internal static readonly PerLanguageOption<bool> DebugMode = new PerLanguageOption<bool>(FormattingFeatureName, "DebugMode", defaultValue: false);
#if MEF
[ExportOption]
#endif
internal static readonly Option<bool> AllowDisjointSpanMerging = new Option<bool>(FormattingFeatureName, "ShouldUseFormattingSpanCollapse", defaultValue: false);
public enum IndentStyle
{
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
namespace Microsoft.CodeAnalysis.Simplification
{
internal class SimplifyTypeNameCodeAction : CodeAction
{
private readonly string title;
private readonly Func<CancellationToken, Task<Document>> createChangedDocument;
public SimplifyTypeNameCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument)
{
this.title = title;
this.createChangedDocument = createChangedDocument;
}
public override string Title
{
get { return this.title; }
}
protected override Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
{
return this.createChangedDocument(cancellationToken);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CaseCorrection;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Formatting;
namespace Microsoft.CodeAnalysis.Simplification
{
internal class SimplifyTypeNameFixAllCodeAction : CodeAction
{
private readonly string title;
private readonly Func<CancellationToken, Task<Document>> createChangedDocument;
public SimplifyTypeNameFixAllCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument)
{
this.title = title;
this.createChangedDocument = createChangedDocument;
}
public override string Title
{
get { return this.title; }
}
protected override Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
{
return this.createChangedDocument(cancellationToken);
}
protected override async Task<Document> PostProcessChangesAsync(Document document, CancellationToken cancellationToken)
{
var optionSet = document.Project.Solution.Workspace.Options.WithChangedOption(FormattingOptions.AllowDisjointSpanMerging, true);
document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false);
document = await Formatter.FormatAsync(document, Formatter.Annotation, optionSet, cancellationToken: cancellationToken).ConfigureAwait(false);
document = await CaseCorrector.CaseCorrectAsync(document, CaseCorrector.Annotation, cancellationToken).ConfigureAwait(false);
return document;
}
}
}
......@@ -348,6 +348,8 @@
<Compile Include="Log\KeyValueLogMessage.cs" />
<Compile Include="Log\Logger.LogBlock.cs" />
<Compile Include="Log\LogMessage.cs" />
<Compile Include="Simplification\SimplifyTypeNameCodeAction.cs" />
<Compile Include="Simplification\SimplifyTypeNameFixAllCodeAction.cs" />
<Compile Include="Utilities\WeakEventHandler.cs" />
<Compile Include="Workspace\Host\Caching\AbstractCacheServiceFactory.cs" />
<Compile Include="Workspace\Host\Caching\CacheOptions.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册