public static async Task <RemoveSuppressionCodeAction> CreateAsync(
                SuppressionTargetInfo suppressionTargetInfo,
                Document documentOpt,
                Project project,
                Diagnostic diagnostic,
                AbstractSuppressionCodeFixProvider fixer,
                CancellationToken cancellationToken)
            {
                var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                var attribute = diagnostic.GetSuppressionInfo(compilation).Attribute;

                if (attribute != null)
                {
                    return(AttributeRemoveAction.Create(attribute, project, diagnostic, fixer));
                }
                else if (documentOpt != null && !SuppressionHelpers.IsSynthesizedExternalSourceDiagnostic(diagnostic))
                {
                    var options = await SyntaxFormattingOptions.FromDocumentAsync(documentOpt, cancellationToken).ConfigureAwait(false);

                    return(PragmaRemoveAction.Create(suppressionTargetInfo, documentOpt, options, diagnostic, fixer));
                }
                else
                {
                    return(null);
                }
            }
            private async Task <Solution> RemoveUnnecessaryImportsAsync(
                Solution solution, DocumentId sourceDocumentId, DocumentId documentWithMovedTypeId)
            {
                var documentWithMovedType = solution.GetRequiredDocument(documentWithMovedTypeId);
                var documentWithMovedTypeFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(documentWithMovedType, CancellationToken).ConfigureAwait(false);

                var syntaxFacts = documentWithMovedType.GetRequiredLanguageService <ISyntaxFactsService>();
                var removeUnnecessaryImports = documentWithMovedType.GetRequiredLanguageService <IRemoveUnnecessaryImportsService>();

                // Remove all unnecessary imports from the new document we've created.
                documentWithMovedType = await removeUnnecessaryImports.RemoveUnnecessaryImportsAsync(documentWithMovedType, documentWithMovedTypeFormattingOptions, CancellationToken).ConfigureAwait(false);

                solution = solution.WithDocumentSyntaxRoot(
                    documentWithMovedTypeId, await documentWithMovedType.GetRequiredSyntaxRootAsync(CancellationToken).ConfigureAwait(false));

                // See which imports we kept around.
                var rootWithMovedType = await documentWithMovedType.GetRequiredSyntaxRootAsync(CancellationToken).ConfigureAwait(false);

                var movedImports = rootWithMovedType.DescendantNodes()
                                   .Where(syntaxFacts.IsUsingOrExternOrImport)
                                   .ToImmutableArray();

                // Now remove any unnecessary imports from the original doc that moved to the new doc.
                var sourceDocument = solution.GetRequiredDocument(sourceDocumentId);
                var sourceDocumentFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(sourceDocument, CancellationToken).ConfigureAwait(false);

                sourceDocument = await removeUnnecessaryImports.RemoveUnnecessaryImportsAsync(
                    sourceDocument,
                    n => movedImports.Contains(i => syntaxFacts.AreEquivalent(i, n)),
                    sourceDocumentFormattingOptions,
                    CancellationToken).ConfigureAwait(false);

                return(solution.WithDocumentSyntaxRoot(
                           sourceDocumentId, await sourceDocument.GetRequiredSyntaxRootAsync(CancellationToken).ConfigureAwait(false)));
            }
        public static async Task <Document> AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, CancellationToken cancellationToken)
        {
            var service           = document.GetRequiredLanguageService <IMetadataAsSourceService>();
            var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            return(await service.AddSourceToAsync(document, symbolCompilation, symbol, formattingOptions, cancellationToken).ConfigureAwait(false));
        }
예제 #4
0
        /// <summary>
        /// Clean up the provided spans in the document.
        /// Optionally you can provide your own options and code cleaners. Otherwise, the default will be used.
        /// </summary>
        public static async Task <Document> CleanupAsync(Document document, ImmutableArray <TextSpan> spans, ImmutableArray <ICodeCleanupProvider> providers = default, CancellationToken cancellationToken = default)
        {
            var cleanupService = document.GetRequiredLanguageService <ICodeCleanerService>();
            var options        = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            return(await cleanupService.CleanupAsync(document, spans, options, providers, cancellationToken).ConfigureAwait(false));
        }
예제 #5
0
            protected override async Task <Document> GetChangedSuppressionDocumentAsync(CancellationToken cancellationToken)
            {
                var suppressionsDoc = await GetOrCreateSuppressionsDocumentAsync(cancellationToken).ConfigureAwait(false);

                var services         = suppressionsDoc.Project.Solution.Workspace.Services;
                var suppressionsRoot = await suppressionsDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var addImportsService = suppressionsDoc.GetRequiredLanguageService <IAddImportsService>();
                var options           = await SyntaxFormattingOptions.FromDocumentAsync(suppressionsDoc, cancellationToken).ConfigureAwait(false);

                foreach (var(targetSymbol, diagnostics) in _diagnosticsBySymbol)
                {
                    foreach (var diagnostic in diagnostics)
                    {
                        Contract.ThrowIfFalse(!diagnostic.IsSuppressed);
                        suppressionsRoot = Fixer.AddGlobalSuppressMessageAttribute(
                            suppressionsRoot, targetSymbol, _suppressMessageAttribute, diagnostic,
                            services, options, addImportsService, cancellationToken);
                    }
                }

                var result = suppressionsDoc.WithSyntaxRoot(suppressionsRoot);
                var final  = await CleanupDocumentAsync(result, cancellationToken).ConfigureAwait(false);

                return(final);
            }
