Ejemplo n.º 1
0
        public async Task <CodeAction> IntroduceVariableAsync(
            Document document,
            TextSpan textSpan,
            CodeCleanupOptions options,
            CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.Refactoring_IntroduceVariable, cancellationToken))
            {
                var semanticDocument = await SemanticDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false);

                var state = await State.GenerateAsync((TService)this, semanticDocument, options, textSpan, cancellationToken).ConfigureAwait(false);

                if (state != null)
                {
                    var(title, actions) = CreateActions(state, cancellationToken);
                    if (actions.Length > 0)
                    {
                        // We may end up creating a lot of viable code actions for the selected
                        // piece of code.  Create a top level code action so that we don't overwhelm
                        // the light bulb if there are a lot of other options in the list.  Set
                        // the code action as 'inlinable' so that if the lightbulb is not cluttered
                        // then the nested items can just be lifted into it, giving the user fast
                        // access to them.
                        return(CodeActionWithNestedActions.Create(title, actions, isInlinable: true));
                    }
                }

                return(null);
            }
        }
Ejemplo n.º 2
0
 protected virtual (string description, bool hasExistingImport) GetDescription(
     Document document, CodeCleanupOptions options, SyntaxNode node,
     SemanticModel semanticModel, CancellationToken cancellationToken)
 {
     return(provider.GetDescription(
                document, options.AddImportOptions, SymbolResult.Symbol, semanticModel, node, cancellationToken));
 }
