Lints and suggestions for the Nix programming language
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(repeated_keys): let-else and try-expression

+71 -56
+71 -56
lib/src/lints/repeated_keys.rs
··· 45 45 46 46 impl Rule for RepeatedKeys { 47 47 fn validate(&self, node: &SyntaxElement, _sess: &SessionInfo) -> Option<Report> { 48 - if let NodeOrToken::Node(node) = node 49 - && let Some(key_value) = KeyValue::cast(node.clone()) 50 - && let Some(key) = key_value.key() 51 - && let mut components = key.path() 52 - && let Some(first_component) = components.next() 53 - && let Some(first_component_ident) = Ident::cast(first_component) 54 - // ensure that there are >1 components 55 - && components.next().is_some() 56 - && let Some(parent_node) = node.parent() 57 - && let Some(parent_attr_set) = AttrSet::cast(parent_node) 58 - && !parent_attr_set.recursive() 59 - && let occurrences = parent_attr_set.entries().filter_map(|kv_scrutinee| { 48 + let NodeOrToken::Node(node) = node else { 49 + return None; 50 + }; 51 + 52 + let key_value = KeyValue::cast(node.clone())?; 53 + let key = key_value.key()?; 54 + let mut components = key.path(); 55 + let first_component = components.next()?; 56 + let first_component_ident = Ident::cast(first_component)?; 57 + 58 + // ensure that there are >1 components 59 + components.next()?; 60 + 61 + let parent_node = node.parent()?; 62 + let parent_attr_set = AttrSet::cast(parent_node)?; 63 + 64 + if parent_attr_set.recursive() { 65 + return None; 66 + } 67 + 68 + let occurrences = parent_attr_set 69 + .entries() 70 + .filter_map(|kv_scrutinee| { 60 71 let scrutinee_key = kv_scrutinee.key()?; 61 72 let mut kv_scrutinee_components = scrutinee_key.path(); 62 73 let kv_scrutinee_first_component = kv_scrutinee_components.next()?; 63 74 let kv_scrutinee_ident = Ident::cast(kv_scrutinee_first_component)?; 64 75 if kv_scrutinee_ident.as_str() == first_component_ident.as_str() { 65 76 Some(( 66 - kv_scrutinee.key()?.node().text_range(), 67 - kv_scrutinee_components 68 - .map(|n| n.to_string()) 69 - .collect::<Vec<_>>() 70 - .join("."), 77 + kv_scrutinee.key()?.node().text_range(), 78 + kv_scrutinee_components 79 + .map(|n| n.to_string()) 80 + .collect::<Vec<_>>() 81 + .join("."), 71 82 )) 72 83 } else { 73 84 None 74 85 } 75 - }).collect::<Vec<_>>() 76 - && occurrences.first()?.0 == key.node().text_range() 77 - && occurrences.len() >= 3 78 - { 79 - let mut iter = occurrences.into_iter(); 86 + }) 87 + .collect::<Vec<_>>(); 88 + 89 + if occurrences.first()?.0 != key.node().text_range() { 90 + return None; 91 + } 80 92 81 - let (first_annotation, first_subkey) = iter.next().unwrap(); 82 - let first_message = format!( 83 - "The key `{}` is first assigned here ...", 84 - first_component_ident.as_str() 85 - ); 93 + if occurrences.len() < 3 { 94 + return None; 95 + } 96 + 97 + let mut iter = occurrences.into_iter(); 98 + 99 + let (first_annotation, first_subkey) = iter.next().unwrap(); 100 + let first_message = format!( 101 + "The key `{}` is first assigned here ...", 102 + first_component_ident.as_str() 103 + ); 86 104 87 - let (second_annotation, second_subkey) = iter.next().unwrap(); 88 - let second_message = "... repeated here ..."; 105 + let (second_annotation, second_subkey) = iter.next().unwrap(); 106 + let second_message = "... repeated here ..."; 89 107 90 - let (third_annotation, third_subkey) = iter.next().unwrap(); 91 - let third_message = { 92 - let remaining_occurrences = iter.count(); 93 - let mut message = match remaining_occurrences { 94 - 0 => "... and here.".to_string(), 95 - 1 => "... and here (`1` occurrence omitted).".to_string(), 96 - n => format!("... and here (`{n}` occurrences omitted)."), 97 - }; 98 - write!( 99 - message, 100 - " Try `{} = {{ {}=...; {}=...; {}=...; }}` instead.", 101 - first_component_ident.as_str(), 102 - first_subkey, 103 - second_subkey, 104 - third_subkey 105 - ) 106 - .unwrap(); 107 - message 108 + let (third_annotation, third_subkey) = iter.next().unwrap(); 109 + let third_message = { 110 + let remaining_occurrences = iter.count(); 111 + let mut message = match remaining_occurrences { 112 + 0 => "... and here.".to_string(), 113 + 1 => "... and here (`1` occurrence omitted).".to_string(), 114 + n => format!("... and here (`{n}` occurrences omitted)."), 108 115 }; 116 + write!( 117 + message, 118 + " Try `{} = {{ {}=...; {}=...; {}=...; }}` instead.", 119 + first_component_ident.as_str(), 120 + first_subkey, 121 + second_subkey, 122 + third_subkey 123 + ) 124 + .unwrap(); 125 + message 126 + }; 109 127 110 - Some( 111 - self.report() 112 - .diagnostic(first_annotation, first_message) 113 - .diagnostic(second_annotation, second_message) 114 - .diagnostic(third_annotation, third_message), 115 - ) 116 - } else { 117 - None 118 - } 128 + Some( 129 + self.report() 130 + .diagnostic(first_annotation, first_message) 131 + .diagnostic(second_annotation, second_message) 132 + .diagnostic(third_annotation, third_message), 133 + ) 119 134 } 120 135 }