@@ -47,6 +47,11 @@ pub struct GroupSelector {
4747 /// - "workspace-protocol" or -!workspace-protocol"
4848 pub include_specifier_types : Vec < String > ,
4949 pub exclude_specifier_types : Vec < String > ,
50+ // Cache frequently accessed values
51+ has_dependency_type_filters : bool ,
52+ has_specifier_type_filters : bool ,
53+ has_dependency_filters : bool ,
54+ has_package_filters : bool ,
5055}
5156
5257impl GroupSelector {
@@ -57,44 +62,73 @@ impl GroupSelector {
5762 label : String ,
5863 packages : Vec < String > ,
5964 specifier_types : Vec < String > ,
65+ all_dependency_types : & [ DependencyType ] ,
6066 ) -> GroupSelector {
6167 let dependencies = with_resolved_keywords ( & dependencies, all_packages) ;
68+
69+ let include_dependencies = create_globs ( true , & dependencies) ;
70+ let exclude_dependencies = create_globs ( false , & dependencies) ;
71+ let include_dependency_types = create_identifiers ( true , & dependency_types) ;
72+ let exclude_dependency_types = create_identifiers ( false , & dependency_types) ;
73+ let include_packages = create_globs ( true , & packages) ;
74+ let exclude_packages = create_globs ( false , & packages) ;
75+ let include_specifier_types = create_identifiers ( true , & specifier_types) ;
76+ let exclude_specifier_types = create_identifiers ( false , & specifier_types) ;
77+
78+ // Validate dependency types during construction
79+ for expected in include_dependency_types. iter ( ) . chain ( exclude_dependency_types. iter ( ) ) {
80+ if !all_dependency_types. iter ( ) . any ( |actual| actual. name == * expected) {
81+ error ! ( "dependencyType '{expected}' does not match any of syncpack or your customTypes" ) ;
82+ error ! ( "check your syncpack config file" ) ;
83+ process:: exit ( 1 ) ;
84+ }
85+ }
86+
6287 GroupSelector {
63- include_dependencies : create_globs ( true , & dependencies) ,
64- exclude_dependencies : create_globs ( false , & dependencies) ,
65- include_dependency_types : create_identifiers ( true , & dependency_types) ,
66- exclude_dependency_types : create_identifiers ( false , & dependency_types) ,
88+ // Pre-compute boolean flags to avoid repeated empty checks
89+ has_dependency_type_filters : !include_dependency_types. is_empty ( ) || !exclude_dependency_types. is_empty ( ) ,
90+ has_specifier_type_filters : !include_specifier_types. is_empty ( ) || !exclude_specifier_types. is_empty ( ) ,
91+ has_dependency_filters : !include_dependencies. is_empty ( ) || !exclude_dependencies. is_empty ( ) ,
92+ has_package_filters : !include_packages. is_empty ( ) || !exclude_packages. is_empty ( ) ,
93+
94+ include_dependencies,
95+ exclude_dependencies,
96+ include_dependency_types,
97+ exclude_dependency_types,
6798 label,
68- include_packages : create_globs ( true , & packages ) ,
69- exclude_packages : create_globs ( false , & packages ) ,
70- include_specifier_types : create_identifiers ( true , & specifier_types ) ,
71- exclude_specifier_types : create_identifiers ( false , & specifier_types ) ,
99+ include_packages,
100+ exclude_packages,
101+ include_specifier_types,
102+ exclude_specifier_types,
72103 }
73104 }
74105
75- pub fn can_add ( & self , all_dependency_types : & [ DependencyType ] , descriptor : & InstanceDescriptor ) -> bool {
76- self . has_valid_dependency_types ( all_dependency_types)
77- && self . matches_dependency_types ( descriptor)
78- && self . matches_packages ( descriptor)
79- && self . matches_dependencies ( descriptor)
80- && self . matches_specifier_types ( descriptor)
81- }
106+ pub fn can_add ( & self , descriptor : & InstanceDescriptor ) -> bool {
107+ // Order checks from cheapest/most-likely-to-fail to most expensive
108+ // 1. Specifier types (often empty, cheap string comparison)
109+ if self . has_specifier_type_filters && !self . matches_specifier_types ( descriptor) {
110+ return false ;
111+ }
112+
113+ // 2. Dependency types (cheap string comparison)
114+ if self . has_dependency_type_filters && !self . matches_dependency_types ( descriptor) {
115+ return false ;
116+ }
117+
118+ // 3. Dependencies (glob matching, more expensive)
119+ if self . has_dependency_filters && !self . matches_dependencies ( descriptor) {
120+ return false ;
121+ }
122+
123+ // 4. Packages (glob matching + borrow, most expensive)
124+ if self . has_package_filters && !self . matches_packages ( descriptor) {
125+ return false ;
126+ }
82127
83- fn has_valid_dependency_types ( & self , all_dependency_types : & [ DependencyType ] ) -> bool {
84- self
85- . include_dependency_types
86- . iter ( )
87- . chain ( self . exclude_dependency_types . iter ( ) )
88- . for_each ( |expected| {
89- if !all_dependency_types. iter ( ) . any ( |actual| actual. name == * expected) {
90- error ! ( "dependencyType '{expected}' does not match any of syncpack or your customTypes" ) ;
91- error ! ( "check your syncpack config file" ) ;
92- process:: exit ( 1 ) ;
93- }
94- } ) ;
95128 true
96129 }
97130
131+ #[ inline]
98132 fn matches_dependency_types ( & self , descriptor : & InstanceDescriptor ) -> bool {
99133 matches_identifiers (
100134 & descriptor. dependency_type . name ,
@@ -103,21 +137,25 @@ impl GroupSelector {
103137 )
104138 }
105139
140+ #[ inline]
106141 fn matches_packages ( & self , descriptor : & InstanceDescriptor ) -> bool {
107- matches_globs ( & descriptor. package . borrow ( ) . name , & self . include_packages , & self . exclude_packages )
142+ // Cache the borrow result to avoid repeated borrow checks
143+ let package_name = & descriptor. package . borrow ( ) . name ;
144+ matches_globs ( package_name, & self . include_packages , & self . exclude_packages )
108145 }
109146
147+ #[ inline]
110148 fn matches_dependencies ( & self , descriptor : & InstanceDescriptor ) -> bool {
111149 matches_globs ( & descriptor. internal_name , & self . include_dependencies , & self . exclude_dependencies )
112150 }
113151
152+ #[ inline]
114153 fn matches_specifier_types ( & self , descriptor : & InstanceDescriptor ) -> bool {
115- self . include_specifier_types . is_empty ( )
116- || matches_identifiers (
117- & descriptor. specifier . get_config_identifier ( ) ,
118- & self . include_specifier_types ,
119- & self . exclude_specifier_types ,
120- )
154+ matches_identifiers (
155+ & descriptor. specifier . get_config_identifier ( ) ,
156+ & self . include_specifier_types ,
157+ & self . exclude_specifier_types ,
158+ )
121159 }
122160}
123161
@@ -158,7 +196,7 @@ fn matches_identifiers(name: &str, includes: &[String], excludes: &[String]) ->
158196}
159197
160198fn matches_any_identifier ( value : & str , identifiers : & [ String ] ) -> bool {
161- identifiers. contains ( & value . to_string ( ) )
199+ identifiers. iter ( ) . any ( |id| id == value )
162200}
163201
164202/// Resolve keywords such as `$LOCAL` and `!$LOCAL` to their actual values.
0 commit comments