Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feature/fix-all-pro…
Browse files Browse the repository at this point in the history
…viders
  • Loading branch information
david-driscoll committed Jul 29, 2020
2 parents d8252f7 + 1d552c5 commit 4dc7c18
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 38 deletions.
1 change: 1 addition & 0 deletions build.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"XunitTestProject",
"MSTestProject",
"ProjectAndSolution",
"ProjectAndSolutionWithGlobs",
"ProjectAndSolutionWithProjectSection",
"TwoProjectsWithSolution",
"ProjectWithGeneratedFile",
Expand Down
3 changes: 3 additions & 0 deletions src/OmniSharp.MSBuild/Notification/ProjectLoadedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace OmniSharp.MSBuild.Notification
public class ProjectLoadedEventArgs
{
public ProjectId Id { get; }
public MSB.Evaluation.Project Project { get; }
public Guid SessionId { get; }
public MSB.Execution.ProjectInstance ProjectInstance { get; }
public ImmutableArray<MSBuildDiagnostic> Diagnostics { get; }
Expand All @@ -22,6 +23,7 @@ public class ProjectLoadedEventArgs

public ProjectLoadedEventArgs(
ProjectId id,
MSB.Evaluation.Project project,
Guid sessionId,
MSB.Execution.ProjectInstance projectInstance,
ImmutableArray<MSBuildDiagnostic> diagnostics,
Expand All @@ -32,6 +34,7 @@ public ProjectLoadedEventArgs(
IEnumerable<string> references = null)
{
Id = id;
Project = project;
SessionId = sessionId;
ProjectInstance = projectInstance;
Diagnostics = diagnostics;
Expand Down
57 changes: 48 additions & 9 deletions src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.ProjectData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.IO;
using System.Linq;
using System.Runtime.Versioning;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Globbing;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using NuGet.Packaging.Core;
Expand Down Expand Up @@ -43,6 +45,7 @@ private class ProjectData
public bool SignAssembly { get; }
public string AssemblyOriginatorKeyFile { get; }

public ImmutableArray<IMSBuildGlob> FileInclusionGlobs { get; }
public ImmutableArray<string> SourceFiles { get; }
public ImmutableArray<string> ProjectReferences { get; }
public ImmutableArray<string> References { get; }
Expand Down Expand Up @@ -77,6 +80,7 @@ private ProjectData()
ReferenceAliases = ImmutableDictionary<string, string>.Empty;
ProjectReferenceAliases = ImmutableDictionary<string, string>.Empty;
WarningsAsErrors = ImmutableArray<string>.Empty;
FileInclusionGlobs = ImmutableArray<IMSBuildGlob>.Empty;
WarningsNotAsErrors = ImmutableArray<string>.Empty;
}

Expand Down Expand Up @@ -173,7 +177,8 @@ private ProjectData(
bool runAnalyzersDuringLiveAnalysis,
RuleSet ruleset,
ImmutableDictionary<string, string> referenceAliases,
ImmutableDictionary<string, string> projectReferenceAliases)
ImmutableDictionary<string, string> projectReferenceAliases,
ImmutableArray<IMSBuildGlob> fileInclusionGlobs)
: this(guid, name, assemblyName, targetPath, outputPath, intermediateOutputPath, projectAssetsFile,
configuration, platform, targetFramework, targetFrameworks, outputKind, languageVersion, nullableContextOptions, allowUnsafeCode, checkForOverflowUnderflow,
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, warningsAsErrors, warningsNotAsErrors, signAssembly, assemblyOriginatorKeyFile, treatWarningsAsErrors, defaultNamespace, runAnalyzers, runAnalyzersDuringLiveAnalysis, ruleset)
Expand All @@ -187,6 +192,7 @@ private ProjectData(
AnalyzerConfigFiles = analyzerConfigFiles.EmptyIfDefault();
ReferenceAliases = referenceAliases;
ProjectReferenceAliases = projectReferenceAliases;
FileInclusionGlobs = fileInclusionGlobs;
}

public static ProjectData Create(MSB.Evaluation.Project project)
Expand Down Expand Up @@ -234,7 +240,7 @@ public static ProjectData Create(MSB.Evaluation.Project project)
documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, warningsAsErrors, warningsNotAsErrors, signAssembly, assemblyOriginatorKeyFile, treatWarningsAsErrors, defaultNamespace, runAnalyzers, runAnalyzersDuringLiveAnalysis, ruleset: null);
}

