Merge pull request #6475 from wli3/replace-with-package-ref-for-migration2

Replace with p2p reference for ProjectJsonMigrate to package reference
This commit is contained in:
William Lee 2017-05-02 15:04:42 -07:00 committed by GitHub
commit f3a4b22457
248 changed files with 116 additions and 29633 deletions

View file

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26228.9
VisualStudioVersion = 15.0.26419.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED2FE3E2-F7E7-4389-8231-B65123F2076F}"
EndProject
@ -139,8 +139,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Configurer
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.InternalAbstractions", "src\Microsoft.DotNet.InternalAbstractions\Microsoft.DotNet.InternalAbstractions.csproj", "{570950AD-A080-4F32-980C-F50E312910DF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ProjectJsonMigration", "src\Microsoft.DotNet.ProjectJsonMigration\Microsoft.DotNet.ProjectJsonMigration.csproj", "{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.TestFramework", "src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.csproj", "{6592A22C-2386-4E83-A4D3-FC08075C723A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "redist", "src\redist\redist.csproj", "{098D9321-1201-4974-A75E-F58EBCD98ACF}"
@ -193,8 +191,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Cli.Utils.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Configurer.UnitTests", "test\Microsoft.DotNet.Configurer.UnitTests\Microsoft.DotNet.Configurer.UnitTests.csproj", "{F228580D-9373-4A60-AB88-76DF58D11580}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ProjectJsonMigration.Tests", "test\Microsoft.DotNet.ProjectJsonMigration.Tests\Microsoft.DotNet.ProjectJsonMigration.Tests.csproj", "{53F4CC00-72B3-4049-8888-FC05F622A9AC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.Tools.Tests.Utilities", "test\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Tests.Utilities.csproj", "{48E260F4-6F3F-4387-B61F-D15BABD06D9A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "msbuild.IntegrationTests", "test\msbuild.IntegrationTests\msbuild.IntegrationTests.csproj", "{23EE9BBB-3B33-4CF2-8D1A-29A8DB12E878}"
@ -655,30 +651,6 @@ Global
{570950AD-A080-4F32-980C-F50E312910DF}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{570950AD-A080-4F32-980C-F50E312910DF}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{570950AD-A080-4F32-980C-F50E312910DF}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Debug|x64.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Debug|x64.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Debug|x86.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Debug|x86.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.MinSizeRel|Any CPU.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.MinSizeRel|Any CPU.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.MinSizeRel|x64.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.MinSizeRel|x64.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.MinSizeRel|x86.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.MinSizeRel|x86.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Release|Any CPU.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Release|x64.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Release|x64.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Release|x86.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.Release|x86.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
{6592A22C-2386-4E83-A4D3-FC08075C723A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6592A22C-2386-4E83-A4D3-FC08075C723A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6592A22C-2386-4E83-A4D3-FC08075C723A}.Debug|x64.ActiveCfg = Release|Any CPU
@ -1303,30 +1275,6 @@ Global
{F228580D-9373-4A60-AB88-76DF58D11580}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{F228580D-9373-4A60-AB88-76DF58D11580}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{F228580D-9373-4A60-AB88-76DF58D11580}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Debug|x64.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Debug|x64.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Debug|x86.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Debug|x86.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.MinSizeRel|Any CPU.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.MinSizeRel|Any CPU.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.MinSizeRel|x64.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.MinSizeRel|x64.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.MinSizeRel|x86.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.MinSizeRel|x86.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Release|Any CPU.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Release|x64.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Release|x64.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Release|x86.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.Release|x86.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{53F4CC00-72B3-4049-8888-FC05F622A9AC}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
{48E260F4-6F3F-4387-B61F-D15BABD06D9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48E260F4-6F3F-4387-B61F-D15BABD06D9A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48E260F4-6F3F-4387-B61F-D15BABD06D9A}.Debug|x64.ActiveCfg = Release|Any CPU
@ -1669,7 +1617,6 @@ Global
{73ACEB34-D22C-43EA-87BE-EFC0E83D0126} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{ABB81DAE-0D26-483C-BE3B-0F9ACD812A62} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{570950AD-A080-4F32-980C-F50E312910DF} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{A8E6EFEB-027A-4C4B-A73C-C193A0F00569} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{6592A22C-2386-4E83-A4D3-FC08075C723A} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{098D9321-1201-4974-A75E-F58EBCD98ACF} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{A0670C63-BA7A-4C1B-B9A7-1CA26A7F235C} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
@ -1695,7 +1642,6 @@ Global
{7F115EF9-1827-4175-B50E-F214A490093E} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{FC9A1FF2-86AC-4DBE-B045-1A8EE6E9B3F3} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{F228580D-9373-4A60-AB88-76DF58D11580} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{53F4CC00-72B3-4049-8888-FC05F622A9AC} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{48E260F4-6F3F-4387-B61F-D15BABD06D9A} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{23EE9BBB-3B33-4CF2-8D1A-29A8DB12E878} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
{F5E27BA5-063B-4770-A6E8-87252E9AB22C} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}

View file

@ -17,6 +17,7 @@
<PlatformAbstractionsVersion>2.0.0-preview2-002093</PlatformAbstractionsVersion>
<DependencyModelVersion>2.0.0-preview2-002093</DependencyModelVersion>
<CliCommandLineParserVersion>0.1.0-alpha-142</CliCommandLineParserVersion>
<CliMigrateVersion>1.2.1-alpha-002130</CliMigrateVersion>
</PropertyGroup>

View file

@ -1,19 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.ProjectJsonMigration
{
internal class ConstantPackageVersions
{
public const string AspNetToolsVersion = "1.0.0";
public const string AspNet110ToolsVersion = "1.1.0";
public const string AspNetLTSPackagesVersion = "1.0.3";
public const string EntityFrameworkLTSPackagesVersion = "1.0.3";
public const string TestSdkPackageVersion = "15.0.0-preview-20170106-08";
public const string XUnitPackageVersion = "2.2.0-beta5-build3474";
public const string XUnitRunnerPackageVersion = "2.2.0-beta5-build1225";
public const string MstestTestAdapterVersion = "1.1.8-rc";
public const string MstestTestFrameworkVersion = "1.0.8-rc";
public const string BundleMinifierToolVersion = "2.2.301";
}
}

View file

@ -1,41 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.ProjectJsonMigration.Rules;
namespace Microsoft.DotNet.ProjectJsonMigration
{
internal class DefaultMigrationRuleSet : IMigrationRule
{
private IMigrationRule[] Rules => new IMigrationRule[]
{
new AddDefaultsToProjectRule(),
new MigrateRootOptionsRule(),
new MigrateTFMRule(),
new MigrateBuildOptionsRule(),
new MigrateJsonPropertiesRule(),
new MigratePackOptionsRule(),
new MigrateRuntimeOptionsRule(),
new MigrateRuntimesRule(),
new MigratePublishOptionsRule(),
new MigrateProjectDependenciesRule(),
new MigratePackageDependenciesAndToolsRule(),
new MigrateConfigurationsRule(),
new MigrateScriptsRule(),
new MigrateAssemblyInfoRule(),
new RemoveDefaultsFromProjectRule(),
new CleanOutputProjectRule(),
new SaveOutputProjectRule(),
new MigrateWebSdkRule()
};
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
foreach (var rule in Rules)
{
MigrationTrace.Instance.WriteLine(string.Format(LocalizableStrings.ExecutingMigrationRule, nameof(DefaultMigrationRuleSet), rule.GetType().Name));
rule.Apply(migrationSettings, migrationRuleInputs);
}
}
}
}

View file

@ -1,72 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
namespace Microsoft.DotNet.ProjectJsonMigration
{
internal class DotnetSupportedPackageVersionsCsvProvider : IDotnetSupportedPackageVersionsProvider
{
public void AddDotnetSupportedPackageVersions(
IDictionary<PackageDependencyInfo, PackageDependencyInfo> projectDependenciesPackages)
{
var dotnetSupportedPackageVersionsPath =
Path.Combine(AppContext.BaseDirectory, "dotnet-supported-package-versions.csv");
using (var reader = new StreamReader(File.OpenRead(dotnetSupportedPackageVersionsPath)))
{
SkipHeader(reader);
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
var packageName = values[0];
var ltsVersion = values[1];
var ftsVersion = values[2];
if (HasVersion(ltsVersion))
{
projectDependenciesPackages.Add(
new PackageDependencyInfo
{
Name = packageName,
Version = $"[,{ltsVersion})"
},
new PackageDependencyInfo
{
Name = packageName,
Version = ltsVersion
});
}
if(HasVersion(ftsVersion))
{
var version = HasVersion(ltsVersion) ? $"({ltsVersion},{ftsVersion})" : $"[,{ftsVersion})";
projectDependenciesPackages.Add(
new PackageDependencyInfo
{
Name = packageName,
Version = version
},
new PackageDependencyInfo
{
Name = packageName,
Version = ftsVersion
});
}
}
}
}
private void SkipHeader(StreamReader reader)
{
reader.ReadLine();
}
private bool HasVersion(string version)
{
return !string.IsNullOrEmpty(version);
}
}
}

View file

@ -1,13 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.DotNet.ProjectJsonMigration
{
internal interface IDotnetSupportedPackageVersionsProvider
{
void AddDotnetSupportedPackageVersions(
IDictionary<PackageDependencyInfo, PackageDependencyInfo> projectDependenciesPackages);
}
}

View file

@ -1,130 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.ProjectJsonMigration
{
internal class LocalizableStrings
{
public const string DoubleMigrationError = "Detected double project migration: {0}";
public const string CannotMergeMetadataError = "Cannot merge metadata with the same name and different values";
public const string NoXprojFileGivenError = "{0}: No xproj file given.";
public const string MultipleXprojFilesError = "Multiple xproj files found in {0}, please specify which to use";
public const string NullMSBuildProjectTemplateError = "Expected non-null MSBuildProjectTemplate in MigrationSettings";
public const string CannotMigrateProjectWithCompilerError = "Cannot migrate project {0} using compiler {1}";
public const string ExpectedElementToBeOfTypeNotTypeError = "Expected element to be of type {0}, but got {1}";
public const string ProjAlreadyExistsError = "{0} already exists. Has migration already been run?";
public const string NullDestinationElementError = "expected destinationElement to not be null";
public const string DiagnosticMessageTemplate = "{0} (line: {1}, file: {2})";
public const string CannotMergeItemsOfDifferentTypesError = "Cannot merge items of different types.";
public const string CannotMergeItemsWithoutCommonIncludeError = "Cannot merge items without a common include.";
public const string PropertyTransformApplicatorWrongElementTypeError = "Expected element to be of type {0}, but got {1}";
public const string UnexpectedTypeError = "Unexpected type {0}";
public const string MIGRATE1011 = "Deprecated Project";
public const string MIGRATE1012 = "Project not Restored";
public const string MIGRATE1013 = "No Project";
public const string MIGRATE1013Arg = "The project.json specifies no target frameworks in {0}";
public const string MIGRATE1014 = "Unresolved Dependency";
public const string MIGRATE1014Arg = "Unresolved project dependency ({0})";
public const string MIGRATE1015 = "File Overwrite";
public const string MIGRATE1016 = "Unsupported Script Variable";
public const string MIGRATE1016Arg = "{0} is currently an unsupported script variable for project migration";
public const string MIGRATE1017 = "Multiple Xproj Files";
public const string MIGRATE1018 = "Dependency Project not found";
public const string MIGRATE1018Arg = "Dependency project not found ({0})" ;
public const string MIGRATE1019 = "Unsupported Script Event Hook";
public const string MIGRATE1019Arg = "{0} is an unsupported script event hook for project migration";
public const string MIGRATE20011 = "Multi-TFM";
public const string MIGRATE20012 = "Configuration Exclude";
public const string MIGRATE20013 = "Non-Csharp App";
public const string MIGRATE20018 = "Files specified under PackOptions";
public const string IncludesNotEquivalent = "{0}.{1} includes not equivalent.";
public const string UpdatesNotEquivalent = "{0}.{1} updates not equivalent.";
public const string ExcludesNotEquivalent = "{0}.{1} excludes not equivalent.";
public const string RemovesNotEquivalent = "{0}.{1} removes not equivalent.";
public const string MetadataDoesntExist = "{0}.{1} metadata doesn't exist {{ {2} {3} }}";
public const string MetadataHasAnotherValue = "{0}.{1} metadata has another value {{ {2} {3} {4} }}";
public const string AddingMetadataToItem = "{0}: Adding metadata to {1} item: {{ {2}, {3}, {4} }}";
public const string SkipMigrationAlreadyMigrated = "{0}: Skip migrating {1}, it is already migrated.";
public const string ExecutingRule = "Executing rule: {0}";
public const string NoConfigurationOrFrameworkFoundInProject = "{0}: No configuration or framework build options found in project";
public const string MigratingCountTargetFrameworks = "Migrating {0} target frameworks";
public const string MigratingFramework = "Migrating framework {0}";
public const string ImportsTransformNullFor = "{0}: imports transform null for {1}";
public const string MigratingCountXprojToCsprojReferences = "{0}: Migrating {1} xproj to csproj references";
public const string ExecutingMigrationRule = "{0}: Executing migration rule {1}";
public const string ItemTransformApplicatorHeader = "{0}: Item {{ ItemType: {1}, Condition: {2}, Include: {3}, Exclude: {4}, Update: {5} }}";
public const string ItemTransformApplicatorItemGroup = "{0}: ItemGroup {{ Condition: {1} }}";
public const string ItemTransformAppliatorItemCompletelyMerged = "{0}: Item completely merged";
public const string ItemTransformApplicatorAddItemHeader = "{0}: AddItemToItemGroup {{ ItemType: {1}, Condition: {2}, Include: {3}, Exclude: {4}, Update: {5} }}";
public const string ItemTransformApplicatorMergingItemWithExistingItems = "{0}: Merging Item with {1} existing items with a different condition chain.";
public const string ItemTransformApplicatorEncompassedIncludes = "{0}: encompassed includes {1}";
public const string ItemTransformApplicatorEncompassedUpdates = "{0}: encompassed updates {1}";
public const string ItemTransformApplicatorRemovingItem = "{0}: Removing Item {{ ItemType: {1}, Condition: {2}, Include: {3}, Exclude: {4} }}";
public const string ItemTransformApplicatorIgnoringItem = "{0}: Ignoring Item {{ ItemType: {1}, Condition: {2}, Include: {3}, Exclude: {4} }}";
public const string ItemTransformApplicatorMergingItemWithExistingItemsSameChain = "{0}: Merging Item with {1} existing items with the same condition chain.";
public const string ItemTransformApplicatorAddingMergedItem = "{0}: Adding Merged Item {{ ItemType: {1}, Condition: {2}, Include: {3}, Exclude: {4} }}";
public const string MergingProperty = "Merging property, output merged property";
public const string IgnoringMergedProperty = "Ignoring fully merged property";
public const string PropertyInfo = "{0}: {1}, {{ Name={2}, Value={3} }}";
}
}

View file

@ -1,259 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Construction;
namespace Microsoft.DotNet.ProjectJsonMigration
{
public static class MSBuildExtensions
{
public static IEnumerable<string> GetEncompassedIncludes(this ProjectItemElement item,
ProjectItemElement otherItem, TextWriter trace = null)
{
if (otherItem.IsEquivalentToExceptIncludeUpdateAndExclude(item, trace) &&
new HashSet<string>(otherItem.Excludes()).IsSubsetOf(new HashSet<string>(item.Excludes())))
{
return otherItem.IntersectIncludes(item);
}
return Enumerable.Empty<string>();
}
public static IEnumerable<string> GetEncompassedUpdates(this ProjectItemElement item,
ProjectItemElement otherItem, TextWriter trace = null)
{
if (otherItem.IsEquivalentToExceptIncludeUpdateAndExclude(item, trace) &&
new HashSet<string>(otherItem.Excludes()).IsSubsetOf(new HashSet<string>(item.Excludes())))
{
return otherItem.IntersectUpdates(item);
}
return Enumerable.Empty<string>();
}
public static bool IsEquivalentTo(this ProjectItemElement item, ProjectItemElement otherItem, TextWriter trace = null)
{
// Different includes
if (item.IntersectIncludes(otherItem).Count() != item.Includes().Count())
{
trace?.WriteLine(String.Format(LocalizableStrings.IncludesNotEquivalent, nameof(MSBuildExtensions), nameof(IsEquivalentTo)));
return false;
}
if (item.IntersectUpdates(otherItem).Count() != item.Updates().Count())
{
trace?.WriteLine(String.Format(LocalizableStrings.UpdatesNotEquivalent, nameof(MSBuildExtensions), nameof(IsEquivalentTo)));
return false;
}
// Different Excludes
if (item.IntersectExcludes(otherItem).Count() != item.Excludes().Count())
{
trace?.WriteLine(String.Format(LocalizableStrings.ExcludesNotEquivalent, nameof(MSBuildExtensions), nameof(IsEquivalentTo)));
return false;
}
return item.IsEquivalentToExceptIncludeUpdateAndExclude(otherItem, trace);
}
public static bool IsEquivalentToExceptIncludeUpdateAndExclude(this ProjectItemElement item, ProjectItemElement otherItem, TextWriter trace = null)
{
// Different remove
if (item.Remove != otherItem.Remove)
{
trace?.WriteLine(String.Format(LocalizableStrings.RemovesNotEquivalent, nameof(MSBuildExtensions), nameof(IsEquivalentTo)));
return false;
}
// Different Metadata
var metadataTuples = otherItem.Metadata.Select(m => Tuple.Create(m, item)).Concat(
item.Metadata.Select(m => Tuple.Create(m, otherItem)));
foreach (var metadataTuple in metadataTuples)
{
var metadata = metadataTuple.Item1;
var itemToCompare = metadataTuple.Item2;
var otherMetadata = itemToCompare.GetMetadataWithName(metadata.Name);
if (otherMetadata == null)
{
trace?.WriteLine(String.Format(LocalizableStrings.MetadataDoesntExist, nameof(MSBuildExtensions), nameof(IsEquivalentTo), metadata.Name, metadata.Value));
return false;
}
if (!metadata.ValueEquals(otherMetadata))
{
trace?.WriteLine(String.Format(LocalizableStrings.MetadataHasAnotherValue, nameof(MSBuildExtensions), nameof(IsEquivalentTo), metadata.Name, metadata.Value, otherMetadata.Value));
return false;
}
}
return true;
}
public static ISet<string> ConditionChain(this ProjectElement projectElement)
{
var conditionChainSet = new HashSet<string>();
if (!string.IsNullOrEmpty(projectElement.Condition))
{
conditionChainSet.Add(projectElement.Condition);
}
foreach (var parent in projectElement.AllParents)
{
if (!string.IsNullOrEmpty(parent.Condition))
{
conditionChainSet.Add(parent.Condition);
}
}
return conditionChainSet;
}
public static bool ConditionChainsAreEquivalent(this ProjectElement projectElement, ProjectElement otherProjectElement)
{
return projectElement.ConditionChain().SetEquals(otherProjectElement.ConditionChain());
}
public static IEnumerable<ProjectPropertyElement> PropertiesWithoutConditions(
this ProjectRootElement projectRoot)
{
return ElementsWithoutConditions(projectRoot.Properties);
}
public static IEnumerable<ProjectItemElement> ItemsWithoutConditions(
this ProjectRootElement projectRoot)
{
return ElementsWithoutConditions(projectRoot.Items);
}
public static IEnumerable<string> Includes(
this ProjectItemElement item)
{
return SplitSemicolonDelimitedValues(item.Include);
}
public static IEnumerable<string> Updates(
this ProjectItemElement item)
{
return SplitSemicolonDelimitedValues(item.Update);
}
public static IEnumerable<string> Excludes(
this ProjectItemElement item)
{
return SplitSemicolonDelimitedValues(item.Exclude);
}
public static IEnumerable<string> Removes(
this ProjectItemElement item)
{
return SplitSemicolonDelimitedValues(item.Remove);
}
public static IEnumerable<string> AllConditions(this ProjectElement projectElement)
{
return new string[] { projectElement.Condition }.Concat(projectElement.AllParents.Select(p=> p.Condition));
}
public static IEnumerable<string> IntersectIncludes(this ProjectItemElement item, ProjectItemElement otherItem)
{
return item.Includes().Intersect(otherItem.Includes());
}
public static IEnumerable<string> IntersectUpdates(this ProjectItemElement item, ProjectItemElement otherItem)
{
return item.Updates().Intersect(otherItem.Updates());
}
public static IEnumerable<string> IntersectExcludes(this ProjectItemElement item, ProjectItemElement otherItem)
{
return item.Excludes().Intersect(otherItem.Excludes());
}
public static void RemoveIncludes(this ProjectItemElement item, IEnumerable<string> includesToRemove)
{
item.Include = string.Join(";", item.Includes().Except(includesToRemove));
}
public static void RemoveUpdates(this ProjectItemElement item, IEnumerable<string> updatesToRemove)
{
item.Update = string.Join(";", item.Updates().Except(updatesToRemove));
}
public static void UnionIncludes(this ProjectItemElement item, IEnumerable<string> includesToAdd)
{
item.Include = string.Join(";", item.Includes().Union(includesToAdd));
}
public static void UnionExcludes(this ProjectItemElement item, IEnumerable<string> excludesToAdd)
{
item.Exclude = string.Join(";", item.Excludes().Union(excludesToAdd));
}
public static bool ValueEquals(this ProjectMetadataElement metadata, ProjectMetadataElement otherMetadata)
{
return metadata.Value.Equals(otherMetadata.Value, StringComparison.Ordinal);
}
public static void AddMetadata(this ProjectItemElement item, ICollection<ProjectMetadataElement> metadataElements, TextWriter trace = null)
{
foreach (var metadata in metadataElements)
{
item.AddMetadata(metadata, trace);
}
}
public static void RemoveIfEmpty(this ProjectElementContainer container)
{
if (!container.Children.Any())
{
container.Parent.RemoveChild(container);
}
}
public static ProjectMetadataElement GetMetadataWithName(this ProjectItemElement item, string name)
{
return item.Metadata.FirstOrDefault(m => m.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
}
public static void AddMetadata(this ProjectItemElement item, ProjectMetadataElement metadata, TextWriter trace = null)
{
var existingMetadata = item.GetMetadataWithName(metadata.Name);
if (existingMetadata != default(ProjectMetadataElement) && !existingMetadata.ValueEquals(metadata))
{
throw new Exception(LocalizableStrings.CannotMergeMetadataError);
}
if (existingMetadata == default(ProjectMetadataElement))
{
trace?.WriteLine(String.Format(LocalizableStrings.AddingMetadataToItem, nameof(AddMetadata), item.ItemType, metadata.Name, metadata.Value, metadata.Condition));
var metametadata = item.AddMetadata(metadata.Name, metadata.Value);
metametadata.Condition = metadata.Condition;
metametadata.ExpressedAsAttribute = metadata.ExpressedAsAttribute;
}
}
public static void SetExcludeOnlyIfIncludeIsSet(this ProjectItemElement item, string exclude)
{
item.Exclude = string.IsNullOrEmpty(item.Include) ? string.Empty : exclude;
}
private static IEnumerable<string> SplitSemicolonDelimitedValues(string combinedValue)
{
return string.IsNullOrEmpty(combinedValue) ? Enumerable.Empty<string>() : combinedValue.Split(';');
}
private static IEnumerable<T> ElementsWithoutConditions<T>(IEnumerable<T> elements) where T : ProjectElement
{
return elements
.Where(e => string.IsNullOrEmpty(e.Condition)
&& e.AllParents.All(parent => string.IsNullOrEmpty(parent.Condition)));
}
}
}

View file

@ -1,57 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class AnalyzerOptions : IEquatable<AnalyzerOptions>
{
/// <summary>
/// The identifier indicating the project language as defined by NuGet.
/// </summary>
/// <remarks>
/// See https://docs.nuget.org/create/analyzers-conventions for valid values
/// </remarks>
public string LanguageId { get; }
public AnalyzerOptions(string languageId = null)
{
LanguageId = languageId;
}
public bool Equals(AnalyzerOptions other)
{
return !ReferenceEquals(other, null) && other.LanguageId == LanguageId;
}
public override bool Equals(object obj)
{
return Equals(obj as AnalyzerOptions);
}
public override int GetHashCode()
{
return LanguageId?.GetHashCode() ?? 0;
}
public static bool operator ==(AnalyzerOptions left, AnalyzerOptions right)
{
if (ReferenceEquals(left, right))
{
return true;
}
if (ReferenceEquals(left, null))
{
return false;
}
return left.Equals(right);
}
public static bool operator !=(AnalyzerOptions left, AnalyzerOptions right)
{
return !(left == right);
}
}
}

View file

@ -1,81 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class BuildWorkspace : Workspace
{
public BuildWorkspace(ProjectReaderSettings settings) : base(settings, false) { }
/// <summary>
/// Create an empty <see cref="WorkspaceContext" /> using the default <see cref="ProjectReaderSettings" />
/// </summary>
/// <returns></returns>
public static BuildWorkspace Create() => Create(versionSuffix: string.Empty);
/// <summary>
/// Create an empty <see cref="WorkspaceContext" /> using the default <see cref="ProjectReaderSettings" />, with the specified Version Suffix
/// </summary>
/// <param name="versionSuffix">The suffix to use to replace any '-*' snapshot tokens in Project versions.</param>
/// <returns></returns>
public static BuildWorkspace Create(string versionSuffix)
{
var settings = ProjectReaderSettings.ReadFromEnvironment();
if (!string.IsNullOrEmpty(versionSuffix))
{
settings.VersionSuffix = versionSuffix;
}
return new BuildWorkspace(settings);
}
public ProjectContext GetRuntimeContext(ProjectContext context, IEnumerable<string> runtimeIdentifiers)
{
if (!runtimeIdentifiers.Any())
{
return context;
}
var contexts = GetProjectContextCollection(context.ProjectDirectory);
if (contexts == null)
{
return null;
}
var runtimeContext = runtimeIdentifiers
.Select(r => contexts.GetTarget(context.TargetFramework, r))
.FirstOrDefault(c => c != null);
if (runtimeContext == null)
{
if (context.IsPortable)
{
// We're specializing a portable target, so synthesize a runtime target manually
// We don't cache this project context, but we'll still use the cached Project and LockFile
return CreateBaseProjectBuilder(context.ProjectFile)
.WithTargetFramework(context.TargetFramework)
.WithRuntimeIdentifiers(runtimeIdentifiers)
.Build();
}
// We are standalone, but don't support this runtime
var rids = string.Join(", ", runtimeIdentifiers);
throw new InvalidOperationException($"Can not find runtime target for framework '{context.TargetFramework}' compatible with one of the target runtimes: '{rids}'. " +
"Possible causes:" + Environment.NewLine +
"1. The project has not been restored or restore failed - run `dotnet restore`" + Environment.NewLine +
$"2. The project does not list one of '{rids}' in the 'runtimes' section." + Environment.NewLine +
"3. You may be trying to publish a library, which is not supported. Use `dotnet pack` to distribute libraries.");
}
return runtimeContext;
}
protected override IEnumerable<ProjectContext> BuildProjectContexts(Project project)
{
return CreateBaseProjectBuilder(project).BuildAllTargets();
}
}
}

View file

@ -1,212 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.Files;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class CommonCompilerOptions
{
public IEnumerable<string> Defines { get; set; }
public string LanguageVersion { get; set; }
public string Platform { get; set; }
public bool? AllowUnsafe { get; set; }
public bool? WarningsAsErrors { get; set; }
public bool? Optimize { get; set; }
public string KeyFile { get; set; }
public bool? DelaySign { get; set; }
public bool? PublicSign { get; set; }
public string DebugType { get; set; }
public bool? EmitEntryPoint { get; set; }
public bool? PreserveCompilationContext { get; set; }
public bool? GenerateXmlDocumentation { get; set; }
public IEnumerable<string> SuppressWarnings { get; set; }
public IEnumerable<string> AdditionalArguments { get; set; }
public string OutputName { get; set; }
public string CompilerName { get; set; }
public IncludeContext CompileInclude { get; set; }
public IncludeContext EmbedInclude { get; set; }
public IncludeContext CopyToOutputInclude { get; set; }
public override bool Equals(object obj)
{
var other = obj as CommonCompilerOptions;
return other != null &&
LanguageVersion == other.LanguageVersion &&
Platform == other.Platform &&
AllowUnsafe == other.AllowUnsafe &&
WarningsAsErrors == other.WarningsAsErrors &&
Optimize == other.Optimize &&
KeyFile == other.KeyFile &&
DelaySign == other.DelaySign &&
PublicSign == other.PublicSign &&
DebugType == other.DebugType &&
EmitEntryPoint == other.EmitEntryPoint &&
GenerateXmlDocumentation == other.GenerateXmlDocumentation &&
PreserveCompilationContext == other.PreserveCompilationContext &&
EnumerableEquals(Defines, other.Defines) &&
EnumerableEquals(SuppressWarnings, other.SuppressWarnings) &&
EnumerableEquals(AdditionalArguments, other.AdditionalArguments) &&
OutputName == other.OutputName &&
CompilerName == other.CompilerName &&
IsEqual(CompileInclude, other.CompileInclude) &&
IsEqual(EmbedInclude, other.EmbedInclude) &&
IsEqual(CopyToOutputInclude, other.CopyToOutputInclude);
}
private static bool IsEqual(IncludeContext first, IncludeContext second)
{
if (first == null || second == null)
{
return first == second;
}
return first.Equals(second);
}
private static bool EnumerableEquals(IEnumerable<string> left, IEnumerable<string> right)
=> Enumerable.SequenceEqual(left ?? EmptyArray<string>.Value, right ?? EmptyArray<string>.Value);
public override int GetHashCode()
{
return base.GetHashCode();
}
private static IEnumerable<string> Combine(IEnumerable<string> @new, IEnumerable<string> old)
{
if (@new != null)
{
old = old ?? EmptyArray<string>.Value;
return old.Concat(@new).Distinct().ToArray();
}
return old;
}
public static CommonCompilerOptions Combine(params CommonCompilerOptions[] options)
{
var result = new CommonCompilerOptions();
foreach (var option in options)
{
// Skip null options
if (option == null)
{
continue;
}
// Defines, suppressions, and additional arguments are always combined
result.Defines = Combine(option.Defines, result.Defines);
result.SuppressWarnings = Combine(option.SuppressWarnings, result.SuppressWarnings);
result.AdditionalArguments = Combine(option.AdditionalArguments, result.AdditionalArguments);
if (option.LanguageVersion != null)
{
result.LanguageVersion = option.LanguageVersion;
}
if (option.Platform != null)
{
result.Platform = option.Platform;
}
if (option.AllowUnsafe != null)
{
result.AllowUnsafe = option.AllowUnsafe;
}
if (option.WarningsAsErrors != null)
{
result.WarningsAsErrors = option.WarningsAsErrors;
}
if (option.Optimize != null)
{
result.Optimize = option.Optimize;
}
if (option.KeyFile != null)
{
result.KeyFile = option.KeyFile;
}
if (option.DelaySign != null)
{
result.DelaySign = option.DelaySign;
}
if (option.PublicSign != null)
{
result.PublicSign = option.PublicSign;
}
if (option.DebugType != null)
{
result.DebugType = option.DebugType;
}
if (option.EmitEntryPoint != null)
{
result.EmitEntryPoint = option.EmitEntryPoint;
}
if (option.PreserveCompilationContext != null)
{
result.PreserveCompilationContext = option.PreserveCompilationContext;
}
if (option.GenerateXmlDocumentation != null)
{
result.GenerateXmlDocumentation = option.GenerateXmlDocumentation;
}
if (option.OutputName != null)
{
result.OutputName = option.OutputName;
}
if (option.CompileInclude != null)
{
result.CompileInclude = option.CompileInclude;
}
if (option.EmbedInclude != null)
{
result.EmbedInclude = option.EmbedInclude;
}
if (option.CopyToOutputInclude != null)
{
result.CopyToOutputInclude = option.CopyToOutputInclude;
}
// compilerName set in the root cannot be overriden.
if (result.CompilerName == null)
{
result.CompilerName = option.CompilerName;
}
}
return result;
}
}
}

