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));
    }
예제 #4
0
        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));
        }
예제 #5
0
        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));
        }
예제 #6
0
        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);
        }