예제 #6
0
        public async Task <(Document document, SyntaxToken invocationNameToken)> GetFormattedDocumentAsync(CancellationToken cancellationToken)
        {
            if (DocumentWithoutFinalFormatting is null)
            {
                throw new InvalidOperationException();
            }

            var annotation = new SyntaxAnnotation();

            var root = await DocumentWithoutFinalFormatting.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            root = root.ReplaceToken(InvocationNameToken, InvocationNameToken.WithAdditionalAnnotations(annotation));

            var annotatedDocument  = DocumentWithoutFinalFormatting.WithSyntaxRoot(root);
            var simplifiedDocument = await Simplifier.ReduceAsync(annotatedDocument, Simplifier.Annotation, optionSet : null, cancellationToken).ConfigureAwait(false);

            var simplifiedRoot = await simplifiedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var options = await SyntaxFormattingOptions.FromDocumentAsync(DocumentWithoutFinalFormatting, cancellationToken).ConfigureAwait(false);

            var services = DocumentWithoutFinalFormatting.Project.Solution.Workspace.Services;

            var formattedDocument = simplifiedDocument.WithSyntaxRoot(
                Formatter.Format(simplifiedRoot, Formatter.Annotation, services, options, FormattingRules, cancellationToken));

            var formattedRoot = await formattedDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            return(formattedDocument, formattedRoot.GetAnnotatedTokens(annotation).Single());
        }
예제 #7
0
        internal static async Task <Document> CleanupDocumentAsync(
            Document document, CancellationToken cancellationToken)
        {
            if (document.SupportsSyntaxTree)
            {
                var addImportOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

                var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

                document = await ImportAdder.AddImportsFromSymbolAnnotationAsync(
                    document, Simplifier.AddImportsAnnotation, addImportOptions, cancellationToken).ConfigureAwait(false);

                document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken : cancellationToken).ConfigureAwait(false);

                // format any node with explicit formatter annotation
                document = await Formatter.FormatAsync(document, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false);

                // format any elastic whitespace
                document = await Formatter.FormatAsync(document, SyntaxAnnotation.ElasticAnnotation, formattingOptions, cancellationToken).ConfigureAwait(false);

                document = await CaseCorrector.CaseCorrectAsync(document, CaseCorrector.Annotation, cancellationToken).ConfigureAwait(false);
            }

            return(document);
        }
예제 #8
0
        private static async Task TokenFormatWorkerAsync(TestWorkspace workspace, ITextBuffer buffer, int indentationLine, char ch)
        {
            var document = buffer.CurrentSnapshot.GetRelatedDocumentsWithChanges().First();
            var root     = (CompilationUnitSyntax)await document.GetSyntaxRootAsync();

            var line = root.GetText().Lines[indentationLine];

            var index = line.ToString().LastIndexOf(ch);

            Assert.InRange(index, 0, int.MaxValue);

            // get token
            var position = line.Start + index;
            var token    = root.FindToken(position);

            var formattingRuleProvider = workspace.Services.GetService <IHostDependentFormattingRuleFactoryService>();

            var rules = ImmutableArray.Create(formattingRuleProvider.CreateRule(document, position)).AddRange(Formatter.GetDefaultFormattingRules(document));

            var options = new IndentationOptions(
                await SyntaxFormattingOptions.FromDocumentAsync(document, CancellationToken.None).ConfigureAwait(false),
                AutoFormattingOptions.Default);

            var formatter = new CSharpSmartTokenFormatter(options, rules, root);
            var changes   = await formatter.FormatTokenAsync(token, CancellationToken.None);

            ApplyChanges(buffer, changes);
        }
예제 #9
0
        private static async Task <Document> AddUsingDirectivesAsync(
            Document document, SyntaxNode root, BaseNamespaceDeclarationSyntax namespaceDeclaration, CancellationToken cancellationToken)
        {
            var addImportsService    = document.GetRequiredLanguageService <IAddImportsService>();
            var removeImportsService = document.GetRequiredLanguageService <IRemoveUnnecessaryImportsService>();

            var annotation = new SyntaxAnnotation();

            using var _ = ArrayBuilder <UsingDirectiveSyntax> .GetInstance(out var directives);

            AddUsingDirectives(namespaceDeclaration.Name, annotation, directives);

            var generator = document.GetRequiredLanguageService <SyntaxGenerator>();

            var addImportOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            var documentWithImportsAdded = document.WithSyntaxRoot(addImportsService.AddImports(
                                                                       compilation: null !, root, contextLocation: null, directives, generator,
                                                                       addImportOptions,
                                                                       cancellationToken));

            return(await removeImportsService.RemoveUnnecessaryImportsAsync(
                       documentWithImportsAdded, n => n.HasAnnotation(annotation), formattingOptions, cancellationToken).ConfigureAwait(false));
        }
        private static async Task <Document> RemoveUnnecessaryImportsAsync(
            Document document, CancellationToken cancellationToken)
        {
            var service = document.GetLanguageService <IRemoveUnnecessaryImportsService>();
            var syntaxFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            return(await service.RemoveUnnecessaryImportsAsync(document, syntaxFormattingOptions, cancellationToken).ConfigureAwait(false));
        }
