/// <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)); }
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)); }
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); } } }
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); }
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); }
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)); }
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); } }
/// <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)); }
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); }