Skip to content
This repository has been archived by the owner on Dec 18, 2017. It is now read-only.

Commit

Permalink
DTH: Validate dependency when search paths are updated
Browse files Browse the repository at this point in the history
  • Loading branch information
troydai committed Sep 26, 2015
1 parent 96e9385 commit 5066768
Show file tree
Hide file tree
Showing 14 changed files with 586 additions and 172 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"version": "6.0.8",
"dependencies": {
},
"frameworks": {
"dnx451": { }
}
}
6 changes: 6 additions & 0 deletions misc/DthTestProjects/UpdateSearchPathSample/home/global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"projects": [
"src",
"../ext"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"dependencies": {
"Newtonsoft.Json": "6.0.8"
},
"frameworks": {
"dnx451": { }
}
}
7 changes: 6 additions & 1 deletion src/Microsoft.Dnx.DesignTimeHost/ApplicationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,12 @@ private bool ResolveDependencies()
// hasn't died yet
TriggerProjectOutputsChanged();

state = _projectStateResolver.Resolve(_appPath.Value, _configuration.Value, triggerBuildOutputs, triggerDependencies, ProtocolVersion);
state = _projectStateResolver.Resolve(_appPath.Value,
_configuration.Value,
triggerBuildOutputs,
triggerDependencies,
ProtocolVersion,
_remote.ProjectInformation?.ProjectSearchPaths);
}

if (state == null)
Expand Down
160 changes: 125 additions & 35 deletions src/Microsoft.Dnx.DesignTimeHost/ProjectStateResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Microsoft.Dnx.DesignTimeHost.Models.OutgoingMessages;
using Microsoft.Dnx.Runtime;
using Microsoft.Dnx.Runtime.Common.Impl;
using Microsoft.Dnx.Runtime.Internals;
using NuGet;

namespace Microsoft.Dnx.DesignTimeHost
Expand All @@ -32,7 +33,12 @@ public ProjectStateResolver(CompilationEngine compilationEngine,
_applicationHostContextCreator = applicaitonHostContextCreator;
}

