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:
commit
f3a4b22457
248 changed files with 116 additions and 29633 deletions
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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} }}";
|
||||
}
|
||||
}
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
}
|
||||
}
|
|
@ -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); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
Loading…
Reference in a new issue