rubydex 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -108,4 +108,5 @@ rules! {
108
108
 
109
109
  // Resolution
110
110
  UndefinedMethodVisibilityTarget;
111
+ UndefinedConstantVisibilityTarget;
111
112
  }
@@ -1200,9 +1200,7 @@ impl<'a> RubyIndexer<'a> {
1200
1200
  }
1201
1201
  Some(ruby_prism::Node::SelfNode { .. }) | None => match self.nesting_stack.last() {
1202
1202
  Some(Nesting::Method(_)) => {
1203
- // Dynamic private constant (called from a method), we ignore it but don't report an error since it's valid Ruby
1204
- // if being called from a singleton method.
1205
-
1203
+ self.visit_call_node_parts(node);
1206
1204
  return;
1207
1205
  }
1208
1206
  None => {
@@ -1211,7 +1209,7 @@ impl<'a> RubyIndexer<'a> {
1211
1209
  Offset::from_prism_location(&node.location()),
1212
1210
  "Private constant called at top level".to_string(),
1213
1211
  );
1214
-
1212
+ self.visit_call_node_parts(node);
1215
1213
  return;
1216
1214
  }
1217
1215
  _ => None,
@@ -1222,7 +1220,7 @@ impl<'a> RubyIndexer<'a> {
1222
1220
  Offset::from_prism_location(&node.location()),
1223
1221
  "Dynamic receiver for private constant".to_string(),
1224
1222
  );
1225
-
1223
+ self.visit_call_node_parts(node);
1226
1224
  return;
1227
1225
  }
1228
1226
  };
@@ -1252,19 +1250,16 @@ impl<'a> RubyIndexer<'a> {
1252
1250
  Offset::from_prism_location(&argument.location()),
1253
1251
  "Private constant called with non-symbol argument".to_string(),
1254
1252
  );
1255
-
1256
- return;
1253
+ self.visit(&argument);
1254
+ continue;
1257
1255
  }
1258
1256
  };
1259
1257
 
1260
1258
  let str_id = self.local_graph.intern_string(name);
1261
1259
  let offset = Offset::from_prism_location(&location);
1262
1260
  let definition = Definition::ConstantVisibility(Box::new(ConstantVisibilityDefinition::new(
1263
- self.local_graph.add_name(Name::new(
1264
- str_id,
1265
- receiver_name_id.map_or(ParentScope::None, ParentScope::Some),
1266
- self.current_lexical_scope_name_id(),
1267
- )),
1261
+ receiver_name_id,
1262
+ str_id,
1268
1263
  visibility,
1269
1264
  self.uri_id,
1270
1265
  offset,
@@ -1279,6 +1274,60 @@ impl<'a> RubyIndexer<'a> {
1279
1274
  }
1280
1275
  }
1281
1276
 
1277
+ fn handle_singleton_method_visibility(
1278
+ &mut self,
1279
+ node: &ruby_prism::CallNode,
1280
+ visibility: Visibility,
1281
+ call_name: &str,
1282
+ ) {
1283
+ match node.receiver() {
1284
+ Some(ruby_prism::Node::SelfNode { .. }) | None => match self.nesting_stack.last() {
1285
+ Some(Nesting::Method(_)) => {
1286
+ self.visit_call_node_parts(node);
1287
+ return;
1288
+ }
1289
+ None => {
1290
+ self.local_graph.add_diagnostic(
1291
+ Rule::InvalidMethodVisibility,
1292
+ Offset::from_prism_location(&node.location()),
1293
+ format!("`{call_name}` called at top level"),
1294
+ );
1295
+ self.visit_call_node_parts(node);
1296
+ return;
1297
+ }
1298
+ _ => {}
1299
+ },
1300
+ _ => {
1301
+ self.visit_call_node_parts(node);
1302
+ return;
1303
+ }
1304
+ }
1305
+
1306
+ let Some(arguments) = node.arguments() else {
1307
+ return;
1308
+ };
1309
+
1310
+ for argument in &arguments.arguments() {
1311
+ match argument {
1312
+ ruby_prism::Node::SymbolNode { .. } | ruby_prism::Node::StringNode { .. } => {
1313
+ self.create_method_visibility_definition(
1314
+ &argument,
1315
+ visibility,
1316
+ DefinitionFlags::SINGLETON_METHOD_VISIBILITY,
1317
+ );
1318
+ }
1319
+ _ => {
1320
+ self.local_graph.add_diagnostic(
1321
+ Rule::InvalidMethodVisibility,
1322
+ Offset::from_prism_location(&argument.location()),
1323
+ format!("`{call_name}` called with a non-literal argument"),
1324
+ );
1325
+ self.visit(&argument);
1326
+ }
1327
+ }
1328
+ }
1329
+ }
1330
+
1282
1331
  fn is_attr_call(arg: &ruby_prism::Node) -> bool {
1283
1332
  arg.as_call_node().is_some_and(|call| {
1284
1333
  let receiver = call.receiver();
@@ -1316,7 +1365,7 @@ impl<'a> RubyIndexer<'a> {
1316
1365
  arg,
1317
1366
  ruby_prism::Node::SymbolNode { .. } | ruby_prism::Node::StringNode { .. }
1318
1367
  ) {
1319
- self.create_method_visibility_definition(&arg, visibility);
1368
+ self.create_method_visibility_definition(&arg, visibility, DefinitionFlags::empty());
1320
1369
  } else {
1321
1370
  // Unsupported arg — diagnostic + visit for side effects.
1322
1371
  let arg_offset = Offset::from_prism_location(&arg.location());
@@ -1332,7 +1381,12 @@ impl<'a> RubyIndexer<'a> {
1332
1381
  }
1333
1382
  }
1334
1383
 
1335
- fn create_method_visibility_definition(&mut self, arg: &ruby_prism::Node, visibility: Visibility) {
1384
+ fn create_method_visibility_definition(
1385
+ &mut self,
1386
+ arg: &ruby_prism::Node,
1387
+ visibility: Visibility,
1388
+ flags: DefinitionFlags,
1389
+ ) {
1336
1390
  let (name, location) = match arg {
1337
1391
  ruby_prism::Node::SymbolNode { .. } => {
1338
1392
  let symbol = arg.as_symbol_node().unwrap();
@@ -1358,7 +1412,7 @@ impl<'a> RubyIndexer<'a> {
1358
1412
  self.uri_id,
1359
1413
  arg_offset,
1360
1414
  Box::default(),
1361
- DefinitionFlags::empty(),
1415
+ flags,
1362
1416
  self.current_nesting_definition_id(),
1363
1417
  )));
1364
1418
 
@@ -2052,6 +2106,12 @@ impl Visit<'_> for RubyIndexer<'_> {
2052
2106
  "public_constant" => {
2053
2107
  self.handle_constant_visibility(node, Visibility::Public);
2054
2108
  }
2109
+ "private_class_method" => {
2110
+ self.handle_singleton_method_visibility(node, Visibility::Private, "private_class_method");
2111
+ }
2112
+ "public_class_method" => {
2113
+ self.handle_singleton_method_visibility(node, Visibility::Public, "public_class_method");
2114
+ }
2055
2115
  _ => {
2056
2116
  // For method calls that we don't explicitly handle each part, we continue visiting their parts as we
2057
2117
  // may discover something inside