public void Build() { HasPathSeparators = false; Asterisk lastAsterisk = null; int fixedItemsLength = 0; for (int i = 0; i < Count; i++) { var item = this[i]; if (item is PathSeparator || item is DoubleAsterisk) { HasPathSeparators = true; } switch (item) { case Literal literal: if (lastAsterisk != null && lastAsterisk.LiteralAfterAsterisk == -1) { lastAsterisk.LiteralAfterAsterisk = i; } fixedItemsLength += literal.Source.Length; break; case PathSeparator _: if (lastAsterisk != null && lastAsterisk.LiteralAfterAsterisk == -1) { lastAsterisk.LiteralAfterAsterisk = i; } // First slash after ** could be skipped if (!(lastAsterisk is DoubleAsterisk) || fixedItemsLength > 0) { fixedItemsLength += 1; } break; case OneChar _: fixedItemsLength += 1; break; case Asterisk item1: if (lastAsterisk != null) { lastAsterisk.NextAsterisk = item1; lastAsterisk.FixedItemsLengthAfterAsterisk = fixedItemsLength; } fixedItemsLength = 0; lastAsterisk = item1; break; } } }
bool CheckMatchedByAsterisk(Asterisk asteriskItem, bool first, int oldStartPos, int newStartPos) { if (asteriskItem is SimpleAsterisk) { if (first && newStartPos == oldStartPos) { // a/b/ should *not* match "a/b/*" bool atStart = newStartPos == 0 || IsPathSeparator(myOptions, myStr[newStartPos - 1]); bool atEnd = newStartPos == myStr.Length || IsPathSeparator(myOptions, myStr[newStartPos]); if (atStart && atEnd) { return(false); } } if (newStartPos > oldStartPos) { if (myStr.IndexOfAny(PathSeparatorChars, oldStartPos, newStartPos - oldStartPos) != -1) { return(false); } if (first && myStr[oldStartPos] == '.' && !CheckDot(oldStartPos)) { return(false); } } } if (asteriskItem is DoubleAsterisk && newStartPos > oldStartPos) { int length = newStartPos - oldStartPos; if (newStartPos < myStr.Length) { // We also search for dot immediately after **. For example, pattern **.hidden shouldn't be matched by **/.hidden length++; } var dotPos = myStr.IndexOf('.', oldStartPos, length); if (dotPos != -1) { if (!CheckDot(dotPos)) { return(false); } } } return(true); }