Example #1
0
        /// <summary>
        /// Creates a new syntax tree from a syntax node.
        /// </summary>
        public static SyntaxTree Create(
            CSharpSyntaxNode root,
            CSharpParseOptions options = null,
            string path       = "",
            Encoding encoding = null,
            ImmutableDictionary <string, ReportDiagnostic> diagnosticOptions = null,
            bool?isGeneratedCode = null)
        {
            if (root == null)
            {
                throw new ArgumentNullException(nameof(root));
            }

            var directives = root.Kind() == SyntaxKind.CompilationUnit ?
                             ((CompilationUnitSyntax)root).GetConditionalDirectivesStack() :
                             InternalSyntax.DirectiveStack.Empty;

            bool isGenerated = isGeneratedCode ??
                               GeneratedCodeUtilities.IsGeneratedCode(
                path,
                root,
                isComment: trivia => trivia.Kind() == SyntaxKind.SingleLineCommentTrivia || trivia.Kind() == SyntaxKind.MultiLineCommentTrivia);

            return(new ParsedSyntaxTree(
                       textOpt: null,
                       encodingOpt: encoding,
                       checksumAlgorithm: SourceHashAlgorithm.Sha1,
                       path: path,
                       options: options ?? CSharpParseOptions.Default,
                       root: root,
                       directives: directives,
                       diagnosticOptions,
                       isGenerated,
                       cloneRoot: true));
        }
Example #2
0
        public bool IsGeneratedCode(Document document, CancellationToken cancellationToken)
        {
            var syntaxTree  = document.GetSyntaxTreeSynchronously(cancellationToken);
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            return(GeneratedCodeUtilities.IsGeneratedCode(
                       syntaxTree, t => syntaxFacts.IsRegularComment(t) || syntaxFacts.IsDocumentationComment(t), cancellationToken));
        }