public ProjectState Resolve(string appPath, string configuration, bool triggerBuildOutputs, bool triggerDependencies, int protocolVersion)
public ProjectState Resolve(string appPath,
string configuration,
bool triggerBuildOutputs,
bool triggerDependencies,
int protocolVersion,
IList<string> currentSearchPaths)
{
var state = new ProjectState
{
Expand Down Expand Up @@ -72,9 +78,16 @@ public ProjectState Resolve(string appPath, string configuration, bool triggerBu

var sourcesProjectWidesources = project.Files.SourceFiles.ToList();

ResolveSearchPaths(state);

foreach (var frameworkName in frameworks)
{
var dependencyInfo = ResolveProjectDependencies(project, configuration, frameworkName, protocolVersion);
var dependencyInfo = ResolveProjectDependencies(project,
configuration,
frameworkName,
protocolVersion,
GetUpdatedSearchPaths(currentSearchPaths, state.ProjectSearchPaths));

var dependencySources = new List<string>(sourcesProjectWidesources);

var frameworkData = new FrameworkData
Expand Down Expand Up @@ -121,43 +134,16 @@ public ProjectState Resolve(string appPath, string configuration, bool triggerBu
};

state.Projects.Add(projectInfo);

GlobalSettings settings = null;

if (state.GlobalJsonPath == null)
{
var root = ProjectRootResolver.ResolveRootDirectory(project.ProjectDirectory);

if (GlobalSettings.TryGetGlobalSettings(root, out settings))
{
state.GlobalJsonPath = settings.FilePath;
}
}

if (state.ProjectSearchPaths == null)
{
var searchPaths = new HashSet<string>()
{
Directory.GetParent(project.ProjectDirectory).FullName
};

if (settings != null)
{
foreach (var searchPath in settings.ProjectSearchPaths)
{
var path = Path.Combine(settings.DirectoryPath, searchPath);
searchPaths.Add(Path.GetFullPath(path));
}
}

state.ProjectSearchPaths = searchPaths.ToList();
}
}

return state;
}

private DependencyInfo ResolveProjectDependencies(Project project, string configuration, FrameworkName frameworkName, int protocolVersion)
private DependencyInfo ResolveProjectDependencies(Project project,
string configuration,
FrameworkName frameworkName,
int protocolVersion,
List<string> updatedSearchPath)
{
var cacheKey = Tuple.Create("DependencyInfo", project.Name, configuration, frameworkName);

Expand All @@ -178,10 +164,19 @@ private DependencyInfo ResolveProjectDependencies(Project project, string config
};
var diagnosticSources = info.Diagnostics.ToLookup(diagnostic => diagnostic.Source);
var projectCandiates = GetProjectCandidates(updatedSearchPath);
foreach (var library in applicationHostContext.LibraryManager.GetLibraryDescriptions())
{
var diagnostics = diagnosticSources[library];
var diagnostics = diagnosticSources[library].ToList();
var newDiagnostic = ValidateDependency(library, projectCandiates);
if (newDiagnostic != null)
{
info.Diagnostics.Add(newDiagnostic);
diagnostics.Add(newDiagnostic);
}
var description = CreateDependencyDescription(library, diagnostics, protocolVersion);
info.Dependencies[description.Name] = description;
Expand Down Expand Up @@ -257,6 +252,81 @@ private DependencyInfo ResolveProjectDependencies(Project project, string config
});
}

private DiagnosticMessage ValidateDependency(LibraryDescription library, HashSet<string> projectCandidates)
{
if (!library.Resolved || projectCandidates == null)
{
return null;
}

var foundCandidate = projectCandidates.Contains(library.Identity.Name);

if ((library.Type == LibraryTypes.Project && !foundCandidate) ||
(library.Type == LibraryTypes.Package && foundCandidate))
{
library.Resolved = false;
library.Type = LibraryTypes.Unresolved;

return new DiagnosticMessage(
DiagnosticMonikers.NU1010,
$"The type of dependency {library.Identity.Name} was changed.",
library.RequestedRange.FileName,
DiagnosticMessageSeverity.Error,
library.RequestedRange.Line,
library.RequestedRange.Column,
library);
}

return null;
}

private static HashSet<string> GetProjectCandidates(IEnumerable<string> searchPaths)
{
if (searchPaths == null)
{
return null;
}

return new HashSet<string>(searchPaths.Where(path => Directory.Exists(path))
.SelectMany(path => Directory.GetDirectories(path))
.Where(path => File.Exists(Path.Combine(path, Project.ProjectFileName)))
.Select(path => Path.GetFileName(path)));
}

private static void ResolveSearchPaths(ProjectState state)
{
GlobalSettings settings = null;

if (state.GlobalJsonPath == null)
{
var root = ProjectRootResolver.ResolveRootDirectory(state.Project.ProjectDirectory);

if (GlobalSettings.TryGetGlobalSettings(root, out settings))
{
state.GlobalJsonPath = settings.FilePath;
}
}

if (state.ProjectSearchPaths == null)
{
var searchPaths = new HashSet<string>()
{
Directory.GetParent(state.Project.ProjectDirectory).FullName
};

if (settings != null)
{
foreach (var searchPath in settings.ProjectSearchPaths)
{
var path = Path.Combine(settings.DirectoryPath, searchPath);
searchPaths.Add(Path.GetFullPath(path));
}
}

state.ProjectSearchPaths = searchPaths.ToList();
}
}

private static DependencyDescription CreateDependencyDescription(LibraryDescription library,
IEnumerable<DiagnosticMessage> diagnostics,
int protocolVersion)
Expand Down Expand Up @@ -292,5 +362,25 @@ private static string GetProjectRelativeFullPath(Project referencedProject, stri
{
return Path.GetFullPath(Path.Combine(referencedProject.ProjectDirectory, path));
}

/// <summary>
/// Returns the search paths if they're updated. Otherwise returns null.
/// </summary>
private static List<string> GetUpdatedSearchPaths(IList<string> oldSearchPaths, List<string> newSearchPaths)
{
// The oldSearchPaths is null when the current project is not initialized. It is not necessary to
// validate the dependency in this case.
if (oldSearchPaths == null)
{
return null;
}

if (Enumerable.SequenceEqual(oldSearchPaths, newSearchPaths))
{
return null;
}

return newSearchPaths;
}
}
}
3 changes: 3 additions & 0 deletions src/Microsoft.Dnx.Runtime.Internals/DiagnosticMonikers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@ internal class DiagnosticMonikers

// The expected lock file doesn't exist. Please run \"dnu restore\" to generate a new lock file.
public static readonly string NU1009 = nameof(NU1009);

// The dependency type was changed
public static readonly string NU1010 = nameof(NU1010);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public LibraryDescription(
public LibraryRange RequestedRange { get; set; }
public LibraryIdentity Identity { get; }

public string Type { get; }
public string Type { get; set; }
public FrameworkName Framework { get; set; }

public string Path { get; set; }
Expand Down
Loading

0 comments on commit 5066768

Please sign in to comment.