View file

@ -1,42 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using NuGet.Frameworks;
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation
{
internal class AnalyzerReference
{
/// <summary>
/// The fully-qualified path to the analyzer assembly.
/// </summary>
public string AssemblyPath { get; }
/// <summary>
/// The supported language of the analyzer assembly.
/// </summary>
public string AnalyzerLanguage { get; }
/// <summary>
/// The required framework for hosting the analyzer assembly.
/// </summary>
public NuGetFramework RequiredFramework { get; }
/// <summary>
/// The required runtime for hosting the analyzer assembly.
/// </summary>
public string RuntimeIdentifier { get; }
public AnalyzerReference(
string assembly,
NuGetFramework framework,
string language,
string runtimeIdentifier)
{
AnalyzerLanguage = language;
AssemblyPath = assembly;
RequiredFramework = framework;
RuntimeIdentifier = runtimeIdentifier;
}
}
}

View file

@ -1,71 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.DotNet.Internal.ProjectModel.Utilities;
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation
{
public struct LibraryAsset
{
public string Name { get; }
public string RelativePath { get; }
public string ResolvedPath { get; }
public string FileName => Path.GetFileName(RelativePath);
public Action<Stream, Stream> Transform { get; set; }
public LibraryAsset(string name, string relativePath, string resolvedPath, Action<Stream, Stream> transform = null)
{
Name = name;
RelativePath = relativePath;
ResolvedPath = resolvedPath;
Transform = transform;
}
public bool Equals(LibraryAsset other)
{
return string.Equals(Name, other.Name)
&& string.Equals(RelativePath, other.RelativePath)
&& string.Equals(ResolvedPath, other.ResolvedPath);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is LibraryAsset && Equals((LibraryAsset) obj);
}
public override int GetHashCode()
{
var combiner = HashCodeCombiner.Start();
combiner.Add(Name);
combiner.Add(RelativePath);
combiner.Add(ResolvedPath);
return combiner.CombinedHash;
}
public static LibraryAsset CreateFromRelativePath(string basePath, string relativePath, Action<Stream, Stream> transform = null)
{
return new LibraryAsset(
Path.GetFileNameWithoutExtension(relativePath),
relativePath,
Path.Combine(basePath, relativePath),
transform);
}
public static LibraryAsset CreateFromAbsolutePath(string basePath, string absolutePath, Action<Stream, Stream> transform = null)
{
var relativePath = absolutePath.Replace(PathUtility.EnsureTrailingSlash(basePath), string.Empty);
return new LibraryAsset(
Path.GetFileNameWithoutExtension(relativePath),
relativePath,
absolutePath,
transform);
}
}
}

View file

@ -1,59 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Reflection;
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation
{
internal static class LibraryAssetExtensions
{
private const string NativeImageSufix = ".ni";
public static AssemblyName GetAssemblyName(this LibraryAsset asset)
{
var name = asset.Name;
if (asset.Name.EndsWith(NativeImageSufix))
{
name = name.Substring(0, name.Length - NativeImageSufix.Length);
}
return new AssemblyName(name);
}
public static string GetTransformedFile(this LibraryAsset asset, string tempLocation, string tempName = null)
{
if (asset.Transform == null)
{
return asset.ResolvedPath;
}
tempName = tempName ?? Path.GetFileName(asset.RelativePath);
using (var input = File.OpenRead(asset.ResolvedPath))
{
var transformedName = Path.Combine(tempLocation, tempName);
using (var output = File.OpenWrite(transformedName))
{
asset.Transform(input, output);
}
return transformedName;
}
}
public static Stream GetTransformedStream(this LibraryAsset asset)
{
if (asset.Transform == null)
{
return File.OpenRead(asset.ResolvedPath);
}
using (var input = File.OpenRead(asset.ResolvedPath))
{
var output = new MemoryStream();
asset.Transform(input, output);
return output;
}
}
}
}

View file

@ -1,29 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Linq;
using System.Collections.Generic;
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation
{
internal class LibraryAssetGroup
{
public LibraryAssetGroup(string runtime, params LibraryAsset[] assets) : this(runtime, (IEnumerable<LibraryAsset>)assets) { }
public LibraryAssetGroup(params LibraryAsset[] assets) : this(string.Empty, (IEnumerable<LibraryAsset>)assets) { }
public LibraryAssetGroup(IEnumerable<LibraryAsset> assets) : this(string.Empty, assets) { }
public LibraryAssetGroup(string runtime,
IEnumerable<LibraryAsset> assets)
{
Runtime = runtime;
Assets = assets.ToArray();
}
public string Runtime { get; }
/// <summary>
/// Gets a list of assets provided in this runtime group
/// </summary>
public IReadOnlyList<LibraryAsset> Assets { get; }
}
}

View file

@ -1,80 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Diagnostics;
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
internal class LibraryExport
{
/// <summary>
/// Gets the library that produced this export
/// </summary>
public LibraryDescription Library { get; }
/// <summary>
/// Gets a list of MSIL binaries required to run
/// </summary>
public IEnumerable<LibraryAssetGroup> RuntimeAssemblyGroups { get; }
/// <summary>
/// Non assembly runtime assets.
/// </summary>
public IEnumerable<LibraryAsset> RuntimeAssets { get; }
/// <summary>
/// Gets a list of native binaries required to run
/// </summary>
public IEnumerable<LibraryAssetGroup> NativeLibraryGroups { get; }
/// <summary>
/// Gets a list of fully-qualified paths to MSIL metadata references
/// </summary>
public IEnumerable<LibraryAsset> CompilationAssemblies { get; }
/// <summary>
/// Get a list of embedded resource files provided by this export.
/// </summary>
public IEnumerable<LibraryAsset> EmbeddedResources { get; }
/// <summary>
/// Gets a list of fully-qualified paths to source code file references
/// </summary>
public IEnumerable<LibraryAsset> SourceReferences { get; }
/// <summary>
/// Get a list of analyzers provided by this export.
/// </summary>
public IEnumerable<AnalyzerReference> AnalyzerReferences { get; }
/// <summary>
/// Get a list of resource assemblies provided by this export.
/// </summary>
public IEnumerable<LibraryResourceAssembly> ResourceAssemblies { get; }
public LibraryExport(LibraryDescription library,
IEnumerable<LibraryAsset> compileAssemblies,
IEnumerable<LibraryAsset> sourceReferences,
IEnumerable<LibraryAssetGroup> runtimeAssemblyGroups,
IEnumerable<LibraryAsset> runtimeAssets,
IEnumerable<LibraryAssetGroup> nativeLibraryGroups,
IEnumerable<LibraryAsset> embeddedResources,
IEnumerable<AnalyzerReference> analyzers,
IEnumerable<LibraryResourceAssembly> resourceAssemblies)
{
Library = library;
CompilationAssemblies = compileAssemblies;
SourceReferences = sourceReferences;
RuntimeAssemblyGroups = runtimeAssemblyGroups;
RuntimeAssets = runtimeAssets;
NativeLibraryGroups = nativeLibraryGroups;
EmbeddedResources = embeddedResources;
AnalyzerReferences = analyzers;
ResourceAssemblies = resourceAssemblies;
}
private string DebuggerDisplay => Library.Identity.ToString();
}
}

View file

@ -1,191 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation
{
internal class LibraryExportBuilder
{
private IList<LibraryAssetGroup> _runtimeAssemblyGroups;
private IList<LibraryAsset> _runtimeAssets;
private IList<LibraryAsset> _compilationAssemblies;
private IList<LibraryAsset> _sourceReferences;
private IList<LibraryAssetGroup> _nativeLibraryGroups;
private IList<LibraryAsset> _embeddedResources;
private IList<AnalyzerReference> _analyzerReferences;
private IList<LibraryResourceAssembly> _resourceAssemblies;
public LibraryDescription Library { get; set; }
public IEnumerable<LibraryAssetGroup> RuntimeAssemblyGroups => _runtimeAssemblyGroups;
public IEnumerable<LibraryAsset> RuntimeAssets => _runtimeAssets;
public IEnumerable<LibraryAsset> CompilationAssemblies => _compilationAssemblies;
public IEnumerable<LibraryAsset> SourceReferences => _sourceReferences;
public IEnumerable<LibraryAssetGroup> NativeLibraryGroups => _nativeLibraryGroups;
public IEnumerable<LibraryAsset> EmbeddedResources => _embeddedResources;
public IEnumerable<AnalyzerReference> AnalyzerReferences => _analyzerReferences;
public IEnumerable<LibraryResourceAssembly> ResourceAssemblies => _resourceAssemblies;
public static LibraryExportBuilder Create(LibraryDescription library = null)
{
return new LibraryExportBuilder().WithLibrary(library);
}
public LibraryExport Build()
{
if (Library == null)
{
throw new InvalidOperationException("Cannot build LibraryExport withoud Library set");
}
return new LibraryExport(
Library,
CompilationAssemblies ?? EmptyArray<LibraryAsset>.Value,
SourceReferences ?? EmptyArray<LibraryAsset>.Value,
RuntimeAssemblyGroups ?? EmptyArray<LibraryAssetGroup>.Value,
RuntimeAssets ?? EmptyArray<LibraryAsset>.Value,
NativeLibraryGroups ?? EmptyArray<LibraryAssetGroup>.Value,
EmbeddedResources ?? EmptyArray<LibraryAsset>.Value,
AnalyzerReferences ?? EmptyArray<AnalyzerReference>.Value,
ResourceAssemblies ?? EmptyArray<LibraryResourceAssembly>.Value);
}
public LibraryExportBuilder WithLibrary(LibraryDescription libraryDescription)
{
Library = libraryDescription;
return this;
}
public LibraryExportBuilder WithRuntimeAssemblyGroups(IEnumerable<LibraryAssetGroup> assets)
{
Replace(ref _runtimeAssemblyGroups, assets);
return this;
}
public LibraryExportBuilder WithRuntimeAssets(IEnumerable<LibraryAsset> assets)
{
Replace(ref _runtimeAssets, assets);
return this;
}
public LibraryExportBuilder WithCompilationAssemblies(IEnumerable<LibraryAsset> assets)
{
Replace(ref _compilationAssemblies, assets);
return this;
}
public LibraryExportBuilder WithSourceReferences(IEnumerable<LibraryAsset> assets)
{
Replace(ref _sourceReferences, assets);
return this;
}
public LibraryExportBuilder WithNativeLibraryGroups(IEnumerable<LibraryAssetGroup> assets)
{
Replace(ref _nativeLibraryGroups, assets);
return this;
}
public LibraryExportBuilder WithEmbedddedResources(IEnumerable<LibraryAsset> assets)
{
Replace(ref _embeddedResources, assets);
return this;
}
public LibraryExportBuilder WithAnalyzerReference(IEnumerable<AnalyzerReference> assets)
{
Replace(ref _analyzerReferences, assets);
return this;
}
public LibraryExportBuilder WithResourceAssemblies(IEnumerable<LibraryResourceAssembly> assemblies)
{
Replace(ref _resourceAssemblies, assemblies);
return this;
}
public LibraryExportBuilder AddRuntimeAssemblyGroup(LibraryAssetGroup asset)
{
Add(ref _runtimeAssemblyGroups, asset);
return this;
}
public LibraryExportBuilder AddRuntimeAsset(LibraryAsset asset)
{
Add(ref _runtimeAssets, asset);
return this;
}
public LibraryExportBuilder AddCompilationAssembly(LibraryAsset asset)
{
Add(ref _compilationAssemblies, asset);
return this;
}
public LibraryExportBuilder AddSourceReference(LibraryAsset asset)
{
Add(ref _sourceReferences, asset);
return this;
}
public LibraryExportBuilder AddNativeLibraryGroup(LibraryAssetGroup asset)
{
Add(ref _nativeLibraryGroups, asset);
return this;
}
public LibraryExportBuilder AddEmbedddedResource(LibraryAsset asset)
{
Add(ref _embeddedResources, asset);
return this;
}
public LibraryExportBuilder AddAnalyzerReference(AnalyzerReference asset)
{
Add(ref _analyzerReferences, asset);
return this;
}
public LibraryExportBuilder AddResourceAssembly(LibraryResourceAssembly assembly)
{
Add(ref _resourceAssemblies, assembly);
return this;
}
private void Replace<T>(ref IList<T> list, IEnumerable<T> enumerable)
{
if (enumerable == null)
{
list = null;
}
else
{
list = new List<T>(enumerable);
}
}
private void Add<T>(ref IList<T> list, T item)
{
if (list == null)
{
list = new List<T>();
}
list.Add(item);
}
}
}

View file

