Minor refactoring for `UpgradeToRegexGeneratorAnalyzer` (#70767)
authorYoussef Victor <youssefvictor00@gmail.com>
Mon, 20 Jun 2022 14:50:37 +0000 (16:50 +0200)
committerGitHub <noreply@github.com>
Mon, 20 Jun 2022 14:50:37 +0000 (07:50 -0700)
src/libraries/System.Text.RegularExpressions/gen/UpgradeToRegexGeneratorAnalyzer.cs
src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/UpgradeToRegexGeneratorAnalyzerTests.cs

index c40ef8d..d36dbb5 100644 (file)
@@ -39,9 +39,9 @@ namespace System.Text.RegularExpressions.Generator
             context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
             context.EnableConcurrentExecution();
 
-            context.RegisterCompilationStartAction(async compilationContext =>
+            context.RegisterCompilationStartAction(context =>
             {
-                Compilation compilation = compilationContext.Compilation;
+                Compilation compilation = context.Compilation;
 
                 // Validate that the project supports the Regex Source Generator based on target framework,
                 // language version, etc.
@@ -53,7 +53,7 @@ namespace System.Text.RegularExpressions.Generator
                 // Validate that the project is not using top-level statements, since if it were, the code-fixer
                 // can't easily convert to the source generator without having to make the program not use top-level
                 // statements any longer.
-                if (await ProjectUsesTopLevelStatements(compilation, compilationContext.CancellationToken).ConfigureAwait(false))
+                if (ProjectUsesTopLevelStatements(compilation))
                 {
                     return;
                 }
@@ -64,10 +64,10 @@ namespace System.Text.RegularExpressions.Generator
                     new HashSet<string> { "Count", "EnumerateMatches", "IsMatch", "Match", "Matches", "Split", "Replace" });
 
                 // Register analysis of calls to the Regex constructors
-                compilationContext.RegisterOperationAction(context => AnalyzeObjectCreation(context, regexTypeSymbol), OperationKind.ObjectCreation);
+                context.RegisterOperationAction(context => AnalyzeObjectCreation(context, regexTypeSymbol), OperationKind.ObjectCreation);
 
                 // Register analysis of calls to Regex static methods
-                compilationContext.RegisterOperationAction(context => AnalyzeInvocation(context, regexTypeSymbol, staticMethodsToDetect), OperationKind.Invocation);
+                context.RegisterOperationAction(context => AnalyzeInvocation(context, regexTypeSymbol, staticMethodsToDetect), OperationKind.Invocation);
             });
 
             // Creates a HashSet of all of the method Symbols containing the static methods to analyze.
@@ -82,7 +82,7 @@ namespace System.Text.RegularExpressions.Generator
 #pragma warning restore RS1024 // Compare symbols correctly
                 ImmutableArray<ISymbol> allMembers = regexTypeSymbol.GetMembers();
 
-                foreach(ISymbol member in allMembers)
+                foreach (ISymbol member in allMembers)
                 {
                     if (member is IMethodSymbol method &&
                         method.IsStatic &&
@@ -253,15 +253,10 @@ namespace System.Text.RegularExpressions.Generator
         /// <summary>
         /// Detects whether or not the current project is using top-level statements.
         /// </summary>
-        private static async Task<bool> ProjectUsesTopLevelStatements(Compilation compilation, CancellationToken cancellationToken)
+        private static bool ProjectUsesTopLevelStatements(Compilation compilation)
         {
-            SyntaxNode? root = await compilation.SyntaxTrees.FirstOrDefault().GetRootAsync(cancellationToken).ConfigureAwait(false);
-            if (root is null)
-            {
-                return false;
-            }
-
-            return root.DescendantNodesAndSelf().Where(node => node.IsKind(SyntaxKind.GlobalStatement)).Any();
+            INamedTypeSymbol? programType = compilation.GetTypeByMetadataName("Program");
+            return programType is not null && !programType.GetMembers("<Main>$").IsEmpty;
         }
 
         /// <summary>
@@ -285,7 +280,7 @@ namespace System.Text.RegularExpressions.Generator
                 return false;
             }
 
-            if (compilation.SyntaxTrees.FirstOrDefault().Options is CSharpParseOptions options && options.LanguageVersion <= (LanguageVersion)1000)
+            if (((CSharpCompilation)compilation).LanguageVersion <= (LanguageVersion)1000)
             {
                 return false;
             }
index 6819ab9..cf913e3 100644 (file)
@@ -736,6 +736,18 @@ partial class Program
             await VerifyCS.VerifyCodeFixAsync(test, expectedDiagnostic, fixedSource);
         }
 
+        [Fact]
+        public async Task NoDiagnosticForTopLevelStatements_MultipleSourceFiles()
+        {
+            await new VerifyCS.Test(references: null, usePreviewLanguageVersion: true, numberOfIterations: 1)
+            {
+                TestState =
+                {
+                    Sources = { "public class C { }", @"var r = new System.Text.RegularExpressions.Regex("""");" },
+                },
+            }.RunAsync();
+        }
+
         #region Test helpers
 
         private static string ConstructRegexInvocation(InvocationType invocationType, string pattern, string? options = null)