Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for excluding search paths via globbing patterns #1161

Merged
merged 12 commits into from
Apr 24, 2018
37 changes: 37 additions & 0 deletions src/OmniSharp.Abstractions/FileSystem/FileSystemHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.Composition;
using System.Linq;
using Microsoft.Extensions.FileSystemGlobbing;
using OmniSharp.Options;

namespace OmniSharp.FileSystem
{
[Export, Shared]
public class FileSystemHelper
{
private readonly OmniSharpOptions _omniSharpOptions;
private readonly IOmniSharpEnvironment _omniSharpEnvironment;

[ImportingConstructor]
public FileSystemHelper(OmniSharpOptions omniSharpOptions, IOmniSharpEnvironment omniSharpEnvironment)
{
_omniSharpOptions = omniSharpOptions;
_omniSharpEnvironment = omniSharpEnvironment;
}

public IEnumerable<string> GetFiles(string includePattern) => GetFiles(includePattern, _omniSharpEnvironment.TargetDirectory);

public IEnumerable<string> GetFiles(string includePattern, string targetDirectory)
{
var matcher = new Matcher();
matcher.AddInclude(includePattern);

if (_omniSharpOptions.FileOptions.ExcludeSearchPatterns != null && _omniSharpOptions.FileOptions.ExcludeSearchPatterns.Any())
{
matcher.AddExcludePatterns(_omniSharpOptions.FileOptions.ExcludeSearchPatterns);
}

return matcher.GetResultsInFullPath(targetDirectory);
}
}
}
7 changes: 7 additions & 0 deletions src/OmniSharp.Abstractions/Options/FileOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace OmniSharp.Options
{
public class FileOptions
{
public string[] ExcludeSearchPatterns { get; set; } = new[] { "**/node_modules/**/*", "**/bin/**/*", "**/obj/**/*" };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also add search inclusions? (in the future perhaps?

Kinda feels like it would be sort of similar to how we used to be able to do things with project.json.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about "**/.git/**/*"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a good one 👍

}
}
2 changes: 2 additions & 0 deletions src/OmniSharp.Abstractions/Options/OmniSharpOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ public class OmniSharpOptions
public RoslynExtensionsOptions RoslynExtensionsOptions { get; } = new RoslynExtensionsOptions();

public FormattingOptions FormattingOptions { get; } = new FormattingOptions();

public FileOptions FileOptions { get; } = new FileOptions();
}
}
8 changes: 5 additions & 3 deletions src/OmniSharp.Cake/CakeProjectSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@
using Microsoft.CodeAnalysis.Scripting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using OmniSharp.Cake.Configuration;
using OmniSharp.Cake.Services;
using OmniSharp.FileSystem;
using OmniSharp.FileWatching;
using OmniSharp.Helpers;
using OmniSharp.Models.UpdateBuffer;
using OmniSharp.Models.WorkspaceInformation;
using OmniSharp.Roslyn.Utilities;
using OmniSharp.Services;
Expand All @@ -32,6 +31,7 @@ public class CakeProjectSystem : IProjectSystem
private readonly IAssemblyLoader _assemblyLoader;
private readonly ICakeScriptService _scriptService;
private readonly IFileSystemWatcher _fileSystemWatcher;
private readonly FileSystemHelper _fileSystemHelper;
private readonly ILogger<CakeProjectSystem> _logger;
private readonly ConcurrentDictionary<string, ProjectInfo> _projects;
private readonly Lazy<CSharpCompilationOptions> _compilationOptions;
Expand All @@ -50,6 +50,7 @@ public CakeProjectSystem(
IAssemblyLoader assemblyLoader,
ICakeScriptService scriptService,
IFileSystemWatcher fileSystemWatcher,
FileSystemHelper fileSystemHelper,
ILoggerFactory loggerFactory)
{
_workspace = workspace ?? throw new ArgumentNullException(nameof(workspace));
Expand All @@ -58,6 +59,7 @@ public CakeProjectSystem(
_assemblyLoader = assemblyLoader ?? throw new ArgumentNullException(nameof(assemblyLoader));
_scriptService = scriptService ?? throw new ArgumentNullException(nameof(scriptService));
_fileSystemWatcher = fileSystemWatcher ?? throw new ArgumentNullException(nameof(fileSystemWatcher));
_fileSystemHelper = fileSystemHelper;
_logger = loggerFactory?.CreateLogger<CakeProjectSystem>() ?? throw new ArgumentNullException(nameof(loggerFactory));

_projects = new ConcurrentDictionary<string, ProjectInfo>();
Expand All @@ -72,7 +74,7 @@ public void Initalize(IConfiguration configuration)
_logger.LogInformation($"Detecting Cake files in '{_environment.TargetDirectory}'.");

// Nothing to do if there are no Cake files
var allCakeFiles = Directory.GetFiles(_environment.TargetDirectory, "*.cake", SearchOption.AllDirectories);
var allCakeFiles = _fileSystemHelper.GetFiles("**/*.cake").ToArray();
if (allCakeFiles.Length == 0)
{
_logger.LogInformation("Could not find any Cake files");
Expand Down
6 changes: 5 additions & 1 deletion src/OmniSharp.MSBuild/ProjectSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using OmniSharp.Eventing;
using OmniSharp.FileSystem;
using OmniSharp.FileWatching;
using OmniSharp.Models.WorkspaceInformation;
using OmniSharp.MSBuild.Discovery;
Expand All @@ -30,6 +31,7 @@ public class ProjectSystem : IProjectSystem
private readonly MetadataFileReferenceCache _metadataFileReferenceCache;
private readonly IEventEmitter _eventEmitter;
private readonly IFileSystemWatcher _fileSystemWatcher;
private readonly FileSystemHelper _fileSystemHelper;
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger _logger;

Expand All @@ -56,6 +58,7 @@ public ProjectSystem(
MetadataFileReferenceCache metadataFileReferenceCache,
IEventEmitter eventEmitter,
IFileSystemWatcher fileSystemWatcher,
FileSystemHelper fileSystemHelper,
ILoggerFactory loggerFactory)
{
_environment = environment;
Expand All @@ -66,6 +69,7 @@ public ProjectSystem(
_metadataFileReferenceCache = metadataFileReferenceCache;
_eventEmitter = eventEmitter;
_fileSystemWatcher = fileSystemWatcher;
_fileSystemHelper = fileSystemHelper;
_loggerFactory = loggerFactory;

_projectsToProcess = new Queue<ProjectFileInfo>();
Expand Down Expand Up @@ -121,7 +125,7 @@ private IEnumerable<string> GetInitialProjectPaths()
// Finally, if there isn't a single solution immediately available,
// Just process all of the projects beneath the root path.
_solutionFileOrRootPath = _environment.TargetDirectory;
return Directory.GetFiles(_environment.TargetDirectory, "*.csproj", SearchOption.AllDirectories);
return _fileSystemHelper.GetFiles("**/*.csproj");
}

private IEnumerable<string> GetProjectPathsFromSolution(string solutionFilePath)
Expand Down
8 changes: 5 additions & 3 deletions src/OmniSharp.Script/ScriptProjectSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.Logging;
using OmniSharp.FileSystem;
using OmniSharp.FileWatching;
using OmniSharp.Models.WorkspaceInformation;
using OmniSharp.Services;
Expand All @@ -36,7 +37,7 @@ public class ScriptProjectSystem : IProjectSystem
private readonly IOmniSharpEnvironment _env;
private readonly ILogger _logger;
private readonly IFileSystemWatcher _fileSystemWatcher;

private readonly FileSystemHelper _fileSystemHelper;
private readonly CompilationDependencyResolver _compilationDependencyResolver;

private ScriptOptions _scriptOptions;
Expand All @@ -45,12 +46,13 @@ public class ScriptProjectSystem : IProjectSystem

[ImportingConstructor]
public ScriptProjectSystem(OmniSharpWorkspace workspace, IOmniSharpEnvironment env, ILoggerFactory loggerFactory,
MetadataFileReferenceCache metadataFileReferenceCache, IFileSystemWatcher fileSystemWatcher)
MetadataFileReferenceCache metadataFileReferenceCache, IFileSystemWatcher fileSystemWatcher, FileSystemHelper fileSystemHelper)
{
_metadataFileReferenceCache = metadataFileReferenceCache;
_workspace = workspace;
_env = env;
_fileSystemWatcher = fileSystemWatcher;
_fileSystemHelper = fileSystemHelper;
_logger = loggerFactory.CreateLogger<ScriptProjectSystem>();
_projects = new ConcurrentDictionary<string, ProjectInfo>();

Expand Down Expand Up @@ -86,7 +88,7 @@ public void Initalize(IConfiguration configuration)
_logger.LogInformation($"Detecting CSX files in '{_env.TargetDirectory}'.");

// Nothing to do if there are no CSX files
var allCsxFiles = Directory.GetFiles(_env.TargetDirectory, "*.csx", SearchOption.AllDirectories);
var allCsxFiles = _fileSystemHelper.GetFiles("**/*.csx").ToArray();
if (allCsxFiles.Length == 0)
{
_logger.LogInformation("Could not find any CSX files");
Expand Down
85 changes: 85 additions & 0 deletions tests/OmniSharp.Tests/FileSystemHelperFacts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using Microsoft.Extensions.Logging;
using OmniSharp.FileSystem;
using OmniSharp.Options;
using OmniSharp.Services;
using System.Linq;
using TestUtility;
using Xunit;

namespace OmniSharp.Tests
{
public class FileSystemHelperFacts
{
[Fact]
public void FileSystemHelperFacts_CanExcludeSearchPath_File()
{
var helper = CreateFileSystemHelper("**/ProjectWithSdkProperty.csproj");

var msbuildProjectFiles = helper.GetFiles("**/*.csproj");
Assert.NotEmpty(msbuildProjectFiles);

var projectWithSdkProperty = msbuildProjectFiles.FirstOrDefault(p => p.Contains("ProjectWithSdkProperty"));
Assert.Null(projectWithSdkProperty);
}

[Fact]
public void FileSystemHelperFacts_CanExcludeSearchPath_MultipleFiles()
{
var helper = CreateFileSystemHelper("**/MSTestProject.csproj", "**/NUnitTestProject.csproj");

var msbuildProjectFiles = helper.GetFiles("**/*.csproj");
Assert.NotEmpty(msbuildProjectFiles);

var msTestProject = msbuildProjectFiles.FirstOrDefault(p => p.Contains("MSTestProject"));
Assert.Null(msTestProject);

var nunitTestProject = msbuildProjectFiles.FirstOrDefault(p => p.Contains("NUnitTestProject"));
Assert.Null(nunitTestProject);
}

[Fact]
public void FileSystemHelperFacts_CanExcludeSearchPath_Folder()
{
var helper = CreateFileSystemHelper("**/ProjectWithSdkProperty/**/*");

var msbuildProjectFiles = helper.GetFiles("**/*.csproj");
Assert.NotEmpty(msbuildProjectFiles);

var projectWithSdkProperty = msbuildProjectFiles.FirstOrDefault(p => p.Contains("ProjectWithSdkProperty"));
Assert.Null(projectWithSdkProperty);
}

[Fact]
public void FileSystemHelperFacts_CanExcludeSearchPath_MultipleFolders()
{
var helper = CreateFileSystemHelper("**/MSTestProject/**/*", "**/NUnitTestProject/**/*");

var msbuildProjectFiles = helper.GetFiles("**/*.csproj");
Assert.NotEmpty(msbuildProjectFiles);

var msTestProject = msbuildProjectFiles.FirstOrDefault(p => p.Contains("MSTestProject"));
Assert.Null(msTestProject);

var nunitTestProject = msbuildProjectFiles.FirstOrDefault(p => p.Contains("NUnitTestProject"));
Assert.Null(nunitTestProject);
}

[Fact]
public void FileSystemHelperFacts_CanHandleInvalidPath()
{
var helper = CreateFileSystemHelper("!@@#$$@%&&*()_+");

var ex = Record.Exception(() => helper.GetFiles("**/*.csproj"));
Assert.Null(ex);
}

private FileSystemHelper CreateFileSystemHelper(params string[] excludePatterns)
{
var environment = new OmniSharpEnvironment(TestAssets.Instance.TestAssetsFolder, 1000, LogLevel.Information, null);
var options = new OmniSharpOptions();
options.FileOptions.ExcludeSearchPatterns = excludePatterns;
var helper = new FileSystemHelper(options, environment);
return helper;
}
}
}