@ -1,514 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.Compilation.Preprocessor;
using Microsoft.DotNet.Internal.ProjectModel.Files;
using Microsoft.DotNet.Internal.ProjectModel.Resolution;
using Microsoft.DotNet.Internal.ProjectModel.Utilities;
using Microsoft.DotNet.Tools.Compiler;
using NuGet.Frameworks;
using NuGet.LibraryModel;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation
{
internal class LibraryExporter
{
private readonly string _configuration;
private readonly string _runtime;
private readonly string[] _runtimeFallbacks;
private readonly ProjectDescription _rootProject;
private readonly string _buildBasePath;
private readonly string _solutionRootPath;
public LibraryExporter(ProjectDescription rootProject,
LibraryManager manager,
string configuration,
string runtime,
string[] runtimeFallbacks,
string buildBasePath,
string solutionRootPath)
{
if (string.IsNullOrEmpty(configuration))
{
throw new ArgumentNullException(nameof(configuration));
}
LibraryManager = manager;
_configuration = configuration;
_runtime = runtime;
_runtimeFallbacks = runtimeFallbacks;
_buildBasePath = buildBasePath;
_solutionRootPath = solutionRootPath;
_rootProject = rootProject;
}
public LibraryManager LibraryManager { get; }
/// <summary>
/// Gets all the exports specified by this project, including the root project itself
/// </summary>
public IEnumerable<LibraryExport> GetAllExports()
{
return ExportLibraries(_ => true);
}
/// <summary>
/// Gets all exports required by the project, NOT including the project itself
/// </summary>
/// <returns></returns>
public IEnumerable<LibraryExport> GetDependencies()
{
return GetDependencies(null);
}
/// <summary>
/// Gets all exports required by the project, of the specified <see cref="LibraryType"/>, NOT including the project itself
/// </summary>
/// <returns></returns>
public IEnumerable<LibraryExport> GetDependencies(LibraryType? type)
{
// Export all but the main project
return ExportLibraries(library =>
library != _rootProject &&
LibraryIsOfType(type, library));
}
/// <summary>
/// Retrieves a list of <see cref="LibraryExport"/> objects representing the assets
/// required from other libraries to compile this project.
/// </summary>
private IEnumerable<LibraryExport> ExportLibraries(Func<LibraryDescription, bool> condition)
{
var seenMetadataReferences = new HashSet<string>();
// Iterate over libraries in the library manager
foreach (var library in LibraryManager.GetLibraries())
{
if (!condition(library))
{
continue;
}
var compilationAssemblies = new List<LibraryAsset>();
var sourceReferences = new List<LibraryAsset>();
var analyzerReferences = new List<AnalyzerReference>();
var libraryExport = GetExport(library);
// We need to filter out source references from non-root libraries,
// so we rebuild the library export
foreach (var reference in libraryExport.CompilationAssemblies)
{
if (seenMetadataReferences.Add(reference.Name))
{
compilationAssemblies.Add(reference);
}
}
// Source and analyzer references are not transitive
if (library.Parents.Contains(_rootProject))
{
sourceReferences.AddRange(libraryExport.SourceReferences);
analyzerReferences.AddRange(libraryExport.AnalyzerReferences);
}
var builder = LibraryExportBuilder.Create(library);
if (_runtime != null && _runtimeFallbacks != null)
{
// For portable apps that are built with runtime trimming we replace RuntimeAssemblyGroups and NativeLibraryGroups
// with single default group that contains asset specific to runtime we are trimming for
// based on runtime fallback list
builder.WithRuntimeAssemblyGroups(TrimAssetGroups(libraryExport.RuntimeAssemblyGroups, _runtimeFallbacks));
builder.WithNativeLibraryGroups(TrimAssetGroups(libraryExport.NativeLibraryGroups, _runtimeFallbacks));
}
else
{
builder.WithRuntimeAssemblyGroups(libraryExport.RuntimeAssemblyGroups);
builder.WithNativeLibraryGroups(libraryExport.NativeLibraryGroups);
}
yield return builder
.WithCompilationAssemblies(compilationAssemblies)
.WithSourceReferences(sourceReferences)
.WithRuntimeAssets(libraryExport.RuntimeAssets)
.WithEmbedddedResources(libraryExport.EmbeddedResources)
.WithAnalyzerReference(analyzerReferences)
.WithResourceAssemblies(libraryExport.ResourceAssemblies)
.Build();
}
}
private IEnumerable<LibraryAssetGroup> TrimAssetGroups(IEnumerable<LibraryAssetGroup> runtimeAssemblyGroups,
string[] runtimeFallbacks)
{
LibraryAssetGroup runtimeAssets;
foreach (var rid in runtimeFallbacks)
{
runtimeAssets = runtimeAssemblyGroups.GetRuntimeGroup(rid);
if (runtimeAssets != null)
{
yield return new LibraryAssetGroup(runtimeAssets.Assets);
yield break;
}
}
runtimeAssets = runtimeAssemblyGroups.GetDefaultGroup();
if (runtimeAssets != null)
{
yield return runtimeAssets;
}
}
/// <summary>
/// Create a LibraryExport from LibraryDescription.
///
/// When the library is not resolved the LibraryExport is created nevertheless.
/// </summary>
private LibraryExport GetExport(LibraryDescription library)
{
if (!library.Resolved)
{
// For a unresolved project reference returns a export with empty asset.
return LibraryExportBuilder.Create(library).Build();
}
var libraryType = library.Identity.Type;
if (library is TargetLibraryWithAssets)
{
return ExportPackage((TargetLibraryWithAssets)library);
}
else if (Equals(LibraryType.Project, libraryType))
{
return ExportProject((ProjectDescription)library);
}
else
{
return ExportFrameworkLibrary(library);
}
}
private LibraryExport ExportPackage(TargetLibraryWithAssets library)
{
var builder = LibraryExportBuilder.Create(library);
builder.AddNativeLibraryGroup(new LibraryAssetGroup(PopulateAssets(library, library.NativeLibraries)));
builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(PopulateAssets(library, library.RuntimeAssemblies)));
builder.WithResourceAssemblies(PopulateResources(library, library.ResourceAssemblies));
builder.WithCompilationAssemblies(PopulateAssets(library, library.CompileTimeAssemblies));
if (library.Identity.Type.Equals(LibraryType.Package))
{
builder.WithSourceReferences(GetSharedSources((PackageDescription) library));
builder.WithAnalyzerReference(GetAnalyzerReferences((PackageDescription) library));
}
if (library.ContentFiles.Any())
{
var parameters = PPFileParameters.CreateForProject(_rootProject.Project);
Action<Stream, Stream> transform = (input, output) => PPFilePreprocessor.Preprocess(input, output, parameters);
var sourceCodeLanguage = _rootProject.Project.GetSourceCodeLanguage();
var languageGroups = library.ContentFiles.GroupBy(file => file.CodeLanguage);
var selectedGroup = languageGroups.FirstOrDefault(g => g.Key == sourceCodeLanguage) ??
languageGroups.FirstOrDefault(g => g.Key == "any") ??
languageGroups.FirstOrDefault(g => g.Key == null);
if (selectedGroup != null)
{
foreach (var contentFile in selectedGroup)
{
if (contentFile.CodeLanguage != null &&
contentFile.CodeLanguage != "any" &&
string.Compare(contentFile.CodeLanguage, sourceCodeLanguage, StringComparison.OrdinalIgnoreCase) != 0)
{
continue;
}
var fileTransform = contentFile.PPOutputPath != null ? transform : null;
var fullPath = Path.Combine(library.Path, contentFile.Path);
if (contentFile.BuildAction == BuildAction.Compile)
{
builder.AddSourceReference(LibraryAsset.CreateFromRelativePath(library.Path, contentFile.Path, fileTransform));
}
else if (contentFile.BuildAction == BuildAction.EmbeddedResource)
{
builder.AddEmbedddedResource(LibraryAsset.CreateFromRelativePath(library.Path, contentFile.Path, fileTransform));
}
if (contentFile.CopyToOutput)
{
builder.AddRuntimeAsset(new LibraryAsset(contentFile.Path, contentFile.OutputPath, fullPath, fileTransform));
}
}
}
}
if (library.RuntimeTargets.Any())
{
foreach (var targetGroup in library.RuntimeTargets.GroupBy(t => t.Runtime))
{
var runtime = new List<LibraryAsset>();
var native = new List<LibraryAsset>();
foreach (var lockFileRuntimeTarget in targetGroup)
{
if (string.Equals(lockFileRuntimeTarget.AssetType, "native", StringComparison.OrdinalIgnoreCase))
{
native.Add(LibraryAsset.CreateFromRelativePath(library.Path, lockFileRuntimeTarget.Path));
}
else if (string.Equals(lockFileRuntimeTarget.AssetType, "runtime", StringComparison.OrdinalIgnoreCase))
{
runtime.Add(LibraryAsset.CreateFromRelativePath(library.Path, lockFileRuntimeTarget.Path));
}
}
if (runtime.Any())
{
builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(targetGroup.Key, runtime.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a.RelativePath))));
}
if (native.Any())
{
builder.AddNativeLibraryGroup(new LibraryAssetGroup(targetGroup.Key, native.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a.RelativePath))));
}
}
}
return builder.Build();
}
private LibraryExport ExportProject(ProjectDescription project)
{
var builder = LibraryExportBuilder.Create(project);
var compilerOptions = project.Project.GetCompilerOptions(project.TargetFrameworkInfo.FrameworkName, _configuration);
if (!string.IsNullOrEmpty(project.TargetFrameworkInfo?.AssemblyPath))
{
// Project specifies a pre-compiled binary. We're done!
var assemblyPath = ResolvePath(project.Project, _configuration, project.TargetFrameworkInfo.AssemblyPath);
var pdbPath = Path.ChangeExtension(assemblyPath, "pdb");
var compileAsset = new LibraryAsset(
project.Project.Name,
Path.GetFileName(assemblyPath),
assemblyPath);
builder.AddCompilationAssembly(compileAsset);
builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(new[] { compileAsset }));
if (File.Exists(pdbPath))
{
builder.AddRuntimeAsset(new LibraryAsset(Path.GetFileName(pdbPath), Path.GetFileName(pdbPath), pdbPath));
}
}
else if (HasSourceFiles(project, compilerOptions))
{
var outputPaths = project.GetOutputPaths(_buildBasePath, _solutionRootPath, _configuration, _runtime);
var compilationAssembly = outputPaths.CompilationFiles.Assembly;
var compilationAssemblyAsset = LibraryAsset.CreateFromAbsolutePath(
outputPaths.CompilationFiles.BasePath,
compilationAssembly);
builder.AddCompilationAssembly(compilationAssemblyAsset);
if (ExportsRuntime(project))
{
var runtimeAssemblyAsset = LibraryAsset.CreateFromAbsolutePath(
outputPaths.RuntimeFiles.BasePath,
outputPaths.RuntimeFiles.Assembly);
builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(new[] { runtimeAssemblyAsset }));
builder.WithRuntimeAssets(CollectAssets(outputPaths.RuntimeFiles));
}
else
{
builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(new[] { compilationAssemblyAsset }));
builder.WithRuntimeAssets(CollectAssets(outputPaths.CompilationFiles));
}
builder.WithResourceAssemblies(outputPaths.CompilationFiles.Resources().Select(r => new LibraryResourceAssembly(
LibraryAsset.CreateFromAbsolutePath(outputPaths.CompilationFiles.BasePath, r.Path),
r.Locale)));
}
builder.WithSourceReferences(project.Project.Files.SharedFiles.Select(f =>
LibraryAsset.CreateFromAbsolutePath(project.Path, f)
));
return builder.Build();
}
private bool HasSourceFiles(ProjectDescription project, CommonCompilerOptions compilerOptions)
{
if (compilerOptions.CompileInclude == null)
{
return project.Project.Files.SourceFiles.Any();
}
var includeFiles = IncludeFilesResolver.GetIncludeFiles(compilerOptions.CompileInclude, "/", diagnostics: null);
return includeFiles.Any();
}
private IEnumerable<LibraryAsset> CollectAssets(CompilationOutputFiles files)
{
var assemblyPath = files.Assembly;
foreach (var path in files.All().Except(files.Resources().Select(r => r.Path)))
{
if (string.Equals(assemblyPath, path))
{
continue;
}
yield return LibraryAsset.CreateFromAbsolutePath(files.BasePath, path);
}
}
private bool ExportsRuntime(ProjectDescription project)
{
return project == _rootProject &&
!string.IsNullOrWhiteSpace(_runtime) &&
project.Project.HasRuntimeOutput(_configuration);
}
private static string ResolvePath(Project project, string configuration, string path)
{
if (string.IsNullOrEmpty(path))
{
return null;
}
path = PathUtility.GetPathWithDirectorySeparator(path);
path = path.Replace("{configuration}", configuration);
return Path.Combine(project.ProjectDirectory, path);
}
private LibraryExport ExportFrameworkLibrary(LibraryDescription library)
{
// We assume the path is to an assembly. Framework libraries only export compile-time stuff
// since they assume the runtime library is present already
var builder = LibraryExportBuilder.Create(library);
if (!string.IsNullOrEmpty(library.Path))
{
builder.WithCompilationAssemblies(new[]
{
new LibraryAsset(library.Identity.Name, null, library.Path)
});
}
return builder.Build();
}
private IEnumerable<LibraryAsset> GetSharedSources(PackageDescription package)
{
return package
.PackageLibrary
.Files
.Select(f => PathUtility.GetPathWithDirectorySeparator(f))
.Where(path => path.StartsWith("shared" + Path.DirectorySeparatorChar))
.Select(path => LibraryAsset.CreateFromRelativePath(package.Path, path));
}
private IEnumerable<AnalyzerReference> GetAnalyzerReferences(PackageDescription package)
{
var analyzers = package
.PackageLibrary
.Files
.Select(f => PathUtility.GetPathWithDirectorySeparator(f))
.Where(path => path.StartsWith("analyzers" + Path.DirectorySeparatorChar) &&
path.EndsWith(".dll"));
var analyzerRefs = new List<AnalyzerReference>();
// See https://docs.nuget.org/create/analyzers-conventions for the analyzer
// NuGet specification
foreach (var analyzer in analyzers)
{
var specifiers = analyzer.Split(Path.DirectorySeparatorChar);
var assemblyPath = Path.Combine(package.Path, analyzer);
// $/analyzers/{Framework Name}{Version}/{Supported Architecture}/{Supported Programming Language}/{Analyzer}.dll
switch (specifiers.Length)
{
// $/analyzers/{analyzer}.dll
case 2:
analyzerRefs.Add(new AnalyzerReference(
assembly: assemblyPath,
framework: null,
language: null,
runtimeIdentifier: null
));
break;
// $/analyzers/{framework}/{analyzer}.dll
case 3:
analyzerRefs.Add(new AnalyzerReference(
assembly: assemblyPath,
framework: NuGetFramework.Parse(specifiers[1]),
language: null,
runtimeIdentifier: null
));
break;
// $/analyzers/{framework}/{language}/{analyzer}.dll
case 4:
analyzerRefs.Add(new AnalyzerReference(
assembly: assemblyPath,
framework: NuGetFramework.Parse(specifiers[1]),
language: specifiers[2],
runtimeIdentifier: null
));
break;
// $/analyzers/{framework}/{runtime}/{language}/{analyzer}.dll
case 5:
analyzerRefs.Add(new AnalyzerReference(
assembly: assemblyPath,
framework: NuGetFramework.Parse(specifiers[1]),
language: specifiers[3],
runtimeIdentifier: specifiers[2]
));
break;
// Anything less than 2 specifiers or more than 4 is
// illegal according to the specification and will be
// ignored
}
}
return analyzerRefs;
}
private IEnumerable<LibraryResourceAssembly> PopulateResources(TargetLibraryWithAssets library, IEnumerable<LockFileItem> section)
{
foreach (var assemblyPath in section.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a.Path)))
{
string locale;
if(!assemblyPath.Properties.TryGetValue(Constants.LocaleLockFilePropertyName, out locale))
{
locale = null;
}
yield return new LibraryResourceAssembly(
LibraryAsset.CreateFromRelativePath(library.Path, assemblyPath.Path),
locale);
}
}
private IEnumerable<LibraryAsset> PopulateAssets(TargetLibraryWithAssets library, IEnumerable<LockFileItem> section)
{
foreach (var assemblyPath in section.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a.Path)))
{
yield return LibraryAsset.CreateFromRelativePath(library.Path, assemblyPath.Path);
}
}
private static bool LibraryIsOfType(LibraryType? type, LibraryDescription library)
{
return type == null || // No type filter was requested
library.Identity.Type.Equals(type); // OR, library type matches requested type
}
}
}

View file

@ -1,18 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation
{
internal class LibraryResourceAssembly
{
public LibraryResourceAssembly(LibraryAsset asset, string locale)
{
Asset = asset;
Locale = locale;
}
public LibraryAsset Asset { get; }
public string Locale { get; }
}
}

View file

@ -1,22 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.DotNet.Internal.ProjectModel.Compilation.Preprocessor
{
internal class PPFileParameters
{
public static IDictionary<string, string> CreateForProject(Project project)
{
return new Dictionary<string, string>()
{
{"rootnamespace", project.Name },
{"assemblyname", project.Name }
};
}
}
}

View file

@ -1,53 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
namespace Microsoft.DotNet.Tools.Compiler
{
internal class PPFilePreprocessor
{
public static void Preprocess(Stream input, Stream output, IDictionary<string, string> parameters)
{
string text;
using (var streamReader = new StreamReader(input))
{
text = streamReader.ReadToEnd();
}
var tokenizer = new PPFileTokenizer(text);
using (var streamWriter = new StreamWriter(output))
{
while (true)
{
var token = tokenizer.Read();
if (token == null)
{
break;
}
if (token.Category == PPFileTokenizer.TokenCategory.Variable)
{
var replaced = ReplaceToken(token.Value, parameters);
streamWriter.Write(replaced);
}
else
{
streamWriter.Write(token.Value);
}
}
}
}
private static string ReplaceToken(string name, IDictionary<string, string> parameters)
{
string value;
if (!parameters.TryGetValue(name, out value))
{
throw new InvalidOperationException($"The replacement token '{name}' has no value.");
}
return value;
}
}
}

View file

@ -1,124 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Globalization;
using System.Text;
namespace Microsoft.DotNet.Tools.Compiler
{
internal class PPFileTokenizer
{
private readonly string _text;
private int _index;
public PPFileTokenizer(string text)
{
_text = text;
_index = 0;
}
/// <summary>
/// Gets the next token.
/// </summary>
/// <returns>The parsed token. Or null if no more tokens are available.</returns>
public Token Read()
{
if (_index >= _text.Length)
{
return null;
}
if (_text[_index] == '$')
{
_index++;
return ParseTokenAfterDollarSign();
}
return ParseText();
}
private static bool IsWordChar(char ch)
{
// See http://msdn.microsoft.com/en-us/library/20bw873z.aspx#WordCharacter
var c = CharUnicodeInfo.GetUnicodeCategory(ch);
return c == UnicodeCategory.LowercaseLetter ||
c == UnicodeCategory.UppercaseLetter ||
c == UnicodeCategory.TitlecaseLetter ||
c == UnicodeCategory.OtherLetter ||
c == UnicodeCategory.ModifierLetter ||
c == UnicodeCategory.DecimalDigitNumber ||
c == UnicodeCategory.ConnectorPunctuation;
}
// Parses and returns the next token after a $ is just read.
// _index is one char after the $.
private Token ParseTokenAfterDollarSign()
{
var sb = new StringBuilder();
while (_index < _text.Length)
{
var ch = _text[_index];
if (ch == '$')
{
++_index;
if (sb.Length == 0)
{
// escape sequence "$$" is encountered
return new Token(TokenCategory.Text, "$");
}
// matching $ is read. So the token is a variable.
return new Token(TokenCategory.Variable, sb.ToString());
}
if (IsWordChar(ch))
{
sb.Append(ch);
++_index;
}
else
{
// non word char encountered. So the current token
// is not a variable after all.
sb.Insert(0, '$');
sb.Append(ch);
++_index;
return new Token(TokenCategory.Text, sb.ToString());
}
}
// no matching $ is found and the end of text is reached.
// So the current token is a text.
sb.Insert(0, '$');
return new Token(TokenCategory.Text, sb.ToString());
}
private Token ParseText()
{
var sb = new StringBuilder();
while (_index < _text.Length
&& _text[_index] != '$')
{
sb.Append(_text[_index]);
_index++;
}
return new Token(TokenCategory.Text, sb.ToString());
}
internal class Token
{
public string Value { get; private set; }
public TokenCategory Category { get; private set; }
public Token(TokenCategory category, string value)
{
Category = category;
Value = value;
}
}
public enum TokenCategory
{
Text,
Variable
}
}
}

View file

@ -1,104 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.Files;
using Microsoft.DotNet.Internal.ProjectModel.Resources;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class CompilationOutputFiles
{
protected readonly Project Project;
protected readonly string Configuration;
protected readonly NuGetFramework Framework;
public CompilationOutputFiles(
string basePath,
Project project,
string configuration,
NuGetFramework framework)
{
BasePath = basePath;
Project = project;
Configuration = configuration;
Framework = framework;
OutputExtension = FileNameSuffixes.DotNet.DynamicLib;
var compilerOptions = Project.GetCompilerOptions(framework, configuration);
if (framework.IsDesktop() && compilerOptions.EmitEntryPoint.GetValueOrDefault())
{
OutputExtension = FileNameSuffixes.DotNet.Exe;
}
}
public string BasePath { get; }
public string Assembly
{
get
{
var compilerOptions = Project.GetCompilerOptions(Framework, Configuration);
return Path.Combine(BasePath, compilerOptions.OutputName + OutputExtension);
}
}
public string PdbPath
{
get
{
return Path.ChangeExtension(Assembly, FileNameSuffixes.CurrentPlatform.ProgramDatabase);
}
}
public string OutputExtension { get; }
public virtual IEnumerable<ResourceFile> Resources()
{
var resourceCultureNames = GetResourceFiles()
.Select(f => ResourceUtility.GetResourceCultureName(f))
.Where(f => !string.IsNullOrEmpty(f))
.Distinct();
foreach (var resourceCultureName in resourceCultureNames)
{
yield return new ResourceFile(
Path.Combine(
BasePath, resourceCultureName, Project.Name + ".resources" + FileNameSuffixes.DotNet.DynamicLib),
resourceCultureName);
}
}
public virtual IEnumerable<string> All()
{
yield return Assembly;
yield return PdbPath;
var compilerOptions = Project.GetCompilerOptions(Framework, Configuration);
if (compilerOptions.GenerateXmlDocumentation == true)
{
yield return Path.ChangeExtension(Assembly, "xml");
}
foreach (var resource in Resources())
{
yield return resource.Path;
}
}
private IEnumerable<string> GetResourceFiles()
{
var compilerOptions = Project.GetCompilerOptions(Framework, Configuration);
if (compilerOptions.EmbedInclude == null)
{
return Project.Files.ResourceFiles.Keys;
}
var includeFiles = IncludeFilesResolver.GetIncludeFiles(compilerOptions.EmbedInclude, "/", diagnostics: null);
return includeFiles.Select(f => f.SourcePath);
}
}
}

View file

@ -1,17 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static class Constants
{
public static readonly string DefaultOutputDirectory = "bin";
public static readonly string DefaultConfiguration = "Debug";
public static readonly string LocaleLockFilePropertyName = "locale";
public static readonly Version Version50 = new Version(5, 0);
}
}

View file

@ -1,240 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.DotNet.Internal.ProjectModel;
using Microsoft.DotNet.Internal.ProjectModel.Compilation;
using Microsoft.DotNet.Internal.ProjectModel.Resolution;
using Microsoft.DotNet.Internal.ProjectModel.Utilities;
using NuGet.Frameworks;
using NuGet.LibraryModel;
namespace Microsoft.Extensions.DependencyModel
{
internal class DependencyContextBuilder
{
private readonly string _referenceAssembliesPath;
public DependencyContextBuilder() : this(FrameworkReferenceResolver.Default.ReferenceAssembliesPath)
{
}
public DependencyContextBuilder(string referenceAssembliesPath)
{
_referenceAssembliesPath = referenceAssembliesPath;
}
public DependencyContext Build(CommonCompilerOptions compilerOptions,
IEnumerable<LibraryExport> compilationExports,
IEnumerable<LibraryExport> runtimeExports,
bool portable,
NuGetFramework target,
string runtime)
{
if (compilationExports == null)
{
compilationExports = Enumerable.Empty<LibraryExport>();
}
var dependencyLookup = compilationExports
.Concat(runtimeExports)
.Select(export => export.Library.Identity)
.Distinct()
.Select(identity => new Dependency(identity.Name, identity.Version.ToString()))
.ToDictionary(dependency => dependency.Name, StringComparer.OrdinalIgnoreCase);
var compilationOptions = compilerOptions != null
? GetCompilationOptions(compilerOptions)
: CompilationOptions.Default;
var runtimeSignature = GenerateRuntimeSignature(runtimeExports);
return new DependencyContext(
new TargetInfo(target.DotNetFrameworkName, runtime, runtimeSignature, portable),
compilationOptions,
GetLibraries(compilationExports, dependencyLookup, runtime: false).Cast<CompilationLibrary>(),
GetLibraries(runtimeExports, dependencyLookup, runtime: true).Cast<RuntimeLibrary>(),
new RuntimeFallbacks[] {});
}
private static string GenerateRuntimeSignature(IEnumerable<LibraryExport> runtimeExports)
{
var sha1 = SHA1.Create();
var builder = new StringBuilder();
var packages = runtimeExports
.Where(libraryExport => libraryExport.Library.Identity.Type == LibraryType.Package);
var seperator = "|";
foreach (var libraryExport in packages)
{
builder.Append(libraryExport.Library.Identity.Name);
builder.Append(seperator);
builder.Append(libraryExport.Library.Identity.Version.ToString());
builder.Append(seperator);
}
var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(builder.ToString()));
builder.Clear();
foreach (var b in hash)
{
builder.AppendFormat("{0:x2}", b);
}
return builder.ToString();
}
private static CompilationOptions GetCompilationOptions(CommonCompilerOptions compilerOptions)
{
return new CompilationOptions(compilerOptions.Defines,
compilerOptions.LanguageVersion,
compilerOptions.Platform,
compilerOptions.AllowUnsafe,
compilerOptions.WarningsAsErrors,
compilerOptions.Optimize,
compilerOptions.KeyFile,
compilerOptions.DelaySign,
compilerOptions.PublicSign,
compilerOptions.DebugType,
compilerOptions.EmitEntryPoint,
compilerOptions.GenerateXmlDocumentation);
}
private IEnumerable<Library> GetLibraries(IEnumerable<LibraryExport> exports,
IDictionary<string, Dependency> dependencyLookup,
bool runtime)
{
return exports.Select(export => GetLibrary(export, runtime, dependencyLookup));
}
private Library GetLibrary(LibraryExport export,
bool runtime,
IDictionary<string, Dependency> dependencyLookup)
{
var type = export.Library.Identity.Type;
// TEMPORARY: All packages are serviceable in RC2
// See https://github.com/dotnet/cli/issues/2569
var serviceable = (export.Library as PackageDescription) != null;
var libraryDependencies = new HashSet<Dependency>();
foreach (var libraryDependency in export.Library.Dependencies)
{
// skip build time dependencies
if (libraryDependency.Type.Equals(LibraryDependencyType.Build))
{
continue;
}
Dependency dependency;
if (dependencyLookup.TryGetValue(libraryDependency.Name, out dependency))
{
libraryDependencies.Add(dependency);
}
}
if (runtime)
{
return new RuntimeLibrary(
type.ToString().ToLowerInvariant(),
export.Library.Identity.Name,
export.Library.Identity.Version.ToString(),
export.Library.Hash,
export.RuntimeAssemblyGroups.Select(CreateRuntimeAssetGroup).ToArray(),
export.NativeLibraryGroups.Select(CreateRuntimeAssetGroup).ToArray(),
export.ResourceAssemblies.Select(CreateResourceAssembly),
libraryDependencies,
serviceable,
GetLibraryPath(export.Library),
GetLibraryHashPath(export.Library));
}
else
{
IEnumerable<string> assemblies;
if (type == LibraryType.Reference)
{
assemblies = ResolveReferenceAssembliesPath(export.CompilationAssemblies);
}
else
{
assemblies = export.CompilationAssemblies.Select(libraryAsset => libraryAsset.RelativePath);
}
return new CompilationLibrary(
type.ToString().ToLowerInvariant(),
export.Library.Identity.Name,
export.Library.Identity.Version.ToString(),
export.Library.Hash,
assemblies,
libraryDependencies,
serviceable,
GetLibraryPath(export.Library),
GetLibraryHashPath(export.Library));
}
}
private string GetLibraryPath(LibraryDescription description)
{
var packageDescription = description as PackageDescription;
if (packageDescription != null)
{
// This is the relative path appended to a NuGet packages directory to find the directory containing
// the package assets. This string should only be mastered by NuGet.
return packageDescription.PackageLibrary?.Path;
}
return null;
}
private string GetLibraryHashPath(LibraryDescription description)
{
var packageDescription = description as PackageDescription;
if (packageDescription != null)
{
// This hash path appended to the package path (much like package assets). This string should only be
// mastered by NuGet.
return packageDescription.HashPath;
}
return null;
}
private RuntimeAssetGroup CreateRuntimeAssetGroup(LibraryAssetGroup libraryAssetGroup)
{
return new RuntimeAssetGroup(
libraryAssetGroup.Runtime,
libraryAssetGroup.Assets.Select(a => a.RelativePath));
}
private ResourceAssembly CreateResourceAssembly(LibraryResourceAssembly resourceAssembly)
{
return new ResourceAssembly(
path: resourceAssembly.Asset.RelativePath,
locale: resourceAssembly.Locale
);
}
private IEnumerable<string> ResolveReferenceAssembliesPath(IEnumerable<LibraryAsset> libraryAssets)
{
var referenceAssembliesPath =
PathUtility.EnsureTrailingSlash(_referenceAssembliesPath);
foreach (var libraryAsset in libraryAssets)
{
// If resolved path is under ReferenceAssembliesPath store it as a relative to it
// if not, save only assembly name and try to find it somehow later
if (libraryAsset.ResolvedPath.StartsWith(referenceAssembliesPath))
{
yield return libraryAsset.ResolvedPath.Substring(referenceAssembliesPath.Length);
}
else
{
yield return Path.GetFileName(libraryAsset.ResolvedPath);
}
}
}
}
}

View file

