Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
namespace ReferenceCop.MSBuild
{
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Build.Evaluation;

/// <summary>
/// Provides project reference information using MSBuild project evaluation.
/// </summary>
public class MSBuildProjectMetadataProvider : IProjectMetadataProvider
public class MSBuildProjectMetadataProvider : IProjectMetadataProvider, IDisposable
{
private const string ProjectReferenceNode = "ProjectReference";
private const string NoWarnMetadata = "NoWarn";

private readonly ProjectCollection projectCollection;
private bool disposed;

/// <summary>
/// Initializes a new instance of the <see cref="MSBuildProjectMetadataProvider"/> class.
/// </summary>
public MSBuildProjectMetadataProvider()
{
this.projectCollection = new ProjectCollection();
}

/// <summary>
/// Gets the project references from a project file.
/// </summary>
/// <param name="projectFilePath">The path to the project file.</param>
/// <returns>The collection of project references.</returns>
public IEnumerable<ProjectReferenceInfo> GetProjectReferences(string projectFilePath)
{
var projectCollection = new ProjectCollection();
var project = projectCollection.LoadProject(projectFilePath);
var project = this.LoadOrGetProject(projectFilePath);

// Get all ProjectReference items. These are the direct project references.
var projectReferences = project.GetItems(ProjectReferenceNode);
Expand All @@ -47,11 +58,48 @@ public IEnumerable<ProjectReferenceInfo> GetProjectReferences(string projectFile
/// <returns>The resolved property value.</returns>
public string GetPropertyValue(string projectFilePath, string propertyName)
{
var projectCollection = new ProjectCollection();
var project = projectCollection.LoadProject(projectFilePath);
var project = this.LoadOrGetProject(projectFilePath);
project.ReevaluateIfNecessary();

return project.GetPropertyValue(propertyName);
}

/// <inheritdoc />
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

/// <summary>
/// Releases the resources used by the <see cref="MSBuildProjectMetadataProvider"/>.
/// </summary>
/// <param name="disposing">Whether managed resources should be disposed.</param>
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
this.projectCollection.UnloadAllProjects();
this.projectCollection.Dispose();
}

this.disposed = true;
}
}

private Project LoadOrGetProject(string projectFilePath)
{
var fullPath = System.IO.Path.GetFullPath(projectFilePath);
var loaded = this.projectCollection.GetLoadedProjects(fullPath);

if (loaded.Count > 0)
{
return loaded.First();
}

return this.projectCollection.LoadProject(fullPath);
}
}
}
4 changes: 4 additions & 0 deletions src/ReferenceCop.MSBuild/ReferenceCopTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ public bool Execute()
success = false;
this.BuildEngine.LogErrorEvent(ex);
}
finally
{
(this.projectReferencesProvider as IDisposable)?.Dispose();
}

return success;
}
Expand Down
Loading