rubydex 0.4.0 → 0.4.1

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -20
  3. data/ext/rubydex/definition.c +34 -0
  4. data/ext/rubydex/definition.h +3 -0
  5. data/ext/rubydex/diagnostic.c +2 -49
  6. data/ext/rubydex/extconf.rb +4 -2
  7. data/ext/rubydex/graph.c +59 -11
  8. data/lib/rubydex/cli/command/lint/explain.rb +8 -6
  9. data/lib/rubydex/cli/command/lint.rb +10 -4
  10. data/lib/rubydex/linter/rule_loader.rb +1 -1
  11. data/lib/rubydex/rules/dynamic_ancestor.rb +29 -0
  12. data/lib/rubydex/rules/dynamic_constant_reference.rb +25 -0
  13. data/lib/rubydex/rules/dynamic_singleton_definition.rb +30 -0
  14. data/lib/rubydex/rules/invalid_constant_visibility.rb +28 -0
  15. data/lib/rubydex/rules/invalid_method_visibility.rb +28 -0
  16. data/lib/rubydex/rules/parse_error.rb +25 -0
  17. data/lib/rubydex/rules/parse_warning.rb +28 -0
  18. data/lib/rubydex/rules/top_level_mixin_self.rb +27 -0
  19. data/lib/rubydex/rules/undefined_constant_visibility_target.rb +27 -0
  20. data/lib/rubydex/rules/undefined_method_visibility_target.rb +27 -0
  21. data/lib/rubydex/skill.rb +1 -0
  22. data/lib/rubydex/version.rb +1 -1
  23. data/lib/rubydex.rb +2 -0
  24. data/lib/rubydex_linter/rules/rule_structure.rb +19 -4
  25. data/rbi/rubydex.rbi +32 -130
  26. data/rust/rubydex/Cargo.toml +4 -0
  27. data/rust/rubydex/src/bin/generate_ruby_rules.rs +94 -0
  28. data/rust/rubydex/src/diagnostic.rs +142 -51
  29. data/rust/rubydex/src/query.rs +191 -1
  30. data/rust/rubydex-sys/src/definition_api.rs +68 -1
  31. data/rust/rubydex-sys/src/diagnostic_api.rs +0 -35
  32. data/rust/rubydex-sys/src/graph_api.rs +112 -11
  33. data/rust/rubydex-sys/src/name_api.rs +47 -11
  34. metadata +13 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c097d20f2e7fbb252e1a0a9e802986b51c951caec785d9a8a22e41779928f2ce
4
- data.tar.gz: 8d987121c97c13ffcf3258830c612d5447a7c5efd4a572f6a9ce37de3669e881
3
+ metadata.gz: 8f1587b49ae8f48d2c9696ac5068591ac24e5bfced6c8a14cb62f6f78e09d8af
4
+ data.tar.gz: 0511b66149af2baa1a4cc61d2a8d902cbb72ea4cf27450fa69e1c7d1bb93fbf1
5
5
  SHA512:
6
- metadata.gz: b978a10b5fe6fe5f76dc916abda86c019bee6b7d36d4b9aa1af4bdb6da88053dc8bceb60d271c559230c16fb2661361bb73f4cbd8dffb4f4fd317b210683c466
7
- data.tar.gz: c90b49725da1efb7597eb15855f829e7a897feb3d7be4cfb5c59543b346965e3485c06fb7358620b4c36674a453ccc9c66f7182c959508c21324eba4af14d354
6
+ metadata.gz: 655ae864ec17820f073e12897408ef71cff2d29c6a63bbb103010f8783caf5b20301ce75acfe26919ed512eb31b5133de562f06d9cb7f6693f25ffb38bd7117a
7
+ data.tar.gz: 762c31f230059a2a667a5756b66e619bf1b7855656cf23924e8adb60b58d992f7ed06e7b95477b9f894f9d911c99fc3e00174e97f991ea091df73f0f9b8fc863
data/README.md CHANGED
@@ -114,7 +114,7 @@ Thread safety comes from an `RwLock` on the Rust side, **not** from Ruby's
114
114
 
