rubydex 0.4.0 → 0.4.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -14
  3. data/THIRD_PARTY_LICENSES.html +13 -24
  4. data/ext/rubydex/definition.c +34 -0
  5. data/ext/rubydex/definition.h +3 -0
  6. data/ext/rubydex/diagnostic.c +2 -49
  7. data/ext/rubydex/extconf.rb +4 -2
  8. data/ext/rubydex/graph.c +59 -11
  9. data/lib/rubydex/cli/command/dead_code.rb +59 -0
  10. data/lib/rubydex/cli/command/lint/explain.rb +8 -6
  11. data/lib/rubydex/cli/command/lint.rb +10 -4
  12. data/lib/rubydex/linter/rule_loader.rb +1 -1
  13. data/lib/rubydex/mcp_server/tools/codebase_stats_tool.rb +1 -1
  14. data/lib/rubydex/mcp_server/tools/find_constant_references_tool.rb +4 -4
  15. data/lib/rubydex/mcp_server/tools/find_dead_code_candidates_tool.rb +33 -0
  16. data/lib/rubydex/mcp_server/tools/get_declaration_tool.rb +2 -2
  17. data/lib/rubydex/mcp_server/tools/get_descendants_tool.rb +4 -4
  18. data/lib/rubydex/mcp_server/tools/get_file_declarations_tool.rb +2 -2
  19. data/lib/rubydex/mcp_server/tools/search_declarations_tool.rb +6 -6
  20. data/lib/rubydex/mcp_server.rb +24 -12
  21. data/lib/rubydex/rules/dynamic_ancestor.rb +29 -0
  22. data/lib/rubydex/rules/dynamic_constant_reference.rb +25 -0
  23. data/lib/rubydex/rules/dynamic_singleton_definition.rb +30 -0
  24. data/lib/rubydex/rules/invalid_constant_visibility.rb +28 -0
  25. data/lib/rubydex/rules/invalid_method_visibility.rb +28 -0
  26. data/lib/rubydex/rules/parse_error.rb +25 -0
  27. data/lib/rubydex/rules/parse_warning.rb +28 -0
  28. data/lib/rubydex/rules/top_level_mixin_self.rb +27 -0
  29. data/lib/rubydex/rules/undefined_constant_visibility_target.rb +27 -0
  30. data/lib/rubydex/rules/undefined_method_visibility_target.rb +27 -0
  31. data/lib/rubydex/skill.rb +1 -0
  32. data/lib/rubydex/version.rb +1 -1
  33. data/lib/rubydex.rb +2 -0
  34. data/lib/rubydex_linter/rules/rule_structure.rb +19 -4
  35. data/rbi/rubydex.rbi +32 -130
  36. data/rust/Cargo.lock +17 -11
  37. data/rust/Cargo.toml +3 -0
  38. data/rust/rubydex/Cargo.toml +6 -2
  39. data/rust/rubydex/src/bin/generate_ruby_rules.rs +94 -0
  40. data/rust/rubydex/src/compile_assertions.rs +2 -0
  41. data/rust/rubydex/src/config.rs +1 -1
  42. data/rust/rubydex/src/diagnostic.rs +142 -51
  43. data/rust/rubydex/src/indexing/rbs_indexer.rs +4 -4
  44. data/rust/rubydex/src/indexing/ruby_indexer.rs +26 -18
  45. data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +42 -2
  46. data/rust/rubydex/src/indexing.rs +6 -6
  47. data/rust/rubydex/src/listing.rs +12 -12
  48. data/rust/rubydex/src/model/built_in.rs +1 -1
  49. data/rust/rubydex/src/model/comment.rs +4 -4
  50. data/rust/rubydex/src/model/declaration.rs +25 -17
  51. data/rust/rubydex/src/model/document.rs +11 -11
  52. data/rust/rubydex/src/model/graph.rs +3 -3
  53. data/rust/rubydex/src/offset.rs +1 -13
  54. data/rust/rubydex/src/operation/ruby_builder.rs +29 -19
  55. data/rust/rubydex/src/query.rs +193 -2
  56. data/rust/rubydex/src/test_utils/graph_test.rs +2 -2
  57. data/rust/rubydex/src/test_utils/local_graph_test.rs +13 -6
  58. data/rust/rubydex-sys/Cargo.toml +2 -2
  59. data/rust/rubydex-sys/src/definition_api.rs +69 -2
  60. data/rust/rubydex-sys/src/diagnostic_api.rs +0 -35
  61. data/rust/rubydex-sys/src/graph_api.rs +193 -45
  62. data/rust/rubydex-sys/src/name_api.rs +219 -48
  63. metadata +191 -180
