/Microsoft.Build/Microsoft.Build/Microsoft/Build/Evaluation/ExpressionShredder.cs
C# | 635 lines | 627 code | 8 blank | 0 comment | 74 complexity | a447007d7632df23d6649e584473c55f MD5 | raw file
Possible License(s): Apache-2.0, LGPL-3.0
- namespace Microsoft.Build.Evaluation
- {
- using Microsoft.Build.Collections;
- using Microsoft.Build.Shared;
- using System;
- using System.Collections.Generic;
- using System.Runtime;
-
- internal static class ExpressionShredder
- {
- internal static bool ContainsMetadataExpressionOutsideTransform(string expression)
- {
- ItemsAndMetadataPair pair = new ItemsAndMetadataPair(null, null);
- GetReferencedItemNamesAndMetadata(expression, 0, expression.Length, ref pair, ShredderOptions.MetadataOutsideTransforms);
- return ((pair.Metadata != null) && (pair.Metadata.Count > 0));
- }
-
- internal static List<ItemExpressionCapture> GetReferencedItemExpressions(string expression)
- {
- return GetReferencedItemExpressions(expression, 0, expression.Length);
- }
-
- internal static List<ItemExpressionCapture> GetReferencedItemExpressions(string expression, int start, int end)
- {
- List<ItemExpressionCapture> list = null;
- if (expression.IndexOf('@') < 0)
- {
- return null;
- }
- for (int i = start; i < end; i++)
- {
- if (!Sink(expression, ref i, end, '@', '('))
- {
- continue;
- }
- List<ItemExpressionCapture> captures = null;
- string itemType = null;
- string separator = null;
- int separatorStart = -1;
- int length = -1;
- int num2 = i - 1;
- int index = i - 2;
- SinkWhitespace(expression, ref i);
- int startIndex = i;
- if (!SinkValidName(expression, ref i, end))
- {
- i = num2;
- continue;
- }
- if (((end > i) && (expression[i - 1] == '-')) && (expression[i] == '>'))
- {
- i--;
- }
- itemType = expression.Substring(startIndex, i - startIndex);
- SinkWhitespace(expression, ref i);
- bool flag = true;
- while (Sink(expression, ref i, end, '-', '>') && flag)
- {
- SinkWhitespace(expression, ref i);
- int startTransform = i;
- bool flag2 = SinkSingleQuotedExpression(expression, ref i, end);
- if (flag2)
- {
- int num8 = startTransform + 1;
- int num9 = i - 1;
- if (captures == null)
- {
- captures = new List<ItemExpressionCapture>();
- }
- captures.Add(new ItemExpressionCapture(num8, num9 - num8, expression.Substring(num8, num9 - num8)));
- }
- else
- {
- startTransform = i;
- ItemExpressionCapture item = SinkItemFunctionExpression(expression, startTransform, ref i, end);
- if (item != null)
- {
- if (captures == null)
- {
- captures = new List<ItemExpressionCapture>();
- }
- captures.Add(item);
- continue;
- }
- if (!flag2 && (item == null))
- {
- i = num2;
- flag = false;
- }
- }
- }
- if (flag)
- {
- SinkWhitespace(expression, ref i);
- if (Sink(expression, ref i, ','))
- {
- SinkWhitespace(expression, ref i);
- if (!Sink(expression, ref i, '\''))
- {
- i = num2;
- continue;
- }
- int num10 = expression.IndexOf('\'', i);
- if (num10 == -1)
- {
- i = num2;
- continue;
- }
- separatorStart = i - index;
- length = num10 - i;
- separator = expression.Substring(i, length);
- i = num10 + 1;
- }
- SinkWhitespace(expression, ref i);
- if (!Sink(expression, ref i, ')'))
- {
- i = num2;
- }
- else
- {
- int num11 = i;
- i--;
- if (list == null)
- {
- list = new List<ItemExpressionCapture>();
- }
- ItemExpressionCapture capture2 = new ItemExpressionCapture(index, num11 - index, expression.Substring(index, num11 - index), itemType, separator, separatorStart, length, captures);
- list.Add(capture2);
- }
- }
- }
- return list;
- }
-
- internal static ItemsAndMetadataPair GetReferencedItemNamesAndMetadata(List<string> expressions)
- {
- ItemsAndMetadataPair pair = new ItemsAndMetadataPair(null, null);
- foreach (string str in expressions)
- {
- GetReferencedItemNamesAndMetadata(str, 0, str.Length, ref pair, ShredderOptions.All);
- }
- return pair;
- }
-
- private static void GetReferencedItemNamesAndMetadata(string expression, int start, int end, ref ItemsAndMetadataPair pair, ShredderOptions whatToShredFor)
- {
- for (int i = start; i < end; i++)
- {
- int num2;
- if (Sink(expression, ref i, end, '@', '('))
- {
- num2 = i - 1;
- SinkWhitespace(expression, ref i);
- int startIndex = i;
- if (!SinkValidName(expression, ref i, end))
- {
- i = num2;
- }
- else
- {
- if (((end > i) && (expression[i - 1] == '-')) && (expression[i] == '>'))
- {
- i--;
- }
- string item = expression.Substring(startIndex, i - startIndex);
- SinkWhitespace(expression, ref i);
- bool flag = true;
- while (Sink(expression, ref i, end, '-', '>') && flag)
- {
- SinkWhitespace(expression, ref i);
- int startTransform = i;
- bool flag2 = SinkSingleQuotedExpression(expression, ref i, end);
- if (!flag2)
- {
- ItemExpressionCapture capture = SinkItemFunctionExpression(expression, startTransform, ref i, end);
- if (((capture == null) && !flag2) && (capture == null))
- {
- i = num2;
- flag = false;
- }
- }
- }
- if (flag)
- {
- SinkWhitespace(expression, ref i);
- if (Sink(expression, ref i, ','))
- {
- SinkWhitespace(expression, ref i);
- if (!Sink(expression, ref i, '\''))
- {
- i = num2;
- continue;
- }
- int index = expression.IndexOf('\'', i);
- if (index == -1)
- {
- i = num2;
- continue;
- }
- GetReferencedItemNamesAndMetadata(expression, i, index, ref pair, ShredderOptions.MetadataOutsideTransforms);
- i = index + 1;
- }
- SinkWhitespace(expression, ref i);
- if (!Sink(expression, ref i, ')'))
- {
- i = num2;
- }
- else
- {
- if ((whatToShredFor & ShredderOptions.ItemTypes) != ShredderOptions.Invalid)
- {
- pair.Items = pair.Items ?? new HashSet<string>(MSBuildNameIgnoreCaseComparer.Default);
- pair.Items.Add(item);
- }
- i--;
- }
- }
- }
- }
- else if (Sink(expression, ref i, end, '%', '('))
- {
- num2 = i - 1;
- SinkWhitespace(expression, ref i);
- int num6 = i;
- if (!SinkValidName(expression, ref i, end))
- {
- i = num2;
- }
- else
- {
- string str4;
- string str5;
- string str2 = expression.Substring(num6, i - num6);
- string itemName = null;
- SinkWhitespace(expression, ref i);
- if (Sink(expression, ref i, '.'))
- {
- SinkWhitespace(expression, ref i);
- num6 = i;
- if (!SinkValidName(expression, ref i, end))
- {
- i = num2;
- continue;
- }
- itemName = str2;
- str4 = expression.Substring(num6, i - num6);
- str5 = itemName + "." + str4;
- }
- else
- {
- str4 = str2;
- str5 = str4;
- }
- SinkWhitespace(expression, ref i);
- if (!Sink(expression, ref i, ')'))
- {
- i = num2;
- }
- else
- {
- if ((whatToShredFor & ShredderOptions.MetadataOutsideTransforms) != ShredderOptions.Invalid)
- {
- pair.Metadata = pair.Metadata ?? new Dictionary<string, MetadataReference>(MSBuildNameIgnoreCaseComparer.Default);
- pair.Metadata[str5] = new MetadataReference(itemName, str4);
- }
- i--;
- }
- }
- }
- }
- }
-
- private static bool Sink(string expression, ref int i, char c)
- {
- if ((i < expression.Length) && (expression[i] == c))
- {
- i++;
- return true;
- }
- return false;
- }
-
- private static bool Sink(string expression, ref int i, int end, char c1, char c2)
- {
- if (((i < (end - 1)) && (expression[i] == c1)) && (expression[i + 1] == c2))
- {
- i += 2;
- return true;
- }
- return false;
- }
-
- private static unsafe bool SinkArgumentsInParentheses(string expression, ref int i, int end)
- {
- int num = 0;
- int length = expression.Length;
- fixed (char* str = ((char*) expression))
- {
- char ch;
- char* chPtr = str;
- if (chPtr[i] == '(')
- {
- num++;
- i++;
- goto Label_0085;
- }
- return false;
- Label_0036:
- ch = chPtr[i];
- switch (ch)
- {
- case '\'':
- case '`':
- case '"':
- {
- int num3 = i;
- if (!SinkUntilClosingQuote(ch, expression, ref i, end))
- {
- i = num3;
- return false;
- }
- break;
- }
- case '(':
- num++;
- break;
-
- case ')':
- num--;
- break;
- }
- i++;
- Label_0085:
- if (((i < length) && (i < end)) && (num > 0))
- {
- goto Label_0036;
- }
- }
- return (num == 0);
- }
-
- private static ItemExpressionCapture SinkItemFunctionExpression(string expression, int startTransform, ref int i, int end)
- {
- if (!SinkValidName(expression, ref i, end))
- {
- return null;
- }
- int num = i;
- SinkWhitespace(expression, ref i);
- int startIndex = i + 1;
- if (!SinkArgumentsInParentheses(expression, ref i, end))
- {
- return null;
- }
- int num3 = i - 1;
- ItemExpressionCapture capture = new ItemExpressionCapture(startTransform, i - startTransform, expression.Substring(startTransform, i - startTransform)) {
- FunctionName = expression.Substring(startTransform, num - startTransform)
- };
- if (num3 > startIndex)
- {
- capture.FunctionArguments = expression.Substring(startIndex, num3 - startIndex);
- }
- return capture;
- }
-
- private static bool SinkSingleQuotedExpression(string expression, ref int i, int end)
- {
- if (Sink(expression, ref i, '\''))
- {
- while ((i < end) && (expression[i] != '\''))
- {
- i++;
- }
- i++;
- if (end <= i)
- {
- return false;
- }
- return true;
- }
- return false;
- }
-
- private static unsafe bool SinkUntilClosingQuote(char quoteChar, string expression, ref int i, int end)
- {
- fixed (char* str = ((char*) expression))
- {
- char* chPtr = str;
- i++;
- while ((i < expression.Length) && (i < end))
- {
- if (chPtr[i] == quoteChar)
- {
- return true;
- }
- i++;
- }
- }
- return false;
- }
-
- private static bool SinkValidName(string expression, ref int i, int end)
- {
- if ((end <= i) || !XmlUtilities.IsValidInitialElementNameCharacter(expression[i]))
- {
- return false;
- }
- i++;
- while ((end > i) && XmlUtilities.IsValidSubsequentElementNameCharacter(expression[i]))
- {
- i++;
- }
- return true;
- }
-
- private static void SinkWhitespace(string expression, ref int i)
- {
- while ((i < expression.Length) && char.IsWhiteSpace(expression[i]))
- {
- i++;
- }
- }
-
- internal static IList<string> SplitSemiColonSeparatedList(string expression)
- {
- string str;
- expression = expression.Trim();
- if (expression.Length == 0)
- {
- return ReadOnlyEmptyList<string>.Instance;
- }
- List<string> list = new List<string>(1);
- int startIndex = 0;
- bool flag = false;
- bool flag2 = false;
- for (int i = 0; i < expression.Length; i++)
- {
- switch (expression[i])
- {
- case '\'':
- if (flag)
- {
- flag2 = !flag2;
- }
- break;
-
- case ')':
- if (flag && !flag2)
- {
- flag = false;
- }
- break;
-
- case ';':
- if (!flag)
- {
- str = expression.Substring(startIndex, i - startIndex).Trim();
- if (str.Length > 0)
- {
- list.Add(str);
- }
- startIndex = i + 1;
- }
- break;
-
- case '@':
- if ((expression.Length > (i + 1)) && (expression[i + 1] == '('))
- {
- flag = true;
- }
- break;
- }
- }
- str = expression.Substring(startIndex, expression.Length - startIndex).Trim();
- if (str.Length > 0)
- {
- list.Add(str);
- }
- return list;
- }
-
- internal class ItemExpressionCapture
- {
- private List<ExpressionShredder.ItemExpressionCapture> captures;
- private string functionArguments;
- private string functionName;
- private int index;
- private string itemType;
- private int length;
- private string separator;
- private int separatorLength;
- private int separatorStart;
- private string value;
-
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- public ItemExpressionCapture(int index, int length, string subExpression) : this(index, length, subExpression, null, null, -1, -1, null)
- {
- }
-
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- public ItemExpressionCapture(int index, int length, string subExpression, string itemType, string separator, int separatorStart, int separatorLength, List<ExpressionShredder.ItemExpressionCapture> captures)
- {
- this.index = index;
- this.length = length;
- this.value = subExpression;
- this.itemType = itemType;
- this.separator = separator;
- this.separatorStart = separatorStart;
- this.separatorLength = separatorLength;
- this.captures = captures;
- }
-
- public override string ToString()
- {
- return this.value;
- }
-
- public List<ExpressionShredder.ItemExpressionCapture> Captures
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.captures;
- }
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- set
- {
- this.captures = value;
- }
- }
-
- public string FunctionArguments
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.functionArguments;
- }
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- set
- {
- this.functionArguments = value;
- }
- }
-
- public string FunctionName
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.functionName;
- }
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- set
- {
- this.functionName = value;
- }
- }
-
- public int Index
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.index;
- }
- }
-
- public string ItemType
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.itemType;
- }
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- set
- {
- this.itemType = value;
- }
- }
-
- public int Length
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.length;
- }
- }
-
- public string Separator
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.separator;
- }
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- set
- {
- this.separator = value;
- }
- }
-
- public int SeparatorLength
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.separatorLength;
- }
- }
-
- public int SeparatorStart
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.separatorStart;
- }
- }
-
- public string Value
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.value;
- }
- }
- }
- }
- }
-