public CallExpressionCodeActionComputer( AbstractChainedExpressionWrapper <TNameSyntax, TBaseArgumentListSyntax> service, Document document, SourceText originalSourceText, SyntaxWrappingOptions options, ImmutableArray <ImmutableArray <SyntaxNodeOrToken> > chunks, CancellationToken cancellationToken) : base(service, document, originalSourceText, options, cancellationToken) { _chunks = chunks; var generator = SyntaxGenerator.GetGenerator(document); // Both [0][0] indices are safe here. We can only get here if we had more than // two chunks to wrap. And each chunk is required to have at least three elements // (i.e. <c>. name (arglist)</c>). var firstPeriod = chunks[0][0]; _firstPeriodIndentationTrivia = new SyntaxTriviaList(generator.Whitespace( OriginalSourceText.GetOffset(firstPeriod.SpanStart).CreateIndentationString(options.UseTabs, options.TabSize))); _smartIndentTrivia = new SyntaxTriviaList(generator.Whitespace( GetSmartIndentationAfter(firstPeriod))); _newlineBeforeOperatorTrivia = service.GetNewLineBeforeOperatorTrivia(NewLineTrivia); }
public sealed override async Task <ICodeActionComputer?> TryCreateComputerAsync( Document document, int position, SyntaxNode node, SyntaxWrappingOptions options, bool containsSyntaxError, CancellationToken cancellationToken) { if (containsSyntaxError) { return(null); } // We have to be on a chain part. If not, there's nothing to do here at all. if (!IsDecomposableChainPart(node)) { return(null); } // Has to be the topmost chain part. If we're not on the topmost, then just // bail out here. Our caller will continue walking upwards until it hits the // topmost node. if (IsDecomposableChainPart(node.Parent)) { return(null); } // We're at the top of something that looks like it could be part of a chained // expression. Break it into the individual chunks. We need to have at least // two chunks or this to be worth wrapping. // // i.e. if we only have <c>this.Goo(...)</c> there's nothing to wrap. However, we can // wrap when we have <c>this.Goo(...).Bar(...)</c>. var chunks = GetChainChunks(node); if (chunks.Length <= 1) { return(null); } // If any of these chunk parts are unformattable, then we don't want to offer anything // here as we may make formatting worse for this construct. foreach (var chunk in chunks) { var unformattable = await ContainsUnformattableContentAsync( document, chunk, cancellationToken).ConfigureAwait(false); if (unformattable) { return(null); } } // Looks good. Create the action computer which will actually determine // the set of wrapping options to provide. var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); return(new CallExpressionCodeActionComputer( this, document, sourceText, options, chunks, cancellationToken)); }
public override async Task <ICodeActionComputer?> TryCreateComputerAsync( Document document, int position, SyntaxNode declaration, SyntaxWrappingOptions options, bool containsSyntaxError, CancellationToken cancellationToken) { var listSyntax = TryGetApplicableList(declaration); if (listSyntax == null || listSyntax.Span.IsEmpty) { return(null); } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (!PositionIsApplicable(root, position, declaration, containsSyntaxError, listSyntax)) { return(null); } var listItems = GetListItems(listSyntax); if (listItems.Count <= 1) { // nothing to do with 0-1 items. Simple enough for users to just edit // themselves, and this prevents constant clutter with formatting that isn't // really that useful. return(null); } var containsUnformattableContent = await ContainsUnformattableContentAsync( document, listItems.GetWithSeparators(), cancellationToken).ConfigureAwait(false); if (containsUnformattableContent) { return(null); } var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); return(new SeparatedSyntaxListCodeActionComputer( this, document, sourceText, options, listSyntax, listItems, cancellationToken)); }
public SeparatedSyntaxListCodeActionComputer( AbstractSeparatedSyntaxListWrapper <TListSyntax, TListItemSyntax> service, Document document, SourceText sourceText, SyntaxWrappingOptions options, TListSyntax listSyntax, SeparatedSyntaxList <TListItemSyntax> listItems, CancellationToken cancellationToken) : base(service, document, sourceText, options, cancellationToken) { _listSyntax = listSyntax; _listItems = listItems; _shouldMoveOpenBraceToNewLine = service.ShouldMoveOpenBraceToNewLine(options); _shouldMoveCloseBraceToNewLine = service.ShouldMoveCloseBraceToNewLine; var generator = SyntaxGenerator.GetGenerator(OriginalDocument); _afterOpenTokenIndentationTrivia = generator.Whitespace(GetAfterOpenTokenIdentation()); _singleIndentationTrivia = generator.Whitespace(GetSingleIdentation()); _braceIndentationTrivia = generator.Whitespace(GetBraceTokenIndentation()); }
public BinaryExpressionCodeActionComputer( AbstractBinaryExpressionWrapper <TBinaryExpressionSyntax> service, Document document, SourceText originalSourceText, SyntaxWrappingOptions options, TBinaryExpressionSyntax binaryExpression, ImmutableArray <SyntaxNodeOrToken> exprsAndOperators, CancellationToken cancellationToken) : base(service, document, originalSourceText, options, cancellationToken) { _exprsAndOperators = exprsAndOperators; var generator = SyntaxGenerator.GetGenerator(document); _newlineBeforeOperatorTrivia = service.GetNewLineBeforeOperatorTrivia(NewLineTrivia); _indentAndAlignTrivia = new SyntaxTriviaList(generator.Whitespace( OriginalSourceText.GetOffset(binaryExpression.Span.Start) .CreateIndentationString(options.FormattingOptions.UseTabs, options.FormattingOptions.TabSize))); _smartIndentTrivia = new SyntaxTriviaList(generator.Whitespace( GetSmartIndentationAfter(_exprsAndOperators[1]))); }
protected abstract bool ShouldMoveOpenBraceToNewLine(SyntaxWrappingOptions options);
protected override bool ShouldMoveOpenBraceToNewLine(SyntaxWrappingOptions options) => false;
public sealed override async Task <ICodeActionComputer?> TryCreateComputerAsync( Document document, int position, SyntaxNode node, SyntaxWrappingOptions options, bool containsSyntaxError, CancellationToken cancellationToken) { if (containsSyntaxError) { return(null); } if (node is not TBinaryExpressionSyntax binaryExpr) { return(null); } var precedence = _precedenceService.GetPrecedenceKind(binaryExpr); if (precedence == PrecedenceKind.Other) { return(null); } // Don't process this binary expression if it's in a parent binary expr of the same or // lower precedence. We'll just allow our caller to walk up to that and call back into // us to handle. This way, we're always starting at the topmost binary expr of this // precedence. // // for example, if we have `if (a + b == c + d)` expectation is to wrap on the lower // precedence `==` op, not either of the `+` ops // // Note: we use `<=` when comparing precedence because lower precedence has a higher // value. if (binaryExpr.Parent is TBinaryExpressionSyntax parentBinary && precedence <= _precedenceService.GetPrecedenceKind(parentBinary)) { return(null); } var exprsAndOperators = GetExpressionsAndOperators(precedence, binaryExpr); #if DEBUG Debug.Assert(exprsAndOperators.Length >= 3); Debug.Assert(exprsAndOperators.Length % 2 == 1, "Should have odd number of exprs and operators"); for (var i = 0; i < exprsAndOperators.Length; i++) { var item = exprsAndOperators[i]; Debug.Assert(((i % 2) == 0 && item.IsNode) || ((i % 2) == 1 && item.IsToken)); } #endif var containsUnformattableContent = await ContainsUnformattableContentAsync( document, exprsAndOperators, cancellationToken).ConfigureAwait(false); if (containsUnformattableContent) { return(null); } var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); return(new BinaryExpressionCodeActionComputer( this, document, sourceText, options, binaryExpr, exprsAndOperators, cancellationToken)); }
protected override bool ShouldMoveOpenBraceToNewLine(SyntaxWrappingOptions options) => ((CSharpSyntaxWrappingOptions)options).NewLinesForBracesInObjectCollectionArrayInitializers;