@ -1,148 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NuGet.LibraryModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class DesignTimeWorkspace : Workspace
{
private readonly HashSet<string> _projects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private bool _needRefresh;
public DesignTimeWorkspace(ProjectReaderSettings settings) : base(settings, true) { }
public void AddProject(string path)
{
var projectPath = ProjectPathHelper.NormalizeProjectDirectoryPath(path);
if (projectPath != null)
{
_needRefresh = _projects.Add(path);
}
}
public void RemoveProject(string path)
{
_needRefresh = _projects.Remove(path);
}
/// <summary>
/// Refresh all cached projects in the Workspace
/// </summary>
public void Refresh()
{
if (!_needRefresh)
{
return;
}
var basePaths = new List<string>(_projects);
_projects.Clear();
foreach (var projectDirectory in basePaths)
{
var project = GetProject(projectDirectory);
if (project == null)
{
continue;
}
_projects.Add(project.ProjectDirectory);
foreach (var projectContext in GetProjectContextCollection(project.ProjectDirectory).ProjectContexts)
{
foreach (var reference in GetProjectReferences(projectContext))
{
var referencedProject = GetProject(reference.Path);
if (referencedProject != null)
{
_projects.Add(referencedProject.ProjectDirectory);
}
}
}
}
_needRefresh = false;
}
protected override IEnumerable<ProjectContext> BuildProjectContexts(Project project)
{
foreach (var framework in project.GetTargetFrameworks())
{
yield return CreateBaseProjectBuilder(project)
.AsDesignTime()
.WithTargetFramework(framework.FrameworkName)
.Build();
}
}
private static List<string> ResolveProjectPath(string projectPath)
{
if (File.Exists(projectPath))
{
var filename = Path.GetFileName(projectPath);
if (!Project.FileName.Equals(filename, StringComparison.OrdinalIgnoreCase) &&
!GlobalSettings.FileName.Equals(filename, StringComparison.OrdinalIgnoreCase))
{
return null;
}
projectPath = Path.GetDirectoryName(projectPath);
}
if (File.Exists(Path.Combine(projectPath, Project.FileName)))
{
return new List<string> { projectPath };
}
if (File.Exists(Path.Combine(projectPath, GlobalSettings.FileName)))
{
var root = ProjectRootResolver.ResolveRootDirectory(projectPath);
GlobalSettings globalSettings;
if (GlobalSettings.TryGetGlobalSettings(projectPath, out globalSettings))
{
return globalSettings.ProjectSearchPaths
.Select(searchPath => Path.Combine(globalSettings.DirectoryPath, searchPath))
.Where(actualPath => Directory.Exists(actualPath))
.SelectMany(actualPath => Directory.GetDirectories(actualPath))
.Where(actualPath => File.Exists(Path.Combine(actualPath, Project.FileName)))
.Select(path => Path.GetFullPath(path))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
}
}
return null;
}
private static IEnumerable<ProjectDescription> GetProjectReferences(ProjectContext context)
{
var projectDescriptions = context.LibraryManager
.GetLibraries()
.Where(lib => lib.Identity.Type == LibraryType.Project)
.OfType<ProjectDescription>();
foreach (var description in projectDescriptions)
{
if (description.Identity.Name == context.ProjectFile.Name)
{
continue;
}
// if this is an assembly reference then don't threat it as project reference
if (!string.IsNullOrEmpty(description.TargetFrameworkInfo?.AssemblyPath))
{
continue;
}
yield return description;
}
}
}
}

View file

@ -1,132 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel
{
/// <summary>
/// Represents a single diagnostic message, such as a compilation error or a project.json parsing error.
/// </summary>
internal class DiagnosticMessage
{
public DiagnosticMessage(string errorCode, string message, string filePath, DiagnosticMessageSeverity severity)
: this(errorCode, message, filePath, severity, startLine: 1, startColumn: 0)
{ }
public DiagnosticMessage(string errorCode, string message, string filePath, DiagnosticMessageSeverity severity, int startLine, int startColumn)
: this(
errorCode,
message,
$"{filePath}({startLine},{startColumn}): {severity.ToString().ToLowerInvariant()} {errorCode}: {message}",
filePath,
severity,
startLine,
startColumn,
endLine: startLine,
endColumn: startColumn,
source: null)
{ }
public DiagnosticMessage(string errorCode, string message, string filePath, DiagnosticMessageSeverity severity, int startLine, int startColumn, LibraryDescription source)
: this(
errorCode,
message,
$"{filePath}({startLine},{startColumn}): {severity.ToString().ToLowerInvariant()} {errorCode}: {message}",
filePath,
severity,
startLine,
startColumn,
endLine: startLine,
endColumn: startColumn,
source: source)
{ }
public DiagnosticMessage(string errorCode, string message, string formattedMessage, string filePath,
DiagnosticMessageSeverity severity, int startLine, int startColumn, int endLine, int endColumn)
: this(errorCode,
message,
formattedMessage,
filePath,
severity,
startLine,
startColumn,
endLine,
endColumn,
source: null)
{
}
public DiagnosticMessage(
string errorCode,
string message,
string formattedMessage,
string filePath,
DiagnosticMessageSeverity severity,
int startLine,
int startColumn,
int endLine,
int endColumn,
LibraryDescription source)
{
ErrorCode = errorCode;
Message = message;
SourceFilePath = filePath;
Severity = severity;
StartLine = startLine;
EndLine = endLine;
StartColumn = startColumn;
EndColumn = endColumn;
FormattedMessage = formattedMessage;
Source = source;
}
/// <summary>
/// The moniker associated with the error message
/// </summary>
public string ErrorCode { get; }
/// <summary>
/// Path of the file that produced the message.
/// </summary>
public string SourceFilePath { get; }
/// <summary>
/// Gets the error message.
/// </summary>
public string Message { get; }
/// <summary>
/// Gets the <see cref="DiagnosticMessageSeverity"/>.
/// </summary>
public DiagnosticMessageSeverity Severity { get; }
/// <summary>
/// Gets the one-based line index for the start of the compilation error.
/// </summary>
public int StartLine { get; }
/// <summary>
/// Gets the zero-based column index for the start of the compilation error.
/// </summary>
public int StartColumn { get; }
/// <summary>
/// Gets the one-based line index for the end of the compilation error.
/// </summary>
public int EndLine { get; }
/// <summary>
/// Gets the zero-based column index for the end of the compilation error.
/// </summary>
public int EndColumn { get; }
/// <summary>
/// Gets the formatted error message.
/// </summary>
public string FormattedMessage { get; }
/// <summary>
/// Gets the source of this message
/// </summary>
public LibraryDescription Source { get; }
}
}

View file

@ -1,15 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel
{
/// <summary>
/// Specifies the severity of a <see cref="DiagnosticMessage"/>.
/// </summary>
public enum DiagnosticMessageSeverity
{
Info,
Warning,
Error,
}
}

View file

@ -1,12 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static class DirectoryNames
{
public const string Bin = "bin";
public const string Obj = "obj";
}
}

View file

@ -1,11 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class EnvironmentNames
{
public static readonly string PackagesStore = "NUGET_PACKAGES";
public static readonly string StrongNameKeyFile = "DOTNET_BUILD_STRONG_NAME_KEYFILE";
}
}

View file

@ -1,29 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static partial class ErrorCodes
{
// Target framework not installed
public static readonly string DOTNET1011 = nameof(DOTNET1011);
// Reference assemblies location not specified
public static readonly string DOTNET1012 = nameof(DOTNET1012);
// Multiple libraries marked as "platform"
public static readonly string DOTNET1013 = nameof(DOTNET1013);
// Failed to read lock file
public static readonly string DOTNET1014 = nameof(DOTNET1014);
// The '{0}' option is deprecated. Use '{1}' instead.
public static readonly string DOTNET1015 = nameof(DOTNET1015);
// The '{0}' option in the root is deprecated. Use it in '{1}' instead.
public static readonly string DOTNET1016 = nameof(DOTNET1016);
// Project file does not exist '{0}'.
public static readonly string DOTNET1017 = nameof(DOTNET1017);
}
}

View file

@ -1,44 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static partial class ErrorCodes
{
// The dependency A could not be resolved.
public static readonly string NU1001 = nameof(NU1001);
// The dependency A in project B does not support framework C."
public static readonly string NU1002 = nameof(NU1002);
// Invalid A section. The target B is invalid, targets must either be a file name or a directory suffixed with '/'. The root directory of the package can be specified by using a single '/' character.
public static readonly string NU1003 = nameof(NU1003);
// Invalid A section. The target B contains path-traversal characters ('.' or '..'). These characters are not permitted in target paths.
public static readonly string NU1004 = nameof(NU1004);
// Invalid A section. The target B refers to a single file, but the pattern C produces multiple files. To mark the target as a directory, suffix it with '/'.
public static readonly string NU1005 = nameof(NU1005);
// A. Please run \"dotnet restore\" to generate a new lock file.
public static readonly string NU1006 = nameof(NU1006);
// Dependency specified was A but ended up with B.
public static readonly string NU1007 = nameof(NU1007);
// A is an unsupported framework.
public static readonly string NU1008 = nameof(NU1008);
// The expected lock file doesn't exist. Please run \"dotnet 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);
// The dependency target '{0}' is unsupported.
public static readonly string NU1011 = nameof(NU1011);
// Dependency conflict.
public static readonly string NU1012 = nameof(NU1012);
}
}

View file

@ -1,127 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel
{
public sealed class FileFormatException : Exception
{
private FileFormatException(string message) :
base(message)
{
}
private FileFormatException(string message, Exception innerException) :
base(message, innerException)
{
}
public string Path { get; private set; }
public int Line { get; private set; }
public int Column { get; private set; }
public override string ToString()
{
return $"{Path}({Line},{Column}): Error: {base.ToString()}";
}
internal static FileFormatException Create(Exception exception, string filePath)
{
return new FileFormatException(exception.Message, exception)
.WithFilePath(filePath)
.WithLineInfo(exception);
}
internal static FileFormatException Create(Exception exception, JToken jsonValue, string filePath)
{
var result = Create(exception, jsonValue)
.WithFilePath(filePath);
return result;
}
internal static FileFormatException Create(Exception exception, JToken jsonValue)
{
var result = new FileFormatException(exception.Message, exception)
.WithLineInfo(jsonValue);
return result;
}
internal static FileFormatException Create(string message, JToken jsonValue, string filePath)
{
var result = Create(message, jsonValue)
.WithFilePath(filePath);
return result;
}
internal static FileFormatException Create(string message, string filePath)
{
var result = new FileFormatException(message)
.WithFilePath(filePath);
return result;
}
internal static FileFormatException Create(string message, JToken jsonValue)
{
var result = new FileFormatException(message)
.WithLineInfo(jsonValue);
return result;
}
internal FileFormatException WithFilePath(string path)
{
if (path == null)
{
throw new ArgumentNullException(nameof(path));
}
Path = path;
return this;
}
private FileFormatException WithLineInfo(Exception exception)
{
if (exception is JsonReaderException)
{
WithLineInfo((JsonReaderException) exception);
}
return this;
}
private FileFormatException WithLineInfo(JsonReaderException exception)
{
if (exception == null)
{
throw new ArgumentNullException(nameof(exception));
}
Line = exception.LineNumber;
Column = exception.LinePosition;
return this;
}
private FileFormatException WithLineInfo(JToken value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
var lineInfo = (IJsonLineInfo)value;
Line = lineInfo.LineNumber;
Column = lineInfo.LinePosition;
return this;
}
}
}

View file

@ -1,76 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.PlatformAbstractions;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static class FileNameSuffixes
{
public const string DepsJson = ".deps.json";
public const string RuntimeConfigJson = ".runtimeconfig.json";
public const string RuntimeConfigDevJson = ".runtimeconfig.dev.json";
public static PlatformFileNameSuffixes CurrentPlatform
{
get
{
switch (RuntimeEnvironment.OperatingSystemPlatform)
{
case Platform.Windows:
return Windows;
case Platform.Darwin:
return OSX;
case Platform.Linux:
return Linux;
default:
throw new InvalidOperationException("Unknown Platform");
}
}
}
public static PlatformFileNameSuffixes DotNet { get; } = new PlatformFileNameSuffixes
{
DynamicLib = ".dll",
Exe = ".exe",
ProgramDatabase = ".pdb",
StaticLib = ".lib"
};
public static PlatformFileNameSuffixes Windows { get; } = new PlatformFileNameSuffixes
{
DynamicLib = ".dll",
Exe = ".exe",
ProgramDatabase = ".pdb",
StaticLib = ".lib"
};
public static PlatformFileNameSuffixes OSX { get; } = new PlatformFileNameSuffixes
{
DynamicLib = ".dylib",
Exe = "",
ProgramDatabase = ".pdb",
StaticLib = ".a"
};
public static PlatformFileNameSuffixes Linux { get; } = new PlatformFileNameSuffixes
{
DynamicLib = ".so",
Exe = "",
ProgramDatabase = ".pdb",
StaticLib = ".a"
};
public struct PlatformFileNameSuffixes
{
public string DynamicLib { get; internal set; }
public string Exe { get; internal set; }
public string ProgramDatabase { get; internal set; }
public string StaticLib { get; internal set; }
}
}
}

View file

@ -1,16 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions
{
internal abstract class DirectoryInfoBase : FileSystemInfoBase
{
public abstract IEnumerable<FileSystemInfoBase> EnumerateFileSystemInfos();
public abstract DirectoryInfoBase GetDirectory(string path);
public abstract FileInfoBase GetFile(string path);
}
}

View file

@ -1,89 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions
{
internal class DirectoryInfoWrapper : DirectoryInfoBase
{
private readonly DirectoryInfo _directoryInfo;
private readonly bool _isParentPath;
public DirectoryInfoWrapper(DirectoryInfo directoryInfo, bool isParentPath = false)
{
_directoryInfo = directoryInfo;
_isParentPath = isParentPath;
}
public override IEnumerable<FileSystemInfoBase> EnumerateFileSystemInfos()
{
if (_directoryInfo.Exists)
{
foreach (var fileSystemInfo in _directoryInfo.EnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly))
{
var directoryInfo = fileSystemInfo as DirectoryInfo;
if (directoryInfo != null)
{
yield return new DirectoryInfoWrapper(directoryInfo);
}
else
{
yield return new FileInfoWrapper((FileInfo)fileSystemInfo);
}
}
}
}
public override DirectoryInfoBase GetDirectory(string name)
{
var isParentPath = string.Equals(name, "..", StringComparison.Ordinal);
if (isParentPath)
{
return new DirectoryInfoWrapper(new DirectoryInfo(Path.Combine(_directoryInfo.FullName, name)), isParentPath);
}
else
{
var dirs = _directoryInfo.GetDirectories(name);
if (dirs.Length == 1)
{
return new DirectoryInfoWrapper(dirs[0], isParentPath);
}
else if (dirs.Length == 0)
{
return null;
}
else
{
// This shouldn't happen. The parameter name isn't supposed to contain wild card.
throw new InvalidOperationException(
string.Format("More than one sub directories are found under {0} with name {1}.", _directoryInfo.FullName, name));
}
}
}
public override FileInfoBase GetFile(string name)
{
return new FileInfoWrapper(new FileInfo(Path.Combine(_directoryInfo.FullName, name)));
}
public override string Name
{
get { return _isParentPath ? ".." : _directoryInfo.Name; }
}
public override string FullName
{
get { return _directoryInfo.FullName; }
}
public override DirectoryInfoBase ParentDirectory
{
get { return new DirectoryInfoWrapper(_directoryInfo.Parent); }
}
}
}

View file

@ -1,9 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions
{
internal abstract class FileInfoBase : FileSystemInfoBase
{
}
}

View file

@ -1,32 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.IO;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions
{
internal class FileInfoWrapper : FileInfoBase
{
private FileInfo _fileInfo;
public FileInfoWrapper(FileInfo fileInfo)
{
_fileInfo = fileInfo;
}
public override string Name
{
get { return _fileInfo.Name; }
}
public override string FullName
{
get { return _fileInfo.FullName; }
}
public override DirectoryInfoBase ParentDirectory
{
get { return new DirectoryInfoWrapper(_fileInfo.Directory); }
}
}
}

View file

@ -1,14 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions
{
internal abstract class FileSystemInfoBase
{
public abstract string Name { get; }
public abstract string FullName { get; }
public abstract DirectoryInfoBase ParentDirectory { get; }
}
}

View file

@ -1,40 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.PlatformAbstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing
{
public struct FilePatternMatch : IEquatable<FilePatternMatch>
{
public string Path { get; }
public string Stem { get; }
public FilePatternMatch(string path, string stem)
{
Path = path;
Stem = stem;
}
public bool Equals(FilePatternMatch other)
{
return string.Equals(other.Path, Path, StringComparison.OrdinalIgnoreCase) &&
string.Equals(other.Stem, Stem, StringComparison.OrdinalIgnoreCase);
}
public override bool Equals(object obj)
{
return Equals((FilePatternMatch)obj);
}
public override int GetHashCode()
{
var hashCodeCombiner = HashCodeCombiner.Start();
hashCodeCombiner.Add(Path, StringComparer.OrdinalIgnoreCase);
hashCodeCombiner.Add(Stem, StringComparer.OrdinalIgnoreCase);
return hashCodeCombiner.CombinedHash;
}
}
}

View file

@ -1,12 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal
{
internal interface ILinearPattern : IPattern
{
IList<IPathSegment> Segments { get; }
}
}

View file

@ -1,12 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal
{
internal interface IPathSegment
{
bool CanProduceStem { get; }
bool Match(string value);
}
}

View file

@ -1,12 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal
{
internal interface IPattern
{
IPatternContext CreatePatternContextForInclude();
IPatternContext CreatePatternContextForExclude();
}
}

View file

@ -1,21 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal
{
internal interface IPatternContext
{
void Declare(Action<IPathSegment, bool> onDeclare);
bool Test(DirectoryInfoBase directory);
PatternTestResult Test(FileInfoBase file);
void PushDirectory(DirectoryInfoBase directory);
void PopDirectory();
}
}

View file

@ -1,18 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal
{
internal interface IRaggedPattern : IPattern
{
IList<IPathSegment> Segments { get; }
IList<IPathSegment> StartsWith { get; }
IList<IList<IPathSegment>> Contains { get; }
IList<IPathSegment> EndsWith { get; }
}
}

View file

@ -1,250 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Util;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal
{
internal class MatcherContext
{
private readonly DirectoryInfoBase _root;
private readonly IList<IPatternContext> _includePatternContexts;
private readonly IList<IPatternContext> _excludePatternContexts;
private readonly IList<FilePatternMatch> _files;
private readonly HashSet<string> _declaredLiteralFolderSegmentInString;
private readonly HashSet<LiteralPathSegment> _declaredLiteralFolderSegments = new HashSet<LiteralPathSegment>();
private readonly HashSet<LiteralPathSegment> _declaredLiteralFileSegments = new HashSet<LiteralPathSegment>();
private bool _declaredParentPathSegment;
private bool _declaredWildcardPathSegment;
private readonly StringComparison _comparisonType;
public MatcherContext(IEnumerable<IPattern> includePatterns,
IEnumerable<IPattern> excludePatterns,
DirectoryInfoBase directoryInfo,
StringComparison comparison)
{
_root = directoryInfo;
_files = new List<FilePatternMatch>();
_comparisonType = comparison;
_includePatternContexts = includePatterns.Select(pattern => pattern.CreatePatternContextForInclude()).ToList();
_excludePatternContexts = excludePatterns.Select(pattern => pattern.CreatePatternContextForExclude()).ToList();
_declaredLiteralFolderSegmentInString = new HashSet<string>(StringComparisonHelper.GetStringComparer(comparison));
}
public PatternMatchingResult Execute()
{
_files.Clear();
Match(_root, parentRelativePath: null);
return new PatternMatchingResult(_files);
}
private void Match(DirectoryInfoBase directory, string parentRelativePath)
{
// Request all the including and excluding patterns to push current directory onto their status stack.
PushDirectory(directory);
Declare();
var entities = new List<FileSystemInfoBase>();
if (_declaredWildcardPathSegment || _declaredLiteralFileSegments.Any())
{
entities.AddRange(directory.EnumerateFileSystemInfos());
}
else
{
var candidates = directory.EnumerateFileSystemInfos().OfType<DirectoryInfoBase>();
foreach (var candidate in candidates)
{
if (_declaredLiteralFolderSegmentInString.Contains(candidate.Name))
{
entities.Add(candidate);
}
}
}
if (_declaredParentPathSegment)
{
entities.Add(directory.GetDirectory(".."));
}
// collect files and sub directories
var subDirectories = new List<DirectoryInfoBase>();
foreach (var entity in entities)
{
var fileInfo = entity as FileInfoBase;
if (fileInfo != null)
{
var result = MatchPatternContexts(fileInfo, (pattern, file) => pattern.Test(file));
if (result.IsSuccessful)
{
_files.Add(new FilePatternMatch(
path: CombinePath(parentRelativePath, fileInfo.Name),
stem: result.Stem));
}
continue;
}
var directoryInfo = entity as DirectoryInfoBase;
if (directoryInfo != null)
{
if (MatchPatternContexts(directoryInfo, (pattern, dir) => pattern.Test(dir)))
{
subDirectories.Add(directoryInfo);
}
continue;
}
}
// Matches the sub directories recursively
foreach (var subDir in subDirectories)
{
var relativePath = CombinePath(parentRelativePath, subDir.Name);
Match(subDir, relativePath);
}
// Request all the including and excluding patterns to pop their status stack.
PopDirectory();
}
private void Declare()
{
_declaredLiteralFileSegments.Clear();
_declaredLiteralFolderSegments.Clear();
_declaredParentPathSegment = false;
_declaredWildcardPathSegment = false;
foreach (var include in _includePatternContexts)
{
include.Declare(DeclareInclude);
}
}
private void DeclareInclude(IPathSegment patternSegment, bool isLastSegment)
{
var literalSegment = patternSegment as LiteralPathSegment;
if (literalSegment != null)
{
if (isLastSegment)
{
_declaredLiteralFileSegments.Add(literalSegment);
}
else
{
_declaredLiteralFolderSegments.Add(literalSegment);
_declaredLiteralFolderSegmentInString.Add(literalSegment.Value);
}
}
else if (patternSegment is ParentPathSegment)
{
_declaredParentPathSegment = true;
}
else if (patternSegment is WildcardPathSegment)
{
_declaredWildcardPathSegment = true;
}
}
internal static string CombinePath(string left, string right)
{
if (string.IsNullOrEmpty(left))
{
return right;
}
else
{
return string.Format("{0}/{1}", left, right);
}
}
// Used to adapt Test(DirectoryInfoBase) for the below overload
private bool MatchPatternContexts<TFileInfoBase>(TFileInfoBase fileinfo, Func<IPatternContext, TFileInfoBase, bool> test)
{
return MatchPatternContexts(
fileinfo,
(ctx, file) =>
{
if (test(ctx, file))
{
return PatternTestResult.Success(stem: string.Empty);
}
else
{
return PatternTestResult.Failed;
}
}).IsSuccessful;
}
private PatternTestResult MatchPatternContexts<TFileInfoBase>(TFileInfoBase fileinfo, Func<IPatternContext, TFileInfoBase, PatternTestResult> test)
{
var result = PatternTestResult.Failed;
// If the given file/directory matches any including pattern, continues to next step.
foreach (var context in _includePatternContexts)
{
var localResult = test(context, fileinfo);
if (localResult.IsSuccessful)
{
result = localResult;
break;
}
}
// If the given file/directory doesn't match any of the including pattern, returns false.
if (!result.IsSuccessful)
{
return PatternTestResult.Failed;
}
// If the given file/directory matches any excluding pattern, returns false.
foreach (var context in _excludePatternContexts)
{
if (test(context, fileinfo).IsSuccessful)
{
return PatternTestResult.Failed;
}
}
return result;
}
private void PopDirectory()
{
foreach (var context in _excludePatternContexts)
{
context.PopDirectory();
}
foreach (var context in _includePatternContexts)
{
context.PopDirectory();
}
}
private void PushDirectory(DirectoryInfoBase directory)
{
foreach (var context in _includePatternContexts)
{
context.PushDirectory(directory);
}
foreach (var context in _excludePatternContexts)
{
context.PushDirectory(directory);
}
}
}
}

View file

@ -1,17 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PathSegments
{
internal class CurrentPathSegment : IPathSegment
{
public bool CanProduceStem { get { return false; } }
public bool Match(string value)
{
return false;
}
}
}

View file

@ -1,48 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Util;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PathSegments
{
internal class LiteralPathSegment : IPathSegment
{
private readonly StringComparison _comparisonType;
public bool CanProduceStem { get { return false; } }
public LiteralPathSegment(string value, StringComparison comparisonType)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
Value = value;
_comparisonType = comparisonType;
}
public string Value { get; }
public bool Match(string value)
{
return string.Equals(Value, value, _comparisonType);
}
public override bool Equals(object obj)
{
var other = obj as LiteralPathSegment;
return other != null &&
_comparisonType == other._comparisonType &&
string.Equals(other.Value, Value, _comparisonType);
}
public override int GetHashCode()
{
return StringComparisonHelper.GetStringComparer(_comparisonType).GetHashCode(Value);
}
}
}

View file

@ -1,19 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PathSegments
{
internal class ParentPathSegment : IPathSegment
{
private static readonly string LiteralParent = "..";
public bool CanProduceStem { get { return false; } }
public bool Match(string value)
{
return string.Equals(LiteralParent, value, StringComparison.Ordinal);
}
}
}

View file

@ -1,17 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PathSegments
{
internal class RecursiveWildcardSegment : IPathSegment
{
public bool CanProduceStem { get { return true; } }
public bool Match(string value)
{
return false;
}
}
}

View file

@ -1,74 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PathSegments
{
internal class WildcardPathSegment : IPathSegment
{
// It doesn't matter which StringComparison type is used in this MatchAll segment because
// all comparing are skipped since there is no content in the segment.
public static readonly WildcardPathSegment MatchAll = new WildcardPathSegment(
string.Empty, new List<string>(), string.Empty, StringComparison.OrdinalIgnoreCase);
private readonly StringComparison _comparisonType;
public WildcardPathSegment(string beginsWith, List<string> contains, string endsWith, StringComparison comparisonType)
{
BeginsWith = beginsWith;
Contains = contains;
EndsWith = endsWith;
_comparisonType = comparisonType;
}
public bool CanProduceStem { get { return true; } }
public string BeginsWith { get; }
public List<string> Contains { get; }
public string EndsWith { get; }
public bool Match(string value)
{
var wildcard = this;
if (value.Length < wildcard.BeginsWith.Length + wildcard.EndsWith.Length)
{
return false;
}
if (!value.StartsWith(wildcard.BeginsWith, _comparisonType))
{
return false;
}
if (!value.EndsWith(wildcard.EndsWith, _comparisonType))
{
return false;
}
var beginRemaining = wildcard.BeginsWith.Length;
var endRemaining = value.Length - wildcard.EndsWith.Length;
for (var containsIndex = 0; containsIndex != wildcard.Contains.Count; ++containsIndex)
{
var containsValue = wildcard.Contains[containsIndex];
var indexOf = value.IndexOf(
value: containsValue,
startIndex: beginRemaining,
count: endRemaining - beginRemaining,
comparisonType: _comparisonType);
if (indexOf == -1)
{
return false;
}
beginRemaining = indexOf + containsValue.Length;
}
return true;
}
}
}

