diff --git a/ChangeLog.md b/ChangeLog.md index ec4985e6de..42fae1d185 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix [RCS1164](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1164) ([#1196](https://github.com/JosefPihrt/Roslynator/pull/1196)). - Fix [RCS1241](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1241) ([#1197](https://github.com/JosefPihrt/Roslynator/pull/1197)). - Fix [RCS1250](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1250) ([#1205](https://github.com/JosefPihrt/Roslynator/pull/1205)). +- [CLI] Fix globbing ([#1215](https://github.com/JosefPihrt/Roslynator/pull/1215)). ## [4.5.0] - 2023-08-27 diff --git a/src/CommandLine/Commands/MSBuildWorkspaceCommand.cs b/src/CommandLine/Commands/MSBuildWorkspaceCommand.cs index fca8f71d21..148c686b27 100644 --- a/src/CommandLine/Commands/MSBuildWorkspaceCommand.cs +++ b/src/CommandLine/Commands/MSBuildWorkspaceCommand.cs @@ -158,6 +158,9 @@ private async Task ExecuteAsync(string path, MSBuildWorkspace wo return null; } + if (FileSystemFilter is not null) + FileSystemFilter.RootDirectoryPath = Path.GetDirectoryName(path); + return await ExecuteAsync(projectOrSolution, cancellationToken); } diff --git a/src/CommandLine/Rename/CliSymbolRenameState.cs b/src/CommandLine/Rename/CliSymbolRenameState.cs index 95ebc5066b..84e2b8db4d 100644 --- a/src/CommandLine/Rename/CliSymbolRenameState.cs +++ b/src/CommandLine/Rename/CliSymbolRenameState.cs @@ -47,7 +47,10 @@ public CliSymbolRenameState( public ConsoleDialog UserDialog { get; set; } - protected override async Task RenameSymbolsAsync(ImmutableArray projects, CancellationToken cancellationToken = default) + protected override async Task RenameSymbolsAsync( + ImmutableArray projects, + bool isSolution, + CancellationToken cancellationToken = default) { Stopwatch stopwatch = Stopwatch.StartNew(); TimeSpan lastElapsed = TimeSpan.Zero; @@ -65,6 +68,9 @@ protected override async Task RenameSymbolsAsync(ImmutableArray proje WriteLine($" Rename {GetScopePluralName(renameScopes[i])} in '{project.Name}' {$"{j + 1}/{projects.Length}"}", ConsoleColors.Cyan, Verbosity.Minimal); + if (!isSolution) + CurrentDirectoryPath = Path.GetDirectoryName(project.FilePath); + await AnalyzeProjectAsync(project, renameScopes[i], cancellationToken); WriteLine($" Done renaming {GetScopePluralName(renameScopes[i])} in '{project.Name}' in {stopwatch.Elapsed - lastElapsed:mm\\:ss\\.ff}", Verbosity.Normal); diff --git a/src/Workspaces.Core/Extensions/Extensions.cs b/src/Workspaces.Core/Extensions/Extensions.cs index 8f6e0bbb24..1351cfb720 100644 --- a/src/Workspaces.Core/Extensions/Extensions.cs +++ b/src/Workspaces.Core/Extensions/Extensions.cs @@ -18,16 +18,20 @@ namespace Roslynator; internal static class Extensions { - public static bool IsMatch(this Matcher matcher, ISymbol symbol) + public static bool IsMatch(this Matcher matcher, ISymbol symbol, string rootDirectoryPath) { foreach (Location location in symbol.Locations) { SyntaxTree tree = location.SourceTree; - if (tree is not null - && !matcher.Match(tree.FilePath).HasMatches) + if (tree is not null) { - return false; + PatternMatchingResult result = (rootDirectoryPath is not null) + ? matcher.Match(tree.FilePath, rootDirectoryPath) + : matcher.Match(tree.FilePath); + + if (!result.HasMatches) + return false; } } diff --git a/src/Workspaces.Core/FileSystemFilter.cs b/src/Workspaces.Core/FileSystemFilter.cs index d4b9769c7b..10d7b79f1b 100644 --- a/src/Workspaces.Core/FileSystemFilter.cs +++ b/src/Workspaces.Core/FileSystemFilter.cs @@ -22,6 +22,8 @@ private FileSystemFilter(Matcher matcher) public Matcher Matcher { get; } + public string RootDirectoryPath { get; set; } + public static FileSystemFilter CreateOrDefault( IEnumerable include, IEnumerable exclude) @@ -51,7 +53,7 @@ public static FileSystemFilter CreateOrDefault( public bool IsMatch(ISymbol symbol) { - bool isMatch = Matcher.IsMatch(symbol); + bool isMatch = Matcher.IsMatch(symbol, RootDirectoryPath); #if DEBUG if (!isMatch && Logger.ShouldWrite(Verbosity.Diagnostic)) @@ -65,7 +67,9 @@ public bool IsMatch(ISymbol symbol) public bool IsMatch(string filePath) { - PatternMatchingResult result = Matcher.Match(filePath); + PatternMatchingResult result = (RootDirectoryPath is not null) + ? Matcher.Match(RootDirectoryPath, filePath) + : Matcher.Match(filePath); #if DEBUG Debug.Assert(result.Files.Count() <= 1, result.Files.Count().ToString()); diff --git a/src/Workspaces.Core/Rename/SymbolProvider.cs b/src/Workspaces.Core/Rename/SymbolProvider.cs index 033bdcec08..2ccb677928 100644 --- a/src/Workspaces.Core/Rename/SymbolProvider.cs +++ b/src/Workspaces.Core/Rename/SymbolProvider.cs @@ -22,6 +22,8 @@ internal class SymbolProvider public Matcher FileSystemMatcher { get; init; } + public string RootDirectoryPath { get; init; } + public async Task> GetSymbolsAsync( Project project, RenameScope scope, @@ -50,6 +52,7 @@ public async Task> GetSymbolsAsync( { IncludeGeneratedCode = IncludeGeneratedCode, FileSystemMatcher = FileSystemMatcher, + RootDirectoryPath = RootDirectoryPath, }; analyzer.SymbolKinds.AddRange(symbolKinds); @@ -90,6 +93,8 @@ private class Analyzer : DiagnosticAnalyzer public Matcher FileSystemMatcher { get; init; } + public string RootDirectoryPath { get; init; } + public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); @@ -146,7 +151,7 @@ private void AnalyzeSymbol(SymbolAnalysisContext context) private void AddSymbol(ISymbol symbol) { - if (FileSystemMatcher?.IsMatch(symbol) != false) + if (FileSystemMatcher?.IsMatch(symbol, RootDirectoryPath) != false) Symbols.Add(symbol); } } diff --git a/src/Workspaces.Core/Rename/SymbolRenameState.cs b/src/Workspaces.Core/Rename/SymbolRenameState.cs index 3f56ee0dfd..1fcf1618d6 100644 --- a/src/Workspaces.Core/Rename/SymbolRenameState.cs +++ b/src/Workspaces.Core/Rename/SymbolRenameState.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -48,6 +49,8 @@ public SymbolRenameState( private bool DryRun => Options.DryRun; + protected string CurrentDirectoryPath { get; set; } + public Task RenameSymbolsAsync(CancellationToken cancellationToken = default) { ImmutableArray projectIds = CurrentSolution @@ -55,7 +58,9 @@ public Task RenameSymbolsAsync(CancellationToken cancellationToken = default) .GetTopologicallySortedProjects(cancellationToken) .ToImmutableArray(); - return RenameSymbolsAsync(projectIds, cancellationToken); + CurrentDirectoryPath = Path.GetDirectoryName(CurrentSolution.FilePath); + + return RenameSymbolsAsync(projectIds, isSolution: true, cancellationToken); } public Task RenameSymbolsAsync( @@ -68,11 +73,12 @@ public Task RenameSymbolsAsync( .Join(projects, id => id, p => p.Id, (id, _) => id) .ToImmutableArray(); - return RenameSymbolsAsync(projectIds, cancellationToken); + return RenameSymbolsAsync(projectIds, isSolution: false, cancellationToken); } protected virtual async Task RenameSymbolsAsync( ImmutableArray projects, + bool isSolution, CancellationToken cancellationToken = default) { foreach (RenameScope renameScope in GetRenameScopes()) @@ -83,6 +89,9 @@ protected virtual async Task RenameSymbolsAsync( Project project = CurrentSolution.GetProject(projects[j]); + if (!isSolution) + CurrentDirectoryPath = Path.GetDirectoryName(project.FilePath); + await AnalyzeProjectAsync(project, renameScope, cancellationToken).ConfigureAwait(false); } } @@ -92,6 +101,8 @@ public virtual async Task RenameSymbolsAsync( Project project, CancellationToken cancellationToken = default) { + CurrentDirectoryPath = Path.GetDirectoryName(project.FilePath); + foreach (RenameScope renameScope in GetRenameScopes()) { cancellationToken.ThrowIfCancellationRequested(); @@ -135,6 +146,7 @@ protected async Task AnalyzeProjectAsync( { IncludeGeneratedCode = Options.IncludeGeneratedCode, FileSystemMatcher = Options.FileSystemMatcher, + RootDirectoryPath = CurrentDirectoryPath, }; IEnumerable symbols = await symbolProvider.GetSymbolsAsync(project, scope, cancellationToken).ConfigureAwait(false);