예제 #11
0
    // TODO: move to LSP layer
    public static async Task <IndentationOptions> GetIndentationOptionsAsync(this IGlobalOptionService globalOptions, Document document, CancellationToken cancellationToken)
    {
        var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

        var autoFormattingOptions = globalOptions.GetAutoFormattingOptions(document.Project.Language);
        var indentStyle           = globalOptions.GetOption(SmartIndent, document.Project.Language);

        return(new(formattingOptions, autoFormattingOptions, indentStyle));
    }
예제 #12
0
            protected override async Task<Document> GetChangedSuppressionDocumentAsync(CancellationToken cancellationToken)
            {
                var suppressionsDoc = await GetOrCreateSuppressionsDocumentAsync(cancellationToken).ConfigureAwait(false);
                var services = suppressionsDoc.Project.Solution.Workspace.Services;
                var suppressionsRoot = await suppressionsDoc.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
                var addImportsService = suppressionsDoc.GetRequiredLanguageService<IAddImportsService>();
                var options = await SyntaxFormattingOptions.FromDocumentAsync(suppressionsDoc, cancellationToken).ConfigureAwait(false);

                suppressionsRoot = Fixer.AddGlobalSuppressMessageAttribute(
                    suppressionsRoot, _targetSymbol, _suppressMessageAttribute, _diagnostic, services, options, addImportsService, cancellationToken);
                return suppressionsDoc.WithSyntaxRoot(suppressionsRoot);
            }
            protected override async Task <Document> PostProcessChangesAsync(Document document, CancellationToken cancellationToken)
            {
                var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

                document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken : cancellationToken).ConfigureAwait(false);

                document = await Formatter.FormatAsync(document, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false);

                document = await CaseCorrector.CaseCorrectAsync(document, CaseCorrector.Annotation, cancellationToken).ConfigureAwait(false);

                return(document);
            }
예제 #14
0
            protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
            {
                using var _ = ArrayBuilder <IMethodSymbol> .GetInstance(out var methods);

                if (_generateEquals)
                {
                    methods.Add(await CreateEqualsMethodAsync(cancellationToken).ConfigureAwait(false));
                }

                var constructedTypeToImplement = await GetConstructedTypeToImplementAsync(cancellationToken).ConfigureAwait(false);

                if (constructedTypeToImplement is object)
                {
                    methods.Add(await CreateIEquatableEqualsMethodAsync(constructedTypeToImplement, cancellationToken).ConfigureAwait(false));
                }

                if (_generateGetHashCode)
                {
                    methods.Add(await CreateGetHashCodeMethodAsync(cancellationToken).ConfigureAwait(false));
                }

                if (_generateOperators)
                {
                    await AddOperatorsAsync(methods, cancellationToken).ConfigureAwait(false);
                }

                var codeGenerator  = _document.GetRequiredLanguageService <ICodeGenerationService>();
                var codeGenOptions = await CodeGenerationOptions.FromDocumentAsync(CodeGenerationContext.Default, _document, cancellationToken).ConfigureAwait(false);

                var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(_document, cancellationToken).ConfigureAwait(false);

                var newTypeDeclaration = codeGenerator.AddMembers(_typeDeclaration, methods, codeGenOptions, cancellationToken);

                if (constructedTypeToImplement is object)
                {
                    var generator = _document.GetRequiredLanguageService <SyntaxGenerator>();

                    newTypeDeclaration = generator.AddInterfaceType(newTypeDeclaration,
                                                                    generator.TypeExpression(constructedTypeToImplement));
                }

                var newDocument = await UpdateDocumentAndAddImportsAsync(
                    _typeDeclaration, newTypeDeclaration, cancellationToken).ConfigureAwait(false);

                var service           = _document.GetRequiredLanguageService <IGenerateEqualsAndGetHashCodeService>();
                var formattedDocument = await service.FormatDocumentAsync(
                    newDocument, formattingOptions, cancellationToken).ConfigureAwait(false);

                return(formattedDocument);
            }
예제 #15
0
        private int FormatWorker(IVsTextLayer textLayer, TextSpan[] selections, CancellationToken cancellationToken)
        {
            var textBuffer = this.EditorAdaptersFactoryService.GetDataBuffer((IVsTextBuffer)textLayer);

            if (textBuffer == null)
            {
                return(VSConstants.E_UNEXPECTED);
            }

            var document = textBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();

            if (document == null)
            {
                return(VSConstants.E_FAIL);
            }

            var root    = document.GetSyntaxRootSynchronously(cancellationToken);
            var text    = root.SyntaxTree.GetText(cancellationToken);
            var options = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken);

            var ts           = selections.Single();
            var start        = text.Lines[ts.iStartLine].Start + ts.iStartIndex;
            var end          = text.Lines[ts.iEndLine].Start + ts.iEndIndex;
            var adjustedSpan = GetFormattingSpan(root, start, end);

            // Since we know we are on the UI thread, lets get the base indentation now, so that there is less
            // cleanup work to do later in Venus.
            var ruleFactory = Workspace.Services.GetService <IHostDependentFormattingRuleFactoryService>();
            var rules       = ruleFactory.CreateRule(document, start).Concat(Formatter.GetDefaultFormattingRules(document));

            // use formatting that return text changes rather than tree rewrite which is more expensive
            var formatter       = document.GetRequiredLanguageService <ISyntaxFormattingService>();
            var originalChanges = formatter.GetFormattingResult(root, SpecializedCollections.SingletonEnumerable(adjustedSpan), options, rules, cancellationToken)
                                  .GetTextChanges(cancellationToken);

            var originalSpan     = RoslynTextSpan.FromBounds(start, end);
            var formattedChanges = ruleFactory.FilterFormattedChanges(document, originalSpan, originalChanges);

            if (formattedChanges.IsEmpty())
            {
                return(VSConstants.S_OK);
            }

            // create new formatted document
            var formattedDocument = document.WithText(text.WithChanges(formattedChanges));

            Workspace.ApplyDocumentChanges(formattedDocument, cancellationToken);

            return(VSConstants.S_OK);
        }