@@ -4,10 +4,10 @@ module Rubydex
4
4
  module MCPServer
5
5
  class GetFileDeclarationsTool < BaseTool
6
6
  tool_name "get_file_declarations"
7
- description "List all Ruby classes, modules, methods, and constants defined in a specific file. Returns a structural overview with names, kinds, and line numbers. Use this to understand a file's structure before reading it, or to see what a file contributes to the codebase. Accepts relative or absolute paths."
7
+ description "List Ruby declarations defined in an indexed file."
8
8
  input_schema(
9
9
  properties: {
10
- file_path: { type: "string", description: "File path (relative or absolute) to list declarations for" },
10
+ file_path: { type: "string", description: "Absolute path or path relative to the workspace root" },
11
11
  },
12
12
  required: ["file_path"],
13
13
  )
@@ -4,14 +4,14 @@ module Rubydex
4
4
  module MCPServer
5
5
  class SearchDeclarationsTool < BaseTool
6
6
  tool_name "search_declarations"
7
- description 'Search for Ruby classes, modules, methods, or constants by name. Use this INSTEAD OF Grep when you know part of a Ruby identifier name and want to find its definition. Returns fully qualified names, kinds, and file locations. Use the `kind` filter ("Class", "Module", "Method", "Constant") to narrow results. Set `match_mode` to "exact" for precise substring matching or "fuzzy" for LSP-style workspace symbol search (default). Results are paginated: the response includes `total` (the full count of matches). If `total` exceeds the number of returned results, use `offset` to fetch subsequent pages.'
7
+ description "Find definitions of Ruby classes, modules, methods, or constants by full or partial name."
8
8
  input_schema(
9
9
  properties: {
10
- query: { type: "string", description: "Search query to match against declaration names" },
11
- kind: { type: "string", description: "Filter by declaration kind: Class, Module, Method, Constant, etc." },
12
- match_mode: { type: "string", description: 'Matching mode: "fuzzy" (default) for LSP-style workspace symbol search, or "exact" for precise substring matching' },
13
- limit: { type: "integer", description: "Maximum number of results to return (default 50, max 100)" },
14
- offset: { type: "integer", description: "Number of results to skip for pagination (default 0)" },
10
+ query: { type: "string", description: "Text to match against fully qualified names. An empty string matches all declarations." },
11
+ kind: { type: "string", description: "Case-insensitive declaration kind, such as Class, Module, Method, or Constant" },
12
+ match_mode: { type: "string", description: '"fuzzy" (default) matches characters in order, ignoring ASCII case. "exact" matches a case-sensitive substring.' },
13
+ limit: { type: "integer", description: "Page size (default 50, capped at 100)" },
14
+ offset: { type: "integer", description: "Number of results to skip (default 0)" },
15
15
  },
16
16
  required: ["query"],
17
17
  )