Ejemplo n.º 3
0
        private protected static async Task AssertCodeCleanupResult(string expected, string code, CodeStyleOption2 <AddImportPlacement> preferredImportPlacement, bool systemUsingsFirst = true, bool separateUsingGroups = false)
        {
            using var workspace = TestWorkspace.CreateCSharp(code, composition: EditorTestCompositions.EditorFeaturesWpf);

            var solution = workspace.CurrentSolution
                           .WithOptions(workspace.Options
                                        .WithChangedOption(GenerationOptions.PlaceSystemNamespaceFirst, LanguageNames.CSharp, systemUsingsFirst)
                                        .WithChangedOption(GenerationOptions.SeparateImportDirectiveGroups, LanguageNames.CSharp, separateUsingGroups)
                                        .WithChangedOption(CSharpCodeStyleOptions.PreferredUsingDirectivePlacement, preferredImportPlacement))
                           .WithAnalyzerReferences(new[]
            {
                new AnalyzerFileReference(typeof(CSharpCompilerDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile),
                new AnalyzerFileReference(typeof(UseExpressionBodyDiagnosticAnalyzer).Assembly.Location, TestAnalyzerAssemblyLoader.LoadFromFile)
            });

            workspace.TryApplyChanges(solution);

            // register this workspace to solution crawler so that analyzer service associate itself with given workspace
            var incrementalAnalyzerProvider = workspace.ExportProvider.GetExportedValue <IDiagnosticAnalyzerService>() as IIncrementalAnalyzerProvider;

            incrementalAnalyzerProvider.CreateIncrementalAnalyzer(workspace);

            var hostdoc  = workspace.Documents.Single();
            var document = workspace.CurrentSolution.GetDocument(hostdoc.Id);

            var codeCleanupService = document.GetLanguageService <ICodeCleanupService>();

            var enabledDiagnostics = codeCleanupService.GetAllDiagnostics();

            var fallbackOptions = new CodeActionOptions(
                CleanupOptions: CodeCleanupOptions.GetDefault(document.Project.LanguageServices) with
            {
                FormattingOptions = new CSharpSyntaxFormattingOptions(separateImportDirectiveGroups: separateUsingGroups)
            });
Ejemplo n.º 4
0
            private async Task <ImmutableArray <TextChange> > GetTextChangesAsync(
                Document document, SyntaxNode contextNode,
                CodeCleanupOptions options, bool hasExistingImport,
                CancellationToken cancellationToken)
            {
                // Defer to the language to add the actual import/using.
                if (hasExistingImport)
                {
                    return(ImmutableArray <TextChange> .Empty);
                }

                (var newContextNode, var newDocument) = await ReplaceNameNodeAsync(
                    contextNode, document, cancellationToken).ConfigureAwait(false);

                var updatedDocument = await provider.AddImportAsync(
                    newContextNode, SymbolResult.Symbol, newDocument,
                    options.AddImportOptions, cancellationToken).ConfigureAwait(false);

                var cleanedDocument = await CodeAction.CleanupDocumentAsync(
                    updatedDocument, options, cancellationToken).ConfigureAwait(false);

                var textChanges = await cleanedDocument.GetTextChangesAsync(
                    document, cancellationToken).ConfigureAwait(false);

                return(textChanges.ToImmutableArray());
            }
Ejemplo n.º 5
0
        public async Task CodeCleanersCSharp_Document()
        {
            var document      = CreateDocument("class C { }", LanguageNames.CSharp);
            var cleanDocument = await CodeCleaner.CleanupAsync(document, CodeCleanupOptions.GetDefault(document.Project.LanguageServices));

            Assert.Equal(document, cleanDocument);
        }
Ejemplo n.º 6
0
        public async Task CodeCleanersVisualBasic_Document()
        {
            var document      = CreateDocument(@"Class C
End Class", LanguageNames.VisualBasic);
            var cleanDocument = await CodeCleaner.CleanupAsync(document, CodeCleanupOptions.GetDefault(document.Project.LanguageServices));

            Assert.Equal(document, cleanDocument);
        }
Ejemplo n.º 7
0
            public override async Task <AddImportFixData> TryGetFixDataAsync(
                Document document, SyntaxNode node, CodeCleanupOptions options, CancellationToken cancellationToken)
            {
                var textChanges = await GetTextChangesAsync(
                    document, node, options, cancellationToken).ConfigureAwait(false);

                return(AddImportFixData.CreateForPackageSymbol(
                           textChanges, _source, _packageName, _versionOpt));
            }
Ejemplo n.º 8
0
        public async Task CodeCleanersCSharp_Annotation()
        {
            var document   = CreateDocument("class C { }", LanguageNames.CSharp);
            var annotation = new SyntaxAnnotation();

            document = document.WithSyntaxRoot((await document.GetSyntaxRootAsync()).WithAdditionalAnnotations(annotation));

            var cleanDocument = await CodeCleaner.CleanupAsync(document, annotation, CodeCleanupOptions.GetDefault(document.Project.LanguageServices));

            Assert.Equal(document, cleanDocument);
        }
Ejemplo n.º 9
0
 internal IntroduceVariableAllOccurrenceCodeAction(
     TService service,
     SemanticDocument document,
     CodeCleanupOptions options,
     TExpressionSyntax expression,
     bool allOccurrences,
     bool isConstant,
     bool isLocal,
     bool isQueryLocal)
     : base(service, document, options, expression, allOccurrences, isConstant, isLocal, isQueryLocal)
 {
 }
Ejemplo n.º 10
0
            public override async Task <AddImportFixData> TryGetFixDataAsync(
                Document document, SyntaxNode node, CodeCleanupOptions options, CancellationToken cancellationToken)
            {
                var textChanges = await GetTextChangesAsync(document, node, options, cancellationToken).ConfigureAwait(false);

                var title = $"{provider.GetDescription(SearchResult.NameParts)} ({string.Format(FeaturesResources.from_0, _referenceAssemblyWithType.AssemblyName)})";
                var fullyQualifiedTypeName = string.Join(
                    ".", _referenceAssemblyWithType.ContainingNamespaceNames.Concat(_referenceAssemblyWithType.TypeName));

                return(AddImportFixData.CreateForReferenceAssemblySymbol(
                           textChanges, title, _referenceAssemblyWithType.AssemblyName, fullyQualifiedTypeName));
            }
Ejemplo n.º 11
0
            protected override (string description, bool hasExistingImport) GetDescription(
                Document document, CodeCleanupOptions options, SyntaxNode node,
                SemanticModel semanticModel, CancellationToken cancellationToken)
            {
                var(description, hasExistingImport) = base.GetDescription(document, options, node, semanticModel, cancellationToken);
                if (description == null)
                {
                    return(null, false);
                }

                return(string.Format(FeaturesResources.Add_reference_to_0, Path.GetFileName(_reference.FilePath)),
                       hasExistingImport);
            }
            public static async Task <State> GenerateAsync(
                TService service,
                SemanticDocument document,
                CodeCleanupOptions options,
                TextSpan textSpan,
                CancellationToken cancellationToken)
            {
                var state = new State(service, document, options);

                if (!await state.TryInitializeAsync(document, textSpan, cancellationToken).ConfigureAwait(false))
                {
                    return(null);
                }

                return(state);
            }
Ejemplo n.º 13
0
        protected static async Task <SyntaxNode> ExtractMethodAsync(
            TestWorkspace workspace,
            TestHostDocument testDocument,
            bool succeed = true,
            bool dontPutOutOrRefOnStruct = true,
            bool allowBestEffort         = false)
        {
            var document = workspace.CurrentSolution.GetDocument(testDocument.Id);

            Assert.NotNull(document);

            var options = new ExtractMethodGenerationOptions(
                ExtractOptions: new ExtractMethodOptions(dontPutOutOrRefOnStruct),
                CodeGenerationOptions: CodeGenerationOptions.GetDefault(document.Project.LanguageServices),
                AddImportOptions: AddImportPlacementOptions.Default,
                NamingPreferences: _ => NamingStylePreferences.Default);

            var semanticDocument = await SemanticDocument.CreateAsync(document, CancellationToken.None);

            var validator = new CSharpSelectionValidator(semanticDocument, testDocument.SelectedSpans.Single(), options.ExtractOptions, localFunction: false);

            var selectedCode = await validator.GetValidSelectionAsync(CancellationToken.None);

            if (!succeed && selectedCode.Status.FailedWithNoBestEffortSuggestion())
            {
                return(null);
            }

            Assert.True(selectedCode.ContainsValidContext);

            // extract method
            var extractor = new CSharpMethodExtractor((CSharpSelectionResult)selectedCode, options, localFunction: false);
            var result    = await extractor.ExtractMethodAsync(CancellationToken.None);

            Assert.NotNull(result);
            Assert.Equal(succeed,
                         result.Succeeded ||
                         result.SucceededWithSuggestion ||
                         (allowBestEffort && result.Status.HasBestEffort()));

            var(doc, _) = await result.GetFormattedDocumentAsync(CodeCleanupOptions.GetDefault(document.Project.LanguageServices), CancellationToken.None);

            return(doc == null
                ? null
                : await doc.GetSyntaxRootAsync());
        }
Ejemplo n.º 14
0
        internal static async Task <Document> CleanupDocumentAsync(
            Document document, CodeCleanupOptions options, CancellationToken cancellationToken)
        {
            document = await ImportAdder.AddImportsFromSymbolAnnotationAsync(
                document, Simplifier.AddImportsAnnotation, options.AddImportOptions, cancellationToken).ConfigureAwait(false);

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

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

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

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

            return(document);
        }
            protected override (string description, bool hasExistingImport) GetDescription(
                Document document, CodeCleanupOptions options, SyntaxNode node,
                SemanticModel semanticModel, CancellationToken cancellationToken)
            {
                var(description, hasExistingImport) = base.GetDescription(document, options, node, semanticModel, cancellationToken);
                if (description == null)
                {
                    return(null, false);
                }

                var project = document.Project;

                description = project.Id == _project.Id
                    ? description
                    : string.Format(FeaturesResources.Add_reference_to_0, _project.Name);

                return(description, hasExistingImport);
            }
Ejemplo n.º 16
0
            public sealed override async Task <AddImportFixData> TryGetFixDataAsync(
                Document document, SyntaxNode node,
                CodeCleanupOptions options, CancellationToken cancellationToken)
            {
                var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                var(description, hasExistingImport) = GetDescription(document, options, node, semanticModel, cancellationToken);
                if (description == null)
                {
                    return(null);
                }

                if (hasExistingImport && !ShouldAddWithExistingImport(document))
                {
                    return(null);
                }

                var isFuzzy = !SearchResult.DesiredNameMatchesSourceName(document);
                var tags    = GetTags(document);

                if (isFuzzy)
                {
                    // The name is going to change.  Make it clear in the description that this is
                    // going to happen.
                    description = $"{SearchResult.DesiredName} - {description}";

                    // if we were a fuzzy match, and we didn't have any glyph to show, then add the
                    // namespace-glyph to this item. This helps indicate that not only are we fixing
                    // the spelling of this name we are *also* adding a namespace.  This helps as we
                    // have gotten feedback in the past that the 'using/import' addition was
                    // unexpected.
                    if (tags.IsDefaultOrEmpty)
                    {
                        tags = WellKnownTagArrays.Namespace;
                    }
                }

                var textChanges = await GetTextChangesAsync(
                    document, node, options, hasExistingImport, cancellationToken).ConfigureAwait(false);

                return(GetFixData(
                           document, textChanges, description,
                           tags, GetPriority(document)));
            }
        public static async ValueTask <OmniSharpSyntaxFormattingOptionsWrapper> FromDocumentAsync(Document document, OmniSharpLineFormattingOptions fallbackLineFormattingOptions, CancellationToken cancellationToken)
        {
            var defaultOptions  = CodeCleanupOptions.GetDefault(document.Project.LanguageServices);
            var fallbackOptions = defaultOptions with
            {
                FormattingOptions = defaultOptions.FormattingOptions.With(new LineFormattingOptions
                {
                    IndentationSize = fallbackLineFormattingOptions.IndentationSize,
                    TabSize         = fallbackLineFormattingOptions.TabSize,
                    UseTabs         = fallbackLineFormattingOptions.UseTabs,
                    NewLine         = fallbackLineFormattingOptions.NewLine,
                })
            };

            var cleanupOptions = await document.GetCodeCleanupOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false);

            return(new OmniSharpSyntaxFormattingOptionsWrapper(cleanupOptions));
        }
    }
            public override ValueTask <CleanCodeGenerationOptions> GetCleanCodeGenerationOptionsAsync(HostLanguageServices languageServices, CancellationToken cancellationToken)
            {
                var lineFormattingOptions = _lineFormattingOptionsProvider.GetLineFormattingOptions();
                var codeGenerationOptions = CleanCodeGenerationOptions.GetDefault(languageServices) with
                {
                    CleanupOptions = CodeCleanupOptions.GetDefault(languageServices) with
                    {
                        FormattingOptions = SyntaxFormattingOptions.GetDefault(languageServices).With(new LineFormattingOptions
                        {
                            IndentationSize = lineFormattingOptions.IndentationSize,
                            TabSize         = lineFormattingOptions.TabSize,
                            UseTabs         = lineFormattingOptions.UseTabs,
                            NewLine         = lineFormattingOptions.NewLine,
                        })
                    }
                };

                return(new ValueTask <CleanCodeGenerationOptions>(codeGenerationOptions));
            }
Ejemplo n.º 19
0
            protected async Task <ImmutableArray <TextChange> > GetTextChangesAsync(
                Document document, SyntaxNode node, CodeCleanupOptions options, CancellationToken cancellationToken)
            {
                var originalDocument = document;

                (node, document) = await ReplaceNameNodeAsync(
                    node, document, cancellationToken).ConfigureAwait(false);

                var newDocument = await provider.AddImportAsync(
                    node, SearchResult.NameParts, document, options.AddImportOptions, cancellationToken).ConfigureAwait(false);

                var cleanedDocument = await CodeAction.CleanupDocumentAsync(
                    newDocument, options, cancellationToken).ConfigureAwait(false);

                var textChanges = await cleanedDocument.GetTextChangesAsync(
                    originalDocument, cancellationToken).ConfigureAwait(false);

                return(textChanges.ToImmutableArray());
            }
Ejemplo n.º 20
0
        private static async Task <ImmutableArray <CodeAction> > GetCodeActionsAsync(
            Document document,
            TextSpan textSpan,
            ExtractMethodGenerationOptions extractOptions,
            CodeCleanupOptions cleanupOptions,
            CancellationToken cancellationToken)
        {
            using var _ = ArrayBuilder <CodeAction> .GetInstance(out var actions);

            var methodAction = await ExtractMethodAsync(document, textSpan, extractOptions, cleanupOptions, cancellationToken).ConfigureAwait(false);

            actions.AddIfNotNull(methodAction);

            var localFunctionAction = await ExtractLocalFunctionAsync(document, textSpan, extractOptions, cleanupOptions, cancellationToken).ConfigureAwait(false);

            actions.AddIfNotNull(localFunctionAction);

            return(actions.ToImmutable());
        }
Ejemplo n.º 21
0
        public async Task DontCrash_VB_2()
        {
            var code          = @"
Public Class Class1
    Public Custom Event Event2 As EventHandler
        AddHandler(ByVal value As EventHandler)
        End AddHandler
        RemoveHandler(ByVal value As EventHandler)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
            e
    End Event

End Class
";
            var document      = CreateDocument(code, LanguageNames.VisualBasic);
            var semanticModel = await document.GetSemanticModelAsync();

            var root = await document.GetSyntaxRootAsync();

            var accessor         = root.DescendantNodes().OfType <VisualBasic.Syntax.AccessorBlockSyntax>().Last();
            var newSemanticModel = await document.ReuseExistingSpeculativeModelAsync(accessor.Statements[0], CancellationToken.None);

            Assert.NotNull(newSemanticModel);
            Assert.False(newSemanticModel.IsSpeculativeSemanticModel);

            var newDocument = CreateDocument(code, LanguageNames.VisualBasic);
            var newRoot     = await newDocument.GetSyntaxRootAsync();

            var newAccessor = newRoot.DescendantNodes().OfType <VisualBasic.Syntax.AccessorBlockSyntax>().Last();

            root             = root.ReplaceNode(accessor, newAccessor);
            document         = document.WithSyntaxRoot(root);
            accessor         = root.DescendantNodes().OfType <VisualBasic.Syntax.AccessorBlockSyntax>().Last();
            newSemanticModel = await document.ReuseExistingSpeculativeModelAsync(accessor.Statements[0], CancellationToken.None);

            Assert.NotNull(newSemanticModel);
            Assert.True(newSemanticModel.IsSpeculativeSemanticModel);

            var cleanDocument = await CodeCleaner.CleanupAsync(document, CodeCleanupOptions.GetDefault(document.Project.LanguageServices));

            Assert.Equal(document, cleanDocument);
        }
Ejemplo n.º 22
0
 internal AbstractIntroduceVariableCodeAction(
     TService service,
     SemanticDocument document,
     CodeCleanupOptions options,
     TExpressionSyntax expression,
     bool allOccurrences,
     bool isConstant,
     bool isLocal,
     bool isQueryLocal)
 {
     _service          = service;
     _semanticDocument = document;
     Options           = options;
     _expression       = expression;
     _allOccurrences   = allOccurrences;
     _isConstant       = isConstant;
     _isLocal          = isLocal;
     _isQueryLocal     = isQueryLocal;
     Title             = CreateDisplayText(expression);
 }
Ejemplo n.º 23
0
        internal async Task TestAsync(string testCode, string expected, OptionsCollection?options = null, ParseOptions?parseOptions = null)
        {
            using var workspace = CreateTestWorkspace(testCode, parseOptions);
            options?.SetGlobalOptions(workspace.GlobalOptions);

            var solution = workspace.CurrentSolution;

            var document         = workspace.CurrentSolution.Projects.First().Documents.First();
            var languageServices = document.Project.LanguageServices;

            var cleanupOptions =
                options?.ToAnalyzerConfigOptions(languageServices).GetCodeCleanupOptions(allowImportsInHiddenRegions: false, fallbackOptions: null, languageServices) ??
                CodeCleanupOptions.GetDefault(languageServices);

            var formattingService = document.GetRequiredLanguageService <INewDocumentFormattingService>();
            var formattedDocument = await formattingService.FormatNewDocumentAsync(document, hintDocument : null, cleanupOptions, CancellationToken.None);

            var actual = await formattedDocument.GetTextAsync();

            AssertEx.EqualOrDiff(expected, actual.ToString());
        }
Ejemplo n.º 24
0
        public void OptionsAreMessagePackSerializable(string language)
        {
            var messagePackOptions = MessagePackSerializerOptions.Standard.WithResolver(MessagePackFormatters.DefaultResolver);

            using var workspace = new AdhocWorkspace();
            var languageServices = workspace.Services.GetLanguageServices(language);

            var options = new object[]
            {
                SimplifierOptions.GetDefault(languageServices),
                SyntaxFormattingOptions.GetDefault(languageServices),
                CodeCleanupOptions.GetDefault(languageServices),
                CodeGenerationOptions.GetDefault(languageServices),
                IdeCodeStyleOptions.GetDefault(languageServices),
                CodeActionOptions.GetDefault(languageServices),
                IndentationOptions.GetDefault(languageServices),
                ExtractMethodGenerationOptions.GetDefault(languageServices),

                // some non-default values:
                new VisualBasicIdeCodeStyleOptions(
                    new IdeCodeStyleOptions.CommonOptions()
                {
                    AllowStatementImmediatelyAfterBlock = new CodeStyleOption2 <bool>(false, NotificationOption2.Error)
                },
                    PreferredModifierOrder: new CodeStyleOption2 <string>("Public Private", NotificationOption2.Error))
            };

            foreach (var original in options)
            {
                using var stream = new MemoryStream();
                MessagePackSerializer.Serialize(stream, original, messagePackOptions);
                stream.Position = 0;

                var deserialized = MessagePackSerializer.Deserialize(original.GetType(), stream, messagePackOptions);
                Assert.Equal(original, deserialized);
            }
        }
Ejemplo n.º 25
0
        private static void VerifyRange(string code, ImmutableArray <ICodeCleanupProvider> codeCleanups, ImmutableArray <TextSpan> spans, ref IEnumerable <TextSpan> expectedResult, string language)
        {
            var result          = (IEnumerable <TextSpan>)null;
            var spanCodeCleanup = new MockCodeCleanupProvider()
            {
                CleanupDocumentAsyncImpl = (document, spans, options, cancellationToken) =>
                {
                    result = spans;
                    return(Task.FromResult(document));
                }
            };

            var document = CreateDocument(code, language);

            CodeCleaner.CleanupAsync(document, spans, CodeCleanupOptions.GetDefault(document.Project.LanguageServices), codeCleanups.Concat(spanCodeCleanup)).Wait();

            var sortedSpans   = result.ToList();
            var expectedSpans = expectedResult.ToList();

            sortedSpans.Sort();
            expectedSpans.Sort();

            AssertEx.Equal(expectedSpans, sortedSpans);
        }
Ejemplo n.º 26
0
        public async Task <Document> FormatNewDocumentAsync(Document document, Document?hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken)
        {
            var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

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

            var namespaces = GetNamespacesToReplace(document, root, optionSet).ToList();

            if (namespaces.Count != 1)
            {
                return(document);
            }

            return(await ConvertNamespaceTransform.ConvertAsync(document, namespaces[0], options.FormattingOptions, cancellationToken).ConfigureAwait(false));
        }
        public async Task <Document> FormatNewDocumentAsync(Document document, Document?hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken)
        {
            var rootToFormat = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            // Apply file header preferences
            var fileHeaderTemplate = options.DocumentFormattingOptions.FileHeaderTemplate;

            if (!string.IsNullOrEmpty(fileHeaderTemplate))
            {
                var newLineTrivia      = SyntaxGeneratorInternal.EndOfLine(options.FormattingOptions.NewLine);
                var rootWithFileHeader = await AbstractFileHeaderCodeFixProvider.GetTransformedSyntaxRootAsync(
                    SyntaxGenerator.SyntaxFacts,
                    FileHeaderHelper,
                    newLineTrivia,
                    document,
                    fileHeaderTemplate,
                    cancellationToken).ConfigureAwait(false);

                return(document.WithSyntaxRoot(rootWithFileHeader));
            }
            else if (hintDocument is not null)
            {
                // If there is no file header preference, see if we can use the one in the hint document
                var bannerService  = hintDocument.GetRequiredLanguageService <IFileBannerFactsService>();
                var hintSyntaxRoot = await hintDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var fileBanner = bannerService.GetFileBanner(hintSyntaxRoot);

                var rootWithBanner = rootToFormat.WithPrependedLeadingTrivia(fileBanner);
                return(document.WithSyntaxRoot(rootWithBanner));
            }

            return(document);
        }
Ejemplo n.º 28
0
        private static async Task <CodeAction> ExtractMethodAsync(Document document, TextSpan textSpan, ExtractMethodGenerationOptions extractOptions, CodeCleanupOptions cleanupOptions, CancellationToken cancellationToken)
        {
            var result = await ExtractMethodService.ExtractMethodAsync(
                document,
                textSpan,
                localFunction : false,
                extractOptions,
                cancellationToken).ConfigureAwait(false);

            Contract.ThrowIfNull(result);

            if (!result.Succeeded && !result.SucceededWithSuggestion)
            {
                return(null);
            }

            return(CodeAction.Create(
                       FeaturesResources.Extract_method,
                       async c =>
            {
                var(document, invocationNameToken) = await result.GetFormattedDocumentAsync(cleanupOptions, c).ConfigureAwait(false);
                return await AddRenameAnnotationAsync(document, invocationNameToken, c).ConfigureAwait(false);
            },
                       nameof(FeaturesResources.Extract_method)));
        }
Ejemplo n.º 29
0
        public async Task <(Document document, SyntaxToken invocationNameToken)> GetFormattedDocumentAsync(CodeCleanupOptions cleanupOptions, 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, cleanupOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false);

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

            var services = DocumentWithoutFinalFormatting.Project.Solution.Services;

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

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

            return(formattedDocument, formattedRoot.GetAnnotatedTokens(annotation).Single());
        }
        public async Task <Document> FormatNewDocumentAsync(Document document, Document?hintDocument, CodeCleanupOptions options, CancellationToken cancellationToken)
        {
            var accessibilityPreferences = options.FormattingOptions.AccessibilityModifiersRequired;

            if (accessibilityPreferences == AccessibilityModifiersRequired.Never)
            {
                return(document);
            }

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

            var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts      = document.GetRequiredLanguageService <ISyntaxFactsService>();
            var typeDeclarations = root.DescendantNodes().Where(node => syntaxFacts.IsTypeDeclaration(node));
            var editor           = new SyntaxEditor(root, document.Project.Solution.Services);

            var service = document.GetRequiredLanguageService <IAddAccessibilityModifiersService>();

            foreach (var declaration in typeDeclarations)
            {
                if (!service.ShouldUpdateAccessibilityModifier(CSharpAccessibilityFacts.Instance, declaration, accessibilityPreferences, out _))
                {
                    continue;
                }

                // Since we format each document as they are added to a project we can't assume we know about all
                // of the files that are coming, so we have to opt out of changing partial classes. This especially
                // manifests when creating new projects as we format before we have a project at all, so we could get a
                // situation like this:
                //
                // File1.cs:
                //    partial class C { }
                // File2.cs:
                //    public partial class C { }
                //
                // When we see File1, we don't know about File2, so would add an internal modifier, which would result in a compile
                // error.
                var modifiers = syntaxFacts.GetModifiers(declaration);
                CSharpAccessibilityFacts.GetAccessibilityAndModifiers(modifiers, out _, out var declarationModifiers, out _);
                if (declarationModifiers.IsPartial)
                {
                    continue;
                }

                var type = semanticModel.GetDeclaredSymbol(declaration, cancellationToken);
                if (type == null)
                {
                    continue;
                }

                AddAccessibilityModifiersHelpers.UpdateDeclaration(editor, type, declaration);
            }

            return(document.WithSyntaxRoot(editor.GetChangedRoot()));
        }