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
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
|
-
|
|
179
|
-
class Rubydex::
|
|
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
|
|
895
|
-
|
|
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
|
|
data/rust/Cargo.lock
CHANGED
|
@@ -99,7 +99,7 @@ dependencies = [
|
|
|
99
99
|
"quote",
|
|
100
100
|
"regex",
|
|
101
101
|
"rustc-hash",
|
|
102
|
-
"shlex",
|
|
102
|
+
"shlex 1.3.0",
|
|
103
103
|
"syn",
|
|
104
104
|
]
|
|
105
105
|
|
|
@@ -151,7 +151,7 @@ version = "1.2.30"
|
|
|
151
151
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
152
152
|
checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
|
|
153
153
|
dependencies = [
|
|
154
|
-
"shlex",
|
|
154
|
+
"shlex 1.3.0",
|
|
155
155
|
]
|
|
156
156
|
|
|
157
157
|
[[package]]
|
|
@@ -718,9 +718,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
|
|
718
718
|
|
|
719
719
|
[[package]]
|
|
720
720
|
name = "ruby-prism"
|
|
721
|
-
version = "
|
|
721
|
+
version = "2.0.0-rc.2"
|
|
722
722
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
723
|
-
checksum = "
|
|
723
|
+
checksum = "6d34b0f30ca0b7233a454827204ee7dc1a70d8faa3a26eae95f09ada5386757c"
|
|
724
724
|
dependencies = [
|
|
725
725
|
"ruby-prism-sys",
|
|
726
726
|
"serde",
|
|
@@ -729,12 +729,12 @@ dependencies = [
|
|
|
729
729
|
|
|
730
730
|
[[package]]
|
|
731
731
|
name = "ruby-prism-sys"
|
|
732
|
-
version = "
|
|
732
|
+
version = "2.0.0-rc.2"
|
|
733
733
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
734
|
-
checksum = "
|
|
734
|
+
checksum = "f0e59b94e20c878bb618a355abd00724ad1eb4514341936c6668bea987437a29"
|
|
735
735
|
dependencies = [
|
|
736
|
-
"bindgen",
|
|
737
736
|
"cc",
|
|
737
|
+
"shlex 2.0.1",
|
|
738
738
|
]
|
|
739
739
|
|
|
740
740
|
[[package]]
|
|
@@ -760,7 +760,7 @@ dependencies = [
|
|
|
760
760
|
|
|
761
761
|
[[package]]
|
|
762
762
|
name = "rubydex"
|
|
763
|
-
version = "0.2
|
|
763
|
+
version = "0.4.2"
|
|
764
764
|
dependencies = [
|
|
765
765
|
"assert_cmd",
|
|
766
766
|
"bitflags",
|
|
@@ -789,7 +789,7 @@ dependencies = [
|
|
|
789
789
|
|
|
790
790
|
[[package]]
|
|
791
791
|
name = "rubydex-sys"
|
|
792
|
-
version = "0.2
|
|
792
|
+
version = "0.4.2"
|
|
793
793
|
dependencies = [
|
|
794
794
|
"cbindgen",
|
|
795
795
|
"libc",
|
|
@@ -902,6 +902,12 @@ version = "1.3.0"
|
|
|
902
902
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
903
903
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|
904
904
|
|
|
905
|
+
[[package]]
|
|
906
|
+
name = "shlex"
|
|
907
|
+
version = "2.0.1"
|
|
908
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
909
|
+
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
|
910
|
+
|
|
905
911
|
[[package]]
|
|
906
912
|
name = "smallvec"
|
|
907
913
|
version = "1.15.1"
|
|
@@ -1326,9 +1332,9 @@ checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
|
|
|
1326
1332
|
|
|
1327
1333
|
[[package]]
|
|
1328
1334
|
name = "xxhash-rust"
|
|
1329
|
-
version = "0.8.
|
|
1335
|
+
version = "0.8.16"
|
|
1330
1336
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1331
|
-
checksum = "
|
|
1337
|
+
checksum = "4d93c89cdc2d3a63c3ec48ffe926931bdc069eafa8e4402fe6d8f790c9d1e576"
|
|
1332
1338
|
|
|
1333
1339
|
[[package]]
|
|
1334
1340
|
name = "yoke"
|
data/rust/Cargo.toml
CHANGED
data/rust/rubydex/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "rubydex"
|
|
3
|
-
version =
|
|
3
|
+
version.workspace = true
|
|
4
4
|
edition = "2024"
|
|
5
5
|
rust-version = "1.89.0"
|
|
6
6
|
license = "MIT"
|
|
@@ -15,6 +15,10 @@ categories = ["development-tools"]
|
|
|
15
15
|
name = "rubydex_cli"
|
|
16
16
|
path = "src/main.rs"
|
|
17
17
|
|
|
18
|
+
[[bin]]
|
|
19
|
+
name = "generate_ruby_rules"
|
|
20
|
+
path = "src/bin/generate_ruby_rules.rs"
|
|
21
|
+
|
|
18
22
|
[lib]
|
|
19
23
|
crate-type = ["rlib"]
|
|
20
24
|
|
|
@@ -28,7 +32,7 @@ test_utils = ["dep:tempfile"]
|
|
|
28
32
|
|
|
29
33
|
[dependencies]
|
|
30
34
|
cypher-parser = "0.8.1"
|
|
31
|
-
ruby-prism = "
|
|
35
|
+
ruby-prism = "2.0.0-rc.2"
|
|
32
36
|
ruby-rbs = "0.3"
|
|
33
37
|
url = "2.5.4"
|
|
34
38
|
xxhash-rust = { version = "0.8.15", features = ["xxh3"] }
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
use rubydex::diagnostic::{Rule, Severity};
|
|
2
|
+
use std::collections::HashSet;
|
|
3
|
+
use std::path::Path;
|
|
4
|
+
use std::{env, fs};
|
|
5
|
+
|
|
6
|
+
// Takes the built-in diagnostic rules and generates Ruby classes for them in `lib/rubydex/rules`.
|
|
7
|
+
fn main() {
|
|
8
|
+
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("..").join("..");
|
|
9
|
+
let directory = root.join("lib").join("rubydex").join("rules");
|
|
10
|
+
let mut generated_files = HashSet::new();
|
|
11
|
+
|
|
12
|
+
for rule in Rule::all().iter().copied() {
|
|
13
|
+
write_rule(&directory, rule, &mut generated_files);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Remove stale rules
|
|
17
|
+
for entry in fs::read_dir(&directory).unwrap() {
|
|
18
|
+
let entry = entry.unwrap();
|
|
19
|
+
let path = entry.path();
|
|
20
|
+
|
|
21
|
+
if path.is_file() {
|
|
22
|
+
let file_name = path.file_name().unwrap().to_string_lossy();
|
|
23
|
+
|
|
24
|
+
if !generated_files.contains(&file_name.to_string()) {
|
|
25
|
+
fs::remove_file(path).unwrap();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fn write_rule(dir: &Path, rule: Rule, generated_files: &mut HashSet<String>) {
|
|
32
|
+
let documentation = rule
|
|
33
|
+
.documentation()
|
|
34
|
+
.iter()
|
|
35
|
+
.map(|line| format!(" #{line}").trim_end().to_owned())
|
|
36
|
+
.collect::<Vec<String>>()
|
|
37
|
+
.join("\n");
|
|
38
|
+
|
|
39
|
+
let contents = format!(
|
|
40
|
+
"# typed: strict
|
|
41
|
+
# frozen_string_literal: true
|
|
42
|
+
|
|
43
|
+
# This file is generated by `generate_ruby_rules.rs`. Do not edit this manually.
|
|
44
|
+
|
|
45
|
+
module Rubydex
|
|
46
|
+
module Rules
|
|
47
|
+
{documentation}
|
|
48
|
+
class {name} < Rule
|
|
49
|
+
class << self
|
|
50
|
+
# @override
|
|
51
|
+
#: -> singleton(Severity::Base)
|
|
52
|
+
def default_severity
|
|
53
|
+
{severity}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
",
|
|
60
|
+
name = rule.name(),
|
|
61
|
+
severity = to_ruby_severity(rule.default_severity()),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
let file_name = format!("{}.rb", snake_case(rule.name()));
|
|
65
|
+
fs::write(dir.join(&file_name), contents).unwrap();
|
|
66
|
+
generated_files.insert(file_name);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
fn to_ruby_severity(severity: Severity) -> &'static str {
|
|
70
|
+
match severity {
|
|
71
|
+
Severity::Error => "Severity::Error",
|
|
72
|
+
Severity::Warning => "Severity::Warning",
|
|
73
|
+
Severity::Information => "Severity::Information",
|
|
74
|
+
Severity::Hint => "Severity::Hint",
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
fn snake_case(name: &str) -> String {
|
|
79
|
+
let mut result = String::with_capacity(name.len() + 4);
|
|
80
|
+
|
|
81
|
+
for (index, character) in name.char_indices() {
|
|
82
|
+
if character.is_uppercase() {
|
|
83
|
+
if index != 0 {
|
|
84
|
+
result.push('_');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
result.extend(character.to_lowercase());
|
|
88
|
+
} else {
|
|
89
|
+
result.push(character);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
result
|
|
94
|
+
}
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
macro_rules! assert_mem_size {
|
|
4
4
|
($struct:ident, $size:expr) => {
|
|
5
5
|
// Check struct name on this assert! error
|
|
6
|
+
#[cfg(target_pointer_width = "64")]
|
|
6
7
|
const _: () = assert!(
|
|
7
8
|
std::mem::size_of::<$struct>() == $size,
|
|
8
9
|
concat!("Incorrect size for `", stringify!($struct), "`")
|
|
9
10
|
);
|
|
10
11
|
// Check actual size on this array error
|
|
12
|
+
#[cfg(target_pointer_width = "64")]
|
|
11
13
|
const _: [(); $size] = [(); std::mem::size_of::<$struct>()];
|
|
12
14
|
};
|
|
13
15
|
}
|
data/rust/rubydex/src/config.rs
CHANGED
|
@@ -433,7 +433,7 @@ mod tests {
|
|
|
433
433
|
|
|
434
434
|
let other = rules.iter().find(|rule| rule.name() == "Other").unwrap();
|
|
435
435
|
assert!(!other.enabled());
|
|
436
|
-
|
|
436
|
+
assert_eq!(other.exclude_patterns(), []);
|
|
437
437
|
assert_eq!(other.severity(), None);
|
|
438
438
|
}
|
|
439
439
|
|
|
@@ -64,10 +64,10 @@ pub enum Severity {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
macro_rules! rules {
|
|
67
|
-
($($(#[$
|
|
67
|
+
($($(#[doc = $documentation:literal])+ $rule:ident => $severity:ident),+ $(,)?) => {
|
|
68
68
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
69
69
|
pub enum Rule {
|
|
70
|
-
$($(#[$
|
|
70
|
+
$($(#[doc = $documentation])+ $rule,)+
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
impl Rule {
|
|
@@ -75,60 +75,151 @@ macro_rules! rules {
|
|
|
75
75
|
pub fn all() -> &'static [Self] {
|
|
76
76
|
&[$(Self::$rule,)+]
|
|
77
77
|
}
|
|
78
|
+
|
|
79
|
+
#[must_use]
|
|
80
|
+
pub fn name(&self) -> &'static str {
|
|
81
|
+
match self {
|
|
82
|
+
$(Self::$rule => stringify!($rule),)+
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#[must_use]
|
|
87
|
+
pub fn default_severity(&self) -> Severity {
|
|
88
|
+
match self {
|
|
89
|
+
$(Self::$rule => Severity::$severity,)+
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#[must_use]
|
|
94
|
+
pub fn documentation(&self) -> &'static [&'static str] {
|
|
95
|
+
match self {
|
|
96
|
+
$(Self::$rule => &[$($documentation,)+],)+
|
|
97
|
+
}
|
|
98
|
+
}
|
|
78
99
|
}
|
|
79
100
|
};
|
|
80
101
|
}
|
|
81
102
|
|
|
82
103
|
rules! {
|
|
83
|
-
// Parsing
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
104
|
+
// ******** Parsing ******** //
|
|
105
|
+
|
|
106
|
+
/// A parse error represents invalid Ruby syntax and a program that will fail to execute. For example, a missing
|
|
107
|
+
/// `end`, an unterminated string, a missing parenthesis.
|
|
108
|
+
///
|
|
109
|
+
/// ```ruby
|
|
110
|
+
/// class Foo
|
|
111
|
+
/// ^^^^^ Syntax error. Missing end token
|
|
112
|
+
/// ```
|
|
113
|
+
ParseError => Error,
|
|
114
|
+
|
|
115
|
+
/// Parse warnings represent code that has valid syntax, but may not do what the developer expects. For example,
|
|
116
|
+
/// local variables that are completely unused or usage in a void context (creating a line of code that does
|
|
117
|
+
/// nothing).
|
|
118
|
+
///
|
|
119
|
+
/// ```ruby
|
|
120
|
+
/// CONST = 1
|
|
121
|
+
/// CONST
|
|
122
|
+
/// ^^^^^ Constant used in void context (the expression does nothing).
|
|
123
|
+
/// puts CONST + 2
|
|
124
|
+
/// ```
|
|
125
|
+
ParseWarning => Warning,
|
|
126
|
+
|
|
127
|
+
// ******** Indexing ******** //
|
|
128
|
+
|
|
129
|
+
/// Dynamic constant references cannot be reasoned about statically because they depend on runtime values. The
|
|
130
|
+
/// program may still be valid, but the quality of the analysis degrades.
|
|
131
|
+
///
|
|
132
|
+
/// ```ruby
|
|
133
|
+
/// var::Foo
|
|
134
|
+
/// ^^^^^^^^ Dynamic constant reference. This might be correct, but it cannot be understood by the analysis.
|
|
135
|
+
/// ```
|
|
136
|
+
DynamicConstantReference => Information,
|
|
137
|
+
|
|
138
|
+
/// Dynamic singleton targets cannot be reasoned about statically because they depend on runtime values. The program
|
|
139
|
+
/// may still be valid, but the quality of the analysis degrades.
|
|
140
|
+
///
|
|
141
|
+
/// ```ruby
|
|
142
|
+
/// class << var
|
|
143
|
+
/// ^^^ Dynamic singleton target. This might be correct, but it cannot be understood by the analysis.
|
|
144
|
+
/// end
|
|
145
|
+
///
|
|
146
|
+
/// def var.bar
|
|
147
|
+
/// ^^^ Dynamic singleton target.
|
|
148
|
+
/// end
|
|
149
|
+
/// ```
|
|
150
|
+
DynamicSingletonDefinition => Information,
|
|
151
|
+
|
|
152
|
+
/// Dynamic ancestor references cannot be reasoned about statically because they depend on runtime values. The
|
|
153
|
+
/// program may still be valid, but the quality of the analysis degrades. In the case of ancestors, since they
|
|
154
|
+
/// influence constant resolution, the degradation may be more impactful than other dynamic references.
|
|
155
|
+
///
|
|
156
|
+
/// ```ruby
|
|
157
|
+
/// class Foo < var
|
|
158
|
+
/// ^^^ Dynamic ancestor reference. This might be correct, but it cannot be understood by the analysis.
|
|
159
|
+
/// include SomeClass.method_call
|
|
160
|
+
/// ^^^^^^^^^^^^^^^^^^^^^ Dynamic ancestor reference.
|
|
161
|
+
/// end
|
|
162
|
+
/// ```
|
|
163
|
+
DynamicAncestor => Information,
|
|
164
|
+
|
|
165
|
+
/// The top level of a Ruby program is the special <main> object. It is not possible to use `include self` or
|
|
166
|
+
/// `extend self` on that object.
|
|
167
|
+
///
|
|
168
|
+
/// ```ruby
|
|
169
|
+
/// include self
|
|
170
|
+
/// ^^^^ Cannot include self at the top level
|
|
171
|
+
/// extend self
|
|
172
|
+
/// ^^^^ Cannot extend self at the top level
|
|
173
|
+
/// ```
|
|
174
|
+
TopLevelMixinSelf => Information,
|
|
175
|
+
|
|
176
|
+
/// Constant visibility operations that depend on dynamic values cannot be reasoned about statically because they
|
|
177
|
+
/// depend on runtime values. The program may still be valid, but the quality of the analysis degrades.
|
|
178
|
+
///
|
|
179
|
+
/// ```ruby
|
|
180
|
+
/// var.private_constant :Foo
|
|
181
|
+
/// ^^^ Invalid constant visibility. This might be correct, but it cannot be understood by the analysis.
|
|
182
|
+
///
|
|
183
|
+
/// private_constant(var)
|
|
184
|
+
/// ^^^ Invalid constant visibility.
|
|
185
|
+
/// ```
|
|
186
|
+
InvalidConstantVisibility => Warning,
|
|
187
|
+
|
|
188
|
+
/// Method visibility operations that depend on dynamic values cannot be reasoned about statically because they
|
|
189
|
+
/// depend on runtime values. The program may still be valid, but the quality of the analysis degrades.
|
|
190
|
+
///
|
|
191
|
+
/// ```ruby
|
|
192
|
+
/// var.private :foo
|
|
193
|
+
/// ^^^ Invalid method visibility. This might be correct, but it cannot be understood by the analysis.
|
|
194
|
+
///
|
|
195
|
+
/// private(var)
|
|
196
|
+
/// ^^^ Invalid method visibility.
|
|
197
|
+
/// ```
|
|
198
|
+
InvalidMethodVisibility => Warning,
|
|
199
|
+
|
|
200
|
+
// ******** Resolution ******** //
|
|
201
|
+
|
|
202
|
+
/// Undefined method visibility target means the analysis couldn't find the definition for the method the code is
|
|
203
|
+
/// attempting to change visibility of. It could be defined through meta-programming or it indeed does not exist.
|
|
204
|
+
///
|
|
205
|
+
/// ```ruby
|
|
206
|
+
/// class Foo
|
|
207
|
+
/// private :bar
|
|
208
|
+
/// ^^^ Undefined method visibility target. The method `bar` is not defined.
|
|
209
|
+
/// end
|
|
210
|
+
/// ```
|
|
211
|
+
UndefinedMethodVisibilityTarget => Warning,
|
|
212
|
+
|
|
213
|
+
/// Undefined constant visibility target means the analysis couldn't find the definition for the constant the code is
|
|
214
|
+
/// attempting to change visibility of. It could be defined through meta-programming or it indeed does not exist.
|
|
215
|
+
///
|
|
216
|
+
/// ```ruby
|
|
217
|
+
/// class Foo
|
|
218
|
+
/// private_constant :Bar
|
|
219
|
+
/// ^^^ Undefined constant visibility target. The constant `Bar` is not defined.
|
|
220
|
+
/// end
|
|
221
|
+
/// ```
|
|
222
|
+
UndefinedConstantVisibilityTarget => Warning,
|
|
132
223
|
}
|
|
133
224
|
|
|
134
225
|
impl std::fmt::Display for Rule {
|