@@ -10,19 +10,13 @@ Dir[File.join(__dir__, "mcp_server", "tools", "*_tool.rb")].sort.each { |file| r
10
10
  module Rubydex
11
11
  module MCPServer
12
12
  SERVER_INSTRUCTIONS = <<~TEXT
13
- Rubydex provides semantic Ruby code intelligence.
14
-
15
- Use these tools for Ruby source files (.rb, .rbi, .rbs) when you need structural information about declarations, locations, hierarchy, references, or codebase composition.
16
-
17
- Use text search instead for literal strings, comments, log messages, non-Ruby files, or content search rather than structural queries.
18
-
19
- Fully qualified name format: "Foo::Bar" for classes/modules/constants, "Foo::Bar#method_name" for instance methods.
20
-
21
- Pagination: tools that may return a high number of results include `total` for pagination. When `total` exceeds the number of returned items, use `offset` to fetch the next page.
13
+ Tools query a static index of workspace code, available bundle dependencies, and available Ruby core and standard-library RBS definitions.
14
+ The index is built at server startup and does not track file changes; restart the server to refresh it.
22
15
  TEXT
23
16
 
24
17
  class Server
25
18
  WORKER_COUNT = 4
19
+ SHUTDOWN_JOIN_TIMEOUT = 2
26
20
 
27
21
  #: (root_path: String, ?transport: StdioTransport) -> void
28
22
  def initialize(root_path:, transport: nil)
@@ -34,13 +28,14 @@ module Rubydex
34
28
  @outgoing_queue = Thread::Queue.new
35
29
  @workers = []
36
30
  @outgoing_dispatcher = nil
31
+ @indexer = nil
37
32
  end
38
33
 
39
34
  attr_reader :root_path
40
35
 
41
36
  #: -> Thread
42
37
  def spawn_indexer
43
- Thread.new do
38
+ @indexer = Thread.new do
44
39
  @graph.index_workspace
45
40
  @graph.resolve
46
41
  @index_finished = true
@@ -150,9 +145,26 @@ module Rubydex
150
145
  #: -> void
151
146
  def run_shutdown
152
147
  @incoming_queue.close unless @incoming_queue.closed?
153
- @workers.each(&:join)
148
+ join_or_kill_all(@workers + [@indexer])
154
149
  @outgoing_queue.close unless @outgoing_queue.closed?
155
- @outgoing_dispatcher&.join
150
+ join_or_kill_all([@outgoing_dispatcher])
151
+ end
152
+
153
+ #: (Array[Thread?]) -> void
154
+ def join_or_kill_all(threads)
155
+ live_threads = threads.compact.select(&:alive?)
156
+ return if live_threads.empty?
157
+
158
+ deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + SHUTDOWN_JOIN_TIMEOUT
159
+ live_threads.each do |thread|
160
+ remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
161
+ break if remaining <= 0
162
+
163
+ thread.join(remaining)
164
+ end
165
+
166
+ live_threads.select(&:alive?).each(&:kill)
167
+ live_threads.select(&:alive?).each(&:join)
156
168
  end
157
169
 
158
170
  #: -> Thread
@@ -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
@@ -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 method visibility target means the analysis couldn't find the definition for the method 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 :bar
14
+ # ^^^ Undefined method visibility target. The method `bar` is not defined.
15
+ # end
16
+ # ```
17
+ class UndefinedMethodVisibilityTarget < 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
data/lib/rubydex/skill.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "yaml"
3
4
  require "rubydex/errors"
4
5
 
5
6
  module Rubydex
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubydex
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.2"
5
5
  end
data/lib/rubydex.rb CHANGED
@@ -31,3 +31,5 @@ require "rubydex/graph"
31
31
  require "rubydex/declaration"
32
32
  require "rubydex/signature"
33
33
  require "rubydex/reference"
34
+
35
+ Dir.glob("#{__dir__}/rubydex/rules/**/*.rb").each { |file| require file }
@@ -9,7 +9,8 @@ module Rubydex
9
9
  # - Each rule subclass outside a test directory is in a rule directory.
10
10
  # - Each checked rule subclass is in the `Rubydex::Linter::Rules` namespace.
11
11
  #
12
- # The rule directories are `rubydex_linter/rules/` and `lib/rubydex_linter/rules/`.
12
+ # The rule directories are `rubydex_linter/rules/` and `lib/rubydex_linter/rules/`, including
13
+ # `lib/rubydex_linter/rules/` directories in nested gems.
13
14
  # This rule does not report files in those directories that define no rule subclass.
14
15
  class RuleStructure < CustomRule
15
16
  include Helpers::SourceAccessHelpers
@@ -18,7 +19,7 @@ module Rubydex
18
19
  RULE_NAMESPACE = "Rubydex::Linter::Rules" #: String
19
20
  RULE_FILE_PATTERNS = [
20
21
  "rubydex_linter/rules/**/*.rb",
21
- "lib/rubydex_linter/rules/**/*.rb",
22
+ "**/lib/rubydex_linter/rules/**/*.rb",
22
23
  ].freeze #: Array[String]
23
24
  TEST_FILE_PATTERNS = ["test/**/*", "**/test/**/*"].freeze #: Array[String]
24
25
 
@@ -37,6 +38,8 @@ module Rubydex
37
38
  rule_definitions_by_file = {} #: Hash[String, Hash[Rubydex::Class, Definition]]
38
39
 
39
40
  rules.each do |rule|
41
+ rule_docs = []
42
+
40
43
  rule.definitions.each do |rule_definition|
41
44
  uri = rule_definition.document.uri
42
45
  path = path_for_uri(uri)
@@ -48,6 +51,8 @@ module Rubydex
48
51
  elsif !test_file?(path)
49
52
  report_wrong_rule_directory(rule.name, rule_definition)
50
53
  end
54
+
55
+ rule_docs.concat(rule_definition.comments)
51
56
  end
52
57
 
53
58
  rule_definition = rule.definitions.find do |definition|
@@ -55,9 +60,19 @@ module Rubydex
55
60
  path_in_workspace?(path) && (rule_file?(path) || !test_file?(path))
56
61
  end
57
62
  next unless rule_definition
58
- next if rule.name.start_with?("#{RULE_NAMESPACE}::")
59
63
 
60
- report_wrong_rule_namespace(rule.name, rule_definition)
64
+ rule_name = rule.name
65
+
66
+ if rule_docs.empty?
67
+ add_diagnostic(
68
+ "`#{rule_name}` is missing documentation.",
69
+ diagnostic_location(rule_definition),
70
+ )
71
+ end
72
+
73
+ next if rule_name.start_with?("#{RULE_NAMESPACE}::")
74
+
75
+ report_wrong_rule_namespace(rule_name, rule_definition)
61
76
  end
62
77
 
63
78
  rule_definitions_by_file.each do |uri, rule_definitions|
data/rbi/rubydex.rbi CHANGED
@@ -175,8 +175,17 @@ class Rubydex::AttrAccessorDefinition < Rubydex::Definition; end
175
175
  class Rubydex::AttrReaderDefinition < Rubydex::Definition; end
176
176
  class Rubydex::AttrWriterDefinition < Rubydex::Definition; end
177
177
  class Rubydex::ClassVariableDefinition < Rubydex::Definition; end
178
- class Rubydex::ConstantAliasDefinition < Rubydex::Definition; end
179
- class Rubydex::ConstantDefinition < Rubydex::Definition; end
178
+
179
+ class Rubydex::ConstantAliasDefinition < Rubydex::Definition
180
+ sig { returns(String) }
181
+ def raw_name; end
182
+ end
183
+
184
+ class Rubydex::ConstantDefinition < Rubydex::Definition
185
+ sig { returns(String) }
186
+ def raw_name; end
187
+ end
188
+
180
189
  class Rubydex::GlobalVariableAliasDefinition < Rubydex::Definition; end
181
190
  class Rubydex::GlobalVariableDefinition < Rubydex::Definition; end
182
191
  class Rubydex::InstanceVariableDefinition < Rubydex::Definition; end
@@ -271,6 +280,9 @@ class Rubydex::Signature::BlockParameter < Rubydex::Signature::Parameter; end
271
280
  class Rubydex::ModuleDefinition < Rubydex::Definition
272
281
  sig { returns(T::Array[Rubydex::Mixin]) }
273
282
  def mixins; end
283
+
284
+ sig { returns(String) }
285
+ def raw_name; end
274
286
  end
275
287
 
276
288
  class Rubydex::SingletonClassDefinition < Rubydex::Definition
@@ -284,6 +296,9 @@ class Rubydex::ClassDefinition < Rubydex::Definition
284
296
 
285
297
  sig { returns(T::Array[Rubydex::Mixin]) }
286
298
  def mixins; end
299
+
300
+ sig { returns(String) }
301
+ def raw_name; end
287
302
  end
288
303
 
289
304
  class Rubydex::Mixin
@@ -337,80 +352,6 @@ class Rubydex::Rule
337
352
  end
338
353
  end
339
354
 
340
- module Rubydex::Rules
341
- ALL = T.let(T.unsafe(nil), T::Array[T.class_of(Rubydex::Rule)])
342
- end
343
-
344
- class Rubydex::Rules::ParseError < Rubydex::Rule
345
- class << self
346
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
347
- def default_severity; end
348
- end
349
- end
350
-
351
- class Rubydex::Rules::ParseWarning < Rubydex::Rule
352
- class << self
353
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
354
- def default_severity; end
355
- end
356
- end
357
-
358
- class Rubydex::Rules::DynamicConstantReference < Rubydex::Rule
359
- class << self
360
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
361
- def default_severity; end
362
- end
363
- end
364
-
365
- class Rubydex::Rules::DynamicSingletonDefinition < Rubydex::Rule
366
- class << self
367
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
368
- def default_severity; end
369
- end
370
- end
371
-
372
- class Rubydex::Rules::DynamicAncestor < Rubydex::Rule
373
- class << self
374
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
375
- def default_severity; end
376
- end
377
- end
378
-
379
- class Rubydex::Rules::TopLevelMixinSelf < Rubydex::Rule
380
- class << self
381
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
382
- def default_severity; end
383
- end
384
- end
385
-
386
- class Rubydex::Rules::InvalidConstantVisibility < Rubydex::Rule
387
- class << self
388
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
389
- def default_severity; end
390
- end
391
- end
392
-
393
- class Rubydex::Rules::InvalidMethodVisibility < Rubydex::Rule
394
- class << self
395
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
396
- def default_severity; end
397
- end
398
- end
399
-
400
- class Rubydex::Rules::UndefinedMethodVisibilityTarget < Rubydex::Rule
401
- class << self
402
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
403
- def default_severity; end
404
- end
405
- end
406
-
407
- class Rubydex::Rules::UndefinedConstantVisibilityTarget < Rubydex::Rule
408
- class << self
409
- sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
410
- def default_severity; end
411
- end
412
- end
413
-
414
355
  class Rubydex::RelatedInformation
415
356
  sig { params(message: String, location: Rubydex::Location).void }
416
357
  def initialize(message, location); end
@@ -594,58 +535,6 @@ class Rubydex::Linter::Rules::RuleStructure < Rubydex::Linter::CustomRule
594
535
  def lint; end
595
536
  end
596
537
 
597
- class Rubydex::Linter::RuleTestCase < Minitest::Test
598
- DEFAULT_FILE = T.let(T.unsafe(nil), String)
599
- ANNOTATION_PATTERN = T.let(T.unsafe(nil), Regexp)
600
-
601
- sig { returns(String) }
602
- def workspace_path; end
603
-
604
- sig { params(name: String).void }
605
- def initialize(name); end
606
-
607
- sig { void }
608
- def teardown; end
609
-
610
- sig { returns(T.class_of(Rubydex::Linter::CustomRule)) }
611
- def rule_class; end
612
-
613
- sig { params(sources: T::Hash[String, String]).void }
614
- def add_shared_source(sources); end
615
-
616
- sig { returns(T::Array[String]) }
617
- def ignored_diagnostic_files; end
618
-
619
- sig { returns(Rubydex::LinterConfig) }
620
- def rule_config; end
621
-
622
- sig do
623
- params(
624
- args: T.any(String, T::Hash[T.any(String, Symbol), String]),
625
- rule_builder: T.nilable(T.proc.params(graph: Rubydex::Graph).returns(Rubydex::Linter::CustomRule)),
626
- ).returns(T::Array[Rubydex::Diagnostic])
627
- end
628
- def assert_diagnostics(*args, &rule_builder); end
629
-
630
- sig do
631
- params(
632
- args: T.any(String, T::Hash[T.any(String, Symbol), String]),
633
- rule_builder: T.nilable(T.proc.params(graph: Rubydex::Graph).returns(Rubydex::Linter::CustomRule)),
634
- ).returns(T::Array[Rubydex::Diagnostic])
635
- end
636
- def assert_no_diagnostics(*args, &rule_builder); end
637
-
638
- sig do
639
- params(
640
- dependency: String,
641
- args: T.any(String, T::Hash[T.any(String, Symbol), String]),
642
- after_excluding: T::Array[String],
643
- rule_builder: T.nilable(T.proc.params(graph: Rubydex::Graph).returns(Rubydex::Linter::CustomRule)),
644
- ).void
645
- end
646
- def assert_handles_missing_required_dependency(dependency, *args, after_excluding: [], &rule_builder); end
647
- end
648
-
649
538
  class Rubydex::Linter::Runner
650
539
  sig do
651
540
  params(
@@ -891,8 +780,18 @@ class Rubydex::Graph
891
780
  sig { returns(T.self_type) }
892
781
  def resolve; end
893
782
 
894
- sig { params(name: String, nesting: T::Array[String]).returns(T.nilable(Rubydex::Declaration)) }
895
- def resolve_constant(name, nesting); end
783
+ sig do
784
+ params(
785
+ name: String,
786
+ context: T.any(
787
+ T::Array[String],
788
+ Rubydex::ClassDefinition,
789
+ Rubydex::SingletonClassDefinition,
790
+ Rubydex::ModuleDefinition,
791
+ ),
792
+ ).returns(T.nilable(Rubydex::Declaration))
793
+ end
794
+ def resolve_constant(name, context); end
896
795
 
897
796
  sig { params(require_path: String, load_paths: T::Array[String]).returns(T.nilable(Rubydex::Document)) }
898
797
  def resolve_require_path(require_path, load_paths); end
@@ -903,6 +802,9 @@ class Rubydex::Graph
903
802
  sig { params(queries: String).returns(T::Enumerable[Rubydex::Declaration]) }
904
803
  def fuzzy_search(*queries); end
905
804
 
805
+ sig { returns(T::Enumerable[Rubydex::Declaration]) }
806
+ def dead_code_candidates; end
807
+
906
808
  sig { params(encoding: String).void }
907
809
  def encoding=(encoding); end
908
810