public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance, MSB.Evaluation.Project project)
{
var guid = PropertyConverter.ToGuid(projectInstance.GetPropertyValue(PropertyNames.ProjectGuid));
var name = projectInstance.GetPropertyValue(PropertyNames.ProjectName);
Expand Down Expand Up @@ -336,14 +342,47 @@ public static ProjectData Create(MSB.Execution.ProjectInstance projectInstance)
var analyzers = GetFullPaths(projectInstance.GetItems(ItemNames.Analyzer));
var additionalFiles = GetFullPaths(projectInstance.GetItems(ItemNames.AdditionalFiles));
var editorConfigFiles = GetFullPaths(projectInstance.GetItems(ItemNames.EditorConfigFiles));
var includeGlobs = project.GetAllGlobs().Select(x => x.MsBuildGlob).ToImmutableArray();

return new ProjectData(guid, name,
assemblyName, targetPath, outputPath, intermediateOutputPath, projectAssetsFile,
configuration, platform, targetFramework, targetFrameworks,
outputKind, languageVersion, nullableContextOptions, allowUnsafeCode, checkForOverflowUnderflow, documentationFile, preprocessorSymbolNames, suppressedDiagnosticIds, warningsAsErrors, warningsNotAsErrors,
signAssembly, assemblyOriginatorKeyFile,
sourceFiles, projectReferences.ToImmutable(), references.ToImmutable(), packageReferences, analyzers, additionalFiles, editorConfigFiles, treatWarningsAsErrors, defaultNamespace, runAnalyzers, runAnalyzersDuringLiveAnalysis, ruleset,
referenceAliases.ToImmutableDictionary(), projectReferenceAliases.ToImmutable());
return new ProjectData(
guid,
name,
assemblyName,
targetPath,
outputPath,
intermediateOutputPath,
projectAssetsFile,
configuration,
platform,
targetFramework,
targetFrameworks,
outputKind,
languageVersion,
nullableContextOptions,
allowUnsafeCode,
checkForOverflowUnderflow,
documentationFile,
preprocessorSymbolNames,
suppressedDiagnosticIds,
warningsAsErrors,
warningsNotAsErrors,
signAssembly,
assemblyOriginatorKeyFile,
sourceFiles,
projectReferences.ToImmutable(),
references.ToImmutable(),
packageReferences,
analyzers,
additionalFiles,
editorConfigFiles,
treatWarningsAsErrors,
defaultNamespace,
runAnalyzers,
runAnalyzersDuringLiveAnalysis,
ruleset,
referenceAliases.ToImmutableDictionary(),
projectReferenceAliases.ToImmutable(),
includeGlobs);
}

private static RuleSet ResolveRulesetIfAny(MSB.Execution.ProjectInstance projectInstance)
Expand Down
24 changes: 20 additions & 4 deletions src/OmniSharp.MSBuild/ProjectFile/ProjectFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
using System.IO;
using System.Linq;
using System.Runtime.Versioning;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Globbing;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using OmniSharp.FileSystem;
using OmniSharp.MSBuild.Logging;
using OmniSharp.MSBuild.Notification;
using OmniSharp.Services;
Expand Down Expand Up @@ -62,6 +65,7 @@ internal partial class ProjectFileInfo
public bool RunAnalyzers => _data.RunAnalyzers;
public bool RunAnalyzersDuringLiveAnalysis => _data.RunAnalyzersDuringLiveAnalysis;
public string DefaultNamespace => _data.DefaultNamespace;
public ImmutableArray<IMSBuildGlob> FileInclusionGlobPatterns => _data.FileInclusionGlobs;

public ProjectIdInfo ProjectIdInfo { get; }
public DotNetInfo DotNetInfo { get; }
Expand Down Expand Up @@ -109,15 +113,16 @@ public static (ProjectFileInfo, ImmutableArray<MSBuildDiagnostic>, ProjectLoaded
return (null, ImmutableArray<MSBuildDiagnostic>.Empty, null);
}