Example #3
0
        private static async Task <Solution> FormatFilesInProjectAsync(ILogger logger, Project project, ICodingConventionsManager codingConventionsManager, EditorConfigOptionsApplier optionsApplier, CancellationToken cancellationToken)
        {
            var isCommentTrivia = project.Language == LanguageNames.CSharp
                ? IsCSharpCommentTrivia
                : IsVisualBasicCommentTrivia;

            var formattedDocuments = new List <(DocumentId documentId, Task <SourceText> formatTask)>();

            foreach (var documentId in project.DocumentIds)
            {
                var document = project.Solution.GetDocument(documentId);
                if (!document.SupportsSyntaxTree)
                {
                    continue;
                }

                var formatTask = Task.Run(async() =>
                {
                    var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
                    if (GeneratedCodeUtilities.IsGeneratedCode(syntaxTree, isCommentTrivia, cancellationToken))
                    {
                        return(null);
                    }

                    logger.LogTrace(Resources.Formatting_code_file_0, Path.GetFileName(document.FilePath));

                    OptionSet documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

                    var codingConventionsContext = await codingConventionsManager.GetConventionContextAsync(document.FilePath, cancellationToken).ConfigureAwait(false);
                    if (codingConventionsContext?.CurrentConventions != null)
                    {
                        documentOptions = optionsApplier.ApplyConventions(documentOptions, codingConventionsContext.CurrentConventions, project.Language);
                    }

                    var formattedDocument = await Formatter.FormatAsync(document, documentOptions, cancellationToken).ConfigureAwait(false);
                    return(await formattedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false));
                }, cancellationToken);

                formattedDocuments.Add((documentId, formatTask));
            }

            var formattedSolution = project.Solution;

            foreach (var(documentId, formatTask) in formattedDocuments)
            {
                var text = await formatTask.ConfigureAwait(false);

                if (text is null)
                {
                    continue;
                }

                formattedSolution = formattedSolution.WithDocumentText(documentId, text);
            }

            return(formattedSolution);
        }
        private void AnalyzeSemanticModel(SemanticModelAnalysisContext context)
        {
            var tree = context.SemanticModel.SyntaxTree;
            var cancellationToken = context.CancellationToken;

            if (!(context.Options is WorkspaceAnalyzerOptions workspaceOptions))
            {
                return;
            }

            var language = context.SemanticModel.Compilation.Language;
            var service  = workspaceOptions.Services.GetLanguageServices(language)
                           .GetService <IUnnecessaryImportsService>();

            var unnecessaryImports = service.GetUnnecessaryImports(context.SemanticModel, cancellationToken);

            if (unnecessaryImports.Any())
            {
                // The IUnnecessaryImportsService will return individual import pieces that
                // need to be removed.  For example, it will return individual import-clauses
                // from VB.  However, we want to mark the entire import statement if we are
                // going to remove all the clause.  Defer to our subclass to stitch this up
                // for us appropriately.
                unnecessaryImports = MergeImports(unnecessaryImports);

                EnsureClassificationIdDescriptors();
                var fadeOut = workspaceOptions.Services.Workspace.Options.GetOption(FadingOptions.FadeOutUnusedImports, language);

                DiagnosticDescriptor descriptor;
                var syntaxFacts = workspaceOptions.Services.GetLanguageServices(language).GetRequiredService <ISyntaxFactsService>();
                if (GeneratedCodeUtilities.IsGeneratedCode(tree, t => syntaxFacts.IsRegularComment(t) || syntaxFacts.IsDocumentationComment(t), context.CancellationToken))
                {
                    descriptor = fadeOut ? _unnecessaryGeneratedCodeClassificationIdDescriptor : _generatedCodeClassificationIdDescriptor;
                }
                else
                {
                    descriptor = fadeOut ? _unnecessaryClassificationIdDescriptor : _classificationIdDescriptor;
                }

                var getLastTokenFunc = GetLastTokenDelegateForContiguousSpans();
                var contiguousSpans  = unnecessaryImports.GetContiguousSpans(getLastTokenFunc);
                var diagnostics      =
                    CreateClassificationDiagnostics(contiguousSpans, tree, descriptor, cancellationToken).Concat(
                        CreateFixableDiagnostics(unnecessaryImports, tree, cancellationToken));

                foreach (var diagnostic in diagnostics)
                {
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }
Example #5
0
        internal bool IsGeneratedCode()
        {
            if (_lazyIsGeneratedCode == ThreeState.Unknown)
            {
                // Create the generated code status on demand
                bool isGenerated = GeneratedCodeUtilities.IsGeneratedCode(
                    this,
                    isComment: trivia => trivia.Kind() == SyntaxKind.SingleLineCommentTrivia || trivia.Kind() == SyntaxKind.MultiLineCommentTrivia,
                    cancellationToken: default);
                _lazyIsGeneratedCode = isGenerated.ToThreeState();
            }

            return(_lazyIsGeneratedCode == ThreeState.True);
        }
Example #6
0
        internal bool IsGeneratedCode()
        {
            if (_lazyIsGeneratedCode == -1)
            {
                // Create the generated code status on demand
                bool isGenerated = GeneratedCodeUtilities.IsGeneratedCode(
                    this,
                    isComment: trivia => trivia.Kind() == SyntaxKind.SingleLineCommentTrivia || trivia.Kind() == SyntaxKind.MultiLineCommentTrivia,
                    cancellationToken: default);

                Interlocked.CompareExchange(ref _lazyIsGeneratedCode, isGenerated ? 1 : 0, -1);
            }

            return(_lazyIsGeneratedCode == 1);
        }
Example #7
0
        private static bool IsGeneratedCode(SyntaxTree syntaxTree, Document document, CancellationToken cancellationToken)
        {
            // First check if user has configured "generated_code = true | false" in .editorconfig
            var analyzerOptions = document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree);
            var isUserConfiguredGeneratedCode = GeneratedCodeUtilities.GetIsGeneratedCodeFromOptions(analyzerOptions);

            if (isUserConfiguredGeneratedCode.HasValue)
            {
                return(isUserConfiguredGeneratedCode.Value);
            }

            // Otherwise, fallback to generated code heuristic.
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            return(GeneratedCodeUtilities.IsGeneratedCode(
                       syntaxTree, t => syntaxFacts.IsRegularComment(t) || syntaxFacts.IsDocumentationComment(t), cancellationToken));
        }
Example #8
0
        private void AnalyzeSemanticModel(SemanticModelAnalysisContext context)
        {
            var tree = context.SemanticModel.SyntaxTree;
            var cancellationToken = context.CancellationToken;
            var language          = context.SemanticModel.Language;

            var unnecessaryImports = UnnecessaryImportsProvider.GetUnnecessaryImports(context.SemanticModel, cancellationToken);

            if (unnecessaryImports.Any())
            {
                // The IUnnecessaryImportsService will return individual import pieces that
                // need to be removed.  For example, it will return individual import-clauses
                // from VB.  However, we want to mark the entire import statement if we are
                // going to remove all the clause.  Defer to our subclass to stitch this up
                // for us appropriately.
                unnecessaryImports = MergeImports(unnecessaryImports);

                EnsureClassificationIdDescriptors();
                var fadeOut = ShouldFade(context.Options, tree, language, cancellationToken);

                DiagnosticDescriptor descriptor;
                if (GeneratedCodeUtilities.IsGeneratedCode(tree, IsRegularCommentOrDocComment, cancellationToken))
                {
                    descriptor = fadeOut ? _unnecessaryGeneratedCodeClassificationIdDescriptor : _generatedCodeClassificationIdDescriptor;
                }
                else
                {
                    descriptor = fadeOut ? _unnecessaryClassificationIdDescriptor : _classificationIdDescriptor;
                }

                var getLastTokenFunc = GetLastTokenDelegateForContiguousSpans();
                var contiguousSpans  = unnecessaryImports.GetContiguousSpans(getLastTokenFunc);
                var diagnostics      =
                    CreateClassificationDiagnostics(contiguousSpans, tree, descriptor, cancellationToken).Concat(
                        CreateFixableDiagnostics(unnecessaryImports, tree, cancellationToken));

                foreach (var diagnostic in diagnostics)
                {
                    context.ReportDiagnostic(diagnostic);
                }
            }
Example #9
0
        /// <summary>
        /// Returns true if this <paramref name="syntaxTree"/> is obtained from generated code.
        /// </summary>
        public static bool IsGeneratedCode(this SyntaxTree syntaxTree)
        {
            // TODO: check explicit user definitions

            return(GeneratedCodeUtilities.IsGeneratedCode(syntaxTree, SyntaxTriviaExtensions.IsRegularOrDocComment, cancellationToken: default));
        }
Example #10
0
        private static async Task <(Solution solution, int filesFormatted)> FormatFilesInProjectAsync(ILogger logger, Project project, ICodingConventionsManager codingConventionsManager, EditorConfigOptionsApplier optionsApplier, string[] filesToFormat, CancellationToken cancellationToken)
        {
            var isCommentTrivia = project.Language == LanguageNames.CSharp
                ? IsCSharpCommentTrivia
                : IsVisualBasicCommentTrivia;

            var formattedDocuments = new List <(DocumentId documentId, Task <SourceText> formatTask)>();

            foreach (var documentId in project.DocumentIds)
            {
                var document = project.Solution.GetDocument(documentId);
                if (!document.SupportsSyntaxTree)
                {
                    continue;
                }

                if (filesToFormat != null)
                {
                    var fileInArgumentList = filesToFormat.Any(relativePath => document.FilePath.EndsWith(relativePath, StringComparison.OrdinalIgnoreCase));

                    if (!fileInArgumentList)
                    {
                        continue;
                    }
                }

                var formatTask = Task.Run(async() =>
                {
                    var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
                    if (GeneratedCodeUtilities.IsGeneratedCode(syntaxTree, isCommentTrivia, cancellationToken))
                    {
                        return(null);
                    }

                    logger.LogTrace(Resources.Formatting_code_file_0, Path.GetFileName(document.FilePath));

                    OptionSet documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

                    var codingConventionsContext = await codingConventionsManager.GetConventionContextAsync(document.FilePath, cancellationToken).ConfigureAwait(false);
                    if (codingConventionsContext?.CurrentConventions != null)
                    {
                        documentOptions = optionsApplier.ApplyConventions(documentOptions, codingConventionsContext.CurrentConventions, project.Language);
                    }

                    var formattedDocument   = await Formatter.FormatAsync(document, documentOptions, cancellationToken).ConfigureAwait(false);
                    var formattedSourceText = await formattedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
                    if (formattedSourceText.ContentEquals(await document.GetTextAsync(cancellationToken).ConfigureAwait(false)))
                    {
                        // Avoid touching files that didn't actually change
                        return(null);
                    }

                    return(formattedSourceText);
                }, cancellationToken);

                formattedDocuments.Add((documentId, formatTask));
            }

            var formattedSolution = project.Solution;
            var filesFormatted    = 0;

            foreach (var(documentId, formatTask) in formattedDocuments)
            {
                var text = await formatTask.ConfigureAwait(false);

                if (text is null)
                {
                    continue;
                }

                filesFormatted++;
                formattedSolution = formattedSolution.WithDocumentText(documentId, text);
            }

            return(formattedSolution, filesFormatted);
        }