예제 #16
0
        private static Document Format(ICommentSelectionService service, ITextSnapshot snapshot, IEnumerable <SnapshotSpan> changes, CancellationToken cancellationToken)
        {
            var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();

            if (document == null)
            {
                return(null);
            }

            var formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken);
            var textSpans         = changes.SelectAsArray(change => change.Span.ToTextSpan());

            return(service.FormatAsync(document, textSpans, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken));
        }
        private static async Task <Document> RemoveUnnecessaryImportsAsync(
#endif
            Document document,
            CancellationToken cancellationToken)
        {
#if CODE_STYLE
            var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var formattingOptions = GetSyntaxFormatting().GetFormattingOptions(document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree));
#else
            var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);
#endif
            var service = document.GetRequiredLanguageService <IRemoveUnnecessaryImportsService>();
            return(await service.RemoveUnnecessaryImportsAsync(document, formattingOptions, cancellationToken).ConfigureAwait(false));
        }
        public async Task <Document> AddSourceToAsync(Document document, Compilation symbolCompilation, ISymbol symbol, CancellationToken cancellationToken)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            var newSemanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var rootNamespace = newSemanticModel.GetEnclosingNamespace(0, cancellationToken);

            var context = new CodeGenerationContext(
                contextLocation: newSemanticModel.SyntaxTree.GetLocation(new TextSpan()),
                generateMethodBodies: false,
                generateDocumentationComments: true,
                mergeAttributes: false,
                autoInsertionLocation: false);

            // Add the interface of the symbol to the top of the root namespace
            document = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync(
                document.Project.Solution,
                rootNamespace,
                CreateCodeGenerationSymbol(document, symbol),
                context,
                cancellationToken).ConfigureAwait(false);

            document = await AddNullableRegionsAsync(document, cancellationToken).ConfigureAwait(false);

            var docCommentFormattingService = document.GetLanguageService <IDocumentationCommentFormattingService>();
            var docWithDocComments          = await ConvertDocCommentsToRegularCommentsAsync(document, docCommentFormattingService, cancellationToken).ConfigureAwait(false);

            var docWithAssemblyInfo = await AddAssemblyInfoRegionAsync(docWithDocComments, symbolCompilation, symbol.GetOriginalUnreducedDefinition(), cancellationToken).ConfigureAwait(false);

            var node = await docWithAssemblyInfo.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var options = await SyntaxFormattingOptions.FromDocumentAsync(docWithAssemblyInfo, cancellationToken).ConfigureAwait(false);

            var formattedDoc = await Formatter.FormatAsync(
                docWithAssemblyInfo,
                SpecializedCollections.SingletonEnumerable(node.FullSpan),
                options,
                GetFormattingRules(docWithAssemblyInfo),
                cancellationToken).ConfigureAwait(false);

            var reducers = GetReducers();

            return(await Simplifier.ReduceAsync(formattedDoc, reducers, null, cancellationToken).ConfigureAwait(false));
        }
        public static async Task <Document> FormatDocumentAsync(Document document, CancellationToken cancellationToken)
        {
            var node = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            // Apply formatting rules
            var formattedDoc = await Formatter.FormatAsync(
                document,
                SpecializedCollections.SingletonEnumerable(node.FullSpan),
                options,
                CSharpDecompiledSourceFormattingRule.Instance.Concat(Formatter.GetDefaultFormattingRules(document)),
                cancellationToken).ConfigureAwait(false);

            return(formattedDoc);
        }
        private static async Task <Document> CleanUpNewLinesAsync(Document document, IEnumerable <TextSpan> insertSpans, CancellationToken cancellationToken)
        {
            var options = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            var newDocument = document;

            // Since imports can be added at both the CompilationUnit and the Namespace level,
            // format each span individually so that we can retain each newline that was intended
            // to separate the import section from the other content.
            foreach (var insertSpan in insertSpans)
            {
                newDocument = await CleanUpNewLinesAsync(newDocument, insertSpan, options, cancellationToken).ConfigureAwait(false);
            }

            return(newDocument);
        }
예제 #21
0
        protected override async Task FixAllAsync(
            Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor,
            CancellationToken cancellationToken)
        {
            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            // Defer to our callback to actually make the edits for each diagnostic. In turn, it
            // will return 'true' if it made a multi-line conditional expression. In that case,
            // we'll need to explicitly format this node so we can get our special multi-line
            // formatting in VB and C#.
            var nestedEditor = new SyntaxEditor(root, document.Project.Solution.Workspace.Services);

            foreach (var diagnostic in diagnostics)
            {
                await FixOneAsync(
                    document, diagnostic, nestedEditor, cancellationToken).ConfigureAwait(false);
            }

            var changedRoot = nestedEditor.GetChangedRoot();

            // Get the language specific rule for formatting this construct and call into the
            // formatted to explicitly format things.  Note: all we will format is the new
            // conditional expression as that's the only node that has the appropriate
            // annotation on it.
            var rules = new List <AbstractFormattingRule> {
                GetMultiLineFormattingRule()
            };

#if CODE_STYLE
            var provider = GetSyntaxFormattingService();
            var options  = provider.GetFormattingOptions(document.Project.AnalyzerOptions.GetAnalyzerOptionSet(root.SyntaxTree, cancellationToken));
#else
            var provider = document.Project.Solution.Workspace.Services;
            var options  = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);