115
115
  All built-in tools are experimental. These tools can change without deprecation warnings.
116
116
 
117
- ### `rdx query`
117
+ ### Querying
118
118
 
119
119
  Rubydex exposes the indexed graph through a read-only subset of the
120
120
  [Cypher](https://opencypher.org/) query language. Only read clauses (`MATCH`,
@@ -153,27 +153,11 @@ puts result.render("json")
153
153
  puts Rubydex::Query.schema("table")
154
154
  ```
155
155
 
156
- ### `rdx lint`
156
+ ### Linter
157
157
 
158
- Put rule files under `rubydex_linter/rules`. Each rule must inherit from `Rubydex::Linter::CustomRule`.
158
+ See the [linter docs](docs/linter.md).
159
159
 
160
- Run the linter:
161
-
162
- ```bash
163
- bundle exec rdx lint
164
- ```
165
-
166
- Rubydex uses the bundle root, or the current directory when no bundle is available.
167
-
168
- Configure a rule in `rubydex.toml`:
169
-
170
- ```toml
171
- [linter.rules.<Rule name>]
172
- enabled = true
173
- exclude = ["path_to_skip/**"]
174
- ```
175
-
176
- ### `rdx mcp`
160
+ ### MCP server
177
161
 
178
162
  Rubydex can run as an MCP (Model Context Protocol) server, enabling AI assistants
179
163
  like Claude to semantically query your Ruby codebase.
@@ -38,6 +38,17 @@ VALUE cClassVariableDefinition;
38
38
  VALUE cMethodAliasDefinition;
39
39
  VALUE cGlobalVariableAliasDefinition;
40
40
 
41
+ uint64_t rdxi_definition_id_for_graph(VALUE definition, VALUE graph_obj) {
42
+ HandleData *data;
43
+ TypedData_Get_Struct(definition, HandleData, &handle_type, data);
44
+
45
+ if (data->graph_obj != graph_obj) {
46
+ rb_raise(rb_eArgError, "definition must belong to this graph");
47
+ }
48
+
49
+ return data->id;
50
+ }
51
+
41
52
  // Keep this in sync with definition.rs
42
53
  VALUE rdxi_definition_class_for_kind(DefinitionKind kind) {
43
54
  switch (kind) {
@@ -153,6 +164,25 @@ static VALUE rdxr_definition_name(VALUE self) {
153
164
  return rdxi_owned_c_string_to_ruby(name);
154
165
  }
155
166
 
167
+ /*
168
+ * call-seq:
169
+ * raw_name -> String
170
+ *
171
+ * Returns the class, module, or constant name as written in source, preserving explicit parent scopes like "Foo::Bar"
172
+ * and rooted paths like "::Bar".
173
+ */
174
+ static VALUE rdxr_definition_raw_name(VALUE self) {
175
+ HandleData *data;
176
+ void *graph = rdxi_graph_from_handle(self, &data);
177
+
178
+ const char *name = rdx_definition_raw_name(graph, data->id);
179
+ if (name == NULL) {
180
+ rb_raise(rb_eRuntimeError, "Definition not found");
181
+ }
182
+
183
+ return rdxi_owned_c_string_to_ruby(name);
184
+ }
185
+
156
186
  /*
157
187
  * call-seq:
158
188
  * deprecated? -> bool
@@ -442,6 +472,7 @@ void rdxi_initialize_definition(VALUE mod) {
442
472
  rb_define_method(cDefinition, "document", rdxr_definition_document, 0);
443
473
 
444
474
  cClassDefinition = rb_define_class_under(mRubydex, "ClassDefinition", cDefinition);
475
+ rb_define_method(cClassDefinition, "raw_name", rdxr_definition_raw_name, 0);
445
476
  rb_define_method(cClassDefinition, "superclass", rdxr_class_definition_superclass, 0);
446
477
  rb_define_method(cClassDefinition, "mixins", rdxr_definition_mixins, 0);
447
478
 
@@ -449,10 +480,13 @@ void rdxi_initialize_definition(VALUE mod) {
449
480
  rb_define_method(cSingletonClassDefinition, "mixins", rdxr_definition_mixins, 0);
450
481
 
451
482
  cModuleDefinition = rb_define_class_under(mRubydex, "ModuleDefinition", cDefinition);
483
+ rb_define_method(cModuleDefinition, "raw_name", rdxr_definition_raw_name, 0);
452
484
  rb_define_method(cModuleDefinition, "mixins", rdxr_definition_mixins, 0);
453
485
 
454
486
  cConstantDefinition = rb_define_class_under(mRubydex, "ConstantDefinition", cDefinition);
487
+ rb_define_method(cConstantDefinition, "raw_name", rdxr_definition_raw_name, 0);
455
488
  cConstantAliasDefinition = rb_define_class_under(mRubydex, "ConstantAliasDefinition", cDefinition);
489
+ rb_define_method(cConstantAliasDefinition, "raw_name", rdxr_definition_raw_name, 0);
456
490
  cConstantVisibilityDefinition = rb_define_class_under(mRubydex, "ConstantVisibilityDefinition", cDefinition);
457
491
  cMethodVisibilityDefinition = rb_define_class_under(mRubydex, "MethodVisibilityDefinition", cDefinition);
458
492
  cMethodDefinition = rb_define_class_under(mRubydex, "MethodDefinition", cDefinition);
@@ -22,6 +22,9 @@ extern VALUE cGlobalVariableAliasDefinition;
22
22
 
23
23
  void rdxi_initialize_definition(VALUE mRubydex);
24
24
 
25
+ // Returns the definition ID after verifying that the definition belongs to `graph_obj`.
26
+ uint64_t rdxi_definition_id_for_graph(VALUE definition, VALUE graph_obj);
27
+
25
28
  // Returns the Ruby class for a given DefinitionKind without calling back into Rust
26
29
  VALUE rdxi_definition_class_for_kind(DefinitionKind kind);
27
30
 
@@ -6,11 +6,8 @@
6
6
  * mRubydex = rb_define_module("Rubydex")
7
7
  */
8
8
 
9
- static VALUE mRubydex;
10
9
  static VALUE mRules;
11
10
  VALUE cDiagnostic;
12
- static VALUE cRule;
13
- static ID id_default_severity;
14
11
 
15
12
  VALUE rdxi_build_diagnostic_severity_value(VALUE mRubydex, DiagnosticSeverity severity) {
16
13
  VALUE mSeverity = rb_const_get(mRubydex, rb_intern("Severity"));
@@ -31,55 +28,11 @@ VALUE rdxi_build_diagnostic_severity_value(VALUE mRubydex, DiagnosticSeverity se
31
28
  return Qnil;
32
29
  }
33
30
 
34
- /*
35
- * call-seq:
36
- * default_severity -> Rubydex::Severity::Base
37
- *
38
- * Returns the Rubydex::Severity subclass the diagnostics of this rule get unless the configuration overrides it.
39
- */
40
- static VALUE rdxr_generated_rule_default_severity(VALUE self) {
41
- VALUE severity = rb_attr_get(self, id_default_severity);
42
-
43
- // Class-level instance variables are not inherited, so a class inheriting from a generated rule reaches this without
44
- // a severity of its own.
45
- if (NIL_P(severity)) {
46
- rb_raise(rb_eRuntimeError, "Rule %s has no default severity", rb_class2name(self));
47
- }
48
-
49
- return severity;
50
- }
51
-
52
- // Generates a rule class for every rule the graph can report. Severities are resolved here rather than when they are
53
- // read, which is why Rubydex::Severity is loaded before this extension (see `lib/rubydex.rb`).
54
- static void define_generated_rules(void) {
55
- CRuleArray rule_array = rdx_rules();
56
- VALUE rules = rb_ary_new_capa((long)rule_array.len);
57
-
58
- for (size_t i = 0; i < rule_array.len; i++) {
59
- CRule built_in_rule = rule_array.items[i];
60
- VALUE name = rb_utf8_str_new(built_in_rule.name, (long)built_in_rule.name_length);
61
- VALUE rule = rb_define_class_under(mRules, StringValueCStr(name), cRule);
62
- VALUE severity = rdxi_build_diagnostic_severity_value(mRubydex, built_in_rule.default_severity);
63
-
64
- rb_ivar_set(rule, id_default_severity, severity);
65
- rb_define_singleton_method(rule, "default_severity", rdxr_generated_rule_default_severity, 0);
66
- rb_ary_push(rules, rule);
67
- }
68
-
69
- rdx_rules_free(rule_array);
70
- rb_define_const(mRules, "ALL", rb_obj_freeze(rules));
71
- }
72
-
73
31
  VALUE rdxi_rule_class_from_name(const char *name, size_t length) {
74
32
  return rb_const_get_at(mRules, rb_intern2(name, (long)length));
75
33
  }
76
34
 
77
35
  void rdxi_initialize_diagnostic(VALUE moduleRubydex) {
78
- mRubydex = moduleRubydex;
79
- id_default_severity = rb_intern("@default_severity");
80
-
81
- cDiagnostic = rb_define_class_under(mRubydex, "Diagnostic", rb_cObject);
82
- cRule = rb_define_class_under(mRubydex, "Rule", rb_cObject);
83
- mRules = rb_define_module_under(mRubydex, "Rules");
84
- define_generated_rules();
36
+ cDiagnostic = rb_define_class_under(moduleRubydex, "Diagnostic", rb_cObject);
37
+ mRules = rb_define_module_under(moduleRubydex, "Rules");
85
38
  }
@@ -23,12 +23,12 @@ release = ENV["RELEASE"] || !developing_rubydex
23
23
  root_dir = gem_dir.join("rust")
24
24
  target_dir = root_dir.join("target")
25
25
  target_dir = target_dir.join("x86_64-pc-windows-gnu") if Gem.win_platform?
26
- target_dir = target_dir.join(release ? "release" : "debug")
26
+ target_dir = target_dir.join("$(RUST_PROFILE)")
27
27
 
28
28
  bindings_path = root_dir.join("rubydex-sys").join("rustbindings.h")
29
29
 
30
30
  cargo_args = ["--manifest-path #{root_dir.join("Cargo.toml")}"]
31
- cargo_args << "--release" if release
31
+ cargo_args << "$(CARGO_PROFILE_FLAG)"
32
32
 
33
33
  if Gem.win_platform?
34
34
  cargo_args << "--target x86_64-pc-windows-gnu"
@@ -102,6 +102,8 @@ makefile = File.read("Makefile")
102
102
 
103
103
  new_makefile = makefile.gsub("$(OBJS): $(HDRS) $(ruby_headers)", <<~MAKEFILE.chomp)
104
104
  .PHONY: compile_rust
105
+ RUST_PROFILE = $(if $(strip $(RELEASE)),release,#{developing_rubydex ? "debug" : "release"})
106
+ CARGO_PROFILE_FLAG = $(if $(filter release,$(RUST_PROFILE)),--release)
105
107
  RUST_SRCS = #{File.expand_path("Cargo.toml", root_dir)} #{File.expand_path("Cargo.lock", root_dir)} #{rust_srcs.join(" ")}
106
108
 
107
109
  .rust_built: $(RUST_SRCS)
data/ext/rubydex/graph.c CHANGED
@@ -1,6 +1,7 @@
1
1
  #include "graph.h"
2
2
  #include "config.h"
3
3
  #include "declaration.h"
4
+ #include "definition.h"
4
5
  #include "diagnostic.h"
5
6
  #include "document.h"
6
7
  #include "location.h"
@@ -256,6 +257,30 @@ static VALUE rdxr_graph_fuzzy_search(int argc, VALUE *argv, VALUE self) {
256
257
  return rdxr_graph_yield_search_results(self, iter);
257
258
  }
258
259
 
260
+ /*
261
+ * call-seq:
262
+ * dead_code_candidates -> Enumerator[Rubydex::Declaration]
263
+ *
264
+ * Returns an enumerator over declarations that may be unused because the analysis could not find any references to
265
+ * them. This misses metaprogramming or untyped code, which is why the term candidates is used.
266
+ *
267
+ * Currently, only supports constants.
268
+ */
269
+ static VALUE rdxr_graph_dead_code_candidates(VALUE self) {
270
+ if (!rb_block_given_p()) {
271
+ return rb_enumeratorize(self, rb_str_new2("dead_code_candidates"), 0, NULL);
272
+ }
273
+
274
+ void *graph;
275
+ TypedData_Get_Struct(self, void *, &graph_type, graph);
276
+
277
+ void *iter = rdx_graph_dead_code_candidates(graph);
278
+ VALUE args = rb_ary_new_from_args(2, self, ULL2NUM((uintptr_t)iter));
279
+ rb_ensure(rdxi_declarations_yield, args, rdxi_declarations_ensure, args);
280
+
281
+ return self;
282
+ }
283
+
259
284
  // Body function for rb_ensure in Graph#documents
260
285
  static VALUE graph_documents_yield(VALUE args) {
261
286
  VALUE self = rb_ary_entry(args, 0);
@@ -486,26 +511,48 @@ static VALUE rdxr_graph_set_encoding(VALUE self, VALUE encoding) {
486
511
 
487
512
  /*
488
513
  * call-seq:
489
- * resolve_constant(name, nesting) -> Rubydex::Declaration?
514
+ * resolve_constant(name, context) -> Rubydex::Declaration?
490
515
  *
491
- * Runs the resolver on a single constant reference to determine what it points to.
516
+ * Runs the resolver on a single constant reference using an array of nesting names or a namespace definition as its
517
+ * context.
492
518
  */
493
- static VALUE rdxr_graph_resolve_constant(VALUE self, VALUE const_name, VALUE nesting) {
519
+ static VALUE rdxr_graph_resolve_constant(VALUE self, VALUE const_name, VALUE context) {
494
520
  Check_Type(const_name, T_STRING);
495
- rdxi_check_array_of_strings(nesting);
496
521
  const char *const_name_string = StringValueCStr(const_name);
497
522
 
498
- // Convert the given file paths into a char** array, so that we can pass to Rust
499
- size_t length = RARRAY_LEN(nesting);
500
- char **converted_file_paths = rdxi_str_array_to_char(nesting, length);
501
-
502
523
  void *graph;
503
524
  TypedData_Get_Struct(self, void *, &graph_type, graph);
504
525
 
505
- const CDeclaration *decl =
506
- rdx_graph_resolve_constant(graph, const_name_string, (const char **)converted_file_paths, length);
526
+ const CDeclaration *decl;
527
+ if (RB_TYPE_P(context, T_ARRAY)) {
528
+ rdxi_check_array_of_strings(context);
529
+
530
+ size_t length = RARRAY_LEN(context);
531
+ char **converted_names = rdxi_str_array_to_char(context, length);
532
+ decl = rdx_graph_resolve_constant(graph, const_name_string, (const char **)converted_names, length);
533
+ rdxi_free_str_array(converted_names, length);
534
+ } else if (rb_obj_is_kind_of(context, cClassDefinition) ||
535
+ rb_obj_is_kind_of(context, cSingletonClassDefinition) ||
536
+ rb_obj_is_kind_of(context, cModuleDefinition)) {
537
+ uint64_t definition_id = rdxi_definition_id_for_graph(context, self);
538
+ CDefinitionConstantResolutionResult result =
539
+ rdx_graph_resolve_constant_from_definition(graph, const_name_string, definition_id);
540
+
541
+ if (result.status == CDefinitionConstantResolution_DefinitionNotFound) {
542
+ rb_raise(rb_eRuntimeError, "Definition not found");
543
+ }
544
+ if (result.status == CDefinitionConstantResolution_InvalidDefinitionKind) {
545
+ // This is unreachable because the rb_obj_is_kind_of checks above only accept supported definition kinds.
546
+ rb_raise(rb_eRuntimeError, "Unexpected definition kind");
547
+ }
507
548
 
508
- rdxi_free_str_array(converted_file_paths, length);
549
+ decl = result.declaration;
550
+ } else {
551
+ rb_raise(
552
+ rb_eTypeError,
553
+ "context must be an Array of Strings, ClassDefinition, SingletonClassDefinition, or ModuleDefinition"
554
+ );
555
+ }
509
556
 
510
557
  if (decl == NULL) {
511
558
  return Qnil;
@@ -938,6 +985,7 @@ void rdxi_initialize_graph(VALUE moduleRubydex) {
938
985
  rb_define_method(cGraph, "[]", rdxr_graph_aref, 1);
939
986
  rb_define_method(cGraph, "search", rdxr_graph_search, -1);
940
987
  rb_define_method(cGraph, "fuzzy_search", rdxr_graph_fuzzy_search, -1);
988
+ rb_define_method(cGraph, "dead_code_candidates", rdxr_graph_dead_code_candidates, 0);
941
989
  rb_define_method(cGraph, "encoding=", rdxr_graph_set_encoding, 1);
942
990
  rb_define_method(cGraph, "resolve_require_path", rdxr_graph_resolve_require_path, 2);
943
991
  rb_define_method(cGraph, "require_paths", rdxr_graph_require_paths, 1);
@@ -9,8 +9,10 @@ module Rubydex
9
9
  class Lint
10
10
  # `rdx lint explain <RULE>` — prints documentation for rules with a matching name.
11
11
  class Explain < Command
12
- BASE_RULE_NAME = "Rubydex::Linter::CustomRule" #: String
13
- BASE_RULE_PATH = File.expand_path("../../../linter/custom_rule.rb", __dir__) #: String
12
+ BASE_PATHS = [
13
+ File.expand_path("../../../linter/custom_rule.rb", __dir__),
14
+ File.expand_path("../../../rule.rb", __dir__),
15
+ ] #: Array[String]
14
16
 
15
17
  class << self
16
18
  #: -> String
@@ -30,17 +32,17 @@ module Rubydex
30
32
  workspace_path = current_workspace_path
31
33
 
32
34
  graph = Rubydex::Graph.configure_for_workspace(workspace_path)
33
- graph.index_all([BASE_RULE_PATH, *Rubydex::Linter::RuleLoader.paths(workspace_path)])
35
+ graph.index_all([*BASE_PATHS, *Rubydex::Linter::RuleLoader.paths(workspace_path)])
34
36
  graph.resolve
35
37
 
36
- base_rule = graph[BASE_RULE_NAME]
37
- abort("Base rule class #{BASE_RULE_NAME} is not found. This is likely an issue in Rubydex itself") unless base_rule.is_a?(Rubydex::Class)
38
+ base_rule = graph["Rubydex::Rule"]
39
+ abort("Base rule class is not found. This is an issue in Rubydex itself") unless base_rule.is_a?(Rubydex::Class)
38
40
 
39
41
  rule_declarations = base_rule.descendants.grep(Rubydex::Class) #: as Array[Rubydex::Class]
40
42
  matched_rule_names = rule_declarations.filter_map do |declaration|
41
43
  declaration_name = declaration.name
42
44
  next unless declaration_name
43
- next if declaration_name == BASE_RULE_NAME
45
+ next if declaration_name == "Rubydex::Rule" || declaration_name == "Rubydex::Linter::CustomRule"
44
46
  next unless declaration_name.end_with?(rule_name)
45
47
 
46
48
  declaration
@@ -35,7 +35,7 @@ module Rubydex
35
35
  require "rubydex/linter"
36
36
 
37
37
  custom_rules = load_linter_rules(workspace_path)
38
- warn_unknown_rules(custom_rules)
38
+ warn_unknown_rules
39
39
 
40
40
  graph = build_graph($stderr, workspace_path:, config:)
41
41
  runner = Rubydex::Linter::Runner.new(graph, custom_rules:, config: linter_config)
@@ -64,9 +64,15 @@ module Rubydex
64
64
  @linter_config ||= config.linter #: Rubydex::LinterConfig?
65
65
  end
66
66
 
67
- #: (Array[singleton(Rubydex::Linter::CustomRule)] custom_rule_classes) -> void
68
- def warn_unknown_rules(custom_rule_classes)
69
- known_rule_names = (Rubydex::Rules::ALL + custom_rule_classes).map(&:rule_name).uniq.sort
67
+ #: () -> void
68
+ def warn_unknown_rules
69
+ known_rule_names = (Rule.subclasses + Rubydex::Linter::CustomRule.subclasses).filter_map do |rule|
70
+ name = rule.rule_name
71
+ name unless name == "CustomRule"
72
+ end
73
+ known_rule_names.uniq!
74
+ known_rule_names.sort!
75
+
70
76
  unknown_rule_names = linter_config.rules.keys.reject { |name| known_rule_names.include?(name) }.sort
71
77
  return if unknown_rule_names.empty?
72
78
 
@@ -4,7 +4,7 @@ module Rubydex
4
4
  module Linter
5
5
  # Loads project and bundled-gem rules using the Rubydex linter path convention.
6
6
  class RuleLoader
7
- BUILT_IN_RULE_GLOB = File.expand_path("../../rubydex_linter/rules/**/*.rb", __dir__) #: String
7
+ BUILT_IN_RULE_GLOB = File.expand_path("../../{rubydex_linter,rubydex}/rules/**/*.rb", __dir__) #: String
8
8
  RULE_GLOB = "rubydex_linter/rules/**/*.rb" #: String
9
9
 
10
10
  class << self
@@ -0,0 +1,29 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # Dynamic ancestor references cannot be reasoned about statically because they depend on runtime values. The
9
+ # program may still be valid, but the quality of the analysis degrades. In the case of ancestors, since they
10
+ # influence constant resolution, the degradation may be more impactful than other dynamic references.
11
+ #
12
+ # ```ruby
13
+ # class Foo < var
14
+ # ^^^ Dynamic ancestor reference. This might be correct, but it cannot be understood by the analysis.
15
+ # include SomeClass.method_call
16
+ # ^^^^^^^^^^^^^^^^^^^^^ Dynamic ancestor reference.
17
+ # end
18
+ # ```
19
+ class DynamicAncestor < Rule
20
+ class << self
21
+ # @override
22
+ #: -> singleton(Severity::Base)
23
+ def default_severity
24
+ Severity::Information
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # Dynamic constant references cannot be reasoned about statically because they depend on runtime values. The
9
+ # program may still be valid, but the quality of the analysis degrades.
10
+ #
11
+ # ```ruby
12
+ # var::Foo
13
+ # ^^^^^^^^ Dynamic constant reference. This might be correct, but it cannot be understood by the analysis.
14
+ # ```
15
+ class DynamicConstantReference < Rule
16
+ class << self
17
+ # @override
18
+ #: -> singleton(Severity::Base)
19
+ def default_severity
20
+ Severity::Information
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # Dynamic singleton targets cannot be reasoned about statically because they depend on runtime values. The program
9
+ # may still be valid, but the quality of the analysis degrades.
10
+ #
11
+ # ```ruby
12
+ # class << var
13
+ # ^^^ Dynamic singleton target. This might be correct, but it cannot be understood by the analysis.
14
+ # end
15
+ #
16
+ # def var.bar
17
+ # ^^^ Dynamic singleton target.
18
+ # end
19
+ # ```
20
+ class DynamicSingletonDefinition < Rule
21
+ class << self
22
+ # @override
23
+ #: -> singleton(Severity::Base)
24
+ def default_severity
25
+ Severity::Information
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # Constant visibility operations that depend on dynamic values cannot be reasoned about statically because they
9
+ # depend on runtime values. The program may still be valid, but the quality of the analysis degrades.
10
+ #
11
+ # ```ruby
12
+ # var.private_constant :Foo
13
+ # ^^^ Invalid constant visibility. This might be correct, but it cannot be understood by the analysis.
14
+ #
15
+ # private_constant(var)
16
+ # ^^^ Invalid constant visibility.
17
+ # ```
18
+ class InvalidConstantVisibility < Rule
19
+ class << self
20
+ # @override
21
+ #: -> singleton(Severity::Base)
22
+ def default_severity
23
+ Severity::Warning
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # Method visibility operations that depend on dynamic values cannot be reasoned about statically because they
9
+ # depend on runtime values. The program may still be valid, but the quality of the analysis degrades.
10
+ #
11
+ # ```ruby
12
+ # var.private :foo
13
+ # ^^^ Invalid method visibility. This might be correct, but it cannot be understood by the analysis.
14
+ #
15
+ # private(var)
16
+ # ^^^ Invalid method visibility.
17
+ # ```
18
+ class InvalidMethodVisibility < Rule
19
+ class << self
20
+ # @override
21
+ #: -> singleton(Severity::Base)
22
+ def default_severity
23
+ Severity::Warning
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # A parse error represents invalid Ruby syntax and a program that will fail to execute. For example, a missing
9
+ # `end`, an unterminated string, a missing parenthesis.
10
+ #
11
+ # ```ruby
12
+ # class Foo
13
+ # ^^^^^ Syntax error. Missing end token
14
+ # ```
15
+ class ParseError < Rule
16
+ class << self
17
+ # @override
18
+ #: -> singleton(Severity::Base)
19
+ def default_severity
20
+ Severity::Error
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # Parse warnings represent code that has valid syntax, but may not do what the developer expects. For example,
9
+ # local variables that are completely unused or usage in a void context (creating a line of code that does
10
+ # nothing).
11
+ #
12
+ # ```ruby
13
+ # CONST = 1
14
+ # CONST
15
+ # ^^^^^ Constant used in void context (the expression does nothing).
16
+ # puts CONST + 2
17
+ # ```
18
+ class ParseWarning < Rule
19
+ class << self
20
+ # @override
21
+ #: -> singleton(Severity::Base)
22
+ def default_severity
23
+ Severity::Warning
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # The top level of a Ruby program is the special <main> object. It is not possible to use `include self` or
9
+ # `extend self` on that object.
10
+ #
11
+ # ```ruby
12
+ # include self
13
+ # ^^^^ Cannot include self at the top level
14
+ # extend self
15
+ # ^^^^ Cannot extend self at the top level
16
+ # ```
17
+ class TopLevelMixinSelf < Rule
18
+ class << self
19
+ # @override
20
+ #: -> singleton(Severity::Base)
21
+ def default_severity
22
+ Severity::Information
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
5
+
6
+ module Rubydex
7
+ module Rules
8
+ # Undefined constant visibility target means the analysis couldn't find the definition for the constant the code is
9
+ # attempting to change visibility of. It could be defined through meta-programming or it indeed does not exist.
10
+ #
11
+ # ```ruby
12
+ # class Foo
13
+ # private_constant :Bar
14
+ # ^^^ Undefined constant visibility target. The constant `Bar` is not defined.
15
+ # end
16
+ # ```
17
+ class UndefinedConstantVisibilityTarget < Rule
18
+ class << self
19
+ # @override
20
+ #: -> singleton(Severity::Base)
21
+ def default_severity
22
+ Severity::Warning
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end