protected override StatementSyntax CreateParameterCheckIfStatement( DocumentOptionSet options, ExpressionSyntax condition, StatementSyntax ifTrueStatement ) { var withBlock = options.GetOption(CSharpCodeStyleOptions.PreferBraces).Value == CodeAnalysis.CodeStyle.PreferBracesPreference.Always; var singleLine = options.GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine).Value; var closeParenToken = Token(SyntaxKind.CloseParenToken); if (withBlock) { ifTrueStatement = Block(ifTrueStatement); } else if (singleLine) { // Any elastic trivia between the closing parenthesis of if and the statement must be removed // to convince the formatter to keep everything on a single line. // Note: ifTrueStatement and closeParenToken are generated, so there is no need to deal with any existing trivia. closeParenToken = closeParenToken.WithTrailingTrivia(Space); ifTrueStatement = ifTrueStatement.WithoutLeadingTrivia(); } return(IfStatement( attributeLists: default,
private static string GetReplacementText( ITextView textView, DocumentOptionSet options, ITextSnapshotLine triviaLine, SyntaxTrivia trivia, int position ) { // We're inside a comment. Instead of inserting just a newline here, insert // 1. a newline // 2. spaces up to the indentation of the current comment // 3. the comment prefix (extended out for repeated chars). // Then, depending on if the current comment starts with whitespace or not, we will insert those same spaces // to match. var commentStartColumn = triviaLine.GetColumnFromLineOffset( trivia.SpanStart - triviaLine.Start, textView.Options ); var useTabs = options.GetOption(FormattingOptions.UseTabs); var tabSize = options.GetOption(FormattingOptions.TabSize); var prefix = GetCommentPrefix(triviaLine.Snapshot, trivia, position); var replacementText = options.GetOption(FormattingOptions.NewLine) + commentStartColumn.CreateIndentationString(useTabs, tabSize) + prefix + GetWhitespaceAfterCommentPrefix(trivia, triviaLine, prefix, position); return(replacementText); }
private bool OnlySmartIndentCloseBrace(DocumentOptionSet options) { // User does not want auto-formatting (either in general, or for close braces in // specific). So we only smart indent close braces when typed. return(!options.GetOption(FeatureOnOffOptions.AutoFormattingOnCloseBrace) || !options.GetOption(FeatureOnOffOptions.AutoFormattingOnTyping)); }
private static int?SplitStringLiteral( Document document, DocumentOptionSet options, int position, CancellationToken cancellationToken ) { var useTabs = options.GetOption(FormattingOptions.UseTabs); var tabSize = options.GetOption(FormattingOptions.TabSize); var indentStyle = options.GetOption( FormattingOptions.SmartIndent, LanguageNames.CSharp ); var root = document.GetSyntaxRootSynchronously(cancellationToken); var sourceText = root.SyntaxTree.GetText(cancellationToken); var splitter = StringSplitter.Create( document, position, root, sourceText, useTabs, tabSize, indentStyle, cancellationToken ); if (splitter == null) { return(null); } return(splitter.TrySplit()); }
public DocumentationCommentSnippet?GetDocumentationCommentSnippetOnCharacterTyped( SyntaxTree syntaxTree, SourceText text, int position, DocumentOptionSet options, CancellationToken cancellationToken) { if (!options.GetOption(FeatureOnOffOptions.AutoXmlDocCommentGeneration)) { return(null); } // Only generate if the position is immediately after '///', // and that is the only documentation comment on the target member. var token = syntaxTree.GetRoot(cancellationToken).FindToken(position, findInsideTrivia: true); if (position != token.SpanStart) { return(null); } var lines = GetDocumentationCommentLines(token, text, options, out var indentText); if (lines == null) { return(null); } var newLine = options.GetOption(FormattingOptions.NewLine); var lastLine = lines[^ 1];
private bool InsertOnCommandInvoke( SyntaxTree syntaxTree, SourceText text, int position, int originalPosition, ITextBuffer subjectBuffer, ITextView textView, DocumentOptionSet options, CancellationToken cancellationToken) { var targetMember = GetTargetMember(syntaxTree, text, position, cancellationToken); if (targetMember == null) { return(false); } var startPosition = targetMember.GetFirstToken().SpanStart; var line = text.Lines.GetLineFromPosition(startPosition); Debug.Assert(!line.IsEmptyOrWhitespace()); var lines = GetDocumentationCommentStubLines(targetMember); Debug.Assert(lines.Count > 2); var newLine = options.GetOption(FormattingOptions.NewLine); AddLineBreaks(text, lines, newLine); // Add indents var lineOffset = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.GetOption(FormattingOptions.TabSize)); Debug.Assert(line.Start + lineOffset == startPosition); var indentText = lineOffset.CreateIndentationString(options.GetOption(FormattingOptions.UseTabs), options.GetOption(FormattingOptions.TabSize)); for (var i = 1; i < lines.Count; i++) { lines[i] = indentText + lines[i]; } lines[lines.Count - 1] = lines[lines.Count - 1] + indentText; var newText = string.Join(string.Empty, lines); var offset = lines[0].Length + lines[1].Length - newLine.Length; subjectBuffer.Insert(startPosition, newText); textView.TryMoveCaretToAndEnsureVisible(subjectBuffer.CurrentSnapshot.GetPoint(startPosition + offset)); return(true); }
public BinaryExpressionCodeActionComputer( AbstractBinaryExpressionWrapper <TBinaryExpressionSyntax> service, Document document, SourceText originalSourceText, DocumentOptionSet options, TBinaryExpressionSyntax binaryExpression, ImmutableArray <SyntaxNodeOrToken> exprsAndOperators, CancellationToken cancellationToken ) : base(service, document, originalSourceText, options, cancellationToken) { _exprsAndOperators = exprsAndOperators; _preference = options.GetOption(CodeStyleOptions2.OperatorPlacementWhenWrapping); var generator = SyntaxGenerator.GetGenerator(document); _newlineBeforeOperatorTrivia = service.GetNewLineBeforeOperatorTrivia( NewLineTrivia ); _indentAndAlignTrivia = new SyntaxTriviaList( generator.Whitespace( OriginalSourceText .GetOffset(binaryExpression.Span.Start) .CreateIndentationString(UseTabs, TabSize) ) ); _smartIndentTrivia = new SyntaxTriviaList( generator.Whitespace(GetSmartIndentationAfter(_exprsAndOperators[1])) ); }
private bool OnlySmartIndentOpenBrace(DocumentOptionSet options) { // User does not want auto-formatting . So we only smart indent open braces when typed. // Note: there is no specific option for controlling formatting on open brace. So we // don't have the symmetry with OnlySmartIndentCloseBrace. return(!options.GetOption(FeatureOnOffOptions.AutoFormattingOnTyping)); }
private static SyntaxNode UseExpressionOrBlockBodyIfDesired( DocumentOptionSet documentOptions, ParseOptions parseOptions, MethodDeclarationSyntax methodDeclaration, bool createReturnStatementForExpression) { var expressionBodyPreference = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedMethods).Value; if (methodDeclaration.Body != null && expressionBodyPreference != ExpressionBodyPreference.Never) { if (methodDeclaration.Body.TryConvertToArrowExpressionBody( methodDeclaration.Kind(), parseOptions, expressionBodyPreference, out var arrowExpression, out var semicolonToken)) { return(methodDeclaration.WithBody(null) .WithExpressionBody(arrowExpression) .WithSemicolonToken(semicolonToken) .WithAdditionalAnnotations(Formatter.Annotation)); } } else if (methodDeclaration.ExpressionBody != null && expressionBodyPreference == ExpressionBodyPreference.Never) { if (methodDeclaration.ExpressionBody.TryConvertToBlock( methodDeclaration.SemicolonToken, createReturnStatementForExpression, out var block)) { return(methodDeclaration.WithExpressionBody(null) .WithSemicolonToken(default)
private static AccessorDeclarationSyntax UseExpressionOrBlockBodyIfDesired( DocumentOptionSet documentOptions, ParseOptions parseOptions, AccessorDeclarationSyntax accessorDeclaration) { var preferExpressionBody = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedAccessors).Value; if (accessorDeclaration?.Body != null && preferExpressionBody) { if (accessorDeclaration.Body.TryConvertToExpressionBody( parseOptions, out var arrowExpression, out var semicolonToken)) { return(accessorDeclaration.WithBody(null) .WithExpressionBody(arrowExpression) .WithSemicolonToken(semicolonToken) .WithAdditionalAnnotations(Formatter.Annotation)); } } else if (accessorDeclaration?.ExpressionBody != null && !preferExpressionBody) { var block = accessorDeclaration.ExpressionBody.ConvertToBlock( accessorDeclaration.SemicolonToken, createReturnStatementForExpression: accessorDeclaration.Kind() == SyntaxKind.GetAccessorDeclaration); return(accessorDeclaration.WithExpressionBody(null) .WithSemicolonToken(default(SyntaxToken)) .WithBody(block) .WithAdditionalAnnotations(Formatter.Annotation)); } return(accessorDeclaration); }
private int?SplitStringLiteral( ITextBuffer subjectBuffer, Document document, DocumentOptionSet options, int position, CancellationToken cancellationToken) { var useTabs = options.GetOption(FormattingOptions.UseTabs); var tabSize = options.GetOption(FormattingOptions.TabSize); var root = document.GetSyntaxRootSynchronously(cancellationToken); var sourceText = root.SyntaxTree.GetText(cancellationToken); var splitter = StringSplitter.Create(document, position, root, sourceText, useTabs, tabSize, cancellationToken); if (splitter == null) { return(null); } return(splitter.TrySplit()); }
public static KeyValueLogMessage Create(DocumentOptionSet docOptions) { return(KeyValueLogMessage.Create(LogType.UserAction, m => { foreach (var option in CodeCleanupOptionsProvider.SingletonOptions) { m[option.Name] = docOptions.GetOption((PerLanguageOption <bool>)option, LanguageNames.CSharp); } })); }
public SyntaxNode ConvertMethodsToProperty( DocumentOptionSet documentOptions, ParseOptions parseOptions, SemanticModel semanticModel, SyntaxGenerator generator, GetAndSetMethods getAndSetMethods, string propertyName, bool nameChanged) { var propertyDeclaration = ConvertMethodsToPropertyWorker( documentOptions, parseOptions, semanticModel, generator, getAndSetMethods, propertyName, nameChanged); var expressionBodyPreference = documentOptions.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedProperties).Value; if (expressionBodyPreference != ExpressionBodyPreference.Never) { if (propertyDeclaration.AccessorList?.Accessors.Count == 1 && propertyDeclaration.AccessorList?.Accessors[0].Kind() == SyntaxKind.GetAccessorDeclaration) { var getAccessor = propertyDeclaration.AccessorList.Accessors[0]; if (getAccessor.ExpressionBody != null) { return(propertyDeclaration.WithExpressionBody(getAccessor.ExpressionBody) .WithSemicolonToken(getAccessor.SemicolonToken) .WithAccessorList(null)); } else if (getAccessor.Body != null && getAccessor.Body.TryConvertToExpressionBody( parseOptions, expressionBodyPreference, out var arrowExpression, out var semicolonToken)) { return(propertyDeclaration.WithExpressionBody(arrowExpression) .WithSemicolonToken(semicolonToken) .WithAccessorList(null)); } } } else { if (propertyDeclaration.ExpressionBody != null && propertyDeclaration.ExpressionBody.TryConvertToBlock( propertyDeclaration.SemicolonToken, createReturnStatementForExpression: true, block: out var block)) { var accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithBody(block); var accessorList = SyntaxFactory.AccessorList(SyntaxFactory.SingletonList(accessor)); return(propertyDeclaration.WithAccessorList(accessorList) .WithExpressionBody(null) .WithSemicolonToken(default(SyntaxToken))); } } return(propertyDeclaration); }
private async Task <Document> RemoveSortUsingsAsync(Document document, DocumentOptionSet docOptions, CancellationToken cancellationToken) { // remove usings if (docOptions.GetOption(CodeCleanupOptions.RemoveUnusedImports)) { var removeUsingsService = document.GetLanguageService <IRemoveUnnecessaryImportsService>(); if (removeUsingsService != null) { document = await removeUsingsService.RemoveUnnecessaryImportsAsync(document, cancellationToken).ConfigureAwait(false); } } // sort usings if (docOptions.GetOption(CodeCleanupOptions.SortImports)) { document = await OrganizeImportsService.OrganizeImportsAsync(document, cancellationToken).ConfigureAwait(false); } return(document); }
static SourceText GetIndentedText( SourceText textToIndent, TextLine lineToIndent, LinePosition desiredCaretLinePosition, DocumentOptionSet documentOptions ) { // Indent by the amount needed to make the caret line contain the desired indentation column. var amountToIndent = desiredCaretLinePosition.Character - lineToIndent.Span.Length; // Create and apply a text change with whitespace for the indentation amount. var indentText = amountToIndent.CreateIndentationString( documentOptions.GetOption(FormattingOptions.UseTabs), documentOptions.GetOption(FormattingOptions.TabSize) ); var indentedText = textToIndent.WithChanges( new TextChange(new TextSpan(lineToIndent.End, 0), indentText) ); return(indentedText); }
public AbstractCodeActionComputer( TWrapper service, Document document, SourceText originalSourceText, DocumentOptionSet options, CancellationToken cancellationToken) { Wrapper = service; OriginalDocument = document; OriginalSourceText = originalSourceText; CancellationToken = cancellationToken; UseTabs = options.GetOption(FormattingOptions.UseTabs); TabSize = options.GetOption(FormattingOptions.TabSize); NewLine = options.GetOption(FormattingOptions.NewLine); WrappingColumn = options.GetOption(FormattingOptions.PreferredWrappingColumn); var generator = SyntaxGenerator.GetGenerator(document); NewLineTrivia = new SyntaxTriviaList(generator.EndOfLine(NewLine)); SingleWhitespaceTrivia = new SyntaxTriviaList(generator.Whitespace(" ")); }
private string CreateInsertionTextFromPreviousLine(TextLine previousLine, DocumentOptionSet options) { var useTabs = options.GetOption(FormattingOptions.UseTabs); var tabSize = options.GetOption(FormattingOptions.TabSize); var previousLineText = previousLine.ToString(); var firstNonWhitespaceColumn = previousLineText.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(tabSize); var trimmedPreviousLine = previousLineText.Trim(); Debug.Assert(trimmedPreviousLine.StartsWith(ExteriorTriviaText), "Unexpected: previous line does not begin with doc comment exterior trivia."); // skip exterior trivia. trimmedPreviousLine = trimmedPreviousLine.Substring(3); var firstNonWhitespaceOffsetInPreviousXmlText = trimmedPreviousLine.GetFirstNonWhitespaceOffset(); var extraIndent = firstNonWhitespaceOffsetInPreviousXmlText != null ? trimmedPreviousLine.Substring(0, firstNonWhitespaceOffsetInPreviousXmlText.Value) : " "; return(firstNonWhitespaceColumn.CreateIndentationString(useTabs, tabSize) + ExteriorTriviaText + extraIndent); }
private IEnumerable <string> GetEnabledDiagnosticIds(DocumentOptionSet docOptions) { var diagnosticIds = new List <string>(); foreach (var tuple in _optionDiagnosticsMappings) { if (docOptions.GetOption(tuple.Item1)) { diagnosticIds.AddRange(tuple.Item2); } } return(diagnosticIds); }
private int?DoSmartIndent(ITextSnapshotLine line, Document document, DocumentOptionSet optionSet, CancellationToken cancellationToken) { var indentationService = document.GetLanguageService <IIndentationService>(); var syntaxFactsService = document.GetLanguageService <ISyntaxFactsService>(); var syntaxTree = document.GetSyntaxTreeSynchronously(cancellationToken); var indent = FindTotalParentChainIndent( syntaxTree.Root, line.Start.Position, 0, optionSet.GetOption(FormattingOptions.IndentationSize), indentationService, syntaxFactsService); return(indent); }
private static IEnumerable <XmlNodeSyntax> ExceptionDocumentation(DocumentOptionSet options, ImmutableArray <String> exceptions) { ImmutableArrayIterator <String> iterator = new ImmutableArrayIterator <String>(exceptions); if (iterator.TryGetNext(out String exception, out iterator)) { String newLine = options.GetOption(FormattingOptions.NewLine); yield return(XmlExceptionElement(TypeCref(TypeName(exception))) .WithLeadingTrivia(DocumentationCommentExterior("/// "))); while (iterator.TryGetNext(out exception, out iterator)) { yield return(XmlNewLine(newLine, continueXmlDocumentationComment: true)); yield return(XmlExceptionElement(TypeCref(TypeName(exception)))); } yield return(XmlNewLine(newLine, continueXmlDocumentationComment: false)); } }
private int GetLeadingWhiteSpace(string text, DocumentOptionSet optionSet) { var size = 0; foreach (var ch in text) { if (ch == '\t') { size += optionSet.GetOption(FormattingOptions.TabSize); } else if (ch == ' ') { size++; } else { break; } } return(size); }
/// <summary> /// re-adjust caret position to be the beginning of first text on the line. and make sure the text start at the given indentation /// </summary> private static void ReadjustIndentation(ITextView view, ITextBuffer subjectBuffer, int firstNonWhitespaceIndex, int indentation, DocumentOptionSet options) { var lineInSubjectBuffer = view.GetCaretPoint(subjectBuffer).Value.GetContainingLine(); // first set the caret at the beginning of the text on the line view.TryMoveCaretToAndEnsureVisible(new SnapshotPoint(lineInSubjectBuffer.Snapshot, lineInSubjectBuffer.Start + firstNonWhitespaceIndex)); var document = lineInSubjectBuffer.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } // and then, insert the text document.Project.Solution.Workspace.ApplyTextChanges(document.Id, new TextChange( new TextSpan( lineInSubjectBuffer.Start.Position, firstNonWhitespaceIndex), indentation.CreateIndentationString(options.GetOption(FormattingOptions.UseTabs), options.GetOption(FormattingOptions.TabSize))), CancellationToken.None); }
private bool TryGenerateDocumentationCommentAfterEnter( SyntaxTree syntaxTree, SourceText text, int position, int originalPosition, ITextBuffer subjectBuffer, ITextView textView, DocumentOptionSet options, CancellationToken cancellationToken) { // Find the documentation comment before the new line that was just pressed var token = GetTokenToLeft(syntaxTree, position, cancellationToken); if (!IsDocCommentNewLine(token)) { return(false); } var documentationComment = token.GetAncestor <TDocumentationComment>(); if (!IsSingleExteriorTrivia(documentationComment)) { return(false); } var targetMember = GetTargetMember(documentationComment); if (targetMember == null) { return(false); } // Ensure that the target member is only preceded by a single documentation comment (our ///). if (GetPrecedingDocumentationCommentCount(targetMember) != 1) { return(false); } var line = text.Lines.GetLineFromPosition(documentationComment.FullSpan.Start); if (line.IsEmptyOrWhitespace()) { return(false); } var lines = GetDocumentationCommentStubLines(targetMember); Contract.Assume(lines.Count > 2); AddLineBreaks(text, lines); // Shave off initial exterior trivia lines[0] = lines[0].Substring(3); // Add indents var lineOffset = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.GetOption(FormattingOptions.TabSize)); var indentText = lineOffset.CreateIndentationString(options.GetOption(FormattingOptions.UseTabs), options.GetOption(FormattingOptions.TabSize)); for (int i = 1; i < lines.Count; i++) { lines[i] = indentText + lines[i]; } var newText = string.Join(string.Empty, lines); var offset = lines[0].Length + lines[1].Length - GetNewLine(text).Length; // Shave off final line break or add trailing indent if necessary var trivia = syntaxTree.GetRoot(cancellationToken).FindTrivia(position, findInsideTrivia: false); if (IsEndOfLineTrivia(trivia)) { newText = newText.Substring(0, newText.Length - GetNewLine(text).Length); } else { newText += indentText; } var replaceSpan = token.Span.ToSpan(); var currentLine = text.Lines.GetLineFromPosition(position); var currentLinePosition = currentLine.GetFirstNonWhitespacePosition(); if (currentLinePosition.HasValue) { replaceSpan = Span.FromBounds(replaceSpan.Start, currentLinePosition.Value); } subjectBuffer.Replace(replaceSpan, newText); textView.TryMoveCaretToAndEnsureVisible(subjectBuffer.CurrentSnapshot.GetPoint(replaceSpan.Start + offset)); return(true); }
protected override bool PrefersThrowExpression(DocumentOptionSet options) => options.GetOption(CSharpCodeStyleOptions.PreferThrowExpression).Value;
private bool InsertOnCharacterTyped( SyntaxTree syntaxTree, SourceText text, int position, int originalPosition, ITextBuffer subjectBuffer, ITextView textView, DocumentOptionSet options, CancellationToken cancellationToken) { if (!subjectBuffer.GetFeatureOnOffOption(FeatureOnOffOptions.AutoXmlDocCommentGeneration)) { return(false); } // Only generate if the position is immediately after '///', // and that is the only documentation comment on the target member. var token = syntaxTree.GetRoot(cancellationToken).FindToken(position, findInsideTrivia: true); if (position != token.SpanStart) { return(false); } var documentationComment = token.GetAncestor <TDocumentationComment>(); if (!IsSingleExteriorTrivia(documentationComment)) { return(false); } var targetMember = GetTargetMember(documentationComment); if (targetMember == null) { return(false); } // Ensure that the target member is only preceded by a single documentation comment (i.e. our ///). if (GetPrecedingDocumentationCommentCount(targetMember) != 1) { return(false); } var line = text.Lines.GetLineFromPosition(documentationComment.FullSpan.Start); if (line.IsEmptyOrWhitespace()) { return(false); } var lines = GetDocumentationCommentStubLines(targetMember); Contract.Assume(lines.Count > 2); AddLineBreaks(text, lines); // Shave off initial three slashes lines[0] = lines[0].Substring(3); // Add indents var lineOffset = line.GetColumnOfFirstNonWhitespaceCharacterOrEndOfLine(options.GetOption(FormattingOptions.TabSize)); var indentText = lineOffset.CreateIndentationString(options.GetOption(FormattingOptions.UseTabs), options.GetOption(FormattingOptions.TabSize)); for (int i = 1; i < lines.Count - 1; i++) { lines[i] = indentText + lines[i]; } var lastLine = lines[lines.Count - 1]; lastLine = indentText + lastLine.Substring(0, lastLine.Length - GetNewLine(text).Length); lines[lines.Count - 1] = lastLine; var newText = string.Join(string.Empty, lines); var offset = lines[0].Length + lines[1].Length - GetNewLine(text).Length; subjectBuffer.Insert(position, newText); textView.TryMoveCaretToAndEnsureVisible(subjectBuffer.CurrentSnapshot.GetPoint(position + offset)); return(true); }