@@ -625,51 +625,51 @@ public func configurationForEntryPoint(from args: __CommandLineArguments_v0) thr
625625#endif
626626
627627 // Filtering
628+
629+ // Filters currently come in two flavors: those with a prefix and those
630+ // without. Those without a prefix are treated the same as those with an
631+ // "id:" prefix.
632+ enum FilterPrefix : String , CaseIterable {
633+ case id = " id: "
634+ case tag = " tag: "
635+ }
628636 var filters = [ Configuration . TestFilter] ( )
629637 func testFilters( forOptionArguments optionArguments: [ String ] ? , label: String , membership: Configuration . TestFilter . Membership ) throws -> [ Configuration . TestFilter ] {
630-
631- // Filters will come in two flavors: those with `tag:` as a prefix, and
632- // those without. We split them into two collections, taking care to handle
633- // an escaped colon, treating it as a pseudo-operator.
634- let tagPrefix = " tag: "
635- let escapedTagPrefix = #"tag\:"#
636- var tags = [ Tag] ( )
637- var regexes = [ String] ( )
638+ var tagPatterns = [ String] ( )
639+ var idPatterns = [ String] ( )
638640
639641 // Loop through all the option arguments, separating tags from regex filters
640642 for var optionArg in optionArguments ?? [ ] {
641- if optionArg. hasPrefix ( tagPrefix) {
642- // Running into the `tag:` prefix means we should strip it and use the
643- // actual tag name the user has provided
644- let tagStringWithoutPrefix = String ( optionArg. dropFirst ( tagPrefix. count) )
645- tags. append ( Tag ( userProvidedStringValue: tagStringWithoutPrefix) )
646- } else {
647- // If we run into the escaped tag prefix, the user has indicated they
648- // want to us to treat it as a regex filter. We need to to unescape it
649- // before adding it as a regex filter
650- if optionArg. hasPrefix ( escapedTagPrefix) {
651- optionArg. replaceSubrange ( escapedTagPrefix. startIndex..< escapedTagPrefix. endIndex, with: tagPrefix)
643+ if let prefix = FilterPrefix . allCases. first ( where: { optionArg. hasPrefix ( $0. rawValue) } ) {
644+ // We have encountered a prefix, so trim it off and add the supplied
645+ // argument to the appropriate filter list
646+ optionArg. trimPrefix ( prefix. rawValue)
647+ switch prefix {
648+ case . id: idPatterns. append ( optionArg)
649+ case . tag: tagPatterns. append ( optionArg)
652650 }
653- regexes. append ( optionArg)
651+ } else {
652+ // No prefix was detected, so we treat this as a regex matching a test ID.
653+ idPatterns. append ( optionArg)
654654 }
655655 }
656656
657657 // If we didn't find any tags, the tagFilter should be .unfiltered,
658658 // otherwise we construct it with the provided tags
659- let tagFilter : Configuration . TestFilter = switch ( membership, tags . isEmpty) {
659+ let tagFilter : Configuration . TestFilter = switch ( membership, tagPatterns . isEmpty) {
660660 case ( _, true ) : . unfiltered
661- case ( . including, false ) : Configuration . TestFilter ( includingAnyOf : tags )
662- case ( . excluding, false ) : Configuration . TestFilter ( excludingAnyOf : tags )
661+ case ( . including, false ) : Configuration . TestFilter ( includingTagsMatching : tagPatterns )
662+ case ( . excluding, false ) : Configuration . TestFilter ( excludingTagsMatching : tagPatterns )
663663 }
664664
665- guard !regexes . isEmpty else {
665+ guard !idPatterns . isEmpty else {
666666 // Return early with just the tag filter, otherwise we try to match
667667 // against an empty array of regular expressions which is _not_
668668 // equivalent to `.unfiltered`.
669669 return [ tagFilter]
670670 }
671671
672- return [ try Configuration . TestFilter ( membership: membership, matchingAnyOf: regexes ) , tagFilter]
672+ return [ try Configuration . TestFilter ( membership: membership, matchingAnyOf: idPatterns ) , tagFilter]
673673 }
674674
675675 filters += try testFilters ( forOptionArguments: args. filter, label: " --filter " , membership: . including)
0 commit comments