public void FormatSpan(SnapshotSpan span) { // Formatting a snippet isn't cancellable. var cancellationToken = CancellationToken.None; // At this point, the $selection$ token has been replaced with the selected text and // declarations have been replaced with their default text. We need to format the // inserted snippet text while carefully handling $end$ position (where the caret goes // after Return is pressed). The IExpansionSession keeps a tracking point for this // position but we do the tracking ourselves to properly deal with virtual space. To // ensure the end location is correct, we take three extra steps: // 1. Insert an empty comment ("/**/" or "'") at the current $end$ position (prior // to formatting), and keep a tracking span for the comment. // 2. After formatting the new snippet text, find and delete the empty multiline // comment (via the tracking span) and notify the IExpansionSession of the new // $end$ location. If the line then contains only whitespace (due to the formatter // putting the empty comment on its own line), then delete the white space and // remember the indentation depth for that line. // 3. When the snippet is finally completed (via Return), and PositionCaretForEditing() // is called, check to see if the end location was on a line containing only white // space in the previous step. If so, and if that line is still empty, then position // the caret in virtual space. // This technique ensures that a snippet like "if($condition$) { $end$ }" will end up // as: // if ($condition$) // { // $end$ // } if (!TryGetSubjectBufferSpan(span, out var snippetSpan)) { return; } // Insert empty comment and track end position var snippetTrackingSpan = snippetSpan.CreateTrackingSpan(SpanTrackingMode.EdgeInclusive); var fullSnippetSpan = ExpansionSession.GetSnippetSpan(); var isFullSnippetFormat = fullSnippetSpan == span; var endPositionTrackingSpan = isFullSnippetFormat ? InsertEmptyCommentAndGetEndPositionTrackingSpan() : null; var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(SubjectBuffer.CurrentSnapshot, snippetTrackingSpan.GetSpan(SubjectBuffer.CurrentSnapshot)); SubjectBuffer.CurrentSnapshot.FormatAndApplyToBuffer(formattingSpan, CancellationToken.None); if (isFullSnippetFormat) { CleanUpEndLocation(endPositionTrackingSpan); // Unfortunately, this is the only place we can safely add references and imports // specified in the snippet xml. In OnBeforeInsertion we have no guarantee that the // snippet xml will be available, and changing the buffer during OnAfterInsertion can // cause the underlying tracking spans to get out of sync. var currentStartPosition = snippetTrackingSpan.GetStartPoint(SubjectBuffer.CurrentSnapshot).Position; AddReferencesAndImports( ExpansionSession, currentStartPosition, cancellationToken); SetNewEndPosition(endPositionTrackingSpan); } }
public async Task <ImmutableArray <TextChange> > GetFormattingChangesOnPasteAsync( Document document, TextSpan textSpan, DocumentOptionSet?documentOptions, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, textSpan); var service = document.GetRequiredLanguageService <ISyntaxFormattingService>(); var rules = new List <AbstractFormattingRule>() { new PasteFormattingRule() }; rules.AddRange(service.GetDefaultFormattingRules()); if (documentOptions == null) { var inferredIndentationService = document.Project.Solution.Workspace.Services.GetRequiredService <IInferredIndentationService>(); documentOptions = await inferredIndentationService.GetDocumentOptionsWithInferredIndentationAsync(document, explicitFormat : false, cancellationToken : cancellationToken).ConfigureAwait(false); } var formattingOptions = SyntaxFormattingOptions.Create(documentOptions, document.Project.Solution.Workspace.Services, document.Project.Language); var result = service.GetFormattingResult(root, SpecializedCollections.SingletonEnumerable(formattingSpan), formattingOptions, rules, cancellationToken); return(result.GetTextChanges(cancellationToken).ToImmutableArray()); }
protected static async Task <LSP.TextEdit[]?> GetTextEditsAsync( RequestContext context, LSP.FormattingOptions options, IGlobalOptionService globalOptions, CancellationToken cancellationToken, LSP.Range?range = null) { var document = context.Document; if (document == null) { return(null); } var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var rangeSpan = (range != null) ? ProtocolConversions.RangeToTextSpan(range, text) : new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, rangeSpan); // We should use the options passed in by LSP instead of the document's options. var formattingOptions = await ProtocolConversions.GetFormattingOptionsAsync(options, document, globalOptions, cancellationToken).ConfigureAwait(false); var services = document.Project.Solution.Services; var textChanges = Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), services, formattingOptions, rules: null, cancellationToken); var edits = new ArrayBuilder <LSP.TextEdit>(); edits.AddRange(textChanges.Select(change => ProtocolConversions.TextChangeToTextEdit(change, text))); return(edits.ToArrayAndFree()); }
public int GetIndentationOfCurrentPosition( SyntaxNode root, IndentBlockOperation startingOperation, Func <SyntaxToken, int> tokenColumnGetter, CancellationToken cancellationToken) { var token = startingOperation.StartToken; // gather all indent operations var list = GetParentIndentBlockOperations(token); // remove one that is smaller than current one for (int i = list.Count - 1; i >= 0; i--) { if (CommonFormattingHelpers.IndentBlockOperationComparer(startingOperation, list[i]) < 0) { list.RemoveAt(i); } else { break; } } return(GetIndentationOfCurrentPosition(root, token, list, token.SpanStart, /* extraSpaces */ 0, tokenColumnGetter, cancellationToken)); }
public Task <Document> FormatAsync(Document document, ImmutableArray <TextSpan> changes, CancellationToken cancellationToken) { var root = document.GetSyntaxRootSynchronously(cancellationToken); var formattingSpans = changes.Select(s => CommonFormattingHelpers.GetFormattingSpan(root, s)); return(Formatter.FormatAsync(document, formattingSpans, cancellationToken: cancellationToken)); }
public Document Format(Document document, IEnumerable <TextSpan> changes, CancellationToken cancellationToken) { var root = document.GetSyntaxRootSynchronously(cancellationToken); var formattingSpans = changes.Select(s => CommonFormattingHelpers.GetFormattingSpan(root, s)); return(Formatter.FormatAsync(document, formattingSpans, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken)); }
public override AdjustSpacesOperation GetAdjustSpacesOperation(SyntaxToken previousToken, SyntaxToken currentToken, OptionSet optionSet, NextOperation <AdjustSpacesOperation> nextOperation) { var operation = nextOperation.Invoke(); if (operation == null) { return(null); } // if operation is already forced, return as it is. if (operation.Option == AdjustSpacesOption.ForceSpaces) { return(operation); } if (CommonFormattingHelpers.HasAnyWhitespaceElasticTrivia(previousToken, currentToken)) { // current implementation of engine gives higher priority on new line operations over space operations if // two are conflicting. // ex) new line operation says add 1 line between tokens, and // space operation says give 1 space between two tokens (basically means remove new lines) // then, engine will pick new line operation and ignore space operation // make every operation forced return(CreateAdjustSpacesOperation(Math.Max(0, operation.Space), AdjustSpacesOption.ForceSpaces)); } return(operation); }
private void AdjustIndentationForSpan( Document document, ITextEdit edit, TextSpan visibleSpan, IFormattingRule baseIndentationRule, OptionSet options) { var root = document.GetSyntaxRootAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None); using (var rulePool = SharedPools.Default <List <IFormattingRule> >().GetPooledObject()) using (var spanPool = SharedPools.Default <List <TextSpan> >().GetPooledObject()) { var venusFormattingRules = rulePool.Object; var visibleSpans = spanPool.Object; venusFormattingRules.Add(baseIndentationRule); venusFormattingRules.Add(ContainedDocumentPreserveFormattingRule.Instance); var formattingRules = venusFormattingRules.Concat(Formatter.GetDefaultFormattingRules(document)); var workspace = document.Project.Solution.Workspace; var changes = Formatter.GetFormattedTextChanges( root, new TextSpan[] { CommonFormattingHelpers.GetFormattingSpan(root, visibleSpan) }, workspace, options, formattingRules, CancellationToken.None); visibleSpans.Add(visibleSpan); var newChanges = FilterTextChanges(document.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None), visibleSpans, changes.ToReadOnlyCollection()).Where(t => visibleSpan.Contains(t.Span)); foreach (var change in newChanges) { edit.Replace(change.Span.ToSpan(), change.NewText); } } }
public override string GetTextBetween(SyntaxToken token1, SyntaxToken token2) { var builder = StringBuilderPool.Allocate(); CommonFormattingHelpers.AppendTextBetween(token1, token2, builder); return(StringBuilderPool.ReturnAndFree(builder)); }
public override AdjustNewLinesOperation GetAdjustNewLinesOperation(SyntaxToken previousToken, SyntaxToken currentToken, OptionSet optionSet, NextOperation <AdjustNewLinesOperation> nextOperation) { var operation = nextOperation.Invoke(); if (operation == null) { // If there are more than one Type Parameter Constraint Clause then each go in separate line if (CommonFormattingHelpers.HasAnyWhitespaceElasticTrivia(previousToken, currentToken) && currentToken.IsKind(SyntaxKind.WhereKeyword) && currentToken.Parent.IsKind(SyntaxKind.TypeParameterConstraintClause)) { // Check if there is another TypeParameterConstraintClause before if (previousToken.Parent.Ancestors().OfType <TypeParameterConstraintClauseSyntax>().Any()) { return(CreateAdjustNewLinesOperation(1, AdjustNewLinesOption.PreserveLines)); } // Check if there is another TypeParameterConstraintClause after var firstTokenAfterTypeConstraint = currentToken.Parent.GetLastToken().GetNextToken(); var lastTokenForTypeConstraint = currentToken.Parent.GetLastToken().GetNextToken(); if (CommonFormattingHelpers.HasAnyWhitespaceElasticTrivia(lastTokenForTypeConstraint, firstTokenAfterTypeConstraint) && firstTokenAfterTypeConstraint.IsKind(SyntaxKind.WhereKeyword) && firstTokenAfterTypeConstraint.Parent.IsKind(SyntaxKind.TypeParameterConstraintClause)) { return(CreateAdjustNewLinesOperation(1, AdjustNewLinesOption.PreserveLines)); } } return(null); } // if operation is already forced, return as it is. if (operation.Option == AdjustNewLinesOption.ForceLines) { return(operation); } if (!CommonFormattingHelpers.HasAnyWhitespaceElasticTrivia(previousToken, currentToken)) { return(operation); } var betweenMemberOperation = GetAdjustNewLinesOperationBetweenMembers(previousToken, currentToken); if (betweenMemberOperation != null) { return(betweenMemberOperation); } var line = Math.Max(LineBreaksAfter(previousToken, currentToken), operation.Line); if (line == 0) { return(CreateAdjustNewLinesOperation(0, AdjustNewLinesOption.PreserveLines)); } return(CreateAdjustNewLinesOperation(line, AdjustNewLinesOption.ForceLines)); }
public async Task <IList <TextChange> > GetFormattingChangesAsync(Document document, TextSpan?textSpan, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = textSpan.HasValue ? textSpan.Value : new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); return(Formatter.GetFormattedTextChanges(root, new TextSpan[] { formattingSpan }, document.Project.Solution.Workspace, cancellationToken: cancellationToken)); }
public Document Format(Document document, IEnumerable <TextSpan> changes, CancellationToken cancellationToken) { var snapshot = document.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).FindCorrespondingEditorTextSnapshot(); var root = document.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); var formattingSpans = changes.Select(s => s.ToSnapshotSpan(snapshot)) .Select(s => CommonFormattingHelpers.GetFormattingSpan(root, s.Span.ToTextSpan())); return(Formatter.FormatAsync(document, formattingSpans, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken)); }
public static bool AreTwoTokensOnSameLine(SyntaxToken token1, SyntaxToken token2) { var tree = token1.SyntaxTree; if (tree != null && tree.TryGetText(out var text)) { return(text.AreOnSameLine(token1, token2)); } return(CommonFormattingHelpers.GetTextBetween(token1, token2).ContainsLineBreak()); }
public async Task<IList<TextChange>> GetFormattingChangesAsync(Document document, TextSpan? textSpan, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var span = textSpan ?? new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); return Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), document.Project.Solution.Workspace, options, cancellationToken); }
public async Task <IList <TextChange> > GetFormattingChangesAsync(Document document, TextSpan?textSpan, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = textSpan ?? new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); var options = await document.GetDocumentOptionsWithInferredIndentationAsync(explicitFormat : true, indentationManagerService : _indentationManagerService, cancellationToken : cancellationToken).ConfigureAwait(false); return(Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), document.Project.Solution.Workspace, options, cancellationToken)); }
private void AddChangeSignatureIndentOperation(List <IndentBlockOperation> list, SyntaxNode node) { if (node.Parent != null) { var baseToken = node.Parent.GetFirstToken(); var startToken = node.GetFirstToken(); var endToken = node.GetLastToken(); var span = CommonFormattingHelpers.GetSpanIncludingTrailingAndLeadingTriviaOfAdjacentTokens(startToken, endToken); span = TextSpan.FromBounds(Math.Max(baseToken.Span.End, span.Start), span.End); list.Add(FormattingOperations.CreateRelativeIndentBlockOperation(baseToken, startToken, endToken, span, indentationDelta: 1, option: IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine)); } }
public Task <ImmutableArray <TextChange> > GetFormattingChangesAsync( Document document, ITextBuffer textBuffer, TextSpan?textSpan, CancellationToken cancellationToken) { var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken); var options = textBuffer.GetSyntaxFormattingOptions(_editorOptionsService, parsedDocument.LanguageServices, explicitFormat: true); var span = textSpan ?? new TextSpan(0, parsedDocument.Root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(parsedDocument.Root, span); return(Task.FromResult(Formatter.GetFormattedTextChanges(parsedDocument.Root, SpecializedCollections.SingletonEnumerable(formattingSpan), document.Project.Solution.Services, options, cancellationToken).ToImmutableArray())); }
private static bool AreTwoTokensOnSameLine(SyntaxToken token1, SyntaxToken token2) { var tree = token1.SyntaxTree; var text = default(SourceText); if (tree != null && tree.TryGetText(out text)) { var line1 = text.Lines.IndexOf(token1.Span.End); var line2 = text.Lines.IndexOf(token2.SpanStart); return(line1 == line2); } return(CommonFormattingHelpers.GetTextBetween(token1, token2).GetNumberOfLineBreaks() == 0); }
public async Task <ImmutableArray <TextChange> > GetFormattingChangesAsync( Document document, TextSpan?textSpan, CancellationToken cancellationToken) { var options = await _indentationManager.GetInferredFormattingOptionsAsync(document, explicitFormat : true, cancellationToken).ConfigureAwait(false); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = textSpan ?? new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); var services = document.Project.Solution.Workspace.Services; return(Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), services, options, cancellationToken).ToImmutableArray()); }
public AbstractComplexTrivia(OptionSet optionSet, TreeData treeInfo, SyntaxToken token1, SyntaxToken token2) : base(optionSet, token1.Language) { Contract.ThrowIfNull(treeInfo); _token1 = token1; _token2 = token2; _treatAsElastic = CommonFormattingHelpers.HasAnyWhitespaceElasticTrivia(token1, token2); this.TreeInfo = treeInfo; this.OriginalString = this.TreeInfo.GetTextBetween(token1, token2); ExtractLineAndSpace(this.OriginalString, out var lineBreaks, out var spaces); this.LineBreaks = lineBreaks; this.Spaces = spaces; }
public async Task<IList<TextChange>> GetFormattingChangesOnPasteAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, textSpan); var service = document.GetLanguageService<ISyntaxFormattingService>(); if (service == null) { return SpecializedCollections.EmptyList<TextChange>(); } var rules = new List<IFormattingRule>() { new PasteFormattingRule() }; rules.AddRange(service.GetDefaultFormattingRules()); return Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), document.Project.Solution.Workspace, options, rules, cancellationToken); }
private void ApplyEdits(Document document, ITextView textView, ITextBuffer subjectBuffer, string title, CommentSelectionResult edits, CancellationToken cancellationToken) { var originalSnapshot = subjectBuffer.CurrentSnapshot; // Apply the text changes. using (var transaction = new CaretPreservingEditTransaction(title, textView, _undoHistoryRegistry, _editorOperationsFactoryService)) { subjectBuffer.ApplyChanges(edits.TextChanges); transaction.Complete(); } if (edits.TrackingSpans.Any()) { // Create tracking spans to track the text changes. var trackingSpans = edits.TrackingSpans .SelectAsArray(textSpan => (originalSpan: textSpan, trackingSpan: CreateTrackingSpan(edits.ResultOperation, originalSnapshot, textSpan.TrackingTextSpan))); // Convert the tracking spans into snapshot spans for formatting and selection. var trackingSnapshotSpans = trackingSpans.Select(s => CreateSnapshotSpan(subjectBuffer.CurrentSnapshot, s.trackingSpan, s.originalSpan)); if (edits.ResultOperation == Operation.Uncomment && document.SupportsSyntaxTree) { // Format the document only during uncomment operations. Use second transaction so it can be undone. using var transaction = new CaretPreservingEditTransaction(title, textView, _undoHistoryRegistry, _editorOperationsFactoryService); var newText = subjectBuffer.CurrentSnapshot.AsText(); var oldSyntaxTree = document.GetSyntaxTreeSynchronously(cancellationToken); var newRoot = oldSyntaxTree.WithChangedText(newText).GetRoot(cancellationToken); var formattingOptions = subjectBuffer.GetSyntaxFormattingOptions(_editorOptionsService, document.Project.LanguageServices, explicitFormat: false); var formattingSpans = trackingSnapshotSpans.Select(change => CommonFormattingHelpers.GetFormattingSpan(newRoot, change.Span.ToTextSpan())); var formattedChanges = Formatter.GetFormattedTextChanges(newRoot, formattingSpans, document.Project.Solution.Services, formattingOptions, rules: null, cancellationToken); subjectBuffer.ApplyChanges(formattedChanges); transaction.Complete(); } // Set the multi selection after edits have been applied. textView.SetMultiSelection(trackingSnapshotSpans); } }
private void AddSwitchIndentationOperation(List <IndentBlockOperation> list, SyntaxNode node, OptionSet optionSet) { var section = node as SwitchSectionSyntax; if (section == null || !optionSet.GetOption(CSharpFormattingOptions.IndentSwitchCaseSection)) { return; } // can this ever happen? if (section.Labels.Count == 0 && section.Statements.Count == 0) { return; } // see whether we are the last statement var switchStatement = node.Parent as SwitchStatementSyntax; var lastSection = switchStatement.Sections.Last() == node; if (section.Statements.Count == 0) { // even if there is no statement under section, we still want indent operation var lastTokenOfLabel = section.Labels.Last().GetLastToken(includeZeroWidth: true); var nextToken = lastTokenOfLabel.GetNextToken(includeZeroWidth: true); AddIndentBlockOperation(list, lastTokenOfLabel, lastTokenOfLabel, lastSection ? TextSpan.FromBounds(lastTokenOfLabel.FullSpan.End, nextToken.SpanStart) : TextSpan.FromBounds(lastTokenOfLabel.FullSpan.End, lastTokenOfLabel.FullSpan.End)); return; } var startToken = section.Statements.First().GetFirstToken(includeZeroWidth: true); var endToken = section.Statements.Last().GetLastToken(includeZeroWidth: true); // see whether we are the last statement var span = CommonFormattingHelpers.GetSpanIncludingTrailingAndLeadingTriviaOfAdjacentTokens(startToken, endToken); span = lastSection ? span : TextSpan.FromBounds(span.Start, endToken.FullSpan.End); AddIndentBlockOperation(list, startToken, endToken, span); }
protected void RemoveIndentBlockOperation( List <IndentBlockOperation> list, SyntaxToken startToken, SyntaxToken endToken) { if (startToken.CSharpKind() == SyntaxKind.None || endToken.CSharpKind() == SyntaxKind.None) { return; } var span = CommonFormattingHelpers.GetSpanIncludingTrailingAndLeadingTriviaOfAdjacentTokens(startToken, endToken); for (int i = 0; i < list.Count; i++) { if (list[i] != null && list[i].TextSpan == span) { list[i] = null; return; } } }
protected static void AddUnindentBlockOperation( List <IndentBlockOperation> list, SyntaxToken startToken, SyntaxToken endToken, bool includeTriviaAtEnd = false, IndentBlockOption option = IndentBlockOption.RelativePosition ) { if (startToken.Kind() == SyntaxKind.None || endToken.Kind() == SyntaxKind.None) { return; } if (includeTriviaAtEnd) { list.Add( FormattingOperations.CreateIndentBlockOperation( startToken, endToken, indentationDelta: -1, option: option ) ); } else { var startPosition = CommonFormattingHelpers.GetStartPositionOfSpan(startToken); var endPosition = endToken.Span.End; list.Add( FormattingOperations.CreateIndentBlockOperation( startToken, endToken, TextSpan.FromBounds(startPosition, endPosition), indentationDelta: -1, option: option ) ); } }
public async Task <ImmutableArray <TextChange> > GetFormattingChangesAsync( Document document, TextSpan?textSpan, DocumentOptionSet?documentOptions, CancellationToken cancellationToken) { var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var span = textSpan ?? new TextSpan(0, root.FullSpan.Length); var formattingSpan = CommonFormattingHelpers.GetFormattingSpan(root, span); if (documentOptions == null) { var inferredIndentationService = document.Project.Solution.Workspace.Services.GetRequiredService <IInferredIndentationService>(); documentOptions = await inferredIndentationService.GetDocumentOptionsWithInferredIndentationAsync(document, explicitFormat : true, cancellationToken : cancellationToken).ConfigureAwait(false); } var services = document.Project.Solution.Workspace.Services; var formattingOptions = SyntaxFormattingOptions.Create(documentOptions, services, document.Project.Language); return(Formatter.GetFormattedTextChanges(root, SpecializedCollections.SingletonEnumerable(formattingSpan), services, formattingOptions, cancellationToken).ToImmutableArray()); }
private void AddSwitchIndentationOperation(List <IndentBlockOperation> list, SyntaxNode node, OptionSet optionSet) { var section = node as SwitchSectionSyntax; if (section == null) { return; } // can this ever happen? if (section.Labels.Count == 0 && section.Statements.Count == 0) { return; } var indentSwitchCase = optionSet.GetOption(CSharpFormattingOptions.IndentSwitchCaseSection); var indentSwitchCaseWhenBlock = optionSet.GetOption(CSharpFormattingOptions.IndentSwitchCaseSectionWhenBlock); if (!indentSwitchCase && !indentSwitchCaseWhenBlock) { // Never indent return; } var alwaysIndent = indentSwitchCase && indentSwitchCaseWhenBlock; if (!alwaysIndent) { // Only one of these values can be true at this point. Debug.Assert(indentSwitchCase != indentSwitchCaseWhenBlock); var firstStatementIsBlock = section.Statements.Count > 0 && section.Statements[0].IsKind(SyntaxKind.Block); if (indentSwitchCaseWhenBlock != firstStatementIsBlock) { return; } } // see whether we are the last statement var switchStatement = node.Parent as SwitchStatementSyntax; var lastSection = switchStatement.Sections.Last() == node; if (section.Statements.Count == 0) { // even if there is no statement under section, we still want indent operation var lastTokenOfLabel = section.Labels.Last().GetLastToken(includeZeroWidth: true); var nextToken = lastTokenOfLabel.GetNextToken(includeZeroWidth: true); AddIndentBlockOperation(list, lastTokenOfLabel, lastTokenOfLabel, lastSection ? TextSpan.FromBounds(lastTokenOfLabel.FullSpan.End, nextToken.SpanStart) : TextSpan.FromBounds(lastTokenOfLabel.FullSpan.End, lastTokenOfLabel.FullSpan.End)); return; } var startToken = section.Statements.First().GetFirstToken(includeZeroWidth: true); var endToken = section.Statements.Last().GetLastToken(includeZeroWidth: true); // see whether we are the last statement var span = CommonFormattingHelpers.GetSpanIncludingTrailingAndLeadingTriviaOfAdjacentTokens(startToken, endToken); span = lastSection ? span : TextSpan.FromBounds(span.Start, endToken.FullSpan.End); AddIndentBlockOperation(list, startToken, endToken, span); }
/// <summary> /// create indent block region around the start and end token with the given indentation delta added to the column of the base token /// </summary> public static IndentBlockOperation CreateRelativeIndentBlockOperation(SyntaxToken baseToken, SyntaxToken startToken, SyntaxToken endToken, int indentationDelta, IndentBlockOption option) { var span = CommonFormattingHelpers.GetSpanIncludingTrailingAndLeadingTriviaOfAdjacentTokens(startToken, endToken); return(CreateRelativeIndentBlockOperation(baseToken, startToken, endToken, span, indentationDelta, option)); }