Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 34 additions & 41 deletions rust/rubydex/src/indexing/ruby_indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,31 +1194,33 @@ impl<'a> RubyIndexer<'a> {
fn handle_constant_visibility(&mut self, node: &ruby_prism::CallNode, visibility: Visibility) {
let receiver = node.receiver();

let receiver_name_id = match receiver {
let receiver_name_id = match &receiver {
Some(ruby_prism::Node::ConstantPathNode { .. } | ruby_prism::Node::ConstantReadNode { .. }) => {
self.index_constant_reference(&receiver.unwrap(), true)
self.index_constant_reference(receiver.as_ref().unwrap(), true)
}
Some(ruby_prism::Node::SelfNode { .. }) | None => match self.nesting_stack.last() {
Some(Nesting::Method(_)) => {
self.visit_call_node_parts(node);
return;
}
None => {
let call_name = String::from_utf8_lossy(node.name().as_slice());
self.local_graph.add_diagnostic(
Rule::InvalidPrivateConstant,
Offset::from_prism_location(&node.location()),
"Private constant called at top level".to_string(),
format!("`{call_name}` called at top level"),
);
self.visit_call_node_parts(node);
return;
}
_ => None,
},
_ => {
Some(other) => {
let call_name = String::from_utf8_lossy(node.name().as_slice());
self.local_graph.add_diagnostic(
Rule::InvalidPrivateConstant,
Offset::from_prism_location(&node.location()),
"Dynamic receiver for private constant".to_string(),
Offset::from_prism_location(&other.location()),
format!("Dynamic receiver for `{call_name}`"),
);
self.visit_call_node_parts(node);
return;
Expand All @@ -1230,29 +1232,14 @@ impl<'a> RubyIndexer<'a> {
};

for argument in &arguments.arguments() {
let (name, location) = match argument {
ruby_prism::Node::SymbolNode { .. } => {
let symbol = argument.as_symbol_node().unwrap();
if let Some(value_loc) = symbol.value_loc() {
(Self::location_to_string(&value_loc), value_loc)
} else {
continue;
}
}
ruby_prism::Node::StringNode { .. } => {
let string = argument.as_string_node().unwrap();
let name = String::from_utf8_lossy(string.unescaped()).to_string();
(name, argument.location())
}
_ => {
self.local_graph.add_diagnostic(
Rule::InvalidPrivateConstant,
Offset::from_prism_location(&argument.location()),
"Private constant called with non-symbol argument".to_string(),
);
self.visit(&argument);
continue;
}
let Some((name, location)) = Self::extract_literal_name(&argument) else {
self.local_graph.add_diagnostic(
Rule::InvalidPrivateConstant,
Offset::from_prism_location(&argument.location()),
"Private constant called with non-symbol argument".to_string(),
);
self.visit(&argument);
continue;
};

let str_id = self.local_graph.intern_string(name);
Expand Down Expand Up @@ -1414,6 +1401,22 @@ impl<'a> RubyIndexer<'a> {
}
}

fn extract_literal_name<'b>(arg: &ruby_prism::Node<'b>) -> Option<(String, ruby_prism::Location<'b>)> {
match arg {
ruby_prism::Node::SymbolNode { .. } => {
let symbol = arg.as_symbol_node().unwrap();
let value_loc = symbol.value_loc()?;
Some((Self::location_to_string(&value_loc), value_loc))
}
ruby_prism::Node::StringNode { .. } => {
let string = arg.as_string_node().unwrap();
let name = String::from_utf8_lossy(string.unescaped()).to_string();
Some((name, arg.location()))
}
_ => None,
}
}

fn is_attr_call(arg: &ruby_prism::Node) -> bool {
arg.as_call_node().is_some_and(|call| {
let receiver = call.receiver();
Expand Down Expand Up @@ -1473,18 +1476,8 @@ impl<'a> RubyIndexer<'a> {
visibility: Visibility,
flags: DefinitionFlags,
) {
let (name, location) = match arg {
ruby_prism::Node::SymbolNode { .. } => {
let symbol = arg.as_symbol_node().unwrap();
let Some(value_loc) = symbol.value_loc() else { return };
(Self::location_to_string(&value_loc), value_loc)
}
ruby_prism::Node::StringNode { .. } => {
let string = arg.as_string_node().unwrap();
let name = String::from_utf8_lossy(string.unescaped()).to_string();
(name, arg.location())
}
_ => return,
let Some((name, location)) = Self::extract_literal_name(arg) else {
return;
};

self.create_method_visibility_definition_from_name(&name, &location, visibility, flags);
Expand Down
6 changes: 3 additions & 3 deletions rust/rubydex/src/indexing/ruby_indexer_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1768,9 +1768,9 @@ mod visibility_tests {
assert_local_diagnostics_eq!(
&context,
vec![
"invalid-private-constant: Private constant called at top level (1:1-1:30)",
"invalid-private-constant: Private constant called at top level (2:1-2:35)",
"invalid-private-constant: Dynamic receiver for private constant (3:1-3:34)",
"invalid-private-constant: `private_constant` called at top level (1:1-1:30)",
"invalid-private-constant: `private_constant` called at top level (2:1-2:35)",
"invalid-private-constant: Dynamic receiver for `private_constant` (3:1-3:4)",
"invalid-private-constant: Private constant called with non-symbol argument (6:20-6:31)",
"invalid-private-constant: Private constant called with non-symbol argument (6:33-6:44)",
]
Expand Down
Loading