From 04453943e8770ba119c4dc37d0e2a0ed0c5d2f2e Mon Sep 17 00:00:00 2001 From: SimaTian Date: Thu, 2 Jan 2025 16:41:27 +0100 Subject: [PATCH 1/2] changing expander regex to use code generated version instead of compiled one where applicable --- src/Build/Evaluation/Expander.cs | 53 ++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/Build/Evaluation/Expander.cs b/src/Build/Evaluation/Expander.cs index aef481962ab..15c8fe69a2a 100644 --- a/src/Build/Evaluation/Expander.cs +++ b/src/Build/Evaluation/Expander.cs @@ -129,7 +129,7 @@ internal enum ExpanderOptions /// /// Type of the properties used. /// Type of the items used. - internal class Expander + internal partial class Expander where P : class, IProperty where I : class, IItem { @@ -952,7 +952,7 @@ internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTa // if there are no item vectors in the string // run a simpler Regex to find item metadata references MetadataMatchEvaluator matchEvaluator = new MetadataMatchEvaluator(metadata, options, elementLocation, loggingContext); - result = RegularExpressions.ItemMetadataPattern.Value.Replace(expression, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); + result = RegularExpressions.ItemMetadataPatternWrapper().Replace(expression, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); } else { @@ -983,7 +983,7 @@ internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTa // Extract the part of the expression that appears before the item vector expression // e.g. the ABC in ABC@(foo->'%(FullPath)') string subExpressionToReplaceIn = expression.Substring(start, itemVectorExpressions[n].Index - start); - string replacementResult = RegularExpressions.NonTransformItemMetadataPattern.Value.Replace(subExpressionToReplaceIn, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); + string replacementResult = RegularExpressions.NonTransformItemMetadataPatternWrapper().Replace(subExpressionToReplaceIn, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); // Append the metadata replacement finalResultBuilder.Append(replacementResult); @@ -991,7 +991,7 @@ internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTa // Expand any metadata that appears in the item vector expression's separator if (itemVectorExpressions[n].Separator != null) { - vectorExpression = RegularExpressions.NonTransformItemMetadataPattern.Value.Replace(itemVectorExpressions[n].Value, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata), -1, itemVectorExpressions[n].SeparatorStart); + vectorExpression = RegularExpressions.NonTransformItemMetadataPatternWrapper().Replace(itemVectorExpressions[n].Value, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata), -1, itemVectorExpressions[n].SeparatorStart); } // Append the item vector expression as is @@ -1008,7 +1008,7 @@ internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTa if (start < expression.Length) { string subExpressionToReplaceIn = expression.Substring(start); - string replacementResult = RegularExpressions.NonTransformItemMetadataPattern.Value.Replace(subExpressionToReplaceIn, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); + string replacementResult = RegularExpressions.NonTransformItemMetadataPatternWrapper().Replace(subExpressionToReplaceIn, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); finalResultBuilder.Append(replacementResult); } @@ -2719,7 +2719,7 @@ internal static IEnumerable> ExpandQuotedExpressionFunct { matchEvaluator = new MetadataMatchEvaluator(item.Key, item.Value, elementLocation); - include = RegularExpressions.ItemMetadataPattern.Value.Replace(arguments[0], matchEvaluator.GetMetadataValueFromMatch); + include = RegularExpressions.ItemMetadataPatternWrapper().Replace(arguments[0], matchEvaluator.GetMetadataValueFromMatch); } // Include may be empty. Historically we have created items with empty include @@ -3086,13 +3086,19 @@ internal string GetMetadataValueFromMatch(Match match) /// Regular expressions used by the expander. /// The expander currently uses regular expressions rather than a parser to do its work. /// - private static class RegularExpressions + private static partial class RegularExpressions { /************************************************************************************************************************** * WARNING: The regular expressions below MUST be kept in sync with the expressions in the ProjectWriter class -- if the * description of an item vector changes, the expressions must be updated in both places. *************************************************************************************************************************/ + + +#if NET7_0_OR_GREATER + [GeneratedRegex(ItemMetadataSpecification, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture)] + internal static partial Regex ItemMetadataPattern(); +#else /// /// Regular expression used to match item metadata references embedded in strings. /// For example, %(Compile.DependsOn) or %(DependsOn). @@ -3100,10 +3106,20 @@ private static class RegularExpressions internal static readonly Lazy ItemMetadataPattern = new Lazy( () => new Regex(ItemMetadataSpecification, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture | RegexOptions.Compiled)); +#endif - /// - /// Name of the group matching the "name" of a metadatum. - /// + internal static Regex ItemMetadataPatternWrapper() + { +#if NET7_0_OR_GREATER + return ItemMetadataPattern(); +#else + return ItemMetadataPattern.Value; +#endif + } + + /// + /// Name of the group matching the "name" of a metadatum. + /// internal const string NameGroup = "NAME"; /// @@ -3116,6 +3132,14 @@ private static class RegularExpressions /// internal const string ItemTypeGroup = "ITEM_TYPE"; +#if NET7_0_OR_GREATER + [GeneratedRegex(@"((?<=" + ItemVectorWithTransformLHS + @")" + ItemMetadataSpecification + @"(?!" + + ItemVectorWithTransformRHS + @")) | ((? /// regular expression used to match item metadata references outside of item vector transforms. /// @@ -3128,6 +3152,15 @@ private static class RegularExpressions ItemVectorWithTransformLHS + @")" + ItemMetadataSpecification + @"(?!" + ItemVectorWithTransformRHS + @"))", RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture | RegexOptions.Compiled)); +#endif + internal static Regex NonTransformItemMetadataPatternWrapper() + { +#if NET7_0_OR_GREATER + return NonTransformItemMetadataPattern(); +#else + return NonTransformItemMetadataPattern.Value; +#endif + } /// /// Complete description of an item metadata reference, including the optional qualifying item type. From 7dbfd3712334857e0ff5a85084d42b818621fdba Mon Sep 17 00:00:00 2001 From: SimaTian Date: Fri, 3 Jan 2025 14:38:09 +0100 Subject: [PATCH 2/2] review update --- src/Build/Evaluation/Expander.cs | 49 +++++++++++++++++--------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/Build/Evaluation/Expander.cs b/src/Build/Evaluation/Expander.cs index 15c8fe69a2a..05ad3902a6f 100644 --- a/src/Build/Evaluation/Expander.cs +++ b/src/Build/Evaluation/Expander.cs @@ -952,7 +952,7 @@ internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTa // if there are no item vectors in the string // run a simpler Regex to find item metadata references MetadataMatchEvaluator matchEvaluator = new MetadataMatchEvaluator(metadata, options, elementLocation, loggingContext); - result = RegularExpressions.ItemMetadataPatternWrapper().Replace(expression, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); + result = RegularExpressions.ItemMetadataRegex.Replace(expression, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); } else { @@ -983,7 +983,7 @@ internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTa // Extract the part of the expression that appears before the item vector expression // e.g. the ABC in ABC@(foo->'%(FullPath)') string subExpressionToReplaceIn = expression.Substring(start, itemVectorExpressions[n].Index - start); - string replacementResult = RegularExpressions.NonTransformItemMetadataPatternWrapper().Replace(subExpressionToReplaceIn, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); + string replacementResult = RegularExpressions.NonTransformItemMetadataRegex.Replace(subExpressionToReplaceIn, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); // Append the metadata replacement finalResultBuilder.Append(replacementResult); @@ -991,7 +991,7 @@ internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTa // Expand any metadata that appears in the item vector expression's separator if (itemVectorExpressions[n].Separator != null) { - vectorExpression = RegularExpressions.NonTransformItemMetadataPatternWrapper().Replace(itemVectorExpressions[n].Value, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata), -1, itemVectorExpressions[n].SeparatorStart); + vectorExpression = RegularExpressions.NonTransformItemMetadataRegex.Replace(itemVectorExpressions[n].Value, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata), -1, itemVectorExpressions[n].SeparatorStart); } // Append the item vector expression as is @@ -1008,7 +1008,7 @@ internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTa if (start < expression.Length) { string subExpressionToReplaceIn = expression.Substring(start); - string replacementResult = RegularExpressions.NonTransformItemMetadataPatternWrapper().Replace(subExpressionToReplaceIn, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); + string replacementResult = RegularExpressions.NonTransformItemMetadataRegex.Replace(subExpressionToReplaceIn, new MatchEvaluator(matchEvaluator.ExpandSingleMetadata)); finalResultBuilder.Append(replacementResult); } @@ -2719,7 +2719,7 @@ internal static IEnumerable> ExpandQuotedExpressionFunct { matchEvaluator = new MetadataMatchEvaluator(item.Key, item.Value, elementLocation); - include = RegularExpressions.ItemMetadataPatternWrapper().Replace(arguments[0], matchEvaluator.GetMetadataValueFromMatch); + include = RegularExpressions.ItemMetadataRegex.Replace(arguments[0], matchEvaluator.GetMetadataValueFromMatch); } // Include may be empty. Historically we have created items with empty include @@ -3108,13 +3108,16 @@ private static partial class RegularExpressions RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture | RegexOptions.Compiled)); #endif - internal static Regex ItemMetadataPatternWrapper() + internal static Regex ItemMetadataRegex { + get + { #if NET7_0_OR_GREATER - return ItemMetadataPattern(); + return ItemMetadataPattern(); #else - return ItemMetadataPattern.Value; + return ItemMetadataPattern.Value; #endif + } } /// @@ -3132,12 +3135,14 @@ internal static Regex ItemMetadataPatternWrapper() /// internal const string ItemTypeGroup = "ITEM_TYPE"; + internal const string NonTransformItemMetadataSpecification = @"((?<=" + ItemVectorWithTransformLHS + @")" + ItemMetadataSpecification + @"(?!" + + ItemVectorWithTransformRHS + @")) | ((? @@ -3145,21 +3150,19 @@ internal static Regex ItemMetadataPatternWrapper() /// /// PERF WARNING: this Regex is complex and tends to run slowly. internal static readonly Lazy NonTransformItemMetadataPattern = new Lazy( - () => new Regex( - @"((?<=" + ItemVectorWithTransformLHS + @")" + ItemMetadataSpecification + @"(?!" + - ItemVectorWithTransformRHS + @")) | ((? new Regex(NonTransformItemMetadataSpecification, + RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture | RegexOptions.Compiled)); #endif - internal static Regex NonTransformItemMetadataPatternWrapper() + internal static Regex NonTransformItemMetadataRegex { + get + { #if NET7_0_OR_GREATER - return NonTransformItemMetadataPattern(); + return NonTransformItemMetadataPattern(); #else - return NonTransformItemMetadataPattern.Value; + return NonTransformItemMetadataPattern.Value; #endif + } } ///