rubydex 0.4.0-aarch64-linux → 0.4.2-aarch64-linux
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.
- checksums.yaml +4 -4
- data/README.md +9 -14
- data/THIRD_PARTY_LICENSES.html +13 -24
- data/ext/rubydex/definition.c +34 -0
- data/ext/rubydex/definition.h +3 -0
- data/ext/rubydex/diagnostic.c +2 -49
- data/ext/rubydex/extconf.rb +4 -2
- data/ext/rubydex/graph.c +59 -11
- data/lib/rubydex/3.2/rubydex.so +0 -0
- data/lib/rubydex/3.3/rubydex.so +0 -0
- data/lib/rubydex/3.4/rubydex.so +0 -0
- data/lib/rubydex/4.0/rubydex.so +0 -0
- data/lib/rubydex/cli/command/dead_code.rb +59 -0
- data/lib/rubydex/cli/command/lint/explain.rb +8 -6
- data/lib/rubydex/cli/command/lint.rb +10 -4
- data/lib/rubydex/librubydex_sys.so +0 -0
- data/lib/rubydex/linter/rule_loader.rb +1 -1
- data/lib/rubydex/mcp_server/tools/codebase_stats_tool.rb +1 -1
- data/lib/rubydex/mcp_server/tools/find_constant_references_tool.rb +4 -4
- data/lib/rubydex/mcp_server/tools/find_dead_code_candidates_tool.rb +33 -0
- data/lib/rubydex/mcp_server/tools/get_declaration_tool.rb +2 -2
- data/lib/rubydex/mcp_server/tools/get_descendants_tool.rb +4 -4
- data/lib/rubydex/mcp_server/tools/get_file_declarations_tool.rb +2 -2
- data/lib/rubydex/mcp_server/tools/search_declarations_tool.rb +6 -6
- data/lib/rubydex/mcp_server.rb +24 -12
- data/lib/rubydex/rules/dynamic_ancestor.rb +29 -0
- data/lib/rubydex/rules/dynamic_constant_reference.rb +25 -0
- data/lib/rubydex/rules/dynamic_singleton_definition.rb +30 -0
- data/lib/rubydex/rules/invalid_constant_visibility.rb +28 -0
- data/lib/rubydex/rules/invalid_method_visibility.rb +28 -0
- data/lib/rubydex/rules/parse_error.rb +25 -0
- data/lib/rubydex/rules/parse_warning.rb +28 -0
- data/lib/rubydex/rules/top_level_mixin_self.rb +27 -0
- data/lib/rubydex/rules/undefined_constant_visibility_target.rb +27 -0
- data/lib/rubydex/rules/undefined_method_visibility_target.rb +27 -0
- data/lib/rubydex/skill.rb +1 -0
- data/lib/rubydex/version.rb +1 -1
- data/lib/rubydex.rb +2 -0
- data/lib/rubydex_linter/rules/rule_structure.rb +19 -4
- data/rbi/rubydex.rbi +32 -130
- data/rust/Cargo.lock +17 -11
- data/rust/Cargo.toml +3 -0
- data/rust/rubydex/Cargo.toml +6 -2
- data/rust/rubydex/src/bin/generate_ruby_rules.rs +94 -0
- data/rust/rubydex/src/compile_assertions.rs +2 -0
- data/rust/rubydex/src/config.rs +1 -1
- data/rust/rubydex/src/diagnostic.rs +142 -51
- data/rust/rubydex/src/indexing/rbs_indexer.rs +4 -4
- data/rust/rubydex/src/indexing/ruby_indexer.rs +26 -18
- data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +42 -2
- data/rust/rubydex/src/indexing.rs +6 -6
- data/rust/rubydex/src/listing.rs +12 -12
- data/rust/rubydex/src/model/built_in.rs +1 -1
- data/rust/rubydex/src/model/comment.rs +4 -4
- data/rust/rubydex/src/model/declaration.rs +25 -17
- data/rust/rubydex/src/model/document.rs +11 -11
- data/rust/rubydex/src/model/graph.rs +3 -3
- data/rust/rubydex/src/offset.rs +1 -13
- data/rust/rubydex/src/operation/ruby_builder.rs +29 -19
- data/rust/rubydex/src/query.rs +193 -2
- data/rust/rubydex/src/test_utils/graph_test.rs +2 -2
- data/rust/rubydex/src/test_utils/local_graph_test.rs +13 -6
- data/rust/rubydex-sys/Cargo.toml +2 -2
- data/rust/rubydex-sys/src/definition_api.rs +69 -2
- data/rust/rubydex-sys/src/diagnostic_api.rs +0 -35
- data/rust/rubydex-sys/src/graph_api.rs +193 -45
- data/rust/rubydex-sys/src/name_api.rs +219 -48
- metadata +199 -187
|
@@ -4,12 +4,12 @@ module Rubydex
|
|
|
4
4
|
module MCPServer
|
|
5
5
|
class GetDescendantsTool < BaseTool
|
|
6
6
|
tool_name "get_descendants"
|
|
7
|
-
description "
|
|
7
|
+
description "List a class or module and its known descendants, including transitive descendants."
|
|
8
8
|
input_schema(
|
|
9
9
|
properties: {
|
|
10
|
-
name: { type: "string", description: "Fully qualified
|
|
11
|
-
limit: { type: "integer", description: "
|
|
12
|
-
offset: { type: "integer", description: "Number of
|
|
10
|
+
name: { type: "string", description: "Fully qualified class or module name" },
|
|
11
|
+
limit: { type: "integer", description: "Page size (default 50, capped at 500)" },
|
|
12
|
+
offset: { type: "integer", description: "Number of results to skip (default 0)" },
|
|
13
13
|
},
|
|
14
14
|
required: ["name"],
|
|
15
15
|
)
|
|
@@ -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
|
|
7
|
+
description "List Ruby declarations defined in an indexed file."
|
|
8
8
|
input_schema(
|
|
9
9
|
properties: {
|
|
10
|
-
file_path: { type: "string", description: "
|
|
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
|
|
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: "
|
|
11
|
-
kind: { type: "string", description: "
|
|
12
|
-
match_mode: { type: "string", description: '
|
|
13
|
-
limit: { type: "integer", description: "
|
|
14
|
-
offset: { type: "integer", description: "Number of results to skip
|
|
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
|
)
|
data/lib/rubydex/mcp_server.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
148
|
+
join_or_kill_all(@workers + [@indexer])
|
|
154
149
|
@outgoing_queue.close unless @outgoing_queue.closed?
|
|
155
|
-
@outgoing_dispatcher
|
|
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
data/lib/rubydex/version.rb
CHANGED
data/lib/rubydex.rb
CHANGED
|
@@ -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
|
-
|
|
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|
|