> Metadata(Expander exp
{
// It may be that the itemspec has unescaped ';'s in it so we need to split here to handle
// that case.
- if (metadataValue.IndexOf(';') >= 0)
+ if (metadataValue.Contains(';'))
{
var splits = ExpressionShredder.SplitSemiColonSeparatedList(metadataValue);
@@ -3095,36 +3099,23 @@ private static partial class RegularExpressions
* description of an item vector changes, the expressions must be updated in both places.
*************************************************************************************************************************/
-
-
-#if NET7_0_OR_GREATER
+#if NET
[GeneratedRegex(ItemMetadataSpecification, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture)]
- internal static partial Regex ItemMetadataPattern();
+ internal static partial Regex ItemMetadataRegex { get; }
#else
///
/// Regular expression used to match item metadata references embedded in strings.
/// For example, %(Compile.DependsOn) or %(DependsOn).
///
- internal static readonly Lazy ItemMetadataPattern = new Lazy(
- () => new Regex(ItemMetadataSpecification,
- RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture | RegexOptions.Compiled));
-#endif
+ internal static Regex ItemMetadataRegex => s_itemMetadataRegex ??=
+ new Regex(ItemMetadataSpecification, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
- internal static Regex ItemMetadataRegex
- {
- get
- {
-#if NET7_0_OR_GREATER
- return ItemMetadataPattern();
-#else
- return ItemMetadataPattern.Value;
+ internal static Regex s_itemMetadataRegex;
#endif
- }
- }
- ///
- /// Name of the group matching the "name" of a metadatum.
- ///
+ ///
+ /// Name of the group matching the "name" of a metadatum.
+ ///
internal const string NameGroup = "NAME";
///
@@ -3143,29 +3134,19 @@ internal static Regex ItemMetadataRegex
ItemVectorWithTransformLHS + @")" + ItemMetadataSpecification + @"(?!" +
ItemVectorWithTransformRHS + @"))";
-#if NET7_0_OR_GREATER
+#if NET
[GeneratedRegex(NonTransformItemMetadataSpecification, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture)]
- internal static partial Regex NonTransformItemMetadataPattern();
+ internal static partial Regex NonTransformItemMetadataRegex { get; }
#else
///
/// regular expression used to match item metadata references outside of item vector transforms.
///
/// PERF WARNING: this Regex is complex and tends to run slowly.
- internal static readonly Lazy NonTransformItemMetadataPattern = new Lazy(
- () => new Regex(NonTransformItemMetadataSpecification,
- RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture | RegexOptions.Compiled));
-#endif
- internal static Regex NonTransformItemMetadataRegex
- {
- get
- {
-#if NET7_0_OR_GREATER
- return NonTransformItemMetadataPattern();
-#else
- return NonTransformItemMetadataPattern.Value;
+ private static Regex s_nonTransformItemMetadataPattern;
+
+ internal static Regex NonTransformItemMetadataRegex => s_nonTransformItemMetadataPattern ??=
+ new Regex(NonTransformItemMetadataSpecification, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
#endif
- }
- }
///
/// Complete description of an item metadata reference, including the optional qualifying item type.
@@ -4114,8 +4095,8 @@ private static object[] CoerceArguments(object[] args, ParameterInfo[] parameter
else if (parameters[n].ParameterType.GetTypeInfo().IsEnum && args[n] is string v && v.Contains("."))
{
Type enumType = parameters[n].ParameterType;
- string typeLeafName = enumType.Name + ".";
- string typeFullName = enumType.FullName + ".";
+ string typeLeafName = $"{enumType.Name}.";
+ string typeFullName = $"{enumType.FullName}.";
// Enum.parse expects commas between enum components
// We'll support the C# type | syntax too
@@ -4200,11 +4181,11 @@ private string GenerateStringOfMethodExecuted(string expression, object objectIn
}
if ((_bindingFlags & BindingFlags.InvokeMethod) == BindingFlags.InvokeMethod)
{
- return "[" + typeName + "]::" + name + "(" + parameters + ")";
+ return $"[{typeName}]::{name}({parameters})";
}
else
{
- return "[" + typeName + "]::" + name;
+ return $"[{typeName}]::{name}";
}
}
else
@@ -4213,11 +4194,11 @@ private string GenerateStringOfMethodExecuted(string expression, object objectIn
if ((_bindingFlags & BindingFlags.InvokeMethod) == BindingFlags.InvokeMethod)
{
- return propertyValue + "." + name + "(" + parameters + ")";
+ return $"{propertyValue}.{name}({parameters})";
}
else
{
- return propertyValue + "." + name;
+ return $"{propertyValue}.{name}";
}
}
}
diff --git a/src/Build/Evaluation/Expander/ArgumentParser.cs b/src/Build/Evaluation/Expander/ArgumentParser.cs
index ca4039aae5d..c2dd113d5ff 100644
--- a/src/Build/Evaluation/Expander/ArgumentParser.cs
+++ b/src/Build/Evaluation/Expander/ArgumentParser.cs
@@ -2,11 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections.Generic;
using System.Globalization;
+#if NETFRAMEWORK
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+#endif
namespace Microsoft.Build.Evaluation.Expander
{
diff --git a/src/Build/Evaluation/Expander/WellKnownFunctions.cs b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
index 72f8b247933..d6bd9de96d3 100644
--- a/src/Build/Evaluation/Expander/WellKnownFunctions.cs
+++ b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
@@ -2,16 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Reflection;
using System.Runtime.CompilerServices;
-using System.Text;
using System.Text.RegularExpressions;
-using System.Threading.Tasks;
using Microsoft.Build.BackEnd.Logging;
-using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
using Microsoft.Build.Shared.FileSystem;
@@ -236,7 +231,7 @@ internal static bool TryExecuteStringFunction(string methodName, out object? ret
{
if (ParseArgs.TryGetArg(args, out string? arg0) && arg0 != null)
{
- returnVal = text.IndexOfAny(arg0.ToCharArray());
+ returnVal = text.AsSpan().IndexOfAny(arg0.AsSpan());
return true;
}
}
@@ -262,7 +257,7 @@ internal static bool TryExecuteStringFunction(string methodName, out object? ret
{
if (ParseArgs.TryGetArg(args, out string? arg0) && arg0 != null)
{
- returnVal = text.LastIndexOfAny(arg0.ToCharArray());
+ returnVal = text.AsSpan().LastIndexOfAny(arg0.AsSpan());
return true;
}
}
diff --git a/src/Build/Evaluation/ExpressionShredder.cs b/src/Build/Evaluation/ExpressionShredder.cs
index fd102dff143..a7d9e48b9a5 100644
--- a/src/Build/Evaluation/ExpressionShredder.cs
+++ b/src/Build/Evaluation/ExpressionShredder.cs
@@ -428,7 +428,7 @@ private static void GetReferencedItemNamesAndMetadata(string expression, int sta
itemName = firstPart;
metadataName = expression.Substring(startOfText, i - startOfText);
- qualifiedMetadataName = itemName + "." + metadataName;
+ qualifiedMetadataName = $"{itemName}.{metadataName}";
}
else
{
diff --git a/src/Build/Evaluation/IItemFactory.cs b/src/Build/Evaluation/IItemFactory.cs
index 9624d90a562..d0f26ffd63b 100644
--- a/src/Build/Evaluation/IItemFactory.cs
+++ b/src/Build/Evaluation/IItemFactory.cs
@@ -3,7 +3,6 @@
using System.Collections.Generic;
using Microsoft.Build.Construction;
-using Microsoft.Build.Shared;
#nullable disable
diff --git a/src/Build/Evaluation/IntrinsicFunctions.cs b/src/Build/Evaluation/IntrinsicFunctions.cs
index 032f95a251c..fc86d54e613 100644
--- a/src/Build/Evaluation/IntrinsicFunctions.cs
+++ b/src/Build/Evaluation/IntrinsicFunctions.cs
@@ -4,9 +4,13 @@
using System;
using System.Collections.Generic;
using System.IO;
+#if NETFRAMEWORK
+using System.Linq;
+#endif
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
+using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Build.BackEnd.Logging;
@@ -18,8 +22,6 @@
using Microsoft.Build.Utilities;
using Microsoft.NET.StringTools;
using Microsoft.Win32;
-using System.Linq;
-
// Needed for DoesTaskHostExistForParameters
using NodeProviderOutOfProcTaskHost = Microsoft.Build.BackEnd.NodeProviderOutOfProcTaskHost;
@@ -40,24 +42,13 @@ internal static partial class IntrinsicFunctions
private static readonly object[] DefaultRegistryViews = [RegistryView.Default];
#pragma warning restore CA1416
-#if NET7_0_OR_GREATER
+#if NET
[GeneratedRegex(RegistrySdkSpecification, RegexOptions.IgnoreCase)]
- private static partial Regex RegistrySdkPattern();
-#else
- private static readonly Lazy RegistrySdkPattern = new Lazy(() => new Regex(RegistrySdkSpecification, RegexOptions.IgnoreCase));
-#endif
-
- private static Regex RegistrySdkRegex
- {
- get
- {
-#if NET7_0_OR_GREATER
- return RegistrySdkPattern();
+ private static partial Regex RegistrySdkRegex { get; }
#else
- return RegistrySdkPattern.Value;
+ private static Regex s_registrySdkRegex;
+ private static Regex RegistrySdkRegex => s_registrySdkRegex ??= new Regex(RegistrySdkSpecification, RegexOptions.IgnoreCase);
#endif
- }
- }
private static readonly Lazy NuGetFramework = new Lazy(() => NuGetFrameworkWrapper.CreateInstance());
@@ -284,8 +275,8 @@ internal static object GetRegistryValueFromView(string keyName, string valueName
{
if (viewObject is string viewAsString)
{
- string typeLeafName = typeof(RegistryView).Name + ".";
- string typeFullName = typeof(RegistryView).FullName + ".";
+ string typeLeafName = $"{typeof(RegistryView).Name}.";
+ string typeFullName = $"{typeof(RegistryView).FullName}.";
// We'll allow the user to specify the leaf or full type name on the RegistryView enum
viewAsString = viewAsString.Replace(typeFullName, "").Replace(typeLeafName, "");
@@ -466,7 +457,12 @@ internal static object StableStringHash(string toHash, StringHashingAlgorithm al
private static string CalculateSha256(string toHash)
{
- using var sha = System.Security.Cryptography.SHA256.Create();
+#if NET
+ Span hash = stackalloc byte[SHA256.HashSizeInBytes];
+ SHA256.HashData(Encoding.UTF8.GetBytes(toHash), hash);
+ return Convert.ToHexStringLower(hash);
+#else
+ using var sha = SHA256.Create();
var hashResult = new StringBuilder();
foreach (byte theByte in sha.ComputeHash(Encoding.UTF8.GetBytes(toHash)))
{
@@ -474,6 +470,7 @@ private static string CalculateSha256(string toHash)
}
return hashResult.ToString();
+#endif
}
///
@@ -651,14 +648,15 @@ internal static string SubstringByAsciiChars(string input, int start, int length
{
return string.Empty;
}
+
if (start + length > input.Length)
{
length = input.Length - start;
}
+
StringBuilder sb = new StringBuilder();
- for (int i = start; i < start + length; i++)
+ foreach (char c in input.AsSpan(start, length))
{
- char c = input[i];
if (c >= 32 && c <= 126 && !FileUtilities.InvalidFileNameChars.Contains(c))
{
sb.Append(c);
@@ -668,6 +666,7 @@ internal static string SubstringByAsciiChars(string input, int start, int length
sb.Append('_');
}
}
+
return sb.ToString();
}
@@ -804,7 +803,7 @@ private static RegistryKey GetBaseKeyFromKeyName(string keyName, RegistryView vi
}
else
{
- subKeyName = keyName.Substring(i + 1, keyName.Length - i - 1);
+ subKeyName = keyName.Substring(i + 1);
}
return basekey;
diff --git a/src/Build/Evaluation/ItemSpec.cs b/src/Build/Evaluation/ItemSpec.cs
index 30400c410f6..26138e50b92 100644
--- a/src/Build/Evaluation/ItemSpec.cs
+++ b/src/Build/Evaluation/ItemSpec.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Globbing;
using Microsoft.Build.Internal;
using Microsoft.Build.Shared;
diff --git a/src/Build/Evaluation/LazyItemEvaluator.ItemFactoryWrapper.cs b/src/Build/Evaluation/LazyItemEvaluator.ItemFactoryWrapper.cs
index 99c7166189b..f83ef9635c8 100644
--- a/src/Build/Evaluation/LazyItemEvaluator.ItemFactoryWrapper.cs
+++ b/src/Build/Evaluation/LazyItemEvaluator.ItemFactoryWrapper.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using Microsoft.Build.Construction;
-using Microsoft.Build.Shared;
#nullable disable
diff --git a/src/Build/Evaluation/LazyItemEvaluator.OrderedItemDataCollection.cs b/src/Build/Evaluation/LazyItemEvaluator.OrderedItemDataCollection.cs
index ff6e6d700ee..3e9a03753da 100644
--- a/src/Build/Evaluation/LazyItemEvaluator.OrderedItemDataCollection.cs
+++ b/src/Build/Evaluation/LazyItemEvaluator.OrderedItemDataCollection.cs
@@ -41,7 +41,6 @@ internal Builder(ImmutableList.Builder listBuilder)
#region IEnumerable implementation
- private ImmutableList.Enumerator GetEnumerator() => _listBuilder.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _listBuilder.GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => _listBuilder.GetEnumerator();
diff --git a/src/Build/Evaluation/LazyItemEvaluator.RemoveOperation.cs b/src/Build/Evaluation/LazyItemEvaluator.RemoveOperation.cs
index 771b0e6ce40..51d91cce6d7 100644
--- a/src/Build/Evaluation/LazyItemEvaluator.RemoveOperation.cs
+++ b/src/Build/Evaluation/LazyItemEvaluator.RemoveOperation.cs
@@ -29,7 +29,7 @@ public RemoveOperation(RemoveOperationBuilder builder, LazyItemEvaluator(builder.MatchOnMetadataOptions, _matchOnMetadata, _itemSpec);
}
@@ -48,7 +48,7 @@ protected override void ApplyImpl(OrderedItemDataCollection.Builder listBuilder,
return;
}
- bool matchingOnMetadata = _matchOnMetadata.Any();
+ bool matchingOnMetadata = !_matchOnMetadata.IsEmpty;
if (!matchingOnMetadata)
{
if (ItemspecContainsASingleBareItemReference(_itemSpec, _itemElement.ItemType))
diff --git a/src/Build/Evaluation/Preprocessor.cs b/src/Build/Evaluation/Preprocessor.cs
index 0d38472e450..d70e8327285 100644
--- a/src/Build/Evaluation/Preprocessor.cs
+++ b/src/Build/Evaluation/Preprocessor.cs
@@ -26,6 +26,9 @@ namespace Microsoft.Build.Evaluation
///
internal class Preprocessor
{
+ /// 140 equal signs.
+ private const string Equals140 = "============================================================================================================================================";
+
///
/// Project to preprocess
///
@@ -99,7 +102,7 @@ private XmlDocument Preprocess()
if (!String.IsNullOrEmpty(_project.FullPath)) // Ignore in-memory projects
{
- destinationDocument.AppendChild(destinationDocument.CreateComment("\r\n" + new String('=', 140) + "\r\n" + _project.FullPath.Replace("--", "__") + "\r\n" + new String('=', 140) + "\r\n"));
+ destinationDocument.AppendChild(destinationDocument.CreateComment($"\r\n{Equals140}\r\n{_project.FullPath.Replace("--", "__")}\r\n{Equals140}\r\n"));
}
CloneChildrenResolvingImports(outerDocument, destinationDocument);
@@ -310,7 +313,7 @@ private void CloneChildrenResolvingImports(XmlNode source, XmlNode destination)
}
destination.AppendChild(destinationDocument.CreateComment(
- $"\r\n{new String('=', 140)}\r\n{importTag}\r\n\r\n{resolved.FullPath.Replace("--", "__")}\r\n{new String('=', 140)}\r\n"));
+ $"\r\n{Equals140}\r\n{importTag}\r\n\r\n{resolved.FullPath.Replace("--", "__")}\r\n{Equals140}\r\n"));
_filePaths.Push(resolved.FullPath);
CloneChildrenResolvingImports(innerDocument, destination);
@@ -318,11 +321,11 @@ private void CloneChildrenResolvingImports(XmlNode source, XmlNode destination)
if (i < resolvedList.Count - 1)
{
- destination.AppendChild(destinationDocument.CreateComment("\r\n" + new String('=', 140) + "\r\n \r\n" + new String('=', 140) + "\r\n"));
+ destination.AppendChild(destinationDocument.CreateComment($"\r\n{Equals140}\r\n \r\n{Equals140}\r\n"));
}
else
{
- destination.AppendChild(destinationDocument.CreateComment("\r\n" + new String('=', 140) + "\r\n \r\n\r\n" + _filePaths.Peek()?.Replace("--", "__") + "\r\n" + new String('=', 140) + "\r\n"));
+ destination.AppendChild(destinationDocument.CreateComment($"\r\n{Equals140}\r\n \r\n\r\n{_filePaths.Peek()?.Replace("--", "__")}\r\n{Equals140}\r\n"));
}
}
@@ -339,7 +342,7 @@ private void CloneChildrenResolvingImports(XmlNode source, XmlNode destination)
CloneChildrenResolvingImports(child, destination);
- destination.AppendChild(destinationDocument.CreateComment("" + XMakeElements.importGroup + ">"));
+ destination.AppendChild(destinationDocument.CreateComment($"{XMakeElements.importGroup}>"));
continue;
}
diff --git a/src/Build/Evaluation/Profiler/EvaluationLocationMarkdownPrettyPrinter.cs b/src/Build/Evaluation/Profiler/EvaluationLocationMarkdownPrettyPrinter.cs
index 065f756fede..99f4bfdf8c6 100644
--- a/src/Build/Evaluation/Profiler/EvaluationLocationMarkdownPrettyPrinter.cs
+++ b/src/Build/Evaluation/Profiler/EvaluationLocationMarkdownPrettyPrinter.cs
@@ -38,14 +38,19 @@ protected override string NormalizeExpression(string description, EvaluationLoca
return null;
}
- text = text.Replace(Separator, "\\" + Separator);
+ text = text.Replace(Separator, $"\\{Separator}");
if (text.Length > 100)
{
- text = text.Remove(100) + "...";
+ text =
+#if NET
+ $"{text.AsSpan(0, 100)}...";
+#else
+ $"{text.Remove(100)}...";
+#endif
}
- return '`' + text + '`';
+ return $"`{text}`";
}
}
}
diff --git a/src/Build/Evaluation/Profiler/EvaluationLocationPrettyPrinterBase.cs b/src/Build/Evaluation/Profiler/EvaluationLocationPrettyPrinterBase.cs
index a1e8dc7f30d..ea8876e874f 100644
--- a/src/Build/Evaluation/Profiler/EvaluationLocationPrettyPrinterBase.cs
+++ b/src/Build/Evaluation/Profiler/EvaluationLocationPrettyPrinterBase.cs
@@ -65,7 +65,7 @@ protected static string GetElementOrConditionText(string description, Evaluation
var outerXml = description;
outerXml = outerXml.Replace(@"xmlns=""http://schemas.microsoft.com/developer/msbuild/2003""", "");
- var newLineIndex = outerXml.IndexOfAny(['\r', '\n']);
+ var newLineIndex = outerXml.AsSpan().IndexOfAny('\r', '\n');
return newLineIndex == -1 ? outerXml : outerXml.Remove(newLineIndex);
}
@@ -74,9 +74,19 @@ protected static string GetElementOrConditionText(string description, Evaluation
///
protected void AppendDefaultHeaderWithSeparator(StringBuilder stringBuilder, string separator)
{
- stringBuilder.AppendLine(
- string.Join(separator, "Id", "ParentId", "Pass", "File", "Line #", "Expression", "Inc (ms)", "Inc (%)", "Exc (ms)",
- "Exc (%)", "#", "Kind", "Bug"));
+ stringBuilder.Append("Id").Append(separator)
+ .Append("ParentId").Append(separator)
+ .Append("Pass").Append(separator)
+ .Append("File").Append(separator)
+ .Append("Line #").Append(separator)
+ .Append("Expression").Append(separator)
+ .Append("Inc (ms)").Append(separator)
+ .Append("Inc (%)").Append(separator)
+ .Append("Exc (ms)").Append(separator)
+ .Append("Exc (%)").Append(separator)
+ .Append('#').Append(separator)
+ .Append("Kind").Append(separator)
+ .Append("Bug").AppendLine();
}
///
@@ -92,9 +102,9 @@ protected void AppendDefaultLocationWithSeparator(StringBuilder stringBuilder, T
evaluationLocation.Line?.ToString() ?? string.Empty,
NormalizeExpression(evaluationLocation.ElementDescription, evaluationLocation.Kind) ?? string.Empty,
GetMilliseconds(profiledLocation.InclusiveTime),
- GetPercentage(totalTime, profiledLocation.InclusiveTime) + "%",
+ $"{GetPercentage(totalTime, profiledLocation.InclusiveTime)}%",
GetMilliseconds(profiledLocation.ExclusiveTime),
- GetPercentage(totalTime, profiledLocation.ExclusiveTime) + "%",
+ $"{GetPercentage(totalTime, profiledLocation.ExclusiveTime)}%",
profiledLocation.NumberOfHits,
evaluationLocation.Kind + separator));
}
diff --git a/src/Build/Evaluation/ProjectParser.cs b/src/Build/Evaluation/ProjectParser.cs
index 3427a49260d..a71a572677d 100644
--- a/src/Build/Evaluation/ProjectParser.cs
+++ b/src/Build/Evaluation/ProjectParser.cs
@@ -577,7 +577,7 @@ private ProjectTargetElement ParseProjectTargetElement(XmlElementWithLocation el
// Orcas compat: all target names are automatically unescaped
string targetName = EscapingUtilities.UnescapeAll(ProjectXmlUtilities.GetAttributeValue(element, XMakeAttributes.name));
- int indexOfSpecialCharacter = targetName.IndexOfAny(XMakeElements.InvalidTargetNameCharacters);
+ int indexOfSpecialCharacter = targetName.AsSpan().IndexOfAny(XMakeElements.InvalidTargetNameCharacters);
if (indexOfSpecialCharacter >= 0)
{
ProjectErrorUtilities.ThrowInvalidProject(element.GetAttributeLocation(XMakeAttributes.name), "NameInvalid", targetName, targetName[indexOfSpecialCharacter]);
diff --git a/src/Build/Evaluation/ProjectRootElementCache.cs b/src/Build/Evaluation/ProjectRootElementCache.cs
index d70e5648f3e..c97ebad4bff 100644
--- a/src/Build/Evaluation/ProjectRootElementCache.cs
+++ b/src/Build/Evaluation/ProjectRootElementCache.cs
@@ -7,7 +7,6 @@
using System.Diagnostics;
using System.Globalization;
using System.IO;
-using System.Linq;
using System.Xml;
using Microsoft.Build.Collections;
using Microsoft.Build.Construction;
@@ -79,7 +78,7 @@ internal class ProjectRootElementCache : ProjectRootElementCacheBase
///
/// Whether the cache should log activity to the Debug.Out stream
///
- private static bool s_debugLogCacheActivity = Environment.GetEnvironmentVariable("MSBUILDDEBUGXMLCACHE") == "1";
+ private static readonly bool s_debugLogCacheActivity = Environment.GetEnvironmentVariable("MSBUILDDEBUGXMLCACHE") == "1";
///
/// Whether the cache should check file content for cache entry invalidation.
@@ -87,7 +86,7 @@ internal class ProjectRootElementCache : ProjectRootElementCacheBase
///
/// Value shall be true only in case of testing. Outside QA tests it shall be false.
///
- private static bool s_сheckFileContent = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDCACHECHECKFILECONTENT"));
+ private static readonly bool s_сheckFileContent = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSBUILDCACHECHECKFILECONTENT"));
#if DEBUG
///
@@ -100,7 +99,7 @@ private struct ReentrancyGuard : IDisposable
/// Shall be always 0 or 1. Reentrance to the Get function (value > 1) could lead to race condition.
///
[ThreadStatic]
- private static int s_getEntriesNumber = 0;
+ private static int s_getEntriesNumber;
public ReentrancyGuard()
{
@@ -674,7 +673,7 @@ private void DebugTraceCache(string message, string param1)
if (s_debugLogCacheActivity)
{
string prefix = OutOfProcNode.IsOutOfProcNode ? "C" : "P";
- Trace.WriteLine(prefix + " " + EnvironmentUtilities.CurrentProcessId + " | " + message + param1);
+ Trace.WriteLine($"{prefix} {Process.GetCurrentProcess().Id} | {message}{param1}");
}
}
}
diff --git a/src/Build/Evaluation/StringMetadataTable.cs b/src/Build/Evaluation/StringMetadataTable.cs
index 5e920a99c23..277c5d829d9 100644
--- a/src/Build/Evaluation/StringMetadataTable.cs
+++ b/src/Build/Evaluation/StringMetadataTable.cs
@@ -69,7 +69,7 @@ public string GetEscapedValueIfPresent(string itemType, string name)
}
else
{
- key = itemType + "." + name;
+ key = $"{itemType}.{name}";
}
string value;
diff --git a/src/Build/FileSystem/DirectoryCacheFileSystemWrapper.cs b/src/Build/FileSystem/DirectoryCacheFileSystemWrapper.cs
index 9d259bda8c6..992e89967f0 100644
--- a/src/Build/FileSystem/DirectoryCacheFileSystemWrapper.cs
+++ b/src/Build/FileSystem/DirectoryCacheFileSystemWrapper.cs
@@ -1,12 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Microsoft.Build.Shared;
-using Microsoft.Build.Shared.FileSystem;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using Microsoft.Build.Shared;
+using Microsoft.Build.Shared.FileSystem;
#if FEATURE_MSIOREDIST
using Path = Microsoft.IO.Path;
diff --git a/src/Build/Globbing/MSBuildGlob.cs b/src/Build/Globbing/MSBuildGlob.cs
index e6cb8ab1ac5..38915e44cd3 100644
--- a/src/Build/Globbing/MSBuildGlob.cs
+++ b/src/Build/Globbing/MSBuildGlob.cs
@@ -47,7 +47,7 @@ public GlobState(string globRoot, string fileSpec, bool isLegal, string fixedDir
}
// Cache of Regex objects that we have created and are still alive.
- private static WeakValueDictionary s_regexCache = new WeakValueDictionary();
+ private static readonly WeakValueDictionary s_regexCache = new WeakValueDictionary();
private readonly Lazy _state;
diff --git a/src/Build/Graph/GraphBuildRequestData.cs b/src/Build/Graph/GraphBuildRequestData.cs
index 4d95ec0afe7..3d67ecf9eb2 100644
--- a/src/Build/Graph/GraphBuildRequestData.cs
+++ b/src/Build/Graph/GraphBuildRequestData.cs
@@ -5,8 +5,9 @@
using System.Collections.Immutable;
using System.Linq;
using Microsoft.Build.Execution;
+#if NETFRAMEWORK
using Microsoft.Build.Experimental.BuildCheck;
-using Microsoft.Build.Framework;
+#endif
using Microsoft.Build.Shared;
namespace Microsoft.Build.Graph
diff --git a/src/Build/Graph/GraphBuildSubmission.cs b/src/Build/Graph/GraphBuildSubmission.cs
index 164cfc8e377..a7280646e08 100644
--- a/src/Build/Graph/GraphBuildSubmission.cs
+++ b/src/Build/Graph/GraphBuildSubmission.cs
@@ -2,9 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Globalization;
using System.Threading;
-using Microsoft.Build.BackEnd;
using Microsoft.Build.Execution;
using Microsoft.Build.Shared;
diff --git a/src/Build/Graph/GraphBuilder.cs b/src/Build/Graph/GraphBuilder.cs
index 311392df81f..3a30af61030 100644
--- a/src/Build/Graph/GraphBuilder.cs
+++ b/src/Build/Graph/GraphBuilder.cs
@@ -205,9 +205,9 @@ private static void AddEdgesFromSolution(IReadOnlyDictionary value))
{
- projectsByPath[projectPath].Add(project.Value.GraphNode);
+ value.Add(project.Value.GraphNode);
}
else
{
@@ -662,8 +662,10 @@ public void AddOrUpdateEdge((ProjectGraphNode node, ProjectGraphNode reference)
{
ReferenceItems.AddOrUpdate(
key,
+#pragma warning disable IDE0350
addValueFactory: static ((ProjectGraphNode node, ProjectGraphNode reference) key, ProjectItemInstance referenceItem) => referenceItem,
updateValueFactory: static ((ProjectGraphNode node, ProjectGraphNode reference) key, ProjectItemInstance existingItem, ProjectItemInstance newItem) =>
+#pragma warning restore IDE0350
{
string existingTargetsMetadata = existingItem.GetMetadataValue(ItemMetadataNames.ProjectReferenceTargetsMetadataName);
string newTargetsMetadata = newItem.GetMetadataValue(ItemMetadataNames.ProjectReferenceTargetsMetadataName);
diff --git a/src/Build/Graph/ParallelWorkSet.cs b/src/Build/Graph/ParallelWorkSet.cs
index ed4ecb41537..8474968ed2c 100644
--- a/src/Build/Graph/ParallelWorkSet.cs
+++ b/src/Build/Graph/ParallelWorkSet.cs
@@ -145,7 +145,12 @@ internal void WaitForAllWorkAndComplete()
// Release one thread that will release all the threads when all the elements are processed.
_semaphore.Release();
- Task.WaitAll(_tasks.ToArray());
+ Task.WaitAll(
+#if NET
+ _tasks);
+#else
+ _tasks.ToArray());
+#endif
if (_exceptions.Count > 0)
{
diff --git a/src/Build/Graph/ProjectGraphNode.cs b/src/Build/Graph/ProjectGraphNode.cs
index dcc2a2a24b1..4c43b1e1061 100644
--- a/src/Build/Graph/ProjectGraphNode.cs
+++ b/src/Build/Graph/ProjectGraphNode.cs
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Build.BackEnd;
diff --git a/src/Build/Graph/ProjectInterpretation.cs b/src/Build/Graph/ProjectInterpretation.cs
index d927eaa7e8c..12ae373485d 100644
--- a/src/Build/Graph/ProjectInterpretation.cs
+++ b/src/Build/Graph/ProjectInterpretation.cs
@@ -64,7 +64,7 @@ public TargetSpecification(string target, bool skipIfNonexistent)
ErrorUtilities.VerifyThrow(
!skipIfNonexistent || (!target.Equals(MSBuildConstants.DefaultTargetsMarker)
&& !target.Equals(MSBuildConstants.ProjectReferenceTargetsOrDefaultTargetsMarker)),
- target + " cannot be marked as SkipNonexistentTargets");
+ $"{target} cannot be marked as SkipNonexistentTargets");
Target = target;
SkipIfNonexistent = skipIfNonexistent;
}
diff --git a/src/Build/Instance/HostObjectException.cs b/src/Build/Instance/HostObjectException.cs
index ee4613d1b14..47ba77e5d17 100644
--- a/src/Build/Instance/HostObjectException.cs
+++ b/src/Build/Instance/HostObjectException.cs
@@ -40,7 +40,7 @@ internal HostObjectException(
Exception innerException) :
base(ErrorMessagePrefix
+ string.Format(ErrorMessageProjectTargetTask, projectFile, targetName, taskName)
- + (innerException == null ? string.Empty : ("\n=============\n" + innerException.ToString() + "\n\n")),
+ + (innerException == null ? string.Empty : ($"\n=============\n{innerException}\n\n")),
innerException)
{
}
diff --git a/src/Build/Instance/ImmutableProjectCollections/ImmutableGlobalPropertiesCollectionConverter.cs b/src/Build/Instance/ImmutableProjectCollections/ImmutableGlobalPropertiesCollectionConverter.cs
index b5579adf088..47e51a66e3f 100644
--- a/src/Build/Instance/ImmutableProjectCollections/ImmutableGlobalPropertiesCollectionConverter.cs
+++ b/src/Build/Instance/ImmutableProjectCollections/ImmutableGlobalPropertiesCollectionConverter.cs
@@ -2,13 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.CodeDom;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
using System.Runtime.Serialization;
-using System.Text;
-using System.Threading.Tasks;
using Microsoft.Build.Collections;
using Microsoft.Build.Execution;
using Microsoft.Build.Shared;
diff --git a/src/Build/Instance/ImmutableProjectCollections/ImmutableItemDefinitionsListConverter.cs b/src/Build/Instance/ImmutableProjectCollections/ImmutableItemDefinitionsListConverter.cs
index 245d42583b5..67243d66e62 100644
--- a/src/Build/Instance/ImmutableProjectCollections/ImmutableItemDefinitionsListConverter.cs
+++ b/src/Build/Instance/ImmutableProjectCollections/ImmutableItemDefinitionsListConverter.cs
@@ -4,9 +4,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Microsoft.Build.Collections;
using Microsoft.Build.Shared;
diff --git a/src/Build/Instance/ImmutableProjectCollections/ImmutableItemDictionary.cs b/src/Build/Instance/ImmutableProjectCollections/ImmutableItemDictionary.cs
index de2d06522ae..00d34f295f2 100644
--- a/src/Build/Instance/ImmutableProjectCollections/ImmutableItemDictionary.cs
+++ b/src/Build/Instance/ImmutableProjectCollections/ImmutableItemDictionary.cs
@@ -5,11 +5,8 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Microsoft.Build.Collections;
using Microsoft.Build.Evaluation;
-using Microsoft.Build.Execution;
using Microsoft.Build.Shared;
namespace Microsoft.Build.Instance
@@ -178,13 +175,11 @@ public ICollection GetItems(string itemType)
private sealed class ListConverter : ICollection
{
- private readonly string _itemType;
private readonly ICollection _list;
private readonly Func _getInstance;
public ListConverter(string itemType, ICollection list, Func getInstance)
{
- _itemType = itemType;
_list = list;
_getInstance = getInstance;
}
diff --git a/src/Build/Instance/ImmutableProjectCollections/ImmutableLinkedMultiDictionaryConverter.cs b/src/Build/Instance/ImmutableProjectCollections/ImmutableLinkedMultiDictionaryConverter.cs
index 1b11db2341a..ecf078d2567 100644
--- a/src/Build/Instance/ImmutableProjectCollections/ImmutableLinkedMultiDictionaryConverter.cs
+++ b/src/Build/Instance/ImmutableProjectCollections/ImmutableLinkedMultiDictionaryConverter.cs
@@ -3,11 +3,7 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Microsoft.Build.Collections;
-using Microsoft.Build.Execution;
namespace Microsoft.Build.Instance.ImmutableProjectCollections
{
diff --git a/src/Build/Instance/ProjectInstance.cs b/src/Build/Instance/ProjectInstance.cs
index 938fcc5cba9..f77da95817b 100644
--- a/src/Build/Instance/ProjectInstance.cs
+++ b/src/Build/Instance/ProjectInstance.cs
@@ -2640,7 +2640,12 @@ private static ProjectInstance[] CalculateToolsVersionAndGenerateSolutionWrapper
}
else /* Dev 12 and above */
{
- toolsVersion = visualStudioVersion.ToString(CultureInfo.InvariantCulture) + ".0";
+ toolsVersion =
+#if NET
+ string.Create(CultureInfo.InvariantCulture, $"{visualStudioVersion}.0");
+#else
+ $"{visualStudioVersion.ToString(CultureInfo.InvariantCulture)}.0";
+#endif
}
string toolsVersionToUse = Utilities.GenerateToolsVersionToUse(
@@ -3161,7 +3166,7 @@ private void Initialize(
if (Traits.Instance.EscapeHatches.DebugEvaluation)
{
- Trace.WriteLine(String.Format(CultureInfo.InvariantCulture, "MSBUILD: Creating a ProjectInstance from an unevaluated state [{0}]", FullPath));
+ Trace.WriteLine($"MSBUILD: Creating a ProjectInstance from an unevaluated state [{FullPath}]");
}
ErrorUtilities.VerifyThrow(EvaluationId == BuildEventContext.InvalidEvaluationId, "Evaluation ID is invalid prior to evaluation");
diff --git a/src/Build/Instance/ProjectItemDefinitionInstance.cs b/src/Build/Instance/ProjectItemDefinitionInstance.cs
index 4e886bd134a..2bfb6750f50 100644
--- a/src/Build/Instance/ProjectItemDefinitionInstance.cs
+++ b/src/Build/Instance/ProjectItemDefinitionInstance.cs
@@ -10,7 +10,6 @@
using Microsoft.Build.Collections;
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
-using Microsoft.Build.Instance;
using Microsoft.Build.Shared;
#nullable disable
diff --git a/src/Build/Instance/ProjectItemInstance.cs b/src/Build/Instance/ProjectItemInstance.cs
index 8dd5127eba5..bce683abb37 100644
--- a/src/Build/Instance/ProjectItemInstance.cs
+++ b/src/Build/Instance/ProjectItemInstance.cs
@@ -1085,6 +1085,7 @@ public void ImportMetadata(IEnumerable> metadata)
_directMetadata.ImportProperties(metadata.Select(kvp => new ProjectMetadataInstance(kvp.Key, kvp.Value, allowItemSpecModifiers: true)));
}
+#if FEATURE_APPDOMAIN
///
/// Used to return metadata from another AppDomain. Can't use yield return because the
/// generated state machine is not marked as [Serializable], so we need to allocate.
@@ -1106,6 +1107,7 @@ private IEnumerable> EnumerateMetadataEager(ICopyOn
// Probably better to send the raw array across the wire even if it's another allocation.
return result.ToArray();
}
+#endif
private IEnumerable> EnumerateMetadata(ICopyOnWritePropertyDictionary list)
{
@@ -2112,7 +2114,7 @@ internal class TaskItemFactory : IItemFactory, IItemFacto
///
/// The singleton instance.
///
- private static TaskItemFactory s_instance = new TaskItemFactory();
+ private static readonly TaskItemFactory s_instance = new TaskItemFactory();
///
/// Private constructor for singleton creation.
diff --git a/src/Build/Instance/ProjectMetadataInstance.cs b/src/Build/Instance/ProjectMetadataInstance.cs
index ec764cbbbb3..15136b19c1d 100644
--- a/src/Build/Instance/ProjectMetadataInstance.cs
+++ b/src/Build/Instance/ProjectMetadataInstance.cs
@@ -164,7 +164,7 @@ internal string EvaluatedValueEscaped
///
public override string ToString()
{
- return _name + "=" + _escapedValue;
+ return $"{_name}={_escapedValue}";
}
#region INodePacketTranslatable Members
diff --git a/src/Build/Instance/ProjectPropertyInstance.cs b/src/Build/Instance/ProjectPropertyInstance.cs
index dc7cb2b6624..2d0de613ea9 100644
--- a/src/Build/Instance/ProjectPropertyInstance.cs
+++ b/src/Build/Instance/ProjectPropertyInstance.cs
@@ -186,7 +186,7 @@ void ITranslatable.Translate(ITranslator translator)
///
public override string ToString()
{
- return _name + "=" + _escapedValue;
+ return $"{_name}={_escapedValue}";
}
///
diff --git a/src/Build/Instance/TaskFactories/TaskHostTask.cs b/src/Build/Instance/TaskFactories/TaskHostTask.cs
index 784b67b200c..fdb9dc2373a 100644
--- a/src/Build/Instance/TaskFactories/TaskHostTask.cs
+++ b/src/Build/Instance/TaskFactories/TaskHostTask.cs
@@ -9,11 +9,13 @@
using System.Threading;
using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Exceptions;
-using Microsoft.Build.FileAccesses;
using Microsoft.Build.Framework;
-using Microsoft.Build.Experimental.FileAccess;
using Microsoft.Build.Internal;
using Microsoft.Build.Shared;
+#if FEATURE_REPORTFILEACCESSES
+using Microsoft.Build.Experimental.FileAccess;
+using Microsoft.Build.FileAccesses;
+#endif
#nullable disable
@@ -372,6 +374,16 @@ public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITr
_packetFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
}
+ ///
+ /// Takes a serializer and deserializes the packet.
+ ///
+ /// The packet type.
+ /// The translator containing the data from which the packet should be reconstructed.
+ public INodePacket DeserializePacket(NodePacketType packetType, ITranslator translator)
+ {
+ return _packetFactory.DeserializePacket(packetType, translator);
+ }
+
///
/// Routes the specified packet
///
diff --git a/src/Build/Instance/TaskRegistry.cs b/src/Build/Instance/TaskRegistry.cs
index a71dad69e15..508cb7483b6 100644
--- a/src/Build/Instance/TaskRegistry.cs
+++ b/src/Build/Instance/TaskRegistry.cs
@@ -11,7 +11,6 @@
using System.Reflection;
using System.Threading;
using Microsoft.Build.BackEnd;
-using Microsoft.Build.BackEnd.Components.RequestBuilder;
using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Collections;
using Microsoft.Build.Construction;
@@ -20,7 +19,6 @@
using Microsoft.Build.Shared;
using Microsoft.Build.Shared.FileSystem;
using Microsoft.NET.StringTools;
-using ILoggingService = Microsoft.Build.BackEnd.Logging.ILoggingService;
using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException;
using ProjectXmlUtilities = Microsoft.Build.Internal.ProjectXmlUtilities;
using TargetLoggingContext = Microsoft.Build.BackEnd.Logging.TargetLoggingContext;
@@ -68,64 +66,64 @@ internal sealed class TaskRegistry : ITranslatable
/// callbacks; as forcing those out of proc would be just setting them up for
/// known failure.
///
- private static bool s_forceTaskHostLaunch = (Environment.GetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC") == "1");
+ private static readonly bool s_forceTaskHostLaunch = (Environment.GetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC") == "1");
///
/// Simple name for the MSBuild tasks (v4), used for shimming in loading
/// task factory UsingTasks
///
- private static string s_tasksV4SimpleName = "Microsoft.Build.Tasks.v4.0";
+ private const string s_tasksV4SimpleName = "Microsoft.Build.Tasks.v4.0";
///
/// Filename for the MSBuild tasks (v4), used for shimming in loading
/// task factory UsingTasks
///
- private static string s_tasksV4Filename = s_tasksV4SimpleName + ".dll";
+ private const string s_tasksV4Filename = $"{s_tasksV4SimpleName}.dll";
///
/// Expected location that MSBuild tasks (v4) is picked up from if the user
/// references it with just a simple name, used for shimming in loading
/// task factory UsingTasks
///
- private static string s_potentialTasksV4Location = Path.Combine(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, s_tasksV4Filename);
+ private static readonly string s_potentialTasksV4Location = Path.Combine(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, s_tasksV4Filename);
///
/// Simple name for the MSBuild tasks (v12), used for shimming in loading
/// task factory UsingTasks
///
- private static string s_tasksV12SimpleName = "Microsoft.Build.Tasks.v12.0";
+ private const string s_tasksV12SimpleName = "Microsoft.Build.Tasks.v12.0";
///
/// Filename for the MSBuild tasks (v12), used for shimming in loading
/// task factory UsingTasks
///
- private static string s_tasksV12Filename = s_tasksV12SimpleName + ".dll";
+ private const string s_tasksV12Filename = $"{s_tasksV12SimpleName}.dll";
///
/// Expected location that MSBuild tasks (v12) is picked up from if the user
/// references it with just a simple name, used for shimming in loading
/// task factory UsingTasks
///
- private static string s_potentialTasksV12Location = Path.Combine(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, s_tasksV12Filename);
+ private static readonly string s_potentialTasksV12Location = Path.Combine(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, s_tasksV12Filename);
///
/// Simple name for the MSBuild tasks (v14+), used for shimming in loading
/// task factory UsingTasks
///
- private static string s_tasksCoreSimpleName = "Microsoft.Build.Tasks.Core";
+ private const string s_tasksCoreSimpleName = "Microsoft.Build.Tasks.Core";
///
/// Filename for the MSBuild tasks (v14+), used for shimming in loading
/// task factory UsingTasks
///
- private static string s_tasksCoreFilename = s_tasksCoreSimpleName + ".dll";
+ private const string s_tasksCoreFilename = $"{s_tasksCoreSimpleName}.dll";
///
/// Expected location that MSBuild tasks (v14+) is picked up from if the user
/// references it with just a simple name, used for shimming in loading
/// task factory UsingTasks
///
- private static string s_potentialTasksCoreLocation = Path.Combine(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, s_tasksCoreFilename);
+ private static readonly string s_potentialTasksCoreLocation = Path.Combine(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, s_tasksCoreFilename);
///
/// Monotonically increasing counter for registered tasks.
@@ -853,13 +851,13 @@ internal class RegisteredTaskIdentityComparer : IEqualityComparer
/// The singleton comparer to use when an exact match is desired
///
- private static RegisteredTaskIdentityComparer s_exact = new RegisteredTaskIdentityComparer(true /* exact match */);
+ private static readonly RegisteredTaskIdentityComparer s_exact = new RegisteredTaskIdentityComparer(true /* exact match */);
///
/// The singleton comparer to use when a fuzzy match is desired. Note that this still does an exact match on the
/// name, but does a fuzzy match on the task identity parameters.
///
- private static RegisteredTaskIdentityComparer s_fuzzy = new RegisteredTaskIdentityComparer(false /* fuzzy match */);
+ private static readonly RegisteredTaskIdentityComparer s_fuzzy = new RegisteredTaskIdentityComparer(false /* fuzzy match */);
///
/// Keeps track of whether we're doing exact or fuzzy equivalency
diff --git a/src/Build/Logging/BaseConsoleLogger.cs b/src/Build/Logging/BaseConsoleLogger.cs
index 508223e628b..364487c1e72 100644
--- a/src/Build/Logging/BaseConsoleLogger.cs
+++ b/src/Build/Logging/BaseConsoleLogger.cs
@@ -518,7 +518,7 @@ internal virtual void OutputEnvironment(IDictionary environment)
foreach (KeyValuePair entry in environment)
{
setColor(ConsoleColor.Gray);
- WritePretty(String.Format(CultureInfo.CurrentCulture, "{0,-30} = ", entry.Key));
+ WritePretty($"{entry.Key,-30} = ");
setColor(ConsoleColor.DarkGray);
WriteLinePretty(entry.Value);
}
@@ -536,7 +536,7 @@ internal virtual void OutputProperties(List list)
foreach (DictionaryEntry prop in list)
{
setColor(ConsoleColor.Gray);
- WritePretty(String.Format(CultureInfo.CurrentCulture, "{0,-30} = ", prop.Key));
+ WritePretty($"{prop.Key,-30} = ");
setColor(ConsoleColor.DarkGray);
WriteLinePretty(EscapingUtilities.UnescapeAll((string)prop.Value));
}
@@ -656,12 +656,12 @@ protected virtual void WriteItemType(string itemType)
protected virtual void WriteItemSpec(string itemSpec)
{
- WriteLinePretty(" " + itemSpec);
+ WriteLinePretty($" {itemSpec}");
}
protected virtual void WriteMetadata(string name, string value)
{
- WriteLinePretty(" " + name + " = " + value);
+ WriteLinePretty($" {name} = {value}");
}
///
@@ -821,8 +821,8 @@ internal virtual void PrintCounterMessage(WriteLinePrettyFromResourceDelegate wr
2,
"PerformanceLine",
time,
- String.Format(CultureInfo.CurrentCulture, "{0,-40}" /* pad to 40 align left */, scopeName),
- String.Format(CultureInfo.CurrentCulture, "{0,3}", calls));
+ $"{scopeName,-40}", // pad to 40 align left
+ $"{calls,3}");
}
///
diff --git a/src/Build/Logging/BinaryLogger/BinaryLogger.cs b/src/Build/Logging/BinaryLogger/BinaryLogger.cs
index 9c3fda8fec3..e5947b6bf33 100644
--- a/src/Build/Logging/BinaryLogger/BinaryLogger.cs
+++ b/src/Build/Logging/BinaryLogger/BinaryLogger.cs
@@ -4,10 +4,10 @@
using System;
using System.IO;
using System.IO.Compression;
+using Microsoft.Build.Experimental.BuildCheck.Infrastructure.EditorConfig;
using Microsoft.Build.Framework;
using Microsoft.Build.Framework.Telemetry;
using Microsoft.Build.Shared;
-using Microsoft.Build.Shared.FileSystem;
#nullable disable
@@ -322,6 +322,12 @@ public void Shutdown()
if (projectImportsCollector != null)
{
+ // Write the build check editorconfig file paths to the log
+ foreach (var filePath in EditorConfigParser.EditorConfigFilePaths)
+ {
+ projectImportsCollector.AddFile(filePath);
+ }
+ EditorConfigParser.ClearEditorConfigFilePaths();
projectImportsCollector.Close();
if (CollectProjectImports == ProjectImportsCollectionMode.Embed)
@@ -337,6 +343,7 @@ public void Shutdown()
projectImportsCollector = null;
}
+
if (stream != null)
{
// It's hard to determine whether we're at the end of decoding GZipStream
diff --git a/src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs b/src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs
index 4b48d9a8592..69afeee1674 100644
--- a/src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs
+++ b/src/Build/Logging/BinaryLogger/BuildEventArgsReader.cs
@@ -56,9 +56,9 @@ public class BuildEventArgsReader : IBuildEventArgsReaderNotifications, IDisposa
// reflection is needed to set these three fields because public constructors don't provide
// a way to set these from the outside
- private static FieldInfo? buildEventArgsFieldThreadId =
+ private static readonly FieldInfo? buildEventArgsFieldThreadId =
typeof(BuildEventArgs).GetField("threadId", BindingFlags.Instance | BindingFlags.NonPublic);
- private static FieldInfo? buildEventArgsFieldSenderName =
+ private static readonly FieldInfo? buildEventArgsFieldSenderName =
typeof(BuildEventArgs).GetField("senderName", BindingFlags.Instance | BindingFlags.NonPublic);
///
diff --git a/src/Build/Logging/BinaryLogger/Postprocessing/ArchiveFile.cs b/src/Build/Logging/BinaryLogger/Postprocessing/ArchiveFile.cs
index ec8ba12c8b1..6239d90f453 100644
--- a/src/Build/Logging/BinaryLogger/Postprocessing/ArchiveFile.cs
+++ b/src/Build/Logging/BinaryLogger/Postprocessing/ArchiveFile.cs
@@ -4,8 +4,6 @@
using System;
using System.IO;
using System.IO.Compression;
-using System.Text;
-using Microsoft.Build.Shared;
namespace Microsoft.Build.Logging
{
diff --git a/src/Build/Logging/BinaryLogger/Postprocessing/StreamExtensions.cs b/src/Build/Logging/BinaryLogger/Postprocessing/StreamExtensions.cs
index 8a0cc2ed489..3e85d2bb02b 100644
--- a/src/Build/Logging/BinaryLogger/Postprocessing/StreamExtensions.cs
+++ b/src/Build/Logging/BinaryLogger/Postprocessing/StreamExtensions.cs
@@ -3,9 +3,7 @@
using System;
using System.Buffers;
-using System.Diagnostics;
using System.IO;
-using System.Text;
using Microsoft.Build.Shared;
namespace Microsoft.Build.Logging
diff --git a/src/Build/Logging/BinaryLogger/Postprocessing/SubStream.cs b/src/Build/Logging/BinaryLogger/Postprocessing/SubStream.cs
index 8c6e0c6e2b8..af92788d62a 100644
--- a/src/Build/Logging/BinaryLogger/Postprocessing/SubStream.cs
+++ b/src/Build/Logging/BinaryLogger/Postprocessing/SubStream.cs
@@ -70,9 +70,13 @@ public override int ReadByte()
public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
count = Math.Min((int)Math.Max(Length - _position, 0), count);
-#pragma warning disable CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
- int read = await _stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
-#pragma warning restore CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
+ int read = await _stream.ReadAsync(
+#if NET
+ buffer.AsMemory(offset, count),
+#else
+ buffer, offset, count,
+#endif
+ cancellationToken).ConfigureAwait(false);
_position += read;
return read;
}
diff --git a/src/Build/Logging/BinaryLogger/Postprocessing/TransparentReadStream.cs b/src/Build/Logging/BinaryLogger/Postprocessing/TransparentReadStream.cs
index ea3fcb3c9c7..bd427fbb3bc 100644
--- a/src/Build/Logging/BinaryLogger/Postprocessing/TransparentReadStream.cs
+++ b/src/Build/Logging/BinaryLogger/Postprocessing/TransparentReadStream.cs
@@ -116,9 +116,13 @@ public override async Task ReadAsync(byte[] buffer, int offset, int count,
count = (int)(_maxAllowedPosition - _position);
}
-#pragma warning disable CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
- int cnt = await _stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
-#pragma warning restore CA1835 // Prefer the 'Memory'-based overloads for 'ReadAsync' and 'WriteAsync'
+ int cnt = await _stream.ReadAsync(
+#if NET
+ buffer.AsMemory(offset, count),
+#else
+ buffer, offset, count,
+#endif
+ cancellationToken).ConfigureAwait(false);
_position += cnt;
return cnt;
}
diff --git a/src/Build/Logging/ConsoleLogger.cs b/src/Build/Logging/ConsoleLogger.cs
index dc365d45387..41bfaf94f50 100644
--- a/src/Build/Logging/ConsoleLogger.cs
+++ b/src/Build/Logging/ConsoleLogger.cs
@@ -2,10 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Reflection;
-using System.Runtime.CompilerServices;
using Microsoft.Build.BackEnd.Logging;
using Microsoft.Build.Framework;
using Microsoft.Build.Framework.Logging;
diff --git a/src/Build/Logging/DistributedLoggers/DistributedFileLogger.cs b/src/Build/Logging/DistributedLoggers/DistributedFileLogger.cs
index 591df6df9f3..bfd1d41a51f 100644
--- a/src/Build/Logging/DistributedLoggers/DistributedFileLogger.cs
+++ b/src/Build/Logging/DistributedLoggers/DistributedFileLogger.cs
@@ -113,7 +113,7 @@ public void Initialize(IEventSource eventSource)
// but avoids confusion by being consistent with the Engine and any error messages it may produce.
fileName = _logFile.Replace(extension, _nodeId + extension);
_nodeFileLogger.Verbosity = LoggerVerbosity.Detailed;
- _nodeFileLogger.Parameters = "ShowEventId;ShowCommandLine;logfile=" + fileName + ";" + _parameters;
+ _nodeFileLogger.Parameters = $"ShowEventId;ShowCommandLine;logfile={fileName};{_parameters}";
}
catch (ArgumentException e) // Catching Exception, but rethrowing unless it's a well-known exception.
{
diff --git a/src/Build/Logging/LogFormatter.cs b/src/Build/Logging/LogFormatter.cs
index b03391a34a1..22c0ab05658 100644
--- a/src/Build/Logging/LogFormatter.cs
+++ b/src/Build/Logging/LogFormatter.cs
@@ -51,7 +51,7 @@ internal static string FormatTimeSpan(TimeSpan t)
string rawTime = t.ToString(); // Timespan is a value type and can't be null.
int rawTimeLength = rawTime.Length;
int prettyLength = System.Math.Min(11, rawTimeLength);
- return t.ToString().Substring(0, prettyLength);
+ return rawTime.Substring(0, prettyLength);
}
}
}
diff --git a/src/Build/Logging/LoggerDescription.cs b/src/Build/Logging/LoggerDescription.cs
index 8f949afb9ad..9b4e34e5c34 100644
--- a/src/Build/Logging/LoggerDescription.cs
+++ b/src/Build/Logging/LoggerDescription.cs
@@ -96,7 +96,7 @@ public string Name
if (!string.IsNullOrEmpty(_loggerClassName) &&
!string.IsNullOrEmpty(_loggerAssembly.AssemblyFile))
{
- return _loggerClassName + ":" + _loggerAssembly.AssemblyFile;
+ return $"{_loggerClassName}:{_loggerAssembly.AssemblyFile}";
}
else if (!string.IsNullOrEmpty(_loggerClassName))
{
diff --git a/src/Build/Logging/OptimizedStringIndenter.cs b/src/Build/Logging/OptimizedStringIndenter.cs
index d98f1d62094..ed28c80e8fd 100644
--- a/src/Build/Logging/OptimizedStringIndenter.cs
+++ b/src/Build/Logging/OptimizedStringIndenter.cs
@@ -4,7 +4,7 @@
using System;
using System.Buffers;
-#if NET7_0_OR_GREATER
+#if NET
using System.Runtime.CompilerServices;
#else
using System.Text;
@@ -49,7 +49,7 @@ namespace Microsoft.Build.BackEnd.Logging;
internal static class OptimizedStringIndenter
{
#nullable enable
-#if NET7_0_OR_GREATER
+#if NET
[SkipLocalsInit]
#endif
internal static unsafe string IndentString(string? s, int indent, IStringBuilderProvider stringBuilderProvider)
@@ -67,7 +67,7 @@ internal static unsafe string IndentString(string? s, int indent, IStringBuilder
indentedStringLength += segment.Length;
}
-#if NET7_0_OR_GREATER
+#if NET
#pragma warning disable CS8500
string result = string.Create(indentedStringLength, (s, (IntPtr)(&segments), indent), static (output, state) =>
{
diff --git a/src/Build/Logging/ParallelLogger/ParallelConsoleLogger.cs b/src/Build/Logging/ParallelLogger/ParallelConsoleLogger.cs
index d59bbb81e46..fb60ed2c23c 100644
--- a/src/Build/Logging/ParallelLogger/ParallelConsoleLogger.cs
+++ b/src/Build/Logging/ParallelLogger/ParallelConsoleLogger.cs
@@ -760,7 +760,7 @@ internal override void OutputProperties(List list)
foreach (DictionaryEntry prop in list)
{
setColor(ConsoleColor.Gray);
- string propertyString = String.Format(CultureInfo.CurrentCulture, "{0} = {1}", prop.Key, EscapingUtilities.UnescapeAll((string)(prop.Value)));
+ string propertyString = $"{prop.Key} = {EscapingUtilities.UnescapeAll((string)(prop.Value))}";
WriteMessageAligned(propertyString, false);
}
resetColor();
@@ -781,7 +781,7 @@ internal override void OutputEnvironment(IDictionary environment
foreach (KeyValuePair entry in environment)
{
setColor(ConsoleColor.Gray);
- string environmentMessage = String.Format(CultureInfo.CurrentCulture, "{0} = {1}", entry.Key, entry.Value);
+ string environmentMessage = $"{entry.Key} = {entry.Value}";
WriteMessageAligned(environmentMessage, false);
}
}
@@ -897,7 +897,7 @@ public override void TargetFinishedHandler(object sender, TargetFinishedEventArg
foreach (DictionaryEntry metadatum in metadata)
{
- WriteMessageAligned(new String(' ', 4 * tabWidth) + metadatum.Key + " = " + item.GetMetadata(metadatum.Key as string), false);
+ WriteMessageAligned($"{new String(' ', 4 * tabWidth)}{metadatum.Key} = {item.GetMetadata(metadatum.Key as string)}", false);
}
}
}
@@ -1343,7 +1343,7 @@ private void PrintTargetNamePerMessage(BuildMessageEventArgs e, bool lightenText
}
else
{
- WriteMessageAligned(targetName + ":", prefixAlreadyWritten);
+ WriteMessageAligned($"{targetName}:", prefixAlreadyWritten);
}
if (lightenText)
@@ -1401,22 +1401,6 @@ private void WriteMessageAligned(string message, bool prefixAlreadyWritten, int
}
}
- ///
- /// Write message taking into account whether or not the prefix (timestamp and key) have already been written on the line
- ///
- private void WriteBasedOnPrefix(string nonNullMessage, bool prefixAlreadyWritten, int adjustedPrefixWidth)
- {
- if (prefixAlreadyWritten)
- {
- WriteHandler(nonNullMessage + Environment.NewLine);
- }
- else
- {
- // No prefix info has been written, indent the line to the proper location
- WriteHandler(IndentString(nonNullMessage, adjustedPrefixWidth));
- }
- }
-
///
/// Will display the target started event which was deferred until the first visible message for the target is ready to be displayed
///
@@ -1618,11 +1602,11 @@ private void WriteLinePrefix(string key, DateTime eventTimeStamp, bool isMessage
if (!isMessagePrefix || IsVerbosityAtLeast(LoggerVerbosity.Detailed))
{
- prefixString = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BuildEventContext", context, key) + ">";
+ prefixString = $"{ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BuildEventContext", context, key)}>";
}
else
{
- prefixString = ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BuildEventContext", context, string.Empty) + " ";
+ prefixString = $"{ResourceUtilities.FormatResourceStringStripCodeAndKeyword("BuildEventContext", context, string.Empty)} ";
}
WritePretty(prefixString);
@@ -1763,8 +1747,8 @@ internal override void PrintCounterMessage(WriteLinePrettyFromResourceDelegate W
MessageIndentLevel,
"PerformanceLine",
time,
- String.Format(CultureInfo.CurrentCulture, "{0,-40}" /* pad to 40 align left */, scopeName),
- String.Format(CultureInfo.CurrentCulture, "{0,3}", calls));
+ $"{scopeName,-40}", // pad to 40 align left
+ $"{calls,3}");
if (_internalPerformanceCounters?.Count > 0)
{
diff --git a/src/Build/Logging/ParallelLogger/ParallelLoggerHelpers.cs b/src/Build/Logging/ParallelLogger/ParallelLoggerHelpers.cs
index dd73599bec2..b066b31fea4 100644
--- a/src/Build/Logging/ParallelLogger/ParallelLoggerHelpers.cs
+++ b/src/Build/Logging/ParallelLogger/ParallelLoggerHelpers.cs
@@ -140,7 +140,6 @@ internal string[] ProjectCallStackFromProject(BuildEventContext e)
ProjectStartedEventMinimumFields startedEvent = GetProjectStartedEvent(currentKey);
- List stackTrace = new List();
// If there is no started event then there should be no stack trace
// this is a valid situation if the event occures in the engine or outside the context of a project
// or the event is raised before the project started event
@@ -150,19 +149,18 @@ internal string[] ProjectCallStackFromProject(BuildEventContext e)
}
List projectStackTrace = GetProjectCallStack(e);
- foreach (ProjectStartedEventMinimumFields projectStartedEvent in projectStackTrace)
+
+ string[] stackTrace = new string[projectStackTrace.Count];
+ for (int i = 0; i < stackTrace.Length; i++)
{
- if (!string.IsNullOrEmpty(projectStartedEvent.TargetNames))
- {
- stackTrace.Add(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("ProjectStackWithTargetNames", projectStartedEvent.ProjectFile, projectStartedEvent.TargetNames, projectStartedEvent.FullProjectKey));
- }
- else
- {
- stackTrace.Add(ResourceUtilities.FormatResourceStringStripCodeAndKeyword("ProjectStackWithDefaultTargets", projectStartedEvent.ProjectFile, projectStartedEvent.FullProjectKey));
- }
+ ProjectStartedEventMinimumFields projectStartedEvent = projectStackTrace[i];
+
+ stackTrace[stackTrace.Length - i - 1] = !string.IsNullOrEmpty(projectStartedEvent.TargetNames) ?
+ ResourceUtilities.FormatResourceStringStripCodeAndKeyword("ProjectStackWithTargetNames", projectStartedEvent.ProjectFile, projectStartedEvent.TargetNames, projectStartedEvent.FullProjectKey) :
+ ResourceUtilities.FormatResourceStringStripCodeAndKeyword("ProjectStackWithDefaultTargets", projectStartedEvent.ProjectFile, projectStartedEvent.FullProjectKey);
}
- stackTrace.Reverse();
- return stackTrace.ToArray();
+
+ return stackTrace;
}
///
diff --git a/src/Build/Logging/ProfilerLogger.cs b/src/Build/Logging/ProfilerLogger.cs
index b80dcf8cf0e..85f659336d8 100644
--- a/src/Build/Logging/ProfilerLogger.cs
+++ b/src/Build/Logging/ProfilerLogger.cs
@@ -134,7 +134,7 @@ internal ProfilerResult GetAggregatedResult(bool pruneSmallItems = true)
// So keeping that map here
var originalLocations = new Dictionary(EvaluationLocationIdAgnosticComparer.Singleton);
- while (_profiledResults.Any())
+ while (!_profiledResults.IsEmpty)
{
ProfilerResult profiledResult;
var result = _profiledResults.TryDequeue(out profiledResult);
diff --git a/src/Build/Logging/SimpleErrorLogger.cs b/src/Build/Logging/SimpleErrorLogger.cs
index 5b248afd5e7..fafc01e340d 100644
--- a/src/Build/Logging/SimpleErrorLogger.cs
+++ b/src/Build/Logging/SimpleErrorLogger.cs
@@ -4,7 +4,6 @@
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Framework.Logging;
-using Microsoft.Build.Logging;
using Microsoft.Build.Shared;
namespace Microsoft.Build.Logging.SimpleErrorLogger
diff --git a/src/Build/Logging/TerminalLogger/TerminalLogger.cs b/src/Build/Logging/TerminalLogger/TerminalLogger.cs
index 4e653123f12..eca3e0749a3 100644
--- a/src/Build/Logging/TerminalLogger/TerminalLogger.cs
+++ b/src/Build/Logging/TerminalLogger/TerminalLogger.cs
@@ -12,8 +12,8 @@
using Microsoft.Build.Framework.Logging;
using Microsoft.Build.Shared;
-#if NET7_0_OR_GREATER
-using System.Diagnostics.CodeAnalysis;
+#if NET
+using System.Buffers;
#endif
#if NETFRAMEWORK
@@ -34,15 +34,10 @@ public sealed partial class TerminalLogger : INodeLogger
{
private const string FilePathPattern = " -> ";
-#if NET7_0_OR_GREATER
- [StringSyntax(StringSyntaxAttribute.Regex)]
- private const string ImmediateMessagePattern = @"\[CredentialProvider\]|--interactive";
- private const RegexOptions Options = RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture;
-
- [GeneratedRegex(ImmediateMessagePattern, Options)]
- private static partial Regex ImmediateMessageRegex();
+#if NET
+ private static readonly SearchValues _immediateMessageKeywords = SearchValues.Create(["[CredentialProvider]", "--interactive"], StringComparison.OrdinalIgnoreCase);
#else
- private static readonly string[] _immediateMessageKeywords = { "[CredentialProvider]", "--interactive" };
+ private static readonly string[] _immediateMessageKeywords = ["[CredentialProvider]", "--interactive"];
#endif
private static readonly string[] newLineStrings = { "\r\n", "\n" };
@@ -165,11 +160,6 @@ public ProjectContext(BuildEventContext context)
///
private bool _loggedPreviewMessage;
- ///
- /// The two directory separator characters to be passed to methods like .
- ///
- private static readonly char[] PathSeparators = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
-
///
/// One summary per finished project test run.
///
@@ -1020,8 +1010,8 @@ private void WarningRaised(object sender, BuildWarningEventArgs e)
/// Raised event.
/// true if marker is detected.
private bool IsImmediateMessage(string message) =>
-#if NET7_0_OR_GREATER
- ImmediateMessageRegex().IsMatch(message);
+#if NET
+ message.AsSpan().ContainsAny(_immediateMessageKeywords);
#else
_immediateMessageKeywords.Any(imk => message.IndexOf(imk, StringComparison.OrdinalIgnoreCase) >= 0);
#endif
@@ -1060,11 +1050,22 @@ private void ErrorRaised(object sender, BuildErrorEventArgs e)
private void ThreadProc()
{
// 1_000 / 30 is a poor approx of 30Hz
+ var count = 0;
while (!_cts.Token.WaitHandle.WaitOne(1_000 / 30))
{
+ count++;
lock (_lock)
{
- DisplayNodes();
+ // Querying the terminal for it's dimensions is expensive, so we only do it every 30 frames e.g. once a second.
+ if (count >= 30)
+ {
+ count = 0;
+ DisplayNodes();
+ }
+ else
+ {
+ DisplayNodes(false);
+ }
}
}
@@ -1075,9 +1076,11 @@ private void ThreadProc()
/// Render Nodes section.
/// It shows what all build nodes do.
///
- internal void DisplayNodes()
+ internal void DisplayNodes(bool updateSize = true)
{
- TerminalNodesFrame newFrame = new TerminalNodesFrame(_nodes, width: Terminal.Width, height: Terminal.Height);
+ var width = updateSize ? Terminal.Width : _currentFrame.Width;
+ var height = updateSize ? Terminal.Height : _currentFrame.Height;
+ TerminalNodesFrame newFrame = new TerminalNodesFrame(_nodes, width: width, height: height);
// Do not render delta but clear everything if Terminal width or height have changed.
if (newFrame.Width != _currentFrame.Width || newFrame.Height != _currentFrame.Height)
@@ -1184,7 +1187,7 @@ private int NodeIndexForContext(BuildEventContext context)
return null;
}
- int index = path.LastIndexOfAny(PathSeparators);
+ int index = path.AsSpan().LastIndexOfAny(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
return index >= 0
? $"{path.Substring(0, index + 1)}{AnsiCodes.MakeBold(path.Substring(index + 1))}"
: path;
@@ -1282,7 +1285,7 @@ private string FormatEventMessage(
builder.Append($"{category} {code}: ");
// render multi-line message in a special way
- if (message.IndexOf('\n') >= 0)
+ if (message.Contains('\n'))
{
// Place the multiline message under the project in case of minimal and higher verbosity.
string[] lines = message.Split(newLineStrings, StringSplitOptions.None);
diff --git a/src/Build/Logging/TerminalLogger/TerminalNodeStatus.cs b/src/Build/Logging/TerminalLogger/TerminalNodeStatus.cs
index 4634040bdf7..22eb0157257 100644
--- a/src/Build/Logging/TerminalLogger/TerminalNodeStatus.cs
+++ b/src/Build/Logging/TerminalLogger/TerminalNodeStatus.cs
@@ -1,10 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+#if DEBUG
using System;
-using System.Diagnostics;
+#endif
using Microsoft.Build.Framework.Logging;
-using Microsoft.Build.Shared;
namespace Microsoft.Build.Logging;
@@ -68,23 +68,10 @@ obj is TerminalNodeStatus status &&
TargetPrefixColor == status.TargetPrefixColor &&
TargetPrefix == status.TargetPrefix;
- public override string ToString()
- {
- string duration = Stopwatch.ElapsedSeconds.ToString("F1");
-
- return string.IsNullOrEmpty(TargetFramework)
- ? string.Format("{0}{1} {2} ({3}s)",
- TerminalLogger.Indentation,
- Project,
- Target,
- duration)
- : string.Format("{0}{1} {2} {3} ({4}s)",
- TerminalLogger.Indentation,
- Project,
- AnsiCodes.Colorize(TargetFramework, TerminalLogger.TargetFrameworkColor),
- Target,
- duration);
- }
+ public override string ToString() =>
+ string.IsNullOrEmpty(TargetFramework) ?
+ $"{TerminalLogger.Indentation}{Project} {Target} ({Stopwatch.ElapsedSeconds:F1}s)" :
+ $"{TerminalLogger.Indentation}{Project} {AnsiCodes.Colorize(TargetFramework, TerminalLogger.TargetFrameworkColor)} {Target} ({Stopwatch.ElapsedSeconds:F1}s)";
public override int GetHashCode()
{
diff --git a/src/Build/Logging/TerminalLogger/TerminalProjectInfo.cs b/src/Build/Logging/TerminalLogger/TerminalProjectInfo.cs
index 8e4f98fe688..8c64b0978f5 100644
--- a/src/Build/Logging/TerminalLogger/TerminalProjectInfo.cs
+++ b/src/Build/Logging/TerminalLogger/TerminalProjectInfo.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
namespace Microsoft.Build.Logging;
diff --git a/src/Build/Resources/Constants.cs b/src/Build/Resources/Constants.cs
index f6c7a968081..68a6ab4f4bc 100644
--- a/src/Build/Resources/Constants.cs
+++ b/src/Build/Resources/Constants.cs
@@ -178,7 +178,7 @@ internal static class AvailableStaticMethods
///
/// Locker to protect initialization
///
- private static Object s_locker = new Object();
+ private static readonly Object s_locker = new Object();
static AvailableStaticMethods()
{
@@ -365,7 +365,7 @@ private static void InitializeAvailableMethods()
availableStaticMethods.TryAdd("Microsoft.Build.Utilities.ToolLocationHelper", new Tuple("Microsoft.Build.Utilities.ToolLocationHelper, Microsoft.Build.Utilities.Core, Version=" + MSBuildConstants.CurrentAssemblyVersion + ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", null));
availableStaticMethods.TryAdd("System.Runtime.InteropServices.RuntimeInformation", runtimeInformationType);
availableStaticMethods.TryAdd("System.Runtime.InteropServices.OSPlatform", osPlatformType);
-#if NET5_0_OR_GREATER
+#if NET
var operatingSystemType = new Tuple(null, typeof(OperatingSystem));
availableStaticMethods.TryAdd("System.OperatingSystem", operatingSystemType);
#else
diff --git a/src/Build/Resources/Strings.resx b/src/Build/Resources/Strings.resx
index 128cf7283c0..f6b9b047fea 100644
--- a/src/Build/Resources/Strings.resx
+++ b/src/Build/Resources/Strings.resx
@@ -2206,6 +2206,12 @@ Utilization: {0} Average Utilization: {1:###.0}
Project {0} specifies 'TargetFramework(s)' property '{1}', which does not use the .NET SDK. Those properties are not understood by projects that import C# targets directly.
Terms in quotes are not to be translated.
+
+ The 'Exec' task should not be used to build a project.
+
+
+ Task {0} from project {1} builds a project using the {2} CLI. The MSBuild task should be used instead.
+
A property that is accessed should be declared first.
@@ -2386,6 +2392,9 @@ Utilization: {0} Average Utilization: {1:###.0}
succeeded: {0}
{0} whole number
+
+ Loading telemetry libraries failed with exception: {0}.
+
@@ -194,6 +193,7 @@
+
@@ -274,9 +274,6 @@
<_OurFiles Include="$(OutputPath)%(_TargetFrameworks.Identity)\Microsoft.VisualBasic.CrossTargeting.targets" TargetFramework="%(_TargetFrameworks.Identity)" />
<_OurFiles Include="$(OutputPath)%(_TargetFrameworks.Identity)\Microsoft.VisualBasic.CurrentVersion.targets" TargetFramework="%(_TargetFrameworks.Identity)" />
<_OurFiles Include="$(OutputPath)%(_TargetFrameworks.Identity)\Microsoft.VisualBasic.targets" TargetFramework="%(_TargetFrameworks.Identity)" />
- <_OurFiles Include="$(OutputPath)%(_TargetFrameworks.Identity)\Microsoft.VisualStudioVersion.v11.Common.props" TargetFramework="%(_TargetFrameworks.Identity)" />
- <_OurFiles Include="$(OutputPath)%(_TargetFrameworks.Identity)\Microsoft.VisualStudioVersion.v12.Common.props" TargetFramework="%(_TargetFrameworks.Identity)" />
- <_OurFiles Include="$(OutputPath)%(_TargetFrameworks.Identity)\Microsoft.VisualStudioVersion.v14.Common.props" TargetFramework="%(_TargetFrameworks.Identity)" />
<_OurFiles Include="$(OutputPath)%(_TargetFrameworks.Identity)\ref\**" TargetFramework="%(_TargetFrameworks.Identity)" Subdirectory="ref\" />
diff --git a/src/MSBuild/MSBuildClientApp.cs b/src/MSBuild/MSBuildClientApp.cs
index be768b58b8d..3eeb975bc40 100644
--- a/src/MSBuild/MSBuildClientApp.cs
+++ b/src/MSBuild/MSBuildClientApp.cs
@@ -97,28 +97,5 @@ public static MSBuildApp.ExitType Execute(
return MSBuildApp.ExitType.MSBuildClientFailure;
}
-
- // Copied from NodeProviderOutOfProcBase.cs
-#if RUNTIME_TYPE_NETCORE
- private static string? CurrentHost;
- private static string GetCurrentHost()
- {
- if (CurrentHost == null)
- {
- string dotnetExe = Path.Combine(FileUtilities.GetFolderAbove(BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory, 2),
- NativeMethodsShared.IsWindows ? "dotnet.exe" : "dotnet");
- if (File.Exists(dotnetExe))
- {
- CurrentHost = dotnetExe;
- }
- else
- {
- CurrentHost = EnvironmentUtilities.ProcessPath ?? throw new InvalidOperationException("Failed to retrieve process executable.");
- }
- }
-
- return CurrentHost;
- }
-#endif
}
}
diff --git a/src/MSBuild/OutOfProcTaskHostNode.cs b/src/MSBuild/OutOfProcTaskHostNode.cs
index f862ae2adca..9b670a086d4 100644
--- a/src/MSBuild/OutOfProcTaskHostNode.cs
+++ b/src/MSBuild/OutOfProcTaskHostNode.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
@@ -592,6 +591,16 @@ public void DeserializeAndRoutePacket(int nodeId, NodePacketType packetType, ITr
_packetFactory.DeserializeAndRoutePacket(nodeId, packetType, translator);
}
+ ///
+ /// Takes a serializer and deserializes the packet.
+ ///
+ /// The packet type.
+ /// The translator containing the data from which the packet should be reconstructed.
+ public INodePacket DeserializePacket(NodePacketType packetType, ITranslator translator)
+ {
+ return _packetFactory.DeserializePacket(packetType, translator);
+ }
+
///
/// Routes the specified packet
///
diff --git a/src/MSBuild/PerformanceLogEventListener.cs b/src/MSBuild/PerformanceLogEventListener.cs
index 6772a6aeefc..a42f05194bc 100644
--- a/src/MSBuild/PerformanceLogEventListener.cs
+++ b/src/MSBuild/PerformanceLogEventListener.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.IO;
using System.Text;
@@ -22,7 +21,7 @@ internal struct ProviderConfiguration
internal EventLevel Level { get; set; }
}
- private static ProviderConfiguration[] s_config =
+ private static readonly ProviderConfiguration[] s_config =
[
new ProviderConfiguration()
{
@@ -82,7 +81,7 @@ internal void Initialize(string logDirectory)
_processIDStr = EnvironmentUtilities.CurrentProcessId.ToString();
// Use a GUID disambiguator to make sure that we have a unique file name.
- string logFilePath = Path.Combine(logDirectory, $"perf-{_processIDStr}-{Guid.NewGuid().ToString("N")}.log");
+ string logFilePath = Path.Combine(logDirectory, $"perf-{_processIDStr}-{Guid.NewGuid():N}.log");
Stream outputStream = new FileStream(
logFilePath,
@@ -143,7 +142,7 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData)
s_builder.Clear();
}
- s_builder.Append($"[{DateTime.UtcNow.ToString("o")}] Event={eventData.EventSource.Name}/{eventData.EventName} ProcessID={_processIDStr} ThreadID={System.Threading.Thread.CurrentThread.ManagedThreadId}\t ");
+ s_builder.Append($"[{DateTime.UtcNow:o}] Event={eventData.EventSource.Name}/{eventData.EventName} ProcessID={_processIDStr} ThreadID={Environment.CurrentManagedThreadId}\t ");
for (int i = 0; i < eventData.PayloadNames.Count; i++)
{
s_builder.Append($"{eventData.PayloadNames[i]}=\"{eventData.Payload[i]}\" ");
diff --git a/src/MSBuild/Resources/xlf/Strings.zh-Hans.xlf b/src/MSBuild/Resources/xlf/Strings.zh-Hans.xlf
index 24c3f4dcb45..0968a8a75fb 100644
--- a/src/MSBuild/Resources/xlf/Strings.zh-Hans.xlf
+++ b/src/MSBuild/Resources/xlf/Strings.zh-Hans.xlf
@@ -841,9 +841,9 @@
WarningsOnly -- 仅显示警告。
NoItemAndPropertyList -- 在开始生成每个项目时不显示
项和属性的列表。
- ShowCommandLine -- 显示 TaskCommandLineEvent 消息
+ ShowCommandLine -- 显示 TaskCommandLineEvent 消息
ShowTimestamp -- 将时间戳作为所有消息的前缀
- 显示。
+ 显示。
ShowEventId -- 显示已开始事件、已完成事件和消息
的事件 ID。
ForceNoAlign -- 不将文本与控制台缓冲区的大小
@@ -900,10 +900,10 @@
Example:
-validate:MyExtendedBuildSchema.xsd
- -validate 依据默认架构验证项目。(缩写:
+ -validate 依据默认架构验证项目。(缩写:
-val)
- -validate:<schema> 依据指定的架构验证项目。(缩写:
+ -validate:<schema> 依据指定的架构验证项目。(缩写:
-val)
示例:
-validate:MyExtendedBuildSchema.xsd
@@ -1081,7 +1081,7 @@
-toolsversion:<version>
要在生成过程中使用的 MSBuild 工具集
(任务、目标等)的版本。此版本将重写
- 各个项目指定的版本。(缩写:
+ 各个项目指定的版本。(缩写:
-tv)
示例:
-toolsversion:3.5
@@ -1137,17 +1137,17 @@
template and append the node id to this fileName to
create a log file for each node.
- -distributedFileLogger
+ -distributedFileLogger
将生成输出记录到多个日志文件,每个 MSBuild 节点
一个日志文件。这些文件的初始位置为
当前目录。默认情况下,这些文件名为
“MSBuild<nodeid>.log”。可通过添加
- “-fileLoggerParameters”开关来指定
+ “-fileLoggerParameters”开关来指定
这些文件的位置和 fileLogger 的其他参数。
如果日志文件名是通过 fileLoggerParameters
开关设置的,分布式记录器将使用 fileName 作为
- 模板并将节点 ID 附加到此 fileName
+ 模板并将节点 ID 附加到此 fileName
以便为每个节点创建一个日志文件。
@@ -1189,12 +1189,12 @@
-flp1:warningsonly;logfile=msbuild.wrn
-flp2:errorsonly;logfile=msbuild.err
- -fileloggerparameters[n]:<parameters>
+ -fileloggerparameters[n]:<parameters>
为文件记录器提供任何额外的参数。
存在此开关意味着
存在对应的 -filelogger[n] 开关。
“n”(如果存在)可以为 1-9 的数字。
- 任何分布式文件记录器也可以使用
+ 任何分布式文件记录器也可以使用
-fileloggerparameters,具体可参阅 -distributedFileLogger 的说明。
(缩写: -flp[n])
为控制台记录器列出的相同参数
@@ -1214,8 +1214,8 @@
-fileLoggerParameters:LogFile=MyLog.log;Append;
Verbosity=diagnostic;Encoding=UTF-8
- -flp:Summary;Verbosity=minimal;LogFile=msbuild.sum
- -flp1:warningsonly;logfile=msbuild.wrn
+ -flp:Summary;Verbosity=minimal;LogFile=msbuild.sum
+ -flp1:warningsonly;logfile=msbuild.wrn
-flp2:errorsonly;logfile=msbuild.err
@@ -2200,4 +2200,4 @@