1- use std:: rc:: Rc ;
1+ use std:: { collections :: BTreeMap , rc:: Rc } ;
22
3- use biome_css_syntax:: { CssRoot , CssSyntaxNode } ;
4- use biome_rowan:: TextRange ;
3+ use biome_css_syntax:: CssRoot ;
4+ use biome_rowan:: { TextRange , TextSize } ;
55use rustc_hash:: FxHashMap ;
66
77/// The façade for all semantic information of a CSS document.
@@ -24,11 +24,6 @@ impl SemanticModel {
2424 & self . data . root
2525 }
2626
27- /// Retrieves a node by its text range.
28- pub fn node_by_range ( & self , range : TextRange ) -> Option < & CssSyntaxNode > {
29- self . data . node_by_range . get ( & range)
30- }
31-
3227 /// Returns a slice of all rules in the CSS document.
3328 pub fn rules ( & self ) -> & [ Rule ] {
3429 & self . data . rules
@@ -44,12 +39,26 @@ impl SemanticModel {
4439
4540 /// Returns the rule that contains the given range.
4641 pub fn get_rule_by_range ( & self , target_range : TextRange ) -> Option < & Rule > {
47- self . data
48- . range_to_rule
49- . iter ( )
50- . filter ( |( rule_range, _) | rule_range. contains_range ( target_range) )
51- . min_by_key ( |( rule_range, _) | rule_range. len ( ) )
52- . map ( |( _, rule) | rule)
42+ // Generally, this function narrows down the search before finding the most specific rule for better performance.
43+ // But when the target range starts from 0, the BTreeMap's range method may not work as expected due to
44+ // the comparison semantics of TextRange.
45+
46+ // Handle the edge case where the target range starts from 0.
47+ if target_range. start ( ) == TextSize :: from ( 0 ) {
48+ self . data
49+ . range_to_rule
50+ . iter ( )
51+ . rev ( )
52+ . find ( |( & range, _) | range. contains_range ( target_range) )
53+ . map ( |( _, rule) | rule)
54+ } else {
55+ self . data
56+ . range_to_rule
57+ . range ( ..=target_range)
58+ . rev ( )
59+ . find ( |( & range, _) | range. contains_range ( target_range) )
60+ . map ( |( _, rule) | rule)
61+ }
5362 }
5463}
5564
@@ -60,16 +69,14 @@ impl SemanticModel {
6069#[ derive( Debug ) ]
6170pub ( crate ) struct SemanticModelData {
6271 pub ( crate ) root : CssRoot ,
63- /// Map to each by its range
64- pub ( crate ) node_by_range : FxHashMap < TextRange , CssSyntaxNode > ,
6572 /// List of all top-level rules in the CSS document
6673 pub ( crate ) rules : Vec < Rule > ,
6774 /// Map of CSS variables declared in the `:root` selector or using the @property rule.
6875 pub ( crate ) global_custom_variables : FxHashMap < String , CssGlobalCustomVariable > ,
6976 /// Map of all the rules by their id
7077 pub ( crate ) rules_by_id : FxHashMap < RuleId , Rule > ,
7178 /// Map of the range of each rule to the rule itself
72- pub ( crate ) range_to_rule : FxHashMap < TextRange , Rule > ,
79+ pub ( crate ) range_to_rule : BTreeMap < TextRange , Rule > ,
7380}
7481
7582/// Represents a CSS rule set, including its selectors, declarations, and nested rules.
0 commit comments