View file

@ -1,39 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PatternContexts
{
internal abstract class PatternContext<TFrame> : IPatternContext
{
private Stack<TFrame> _stack = new Stack<TFrame>();
protected TFrame Frame;
public virtual void Declare(Action<IPathSegment, bool> declare) { }
public abstract PatternTestResult Test(FileInfoBase file);
public abstract bool Test(DirectoryInfoBase directory);
public abstract void PushDirectory(DirectoryInfoBase directory);
public virtual void PopDirectory()
{
Frame = _stack.Pop();
}
protected void PushDataFrame(TFrame frame)
{
_stack.Push(Frame);
Frame = frame;
}
protected bool IsStackEmpty()
{
return _stack.Count == 0;
}
}
}

View file

@ -1,105 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PatternContexts
{
internal abstract class PatternContextLinear
: PatternContext<PatternContextLinear.FrameData>
{
public PatternContextLinear(ILinearPattern pattern)
{
Pattern = pattern;
}
public override PatternTestResult Test(FileInfoBase file)
{
if (IsStackEmpty())
{
throw new InvalidOperationException("Can't test file before entering a directory.");
}
if(!Frame.IsNotApplicable && IsLastSegment() && TestMatchingSegment(file.Name))
{
return PatternTestResult.Success(CalculateStem(file));
}
return PatternTestResult.Failed;
}
public override void PushDirectory(DirectoryInfoBase directory)
{
// copy the current frame
var frame = Frame;
if (IsStackEmpty() || Frame.IsNotApplicable)
{
// when the stack is being initialized
// or no change is required.
}
else if (!TestMatchingSegment(directory.Name))
{
// nothing down this path is affected by this pattern
frame.IsNotApplicable = true;
}
else
{
// Determine this frame's contribution to the stem (if any)
var segment = Pattern.Segments[Frame.SegmentIndex];
if (frame.InStem || segment.CanProduceStem)
{
frame.InStem = true;
frame.StemItems.Add(directory.Name);
}
// directory matches segment, advance position in pattern
frame.SegmentIndex = frame.SegmentIndex + 1;
}
PushDataFrame(frame);
}
public struct FrameData
{
public bool IsNotApplicable;
public int SegmentIndex;
public bool InStem;
private IList<string> _stemItems;
public IList<string> StemItems
{
get { return _stemItems ?? (_stemItems = new List<string>()); }
}
public string Stem
{
get { return _stemItems == null ? null : string.Join("/", _stemItems); }
}
}
protected ILinearPattern Pattern { get; }
protected bool IsLastSegment()
{
return Frame.SegmentIndex == Pattern.Segments.Count - 1;
}
protected bool TestMatchingSegment(string value)
{
if (Frame.SegmentIndex >= Pattern.Segments.Count)
{
return false;
}
return Pattern.Segments[Frame.SegmentIndex].Match(value);
}
protected string CalculateStem(FileInfoBase matchedFile)
{
return MatcherContext.CombinePath(Frame.Stem, matchedFile.Name);
}
}
}

View file

@ -1,31 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PatternContexts
{
internal class PatternContextLinearExclude : PatternContextLinear
{
public PatternContextLinearExclude(ILinearPattern pattern)
: base(pattern)
{
}
public override bool Test(DirectoryInfoBase directory)
{
if (IsStackEmpty())
{
throw new InvalidOperationException("Can't test directory before entering a directory.");
}
if (Frame.IsNotApplicable)
{
return false;
}
return IsLastSegment() && TestMatchingSegment(directory.Name);
}
}
}

View file

@ -1,49 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PatternContexts
{
internal class PatternContextLinearInclude : PatternContextLinear
{
public PatternContextLinearInclude(ILinearPattern pattern)
: base(pattern)
{
}
public override void Declare(Action<IPathSegment, bool> onDeclare)
{
if (IsStackEmpty())
{
throw new InvalidOperationException("Can't declare path segment before entering a directory.");
}
if (Frame.IsNotApplicable)
{
return;
}
if (Frame.SegmentIndex < Pattern.Segments.Count)
{
onDeclare(Pattern.Segments[Frame.SegmentIndex], IsLastSegment());
}
}
public override bool Test(DirectoryInfoBase directory)
{
if (IsStackEmpty())
{
throw new InvalidOperationException("Can't test directory before entering a directory.");
}
if (Frame.IsNotApplicable)
{
return false;
}
return !IsLastSegment() && TestMatchingSegment(directory.Name);
}
}
}

View file

@ -1,186 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PatternContexts
{
internal abstract class PatternContextRagged : PatternContext<PatternContextRagged.FrameData>
{
public PatternContextRagged(IRaggedPattern pattern)
{
Pattern = pattern;
}
public override PatternTestResult Test(FileInfoBase file)
{
if (IsStackEmpty())
{
throw new InvalidOperationException("Can't test file before entering a directory.");
}
if(!Frame.IsNotApplicable && IsEndingGroup() && TestMatchingGroup(file))
{
return PatternTestResult.Success(CalculateStem(file));
}
return PatternTestResult.Failed;
}
public sealed override void PushDirectory(DirectoryInfoBase directory)
{
// copy the current frame
var frame = Frame;
if (IsStackEmpty())
{
// initializing
frame.SegmentGroupIndex = -1;
frame.SegmentGroup = Pattern.StartsWith;
}
else if (Frame.IsNotApplicable)
{
// no change
}
else if (IsStartingGroup())
{
if (!TestMatchingSegment(directory.Name))
{
// nothing down this path is affected by this pattern
frame.IsNotApplicable = true;
}
else
{
// starting path incrementally satisfied
frame.SegmentIndex += 1;
}
}
else if (!IsStartingGroup() && directory.Name == "..")
{
// any parent path segment is not applicable in **
frame.IsNotApplicable = true;
}
else if (!IsStartingGroup() && !IsEndingGroup() && TestMatchingGroup(directory))
{
frame.SegmentIndex = Frame.SegmentGroup.Count;
frame.BacktrackAvailable = 0;
}
else
{
// increase directory backtrack length
frame.BacktrackAvailable += 1;
}
if (frame.InStem)
{
frame.StemItems.Add(directory.Name);
}
while (
frame.SegmentIndex == frame.SegmentGroup.Count &&
frame.SegmentGroupIndex != Pattern.Contains.Count)
{
frame.SegmentGroupIndex += 1;
frame.SegmentIndex = 0;
if (frame.SegmentGroupIndex < Pattern.Contains.Count)
{
frame.SegmentGroup = Pattern.Contains[frame.SegmentGroupIndex];
}
else
{
frame.SegmentGroup = Pattern.EndsWith;
}
// We now care about the stem
frame.InStem = true;
}
PushDataFrame(frame);
}
public override void PopDirectory()
{
base.PopDirectory();
if (Frame.StemItems.Count > 0)
{
Frame.StemItems.RemoveAt(Frame.StemItems.Count - 1);
}
}
public struct FrameData
{
public bool IsNotApplicable;
public int SegmentGroupIndex;
public IList<IPathSegment> SegmentGroup;
public int BacktrackAvailable;
public int SegmentIndex;
public bool InStem;
private IList<string> _stemItems;
public IList<string> StemItems
{
get { return _stemItems ?? (_stemItems = new List<string>()); }
}
public string Stem
{
get { return _stemItems == null ? null : string.Join("/", _stemItems); }
}
}
protected IRaggedPattern Pattern { get; }
protected bool IsStartingGroup()
{
return Frame.SegmentGroupIndex == -1;
}
protected bool IsEndingGroup()
{
return Frame.SegmentGroupIndex == Pattern.Contains.Count;
}
protected bool TestMatchingSegment(string value)
{
if (Frame.SegmentIndex >= Frame.SegmentGroup.Count)
{
return false;
}
return Frame.SegmentGroup[Frame.SegmentIndex].Match(value);
}
protected bool TestMatchingGroup(FileSystemInfoBase value)
{
var groupLength = Frame.SegmentGroup.Count;
var backtrackLength = Frame.BacktrackAvailable + 1;
if (backtrackLength < groupLength)
{
return false;
}
var scan = value;
for (int index = 0; index != groupLength; ++index)
{
var segment = Frame.SegmentGroup[groupLength - index - 1];
if (!segment.Match(scan.Name))
{
return false;
}
scan = scan.ParentDirectory;
}
return true;
}
protected string CalculateStem(FileInfoBase matchedFile)
{
return MatcherContext.CombinePath(Frame.Stem, matchedFile.Name);
}
}
}

View file

@ -1,45 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PatternContexts
{
internal class PatternContextRaggedExclude : PatternContextRagged
{
public PatternContextRaggedExclude(IRaggedPattern pattern)
: base(pattern)
{
}
public override bool Test(DirectoryInfoBase directory)
{
if (IsStackEmpty())
{
throw new InvalidOperationException("Can't test directory before entering a directory.");
}
if (Frame.IsNotApplicable)
{
return false;
}
if (IsEndingGroup() && TestMatchingGroup(directory))
{
// directory excluded with file-like pattern
return true;
}
if (Pattern.EndsWith.Count == 0 &&
Frame.SegmentGroupIndex == Pattern.Contains.Count - 1 &&
TestMatchingGroup(directory))
{
// directory excluded by matching up to final '/**'
return true;
}
return false;
}
}
}

View file

@ -1,60 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PatternContexts
{
internal class PatternContextRaggedInclude : PatternContextRagged
{
public PatternContextRaggedInclude(IRaggedPattern pattern)
: base(pattern)
{
}
public override void Declare(Action<IPathSegment, bool> onDeclare)
{
if (IsStackEmpty())
{
throw new InvalidOperationException("Can't declare path segment before entering a directory.");
}
if (Frame.IsNotApplicable)
{
return;
}
if (IsStartingGroup() && Frame.SegmentIndex < Frame.SegmentGroup.Count)
{
onDeclare(Frame.SegmentGroup[Frame.SegmentIndex], false);
}
else
{
onDeclare(WildcardPathSegment.MatchAll, false);
}
}
public override bool Test(DirectoryInfoBase directory)
{
if (IsStackEmpty())
{
throw new InvalidOperationException("Can't test directory before entering a directory.");
}
if (Frame.IsNotApplicable)
{
return false;
}
if (IsStartingGroup() && !TestMatchingSegment(directory.Name))
{
// deterministic not-included
return false;
}
return true;
}
}
}

View file

@ -1,24 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal
{
public struct PatternTestResult
{
public static readonly PatternTestResult Failed = new PatternTestResult(isSuccessful: false, stem: null);
public bool IsSuccessful { get; }
public string Stem { get; }
private PatternTestResult(bool isSuccessful, string stem)
{
IsSuccessful = isSuccessful;
Stem = stem;
}
public static PatternTestResult Success(string stem)
{
return new PatternTestResult(isSuccessful: true, stem: stem);
}
}
}

View file

@ -1,272 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PathSegments;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.PatternContexts;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.Patterns
{
internal class PatternBuilder
{
private static readonly char[] _slashes = new[] { '/', '\\' };
private static readonly char[] _star = new[] { '*' };
public PatternBuilder()
{
ComparisonType = StringComparison.OrdinalIgnoreCase;
}
public PatternBuilder(StringComparison comparisonType)
{
ComparisonType = comparisonType;
}
public StringComparison ComparisonType { get; }
public IPattern Build(string pattern)
{
if (pattern == null)
{
throw new ArgumentNullException("pattern");
}
pattern = pattern.TrimStart(_slashes);
if (pattern.TrimEnd(_slashes).Length < pattern.Length)
{
// If the pattern end with a slash, it is considered as
// a directory.
pattern = pattern.TrimEnd(_slashes) + "/**";
}
var allSegments = new List<IPathSegment>();
var isParentSegmentLegal = true;
IList<IPathSegment> segmentsPatternStartsWith = null;
IList<IList<IPathSegment>> segmentsPatternContains = null;
IList<IPathSegment> segmentsPatternEndsWith = null;
var endPattern = pattern.Length;
for (int scanPattern = 0; scanPattern < endPattern;)
{
var beginSegment = scanPattern;
var endSegment = NextIndex(pattern, _slashes, scanPattern, endPattern);
IPathSegment segment = null;
if (segment == null && endSegment - beginSegment == 3)
{
if (pattern[beginSegment] == '*' &&
pattern[beginSegment + 1] == '.' &&
pattern[beginSegment + 2] == '*')
{
// turn *.* into *
beginSegment += 2;
}
}
if (segment == null && endSegment - beginSegment == 2)
{
if (pattern[beginSegment] == '*' &&
pattern[beginSegment + 1] == '*')
{
// recognized **
segment = new RecursiveWildcardSegment();
}
else if (pattern[beginSegment] == '.' &&
pattern[beginSegment + 1] == '.')
{
// recognized ..
if (!isParentSegmentLegal)
{
throw new ArgumentException("\"..\" can be only added at the beginning of the pattern.");
}
segment = new ParentPathSegment();
}
}
if (segment == null && endSegment - beginSegment == 1)
{
if (pattern[beginSegment] == '.')
{
// recognized .
segment = new CurrentPathSegment();
}
}
if (segment == null && endSegment - beginSegment > 2)
{
if (pattern[beginSegment] == '*' &&
pattern[beginSegment + 1] == '*' &&
pattern[beginSegment + 2] == '.')
{
// recognize **.
// swallow the first *, add the recursive path segment and
// the remaining part will be treat as wild card in next loop.
segment = new RecursiveWildcardSegment();
endSegment = beginSegment;
}
}
if (segment == null)
{
var beginsWith = string.Empty;
var contains = new List<string>();
var endsWith = string.Empty;
for (int scanSegment = beginSegment; scanSegment < endSegment;)
{
var beginLiteral = scanSegment;
var endLiteral = NextIndex(pattern, _star, scanSegment, endSegment);
if (beginLiteral == beginSegment)
{
if (endLiteral == endSegment)
{
// and the only bit
segment = new LiteralPathSegment(Portion(pattern, beginLiteral, endLiteral), ComparisonType);
}
else
{
// this is the first bit
beginsWith = Portion(pattern, beginLiteral, endLiteral);
}
}
else if (endLiteral == endSegment)
{
// this is the last bit
endsWith = Portion(pattern, beginLiteral, endLiteral);
}
else
{
if (beginLiteral != endLiteral)
{
// this is a middle bit
contains.Add(Portion(pattern, beginLiteral, endLiteral));
}
else
{
// note: NOOP here, adjacent *'s are collapsed when they
// are mixed with literal text in a path segment
}
}
scanSegment = endLiteral + 1;
}
if (segment == null)
{
segment = new WildcardPathSegment(beginsWith, contains, endsWith, ComparisonType);
}
}
if (!(segment is ParentPathSegment))
{
isParentSegmentLegal = false;
}
if (segment is CurrentPathSegment)
{
// ignore ".\"
}
else
{
if (segment is RecursiveWildcardSegment)
{
if (segmentsPatternStartsWith == null)
{
segmentsPatternStartsWith = new List<IPathSegment>(allSegments);
segmentsPatternEndsWith = new List<IPathSegment>();
segmentsPatternContains = new List<IList<IPathSegment>>();
}
else if (segmentsPatternEndsWith.Count != 0)
{
segmentsPatternContains.Add(segmentsPatternEndsWith);
segmentsPatternEndsWith = new List<IPathSegment>();
}
}
else if (segmentsPatternEndsWith != null)
{
segmentsPatternEndsWith.Add(segment);
}
allSegments.Add(segment);
}
scanPattern = endSegment + 1;
}
if (segmentsPatternStartsWith == null)
{
return new LinearPattern(allSegments);
}
else
{
return new RaggedPattern(allSegments, segmentsPatternStartsWith, segmentsPatternEndsWith, segmentsPatternContains);
}
}
private static int NextIndex(string pattern, char[] anyOf, int beginIndex, int endIndex)
{
var index = pattern.IndexOfAny(anyOf, beginIndex, endIndex - beginIndex);
return index == -1 ? endIndex : index;
}
private static string Portion(string pattern, int beginIndex, int endIndex)
{
return pattern.Substring(beginIndex, endIndex - beginIndex);
}
private class LinearPattern : ILinearPattern
{
public LinearPattern(List<IPathSegment> allSegments)
{
Segments = allSegments;
}
public IList<IPathSegment> Segments { get; }
public IPatternContext CreatePatternContextForInclude()
{
return new PatternContextLinearInclude(this);
}
public IPatternContext CreatePatternContextForExclude()
{
return new PatternContextLinearExclude(this);
}
}
private class RaggedPattern : IRaggedPattern
{
public RaggedPattern(List<IPathSegment> allSegments, IList<IPathSegment> segmentsPatternStartsWith, IList<IPathSegment> segmentsPatternEndsWith, IList<IList<IPathSegment>> segmentsPatternContains)
{
Segments = allSegments;
StartsWith = segmentsPatternStartsWith;
Contains = segmentsPatternContains;
EndsWith = segmentsPatternEndsWith;
}
public IList<IList<IPathSegment>> Contains { get; }
public IList<IPathSegment> EndsWith { get; }
public IList<IPathSegment> Segments { get; }
public IList<IPathSegment> StartsWith { get; }
public IPatternContext CreatePatternContextForInclude()
{
return new PatternContextRaggedInclude(this);
}
public IPatternContext CreatePatternContextForExclude()
{
return new PatternContextRaggedExclude(this);
}
}
}
}

View file

@ -1,48 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Internal.Patterns;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing
{
internal class Matcher
{
private IList<IPattern> _includePatterns = new List<IPattern>();
private IList<IPattern> _excludePatterns = new List<IPattern>();
private readonly PatternBuilder _builder;
private readonly StringComparison _comparison;
public Matcher()
: this(StringComparison.OrdinalIgnoreCase)
{
}
public Matcher(StringComparison comparisonType)
{
_comparison = comparisonType;
_builder = new PatternBuilder(comparisonType);
}
public virtual Matcher AddInclude(string pattern)
{
_includePatterns.Add(_builder.Build(pattern));
return this;
}
public virtual Matcher AddExclude(string pattern)
{
_excludePatterns.Add(_builder.Build(pattern));
return this;
}
public virtual PatternMatchingResult Execute(DirectoryInfoBase directoryInfo)
{
var context = new MatcherContext(_includePatterns, _excludePatterns, directoryInfo, _comparison);
return context.Execute();
}
}
}

View file

@ -1,44 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing
{
internal static class MatcherExtensions
{
public static void AddExcludePatterns(this Matcher matcher, params IEnumerable<string>[] excludePatternsGroups)
{
foreach (var group in excludePatternsGroups)
{
foreach (var pattern in group)
{
matcher.AddExclude(pattern);
}
}
}
public static void AddIncludePatterns(this Matcher matcher, params IEnumerable<string>[] includePatternsGroups)
{
foreach (var group in includePatternsGroups)
{
foreach (var pattern in group)
{
matcher.AddInclude(pattern);
}
}
}
public static IEnumerable<string> GetResultsInFullPath(this Matcher matcher, string directoryPath)
{
var matches = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(directoryPath))).Files;
var result = matches.Select(match => Path.GetFullPath(Path.Combine(directoryPath, match.Path))).ToArray();
return result;
}
}
}

View file

@ -1,17 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing
{
internal class PatternMatchingResult
{
public PatternMatchingResult(IEnumerable<FilePatternMatch> files)
{
Files = files;
}
public IEnumerable<FilePatternMatch> Files { get; set; }
}
}

View file

@ -1,33 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Util
{
internal static class StringComparisonHelper
{
public static StringComparer GetStringComparer(StringComparison comparisonType)
{
switch (comparisonType)
{
case StringComparison.CurrentCulture:
return StringComparer.CurrentCulture;
case StringComparison.CurrentCultureIgnoreCase:
return StringComparer.CurrentCultureIgnoreCase;
case StringComparison.Ordinal:
return StringComparer.Ordinal;
case StringComparison.OrdinalIgnoreCase:
return StringComparer.OrdinalIgnoreCase;
#if NET451
case StringComparison.InvariantCulture:
return StringComparer.InvariantCulture;
case StringComparison.InvariantCultureIgnoreCase:
return StringComparer.InvariantCultureIgnoreCase;
#endif
default:
throw new InvalidOperationException($"Unexpected StringComparison type: {comparisonType}");
}
}
}
}

View file

@ -1,54 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
// Similar to IncludeContext, except that it replaces the include information with the exclude information and clears
// out the exclude information. This is to be used by migration to do CopyToOutput with Never set as its metadata.
internal class ExcludeContext : IncludeContext
{
public ExcludeContext(
string sourceBasePath,
string option,
JObject rawObject,
string[] defaultBuiltInInclude,
string[] defaultBuiltInExclude) : base(
sourceBasePath,
option,
rawObject,
defaultBuiltInInclude,
defaultBuiltInExclude)
{
IncludePatterns = ExcludePatterns;
ExcludePatterns = new List<string>();
IncludeFiles = ExcludeFiles;
ExcludeFiles = new List<string>();
BuiltInsInclude = BuiltInsExclude;
BuiltInsExclude = new List<string>();
if (Mappings != null)
{
var newMappings = new Dictionary<string, IncludeContext>();
foreach (var mapping in Mappings)
{
newMappings.Add(mapping.Key, new ExcludeContext(
mapping.Value.SourceBasePath,
mapping.Value.Option,
mapping.Value.RawObject,
mapping.Value.BuiltInsInclude?.ToArray(),
mapping.Value.BuiltInsExclude?.ToArray()));
}
Mappings = newMappings;
}
}
}
}

View file

@ -1,236 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
internal class IncludeContext
{
private static readonly char[] PatternSeparator = new[] { ';' };
public IncludeContext(
string sourceBasePath,
string option,
JObject rawObject,
string[] defaultBuiltInInclude,
string[] defaultBuiltInExclude)
{
if (sourceBasePath == null)
{
throw new ArgumentNullException(nameof(sourceBasePath));
}
if (option == null)
{
throw new ArgumentNullException(nameof(option));
}
if (rawObject == null)
{
throw new ArgumentNullException(nameof(rawObject));
}
CustomIncludePatterns = new List<string>();
CustomRemovePatterns = new List<string>();
SourceBasePath = sourceBasePath;
Option = option;
RawObject = rawObject;
var token = rawObject.Value<JToken>(option);
if (token == null)
{
IncludePatterns = new List<string>();
ExcludePatterns = new List<string>();
IncludeFiles = new List<string>();
ExcludeFiles = new List<string>();
}
else if (token.Type != JTokenType.Object)
{
IncludePatterns = CreateCollection(
sourceBasePath, option, ExtractValues(token), literalPath: false);
}
else
{
IncludePatterns = CreateCollection(
sourceBasePath, "include", ExtractValues(token.Value<JToken>("include")), literalPath: false);
ExcludePatterns = CreateCollection(
sourceBasePath, "exclude", ExtractValues(token.Value<JToken>("exclude")), literalPath: false);
IncludeFiles = CreateCollection(
sourceBasePath, "includeFiles", ExtractValues(token.Value<JToken>("includeFiles")), literalPath: true);
ExcludeFiles = CreateCollection(
sourceBasePath, "excludeFiles", ExtractValues(token.Value<JToken>("excludeFiles")), literalPath: true);
var builtIns = token.Value<JToken>("builtIns") as JObject;
if (builtIns != null)
{
BuiltInsInclude = CreateCollection(
sourceBasePath, "include", ExtractValues(builtIns.Value<JToken>("include")), literalPath: false);
BuiltInsExclude = CreateCollection(
sourceBasePath, "exclude", ExtractValues(builtIns.Value<JToken>("exclude")), literalPath: false);
}
var mappings = token.Value<JToken>("mappings") as JObject;
if (mappings != null)
{
Mappings = new Dictionary<string, IncludeContext>();
foreach (var map in mappings)
{
Mappings.Add(
map.Key,
new IncludeContext(
sourceBasePath,
map.Key,
mappings,
defaultBuiltInInclude: null,
defaultBuiltInExclude: null));
}
}
}
if (defaultBuiltInInclude != null &&
(BuiltInsInclude == null || !BuiltInsInclude.Any()))
{
BuiltInsInclude = defaultBuiltInInclude.ToList();
}
if (defaultBuiltInExclude != null &&
(BuiltInsExclude == null || !BuiltInsExclude.Any()))
{
BuiltInsExclude = defaultBuiltInExclude.ToList();
}
}
public string SourceBasePath { get; }
public string Option { get; }
public List<string> CustomIncludePatterns { get; }
public List<string> CustomRemovePatterns { get; }
public List<string> IncludePatterns { get; protected set; }
public List<string> ExcludePatterns { get; protected set; }
public List<string> IncludeFiles { get; protected set; }
public List<string> ExcludeFiles { get; protected set; }
public List<string> BuiltInsInclude { get; protected set; }
public List<string> BuiltInsExclude { get; protected set; }
public IDictionary<string, IncludeContext> Mappings { get; protected set; }
public JObject RawObject { get; }
public override bool Equals(object obj)
{
var other = obj as IncludeContext;
return other != null &&
SourceBasePath == other.SourceBasePath &&
Option == other.Option &&
EnumerableEquals(CustomIncludePatterns, other.CustomIncludePatterns) &&
EnumerableEquals(IncludePatterns, other.IncludePatterns) &&
EnumerableEquals(ExcludePatterns, other.ExcludePatterns) &&
EnumerableEquals(IncludeFiles, other.IncludeFiles) &&
EnumerableEquals(ExcludeFiles, other.ExcludeFiles) &&
EnumerableEquals(BuiltInsInclude, other.BuiltInsInclude) &&
EnumerableEquals(BuiltInsExclude, other.BuiltInsExclude) &&
EnumerableEquals(Mappings, other.Mappings);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
private static bool EnumerableEquals<T>(IEnumerable<T> left, IEnumerable<T> right)
=> Enumerable.SequenceEqual(left ?? EmptyArray<T>.Value, right ?? EmptyArray<T>.Value);
private static string[] ExtractValues(JToken token)
{
if (token != null)
{
if (token.Type == JTokenType.String)
{
return new string[] { token.Value<string>() };
}
else if (token.Type == JTokenType.Array)
{
return token.Values<string>().ToArray();
}
}
return new string[0];
}
internal static List<string> CreateCollection(
string projectDirectory,
string propertyName,
IEnumerable<string> patternsStrings,
bool literalPath)
{
var patterns = patternsStrings
.SelectMany(patternsString => GetSourcesSplit(patternsString))
.Select(patternString =>
patternString.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar));
foreach (var pattern in patterns)
{
if (Path.IsPathRooted(pattern))
{
throw new InvalidOperationException($"The '{propertyName}' property cannot be a rooted path.");
}
if (literalPath && pattern.Contains('*'))
{
throw new InvalidOperationException($"The '{propertyName}' property cannot contain wildcard characters.");
}
}
return new List<string>(patterns.Select(pattern => FolderToPattern(pattern, projectDirectory)));
}
private static IEnumerable<string> GetSourcesSplit(string sourceDescription)
{
if (string.IsNullOrEmpty(sourceDescription))
{
return Enumerable.Empty<string>();
}
return sourceDescription.Split(PatternSeparator, StringSplitOptions.RemoveEmptyEntries);
}
private static string FolderToPattern(string candidate, string projectDir)
{
// If it's already a pattern, no change is needed
if (candidate.Contains('*'))
{
return candidate;
}
// If the given string ends with a path separator, or it is an existing directory
// we convert this folder name to a pattern matching all files in the folder
if (candidate.EndsWith(@"\") ||
candidate.EndsWith("/") ||
Directory.Exists(Path.Combine(projectDir, candidate)))
{
return Path.Combine(candidate, "**", "*");
}
// Otherwise, it represents a single file
return candidate;
}
}
}