#endif
            var formattedRoot = Formatter.Format(changedRoot, SpecializedFormattingAnnotation, provider, options, rules, cancellationToken);

            changedRoot = formattedRoot;

            editor.ReplaceNode(root, changedRoot);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var(document, span, cancellationToken) = context;
            if (!span.IsEmpty)
            {
                return;
            }

            var position = span.Start;
            var root     = (CompilationUnitSyntax)await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token         = root.FindToken(position);
            var namespaceDecl = token.GetAncestor <BaseNamespaceDeclarationSyntax>();

            if (namespaceDecl == null)
            {
                return;
            }

            if (!IsValidPosition(namespaceDecl, position))
            {
                return;
            }

            var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var info =
                CanOfferUseBlockScoped(optionSet, namespaceDecl, forAnalyzer: false) ? GetInfo(NamespaceDeclarationPreference.BlockScoped) :
                CanOfferUseFileScoped(optionSet, root, namespaceDecl, forAnalyzer: false) ? GetInfo(NamespaceDeclarationPreference.FileScoped) :
                ((string title, string equivalenceKey)?)null;

            if (info == null)
            {
                return;
            }

            var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            context.RegisterRefactoring(new MyCodeAction(
                                            info.Value.title, c => ConvertAsync(document, namespaceDecl, formattingOptions, c), info.Value.equivalenceKey));
        }
예제 #23
0
        internal void PerformEdit(Func <Document, Document> action)
        {
            EnsureEditor(() =>
            {
                Debug.Assert(_invisibleEditor != null);

                var document  = GetDocument();
                var workspace = document.Project.Solution.Workspace;

                var result = action(document);

                var formatted = State.ThreadingContext.JoinableTaskFactory.Run(async() =>
                {
                    var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(result, CancellationToken.None).ConfigureAwait(false);
                    var formatted         = await Formatter.FormatAsync(result, Formatter.Annotation, formattingOptions, CancellationToken.None).ConfigureAwait(true);
                    formatted             = await Formatter.FormatAsync(formatted, SyntaxAnnotation.ElasticAnnotation, formattingOptions, CancellationToken.None).ConfigureAwait(true);

                    return(formatted);
                });

                ApplyChanges(workspace, formatted);
            });
        }
예제 #24
0
        /// <summary>
        /// format given snapshot and apply text changes to buffer
        /// </summary>
        public static void FormatAndApplyToBuffer(this ITextSnapshot snapshot, TextSpan span, IEnumerable <AbstractFormattingRule>?rules, CancellationToken cancellationToken)
        {
            var document = snapshot.GetOpenDocumentInCurrentContextWithChanges();

            if (document == null)
            {
                return;
            }

            rules = document.GetFormattingRules(span, rules);

            var root      = document.GetRequiredSyntaxRootSynchronously(cancellationToken);
            var formatter = document.GetRequiredLanguageService <ISyntaxFormattingService>();

            var options = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken);
            var result  = formatter.GetFormattingResult(root, SpecializedCollections.SingletonEnumerable(span), options, rules, cancellationToken);
            var changes = result.GetTextChanges(cancellationToken);

            using (Logger.LogBlock(FunctionId.Formatting_ApplyResultToBuffer, cancellationToken))
            {
                document.Project.Solution.Workspace.ApplyTextChanges(document.Id, changes, cancellationToken);
            }
        }
