зеркало из https://github.com/dotnet/msbuild.git
Merge branch 'vs17.7' (#9023)
This commit is contained in:
Коммит
2f8fe45756
|
@ -1 +1,2 @@
|
|||
M:System.Globalization.CompareInfo.IndexOf(System.String,System.Char);CompareInfo.IndexOf can unexpectedly allocate strings--use string.IndexOf
|
||||
P:Microsoft.Build.Construction.ProjectElementContainer.Children;Use ChildrenEnumerable instead to avoid boxing
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
{
|
||||
ProjectRootElement project = ProjectRootElement.Create();
|
||||
|
||||
Assert.Null(project.Imports.GetEnumerator().Current);
|
||||
Assert.Empty(project.Imports);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -143,7 +143,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
{
|
||||
ProjectRootElement project = ProjectRootElement.Create();
|
||||
|
||||
Assert.Null(project.Imports.GetEnumerator().Current);
|
||||
Assert.Empty(project.Imports);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -162,7 +162,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
|
||||
ProjectImportGroupElement importGroup = (ProjectImportGroupElement)Helpers.GetFirst(project.ImportGroups);
|
||||
|
||||
Assert.Null(project.Imports.GetEnumerator().Current);
|
||||
Assert.Empty(project.Imports);
|
||||
Assert.Equal(0, Helpers.Count(importGroup.Imports));
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
{
|
||||
ProjectRootElement project = ProjectRootElement.Create();
|
||||
Assert.Equal(0, Helpers.Count(project.Children));
|
||||
Assert.Null(project.ItemDefinitionGroups.GetEnumerator().Current);
|
||||
Assert.Empty(project.ItemDefinitionGroups);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
{
|
||||
ProjectRootElement project = ProjectRootElement.Create();
|
||||
Assert.Equal(0, Helpers.Count(project.Children));
|
||||
Assert.Null(project.ItemGroups.GetEnumerator().Current);
|
||||
Assert.Empty(project.ItemGroups);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
{
|
||||
ProjectRootElement project = ProjectRootElement.Create();
|
||||
Assert.Equal(0, Helpers.Count(project.Children));
|
||||
Assert.Null(project.PropertyGroups.GetEnumerator().Current);
|
||||
Assert.Empty(project.PropertyGroups);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
public void ReadNoTarget()
|
||||
{
|
||||
ProjectRootElement project = ProjectRootElement.Create();
|
||||
Assert.Null(project.Targets.GetEnumerator().Current);
|
||||
Assert.Empty(project.Targets);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
{
|
||||
ProjectRootElement project = ProjectRootElement.Create();
|
||||
|
||||
Assert.Null(project.UsingTasks.GetEnumerator().Current);
|
||||
Assert.Empty(project.UsingTasks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
|
|||
UsingTaskParameterGroupElement parameterGroup = GetParameterGroupXml(s_contentEmptyParameterGroup);
|
||||
Assert.NotNull(parameterGroup);
|
||||
Assert.Equal(0, parameterGroup.Count);
|
||||
Assert.Null(parameterGroup.Parameters.GetEnumerator().Current);
|
||||
Assert.Empty(parameterGroup.Parameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Microsoft.Build.Graph.UnitTests
|
|||
/// <summary>
|
||||
/// Performs SetPlatform negotiation for all project references when opted
|
||||
/// in via the EnableDynamicPlatformResolution property.
|
||||
///
|
||||
///
|
||||
/// The static graph mirrors the negotiation during build to determine plartform for each node.
|
||||
/// These tests mirror GetCompatiblePlatform_Tests.cs in order to make sure they both are in sync.
|
||||
/// </summary>
|
||||
|
@ -351,5 +351,102 @@ namespace Microsoft.Build.Graph.UnitTests
|
|||
GetFirstNodeWithProjectNumber(graph, 2).ProjectInstance.GetPropertyValue("Platform").ShouldBe(GetFirstNodeWithProjectNumber(graph, 1).ProjectInstance.GetPropertyValue("Platform"));
|
||||
}
|
||||
}
|
||||
|
||||
// Validate configurations are defined in project reference protocol
|
||||
[Fact]
|
||||
public void SolutionWithoutAllConfigurations()
|
||||
{
|
||||
using (TestEnvironment testEnvironment = TestEnvironment.Create())
|
||||
{
|
||||
var firstProjectName = "1";
|
||||
var secondProjectName = "2";
|
||||
var thirdProjectName = "3";
|
||||
TransientTestFolder folder = testEnvironment.CreateFolder(createFolder: true);
|
||||
TransientTestFolder project1Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, firstProjectName), createFolder: true);
|
||||
TransientTestFolder project1SubFolder = testEnvironment.CreateFolder(Path.Combine(project1Folder.Path, firstProjectName), createFolder: true);
|
||||
TransientTestFile project1 = testEnvironment.CreateFile(project1SubFolder, $"{firstProjectName}.csproj",
|
||||
@"<Project>
|
||||
<PropertyGroup>
|
||||
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
|
||||
<Platform>x64</Platform>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include=""$(MSBuildThisFileDirectory)\..\..\2\2\2.proj"" />
|
||||
<ProjectReference Include=""$(MSBuildThisFileDirectory)\..\..\3\3\3.proj"" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
");
|
||||
|
||||
TransientTestFolder project2Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, secondProjectName), createFolder: true);
|
||||
TransientTestFolder project2SubFolder = testEnvironment.CreateFolder(Path.Combine(project2Folder.Path, secondProjectName), createFolder: true);
|
||||
TransientTestFile project2 = testEnvironment.CreateFile(project2SubFolder, $"{secondProjectName}.proj",
|
||||
@"<Project>
|
||||
<PropertyGroup>
|
||||
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
");
|
||||
|
||||
TransientTestFolder project3Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, thirdProjectName), createFolder: true);
|
||||
TransientTestFolder project3SubFolder = testEnvironment.CreateFolder(Path.Combine(project3Folder.Path, thirdProjectName), createFolder: true);
|
||||
TransientTestFile project3 = testEnvironment.CreateFile(project3SubFolder, $"{thirdProjectName}.proj",
|
||||
@"<Project>
|
||||
<PropertyGroup>
|
||||
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
");
|
||||
|
||||
|
||||
// Slashes here (and in the .slnf) are hardcoded as backslashes intentionally to support the common case.
|
||||
TransientTestFile solutionFile = testEnvironment.CreateFile(folder, "SimpleProject.sln",
|
||||
@"
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29326.124
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""Project1"", ""1\1\1.csproj"", ""{79B5EBA6-5D27-4976-BC31-14422245A59A}""
|
||||
EndProject
|
||||
Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""2"", ""2\2\2.proj"", ""{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}""
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Debug|x64.Build.0 = Debug|x64
|
||||
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Release|x64.ActiveCfg = Release|x64
|
||||
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Release|x64.Build.0 = Release|x64
|
||||
|
||||
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DE7234EC-0C4D-4070-B66A-DCF1B4F0CFEF}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
");
|
||||
|
||||
ProjectCollection projectCollection = testEnvironment.CreateProjectCollection().Collection;
|
||||
MockLogger logger = new();
|
||||
projectCollection.RegisterLogger(logger);
|
||||
ProjectGraphEntryPoint entryPoint = new(solutionFile.Path, new Dictionary<string, string>());
|
||||
|
||||
// We want to make sure negotiation respects configuration if defined but negotiates if not.
|
||||
ProjectGraph graphFromSolution = new(entryPoint, projectCollection);
|
||||
logger.AssertNoErrors();
|
||||
GetFirstNodeWithProjectNumber(graphFromSolution, 2).ProjectInstance.GetPropertyValue("Platform").ShouldBe("AnyCPU", "Project2 should have followed the sln config to AnyCPU");
|
||||
GetFirstNodeWithProjectNumber(graphFromSolution, 3).ProjectInstance.GetPropertyValue("Platform").ShouldBe("x64", "Project3 isn't in the solution so it should have negotiated to x64 to match Project1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
|
@ -60,7 +58,7 @@ namespace Microsoft.Build.Construction
|
|||
/// Get the When children.
|
||||
/// Will contain at least one entry.
|
||||
/// </summary>
|
||||
public ICollection<ProjectWhenElement> WhenElements => new ReadOnlyCollection<ProjectWhenElement>(Children.OfType<ProjectWhenElement>());
|
||||
public ICollection<ProjectWhenElement> WhenElements => GetChildrenOfType<ProjectWhenElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get any Otherwise child.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
@ -59,10 +60,15 @@ namespace Microsoft.Build.Construction
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an enumerator over all children, gotten recursively.
|
||||
/// Walks the children in a depth-first manner.
|
||||
/// Get an enumerator over all descendants in a depth-first manner.
|
||||
/// </summary>
|
||||
public IEnumerable<ProjectElement> AllChildren => GetChildrenRecursively();
|
||||
public IEnumerable<ProjectElement> AllChildren => GetDescendants();
|
||||
|
||||
internal IEnumerable<T> GetAllChildrenOfType<T>()
|
||||
where T : ProjectElement
|
||||
=> FirstChild == null
|
||||
? Array.Empty<T>()
|
||||
: GetDescendantsOfType<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Get enumerable over all the children
|
||||
|
@ -70,26 +76,41 @@ namespace Microsoft.Build.Construction
|
|||
public ICollection<ProjectElement> Children
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get
|
||||
{
|
||||
return new Collections.ReadOnlyCollection<ProjectElement>(
|
||||
new ProjectElementSiblingEnumerable(FirstChild));
|
||||
}
|
||||
get => FirstChild == null
|
||||
? Array.Empty<ProjectElement>()
|
||||
: new Collections.ReadOnlyCollection<ProjectElement>(new ProjectElementSiblingEnumerable(FirstChild));
|
||||
}
|
||||
|
||||
#pragma warning disable RS0030 // The ref to the banned API is in a doc comment
|
||||
/// <summary>
|
||||
/// Use this instead of <see cref="Children"/> to avoid boxing.
|
||||
/// </summary>
|
||||
#pragma warning restore RS0030
|
||||
internal ProjectElementSiblingEnumerable ChildrenEnumerable => new ProjectElementSiblingEnumerable(FirstChild);
|
||||
|
||||
internal ProjectElementSiblingSubTypeCollection<T> GetChildrenOfType<T>()
|
||||
where T : ProjectElement
|
||||
=> FirstChild == null
|
||||
? ProjectElementSiblingSubTypeCollection<T>.Empty
|
||||
: new ProjectElementSiblingSubTypeCollection<T>(FirstChild);
|
||||
|
||||
/// <summary>
|
||||
/// Get enumerable over all the children, starting from the last
|
||||
/// </summary>
|
||||
public ICollection<ProjectElement> ChildrenReversed
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get
|
||||
{
|
||||
return new Collections.ReadOnlyCollection<ProjectElement>(
|
||||
new ProjectElementSiblingEnumerable(LastChild, false /* reverse */));
|
||||
}
|
||||
get => LastChild == null
|
||||
? Array.Empty<ProjectElement>()
|
||||
: new Collections.ReadOnlyCollection<ProjectElement>(new ProjectElementSiblingEnumerable(LastChild, forwards: false));
|
||||
}
|
||||
|
||||
internal ProjectElementSiblingSubTypeCollection<T> GetChildrenReversedOfType<T>()
|
||||
where T : ProjectElement
|
||||
=> LastChild == null
|
||||
? ProjectElementSiblingSubTypeCollection<T>.Empty
|
||||
: new ProjectElementSiblingSubTypeCollection<T>(LastChild, forwards: false);
|
||||
|
||||
/// <summary>
|
||||
/// Number of children of any kind
|
||||
/// </summary>
|
||||
|
@ -318,7 +339,7 @@ namespace Microsoft.Build.Construction
|
|||
/// </remarks>
|
||||
public void RemoveAllChildren()
|
||||
{
|
||||
foreach (ProjectElement child in Children)
|
||||
foreach (ProjectElement child in ChildrenEnumerable)
|
||||
{
|
||||
RemoveChild(child);
|
||||
}
|
||||
|
@ -341,7 +362,7 @@ namespace Microsoft.Build.Construction
|
|||
RemoveAllChildren();
|
||||
CopyFrom(element);
|
||||
|
||||
foreach (ProjectElement child in element.Children)
|
||||
foreach (ProjectElement child in element.ChildrenEnumerable)
|
||||
{
|
||||
if (child is ProjectElementContainer childContainer)
|
||||
{
|
||||
|
@ -395,7 +416,7 @@ namespace Microsoft.Build.Construction
|
|||
var clone = (ProjectElementContainer)Clone(factory);
|
||||
parent?.AppendChild(clone);
|
||||
|
||||
foreach (ProjectElement child in Children)
|
||||
foreach (ProjectElement child in ChildrenEnumerable)
|
||||
{
|
||||
if (child is ProjectElementContainer childContainer)
|
||||
{
|
||||
|
@ -667,7 +688,7 @@ namespace Microsoft.Build.Construction
|
|||
/// Result does NOT include the element passed in.
|
||||
/// The caller could filter these.
|
||||
/// </summary>
|
||||
private IEnumerable<ProjectElement> GetChildrenRecursively()
|
||||
private IEnumerable<ProjectElement> GetDescendants()
|
||||
{
|
||||
ProjectElement child = FirstChild;
|
||||
|
||||
|
@ -687,6 +708,30 @@ namespace Microsoft.Build.Construction
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<T> GetDescendantsOfType<T>()
|
||||
where T : ProjectElement
|
||||
{
|
||||
ProjectElement child = FirstChild;
|
||||
|
||||
while (child != null)
|
||||
{
|
||||
if (child is T childOfType)
|
||||
{
|
||||
yield return childOfType;
|
||||
}
|
||||
|
||||
if (child is ProjectElementContainer container)
|
||||
{
|
||||
foreach (T grandchild in container.GetAllChildrenOfType<T>())
|
||||
{
|
||||
yield return grandchild;
|
||||
}
|
||||
}
|
||||
|
||||
child = child.NextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TrySearchLeftSiblings(ProjectElement initialElement, Predicate<ProjectElement> siblingIsAcceptable, out ProjectElement referenceSibling)
|
||||
{
|
||||
return TrySearchSiblings(initialElement, siblingIsAcceptable, s => s.PreviousSibling, out referenceSibling);
|
||||
|
@ -721,44 +766,182 @@ namespace Microsoft.Build.Construction
|
|||
return referenceSibling != null;
|
||||
}
|
||||
|
||||
internal sealed class ProjectElementSiblingSubTypeCollection<T> : ICollection<T>, ICollection
|
||||
where T : ProjectElement
|
||||
{
|
||||
private readonly ProjectElement _initial;
|
||||
private readonly bool _forwards;
|
||||
private List<T> _realizedElements;
|
||||
|
||||
internal ProjectElementSiblingSubTypeCollection(ProjectElement initial, bool forwards = true)
|
||||
{
|
||||
_initial = initial;
|
||||
_forwards = forwards;
|
||||
}
|
||||
|
||||
public static ProjectElementSiblingSubTypeCollection<T> Empty { get; } = new ProjectElementSiblingSubTypeCollection<T>(initial: null);
|
||||
|
||||
public int Count => RealizedElements.Count;
|
||||
|
||||
public bool IsReadOnly => true;
|
||||
|
||||
bool ICollection.IsSynchronized => false;
|
||||
|
||||
object ICollection.SyncRoot => this;
|
||||
|
||||
private List<T> RealizedElements
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_realizedElements == null)
|
||||
{
|
||||
// Note! Don't use the List ctor which takes an IEnumerable as it casts to an ICollection and calls Count,
|
||||
// which leads to a StackOverflow exception in this implementation (see Count above)
|
||||
List<T> list = new();
|
||||
foreach (T element in this)
|
||||
{
|
||||
list.Add(element);
|
||||
}
|
||||
|
||||
_realizedElements = list;
|
||||
}
|
||||
|
||||
return _realizedElements;
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(T item) => ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection");
|
||||
|
||||
public void Clear() => ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection");
|
||||
|
||||
public bool Contains(T item) => RealizedElements.Contains(item);
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
ErrorUtilities.VerifyThrowArgumentNull(array, nameof(array));
|
||||
|
||||
if (_realizedElements != null)
|
||||
{
|
||||
_realizedElements.CopyTo(array, arrayIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = arrayIndex;
|
||||
foreach (T entry in this)
|
||||
{
|
||||
array[i] = entry;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection");
|
||||
return false;
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator() => new Enumerator(_initial, _forwards);
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
void ICollection.CopyTo(Array array, int index)
|
||||
{
|
||||
ErrorUtilities.VerifyThrowArgumentNull(array, nameof(array));
|
||||
|
||||
int i = index;
|
||||
foreach (T entry in this)
|
||||
{
|
||||
array.SetValue(entry, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
public struct Enumerator : IEnumerator<T>
|
||||
{
|
||||
// Note! Should not be readonly or we run into infinite loop issues with mutable structs
|
||||
private ProjectElementSiblingEnumerable.Enumerator _innerEnumerator;
|
||||
private T _current;
|
||||
|
||||
internal Enumerator(ProjectElement initial, bool forwards = true)
|
||||
{
|
||||
_innerEnumerator = new ProjectElementSiblingEnumerable.Enumerator(initial, forwards);
|
||||
}
|
||||
|
||||
public T Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_current != null)
|
||||
{
|
||||
return _current;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
object IEnumerator.Current => Current;
|
||||
|
||||
public readonly void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
while (_innerEnumerator.MoveNext())
|
||||
{
|
||||
ProjectElement innerCurrent = _innerEnumerator.Current;
|
||||
if (innerCurrent is T innerCurrentOfType)
|
||||
{
|
||||
_current = innerCurrentOfType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_innerEnumerator.Reset();
|
||||
_current = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerable over a series of sibling ProjectElement objects
|
||||
/// </summary>
|
||||
private struct ProjectElementSiblingEnumerable : IEnumerable<ProjectElement>
|
||||
internal readonly struct ProjectElementSiblingEnumerable : IEnumerable<ProjectElement>
|
||||
{
|
||||
/// <summary>
|
||||
/// The enumerator
|
||||
/// </summary>
|
||||
private readonly ProjectElementSiblingEnumerator _enumerator;
|
||||
private readonly Enumerator _enumerator;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor allowing reverse enumeration
|
||||
/// </summary>
|
||||
internal ProjectElementSiblingEnumerable(ProjectElement initial, bool forwards = true)
|
||||
{
|
||||
_enumerator = new ProjectElementSiblingEnumerator(initial, forwards);
|
||||
_enumerator = new Enumerator(initial, forwards);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get enumerator
|
||||
/// </summary>
|
||||
public readonly IEnumerator<ProjectElement> GetEnumerator()
|
||||
{
|
||||
return _enumerator;
|
||||
}
|
||||
public readonly IEnumerator<ProjectElement> GetEnumerator() => _enumerator;
|
||||
|
||||
/// <summary>
|
||||
/// Get non generic enumerator
|
||||
/// </summary>
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _enumerator;
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() => _enumerator;
|
||||
|
||||
/// <summary>
|
||||
/// Enumerator over a series of sibling ProjectElement objects
|
||||
/// </summary>
|
||||
private struct ProjectElementSiblingEnumerator : IEnumerator<ProjectElement>
|
||||
public struct Enumerator : IEnumerator<ProjectElement>
|
||||
{
|
||||
/// <summary>
|
||||
/// First element
|
||||
|
@ -775,7 +958,7 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Constructor taking the first element
|
||||
/// </summary>
|
||||
internal ProjectElementSiblingEnumerator(ProjectElement initial, bool forwards)
|
||||
internal Enumerator(ProjectElement initial, bool forwards)
|
||||
{
|
||||
_initial = initial;
|
||||
Current = null;
|
||||
|
@ -792,7 +975,7 @@ namespace Microsoft.Build.Construction
|
|||
/// Current element.
|
||||
/// Throws if MoveNext() hasn't been called
|
||||
/// </summary>
|
||||
object System.Collections.IEnumerator.Current
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
|
@ -51,7 +49,7 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get any contained properties.
|
||||
/// </summary>
|
||||
public ICollection<ProjectImportElement> Imports => new ReadOnlyCollection<ProjectImportElement>(Children.OfType<ProjectImportElement>());
|
||||
public ICollection<ProjectImportElement> Imports => GetChildrenOfType<ProjectImportElement>();
|
||||
|
||||
#endregion // Properties
|
||||
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
|
@ -52,7 +50,7 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get any child metadata definitions.
|
||||
/// </summary>
|
||||
public ICollection<ProjectMetadataElement> Metadata => new ReadOnlyCollection<ProjectMetadataElement>(Children.OfType<ProjectMetadataElement>());
|
||||
public ICollection<ProjectMetadataElement> Metadata => GetChildrenOfType<ProjectMetadataElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method to add a piece of metadata to this item definition.
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
|
@ -47,7 +45,7 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get a list of child item definitions.
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemDefinitionElement> ItemDefinitions => new ReadOnlyCollection<ProjectItemDefinitionElement>(Children.OfType<ProjectItemDefinitionElement>());
|
||||
public ICollection<ProjectItemDefinitionElement> ItemDefinitions => GetChildrenOfType<ProjectItemDefinitionElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method that picks a location based on a heuristic:
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
|
@ -285,7 +283,7 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get any child metadata.
|
||||
/// </summary>
|
||||
public ICollection<ProjectMetadataElement> Metadata => new ReadOnlyCollection<ProjectMetadataElement>(Children.OfType<ProjectMetadataElement>());
|
||||
public ICollection<ProjectMetadataElement> Metadata => GetChildrenOfType<ProjectMetadataElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Location of the include attribute
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
@ -55,7 +54,7 @@ namespace Microsoft.Build.Construction
|
|||
/// Get any child items.
|
||||
/// This is a live collection.
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemElement> Items => new ReadOnlyCollection<ProjectItemElement>(Children.OfType<ProjectItemElement>());
|
||||
public ICollection<ProjectItemElement> Items => GetChildrenOfType<ProjectItemElement>();
|
||||
|
||||
/// <summary>
|
||||
/// True if it is known that no child items have wildcards in their
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
|
@ -57,17 +55,17 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get an enumerator over any child item groups
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemGroupElement> ItemGroups => new ReadOnlyCollection<ProjectItemGroupElement>(Children.OfType<ProjectItemGroupElement>());
|
||||
public ICollection<ProjectItemGroupElement> ItemGroups => GetChildrenOfType<ProjectItemGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an enumerator over any child property groups
|
||||
/// </summary>
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroups => new ReadOnlyCollection<ProjectPropertyGroupElement>(Children.OfType<ProjectPropertyGroupElement>());
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroups => GetChildrenOfType<ProjectPropertyGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an enumerator over any child chooses
|
||||
/// </summary>
|
||||
public ICollection<ProjectChooseElement> ChooseElements => new ReadOnlyCollection<ProjectChooseElement>(Children.OfType<ProjectChooseElement>());
|
||||
public ICollection<ProjectChooseElement> ChooseElements => GetChildrenOfType<ProjectChooseElement>();
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
|
@ -47,12 +45,12 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get any contained properties.
|
||||
/// </summary>
|
||||
public ICollection<ProjectPropertyElement> Properties => new ReadOnlyCollection<ProjectPropertyElement>(Children.OfType<ProjectPropertyElement>());
|
||||
public ICollection<ProjectPropertyElement> Properties => GetChildrenOfType<ProjectPropertyElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get any contained properties.
|
||||
/// </summary>
|
||||
public ICollection<ProjectPropertyElement> PropertiesReversed => new ReadOnlyCollection<ProjectPropertyElement>(ChildrenReversed.OfType<ProjectPropertyElement>());
|
||||
public ICollection<ProjectPropertyElement> PropertiesReversed => GetChildrenReversedOfType<ProjectPropertyElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Convenience method that picks a location based on a heuristic:
|
||||
|
|
|
@ -287,81 +287,81 @@ namespace Microsoft.Build.Construction
|
|||
/// <remarks>
|
||||
/// The name is inconsistent to make it more understandable, per API review.
|
||||
/// </remarks>
|
||||
public ICollection<ProjectChooseElement> ChooseElements => new ReadOnlyCollection<ProjectChooseElement>(Children.OfType<ProjectChooseElement>());
|
||||
public ICollection<ProjectChooseElement> ChooseElements => GetChildrenOfType<ProjectChooseElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child item definition groups, if any
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemDefinitionGroupElement> ItemDefinitionGroups => new ReadOnlyCollection<ProjectItemDefinitionGroupElement>(Children.OfType<ProjectItemDefinitionGroupElement>());
|
||||
public ICollection<ProjectItemDefinitionGroupElement> ItemDefinitionGroups => GetChildrenOfType<ProjectItemDefinitionGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child item definitions, if any, in all item definition groups anywhere in the project file.
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemDefinitionElement> ItemDefinitions => new ReadOnlyCollection<ProjectItemDefinitionElement>(AllChildren.OfType<ProjectItemDefinitionElement>());
|
||||
public ICollection<ProjectItemDefinitionElement> ItemDefinitions => new ReadOnlyCollection<ProjectItemDefinitionElement>(GetAllChildrenOfType<ProjectItemDefinitionElement>());
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection over the child item groups, if any.
|
||||
/// Does not include any that may not be at the root, i.e. inside Choose elements.
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemGroupElement> ItemGroups => new ReadOnlyCollection<ProjectItemGroupElement>(Children.OfType<ProjectItemGroupElement>());
|
||||
public ICollection<ProjectItemGroupElement> ItemGroups => GetChildrenOfType<ProjectItemGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child items, if any, in all item groups anywhere in the project file.
|
||||
/// Not restricted to root item groups: traverses through Choose elements.
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemElement> Items => new ReadOnlyCollection<ProjectItemElement>(AllChildren.OfType<ProjectItemElement>());
|
||||
public ICollection<ProjectItemElement> Items => new ReadOnlyCollection<ProjectItemElement>(GetAllChildrenOfType<ProjectItemElement>());
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child import groups, if any.
|
||||
/// </summary>
|
||||
public ICollection<ProjectImportGroupElement> ImportGroups => new ReadOnlyCollection<ProjectImportGroupElement>(Children.OfType<ProjectImportGroupElement>());
|
||||
public ICollection<ProjectImportGroupElement> ImportGroups => GetChildrenOfType<ProjectImportGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child imports
|
||||
/// </summary>
|
||||
public ICollection<ProjectImportElement> Imports => new ReadOnlyCollection<ProjectImportElement>(AllChildren.OfType<ProjectImportElement>());
|
||||
public ICollection<ProjectImportElement> Imports => new ReadOnlyCollection<ProjectImportElement>(GetAllChildrenOfType<ProjectImportElement>());
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child property groups, if any.
|
||||
/// Does not include any that may not be at the root, i.e. inside Choose elements.
|
||||
/// </summary>
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroups => new ReadOnlyCollection<ProjectPropertyGroupElement>(Children.OfType<ProjectPropertyGroupElement>());
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroups => GetChildrenOfType<ProjectPropertyGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Geta read-only collection of the child properties, if any, in all property groups anywhere in the project file.
|
||||
/// Not restricted to root property groups: traverses through Choose elements.
|
||||
/// </summary>
|
||||
public ICollection<ProjectPropertyElement> Properties => new ReadOnlyCollection<ProjectPropertyElement>(AllChildren.OfType<ProjectPropertyElement>());
|
||||
public ICollection<ProjectPropertyElement> Properties => new ReadOnlyCollection<ProjectPropertyElement>(GetAllChildrenOfType<ProjectPropertyElement>());
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child targets
|
||||
/// </summary>
|
||||
public ICollection<ProjectTargetElement> Targets => new ReadOnlyCollection<ProjectTargetElement>(Children.OfType<ProjectTargetElement>());
|
||||
public ICollection<ProjectTargetElement> Targets => GetChildrenOfType<ProjectTargetElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child usingtasks, if any
|
||||
/// </summary>
|
||||
public ICollection<ProjectUsingTaskElement> UsingTasks => new ReadOnlyCollection<ProjectUsingTaskElement>(Children.OfType<ProjectUsingTaskElement>());
|
||||
public ICollection<ProjectUsingTaskElement> UsingTasks => GetChildrenOfType<ProjectUsingTaskElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child item groups, if any, in reverse order
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemGroupElement> ItemGroupsReversed => new ReadOnlyCollection<ProjectItemGroupElement>(ChildrenReversed.OfType<ProjectItemGroupElement>());
|
||||
public ICollection<ProjectItemGroupElement> ItemGroupsReversed => GetChildrenReversedOfType<ProjectItemGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child item definition groups, if any, in reverse order
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemDefinitionGroupElement> ItemDefinitionGroupsReversed => new ReadOnlyCollection<ProjectItemDefinitionGroupElement>(ChildrenReversed.OfType<ProjectItemDefinitionGroupElement>());
|
||||
public ICollection<ProjectItemDefinitionGroupElement> ItemDefinitionGroupsReversed => GetChildrenReversedOfType<ProjectItemDefinitionGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child import groups, if any, in reverse order
|
||||
/// </summary>
|
||||
public ICollection<ProjectImportGroupElement> ImportGroupsReversed => new ReadOnlyCollection<ProjectImportGroupElement>(ChildrenReversed.OfType<ProjectImportGroupElement>());
|
||||
public ICollection<ProjectImportGroupElement> ImportGroupsReversed => GetChildrenReversedOfType<ProjectImportGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get a read-only collection of the child property groups, if any, in reverse order
|
||||
/// </summary>
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroupsReversed => new ReadOnlyCollection<ProjectPropertyGroupElement>(ChildrenReversed.OfType<ProjectPropertyGroupElement>());
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroupsReversed => GetChildrenReversedOfType<ProjectPropertyGroupElement>();
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -702,7 +702,7 @@ namespace Microsoft.Build.Construction
|
|||
/// Not public as we do not wish to encourage the use of ProjectExtensions.
|
||||
/// </remarks>
|
||||
internal ProjectExtensionsElement ProjectExtensions
|
||||
=> ChildrenReversed.OfType<ProjectExtensionsElement>().FirstOrDefault();
|
||||
=> GetChildrenReversedOfType<ProjectExtensionsElement>().FirstOrDefault();
|
||||
|
||||
/// <summary>
|
||||
/// Returns an unlocalized indication of how this file was last dirtied.
|
||||
|
@ -1905,15 +1905,18 @@ namespace Microsoft.Build.Construction
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var sdkNode in Children.OfType<ProjectSdkElement>())
|
||||
foreach (ProjectElement child in ChildrenEnumerable)
|
||||
{
|
||||
var referencedSdk = new SdkReference(
|
||||
sdkNode.XmlElement.GetAttribute("Name"),
|
||||
sdkNode.XmlElement.GetAttribute("Version"),
|
||||
sdkNode.XmlElement.GetAttribute("MinimumVersion"));
|
||||
if (child is ProjectSdkElement sdkNode)
|
||||
{
|
||||
var referencedSdk = new SdkReference(
|
||||
sdkNode.XmlElement.GetAttribute("Name"),
|
||||
sdkNode.XmlElement.GetAttribute("Version"),
|
||||
sdkNode.XmlElement.GetAttribute("MinimumVersion"));
|
||||
|
||||
nodes.Add(ProjectImportElement.CreateImplicit("Sdk.props", currentProjectOrImport, ImplicitImportLocation.Top, referencedSdk, sdkNode));
|
||||
nodes.Add(ProjectImportElement.CreateImplicit("Sdk.targets", currentProjectOrImport, ImplicitImportLocation.Bottom, referencedSdk, sdkNode));
|
||||
nodes.Add(ProjectImportElement.CreateImplicit("Sdk.props", currentProjectOrImport, ImplicitImportLocation.Top, referencedSdk, sdkNode));
|
||||
nodes.Add(ProjectImportElement.CreateImplicit("Sdk.targets", currentProjectOrImport, ImplicitImportLocation.Bottom, referencedSdk, sdkNode));
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.Execution;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
@ -58,22 +56,22 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get an enumerator over any child item groups
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemGroupElement> ItemGroups => new ReadOnlyCollection<ProjectItemGroupElement>(Children.OfType<ProjectItemGroupElement>());
|
||||
public ICollection<ProjectItemGroupElement> ItemGroups => GetChildrenOfType<ProjectItemGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an enumerator over any child property groups
|
||||
/// </summary>
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroups => new ReadOnlyCollection<ProjectPropertyGroupElement>(Children.OfType<ProjectPropertyGroupElement>());
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroups => GetChildrenOfType<ProjectPropertyGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an enumerator over any child tasks
|
||||
/// </summary>
|
||||
public ICollection<ProjectTaskElement> Tasks => new ReadOnlyCollection<ProjectTaskElement>(Children.OfType<ProjectTaskElement>());
|
||||
public ICollection<ProjectTaskElement> Tasks => GetChildrenOfType<ProjectTaskElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an enumerator over any child onerrors
|
||||
/// </summary>
|
||||
public ICollection<ProjectOnErrorElement> OnErrors => new ReadOnlyCollection<ProjectOnErrorElement>(Children.OfType<ProjectOnErrorElement>());
|
||||
public ICollection<ProjectOnErrorElement> OnErrors => GetChildrenOfType<ProjectOnErrorElement>();
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
|
@ -126,7 +125,7 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Gets any output children.
|
||||
/// </summary>
|
||||
public ICollection<ProjectOutputElement> Outputs => new Collections.ReadOnlyCollection<ProjectOutputElement>(Children.OfType<ProjectOutputElement>());
|
||||
public ICollection<ProjectOutputElement> Outputs => GetChildrenOfType<ProjectOutputElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Enumerable over the unevaluated parameters on the task.
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
|
@ -48,17 +46,17 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get an enumerator over any child chooses
|
||||
/// </summary>
|
||||
public ICollection<ProjectChooseElement> ChooseElements => new ReadOnlyCollection<ProjectChooseElement>(Children.OfType<ProjectChooseElement>());
|
||||
public ICollection<ProjectChooseElement> ChooseElements => GetChildrenOfType<ProjectChooseElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an enumerator over any child item groups
|
||||
/// </summary>
|
||||
public ICollection<ProjectItemGroupElement> ItemGroups => new ReadOnlyCollection<ProjectItemGroupElement>(Children.OfType<ProjectItemGroupElement>());
|
||||
public ICollection<ProjectItemGroupElement> ItemGroups => GetChildrenOfType<ProjectItemGroupElement>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an enumerator over any child property groups
|
||||
/// </summary>
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroups => new ReadOnlyCollection<ProjectPropertyGroupElement>(Children.OfType<ProjectPropertyGroupElement>());
|
||||
public ICollection<ProjectPropertyGroupElement> PropertyGroups => GetChildrenOfType<ProjectPropertyGroupElement>();
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Microsoft.Build.Collections;
|
||||
using Microsoft.Build.ObjectModelRemoting;
|
||||
using Microsoft.Build.Shared;
|
||||
using ProjectXmlUtilities = Microsoft.Build.Internal.ProjectXmlUtilities;
|
||||
|
@ -59,7 +57,7 @@ namespace Microsoft.Build.Construction
|
|||
/// <summary>
|
||||
/// Get any contained parameters.
|
||||
/// </summary>
|
||||
public ICollection<ProjectUsingTaskParameterElement> Parameters => new ReadOnlyCollection<ProjectUsingTaskParameterElement>(Children.OfType<ProjectUsingTaskParameterElement>());
|
||||
public ICollection<ProjectUsingTaskParameterElement> Parameters => GetChildrenOfType<ProjectUsingTaskParameterElement>();
|
||||
|
||||
/// <summary>
|
||||
/// This does not allow conditions, so it should not be called.
|
||||
|
|
|
@ -1062,7 +1062,7 @@ namespace Microsoft.Build.Evaluation
|
|||
preserveFormatting: false);
|
||||
}
|
||||
|
||||
foreach (ProjectElement elementXml in projectRootElement.Children)
|
||||
foreach (ProjectElement elementXml in projectRootElement.ChildrenEnumerable)
|
||||
{
|
||||
ProjectUsingTaskElement usingTask = elementXml as ProjectUsingTaskElement;
|
||||
|
||||
|
|
|
@ -535,7 +535,7 @@ namespace Microsoft.Build.Evaluation
|
|||
List<ProjectTargetInstanceChild> targetChildren = new List<ProjectTargetInstanceChild>(targetElement.Count);
|
||||
List<ProjectOnErrorInstance> targetOnErrorChildren = new List<ProjectOnErrorInstance>();
|
||||
|
||||
foreach (ProjectElement targetChildElement in targetElement.Children)
|
||||
foreach (ProjectElement targetChildElement in targetElement.ChildrenEnumerable)
|
||||
{
|
||||
using (evaluationProfiler.TrackElement(targetChildElement))
|
||||
{
|
||||
|
@ -881,7 +881,7 @@ namespace Microsoft.Build.Evaluation
|
|||
}
|
||||
}
|
||||
|
||||
foreach (ProjectElement element in currentProjectOrImport.Children)
|
||||
foreach (ProjectElement element in currentProjectOrImport.ChildrenEnumerable)
|
||||
{
|
||||
switch (element)
|
||||
{
|
||||
|
@ -1499,7 +1499,7 @@ namespace Microsoft.Build.Evaluation
|
|||
{
|
||||
if (EvaluateConditionCollectingConditionedProperties(whenElement, ExpanderOptions.ExpandProperties, ParserOptions.AllowProperties))
|
||||
{
|
||||
EvaluateWhenOrOtherwiseChildren(whenElement.Children);
|
||||
EvaluateWhenOrOtherwiseChildren(whenElement.ChildrenEnumerable);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1507,7 +1507,7 @@ namespace Microsoft.Build.Evaluation
|
|||
// "Otherwise" elements never have a condition
|
||||
if (chooseElement.OtherwiseElement != null)
|
||||
{
|
||||
EvaluateWhenOrOtherwiseChildren(chooseElement.OtherwiseElement.Children);
|
||||
EvaluateWhenOrOtherwiseChildren(chooseElement.OtherwiseElement.ChildrenEnumerable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1517,7 +1517,7 @@ namespace Microsoft.Build.Evaluation
|
|||
/// Returns true if the condition was true, so subsequent
|
||||
/// WhenElements and Otherwise can be skipped.
|
||||
/// </summary>
|
||||
private bool EvaluateWhenOrOtherwiseChildren(IEnumerable<ProjectElement> children)
|
||||
private bool EvaluateWhenOrOtherwiseChildren(ProjectElementContainer.ProjectElementSiblingEnumerable children)
|
||||
{
|
||||
foreach (ProjectElement element in children)
|
||||
{
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace Microsoft.Build.Graph
|
|||
{
|
||||
public TargetSpecification(string target, bool skipIfNonexistent)
|
||||
{
|
||||
// Verify that if this target is skippable then it equals neither
|
||||
// Verify that if this target is skippable then it equals neither
|
||||
// ".default" nor ".projectReferenceTargetsOrDefaultTargets".
|
||||
ErrorUtilities.VerifyThrow(
|
||||
!skipIfNonexistent || (!target.Equals(MSBuildConstants.DefaultTargetsMarker)
|
||||
|
@ -131,6 +131,8 @@ namespace Microsoft.Build.Graph
|
|||
allowCollectionReuse: solutionConfiguration == null && !enableDynamicPlatformResolution,
|
||||
globalPropertiesModifiers);
|
||||
|
||||
bool configurationDefined = false;
|
||||
|
||||
// Match what AssignProjectConfiguration does to resolve project references.
|
||||
if (solutionConfiguration != null)
|
||||
{
|
||||
|
@ -151,6 +153,8 @@ namespace Microsoft.Build.Graph
|
|||
{
|
||||
referenceGlobalProperties.Remove(PlatformMetadataName);
|
||||
}
|
||||
|
||||
configurationDefined = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -161,11 +165,16 @@ namespace Microsoft.Build.Graph
|
|||
referenceGlobalProperties.Remove(ConfigurationMetadataName);
|
||||
referenceGlobalProperties.Remove(PlatformMetadataName);
|
||||
}
|
||||
else
|
||||
{
|
||||
configurationDefined = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Dynamic platform resolution is not enabled for sln-based builds.
|
||||
else if (!projectReferenceItem.HasMetadata(SetPlatformMetadataName) && enableDynamicPlatformResolution)
|
||||
// Note: Dynamic platform resolution is not enabled for sln-based builds,
|
||||
// unless the project isn't known to the solution.
|
||||
if (enableDynamicPlatformResolution && !configurationDefined && !projectReferenceItem.HasMetadata(SetPlatformMetadataName))
|
||||
{
|
||||
string requesterPlatform = requesterInstance.GetPropertyValue("Platform");
|
||||
string requesterPlatformLookupTable = requesterInstance.GetPropertyValue("PlatformLookupTable");
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.IO;
|
|||
using System.IO.Compression;
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Shared;
|
||||
using Microsoft.Build.Shared.FileSystem;
|
||||
|
||||
#nullable disable
|
||||
|
||||
|
@ -226,12 +227,25 @@ namespace Microsoft.Build.Logging
|
|||
|
||||
if (projectImportsCollector != null)
|
||||
{
|
||||
projectImportsCollector.Close();
|
||||
|
||||
if (CollectProjectImports == ProjectImportsCollectionMode.Embed)
|
||||
{
|
||||
eventArgsWriter.WriteBlob(BinaryLogRecordKind.ProjectImportArchive, projectImportsCollector.GetAllBytes());
|
||||
var archiveFilePath = projectImportsCollector.ArchiveFilePath;
|
||||
|
||||
// It is possible that the archive couldn't be created for some reason.
|
||||
// Only embed it if it actually exists.
|
||||
if (FileSystems.Default.FileExists(archiveFilePath))
|
||||
{
|
||||
using (FileStream fileStream = File.OpenRead(archiveFilePath))
|
||||
{
|
||||
eventArgsWriter.WriteBlob(BinaryLogRecordKind.ProjectImportArchive, fileStream);
|
||||
}
|
||||
|
||||
File.Delete(archiveFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
projectImportsCollector.Close();
|
||||
projectImportsCollector = null;
|
||||
}
|
||||
|
||||
|
|
|
@ -218,6 +218,17 @@ namespace Microsoft.Build.Logging
|
|||
Write(bytes);
|
||||
}
|
||||
|
||||
public void WriteBlob(BinaryLogRecordKind kind, Stream stream)
|
||||
{
|
||||
// write the blob directly to the underlying writer,
|
||||
// bypassing the memory stream
|
||||
using var redirection = RedirectWritesToOriginalWriter();
|
||||
|
||||
Write(kind);
|
||||
Write(stream.Length);
|
||||
Write(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switches the binaryWriter used by the Write* methods to the direct underlying stream writer
|
||||
/// until the disposable is disposed. Useful to bypass the currentRecordWriter to write a string,
|
||||
|
@ -1091,6 +1102,11 @@ namespace Microsoft.Build.Logging
|
|||
binaryWriter.Write(bytes);
|
||||
}
|
||||
|
||||
private void Write(Stream stream)
|
||||
{
|
||||
stream.CopyTo(binaryWriter.BaseStream);
|
||||
}
|
||||
|
||||
private void Write(byte b)
|
||||
{
|
||||
binaryWriter.Write(b);
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.IO;
|
|||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Build.Shared;
|
||||
|
||||
#nullable disable
|
||||
|
||||
|
@ -20,30 +21,10 @@ namespace Microsoft.Build.Logging
|
|||
/// </summary>
|
||||
internal class ProjectImportsCollector
|
||||
{
|
||||
private Stream _stream;
|
||||
public byte[] GetAllBytes()
|
||||
{
|
||||
if (_stream == null)
|
||||
{
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
else if (ArchiveFilePath == null)
|
||||
{
|
||||
var stream = _stream as MemoryStream;
|
||||
// Before we can use the zip archive, it must be closed.
|
||||
Close(false);
|
||||
return stream.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
return File.ReadAllBytes(ArchiveFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
private Stream _fileStream;
|
||||
private ZipArchive _zipArchive;
|
||||
|
||||
private string ArchiveFilePath { get; set; }
|
||||
public string ArchiveFilePath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Avoid visiting each file more than once.
|
||||
|
@ -55,33 +36,46 @@ namespace Microsoft.Build.Logging
|
|||
|
||||
public ProjectImportsCollector(string logFilePath, bool createFile, string sourcesArchiveExtension = ".ProjectImports.zip")
|
||||
{
|
||||
if (createFile)
|
||||
{
|
||||
// Archive file will be stored alongside the binlog
|
||||
ArchiveFilePath = Path.ChangeExtension(logFilePath, sourcesArchiveExtension);
|
||||
}
|
||||
else
|
||||
{
|
||||
string cacheDirectory = FileUtilities.GetCacheDirectory();
|
||||
if (!Directory.Exists(cacheDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(cacheDirectory);
|
||||
}
|
||||
|
||||
// Archive file will be temporarily stored in MSBuild cache folder and deleted when no longer needed
|
||||
ArchiveFilePath = Path.Combine(
|
||||
cacheDirectory,
|
||||
Path.ChangeExtension(
|
||||
Path.GetFileName(logFilePath),
|
||||
sourcesArchiveExtension));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (createFile)
|
||||
{
|
||||
ArchiveFilePath = Path.ChangeExtension(logFilePath, sourcesArchiveExtension);
|
||||
_stream = new FileStream(ArchiveFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stream = new MemoryStream();
|
||||
}
|
||||
_zipArchive = new ZipArchive(_stream, ZipArchiveMode.Create, true);
|
||||
_fileStream = new FileStream(ArchiveFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete);
|
||||
_zipArchive = new ZipArchive(_fileStream, ZipArchiveMode.Create);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// For some reason we weren't able to create a file for the archive.
|
||||
// Disable the file collector.
|
||||
_stream = null;
|
||||
_fileStream = null;
|
||||
_zipArchive = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFile(string filePath)
|
||||
{
|
||||
if (filePath != null && _stream != null)
|
||||
if (filePath != null && _fileStream != null)
|
||||
{
|
||||
lock (_stream)
|
||||
lock (_fileStream)
|
||||
{
|
||||
// enqueue the task to add a file and return quickly
|
||||
// to avoid holding up the current thread
|
||||
|
@ -101,9 +95,9 @@ namespace Microsoft.Build.Logging
|
|||
|
||||
public void AddFileFromMemory(string filePath, string data)
|
||||
{
|
||||
if (filePath != null && data != null && _stream != null)
|
||||
if (filePath != null && data != null && _fileStream != null)
|
||||
{
|
||||
lock (_stream)
|
||||
lock (_fileStream)
|
||||
{
|
||||
// enqueue the task to add a file and return quickly
|
||||
// to avoid holding up the current thread
|
||||
|
@ -197,7 +191,7 @@ namespace Microsoft.Build.Logging
|
|||
return archivePath;
|
||||
}
|
||||
|
||||
public void Close(bool closeStream = true)
|
||||
public void Close()
|
||||
{
|
||||
// wait for all pending file writes to complete
|
||||
_currentTask.Wait();
|
||||
|
@ -208,10 +202,10 @@ namespace Microsoft.Build.Logging
|
|||
_zipArchive = null;
|
||||
}
|
||||
|
||||
if (closeStream && (_stream != null))
|
||||
if (_fileStream != null)
|
||||
{
|
||||
_stream.Dispose();
|
||||
_stream = null;
|
||||
_fileStream.Dispose();
|
||||
_fileStream = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
<PackageReference Update="Microsoft.NETCore.App" PrivateAssets="All" />
|
||||
|
||||
<!-- Configure analyzer to forbid certain API calls -->
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt" />
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt" Condition=" '$(IsUnitTestProject)' != 'true' " />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(GenerateReferenceAssemblySource)' == 'true'">
|
||||
|
|
|
@ -1498,8 +1498,8 @@ namespace Microsoft.Build.CommandLine
|
|||
}
|
||||
finally
|
||||
{
|
||||
FileUtilities.ClearCacheDirectory();
|
||||
projectCollection?.Dispose();
|
||||
FileUtilities.ClearCacheDirectory();
|
||||
|
||||
// Build manager shall be reused for all build sessions.
|
||||
// If, for one reason or another, this behavior needs to change in future
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Microsoft.Build.Collections
|
|||
/// Thus this is an omission from the BCL.
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">Type of element in the collection</typeparam>
|
||||
internal class ReadOnlyCollection<T> : ICollection<T>, ICollection
|
||||
internal sealed class ReadOnlyCollection<T> : ICollection<T>, ICollection
|
||||
{
|
||||
/// <summary>
|
||||
/// Backing live enumerable.
|
||||
|
|
|
@ -1648,7 +1648,6 @@ Copyright (C) Microsoft Corporation. All rights reserved.
|
|||
Configuration information. See AssignProjectConfiguration -->
|
||||
<Target Name="_GetProjectReferencePlatformProperties"
|
||||
Condition="'$(EnableDynamicPlatformResolution)' == 'true'
|
||||
and '$(CurrentSolutionConfigurationContents)' == ''
|
||||
and '@(_MSBuildProjectReferenceExistent)' != ''">
|
||||
|
||||
<!-- Allow preset SetPlatform to override this operation -->
|
||||
|
|
Загрузка…
Ссылка в новой задаче