var (projectInstance, diagnostics) = loader.BuildProject(filePath);
var (projectInstance, project, diagnostics) = loader.BuildProject(filePath);
if (projectInstance == null)
{
return (null, diagnostics, null);
}

var data = ProjectData.Create(projectInstance);
var data = ProjectData.Create(projectInstance, project);
var projectFileInfo = new ProjectFileInfo(projectIdInfo, filePath, data, sessionId, dotNetInfo);
var eventArgs = new ProjectLoadedEventArgs(projectIdInfo.Id,
project,
sessionId,
projectInstance,
diagnostics,
Expand All @@ -132,15 +137,16 @@ public static (ProjectFileInfo, ImmutableArray<MSBuildDiagnostic>, ProjectLoaded

public (ProjectFileInfo, ImmutableArray<MSBuildDiagnostic>, ProjectLoadedEventArgs) Reload(ProjectLoader loader)
{
var (projectInstance, diagnostics) = loader.BuildProject(FilePath);
var (projectInstance, project, diagnostics) = loader.BuildProject(FilePath);
if (projectInstance == null)
{
return (null, diagnostics, null);
}

var data = ProjectData.Create(projectInstance);
var data = ProjectData.Create(projectInstance, project);
var projectFileInfo = new ProjectFileInfo(ProjectIdInfo, FilePath, data, SessionId, DotNetInfo);
var eventArgs = new ProjectLoadedEventArgs(Id,
project,
SessionId,
projectInstance,
diagnostics,
Expand All @@ -161,5 +167,15 @@ public bool IsUnityProject()
return string.Equals(fileName, "UnityEngine.dll", StringComparison.OrdinalIgnoreCase)
|| string.Equals(fileName, "UnityEditor.dll", StringComparison.OrdinalIgnoreCase);
});


public bool IsFileIncluded(string filePath)
{
if (SourceFiles.Contains(filePath, StringComparer.OrdinalIgnoreCase))
return true;

var relativePath = FileSystemHelper.GetRelativePath(filePath, FilePath);
return FileInclusionGlobPatterns.Any(glob => glob.IsMatch(relativePath));
}
}
}
6 changes: 3 additions & 3 deletions src/OmniSharp.MSBuild/ProjectLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private static Dictionary<string, string> CreateGlobalProperties(
return globalProperties;
}