예제 #25
0
        public override async Task <Document> RemoveUnnecessaryImportsAsync(
            Document document,
            Func <SyntaxNode, bool> predicate,
            CancellationToken cancellationToken)
        {
            predicate ??= Functions <SyntaxNode> .True;
            using (Logger.LogBlock(FunctionId.Refactoring_RemoveUnnecessaryImports_CSharp, cancellationToken))
            {
                var unnecessaryImports = await GetCommonUnnecessaryImportsOfAllContextAsync(
                    document, predicate, cancellationToken).ConfigureAwait(false);

                if (unnecessaryImports == null || unnecessaryImports.Any(import => import.OverlapsHiddenPosition(cancellationToken)))
                {
                    return(document);
                }

                var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var oldRoot = (CompilationUnitSyntax)root;
                var newRoot = (CompilationUnitSyntax) new Rewriter(document, unnecessaryImports, cancellationToken).Visit(oldRoot);

                cancellationToken.ThrowIfCancellationRequested();
#if CODE_STYLE
                var provider  = GetSyntaxFormattingService();
                var optionSet = document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(oldRoot.SyntaxTree);
                var options   = SyntaxFormattingOptions.Create(optionSet);
#else
                var provider = document.Project.Solution.Workspace.Services;
                var options  = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);
#endif
                var spans = new List <TextSpan>();
                AddFormattingSpans(newRoot, spans, cancellationToken);
                var formattedRoot = Formatter.Format(newRoot, spans, provider, options, rules: null, cancellationToken);

                return(document.WithSyntaxRoot(formattedRoot));
            }
        }
        private Solution CreateSolutionWithEventHandler(
            Document document,
            string eventHandlerMethodName,
            int position,
            out int plusEqualTokenEndPosition,
            CancellationToken cancellationToken)
        {
            _threadingContext.ThrowIfNotOnUIThread();

            // Mark the += token with an annotation so we can find it after formatting
            var plusEqualsTokenAnnotation = new SyntaxAnnotation();

            var documentWithNameAndAnnotationsAdded = AddMethodNameAndAnnotationsToSolution(document, eventHandlerMethodName, position, plusEqualsTokenAnnotation, cancellationToken);
            var semanticDocument = SemanticDocument.CreateAsync(documentWithNameAndAnnotationsAdded, cancellationToken).WaitAndGetResult(cancellationToken);
            var preferences      = CSharpCodeGenerationPreferences.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken);
            var updatedRoot      = AddGeneratedHandlerMethodToSolution(semanticDocument, preferences, eventHandlerMethodName, plusEqualsTokenAnnotation, cancellationToken);

            if (updatedRoot == null)
            {
                plusEqualTokenEndPosition = 0;
                return(null);
            }

            var formattingOptions = SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).WaitAndGetResult(cancellationToken);

            var simplifiedDocument = Simplifier.ReduceAsync(documentWithNameAndAnnotationsAdded.WithSyntaxRoot(updatedRoot), Simplifier.Annotation, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);
            var formattedDocument  = Formatter.FormatAsync(simplifiedDocument, Formatter.Annotation, formattingOptions, cancellationToken).WaitAndGetResult(cancellationToken);

            var newRoot = formattedDocument.GetSyntaxRootSynchronously(cancellationToken);

            plusEqualTokenEndPosition = newRoot.GetAnnotatedNodesAndTokens(plusEqualsTokenAnnotation)
                                        .Single().Span.End;

            return(document.Project.Solution.WithDocumentText(
                       formattedDocument.Id, formattedDocument.GetTextSynchronously(cancellationToken)));
        }