View file

@ -1,45 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.DotNet.PlatformAbstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
internal class IncludeEntry : IEquatable<IncludeEntry>
{
public string TargetPath { get; }
public string SourcePath { get; }
public bool IsCustomTarget { get; set; }
public IncludeEntry(string target, string source)
{
TargetPath = target;
SourcePath = source;
}
public override bool Equals(object obj)
{
return Equals((IncludeEntry)obj);
}
public override int GetHashCode()
{
var combiner = HashCodeCombiner.Start();
combiner.Add(TargetPath);
combiner.Add(SourcePath);
return combiner.CombinedHash;
}
public bool Equals(IncludeEntry other)
{
return other != null &&
string.Equals(TargetPath, other.TargetPath, StringComparison.Ordinal) &&
string.Equals(SourcePath, other.SourcePath, StringComparison.Ordinal) &&
IsCustomTarget == other.IsCustomTarget;
}
}
}

View file

@ -1,212 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.Utilities;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing.Abstractions;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
internal class IncludeFilesResolver
{
public static IEnumerable<IncludeEntry> GetIncludeFiles(IncludeContext context, string targetBasePath, IList<DiagnosticMessage> diagnostics)
{
return GetIncludeFiles(context, targetBasePath, diagnostics, flatten: false);
}
public static IEnumerable<IncludeEntry> GetIncludeFiles(
IncludeContext context,
string targetBasePath,
IList<DiagnosticMessage> diagnostics,
bool flatten)
{
var sourceBasePath = PathUtility.EnsureTrailingSlash(context.SourceBasePath);
targetBasePath = PathUtility.GetPathWithDirectorySeparator(targetBasePath);
var includeEntries = new HashSet<IncludeEntry>();
// Check for illegal characters in target path
if (string.IsNullOrEmpty(targetBasePath))
{
diagnostics?.Add(new DiagnosticMessage(
ErrorCodes.NU1003,
$"Invalid '{context.Option}' section. The target '{targetBasePath}' is invalid, " +
"targets must either be a file name or a directory suffixed with '/'. " +
"The root directory of the package can be specified by using a single '/' character.",
sourceBasePath,
DiagnosticMessageSeverity.Error));
}
else if (targetBasePath.Split(Path.DirectorySeparatorChar).Any(s => s.Equals(".") || s.Equals("..")))
{
diagnostics?.Add(new DiagnosticMessage(
ErrorCodes.NU1004,
$"Invalid '{context.Option}' section. " +
$"The target '{targetBasePath}' contains path-traversal characters ('.' or '..'). " +
"These characters are not permitted in target paths.",
sourceBasePath,
DiagnosticMessageSeverity.Error));
}
else
{
var files = GetIncludeFilesCore(
sourceBasePath,
context.IncludePatterns,
context.ExcludePatterns,
context.IncludeFiles,
context.BuiltInsInclude,
context.BuiltInsExclude).ToList();
var isFile = targetBasePath[targetBasePath.Length - 1] != Path.DirectorySeparatorChar;
if (isFile && files.Count > 1)
{
// It's a file. But the glob matched multiple things
diagnostics?.Add(new DiagnosticMessage(
ErrorCodes.NU1005,
$"Invalid '{ProjectFilesCollection.PackIncludePropertyName}' section. " +
$"The target '{targetBasePath}' refers to a single file, but the corresponding pattern " +
"produces multiple files. To mark the target as a directory, suffix it with '/'.",
sourceBasePath,
DiagnosticMessageSeverity.Error));
}
else if (isFile && files.Count > 0)
{
var filePath = Path.GetFullPath(
Path.Combine(sourceBasePath, PathUtility.GetPathWithDirectorySeparator(files[0].Path)));
includeEntries.Add(new IncludeEntry(targetBasePath, filePath));
}
else if (!isFile)
{
targetBasePath = targetBasePath.Substring(0, targetBasePath.Length - 1);
foreach (var file in files)
{
var fullPath = Path.GetFullPath(
Path.Combine(sourceBasePath, PathUtility.GetPathWithDirectorySeparator(file.Path)));
string targetPath;
if (flatten)
{
targetPath = Path.Combine(targetBasePath, PathUtility.GetPathWithDirectorySeparator(file.Stem));
}
else
{
targetPath = Path.Combine(
targetBasePath,
PathUtility.GetRelativePathIgnoringDirectoryTraversals(sourceBasePath, fullPath));
}
includeEntries.Add(new IncludeEntry(targetPath, fullPath));
}
}
if (context.IncludeFiles != null)
{
foreach (var literalRelativePath in context.IncludeFiles)
{
var fullPath = Path.GetFullPath(Path.Combine(sourceBasePath, literalRelativePath));
string targetPath;
if (isFile)
{
targetPath = targetBasePath;
}
else if (flatten)
{
targetPath = Path.Combine(targetBasePath, Path.GetFileName(fullPath));
}
else
{
targetPath = Path.Combine(targetBasePath, PathUtility.GetRelativePath(sourceBasePath, fullPath));
}
includeEntries.Add(new IncludeEntry(targetPath, fullPath));
}
}
if (context.ExcludeFiles != null)
{
var literalExcludedFiles = new HashSet<string>(
context.ExcludeFiles.Select(file => Path.GetFullPath(Path.Combine(sourceBasePath, file))),
StringComparer.Ordinal);
includeEntries.RemoveWhere(entry => literalExcludedFiles.Contains(entry.SourcePath));
}
}
if (context.Mappings != null)
{
// Finally add all the mappings
foreach (var map in context.Mappings)
{
var targetPath = Path.Combine(targetBasePath, PathUtility.GetPathWithDirectorySeparator(map.Key));
foreach (var file in GetIncludeFiles(map.Value, targetPath, diagnostics, flatten: true))
{
file.IsCustomTarget = true;
// Prefer named targets over default ones
includeEntries.RemoveWhere(f => string.Equals(f.SourcePath, file.SourcePath) && !f.IsCustomTarget);
includeEntries.Add(file);
}
}
}
return includeEntries;
}
private static IEnumerable<FilePatternMatch> GetIncludeFilesCore(
string sourceBasePath,
List<string> includePatterns,
List<string> excludePatterns,
List<string> includeFiles,
List<string> builtInsInclude,
List<string> builtInsExclude)
{
var literalIncludedFiles = new List<string>();
if (includeFiles != null)
{
// literal included files are added at the last, but the search happens early
// so as to make the process fail early in case there is missing file. fail early
// helps to avoid unnecessary globing for performance optimization
foreach (var literalRelativePath in includeFiles)
{
var fullPath = Path.GetFullPath(Path.Combine(sourceBasePath, literalRelativePath));
if (!File.Exists(fullPath))
{
throw new InvalidOperationException(string.Format("Can't find file {0}", literalRelativePath));
}
literalIncludedFiles.Add(fullPath);
}
}
// Globbing
var matcher = new Matcher();
if (builtInsInclude != null)
{
matcher.AddIncludePatterns(builtInsInclude);
}
if (includePatterns != null)
{
matcher.AddIncludePatterns(includePatterns);
}
if (builtInsExclude != null)
{
matcher.AddExcludePatterns(builtInsExclude);
}
if (excludePatterns != null)
{
matcher.AddExcludePatterns(excludePatterns);
}
return matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(sourceBasePath))).Files;
}
}
}

View file

@ -1,75 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
internal static class NamedResourceReader
{
public static IDictionary<string, string> ReadNamedResources(JObject rawProject, string projectFilePath)
{
JToken namedResourceToken;
if (!rawProject.TryGetValue("namedResource", out namedResourceToken))
{
return new Dictionary<string, string>();
}
if (namedResourceToken.Type != JTokenType.Object)
{
throw FileFormatException.Create(
"Value must be object.",
rawProject.Value<JToken>("namedResource"), projectFilePath);
}
var namedResources = new Dictionary<string, string>();
foreach (var namedResource in (JObject)namedResourceToken)
{
if (namedResource.Value.Type != JTokenType.String)
{
throw FileFormatException.Create("Value must be string.", namedResource.Key, projectFilePath);
}
var resourcePath = namedResource.Value.ToString();
if (resourcePath.Contains("*"))
{
throw FileFormatException.Create("Value cannot contain wildcards.", resourcePath, projectFilePath);
}
var resourceFileFullPath =
Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectFilePath), resourcePath));
if (namedResources.ContainsKey(namedResource.Key))
{
throw FileFormatException.Create(
string.Format("The named resource {0} already exists.", namedResource.Key),
resourcePath,
projectFilePath);
}
namedResources.Add(namedResource.Key, resourceFileFullPath);
}
return namedResources;
}
public static void ApplyNamedResources(IDictionary<string, string> namedResources, IDictionary<string, string> resources)
{
foreach (var namedResource in namedResources)
{
// The named resources dictionary is like the project file
// key = name, value = path to resource
if (resources.ContainsKey(namedResource.Value))
{
resources[namedResource.Value] = namedResource.Key;
}
else
{
resources.Add(namedResource.Value, namedResource.Key);
}
}
}
}
}

View file

@ -1,49 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
internal class PackIncludeEntry
{
public string Target { get; }
public string[] SourceGlobs { get; }
public int Line { get; }
public int Column { get; }
internal PackIncludeEntry(string target, JToken json)
{
Target = target;
SourceGlobs = ExtractValues(json);
var lineInfo = (IJsonLineInfo)json;
Line = lineInfo.LineNumber;
Column = lineInfo.LinePosition;
}
public PackIncludeEntry(string target, string[] sourceGlobs, int line, int column)
{
Target = target;
SourceGlobs = sourceGlobs;
Line = line;
Column = column;
}
private static string[] ExtractValues(JToken json)
{
if (json.Type == JTokenType.String)
{
return new string[] { json.Value<string>() };
}
if (json.Type == JTokenType.Array)
{
return json.Select(v => v.ToString()).ToArray();
}
return new string[0];
}
}
}

View file

@ -1,123 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.FileSystemGlobbing;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
internal class PatternGroup
{
private readonly List<PatternGroup> _excludeGroups = new List<PatternGroup>();
private readonly Matcher _matcher = new Matcher();
internal PatternGroup(IEnumerable<string> includePatterns)
{
IncludeLiterals = Enumerable.Empty<string>();
IncludePatterns = includePatterns;
ExcludePatterns = Enumerable.Empty<string>();
_matcher.AddIncludePatterns(IncludePatterns);
}
internal PatternGroup(IEnumerable<string> includePatterns, IEnumerable<string> excludePatterns, IEnumerable<string> includeLiterals)
{
IncludeLiterals = includeLiterals;
IncludePatterns = includePatterns;
ExcludePatterns = excludePatterns;
_matcher.AddIncludePatterns(IncludePatterns);
_matcher.AddExcludePatterns(ExcludePatterns);
}
internal static PatternGroup Build(JObject rawProject,
string projectDirectory,
string projectFilePath,
string name,
IEnumerable<string> fallbackIncluding = null,
IEnumerable<string> additionalIncluding = null,
IEnumerable<string> additionalExcluding = null,
bool includePatternsOnly = false,
ICollection<DiagnosticMessage> warnings = null)
{
string includePropertyName = name;
additionalIncluding = additionalIncluding ?? Enumerable.Empty<string>();
var includePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, includePropertyName, defaultPatterns: fallbackIncluding)
.Concat(additionalIncluding)
.Distinct();
if (includePatternsOnly)
{
return new PatternGroup(includePatterns);
}
additionalExcluding = additionalExcluding ?? Enumerable.Empty<string>();
var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Exclude")
.Concat(additionalExcluding)
.Distinct();
var includeLiterals = PatternsCollectionHelper.GetPatternsCollection(rawProject, projectDirectory, projectFilePath, propertyName: name + "Files", literalPath: true)
.Distinct();
return new PatternGroup(includePatterns, excludePatterns, includeLiterals);
}
public IEnumerable<string> IncludeLiterals { get; }
public IEnumerable<string> IncludePatterns { get; }
public IEnumerable<string> ExcludePatterns { get; }
public IEnumerable<PatternGroup> ExcludePatternsGroup { get { return _excludeGroups; } }
public PatternGroup ExcludeGroup(PatternGroup group)
{
_excludeGroups.Add(group);
return this;
}
public IEnumerable<string> SearchFiles(string rootPath)
{
// literal included files are added at the last, but the search happens early
// so as to make the process fail early in case there is missing file. fail early
// helps to avoid unnecessary globing for performance optimization
var literalIncludedFiles = new List<string>();
foreach (var literalRelativePath in IncludeLiterals)
{
var fullPath = Path.GetFullPath(Path.Combine(rootPath, literalRelativePath));
if (!File.Exists(fullPath))
{
throw new InvalidOperationException(string.Format("Can't find file {0}", literalRelativePath));
}
// TODO: extract utility like NuGet.PathUtility.GetPathWithForwardSlashes()
literalIncludedFiles.Add(fullPath.Replace('\\', '/'));
}
// globing files
var globbingResults = _matcher.GetResultsInFullPath(rootPath);
// if there is no results generated in globing, skip excluding other groups
// for performance optimization.
if (globbingResults.Any())
{
foreach (var group in _excludeGroups)
{
globbingResults = globbingResults.Except(group.SearchFiles(rootPath));
}
}
return globbingResults.Concat(literalIncludedFiles).Distinct();
}
public override string ToString()
{
return string.Format("Pattern group: Literals [{0}] Includes [{1}] Excludes [{2}]", string.Join(", ", IncludeLiterals), string.Join(", ", IncludePatterns), string.Join(", ", ExcludePatterns));
}
}
}

View file

@ -1,54 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
internal static class PatternsCollectionHelper
{
private static readonly char[] PatternSeparator = new[] { ';' };
public static IEnumerable<string> GetPatternsCollection(JObject rawProject,
string projectDirectory,
string projectFilePath,
string propertyName,
IEnumerable<string> defaultPatterns = null,
bool literalPath = false)
{
defaultPatterns = defaultPatterns ?? Enumerable.Empty<string>();
try
{
JToken propertyNameToken;
if (!rawProject.TryGetValue(propertyName, out propertyNameToken))
{
return IncludeContext.CreateCollection(
projectDirectory, propertyName, defaultPatterns, literalPath);
}
if (propertyNameToken.Type == JTokenType.String)
{
return IncludeContext.CreateCollection(
projectDirectory, propertyName, new string[] { propertyNameToken.Value<string>() }, literalPath);
}
if (propertyNameToken.Type == JTokenType.Array)
{
var valuesInArray = propertyNameToken.Values<string>();
return IncludeContext.CreateCollection(
projectDirectory, propertyName, valuesInArray.Select(s => s.ToString()), literalPath);
}
}
catch (Exception ex)
{
throw FileFormatException.Create(ex, rawProject.Value<JToken>(propertyName), projectFilePath);
}
throw FileFormatException.Create("Value must be either string or array.", rawProject.Value<JToken>(propertyName), projectFilePath);
}
}
}

View file

@ -1,193 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel.Files
{
internal class ProjectFilesCollection
{
public static readonly string[] SdkInjectedDefaultCompileBuiltInPatterns = new[] { @"**/*.cs" };
public static readonly string[] DefaultPreprocessPatterns = new[] { @"compiler/preprocess/**/*.cs" };
public static readonly string[] DefaultSharedPatterns = new[] { @"compiler/shared/**/*.cs" };
public static readonly string[] DefaultBuiltInExcludePatterns = new[] { "bin/**", "obj/**", "**/*.xproj", "packages/**" };
public static readonly string PackIncludePropertyName = "packInclude";
private PatternGroup _sharedPatternsGroup;
private PatternGroup _resourcePatternsGroup;
private PatternGroup _preprocessPatternsGroup;
private PatternGroup _compilePatternsGroup;
private PatternGroup _contentPatternsGroup;
private IDictionary<string, string> _namedResources;
private IEnumerable<string> _publishExcludePatterns;
private IEnumerable<PackIncludeEntry> _packInclude;
private readonly string _projectDirectory;
private readonly string _projectFilePath;
private JObject _rawProject;
private bool _initialized;
internal ProjectFilesCollection(JObject rawProject, string projectDirectory, string projectFilePath)
{
_projectDirectory = projectDirectory;
_projectFilePath = projectFilePath;
_rawProject = rawProject;
}
internal void EnsureInitialized()
{
if (_initialized)
{
return;
}
var excludeBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "excludeBuiltIn", DefaultBuiltInExcludePatterns);
var excludePatterns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "exclude")
.Concat(excludeBuiltIns);
var contentBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "contentBuiltIn");
var compileBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "compileBuiltIn", SdkInjectedDefaultCompileBuiltInPatterns);
var resourceBuiltIns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "resourceBuiltIn");
_publishExcludePatterns = PatternsCollectionHelper.GetPatternsCollection(_rawProject, _projectDirectory, _projectFilePath, "publishExclude");
_sharedPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "shared", fallbackIncluding: DefaultSharedPatterns, additionalExcluding: excludePatterns);
_resourcePatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "resource", additionalIncluding: resourceBuiltIns, additionalExcluding: excludePatterns);
_preprocessPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "preprocess", fallbackIncluding: DefaultPreprocessPatterns, additionalExcluding: excludePatterns)
.ExcludeGroup(_sharedPatternsGroup)
.ExcludeGroup(_resourcePatternsGroup);
_compilePatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "compile", additionalIncluding: compileBuiltIns, additionalExcluding: excludePatterns)
.ExcludeGroup(_sharedPatternsGroup)
.ExcludeGroup(_preprocessPatternsGroup)
.ExcludeGroup(_resourcePatternsGroup);
_contentPatternsGroup = PatternGroup.Build(_rawProject, _projectDirectory, _projectFilePath, "content", additionalIncluding: contentBuiltIns, additionalExcluding: _publishExcludePatterns);
_namedResources = NamedResourceReader.ReadNamedResources(_rawProject, _projectFilePath);
// Files to be packed along with the project
var packIncludeJson = _rawProject.Value<JToken>(PackIncludePropertyName) as JObject;
if (packIncludeJson != null)
{
var packIncludeEntries = new List<PackIncludeEntry>();
foreach (var token in packIncludeJson)
{
packIncludeEntries.Add(new PackIncludeEntry(token.Key, token.Value));
}
_packInclude = packIncludeEntries;
}
else
{
_packInclude = new List<PackIncludeEntry>();
}
_initialized = true;
_rawProject = null;
}
public IEnumerable<PackIncludeEntry> PackInclude
{
get
{
EnsureInitialized();
return _packInclude;
}
}
public IEnumerable<string> SourceFiles
{
get { return CompilePatternsGroup.SearchFiles(_projectDirectory).Distinct(); }
}
public IEnumerable<string> PreprocessSourceFiles
{
get { return PreprocessPatternsGroup.SearchFiles(_projectDirectory).Distinct(); }
}
public IDictionary<string, string> ResourceFiles
{
get
{
var resources = ResourcePatternsGroup
.SearchFiles(_projectDirectory)
.Distinct()
.ToDictionary(res => res, res => (string)null);
NamedResourceReader.ApplyNamedResources(_namedResources, resources);
return resources;
}
}
public IEnumerable<string> SharedFiles
{
get { return SharedPatternsGroup.SearchFiles(_projectDirectory).Distinct(); }
}
public IEnumerable<string> GetContentFiles(IEnumerable<string> additionalExcludePatterns = null)
{
var patternGroup = new PatternGroup(ContentPatternsGroup.IncludePatterns,
ContentPatternsGroup.ExcludePatterns.Concat(additionalExcludePatterns ?? new List<string>()),
ContentPatternsGroup.IncludeLiterals);
foreach (var excludedGroup in ContentPatternsGroup.ExcludePatternsGroup)
{
patternGroup.ExcludeGroup(excludedGroup);
}
return patternGroup.SearchFiles(_projectDirectory);
}
internal PatternGroup CompilePatternsGroup
{
get
{
EnsureInitialized();
return _compilePatternsGroup;
}
}
internal PatternGroup SharedPatternsGroup
{
get
{
EnsureInitialized();
return _sharedPatternsGroup;
}
}
internal PatternGroup ResourcePatternsGroup
{
get
{
EnsureInitialized();
return _resourcePatternsGroup;
}
}
internal PatternGroup PreprocessPatternsGroup
{
get
{
EnsureInitialized();
return _preprocessPatternsGroup;
}
}
internal PatternGroup ContentPatternsGroup
{
get
{
EnsureInitialized();
return _contentPatternsGroup;
}
}
}
}

View file

@ -1,105 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using System.Linq;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class GlobalSettings
{
public const string FileName = "global.json";
public IList<string> ProjectSearchPaths { get; private set; }
public string PackagesPath { get; private set; }
public string FilePath { get; private set; }
public string DirectoryPath
{
get
{
return Path.GetFullPath(Path.GetDirectoryName(FilePath));
}
}
public static bool TryGetGlobalSettings(string path, out GlobalSettings globalSettings)
{
globalSettings = null;
string globalJsonPath = null;
if (Path.GetFileName(path) == FileName)
{
globalJsonPath = path;
path = Path.GetDirectoryName(path);
}
else if (!HasGlobalFile(path))
{
return false;
}
else
{
globalJsonPath = Path.Combine(path, FileName);
}
try
{
using (var fs = File.OpenRead(globalJsonPath))
{
globalSettings = GetGlobalSettings(fs, globalJsonPath);
}
}
catch (Exception ex)
{
throw FileFormatException.Create(ex, globalJsonPath);
}
return true;
}
public static GlobalSettings GetGlobalSettings(Stream fs, string globalJsonPath)
{
var globalSettings = new GlobalSettings();
var reader = new StreamReader(fs);
JObject jobject;
try
{
jobject = JObject.Parse(reader.ReadToEnd());
}
catch (JsonReaderException)
{
throw new InvalidOperationException("The JSON file can't be deserialized to a JSON object.");
}
IEnumerable<string> projectSearchPaths = Enumerable.Empty<string>();
JToken projectSearchPathsToken;
if (jobject.TryGetValue("projects", out projectSearchPathsToken) &&
projectSearchPathsToken.Type == JTokenType.Array)
{
projectSearchPaths = projectSearchPathsToken.Values<string>();
}
else if (jobject.TryGetValue("sources", out projectSearchPathsToken) &&
projectSearchPathsToken.Type == JTokenType.Array)
{
projectSearchPaths = projectSearchPathsToken.Values<string>();
}
globalSettings.ProjectSearchPaths = new List<string>(projectSearchPaths);
globalSettings.PackagesPath = jobject.Value<string>("packages");
globalSettings.FilePath = globalJsonPath;
return globalSettings;
}
public static bool HasGlobalFile(string path)
{
string projectPath = Path.Combine(path, FileName);
return File.Exists(projectPath);
}
}
}

View file

@ -1,26 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Linq;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Internal.ProjectModel.Graph
{
internal class ExportFile
{
public static readonly string ExportFileName = "project.fragment.lock.json";
public int Version { get; }
public string ExportFilePath { get; }
public IList<LockFileTargetLibrary> Exports { get; }
public ExportFile(string exportFilePath, int version, IList<LockFileTargetLibrary> exports)
{
ExportFilePath = exportFilePath;
Version = version;
Exports = exports.Any() ? exports : new List<LockFileTargetLibrary>(0);
}
}
}

View file

