public override SyntaxTree CreateSyntaxTree(string filePath, ParseOptions options, Encoding encoding, SyntaxNode root, AnalyzerConfigOptionsResult analyzerConfigOptionsResult)
            {
                options ??= GetDefaultParseOptions();
                var isUserConfiguredGeneratedCode = GeneratedCodeUtilities.GetIsGeneratedCodeFromOptions(analyzerConfigOptionsResult.AnalyzerOptions);

                return(CSharpSyntaxTree.Create((CSharpSyntaxNode)root, (CSharpParseOptions)options, filePath, encoding, analyzerConfigOptionsResult.TreeOptions, isUserConfiguredGeneratedCode));
            }
            public override SyntaxTree ParseSyntaxTree(string filePath, ParseOptions options, SourceText text, AnalyzerConfigOptionsResult?analyzerConfigOptionsResult, CancellationToken cancellationToken)
            {
                options ??= GetDefaultParseOptions();
                var isUserConfiguredGeneratedCode = analyzerConfigOptionsResult.HasValue
                    ? GeneratedCodeUtilities.GetIsGeneratedCodeFromOptions(analyzerConfigOptionsResult.Value.AnalyzerOptions)
                    : null;

                return(SyntaxFactory.ParseSyntaxTree(text, options, filePath, analyzerConfigOptionsResult?.TreeOptions, isUserConfiguredGeneratedCode, cancellationToken: cancellationToken));
            }
 public Options(AnalyzerConfigOptionsResult?result)
 {
     if (result is AnalyzerConfigOptionsResult r)
     {
         DiagnosticOptions = r.TreeOptions;
         IsGenerated       = GeneratedCodeUtilities.GetIsGeneratedCodeFromOptions(r.AnalyzerOptions);
     }
     else
     {
         DiagnosticOptions = SyntaxTree.EmptyDiagnosticOptions;
         IsGenerated       = null;
     }
 }
예제 #4
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));
        }
예제 #5
0
        private static SyntaxTree ParseFile(
            CSharpParseOptions parseOptions,
            CSharpParseOptions scriptParseOptions,
            SourceText content,
            CommandLineSourceFile file,
            AnalyzerConfigOptionsResult?analyzerConfigOptionsResult)
        {
            ImmutableDictionary <string, ReportDiagnostic> diagnosticOptions;
            bool?isUserConfiguredGeneratedCode;

            if (analyzerConfigOptionsResult.HasValue)
            {
                diagnosticOptions             = analyzerConfigOptionsResult.Value.TreeOptions;
                isUserConfiguredGeneratedCode = GeneratedCodeUtilities.GetIsGeneratedCodeFromOptions(analyzerConfigOptionsResult.Value.AnalyzerOptions);
            }
            else
            {
                diagnosticOptions             = null;
                isUserConfiguredGeneratedCode = null;
            }

            var tree = SyntaxFactory.ParseSyntaxTree(
                content,
                file.IsScript ? scriptParseOptions : parseOptions,
                file.Path,
                diagnosticOptions,
                isUserConfiguredGeneratedCode);

            // prepopulate line tables.
            // we will need line tables anyways and it is better to not wait until we are in emit
            // where things run sequentially.
            bool isHiddenDummy;

            tree.GetMappedLineSpanAndVisibility(default(TextSpan), out isHiddenDummy);

            return(tree);
        }
예제 #6
0
        internal static async Task <(int, ImmutableArray <DocumentId>)> DetermineFormattableFilesAsync(
            Solution solution,
            string projectPath,
            FormatOptions formatOptions,
            ILogger logger,
            CancellationToken cancellationToken)
        {
            var totalFileCount   = solution.Projects.Sum(project => project.DocumentIds.Count);
            var projectFileCount = 0;

            var documentsCoveredByEditorConfig    = ImmutableArray.CreateBuilder <DocumentId>(totalFileCount);
            var documentsNotCoveredByEditorConfig = ImmutableArray.CreateBuilder <DocumentId>(totalFileCount);

            var addedFilePaths = new HashSet <string>(totalFileCount);

            foreach (var project in solution.Projects)
            {
                if (project?.FilePath is null)
                {
                    continue;
                }

                // If a project is used as a workspace, then ignore other referenced projects.
                if (!string.IsNullOrEmpty(projectPath) && !project.FilePath.Equals(projectPath, StringComparison.OrdinalIgnoreCase))
                {
                    logger.LogDebug(Resources.Skipping_referenced_project_0, project.Name);
                    continue;
                }

                // Ignore unsupported project types.
                if (project.Language != LanguageNames.CSharp && project.Language != LanguageNames.VisualBasic)
                {
                    logger.LogWarning(Resources.Could_not_format_0_Format_currently_supports_only_CSharp_and_Visual_Basic_projects, project.FilePath);
                    continue;
                }

                projectFileCount += project.DocumentIds.Count;

                foreach (var document in project.Documents)
                {
                    // If we've already added this document, either via a link or multi-targeted framework, then ignore.
                    if (document?.FilePath is null ||
                        addedFilePaths.Contains(document.FilePath))
                    {
                        continue;
                    }

                    addedFilePaths.Add(document.FilePath);

                    var isFileIncluded = formatOptions.WorkspaceType == WorkspaceType.Folder ||
                                         (formatOptions.FileMatcher.HasMatches(document.FilePath) && File.Exists(document.FilePath));
                    if (!isFileIncluded || !document.SupportsSyntaxTree)
                    {
                        continue;
                    }

                    var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                    if (syntaxTree is null)
                    {
                        throw new Exception($"Unable to get a syntax tree for '{document.Name}'");
                    }

                    if (!formatOptions.IncludeGeneratedFiles &&
                        await GeneratedCodeUtilities.IsGeneratedCodeAsync(syntaxTree, cancellationToken).ConfigureAwait(false))
                    {
                        continue;
                    }

                    // Track files covered by an editorconfig separately from those not covered.
                    var analyzerConfigOptions = document.Project.AnalyzerOptions.AnalyzerConfigOptionsProvider.GetOptions(syntaxTree);
                    if (analyzerConfigOptions != null)
                    {
                        if (formatOptions.IncludeGeneratedFiles ||
                            GeneratedCodeUtilities.GetIsGeneratedCodeFromOptions(analyzerConfigOptions) != true)
                        {
                            documentsCoveredByEditorConfig.Add(document.Id);
                        }
                    }
                    else
                    {
                        documentsNotCoveredByEditorConfig.Add(document.Id);
                    }
                }
            }

            // Initially we would format all documents in a workspace, even if some files weren't covered by an
            // .editorconfig and would have defaults applied. This behavior was an early requested change since
            // users were surprised to have files not specified by the .editorconfig modified. The assumption is
            // that users without an .editorconfig still wanted formatting (they did run a formatter after all),
            // so we run on all files with defaults.

            // If no files are covered by an editorconfig, then return them all. Otherwise only return
            // files that are covered by an editorconfig.
            return(documentsCoveredByEditorConfig.Count == 0
                ? (projectFileCount, documentsNotCoveredByEditorConfig.ToImmutable())
                : (projectFileCount, documentsCoveredByEditorConfig.ToImmutable()));
        }