예제 #27
0
        private async Task <ImmutableArray <CodeFix> > GetSuppressionsAsync(
            Document documentOpt, Project project, IEnumerable <Diagnostic> diagnostics, SuppressionTargetInfo suppressionTargetInfo, bool skipSuppressMessage, bool skipUnsuppress, CancellationToken cancellationToken)
        {
            // We only care about diagnostics that can be suppressed/unsuppressed.
            diagnostics = diagnostics.Where(IsFixableDiagnostic);
            if (diagnostics.IsEmpty())
            {
                return(ImmutableArray <CodeFix> .Empty);
            }

            INamedTypeSymbol suppressMessageAttribute = null;

            if (!skipSuppressMessage)
            {
                var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                suppressMessageAttribute = compilation.SuppressMessageAttributeType();
                skipSuppressMessage      = suppressMessageAttribute == null || !suppressMessageAttribute.IsAttribute();
            }

            var lazyFormattingOptions = (SyntaxFormattingOptions)null;
            var result = ArrayBuilder <CodeFix> .GetInstance();

            foreach (var diagnostic in diagnostics)
            {
                if (!diagnostic.IsSuppressed)
                {
                    var nestedActions = ArrayBuilder <NestedSuppressionCodeAction> .GetInstance();

                    if (diagnostic.Location.IsInSource && documentOpt != null)
                    {
                        // pragma warning disable.
                        lazyFormattingOptions ??= await SyntaxFormattingOptions.FromDocumentAsync(documentOpt, cancellationToken).ConfigureAwait(false);

                        nestedActions.Add(PragmaWarningCodeAction.Create(suppressionTargetInfo, documentOpt, lazyFormattingOptions, diagnostic, this));
                    }

                    // SuppressMessageAttribute suppression is not supported for compiler diagnostics.
                    if (!skipSuppressMessage && SuppressionHelpers.CanBeSuppressedWithAttribute(diagnostic))
                    {
                        // global assembly-level suppress message attribute.
                        nestedActions.Add(new GlobalSuppressMessageCodeAction(
                                              suppressionTargetInfo.TargetSymbol, suppressMessageAttribute, project, diagnostic, this));

                        // local suppress message attribute
                        // please note that in order to avoid issues with existing unit tests referencing the code fix
                        // by their index this needs to be the last added to nestedActions
                        if (suppressionTargetInfo.TargetMemberNode != null && suppressionTargetInfo.TargetSymbol.Kind != SymbolKind.Namespace)
                        {
                            nestedActions.Add(new LocalSuppressMessageCodeAction(
                                                  this, suppressionTargetInfo.TargetSymbol, suppressMessageAttribute, suppressionTargetInfo.TargetMemberNode, documentOpt, diagnostic));
                        }
                    }

                    if (nestedActions.Count > 0)
                    {
                        var codeAction = new TopLevelSuppressionCodeAction(
                            diagnostic, nestedActions.ToImmutableAndFree());
                        result.Add(new CodeFix(project, codeAction, diagnostic));
                    }
                }
                else if (!skipUnsuppress)
                {
                    var codeAction = await RemoveSuppressionCodeAction.CreateAsync(suppressionTargetInfo, documentOpt, project, diagnostic, this, cancellationToken).ConfigureAwait(false);

                    if (codeAction != null)
                    {
                        result.Add(new CodeFix(project, codeAction, diagnostic));
                    }
                }
            }

            return(result.ToImmutableAndFree());
        }
        public override async Task <CompletionChange> GetChangeAsync(
            Document document, CompletionItem completionItem, char?commitKey, CancellationToken cancellationToken)
        {
            var containingNamespace          = ImportCompletionItem.GetContainingNamespace(completionItem);
            var provideParenthesisCompletion = await ShouldProvideParenthesisCompletionAsync(
                document,
                completionItem,
                commitKey,
                cancellationToken).ConfigureAwait(false);

            var insertText = completionItem.DisplayText;

            if (provideParenthesisCompletion)
            {
                insertText += "()";
                CompletionProvidersLogger.LogCustomizedCommitToAddParenthesis(commitKey);
            }

            if (await ShouldCompleteWithFullyQualifyTypeName().ConfigureAwait(false))
            {
                var completionText = $"{containingNamespace}.{insertText}";
                return(CompletionChange.Create(new TextChange(completionItem.Span, completionText)));
            }

            // Find context node so we can use it to decide where to insert using/imports.
            var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false);

            var addImportContextNode = root.FindToken(completionItem.Span.Start, findInsideTrivia: true).Parent;

            // Add required using/imports directive.
            var addImportService = document.GetRequiredLanguageService <IAddImportsService>();
            var generator        = document.GetRequiredLanguageService <SyntaxGenerator>();

            var addImportsOptions = await AddImportPlacementOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            var importNode = CreateImport(document, containingNamespace);

            var compilation = await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false);

            var rootWithImport     = addImportService.AddImport(compilation, root, addImportContextNode !, importNode, generator, addImportsOptions, cancellationToken);
            var documentWithImport = document.WithSyntaxRoot(rootWithImport);
            // This only formats the annotated import we just added, not the entire document.
            var formattedDocumentWithImport = await Formatter.FormatAsync(documentWithImport, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false);

            using var _ = ArrayBuilder <TextChange> .GetInstance(out var builder);

            // Get text change for add import
            var importChanges = await formattedDocumentWithImport.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(false);

            builder.AddRange(importChanges);

            // Create text change for complete type name.
            //
            // Note: Don't try to obtain TextChange for completed type name by replacing the text directly,
            //       then use Document.GetTextChangesAsync on document created from the changed text. This is
            //       because it will do a diff and return TextChanges with minimum span instead of actual
            //       replacement span.
            //
            //       For example: If I'm typing "asd", the completion provider could be triggered after "a"
            //       is typed. Then if I selected type "AsnEncodedData" to commit, by using the approach described
            //       above, we will get a TextChange of "AsnEncodedDat" with 0 length span, instead of a change of
            //       the full display text with a span of length 1. This will later mess up span-tracking and end up
            //       with "AsnEncodedDatasd" in the code.
            builder.Add(new TextChange(completionItem.Span, insertText));

            // Then get the combined change
            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var newText = text.WithChanges(builder);

            var changes = builder.ToImmutable();
            var change  = Utilities.Collapse(newText, changes);

            return(CompletionChange.Create(change, changes));

            async Task <bool> ShouldCompleteWithFullyQualifyTypeName()
            {
                if (!IsAddingImportsSupported(document))
                {
                    return(true);
                }

                // We might need to qualify unimported types to use them in an import directive, because they only affect members of the containing
                // import container (e.g. namespace/class/etc. declarations).
                //
                // For example, `List` and `StringBuilder` both need to be fully qualified below:
                //
                //      using CollectionOfStringBuilders = System.Collections.Generic.List<System.Text.StringBuilder>;
                //
                // However, if we are typing in an C# using directive that is inside a nested import container (i.e. inside a namespace declaration block),
                // then we can add an using in the outer import container instead (this is not allowed in VB).
                //
                // For example:
                //
                //      using System.Collections.Generic;
                //      using System.Text;
                //
                //      namespace Foo
                //      {
                //          using CollectionOfStringBuilders = List<StringBuilder>;
                //      }
                //
                // Here we will always choose to qualify the unimported type, just to be consistent and keeps things simple.
                return(await IsInImportsDirectiveAsync(document, completionItem.Span.Start, cancellationToken).ConfigureAwait(false));
            }
        }