@ -1,76 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Internal.ProjectModel.Graph
{
internal static class LockFileExtensions
{
public static readonly int CurrentVersion = 2;
public static bool IsValidForProject(this LockFile lockFile, Project project)
{
string message;
return lockFile.IsValidForProject(project, out message);
}
public static bool IsValidForProject(this LockFile lockFile, Project project, out string message)
{
if (lockFile.Version != CurrentVersion)
{
message = $"The expected lock file version does not match the actual version";
return false;
}
message = $"Dependencies in {Project.FileName} were modified";
var actualTargetFrameworks = project.GetTargetFrameworks();
// The lock file should contain dependencies for each framework plus dependencies shared by all frameworks
if (lockFile.ProjectFileDependencyGroups.Count != actualTargetFrameworks.Count() + 1)
{
Console.WriteLine($"Different count; {lockFile.ProjectFileDependencyGroups.Count} != {actualTargetFrameworks.Count() + 1}");
return false;
}
foreach (var group in lockFile.ProjectFileDependencyGroups)
{
IOrderedEnumerable<string> actualDependencies;
var expectedDependencies = group.Dependencies.OrderBy(x => x);
// If the framework name is empty, the associated dependencies are shared by all frameworks
if (string.IsNullOrEmpty(group.FrameworkName))
{
actualDependencies = project.Dependencies
.Select(d => d.LibraryRange.ToLockFileDependencyGroupString())
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase);
}
else
{
var framework = actualTargetFrameworks
.FirstOrDefault(f => Equals(f.FrameworkName.DotNetFrameworkName, group.FrameworkName));
if (framework == null)
{
return false;
}
actualDependencies = framework.Dependencies
.Select(d => d.LibraryRange.ToLockFileDependencyGroupString())
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase);
}
if (!actualDependencies.SequenceEqual(expectedDependencies))
{
Console.WriteLine($"ActualDependencies don't match");
return false;
}
}
message = null;
return true;
}
}
}

View file

@ -1,66 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using NuGet.LibraryModel;
using NuGet.ProjectModel;
using NuGet.Versioning;
namespace Microsoft.DotNet.Internal.ProjectModel.Graph
{
internal class LockFileLookup
{
// REVIEW: Case sensitivity?
private readonly Dictionary<Tuple<string, NuGetVersion>, LockFileLibrary> _packages;
private readonly Dictionary<string, LockFileLibrary> _projects;
public LockFileLookup(LockFile lockFile)
{
_packages = new Dictionary<Tuple<string, NuGetVersion>, LockFileLibrary>();
_projects = new Dictionary<string, LockFileLibrary>();
foreach (var library in lockFile.Libraries)
{
var libraryType = LibraryType.Parse(library.Type);
if (libraryType == LibraryType.Package)
{
_packages[Tuple.Create(library.Name, library.Version)] = library;
}
if (libraryType == LibraryType.Project)
{
_projects[library.Name] = library;
}
}
}
public LockFileLibrary GetProject(string name)
{
LockFileLibrary project;
if (_projects.TryGetValue(name, out project))
{
return project;
}
return null;
}
public LockFileLibrary GetPackage(string id, NuGetVersion version)
{
LockFileLibrary package;
if (_packages.TryGetValue(Tuple.Create(id, version), out package))
{
return package;
}
return null;
}
public void Clear()
{
_packages.Clear();
_projects.Clear();
}
}
}

View file

@ -1,23 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using NuGet.LibraryModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class ProjectLibraryDependency : LibraryDependency
{
public string SourceFilePath { get; set; }
public int SourceLine { get; set; }
public int SourceColumn { get; set; }
public ProjectLibraryDependency()
{
}
public ProjectLibraryDependency(LibraryRange libraryRange)
{
LibraryRange = libraryRange;
}
}
}

View file

@ -1,10 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal interface IProjectReader
{
Project ReadProject(string projectPath, ProjectReaderSettings settings = null);
}
}

View file

@ -1,14 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static class EmptyArray<T>
{
#if NET451
public static readonly T[] Value = new T[0];
#else
public static readonly T[] Value = System.Array.Empty<T>();
#endif
}
}

View file

@ -1,77 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.PlatformAbstractions;
using NuGet.Frameworks;
using NuGet.LibraryModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
/// <summary>
/// Represents the result of resolving the library
/// </summary>
internal class LibraryDescription
{
public LibraryDescription(
LibraryIdentity identity,
string hash,
string path,
IEnumerable<ProjectLibraryDependency> dependencies,
NuGetFramework framework,
bool resolved,
bool compatible)
{
Path = path;
Identity = identity;
Hash = hash;
Dependencies = dependencies ?? Enumerable.Empty<ProjectLibraryDependency>();
Framework = framework;
Resolved = resolved;
Compatible = compatible;
}
public LibraryIdentity Identity { get; }
public string Hash { get; }
public HashSet<ProjectLibraryDependency> RequestedRanges { get; } =
new HashSet<ProjectLibraryDependency>(new LibraryRangeEqualityComparer());
public List<LibraryDescription> Parents { get; } = new List<LibraryDescription>();
public string Path { get; }
public IEnumerable<ProjectLibraryDependency> Dependencies { get; }
public bool Compatible { get; }
public NuGetFramework Framework { get; set; }
public bool Resolved { get; set; }
public override string ToString()
{
return $"{Identity} ({Identity.Type}) = {Path}";
}
// For diagnostics, we don't want to duplicate requested dependencies so we
// dedupe dependencies defined in project.json
private class LibraryRangeEqualityComparer : IEqualityComparer<ProjectLibraryDependency>
{
public bool Equals(ProjectLibraryDependency x, ProjectLibraryDependency y)
{
return x.Equals(y) &&
x.SourceColumn == y.SourceColumn &&
x.SourceLine == y.SourceLine &&
string.Equals(x.SourceFilePath, y.SourceFilePath, StringComparison.Ordinal);
}
public int GetHashCode(ProjectLibraryDependency obj)
{
var combiner = HashCodeCombiner.Start();
combiner.Add(obj);
combiner.Add(obj.SourceFilePath);
combiner.Add(obj.SourceLine);
combiner.Add(obj.SourceColumn);
return combiner.CombinedHash;
}
}
}
}

View file

@ -1,49 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using NuGet.LibraryModel;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
/// <summary>
/// Represents an MSBuild project.
/// It has been invisibly built by MSBuild, so it behaves like a package: can provide all assets up front
///
/// Path points to the project's directory
/// MSBuildPRojectPath points to the csproj file
/// </summary>
internal class MSBuildProjectDescription : TargetLibraryWithAssets
{
public MSBuildProjectDescription(
string path,
string msbuildProjectPath,
LockFileLibrary projectLibrary,
LockFileTargetLibrary lockFileLibrary,
Project projectFile,
IEnumerable<ProjectLibraryDependency> dependencies,
bool compatible,
bool resolved)
: base(
new LibraryIdentity(projectLibrary.Name, projectLibrary.Version, LibraryType.Project),
string.Empty, //msbuild projects don't have hashes
path,
lockFileLibrary,
dependencies,
resolved: resolved,
compatible: compatible,
framework: null)
{
MSBuildProjectPath = msbuildProjectPath;
ProjectFile = projectFile;
ProjectLibrary = projectLibrary;
}
public LockFileLibrary ProjectLibrary { get; }
public string MSBuildProjectPath { get; set; }
public Project ProjectFile { get; }
}
}

View file

@ -1,58 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class OutputPaths
{
private readonly string _runtimePath;
private readonly RuntimeOutputFiles _runtimeFiles;
public OutputPaths(string intermediateOutputDirectoryPath,
string compilationOutputPath,
string runtimePath,
CompilationOutputFiles compilationFiles,
RuntimeOutputFiles runtimeFiles)
{
_runtimePath = runtimePath;
_runtimeFiles = runtimeFiles;
CompilationOutputPath = compilationOutputPath;
IntermediateOutputDirectoryPath = intermediateOutputDirectoryPath;
CompilationFiles = compilationFiles;
}
public string CompilationOutputPath { get; }
public string IntermediateOutputDirectoryPath { get; }
public string RuntimeOutputPath
{
get
{
if (_runtimePath == null)
{
throw new InvalidOperationException(
$"Cannot get runtime output path for {nameof(OutputPaths)} with no runtime set");
}
return _runtimePath;
}
}
public CompilationOutputFiles CompilationFiles { get; }
public RuntimeOutputFiles RuntimeFiles
{
get
{
if (_runtimeFiles == null)
{
throw new InvalidOperationException(
$"Cannot get runtime output files for {nameof(OutputPaths)} with no runtime set");
}
return _runtimeFiles;
}
}
}
}

View file

@ -1,77 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.IO;
using Microsoft.DotNet.Internal.ProjectModel.Utilities;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class OutputPathsCalculator
{
private const string ObjDirectoryName = "obj";
private const string BinDirectoryName = "bin";
public static OutputPaths GetOutputPaths(
Project project,
NuGetFramework framework,
string runtimeIdentifier,
string configuration,
string solutionRootPath,
string buildBasePath,
string outputPath)
{
string resolvedBuildBasePath;
if (string.IsNullOrEmpty(buildBasePath))
{
resolvedBuildBasePath = project.ProjectDirectory;
}
else
{
if (string.IsNullOrEmpty(solutionRootPath))
{
resolvedBuildBasePath = Path.Combine(buildBasePath, project.Name);
}
else
{
resolvedBuildBasePath = project.ProjectDirectory.Replace(solutionRootPath, buildBasePath);
}
}
var compilationOutputPath = PathUtility.EnsureTrailingSlash(Path.Combine(resolvedBuildBasePath,
BinDirectoryName,
configuration,
framework.GetShortFolderName()));
string runtimeOutputPath = null;
if (string.IsNullOrEmpty(outputPath))
{
if (!string.IsNullOrEmpty(runtimeIdentifier))
{
runtimeOutputPath = PathUtility.EnsureTrailingSlash(Path.Combine(compilationOutputPath, runtimeIdentifier));
}
else
{
// "Runtime" assets (i.e. the deps file) will be dropped to the compilation output path, because
// we are building a RID-less target.
runtimeOutputPath = compilationOutputPath;
}
}
else
{
runtimeOutputPath = PathUtility.EnsureTrailingSlash(Path.GetFullPath(outputPath));
}
var intermediateOutputPath = PathUtility.EnsureTrailingSlash(Path.Combine(
resolvedBuildBasePath,
ObjDirectoryName,
configuration,
framework.GetTwoDigitShortFolderName()));
var compilationFiles = new CompilationOutputFiles(compilationOutputPath, project, configuration, framework);
RuntimeOutputFiles runtimeFiles = new RuntimeOutputFiles(runtimeOutputPath, project, configuration, framework, runtimeIdentifier);
return new OutputPaths(intermediateOutputPath, compilationOutputPath, runtimeOutputPath, compilationFiles, runtimeFiles);
}
}
}

View file

@ -1,32 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.Internal.ProjectModel.Files;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class PackOptions
{
public string[] Tags { get; set; }
public string[] Owners { get; set; }
public string ReleaseNotes { get; set; }
public string IconUrl { get; set; }
public string ProjectUrl { get; set; }
public string LicenseUrl { get; set; }
public bool RequireLicenseAcceptance { get; set; }
public string RepositoryType { get; set; }
public string RepositoryUrl { get; set; }
public string Summary { get; set; }
public IncludeContext PackInclude { get; set; }
}
}

View file

@ -1,53 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.Resolution;
using NuGet.LibraryModel;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class PackageDescription : TargetLibraryWithAssets
{
public PackageDescription(
string path,
string hashPath,
LockFileLibrary package,
LockFileTargetLibrary lockFileLibrary,
IEnumerable<ProjectLibraryDependency> dependencies,
bool compatible,
bool resolved)
: base(
new LibraryIdentity(package.Name, package.Version, LibraryType.Package),
"sha512-" + package.Sha512,
path,
lockFileLibrary,
dependencies,
resolved: resolved,
compatible: compatible,
framework: null)
{
HashPath = hashPath;
PackageLibrary = package;
}
public string HashPath { get; }
public LockFileLibrary PackageLibrary { get; }
public override IEnumerable<LockFileItem> RuntimeAssemblies => FilterPlaceholders(base.RuntimeAssemblies);
public override IEnumerable<LockFileItem> CompileTimeAssemblies => FilterPlaceholders(base.CompileTimeAssemblies);
public bool HasCompileTimePlaceholder =>
base.CompileTimeAssemblies.Any() &&
base.CompileTimeAssemblies.All(a => PackageDependencyProvider.IsPlaceholderFile(a.Path));
private static IEnumerable<LockFileItem> FilterPlaceholders(IEnumerable<LockFileItem> items)
{
return items.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a.Path));
}
}
}

View file

@ -1,156 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.DotNet.Internal.ProjectModel.Files;
using NuGet.Frameworks;
using NuGet.Versioning;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class Project
{
public static readonly string FileName = "project.json";
// REVIEW: It's kinda hacky making these internal but the reader needs to set them
internal Dictionary<NuGetFramework, TargetFrameworkInformation> _targetFrameworks = new Dictionary<NuGetFramework, TargetFrameworkInformation>();
internal Dictionary<string, CommonCompilerOptions> _compilerOptionsByConfiguration = new Dictionary<string, CommonCompilerOptions>(StringComparer.OrdinalIgnoreCase);
internal CommonCompilerOptions _defaultCompilerOptions;
internal TargetFrameworkInformation _defaultTargetFrameworkConfiguration;
public Project()
{
}
public string ProjectFilePath { get; set; }
public string ProjectDirectory
{
get
{
return Path.GetDirectoryName(ProjectFilePath);
}
}
public AnalyzerOptions AnalyzerOptions { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Copyright { get; set; }
public string Language { get; set; }
public string[] Authors { get; set; }
public bool EmbedInteropTypes { get; set; }
public NuGetVersion Version { get; set; }
public Version AssemblyFileVersion { get; set; }
public IList<ProjectLibraryDependency> Dependencies { get; set; }
public List<ProjectLibraryDependency> Tools { get; set; }
public string EntryPoint { get; set; }
public string TestRunner { get; set; }
public ProjectFilesCollection Files { get; set; }
public PackOptions PackOptions { get; set; }
public bool Serviceable { get; set; }
public RuntimeOptions RuntimeOptions { get; set; }
public IList<string> Runtimes { get; set; }
public IDictionary<string, string> Commands { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public IDictionary<string, IEnumerable<string>> Scripts { get; } = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase);
public string RawRuntimeOptions { get; set; }
public IncludeContext PublishOptions { get; set; }
public List<DiagnosticMessage> Diagnostics { get; } = new List<DiagnosticMessage>();
public bool IsTestProject => !string.IsNullOrEmpty(TestRunner);
public IEnumerable<TargetFrameworkInformation> GetTargetFrameworks()
{
return _targetFrameworks.Values;
}
public IEnumerable<string> GetConfigurations()
{
return _compilerOptionsByConfiguration.Keys;
}
public CommonCompilerOptions GetCompilerOptions(NuGetFramework targetFramework, string configurationName)
{
// Get all project options and combine them
var rootOptions = GetCompilerOptions();
var configurationOptions = configurationName != null ? GetRawCompilerOptions(configurationName) : null;
var targetFrameworkOptions = targetFramework != null ? GetRawCompilerOptions(targetFramework) : null;
// Combine all of the options
var compilerOptions = CommonCompilerOptions.Combine(rootOptions, configurationOptions, targetFrameworkOptions);
if (compilerOptions.OutputName == null)
{
compilerOptions.OutputName = Name;
}
return compilerOptions;
}
public TargetFrameworkInformation GetTargetFramework(NuGetFramework targetFramework)
{
TargetFrameworkInformation targetFrameworkInfo = null;
if (targetFramework != null && _targetFrameworks.TryGetValue(targetFramework, out targetFrameworkInfo))
{
return targetFrameworkInfo;
}
return targetFrameworkInfo ?? _defaultTargetFrameworkConfiguration;
}
public bool HasRuntimeOutput(string configuration)
{
var compilerOptions = GetCompilerOptions(targetFramework: null, configurationName: configuration);
// TODO: Make this opt in via another mechanism
return compilerOptions.EmitEntryPoint.GetValueOrDefault() || IsTestProject;
}
private CommonCompilerOptions GetCompilerOptions()
{
return _defaultCompilerOptions;
}
internal CommonCompilerOptions GetRawCompilerOptions(string configurationName)
{
CommonCompilerOptions options;
if (_compilerOptionsByConfiguration.TryGetValue(configurationName, out options))
{
return options;
}
return null;
}
internal CommonCompilerOptions GetRawCompilerOptions(NuGetFramework frameworkName)
{
return GetTargetFramework(frameworkName)?.CompilerOptions;
}
}
}

View file

@ -1,171 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.Compilation;
using Microsoft.DotNet.Internal.ProjectModel.Resolution;
using NuGet.Frameworks;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class ProjectContext
{
private string[] _runtimeFallbacks;
public ProjectContextIdentity Identity { get; }
public GlobalSettings GlobalSettings { get; }
public ProjectDescription RootProject { get; }
public NuGetFramework TargetFramework { get; }
public LibraryDescription PlatformLibrary { get; }
public bool IsPortable { get; }
public string RuntimeIdentifier { get; }
public Project ProjectFile => RootProject?.Project;
public LockFile LockFile { get; }
public string RootDirectory => GlobalSettings?.DirectoryPath;
public string ProjectDirectory => ProjectFile?.ProjectDirectory;
public string PackagesDirectory { get; }
public LibraryManager LibraryManager { get; }
public List<DiagnosticMessage> Diagnostics { get; }
internal ProjectContext(
GlobalSettings globalSettings,
ProjectDescription rootProject,
LibraryDescription platformLibrary,
NuGetFramework targetFramework,
bool isPortable,
string runtimeIdentifier,
string packagesDirectory,
LibraryManager libraryManager,
LockFile lockfile,
List<DiagnosticMessage> diagnostics)
{
Identity = new ProjectContextIdentity(rootProject?.Path, targetFramework);
GlobalSettings = globalSettings;
RootProject = rootProject;
PlatformLibrary = platformLibrary;
TargetFramework = targetFramework;
RuntimeIdentifier = runtimeIdentifier;
PackagesDirectory = packagesDirectory;
LibraryManager = libraryManager;
LockFile = lockfile;
IsPortable = isPortable;
Diagnostics = diagnostics;
}
public LibraryExporter CreateExporter(string configuration, string buildBasePath = null)
{
if (IsPortable && RuntimeIdentifier != null && _runtimeFallbacks == null)
{
var graph = RuntimeGraphCollector.Collect(LibraryManager.GetLibraries());
_runtimeFallbacks = graph.ExpandRuntime(RuntimeIdentifier).ToArray();
}
return new LibraryExporter(RootProject,
LibraryManager,
configuration,
RuntimeIdentifier,
_runtimeFallbacks,
buildBasePath,
RootDirectory);
}
/// <summary>
/// Creates a project context for the project located at <paramref name="projectPath"/>,
/// specifically in the context of the framework specified in <paramref name="framework"/>
/// </summary>
public static ProjectContext Create(string projectPath, NuGetFramework framework)
{
return Create(projectPath, framework, Enumerable.Empty<string>());
}
/// <summary>
/// Creates a project context for the project located at <paramref name="projectPath"/>,
/// specifically in the context of the framework specified in <paramref name="framework"/>
/// and the candidate runtime identifiers specified in <param name="runtimeIdentifiers"/>
/// </summary>
public static ProjectContext Create(string projectPath, NuGetFramework framework, IEnumerable<string> runtimeIdentifiers)
{
if (projectPath.EndsWith(Project.FileName))
{
projectPath = Path.GetDirectoryName(projectPath);
}
return new ProjectContextBuilder()
.WithProjectDirectory(projectPath)
.WithTargetFramework(framework)
.WithRuntimeIdentifiers(runtimeIdentifiers)
.Build();
}
public static ProjectContextBuilder CreateBuilder(string projectPath, NuGetFramework framework)
{
if (projectPath.EndsWith(Project.FileName))
{
projectPath = Path.GetDirectoryName(projectPath);
}
return new ProjectContextBuilder()
.WithProjectDirectory(projectPath)
.WithTargetFramework(framework);
}
/// <summary>
/// Creates a project context for each framework located in the project at <paramref name="projectPath"/>
/// </summary>
public static IEnumerable<ProjectContext> CreateContextForEachFramework(string projectPath, ProjectReaderSettings settings = null, IEnumerable<string> runtimeIdentifiers = null)
{
if (!projectPath.EndsWith(Project.FileName))
{
projectPath = Path.Combine(projectPath, Project.FileName);
}
var project = ProjectReader.GetProject(projectPath, settings);
foreach (var framework in project.GetTargetFrameworks())
{
yield return new ProjectContextBuilder()
.WithProject(project)
.WithTargetFramework(framework.FrameworkName)
.WithProjectReaderSettings(settings)
.WithRuntimeIdentifiers(runtimeIdentifiers ?? Enumerable.Empty<string>())
.Build();
}
}
/// <summary>
/// Creates a project context for each target located in the project at <paramref name="projectPath"/>
/// </summary>
public static IEnumerable<ProjectContext> CreateContextForEachTarget(string projectPath, ProjectReaderSettings settings = null)
{
var project = ProjectReader.GetProject(projectPath);
return new ProjectContextBuilder()
.WithProjectReaderSettings(settings)
.WithProject(project)
.BuildAllTargets();
}
public OutputPaths GetOutputPaths(string configuration, string buidBasePath = null, string outputPath = null)
{
return OutputPathsCalculator.GetOutputPaths(ProjectFile,
TargetFramework,
RuntimeIdentifier,
configuration,
RootDirectory,
buidBasePath,
outputPath);
}
}
}

View file

