public Indenter( AbstractIndentationService <TSyntaxRoot> service, SyntacticDocument document, IEnumerable <AbstractFormattingRule> rules, OptionSet optionSet, TextLine lineToBeIndented, CancellationToken cancellationToken) { Document = document; _service = service; _syntaxFacts = document.Document.GetRequiredLanguageService <ISyntaxFactsService>(); OptionSet = optionSet; OptionService = document.Document.Project.Solution.Workspace.Services.GetRequiredService <IOptionService>(); Root = (TSyntaxRoot)document.Root; LineToBeIndented = lineToBeIndented; _tabSize = this.OptionSet.GetOption(FormattingOptions.TabSize, Root.Language); CancellationToken = cancellationToken; Rules = rules; Finder = new BottomUpBaseIndentationFinder( new ChainedFormattingRules(this.Rules, OptionSet.AsAnalyzerConfigOptions(OptionService, Root.Language)), _tabSize, this.OptionSet.GetOption(FormattingOptions.IndentationSize, Root.Language), tokenStream: null, _syntaxFacts); }
private async Task <Document> CleanUpNewLinesAsync(Document document, TextSpan insertSpan, ISyntaxFormattingService languageFormatter, OptionSet optionSet, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var optionService = document.Project.Solution.Workspace.Services.GetRequiredService <IOptionService>(); var shouldUseFormattingSpanCollapse = optionSet.GetOption(FormattingOptions.AllowDisjointSpanMerging); var options = optionSet.AsAnalyzerConfigOptions(optionService, root.Language); var textChanges = languageFormatter.Format(root, new[] { insertSpan }, shouldUseFormattingSpanCollapse, options, new[] { new CleanUpNewLinesFormatter(text) }, cancellationToken).GetTextChanges(); // If there are no changes then, do less work. if (textChanges.Count == 0) { return(document); } // The last text change should include where the insert span ends Debug.Assert(textChanges.Last().Span.IntersectsWith(insertSpan.End)); // If there are changes then, this was a case where there were no // previous imports statements. We need to retain the final extra // newline because that separates the imports section from the rest // of the code. textChanges.RemoveAt(textChanges.Count - 1); var newText = text.WithChanges(textChanges); return(document.WithText(newText)); }
public static CodeGenerationOptions Create(OptionSet options, CodeGenerationOptions?fallbackOptions, HostLanguageServices languageServices) { var formattingService = languageServices.GetRequiredService <ICodeGenerationService>(); var configOptions = options.AsAnalyzerConfigOptions(languageServices.WorkspaceServices.GetRequiredService <IOptionService>(), languageServices.Language); return(formattingService.GetCodeGenerationOptions(configOptions, fallbackOptions)); }
public static SyntaxFormattingOptions Create(OptionSet options, HostWorkspaceServices services, string language) { var formattingService = services.GetRequiredLanguageService <ISyntaxFormattingService>(language); var configOptions = options.AsAnalyzerConfigOptions(services.GetRequiredService <IOptionService>(), language); return(formattingService.GetFormattingOptions(configOptions)); }
internal static IFormattingResult GetFormattingResult(SyntaxNode node, IEnumerable <TextSpan> spans, Workspace workspace, OptionSet options, IEnumerable <AbstractFormattingRule> rules, CancellationToken cancellationToken) { if (workspace == null) { throw new ArgumentNullException(nameof(workspace)); } if (node == null) { throw new ArgumentNullException(nameof(node)); } var languageFormatter = workspace.Services.GetLanguageServices(node.Language).GetService <ISyntaxFormattingService>(); if (languageFormatter == null) { return(null); } var optionService = workspace.Services.GetRequiredService <IOptionService>(); options ??= workspace.Options; rules ??= GetDefaultFormattingRules(workspace, node.Language); spans ??= SpecializedCollections.SingletonEnumerable(node.FullSpan); var shouldUseFormattingSpanCollapse = options.GetOption(FormattingOptions.AllowDisjointSpanMerging); return(languageFormatter.Format(node, spans, shouldUseFormattingSpanCollapse, options.AsAnalyzerConfigOptions(optionService, node.Language), rules, cancellationToken)); }
public static bool ShouldUseSmartTokenFormatterInsteadOfIndenter( IEnumerable <AbstractFormattingRule> formattingRules, CompilationUnitSyntax root, TextLine line, IOptionService optionService, OptionSet optionSet, out SyntaxToken token) { Contract.ThrowIfNull(formattingRules); Contract.ThrowIfNull(root); token = default; if (!optionSet.GetOption(FormattingOptions.AutoFormattingOnReturn, LanguageNames.CSharp)) { return(false); } if (optionSet.GetOption(FormattingOptions.SmartIndent, LanguageNames.CSharp) != FormattingOptions.IndentStyle.Smart) { return(false); } var firstNonWhitespacePosition = line.GetFirstNonWhitespacePosition(); if (!firstNonWhitespacePosition.HasValue) { return(false); } token = root.FindToken(firstNonWhitespacePosition.Value); if (IsInvalidToken(token)) { return(false); } if (token.IsKind(SyntaxKind.None) || token.SpanStart != firstNonWhitespacePosition) { return(false); } // first see whether there is a line operation for current token var previousToken = token.GetPreviousToken(includeZeroWidth: true); // only use smart token formatter when we have two visible tokens. if (previousToken.Kind() == SyntaxKind.None || previousToken.IsMissing) { return(false); } var lineOperation = FormattingOperations.GetAdjustNewLinesOperation(formattingRules, previousToken, token, optionSet.AsAnalyzerConfigOptions(optionService, LanguageNames.CSharp)); if (lineOperation == null || lineOperation.Option == AdjustNewLinesOption.ForceLinesIfOnSingleLine) { // no indentation operation, nothing to do for smart token formatter return(false); } // We're pressing enter between two tokens, have the formatter figure out hte appropriate // indentation. return(true); }