public (MSB.Execution.ProjectInstance projectInstance, ImmutableArray<MSBuildDiagnostic> diagnostics) BuildProject(string filePath)
public (MSB.Execution.ProjectInstance projectInstance, MSB.Evaluation.Project project, ImmutableArray<MSBuildDiagnostic> diagnostics) BuildProject(string filePath)
{
using (_sdksPathResolver.SetSdksPathEnvironmentVariable(filePath))
{
Expand Down Expand Up @@ -102,8 +102,8 @@ private static Dictionary<string, string> CreateGlobalProperties(
var diagnostics = msbuildLogger.GetDiagnostics();

return buildResult
? (projectInstance, diagnostics)
: (null, diagnostics);
? (projectInstance, evaluatedProject, diagnostics)
: (null, null, diagnostics);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/OmniSharp.MSBuild/ProjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ private void AddProject(ProjectFileInfo projectFileInfo)
var projectInfo = projectFileInfo.CreateProjectInfo(_analyzerAssemblyLoader);

var newSolution = _workspace.CurrentSolution.AddProject(projectInfo);
_workspace.AddDocumentInclusionRuleForProject(projectInfo.Id, (filePath) => projectFileInfo.IsFileIncluded(filePath));

if (!_workspace.TryApplyChanges(newSolution))
{
Expand Down Expand Up @@ -468,6 +469,7 @@ private void UpdateProject(string projectFilePath)
UpdateAnalyzerConfigFiles(project, projectFileInfo.AnalyzerConfigFiles);
UpdateProjectProperties(project, projectFileInfo);

_workspace.AddDocumentInclusionRuleForProject(project.Id, (path) => projectFileInfo.IsFileIncluded(path));
_workspace.TryPromoteMiscellaneousDocumentsToProject(project);
_workspace.UpdateCompilationOptionsForProject(project.Id, projectFileInfo.CreateCompilationOptions());
}
Expand Down
23 changes: 4 additions & 19 deletions src/OmniSharp.Roslyn/BufferManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
Expand Down Expand Up @@ -187,25 +188,9 @@ private void OnFileChanged(string filePath, FileChangeType changeType)

private IEnumerable<Project> FindProjectsByFileName(string fileName)
{
var fileInfo = new FileInfo(fileName);
var dirInfo = fileInfo.Directory;
var candidates = _workspace.CurrentSolution.Projects
.Where(project => !String.IsNullOrWhiteSpace (project.FilePath))
.GroupBy(project => new FileInfo(project.FilePath).Directory.FullName)
.ToDictionary(grouping => grouping.Key, grouping => grouping.ToList());

List<Project> projects = null;
while (dirInfo != null)
{
if (candidates.TryGetValue(dirInfo.FullName, out projects))
{
return projects;
}

dirInfo = dirInfo.Parent;
}

return Array.Empty<Project>();
return _workspace.CurrentSolution.Projects
.Where(project => _workspace.FileBelongsToProject(fileName, project))
.ToImmutableArray();
}

private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
Expand Down
24 changes: 23 additions & 1 deletion src/OmniSharp.Roslyn/OmniSharpWorkspace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public bool Initialized
private readonly ILogger<OmniSharpWorkspace> _logger;

private readonly ConcurrentBag<Func<string, Task>> _waitForProjectModelReadyHandlers = new ConcurrentBag<Func<string, Task>>();

private readonly ConcurrentDictionary<string, ProjectInfo> miscDocumentsProjectInfos = new ConcurrentDictionary<string, ProjectInfo>();
private readonly ConcurrentDictionary<ProjectId, Predicate<string>> documentInclusionRulesPerProject = new ConcurrentDictionary<ProjectId, Predicate<string>>();
private bool isInitialized;

[ImportingConstructor]
Expand Down Expand Up @@ -106,6 +106,11 @@ public void AddProject(ProjectInfo projectInfo)
OnProjectAdded(projectInfo);
}

public void AddDocumentInclusionRuleForProject(ProjectId projectId, Predicate<string> documentPathFilter)
{
documentInclusionRulesPerProject[projectId] = documentPathFilter;
}

public void AddProjectReference(ProjectId projectId, ProjectReference projectReference)
{
OnProjectReferenceAdded(projectId, projectReference);
Expand Down Expand Up @@ -371,9 +376,20 @@ internal bool FileBelongsToProject(string fileName, Project project)
return false;
}

// File path needs to be checked against any rules defined by the specific project system. (e.g. MSBuild default excluded folders)
if (documentInclusionRulesPerProject.TryGetValue(project.Id, out Predicate<string> documentInclusionFilter))
{
return documentInclusionFilter(fileName);
}

// if no custom rule set for this ProjectId, fallback to simple directory heuristic.
var fileDirectory = new FileInfo(fileName).Directory;
var projectPath = project.FilePath;
var projectDirectory = new FileInfo(projectPath).Directory.FullName;
var otherProjectDirectories = CurrentSolution.Projects
.Where(p => p != project && !string.IsNullOrWhiteSpace(p.FilePath))
.Select(p => new FileInfo(p.FilePath).Directory.FullName)
.ToImmutableArray();

while (fileDirectory != null)
{
Expand All @@ -382,6 +398,12 @@ internal bool FileBelongsToProject(string fileName, Project project)
return true;
}

// if any project is closer to the file, file should belong to that project.
if (otherProjectDirectories.Contains(fileDirectory.FullName, StringComparer.OrdinalIgnoreCase))
{
return false;
}

fileDirectory = fileDirectory.Parent;
}

Expand Down
12 changes: 12 additions & 0 deletions test-assets/test-projects/ProjectAndSolutionWithGlobs/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace ProjectAndSolutionWithGlobs
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Compile Include="obj/explicitlyIncludedFolder/*.cs" />
<Compile Remove="explicitlyIgnoredFolder/*.cs" />
<Compile Remove="explicitlyIgnoredFile.cs" />
</ItemGroup>
</Project>
Loading

0 comments on commit 4dc7c18

Please sign in to comment.