@ -1,708 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.DotNet.Internal.ProjectModel.Graph;
using Microsoft.DotNet.Internal.ProjectModel.Resolution;
using NuGet.Common;
using NuGet.Configuration;
using NuGet.Frameworks;
using NuGet.LibraryModel;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class ProjectContextBuilder
{
// Note: When adding a property, make sure to add it to Clone below. You'll also need to update the CloneTest in
// Microsoft.DotNet.ProjectModel.Tests.ProjectContextBuilderTests
private Project Project { get; set; }
private LockFile LockFile { get; set; }
private NuGetFramework TargetFramework { get; set; }
private IEnumerable<string> RuntimeIdentifiers { get; set; } = Enumerable.Empty<string>();
private string RootDirectory { get; set; }
private string ProjectDirectory { get; set; }
private string PackagesDirectory { get; set; }
private string ReferenceAssembliesPath { get; set; }
private bool IsDesignTime { get; set; }
private Func<string, Project> ProjectResolver { get; set; }
private Func<string, LockFile> LockFileResolver { get; set; }
private ProjectReaderSettings ProjectReaderSettings { get; set; } = ProjectReaderSettings.ReadFromEnvironment();
public ProjectContextBuilder()
{
ProjectResolver = ResolveProject;
LockFileResolver = ResolveLockFile;
}
public ProjectContextBuilder Clone()
{
var builder = new ProjectContextBuilder()
.WithLockFile(LockFile)
.WithProject(Project)
.WithProjectDirectory(ProjectDirectory)
.WithTargetFramework(TargetFramework)
.WithRuntimeIdentifiers(RuntimeIdentifiers)
.WithReferenceAssembliesPath(ReferenceAssembliesPath)
.WithPackagesDirectory(PackagesDirectory)
.WithRootDirectory(RootDirectory)
.WithProjectResolver(ProjectResolver)
.WithLockFileResolver(LockFileResolver)
.WithProjectReaderSettings(ProjectReaderSettings);
if (IsDesignTime)
{
builder.AsDesignTime();
}
return builder;
}
public ProjectContextBuilder WithLockFile(LockFile lockFile)
{
LockFile = lockFile;
return this;
}
public ProjectContextBuilder WithProject(Project project)
{
Project = project;
return this;
}
public ProjectContextBuilder WithProjectDirectory(string projectDirectory)
{
ProjectDirectory = projectDirectory;
return this;
}
public ProjectContextBuilder WithTargetFramework(NuGetFramework targetFramework)
{
TargetFramework = targetFramework;
return this;
}
public ProjectContextBuilder WithTargetFramework(string targetFramework)
{
TargetFramework = NuGetFramework.Parse(targetFramework);
return this;
}
public ProjectContextBuilder WithRuntimeIdentifiers(IEnumerable<string> runtimeIdentifiers)
{
RuntimeIdentifiers = runtimeIdentifiers;
return this;
}
public ProjectContextBuilder WithReferenceAssembliesPath(string referenceAssembliesPath)
{
ReferenceAssembliesPath = referenceAssembliesPath;
return this;
}
public ProjectContextBuilder WithPackagesDirectory(string packagesDirectory)
{
PackagesDirectory = packagesDirectory;
return this;
}
public ProjectContextBuilder WithRootDirectory(string rootDirectory)
{
RootDirectory = rootDirectory;
return this;
}
public ProjectContextBuilder WithProjectResolver(Func<string, Project> projectResolver)
{
ProjectResolver = projectResolver;
return this;
}
public ProjectContextBuilder WithLockFileResolver(Func<string, LockFile> lockFileResolver)
{
LockFileResolver = lockFileResolver;
return this;
}
public ProjectContextBuilder WithProjectReaderSettings(ProjectReaderSettings projectReaderSettings)
{
ProjectReaderSettings = projectReaderSettings;
return this;
}
public ProjectContextBuilder AsDesignTime()
{
IsDesignTime = true;
return this;
}
/// <summary>
/// Produce all targets found in the lock file associated with this builder.
/// Returns an empty enumerable if there is no lock file
/// (making this unsuitable for scenarios where the lock file may not be present,
/// such as at design-time)
/// </summary>
/// <returns></returns>
public IEnumerable<ProjectContext> BuildAllTargets()
{
ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory;
EnsureProjectLoaded();
LockFile = LockFile ?? LockFileResolver(ProjectDirectory);
if (LockFile != null)
{
var deduper = new HashSet<string>();
foreach (var target in LockFile.Targets)
{
var context = Clone()
.WithTargetFramework(target.TargetFramework)
.WithRuntimeIdentifiers(new[] { target.RuntimeIdentifier }).Build();
var id = $"{context.TargetFramework}/{context.RuntimeIdentifier}";
if (deduper.Add(id))
{
yield return context;
}
}
}
else
{
// Build a context for each framework. It won't be fully valid, since it won't have resolved data or runtime data, but the diagnostics will show that.
foreach (var framework in Project.GetTargetFrameworks())
{
var builder = new ProjectContextBuilder()
.WithProject(Project)
.WithTargetFramework(framework.FrameworkName);
if (IsDesignTime)
{
builder.AsDesignTime();
}
yield return builder.Build();
}
}
}
public ProjectContext Build()
{
var diagnostics = new List<DiagnosticMessage>();
ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory;
GlobalSettings globalSettings = null;
if (ProjectDirectory != null)
{
RootDirectory = ProjectRootResolver.ResolveRootDirectory(ProjectDirectory);
GlobalSettings.TryGetGlobalSettings(RootDirectory, out globalSettings);
}
RootDirectory = globalSettings?.DirectoryPath ?? RootDirectory;
FrameworkReferenceResolver frameworkReferenceResolver;
if (string.IsNullOrEmpty(ReferenceAssembliesPath))
{
// Use the default static resolver
frameworkReferenceResolver = FrameworkReferenceResolver.Default;
}
else
{
frameworkReferenceResolver = new FrameworkReferenceResolver(ReferenceAssembliesPath);
}
LockFileLookup lockFileLookup = null;
EnsureProjectLoaded();
ReadLockFile(diagnostics);
// some callers only give ProjectContextBuilder a LockFile
ProjectDirectory = ProjectDirectory ?? TryGetProjectDirectoryFromLockFile();
INuGetPathContext nugetPathContext = null;
if (ProjectDirectory != null)
{
nugetPathContext = NuGetPathContext.Create(ProjectDirectory);
}
PackagesDirectory = PackagesDirectory ?? nugetPathContext?.UserPackageFolder;
var validLockFile = true;
string lockFileValidationMessage = null;
if (LockFile != null)
{
if (Project != null)
{
validLockFile = LockFile.IsValidForProject(Project, out lockFileValidationMessage);
}
lockFileLookup = new LockFileLookup(LockFile);
}
var libraries = new Dictionary<LibraryKey, LibraryDescription>();
var projectResolver = new ProjectDependencyProvider(ProjectResolver);
ProjectDescription mainProject = null;
if (Project != null)
{
mainProject = projectResolver.GetDescription(TargetFramework, Project, targetLibrary: null);
// Add the main project
libraries.Add(new LibraryKey(mainProject.Identity.Name), mainProject);
}
ProjectLibraryDependency platformDependency = null;
if (mainProject != null)
{
platformDependency = mainProject.Dependencies
.Where(d => d.Type.Equals(LibraryDependencyType.Platform))
.Cast<ProjectLibraryDependency>()
.FirstOrDefault();
}
bool isPortable = platformDependency != null;
LockFileTarget target = null;
LibraryDescription platformLibrary = null;
if (lockFileLookup != null)
{
target = SelectTarget(LockFile, isPortable);
if (target != null)
{
var nugetPackageResolver = new PackageDependencyProvider(nugetPathContext, frameworkReferenceResolver);
var msbuildProjectResolver = new MSBuildDependencyProvider(Project, ProjectResolver);
ScanLibraries(target, lockFileLookup, libraries, msbuildProjectResolver, nugetPackageResolver, projectResolver);
if (platformDependency != null)
{
libraries.TryGetValue(new LibraryKey(platformDependency.Name), out platformLibrary);
}
}
}
string runtime = target?.RuntimeIdentifier;
if (string.IsNullOrEmpty(runtime) && TargetFramework.IsDesktop())
{
// we got a ridless target for desktop so turning portable mode on
isPortable = true;
var legacyRuntime = RuntimeEnvironmentRidExtensions.GetLegacyRestoreRuntimeIdentifier();
if (RuntimeIdentifiers.Contains(legacyRuntime))
{
runtime = legacyRuntime;
}
else
{
runtime = RuntimeIdentifiers.FirstOrDefault();
}
}
var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(frameworkReferenceResolver);
bool requiresFrameworkAssemblies;
// Resolve the dependencies
ResolveDependencies(libraries, referenceAssemblyDependencyResolver, out requiresFrameworkAssemblies);
// REVIEW: Should this be in NuGet (possibly stored in the lock file?)
if (LockFile == null)
{
diagnostics.Add(new DiagnosticMessage(
ErrorCodes.NU1009,
$"The expected lock file doesn't exist. Please run \"dotnet restore\" to generate a new lock file.",
Path.Combine(Project.ProjectDirectory, LockFileFormat.LockFileName),
DiagnosticMessageSeverity.Error));
}
if (!validLockFile)
{
diagnostics.Add(new DiagnosticMessage(
ErrorCodes.NU1006,
$"{lockFileValidationMessage}. Please run \"dotnet restore\" to generate a new lock file.",
Path.Combine(Project.ProjectDirectory, LockFileFormat.LockFileName),
DiagnosticMessageSeverity.Warning));
}
if (requiresFrameworkAssemblies)
{
var frameworkInfo = Project.GetTargetFramework(TargetFramework);
if (frameworkReferenceResolver == null || string.IsNullOrEmpty(frameworkReferenceResolver.ReferenceAssembliesPath))
{
// If there was an attempt to use reference assemblies but they were not installed
// report an error
diagnostics.Add(new DiagnosticMessage(
ErrorCodes.DOTNET1012,
$"The reference assemblies directory was not specified. You can set the location using the DOTNET_REFERENCE_ASSEMBLIES_PATH environment variable.",
filePath: Project.ProjectFilePath,
severity: DiagnosticMessageSeverity.Error,
startLine: frameworkInfo.Line,
startColumn: frameworkInfo.Column
));
}
else if (!frameworkReferenceResolver.IsInstalled(TargetFramework))
{
// If there was an attempt to use reference assemblies but they were not installed
// report an error
diagnostics.Add(new DiagnosticMessage(
ErrorCodes.DOTNET1011,
$"Framework not installed: {TargetFramework.DotNetFrameworkName} in {ReferenceAssembliesPath}",
filePath: Project.ProjectFilePath,
severity: DiagnosticMessageSeverity.Error,
startLine: frameworkInfo.Line,
startColumn: frameworkInfo.Column
));
}
}
List<DiagnosticMessage> allDiagnostics = new List<DiagnosticMessage>(diagnostics);
if (Project != null)
{
allDiagnostics.AddRange(Project.Diagnostics);
}
// Create a library manager
var libraryManager = new LibraryManager(libraries.Values.ToList(), allDiagnostics, Project?.ProjectFilePath);
return new ProjectContext(
globalSettings,
mainProject,
platformLibrary,
TargetFramework,
isPortable,
runtime,
PackagesDirectory,
libraryManager,
LockFile,
diagnostics);
}
private string TryGetProjectDirectoryFromLockFile()
{
string result = null;
if (LockFile != null && !string.IsNullOrEmpty(LockFile.Path))
{
result = Path.GetDirectoryName(LockFile.Path);
}
return result;
}
private void ReadLockFile(ICollection<DiagnosticMessage> diagnostics)
{
try
{
LockFile = LockFile ?? LockFileResolver(ProjectDirectory);
}
catch (FileFormatException e)
{
var lockFilePath = "";
if (LockFile != null)
{
lockFilePath = LockFile.Path;
}
else if (Project != null)
{
lockFilePath = Path.Combine(Project.ProjectDirectory, LockFileFormat.LockFileName);
}
diagnostics.Add(new DiagnosticMessage(
ErrorCodes.DOTNET1014,
ComposeMessageFromInnerExceptions(e),
lockFilePath,
DiagnosticMessageSeverity.Error));
}
}
private static string ComposeMessageFromInnerExceptions(Exception exception)
{
var sb = new StringBuilder();
var messages = new HashSet<string>();
while (exception != null)
{
messages.Add(exception.Message);
exception = exception.InnerException;
}
foreach (var message in messages)
{
sb.AppendLine(message);
}
return sb.ToString();
}
private void ResolveDependencies(Dictionary<LibraryKey, LibraryDescription> libraries,
ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver,
out bool requiresFrameworkAssemblies)
{
// Remark: the LibraryType in the key of the given dictionary are all "Unspecified" at the beginning.
requiresFrameworkAssemblies = false;
foreach (var pair in libraries.ToList())
{
var library = pair.Value;
// The System.* packages provide placeholders on any non netstandard platform
// To make them work seamlessly on those platforms, we fill the gap with a reference
// assembly (if available)
var package = library as PackageDescription;
if (package != null &&
package.Resolved &&
package.HasCompileTimePlaceholder &&
!TargetFramework.IsPackageBased)
{
// requiresFrameworkAssemblies is true whenever we find a CompileTimePlaceholder in a non-package based framework, even if
// the reference is unresolved. This ensures the best error experience when someone is building on a machine without
// the target framework installed.
requiresFrameworkAssemblies = true;
var newKey = new LibraryKey(library.Identity.Name, LibraryType.Reference);
var dependency = new ProjectLibraryDependency
{
LibraryRange = new LibraryRange(library.Identity.Name, LibraryDependencyTarget.Reference)
};
var replacement = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework);
// If the reference is unresolved, just skip it. Don't replace the package dependency
if (replacement == null)
{
continue;
}
// Remove the original package reference
libraries.Remove(pair.Key);
// Insert a reference assembly key if there isn't one
if (!libraries.ContainsKey(newKey))
{
libraries[newKey] = replacement;
}
}
}
foreach (var pair in libraries.ToList())
{
var library = pair.Value;
library.Framework = library.Framework ?? TargetFramework;
foreach (var dependency in library.Dependencies)
{
var keyType = dependency.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference ?
LibraryType.Reference :
(LibraryType?) null;
var key = new LibraryKey(dependency.Name, keyType);
LibraryDescription dependencyDescription;
if (!libraries.TryGetValue(key, out dependencyDescription))
{
if (keyType == LibraryType.Reference)
{
// a dependency is specified to be reference assembly but fail to match
// then add a unresolved dependency
dependencyDescription = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ??
UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
libraries[key] = dependencyDescription;
}
else if (!libraries.TryGetValue(new LibraryKey(dependency.Name, LibraryType.Reference), out dependencyDescription))
{
// a dependency which type is unspecified fails to match, then try to find a
// reference assembly type dependency
dependencyDescription = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
libraries[key] = dependencyDescription;
}
}
dependencyDescription.RequestedRanges.Add(dependency);
dependencyDescription.Parents.Add(library);
}
}
// Deduplicate libraries with the same name
// Priority list is backwards so not found -1 would be last when sorting by descending
var priorities = new[] { LibraryType.Package, LibraryType.Project, LibraryType.Reference };
var nameGroups = libraries.Keys.ToLookup(libraryKey => libraryKey.Name);
foreach (var nameGroup in nameGroups)
{
var librariesToRemove = nameGroup
.OrderByDescending(libraryKey => Array.IndexOf(priorities, libraryKey.LibraryType))
.Skip(1);
foreach (var library in librariesToRemove)
{
libraries.Remove(library);
}
}
}
private void ScanLibraries(LockFileTarget target,
LockFileLookup lockFileLookup,
Dictionary<LibraryKey, LibraryDescription> libraries,
MSBuildDependencyProvider msbuildResolver,
PackageDependencyProvider packageResolver,
ProjectDependencyProvider projectResolver)
{
foreach (var library in target.Libraries)
{
LibraryDescription description = null;
LibraryDependencyTarget type = LibraryDependencyTarget.All;
if (string.Equals(library.Type, "project"))
{
var projectLibrary = lockFileLookup.GetProject(library.Name);
if (projectLibrary != null)
{
if (MSBuildDependencyProvider.IsMSBuildProjectLibrary(projectLibrary))
{
description = msbuildResolver.GetDescription(TargetFramework, projectLibrary, library, IsDesignTime);
type = LibraryDependencyTarget.Project;
}
else
{
var path = Path.GetFullPath(Path.Combine(ProjectDirectory, projectLibrary.Path));
description = projectResolver.GetDescription(library.Name, path, library, ProjectResolver);
type = LibraryDependencyTarget.Project;
}
}
}
else
{
var packageEntry = lockFileLookup.GetPackage(library.Name, library.Version);
if (packageEntry != null)
{
description = packageResolver.GetDescription(TargetFramework, packageEntry, library);
}
type = LibraryDependencyTarget.Package;
}
description = description ??
UnresolvedDependencyProvider.GetDescription(
new ProjectLibraryDependency
{
LibraryRange = new LibraryRange(library.Name, type)
},
target.TargetFramework);
libraries.Add(new LibraryKey(library.Name), description);
}
}
private void EnsureProjectLoaded()
{
if (Project == null && ProjectDirectory != null)
{
Project = ProjectResolver(ProjectDirectory);
if (Project == null)
{
throw new InvalidOperationException($"Could not resolve project at: {ProjectDirectory}. " +
$"This could happen when project.lock.json was moved after restore.");
}
}
}
private LockFileTarget SelectTarget(LockFile lockFile, bool isPortable)
{
if (!isPortable)
{
foreach (var runtimeIdentifier in RuntimeIdentifiers)
{
foreach (var scanTarget in lockFile.Targets)
{
if (Equals(scanTarget.TargetFramework, TargetFramework) && string.Equals(scanTarget.RuntimeIdentifier, runtimeIdentifier, StringComparison.Ordinal))
{
return scanTarget;
}
}
}
}
foreach (var scanTarget in lockFile.Targets)
{
if (Equals(scanTarget.TargetFramework, TargetFramework) && string.IsNullOrEmpty(scanTarget.RuntimeIdentifier))
{
return scanTarget;
}
}
return null;
}
private Project ResolveProject(string projectDirectory)
{
Project project;
if (ProjectReader.TryGetProject(projectDirectory, out project, settings: ProjectReaderSettings))
{
return project;
}
else
{
return null;
}
}
private static LockFile ResolveLockFile(string projectDir)
{
var projectLockJsonPath = Path.Combine(projectDir, LockFileFormat.LockFileName);
return File.Exists(projectLockJsonPath) ?
new LockFileFormat().Read(Path.Combine(projectDir, LockFileFormat.LockFileName)) :
null;
}
private struct LibraryKey
{
public LibraryKey(string name) : this(name, null)
{
}
public LibraryKey(string name, LibraryType? libraryType)
{
Name = name;
LibraryType = libraryType;
}
public string Name { get; }
public LibraryType? LibraryType { get; }
public override bool Equals(object obj)
{
var otherKey = (LibraryKey)obj;
return string.Equals(otherKey.Name, Name, StringComparison.OrdinalIgnoreCase) &&
otherKey.LibraryType.Equals(LibraryType);
}
public override int GetHashCode()
{
var combiner = new HashCodeCombiner();
combiner.Add(Name.ToLowerInvariant());
combiner.Add(LibraryType);
return combiner.CombinedHash;
}
public override string ToString()
{
return Name + " " + LibraryType;
}
}
}
}

View file

@ -1,85 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class ProjectContextCollection
{
public Project Project { get; set; }
/// <summary>
/// Gets all the ProjectContexts in this collection
/// </summary>
public List<ProjectContext> ProjectContexts { get; } = new List<ProjectContext>();
/// <summary>
/// Gets the ProjectContexts in this collection which are not runtime-specific (i.e. the ones used for compilation)
/// </summary>
public IEnumerable<ProjectContext> FrameworkOnlyContexts => ProjectContexts.Where(c => string.IsNullOrEmpty(c.RuntimeIdentifier));
public List<DiagnosticMessage> ProjectDiagnostics { get; } = new List<DiagnosticMessage>();
public string LockFilePath { get; set; }
public string ProjectFilePath { get; set; }
public DateTime LastProjectFileWriteTimeUtc { get; set; }
public DateTime LastLockFileWriteTimeUtc { get; set; }
public bool HasChanged
{
get
{
if (ProjectFilePath == null || !File.Exists(ProjectFilePath))
{
return true;
}
if (LastProjectFileWriteTimeUtc < File.GetLastWriteTimeUtc(ProjectFilePath))
{
return true;
}
if (LockFilePath == null || !File.Exists(LockFilePath))
{
return true;
}
if (LastLockFileWriteTimeUtc < File.GetLastWriteTimeUtc(LockFilePath))
{
return true;
}
return false;
}
}
public ProjectContext GetTarget(NuGetFramework targetFramework) => GetTarget(targetFramework, string.Empty);
public ProjectContext GetTarget(NuGetFramework targetFramework, string runtimeIdentifier)
{
return ProjectContexts
.FirstOrDefault(c =>
Equals(c.TargetFramework, targetFramework) &&
string.Equals(c.RuntimeIdentifier ?? string.Empty, runtimeIdentifier ?? string.Empty));
}
public void Reset()
{
Project = null;
ProjectContexts.Clear();
ProjectFilePath = null;
LockFilePath = null;
LastLockFileWriteTimeUtc = DateTime.MinValue;
LastProjectFileWriteTimeUtc = DateTime.MinValue;
ProjectDiagnostics.Clear();
}
}
}

View file

@ -1,39 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.PlatformAbstractions;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Internal.ProjectModel
{
public struct ProjectContextIdentity
{
public ProjectContextIdentity(string path, NuGetFramework targetFramework)
{
Path = path;
TargetFramework = targetFramework;
}
public string Path { get; }
public NuGetFramework TargetFramework { get; }
public bool Equals(ProjectContextIdentity other)
{
return string.Equals(Path, other.Path) && Equals(TargetFramework, other.TargetFramework);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is ProjectContextIdentity && Equals((ProjectContextIdentity) obj);
}
public override int GetHashCode()
{
var combiner = HashCodeCombiner.Start();
combiner.Add(Path);
combiner.Add(TargetFramework);
return combiner.CombinedHash;
}
}
}

View file

@ -1,59 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Linq;
using NuGet.LibraryModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class ProjectDescription : LibraryDescription
{
// Create an unresolved project description
public ProjectDescription(string name, string path)
: base(
new LibraryIdentity(name, null, LibraryType.Project),
string.Empty, // Projects don't have hashes
path,
Enumerable.Empty<ProjectLibraryDependency>(),
framework: null,
resolved: false,
compatible: false)
{
}
public ProjectDescription(
LibraryRange libraryRange,
Project project,
IEnumerable<ProjectLibraryDependency> dependencies,
TargetFrameworkInformation targetFrameworkInfo,
bool resolved) :
base(
new LibraryIdentity(project.Name, project.Version, LibraryType.Project),
string.Empty, // Projects don't have hashes
project.ProjectFilePath,
dependencies,
targetFrameworkInfo.FrameworkName,
resolved,
compatible: true)
{
Project = project;
TargetFrameworkInfo = targetFrameworkInfo;
}
public Project Project { get; }
public TargetFrameworkInformation TargetFrameworkInfo { get; }
public OutputPaths GetOutputPaths(string buildBasePath, string solutionRootPath, string configuration, string runtime)
{
return OutputPathsCalculator.GetOutputPaths(Project,
Framework,
runtimeIdentifier: runtime,
configuration: configuration,
solutionRootPath: solutionRootPath,
buildBasePath: buildBasePath,
outputPath: null);
}
}
}

View file

@ -1,32 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static class ProjectExtensions
{
private static readonly KeyValuePair<string, string>[] _compilerNameToLanguageId =
{
new KeyValuePair<string, string>("csc", "cs"),
new KeyValuePair<string, string>("vbc", "vb"),
new KeyValuePair<string, string>("fsc", "fs")
};
public static string GetSourceCodeLanguage(this Project project)
{
foreach (var kvp in _compilerNameToLanguageId)
{
if (kvp.Key == (project._defaultCompilerOptions.CompilerName))
{
return kvp.Value;
}
}
return null;
}
}
}

View file

@ -1,21 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class ProjectFileDependencyGroup
{
public ProjectFileDependencyGroup(NuGetFramework frameworkName, IEnumerable<string> dependencies)
{
FrameworkName = frameworkName;
Dependencies = dependencies;
}
public NuGetFramework FrameworkName { get; }
public IEnumerable<string> Dependencies { get; }
}
}

View file

@ -1,82 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.Internal.ProjectModel.Compilation;
using NuGet.LibraryModel;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static class ProjectModelPlatformExtensions
{
public static HashSet<string> GetPlatformExclusionList(this ProjectContext context, IDictionary<string, LibraryExport> exports)
{
var exclusionList = new HashSet<string>();
var redistPackage = context.PlatformLibrary;
if (redistPackage == null)
{
return exclusionList;
}
var redistExport = exports[redistPackage.Identity.Name];
exclusionList.Add(redistExport.Library.Identity.Name);
CollectDependencies(exports, redistExport.Library.Dependencies, exclusionList);
return exclusionList;
}
private static void CollectDependencies(
IDictionary<string, LibraryExport> exports,
IEnumerable<LibraryDependency> dependencies,
HashSet<string> exclusionList)
{
foreach (var dependency in dependencies)
{
var export = exports[dependency.Name];
if (export.Library.Identity.Version.Equals(dependency.LibraryRange.VersionRange.MinVersion))
{
exclusionList.Add(export.Library.Identity.Name);
CollectDependencies(exports, export.Library.Dependencies, exclusionList);
}
}
}
public static HashSet<string> GetTypeBuildExclusionList(this ProjectContext context, IDictionary<string, LibraryExport> exports)
{
var acceptedExports = new HashSet<string>();
// Accept the root project, obviously :)
acceptedExports.Add(context.RootProject.Identity.Name);
// Walk all dependencies, tagging exports. But don't walk through Build dependencies.
CollectNonBuildDependencies(exports, context.RootProject.Dependencies, acceptedExports);
// Whatever is left in exports was brought in ONLY by a build dependency
var exclusionList = new HashSet<string>(exports.Keys);
exclusionList.ExceptWith(acceptedExports);
return exclusionList;
}
private static void CollectNonBuildDependencies(
IDictionary<string, LibraryExport> exports,
IEnumerable<LibraryDependency> dependencies,
HashSet<string> acceptedExports)
{
foreach (var dependency in dependencies)
{
var export = exports[dependency.Name];
if (!dependency.Type.Equals(LibraryDependencyType.Build))
{
acceptedExports.Add(export.Library.Identity.Name);
CollectNonBuildDependencies(exports, export.Library.Dependencies, acceptedExports);
}
}
}
public static IEnumerable<LibraryExport> FilterExports(this IEnumerable<LibraryExport> exports, HashSet<string> exclusionList)
{
return exports.Where(e => !exclusionList.Contains(e.Library.Identity.Name));
}
}
}

View file

@ -1,48 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static class ProjectPathHelper
{
public static string NormalizeProjectDirectoryPath(string path)
{
string fullPath = Path.GetFullPath(path);
if (IsProjectFilePath(fullPath))
{
return Path.GetDirectoryName(fullPath);
}
else if (IsDirectoryContainingProjectFile(fullPath))
{
return fullPath;
}
return null;
}
public static string NormalizeProjectFilePath(string path)
{
if (!path.EndsWith(Project.FileName))
{
path = Path.Combine(path, Project.FileName);
}
return Path.GetFullPath(path);
}
private static bool IsProjectFilePath(string path)
{
return File.Exists(path) &&
string.Equals(Path.GetFileName(path), Project.FileName, StringComparison.OrdinalIgnoreCase);
}
private static bool IsDirectoryContainingProjectFile(string path)
{
return Directory.Exists(path) && File.Exists(Path.Combine(path, Project.FileName));
}
}
}

View file

@ -1,24 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal class ProjectReaderSettings
{
public string VersionSuffix { get; set; }
public string AssemblyFileVersion { get; set; }
public static ProjectReaderSettings ReadFromEnvironment()
{
var settings = new ProjectReaderSettings
{
VersionSuffix = Environment.GetEnvironmentVariable("DOTNET_BUILD_VERSION"),
AssemblyFileVersion = Environment.GetEnvironmentVariable("DOTNET_ASSEMBLY_FILE_VERSION")
};
return settings;
}
}
}

View file

@ -1,31 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.IO;
namespace Microsoft.DotNet.Internal.ProjectModel
{
internal static class ProjectRootResolver
{
public static readonly string GlobalFileName = "global.json";
public static string ResolveRootDirectory(string projectPath)
{
var di = new DirectoryInfo(projectPath);
while (di.Parent != null)
{
var globalJsonPath = Path.Combine(di.FullName, GlobalFileName);
if (File.Exists(globalJsonPath))
{
return di.FullName;
}
di = di.Parent;
}
// If we don't find any files then make the project folder the root
return projectPath;
}
}
}

View file

@ -1,52 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
namespace Microsoft.DotNet.Internal.ProjectModel.Resolution
{
internal class FrameworkInformation
{
private bool? _exists;
public FrameworkInformation()
{
Assemblies = new Dictionary<string, AssemblyEntry>();
}
public bool Exists
{
get
{
if (_exists == null)
{
_exists = Directory.Exists(Path);
}
return _exists.Value;
}
set
{
_exists = true;
}
}
public string Path { get; set; }
public IEnumerable<string> SearchPaths { get; set; }
public string RedistListPath { get; set; }
public IDictionary<string, AssemblyEntry> Assemblies { get; private set; }
public string Name { get; set; }
}
internal class AssemblyEntry
{
public string Path { get; set; }
public Version Version { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show more