예제 #29
0
        public static async Task <(Document containingDocument, SyntaxAnnotation typeAnnotation)> AddTypeToNewFileAsync(
            Solution solution,
            string containingNamespaceDisplay,
            string fileName,
            ProjectId projectId,
            IEnumerable <string> folders,
            INamedTypeSymbol newSymbol,
            Document hintDocument,
            CancellationToken cancellationToken)
        {
            var newDocumentId   = DocumentId.CreateNewId(projectId, debugName: fileName);
            var newDocumentPath = PathUtilities.CombinePaths(PathUtilities.GetDirectoryName(hintDocument.FilePath), fileName);

            var solutionWithInterfaceDocument = solution.AddDocument(newDocumentId, fileName, text: "", folders: folders, filePath: newDocumentPath);
            var newDocument      = solutionWithInterfaceDocument.GetRequiredDocument(newDocumentId);
            var newSemanticModel = await newDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var context = new CodeGenerationContext(
                contextLocation: newSemanticModel.SyntaxTree.GetLocation(new TextSpan()),
                generateMethodBodies: true);

            // need to remove the root namespace from the containing namespace display because it is implied
            // For C# this does nothing as there is no root namespace (root namespace is empty string)
            var generateTypeService = newDocument.GetRequiredLanguageService <IGenerateTypeService>();
            var rootNamespace       = generateTypeService.GetRootNamespace(newDocument.Project.CompilationOptions);
            var index = rootNamespace.IsEmpty() ? -1 : containingNamespaceDisplay.IndexOf(rootNamespace);
            // if we did find the root namespace as the first element, then we remove it
            // this may leave us with an extra "." character at the start, but when we split it shouldn't matter
            var namespaceWithoutRoot = index == 0
                ? containingNamespaceDisplay.Remove(index, rootNamespace.Length)
                : containingNamespaceDisplay;

            var namespaceParts  = namespaceWithoutRoot.Split('.').Where(s => !string.IsNullOrEmpty(s));
            var newTypeDocument = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync(
                newDocument.Project.Solution,
                newSemanticModel.GetEnclosingNamespace(0, cancellationToken),
                newSymbol.GenerateRootNamespaceOrType(namespaceParts.ToArray()),
                context,
                cancellationToken).ConfigureAwait(false);

            var newTypeFormattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(newTypeDocument, cancellationToken).ConfigureAwait(false);

            var formattingService = newTypeDocument.GetLanguageService <INewDocumentFormattingService>();

            if (formattingService is not null)
            {
                newTypeDocument = await formattingService.FormatNewDocumentAsync(newTypeDocument, hintDocument, newTypeFormattingOptions, cancellationToken).ConfigureAwait(false);
            }

            var syntaxRoot = await newTypeDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var typeAnnotation = new SyntaxAnnotation();
            var syntaxFacts    = newTypeDocument.GetRequiredLanguageService <ISyntaxFactsService>();

            var declarationNode = syntaxRoot.DescendantNodes().First(syntaxFacts.IsTypeDeclaration);
            var annotatedRoot   = syntaxRoot.ReplaceNode(declarationNode, declarationNode.WithAdditionalAnnotations(typeAnnotation));

            newTypeDocument = newTypeDocument.WithSyntaxRoot(annotatedRoot);

            var simplified = await Simplifier.ReduceAsync(newTypeDocument, cancellationToken : cancellationToken).ConfigureAwait(false);

            var formattedDocument = await Formatter.FormatAsync(simplified, newTypeFormattingOptions, cancellationToken).ConfigureAwait(false);

            return(formattedDocument, typeAnnotation);
        }
예제 #30
0
        public async Task <ExtractClassOptions?> GetExtractClassOptionsAsync(Document document, INamedTypeSymbol selectedType, ISymbol?selectedMember, CancellationToken cancellationToken)
        {
            var notificationService = document.Project.Solution.Workspace.Services.GetRequiredService <INotificationService>();

            var membersInType = selectedType.GetMembers().
                                WhereAsArray(member => MemberAndDestinationValidator.IsMemberValid(member));

            var memberViewModels = membersInType
                                   .SelectAsArray(member =>
                                                  new PullMemberUpSymbolViewModel(member, _glyphService)
            {
                // The member user selected will be checked at the beginning.
                IsChecked               = SymbolEquivalenceComparer.Instance.Equals(selectedMember, member),
                MakeAbstract            = false,
                IsMakeAbstractCheckable = !member.IsKind(SymbolKind.Field) && !member.IsAbstract,
                IsCheckable             = true
            });

            var memberToDependentsMap = SymbolDependentsBuilder.FindMemberToDependentsMap(membersInType, document.Project, cancellationToken);

            var conflictingTypeNames = selectedType.ContainingNamespace.GetAllTypes(cancellationToken).Select(t => t.Name);
            var candidateName        = selectedType.Name + "Base";
            var defaultTypeName      = NameGenerator.GenerateUniqueName(candidateName, name => !conflictingTypeNames.Contains(name));

            var containingNamespaceDisplay = selectedType.ContainingNamespace.IsGlobalNamespace
                ? string.Empty
                : selectedType.ContainingNamespace.ToDisplayString();

            var formattingOptions = await SyntaxFormattingOptions.FromDocumentAsync(document, cancellationToken).ConfigureAwait(false);

            var generatedNameTypeParameterSuffix = ExtractTypeHelpers.GetTypeParameterSuffix(document, formattingOptions, selectedType, membersInType, cancellationToken);

            var viewModel = new ExtractClassViewModel(
                _uiThreadOperationExecutor,
                notificationService,
                memberViewModels,
                memberToDependentsMap,
                defaultTypeName,
                containingNamespaceDisplay,
                document.Project.Language,
                generatedNameTypeParameterSuffix,
                conflictingTypeNames.ToImmutableArray(),
                document.GetRequiredLanguageService <ISyntaxFactsService>());

            await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

            var dialog = new ExtractClassDialog(viewModel);

            var result = dialog.ShowModal();

            if (result.GetValueOrDefault())
            {
                return(new ExtractClassOptions(
                           viewModel.DestinationViewModel.FileName,
                           viewModel.DestinationViewModel.TypeName,
                           viewModel.DestinationViewModel.Destination == CommonControls.NewTypeDestination.CurrentFile,
                           viewModel.MemberSelectionViewModel.CheckedMembers.SelectAsArray(m => new ExtractClassMemberAnalysisResult(m.Symbol, m.MakeAbstract))));
            }

            return(null);
        }