|
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.Diagnostics;
namespace Microsoft.CodeAnalysis.Tools.Utilities
{
internal static class GeneratedCodeUtilities
{
private static readonly string[] s_autoGeneratedStrings = new[] { "<autogenerated", "<auto-generated" };
private static readonly Func<SyntaxTrivia, bool> s_isCSharpCommentTrivia =
(syntaxTrivia) => syntaxTrivia.IsKind(CSharp.SyntaxKind.SingleLineCommentTrivia)
|| syntaxTrivia.IsKind(CSharp.SyntaxKind.MultiLineCommentTrivia)
|| syntaxTrivia.IsKind(CSharp.SyntaxKind.SingleLineDocumentationCommentTrivia)
|| syntaxTrivia.IsKind(CSharp.SyntaxKind.MultiLineDocumentationCommentTrivia);
private static readonly Func<SyntaxTrivia, bool> s_isVisualBasicCommentTrivia =
(syntaxTrivia) => syntaxTrivia.IsKind(VisualBasic.SyntaxKind.CommentTrivia)
|| syntaxTrivia.IsKind(VisualBasic.SyntaxKind.DocumentationCommentTrivia);
internal static async Task<bool> IsGeneratedCodeAsync(SyntaxTree syntaxTree, CancellationToken cancellationToken)
{
if (IsGeneratedCodeFileName(syntaxTree.FilePath))
{
return true;
}
var isCommentTrivia = syntaxTree.Options.Language == LanguageNames.CSharp
? s_isCSharpCommentTrivia
: s_isVisualBasicCommentTrivia;
var syntaxRoot = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false);
return BeginsWithAutoGeneratedComment(syntaxRoot, isCommentTrivia);
}
private static bool IsGeneratedCodeFileName(string? filePath)
{
if (!string.IsNullOrEmpty(filePath))
{
var fileName = Path.GetFileName(filePath);
if (fileName.StartsWith("TemporaryGeneratedFile_", StringComparison.OrdinalIgnoreCase))
{
return true;
}
var extension = Path.GetExtension(fileName);
if (!string.IsNullOrEmpty(extension))
{
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath);
if (fileNameWithoutExtension.EndsWith(".designer", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".generated", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".g", StringComparison.OrdinalIgnoreCase) ||
fileNameWithoutExtension.EndsWith(".g.i", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
return false;
}
private static bool BeginsWithAutoGeneratedComment(SyntaxNode syntaxRoot, Func<SyntaxTrivia, bool> isComment)
{
if (syntaxRoot.HasLeadingTrivia)
{
var leadingTrivia = syntaxRoot.GetLeadingTrivia();
foreach (var trivia in leadingTrivia)
{
if (!isComment(trivia))
{
continue;
}
var text = trivia.ToString();
// Check to see if the text of the comment contains an auto generated comment.
foreach (var autoGenerated in s_autoGeneratedStrings)
{
if (text.Contains(autoGenerated))
{
return true;
}
}
}
}
return false;
}
internal static bool? GetIsGeneratedCodeFromOptions(AnalyzerConfigOptions options)
{
// Check for explicit user configuration for generated code.
// generated_code = true | false
if (options.TryGetValue("generated_code", out var optionValue) &&
bool.TryParse(optionValue, out var boolValue))
{
return boolValue;
}
// Either no explicit user configuration or we don't recognize the option value.
return null;
}
}
}
|