diff --git a/README.md b/README.md index eecf595ed..5ace6e6ee 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ## Building/Running 1. Run `build.cmd` or `build.sh` from the root -2. Use `artifacts/{os}-{arch}/state2/dotnet` to try out the `dotnet` command. You can also add `artifacts/{os}-{arch}/state2` to the PATH if you want to run `dotnet` from anywhere. +2. Use `artifacts/{os}-{arch}/stage2/dotnet` to try out the `dotnet` command. You can also add `artifacts/{os}-{arch}/stage2` to the PATH if you want to run `dotnet` from anywhere. ## Notes diff --git a/src/Microsoft.DotNet.Cli.Utils/Command.cs b/src/Microsoft.DotNet.Cli.Utils/Command.cs index f7efcfb50..0df5d1c26 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Command.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Command.cs @@ -130,7 +130,7 @@ namespace Microsoft.DotNet.Cli.Utils #if DEBUG var sw = Stopwatch.StartNew(); - Console.WriteLine($"> {_process.StartInfo.FileName} {_process.StartInfo.Arguments}"); + Reporter.Output.WriteLine($"> {_process.StartInfo.FileName} {_process.StartInfo.Arguments}".White()); #endif _process.Start(); _process.BeginOutputReadLine(); @@ -139,7 +139,15 @@ namespace Microsoft.DotNet.Cli.Utils var exitCode = await _processTcs.Task; #if DEBUG - Console.WriteLine($"> {_process.StartInfo.FileName} {_process.StartInfo.Arguments} exited with {exitCode} in {sw.ElapsedMilliseconds} ms."); + var message = $"> {_process.StartInfo.FileName} {_process.StartInfo.Arguments} exited with {exitCode} in {sw.ElapsedMilliseconds} ms."; + if (exitCode == 0) + { + Reporter.Output.WriteLine(message.Green().Bold()); + } + else + { + Reporter.Output.WriteLine(message.Red().Bold()); + } #endif return new CommandResult( diff --git a/src/Microsoft.DotNet.Tools.Compiler/Reporter.cs b/src/Microsoft.DotNet.Cli.Utils/Reporter.cs similarity index 100% rename from src/Microsoft.DotNet.Tools.Compiler/Reporter.cs rename to src/Microsoft.DotNet.Cli.Utils/Reporter.cs diff --git a/src/Microsoft.DotNet.Cli/project.json b/src/Microsoft.DotNet.Cli/project.json index 2c8acbb10..01f4516ac 100644 --- a/src/Microsoft.DotNet.Cli/project.json +++ b/src/Microsoft.DotNet.Cli/project.json @@ -17,6 +17,10 @@ "Microsoft.DotNet.Cli.Utils": { "type": "build", "version": "1.0.0-*" + }, + "Microsoft.Extensions.CommandLineUtils.Sources": { + "type": "build", + "version": "1.0.0-*" } }, "frameworks": { diff --git a/src/Microsoft.DotNet.Tools.Compiler/Program.cs b/src/Microsoft.DotNet.Tools.Compiler/Program.cs index 2118bb7c5..027f44e7f 100644 --- a/src/Microsoft.DotNet.Tools.Compiler/Program.cs +++ b/src/Microsoft.DotNet.Tools.Compiler/Program.cs @@ -66,7 +66,11 @@ namespace Microsoft.DotNet.Tools.Compiler } catch (Exception ex) { +#if DEBUG + Console.Error.WriteLine(ex); +#else Console.Error.WriteLine(ex.Message); +#endif return 1; } } @@ -163,7 +167,7 @@ namespace Microsoft.DotNet.Tools.Compiler // Get compilation options var compilationOptions = context.ProjectFile.GetCompilerOptions(context.TargetFramework, configuration); - var outputName = Path.Combine(outputPath, context.ProjectFile.Name + ".dll"); + var outputName = Path.Combine(outputPath, context.ProjectFile.Name + (compilationOptions.EmitEntryPoint.GetValueOrDefault() ? ".exe" : ".dll")); var bootstrappingWithMono = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BOOTSTRAPPING_WITH_MONO")); diff --git a/src/Microsoft.DotNet.Tools.Publish/Program.cs b/src/Microsoft.DotNet.Tools.Publish/Program.cs index 9de5e254c..6ad3eaf95 100644 --- a/src/Microsoft.DotNet.Tools.Publish/Program.cs +++ b/src/Microsoft.DotNet.Tools.Publish/Program.cs @@ -58,7 +58,11 @@ namespace Microsoft.DotNet.Tools.Publish } catch (Exception ex) { +#if DEBUG + Console.Error.WriteLine(ex); +#else Console.Error.WriteLine(ex.Message); +#endif return 1; } } @@ -109,6 +113,10 @@ namespace Microsoft.DotNet.Tools.Publish // Use a library exporter to collect publish assets var exporter = context.CreateExporter(configuration); + // Copy things marked as copy to output (which we don't have yet) + // so does copy too many things + CopyContents(context, outputPath); + foreach (var export in exporter.GetAllExports()) { Reporter.Output.WriteLine($"Publishing {export.Library.Identity.ToString().Green().Bold()} ..."); @@ -119,7 +127,7 @@ namespace Microsoft.DotNet.Tools.Publish // Publishing for windows, TODO(anurse): Publish for Mac/Linux/etc. int exitCode; - if (context.RuntimeIdentifier.Equals("win7-x64")) + if (context.RuntimeIdentifier.StartsWith("win")) { exitCode = PublishForWindows(context, outputPath); } @@ -161,7 +169,6 @@ namespace Microsoft.DotNet.Tools.Publish // Use the 'command' field to generate the name var outputExe = Path.Combine(outputPath, context.ProjectFile.Name); - var outputDll = Path.Combine(outputPath, context.ProjectFile.Name + ".dll"); // Write a script that can be used to launch with CoreRun var script = $@"#!/usr/bin/env bash @@ -183,14 +190,15 @@ exec ""$DIR/corerun"" ""$DIR/{context.ProjectFile.Name}.exe"" $*"; .GetAwaiter() .GetResult(); - File.Copy(outputDll, Path.ChangeExtension(outputDll, ".exe")); - File.Delete(outputDll); - return 0; } private static int PublishForWindows(ProjectContext context, string outputPath) { + if (context.TargetFramework.IsDesktop()) + { + return 0; + } // Locate Hosts string hostsPath = Environment.GetEnvironmentVariable(Constants.HostsPathEnvironmentVariable); if (string.IsNullOrEmpty(hostsPath)) @@ -216,13 +224,80 @@ exec ""$DIR/corerun"" ""$DIR/{context.ProjectFile.Name}.exe"" $*"; File.Copy(coreConsole, Path.Combine(outputPath, Constants.CoreConsoleName), overwrite: true); File.Copy(coreRun, Path.Combine(outputPath, Constants.CoreRunName), overwrite: true); - // Use the 'command' field to generate the name var outputExe = Path.Combine(outputPath, context.ProjectFile.Name + Constants.ExeSuffix); - File.Copy(coreConsole, outputExe, overwrite: true); + // Rename the {app}.exe to {app}.dll + File.Copy(outputExe, Path.ChangeExtension(outputExe, ".dll"), overwrite: true); + + // Change coreconsole.exe to the {app}.exe name + File.Copy(coreConsole, outputExe, overwrite: true); return 0; } + private static void CopyContents(ProjectContext context, string outputPath) + { + var sourceFiles = context.ProjectFile.Files.GetFilesForBundling(); + Copy(sourceFiles, context.ProjectDirectory, outputPath); + } + + private static void Copy(IEnumerable sourceFiles, string sourceDirectory, string targetDirectory) + { + if (sourceFiles == null) + { + throw new ArgumentNullException(nameof(sourceFiles)); + } + + sourceDirectory = EnsureTrailingSlash(sourceDirectory); + targetDirectory = EnsureTrailingSlash(targetDirectory); + + foreach (var sourceFilePath in sourceFiles) + { + var fileName = Path.GetFileName(sourceFilePath); + + var targetFilePath = sourceFilePath.Replace(sourceDirectory, targetDirectory); + var targetFileParentFolder = Path.GetDirectoryName(targetFilePath); + + // Create directory before copying a file + if (!Directory.Exists(targetFileParentFolder)) + { + Directory.CreateDirectory(targetFileParentFolder); + } + + File.Copy( + sourceFilePath, + targetFilePath, + overwrite: true); + + // clear read-only bit if set + var fileAttributes = File.GetAttributes(targetFilePath); + if ((fileAttributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) + { + File.SetAttributes(targetFilePath, fileAttributes & ~FileAttributes.ReadOnly); + } + } + } + + private static string EnsureTrailingSlash(string path) + { + return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar); + } + + private static string EnsureTrailingCharacter(string path, char trailingCharacter) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + // if the path is empty, we want to return the original string instead of a single trailing character. + if (path.Length == 0 || path[path.Length - 1] == trailingCharacter) + { + return path; + } + + return path + trailingCharacter; + } + private static void PublishFiles(IEnumerable files, string outputPath) { foreach (var file in files) diff --git a/src/Microsoft.DotNet.Tools.Publish/Reporter.cs b/src/Microsoft.DotNet.Tools.Publish/Reporter.cs deleted file mode 100644 index f5b5ea57f..000000000 --- a/src/Microsoft.DotNet.Tools.Publish/Reporter.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Runtime.InteropServices; -using Microsoft.Dnx.Runtime.Common.CommandLine; - -namespace Microsoft.DotNet.Cli.Utils -{ - // Stupid-simple console manager - internal static class Reporter - { - public static AnsiConsole Output { get; } = AnsiConsole.GetOutput(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); - public static AnsiConsole Error { get; } = AnsiConsole.GetError(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); - } -} diff --git a/src/Microsoft.Extensions.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.Extensions.ProjectModel/Compilation/LibraryExporter.cs index 067cee26b..8198fd737 100644 --- a/src/Microsoft.Extensions.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.Extensions.ProjectModel/Compilation/LibraryExporter.cs @@ -166,12 +166,13 @@ namespace Microsoft.Extensions.ProjectModel.Compilation private string GetOutputPath(ProjectDescription project) { + var compilationOptions = project.Project.GetCompilerOptions(project.Framework, _configuration); return Path.Combine( project.Project.ProjectDirectory, "bin", // This can't access the Constant in Cli Utils. But the output path stuff is temporary right now anyway _configuration, project.Framework.GetTwoDigitShortFolderName(), - project.Project.Name + ".dll"); + project.Project.Name + (compilationOptions.EmitEntryPoint.GetValueOrDefault() ? ".exe" : ".dll")); } private static string ResolvePath(Project project, string configuration, string path) diff --git a/src/Microsoft.Extensions.ProjectModel/Files/ProjectFilesCollection.cs b/src/Microsoft.Extensions.ProjectModel/Files/ProjectFilesCollection.cs index f7fc5a1c2..ab56d43dc 100644 --- a/src/Microsoft.Extensions.ProjectModel/Files/ProjectFilesCollection.cs +++ b/src/Microsoft.Extensions.ProjectModel/Files/ProjectFilesCollection.cs @@ -12,7 +12,7 @@ namespace Microsoft.Extensions.ProjectModel.Files public class ProjectFilesCollection { public static readonly string[] DefaultCompileBuiltInPatterns = new[] { @"**/*.cs" }; - public static readonly string[] DefaultPublishExcludePatterns = new[] { @"obj/**/*.*", @"bin/**/*.*", @"**/.*/**", @"**/global.json" }; + public static readonly string[] DefaultPublishExcludePatterns = new[] { @"obj/**/*.*", @"bin/**/*.*", @"**/.*/**", @"**/global.json", @"**/project.json", @"**/project.lock.json" }; public static readonly string[] DefaultPreprocessPatterns = new[] { @"compiler/preprocess/**/*.cs" }; public static readonly string[] DefaultSharedPatterns = new[] { @"compiler/shared/**/*.cs" }; public static readonly string[] DefaultResourcesBuiltInPatterns = new[] { @"compiler/resources/**/*", "**/*.resx" }; @@ -138,17 +138,15 @@ namespace Microsoft.Extensions.ProjectModel.Files get { return SharedPatternsGroup.SearchFiles(_projectDirectory).Distinct(); } } - public IEnumerable GetFilesForBundling(bool includeSource, IEnumerable additionalExcludePatterns) + public IEnumerable GetFilesForBundling(IEnumerable additionalExcludePatterns = null) { var patternGroup = new PatternGroup(ContentPatternsGroup.IncludePatterns, - ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns), + ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns ?? new List()), ContentPatternsGroup.IncludeLiterals); - if (!includeSource) + + foreach (var excludedGroup in ContentPatternsGroup.ExcludePatternsGroup) { - foreach (var excludedGroup in ContentPatternsGroup.ExcludePatternsGroup) - { - patternGroup.ExcludeGroup(excludedGroup); - } + patternGroup.ExcludeGroup(excludedGroup); } return patternGroup.SearchFiles(_projectDirectory); diff --git a/src/Microsoft.Extensions.ProjectModel/Graph/LibraryType.cs b/src/Microsoft.Extensions.ProjectModel/Graph/LibraryType.cs index 875e747eb..0c1e8c6e3 100644 --- a/src/Microsoft.Extensions.ProjectModel/Graph/LibraryType.cs +++ b/src/Microsoft.Extensions.ProjectModel/Graph/LibraryType.cs @@ -22,12 +22,12 @@ namespace Microsoft.Extensions.ProjectModel.Graph public static bool TryParse(string value, out LibraryType type) { // We only support values we know about - if(string.Equals(Package.Value, value, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(Package.Value, value, StringComparison.OrdinalIgnoreCase)) { type = Package; return true; } - else if(string.Equals(Project.Value, value, StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(Project.Value, value, StringComparison.OrdinalIgnoreCase)) { type = Project; return true; @@ -80,6 +80,10 @@ namespace Microsoft.Extensions.ProjectModel.Graph public override int GetHashCode() { + if (string.IsNullOrEmpty(Value)) + { + return 0; + } return StringComparer.OrdinalIgnoreCase.GetHashCode(Value); } } diff --git a/src/Microsoft.Extensions.ProjectModel/LibraryDescription.cs b/src/Microsoft.Extensions.ProjectModel/LibraryDescription.cs index 2796dd532..d3047fb3c 100644 --- a/src/Microsoft.Extensions.ProjectModel/LibraryDescription.cs +++ b/src/Microsoft.Extensions.ProjectModel/LibraryDescription.cs @@ -1,8 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Internal; using Microsoft.Extensions.ProjectModel.Graph; using NuGet.Frameworks; @@ -14,7 +16,6 @@ namespace Microsoft.Extensions.ProjectModel public class LibraryDescription { public LibraryDescription( - LibraryRange requestedRange, LibraryIdentity identity, string path, IEnumerable dependencies, @@ -23,7 +24,6 @@ namespace Microsoft.Extensions.ProjectModel bool compatible) { Path = path; - RequestedRange = requestedRange; Identity = identity; Dependencies = dependencies ?? Enumerable.Empty(); Framework = framework; @@ -31,9 +31,9 @@ namespace Microsoft.Extensions.ProjectModel Compatible = compatible; } - public LibraryRange RequestedRange { get; } public LibraryIdentity Identity { get; } - public List Parents { get; set; } = new List(); + public HashSet RequestedRanges { get; } = new HashSet(new LibraryRangeEqualityComparer()); + public List Parents { get; } = new List(); public string Path { get; } public IEnumerable Dependencies { get; } public bool Compatible { get; } @@ -45,5 +45,29 @@ namespace Microsoft.Extensions.ProjectModel { return $"{Identity} = {Path}"; } + + // For diagnostics, we don't want to duplicate requested dependencies so we + // dedupe dependencies defined in project.json + private class LibraryRangeEqualityComparer : IEqualityComparer + { + public bool Equals(LibraryRange x, LibraryRange y) + { + return x.Equals(y) && + x.SourceColumn == y.SourceColumn && + x.SourceLine == y.SourceLine && + string.Equals(x.SourceFilePath, y.SourceFilePath, StringComparison.Ordinal); + } + + public int GetHashCode(LibraryRange obj) + { + var combiner = HashCodeCombiner.Start(); + combiner.Add(obj); + combiner.Add(obj.SourceFilePath); + combiner.Add(obj.SourceLine); + combiner.Add(obj.SourceColumn); + + return combiner.CombinedHash; + } + } } } diff --git a/src/Microsoft.Extensions.ProjectModel/PackageDescription.cs b/src/Microsoft.Extensions.ProjectModel/PackageDescription.cs index fd49f2df7..f0b558c15 100644 --- a/src/Microsoft.Extensions.ProjectModel/PackageDescription.cs +++ b/src/Microsoft.Extensions.ProjectModel/PackageDescription.cs @@ -6,19 +6,17 @@ namespace Microsoft.Extensions.ProjectModel public class PackageDescription : LibraryDescription { public PackageDescription( - LibraryRange requestedRange, string path, LockFilePackageLibrary package, LockFileTargetLibrary lockFileLibrary, IEnumerable dependencies, bool compatible) : base( - requestedRange, new LibraryIdentity(package.Name, package.Version, LibraryType.Package), path, dependencies: dependencies, framework: null, - resolved: true, + resolved: compatible, compatible: compatible) { Library = package; diff --git a/src/Microsoft.Extensions.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.Extensions.ProjectModel/ProjectContextBuilder.cs index 92178e1fc..42f18dd1d 100644 --- a/src/Microsoft.Extensions.ProjectModel/ProjectContextBuilder.cs +++ b/src/Microsoft.Extensions.ProjectModel/ProjectContextBuilder.cs @@ -110,7 +110,7 @@ namespace Microsoft.Extensions.ProjectModel } // Create a library manager - var libraryManager = new LibraryManager(Project.ProjectFilePath, libraries.Values.ToList(), diagnostics); + var libraryManager = new LibraryManager(libraries.Values.ToList(), diagnostics); return new ProjectContext( GlobalSettings, @@ -153,6 +153,7 @@ namespace Microsoft.Extensions.ProjectModel } } + dep.RequestedRanges.Add(dependency); dep.Parents.Add(library); } } diff --git a/src/Microsoft.Extensions.ProjectModel/ProjectDescription.cs b/src/Microsoft.Extensions.ProjectModel/ProjectDescription.cs index 3f6609b95..a5c17d662 100644 --- a/src/Microsoft.Extensions.ProjectModel/ProjectDescription.cs +++ b/src/Microsoft.Extensions.ProjectModel/ProjectDescription.cs @@ -12,7 +12,6 @@ namespace Microsoft.Extensions.ProjectModel // Create an unresolved project description public ProjectDescription(string name, string path) : base( - new LibraryRange(name, LibraryType.Unspecified), new LibraryIdentity(name, LibraryType.Project), path, Enumerable.Empty(), @@ -28,7 +27,6 @@ namespace Microsoft.Extensions.ProjectModel TargetFrameworkInformation targetFrameworkInfo, bool resolved) : base( - libraryRange, new LibraryIdentity(project.Name, project.Version, LibraryType.Project), project.ProjectFilePath, dependencies, diff --git a/src/Microsoft.Extensions.ProjectModel/Resolution/LibraryManager.cs b/src/Microsoft.Extensions.ProjectModel/Resolution/LibraryManager.cs index 985095661..7fa1f7aa6 100644 --- a/src/Microsoft.Extensions.ProjectModel/Resolution/LibraryManager.cs +++ b/src/Microsoft.Extensions.ProjectModel/Resolution/LibraryManager.cs @@ -1,9 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using System.IO; -using NuGet.Frameworks; +using System.Linq; +using Microsoft.Extensions.ProjectModel.Graph; using NuGet.Versioning; namespace Microsoft.Extensions.ProjectModel.Resolution @@ -12,13 +14,10 @@ namespace Microsoft.Extensions.ProjectModel.Resolution { private readonly IList _libraries; private readonly IList _diagnostics; - private readonly string _projectPath; - public LibraryManager(string projectPath, - IList libraries, + public LibraryManager(IList libraries, IList diagnostics) { - _projectPath = projectPath; _libraries = libraries; _diagnostics = diagnostics; } @@ -39,72 +38,110 @@ namespace Microsoft.Extensions.ProjectModel.Resolution foreach (var library in GetLibraries()) { - string projectPath = library.RequestedRange.SourceFilePath ?? _projectPath; - if (!library.Resolved) { string message; string errorCode; if (library.Compatible) { - errorCode = ErrorCodes.NU1001; - message = $"The dependency {library.RequestedRange.Name} {library.RequestedRange.VersionRange} could not be resolved."; + foreach (var range in library.RequestedRanges) + { + errorCode = ErrorCodes.NU1001; + message = $"The dependency {range.Name} {range.VersionRange} could not be resolved."; + + AddDiagnostics(messages, library, message, errorCode); + } } else { errorCode = ErrorCodes.NU1002; - var projectName = Directory.GetParent(_projectPath).Name; - message = $"The dependency {library.Identity} in project {projectName} does not support framework {library.Framework}."; - } + message = $"The dependency {library.Identity} does not support framework {library.Framework}."; - messages.Add( - new DiagnosticMessage( - errorCode, - message, - projectPath, - DiagnosticMessageSeverity.Error, - library.RequestedRange.SourceLine, - library.RequestedRange.SourceColumn, - library)); + AddDiagnostics(messages, library, message, errorCode); + } } else { - // Skip libraries that aren't specified in a project.json - if (string.IsNullOrEmpty(library.RequestedRange.SourceFilePath)) + foreach (var range in library.RequestedRanges) { - continue; - } + // Skip libraries that aren't specified in a project.json + if (string.IsNullOrEmpty(range.SourceFilePath)) + { + continue; + } - if (library.RequestedRange.VersionRange == null) - { - // TODO: Show errors/warnings for things without versions - continue; - } + if (range.VersionRange == null) + { + // TODO: Show errors/warnings for things without versions + continue; + } - // If we ended up with a declared version that isn't what was asked for directly - // then report a warning - // Case 1: Non floating version and the minimum doesn't match what was specified - // Case 2: Floating version that fell outside of the range - if ((!library.RequestedRange.VersionRange.IsFloating && - library.RequestedRange.VersionRange.MinVersion != library.Identity.Version) || - (library.RequestedRange.VersionRange.IsFloating && - !library.RequestedRange.VersionRange.EqualsFloating(library.Identity.Version))) - { - var message = string.Format("Dependency specified was {0} but ended up with {1}.", library.RequestedRange, library.Identity); - messages.Add( - new DiagnosticMessage( - ErrorCodes.NU1007, - message, - projectPath, - DiagnosticMessageSeverity.Warning, - library.RequestedRange.SourceLine, - library.RequestedRange.SourceColumn, - library)); + // If we ended up with a declared version that isn't what was asked for directly + // then report a warning + // Case 1: Non floating version and the minimum doesn't match what was specified + // Case 2: Floating version that fell outside of the range + if ((!range.VersionRange.IsFloating && + range.VersionRange.MinVersion != library.Identity.Version) || + (range.VersionRange.IsFloating && + !range.VersionRange.Float.Satisfies(library.Identity.Version))) + { + var message = $"Dependency specified was {range} but ended up with {library.Identity}."; + + foreach (var source in GetRangesWithSourceLocations(library)) + { + messages.Add( + new DiagnosticMessage( + ErrorCodes.NU1007, + message, + source.SourceFilePath, + DiagnosticMessageSeverity.Warning, + source.SourceLine, + source.SourceColumn, + library)); + } + } } } } return messages; } + + private void AddDiagnostics(List messages, LibraryDescription library, string message, string errorCode) + { + // A (in project.json) -> B (unresolved) (not in project.json) + foreach (var source in GetRangesWithSourceLocations(library).Distinct()) + { + messages.Add( + new DiagnosticMessage( + errorCode, + message, + source.SourceFilePath, + DiagnosticMessageSeverity.Error, + source.SourceLine, + source.SourceColumn, + library)); + + } + } + + private IEnumerable GetRangesWithSourceLocations(LibraryDescription library) + { + foreach (var range in library.RequestedRanges) + { + if (!string.IsNullOrEmpty(range.SourceFilePath)) + { + yield return range; + } + } + + foreach (var parent in library.Parents) + { + foreach (var relevantPath in GetRangesWithSourceLocations(parent)) + { + yield return relevantPath; + } + } + } } } \ No newline at end of file diff --git a/src/Microsoft.Extensions.ProjectModel/Resolution/PackageDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel/Resolution/PackageDependencyProvider.cs index 2d41c6b1d..b2638c5cb 100644 --- a/src/Microsoft.Extensions.ProjectModel/Resolution/PackageDependencyProvider.cs +++ b/src/Microsoft.Extensions.ProjectModel/Resolution/PackageDependencyProvider.cs @@ -36,7 +36,6 @@ namespace Microsoft.Extensions.ProjectModel.Resolution var path = _packagePathResolver.GetInstallPath(package.Name, package.Version); var packageDescription = new PackageDescription( - new LibraryRange(package.Name, new VersionRange(package.Version), LibraryType.Package, LibraryDependencyType.Default), path, package, targetLibrary, diff --git a/src/Microsoft.Extensions.ProjectModel/Resolution/ReferenceAssemblyDependencyResolver.cs b/src/Microsoft.Extensions.ProjectModel/Resolution/ReferenceAssemblyDependencyResolver.cs index 25ea02c2a..ca7fd2f34 100644 --- a/src/Microsoft.Extensions.ProjectModel/Resolution/ReferenceAssemblyDependencyResolver.cs +++ b/src/Microsoft.Extensions.ProjectModel/Resolution/ReferenceAssemblyDependencyResolver.cs @@ -41,7 +41,6 @@ namespace Microsoft.Extensions.ProjectModel.Resolution if (version == null || version.Version == assemblyVersion) { return new LibraryDescription( - libraryRange, new LibraryIdentity(libraryRange.Name, new NuGetVersion(assemblyVersion), LibraryType.ReferenceAssembly), path, Enumerable.Empty(), diff --git a/src/Microsoft.Extensions.ProjectModel/Resolution/UnresolvedDependencyProvider.cs b/src/Microsoft.Extensions.ProjectModel/Resolution/UnresolvedDependencyProvider.cs index 7a9541083..5a9cbb1b5 100644 --- a/src/Microsoft.Extensions.ProjectModel/Resolution/UnresolvedDependencyProvider.cs +++ b/src/Microsoft.Extensions.ProjectModel/Resolution/UnresolvedDependencyProvider.cs @@ -12,7 +12,6 @@ namespace Microsoft.Extensions.ProjectModel.Resolution public static LibraryDescription GetDescription(LibraryRange libraryRange, NuGetFramework targetFramework) { return new LibraryDescription( - libraryRange, new LibraryIdentity(libraryRange.Name, libraryRange.VersionRange?.MinVersion, libraryRange.Target), path: null, dependencies: Enumerable.Empty(), diff --git a/src/Microsoft.Extensions.ProjectModel/Utilities/VersioningExtensions.cs b/src/Microsoft.Extensions.ProjectModel/Utilities/VersioningExtensions.cs deleted file mode 100644 index 7b91bcffd..000000000 --- a/src/Microsoft.Extensions.ProjectModel/Utilities/VersioningExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; - -namespace NuGet.Versioning -{ - public static class VersioningExtensions - { - public static bool EqualsFloating(this VersionRange self, NuGetVersion version) - { - if(!self.IsFloating) - { - return Equals(self.MinVersion, version); - } - - switch (self.Float.FloatBehavior) - { - case NuGetVersionFloatBehavior.Prerelease: - return self.MinVersion.Version == version.Version && - version.Release.StartsWith(self.MinVersion.Release, StringComparison.OrdinalIgnoreCase); - - case NuGetVersionFloatBehavior.Revision: - return self.MinVersion.Major == version.Major && - self.MinVersion.Minor == version.Minor && - self.MinVersion.Patch == version.Patch && - self.MinVersion.Revision == version.Revision; - - case NuGetVersionFloatBehavior.Patch: - return self.MinVersion.Major == version.Major && - self.MinVersion.Minor == version.Minor && - self.MinVersion.Patch == version.Patch; - - case NuGetVersionFloatBehavior.Minor: - return self.MinVersion.Major == version.Major && - self.MinVersion.Minor == version.Minor; - - case NuGetVersionFloatBehavior.Major: - return self.MinVersion.Major == version.Major; - - case NuGetVersionFloatBehavior.None: - return self.MinVersion == version; - default: - return false; - } - } - } -}