rubydex 0.1.0.beta11 → 0.1.0.beta13

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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +23 -23
  3. data/README.md +125 -125
  4. data/THIRD_PARTY_LICENSES.html +2018 -945
  5. data/exe/rdx +47 -47
  6. data/ext/rubydex/declaration.c +453 -388
  7. data/ext/rubydex/declaration.h +23 -23
  8. data/ext/rubydex/definition.c +284 -197
  9. data/ext/rubydex/definition.h +28 -28
  10. data/ext/rubydex/diagnostic.c +6 -6
  11. data/ext/rubydex/diagnostic.h +11 -11
  12. data/ext/rubydex/document.c +97 -98
  13. data/ext/rubydex/document.h +10 -10
  14. data/ext/rubydex/extconf.rb +146 -127
  15. data/ext/rubydex/graph.c +701 -512
  16. data/ext/rubydex/graph.h +10 -10
  17. data/ext/rubydex/handle.h +44 -44
  18. data/ext/rubydex/location.c +22 -22
  19. data/ext/rubydex/location.h +15 -15
  20. data/ext/rubydex/reference.c +123 -104
  21. data/ext/rubydex/reference.h +15 -16
  22. data/ext/rubydex/rubydex.c +22 -22
  23. data/ext/rubydex/utils.c +108 -86
  24. data/ext/rubydex/utils.h +34 -28
  25. data/lib/rubydex/comment.rb +17 -17
  26. data/lib/rubydex/declaration.rb +11 -0
  27. data/lib/rubydex/diagnostic.rb +21 -21
  28. data/lib/rubydex/failures.rb +15 -15
  29. data/lib/rubydex/graph.rb +98 -92
  30. data/lib/rubydex/keyword.rb +17 -0
  31. data/lib/rubydex/keyword_parameter.rb +13 -0
  32. data/lib/rubydex/location.rb +90 -90
  33. data/lib/rubydex/mixin.rb +22 -0
  34. data/lib/rubydex/version.rb +5 -5
  35. data/lib/rubydex.rb +24 -20
  36. data/rbi/rubydex.rbi +425 -310
  37. data/rust/Cargo.lock +1851 -1851
  38. data/rust/Cargo.toml +29 -29
  39. data/rust/about.toml +10 -10
  40. data/rust/{about.hbs → about_templates/about.hbs} +81 -78
  41. data/rust/about_templates/mingw_licenses.hbs +1071 -0
  42. data/rust/rubydex/Cargo.toml +42 -42
  43. data/rust/rubydex/src/compile_assertions.rs +13 -13
  44. data/rust/rubydex/src/diagnostic.rs +110 -109
  45. data/rust/rubydex/src/errors.rs +28 -28
  46. data/rust/rubydex/src/indexing/local_graph.rs +224 -224
  47. data/rust/rubydex/src/indexing/rbs_indexer.rs +1551 -1554
  48. data/rust/rubydex/src/indexing/ruby_indexer.rs +2329 -6753
  49. data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +4962 -0
  50. data/rust/rubydex/src/indexing.rs +210 -210
  51. data/rust/rubydex/src/integrity.rs +279 -278
  52. data/rust/rubydex/src/job_queue.rs +199 -205
  53. data/rust/rubydex/src/lib.rs +17 -17
  54. data/rust/rubydex/src/listing.rs +371 -272
  55. data/rust/rubydex/src/main.rs +160 -160
  56. data/rust/rubydex/src/model/built_in.rs +83 -0
  57. data/rust/rubydex/src/model/comment.rs +24 -24
  58. data/rust/rubydex/src/model/declaration.rs +679 -588
  59. data/rust/rubydex/src/model/definitions.rs +1682 -1602
  60. data/rust/rubydex/src/model/document.rs +222 -252
  61. data/rust/rubydex/src/model/encoding.rs +22 -22
  62. data/rust/rubydex/src/model/graph.rs +3782 -3556
  63. data/rust/rubydex/src/model/id.rs +110 -110
  64. data/rust/rubydex/src/model/identity_maps.rs +58 -58
  65. data/rust/rubydex/src/model/ids.rs +60 -38
  66. data/rust/rubydex/src/model/keywords.rs +256 -256
  67. data/rust/rubydex/src/model/name.rs +298 -298
  68. data/rust/rubydex/src/model/references.rs +111 -111
  69. data/rust/rubydex/src/model/string_ref.rs +50 -50
  70. data/rust/rubydex/src/model/visibility.rs +41 -41
  71. data/rust/rubydex/src/model.rs +15 -14
  72. data/rust/rubydex/src/offset.rs +147 -147
  73. data/rust/rubydex/src/position.rs +6 -6
  74. data/rust/rubydex/src/query.rs +1841 -1700
  75. data/rust/rubydex/src/resolution.rs +1852 -5895
  76. data/rust/rubydex/src/resolution_tests.rs +4701 -0
  77. data/rust/rubydex/src/stats/memory.rs +71 -71
  78. data/rust/rubydex/src/stats/orphan_report.rs +264 -263
  79. data/rust/rubydex/src/stats/timer.rs +127 -127
  80. data/rust/rubydex/src/stats.rs +11 -11
  81. data/rust/rubydex/src/test_utils/context.rs +226 -226
  82. data/rust/rubydex/src/test_utils/graph_test.rs +730 -679
  83. data/rust/rubydex/src/test_utils/local_graph_test.rs +602 -602
  84. data/rust/rubydex/src/test_utils.rs +52 -52
  85. data/rust/rubydex/src/visualization/dot.rs +192 -176
  86. data/rust/rubydex/src/visualization.rs +6 -6
  87. data/rust/rubydex/tests/cli.rs +185 -167
  88. data/rust/rubydex-mcp/Cargo.toml +28 -28
  89. data/rust/rubydex-mcp/src/main.rs +48 -48
  90. data/rust/rubydex-mcp/src/server.rs +1145 -1145
  91. data/rust/rubydex-mcp/src/tools.rs +49 -49
  92. data/rust/rubydex-mcp/tests/mcp.rs +302 -302
  93. data/rust/rubydex-sys/Cargo.toml +20 -20
  94. data/rust/rubydex-sys/build.rs +14 -14
  95. data/rust/rubydex-sys/cbindgen.toml +12 -12
  96. data/rust/rubydex-sys/src/declaration_api.rs +485 -469
  97. data/rust/rubydex-sys/src/definition_api.rs +443 -352
  98. data/rust/rubydex-sys/src/diagnostic_api.rs +99 -99
  99. data/rust/rubydex-sys/src/document_api.rs +85 -54
  100. data/rust/rubydex-sys/src/graph_api.rs +1017 -700
  101. data/rust/rubydex-sys/src/lib.rs +79 -9
  102. data/rust/rubydex-sys/src/location_api.rs +79 -79
  103. data/rust/rubydex-sys/src/name_api.rs +187 -135
  104. data/rust/rubydex-sys/src/reference_api.rs +267 -195
  105. data/rust/rubydex-sys/src/utils.rs +70 -70
  106. data/rust/rustfmt.toml +2 -2
  107. metadata +16 -9
  108. data/lib/rubydex/librubydex_sys.so +0 -0
@@ -1,160 +1,160 @@
1
- use clap::{Parser, ValueEnum};
2
- use std::mem;
3
-
4
- use rubydex::{
5
- indexing, integrity, listing,
6
- model::graph::Graph,
7
- resolution::Resolver,
8
- stats::{
9
- memory::MemoryStats,
10
- timer::{Timer, time_it},
11
- },
12
- visualization::dot,
13
- };
14
-
15
- #[derive(Parser, Debug)]
16
- #[command(name = "rubydex_cli", about = "A Static Analysis Toolkit for Ruby", version)]
17
- #[allow(clippy::struct_excessive_bools)]
18
- struct Args {
19
- #[arg(value_name = "PATHS", default_value = ".")]
20
- paths: Vec<String>,
21
-
22
- #[arg(long = "stop-after", help = "Stop after the given stage")]
23
- stop_after: Option<StopAfter>,
24
-
25
- #[arg(long = "visualize")]
26
- visualize: bool,
27
-
28
- #[arg(long = "stats", help = "Show detailed performance statistics")]
29
- stats: bool,
30
-
31
- #[arg(long = "check-integrity", help = "Check the integrity of the graph after resolution")]
32
- check_integrity: bool,
33
-
34
- #[arg(
35
- long = "report-orphans",
36
- value_name = "PATH",
37
- num_args = 0..=1,
38
- require_equals = true,
39
- default_missing_value = "/tmp/rubydex-orphan-report.txt",
40
- help = "Write orphan definitions report to specified file"
41
- )]
42
- report_orphans: Option<String>,
43
- }
44
-
45
- #[derive(Debug, Clone, ValueEnum)]
46
- enum StopAfter {
47
- Listing,
48
- Indexing,
49
- Resolution,
50
- }
51
-
52
- fn exit(print_stats: bool) {
53
- if print_stats {
54
- Timer::print_breakdown();
55
- MemoryStats::print_memory_usage();
56
- }
57
-
58
- std::process::exit(0);
59
- }
60
-
61
- fn main() {
62
- let args = Args::parse();
63
-
64
- if args.stats {
65
- Timer::set_global_timer(Timer::new());
66
- }
67
-
68
- // Listing
69
-
70
- let (file_paths, errors) = time_it!(listing, { listing::collect_file_paths(args.paths) });
71
-
72
- for error in errors {
73
- eprintln!("{error}");
74
- }
75
-
76
- if let Some(StopAfter::Listing) = args.stop_after {
77
- return exit(args.stats);
78
- }
79
-
80
- // Indexing
81
-
82
- let mut graph = Graph::new();
83
- let errors = time_it!(indexing, { indexing::index_files(&mut graph, file_paths) });
84
-
85
- for error in errors {
86
- eprintln!("{error}");
87
- }
88
-
89
- if let Some(StopAfter::Indexing) = args.stop_after {
90
- return exit(args.stats);
91
- }
92
-
93
- // Resolution
94
-
95
- time_it!(resolution, {
96
- let mut resolver = Resolver::new(&mut graph);
97
- resolver.resolve();
98
- });
99
-
100
- if let Some(StopAfter::Resolution) = args.stop_after {
101
- return exit(args.stats);
102
- }
103
-
104
- // Integrity check
105
- if args.check_integrity {
106
- let errors = time_it!(integrity_check, { integrity::check_integrity(&graph) });
107
-
108
- if errors.is_empty() {
109
- println!("Integrity check passed: no issues found");
110
- } else {
111
- eprintln!("Integrity check found {} issue(s):", errors.len());
112
-
113
- for error in &errors {
114
- eprintln!(" - {error}");
115
- }
116
-
117
- std::process::exit(1);
118
- }
119
- }
120
-
121
- // Querying
122
-
123
- if args.stats {
124
- time_it!(querying, {
125
- graph.print_query_statistics();
126
- });
127
- }
128
-
129
- if args.stats {
130
- Timer::print_breakdown();
131
- MemoryStats::print_memory_usage();
132
- }
133
-
134
- // Orphan report
135
- if let Some(ref path) = args.report_orphans {
136
- match std::fs::File::create(path) {
137
- Ok(mut file) => {
138
- if let Err(e) = graph.write_orphan_report(&mut file) {
139
- eprintln!("Failed to write orphan report: {e}");
140
- } else {
141
- println!("Orphan report written to {path}");
142
- }
143
- }
144
- Err(e) => eprintln!("Failed to create orphan report file: {e}"),
145
- }
146
- }
147
-
148
- // Generate visualization or print statistics
149
- if args.visualize {
150
- println!("{}", dot::generate(&graph));
151
- } else {
152
- println!("Indexed {} files", graph.documents().len());
153
- println!("Found {} names", graph.declarations().len());
154
- println!("Found {} definitions", graph.definitions().len());
155
- println!("Found {} URIs", graph.documents().len());
156
- }
157
-
158
- // Forget the graph so we don't have to wait for deallocation and let the system reclaim the memory at exit
159
- mem::forget(graph);
160
- }
1
+ use clap::{Parser, ValueEnum};
2
+ use std::{collections::HashSet, mem};
3
+
4
+ use rubydex::{
5
+ indexing, integrity, listing,
6
+ model::graph::Graph,
7
+ resolution::Resolver,
8
+ stats::{
9
+ memory::MemoryStats,
10
+ timer::{Timer, time_it},
11
+ },
12
+ visualization::dot,
13
+ };
14
+
15
+ #[derive(Parser, Debug)]
16
+ #[command(name = "rubydex_cli", about = "A Static Analysis Toolkit for Ruby", version)]
17
+ #[allow(clippy::struct_excessive_bools)]
18
+ struct Args {
19
+ #[arg(value_name = "PATHS", default_value = ".")]
20
+ paths: Vec<String>,
21
+
22
+ #[arg(long = "stop-after", help = "Stop after the given stage")]
23
+ stop_after: Option<StopAfter>,
24
+
25
+ #[arg(long = "visualize")]
26
+ visualize: bool,
27
+
28
+ #[arg(long = "stats", help = "Show detailed performance statistics")]
29
+ stats: bool,
30
+
31
+ #[arg(long = "check-integrity", help = "Check the integrity of the graph after resolution")]
32
+ check_integrity: bool,
33
+
34
+ #[arg(
35
+ long = "report-orphans",
36
+ value_name = "PATH",
37
+ num_args = 0..=1,
38
+ require_equals = true,
39
+ default_missing_value = "/tmp/rubydex-orphan-report.txt",
40
+ help = "Write orphan definitions report to specified file"
41
+ )]
42
+ report_orphans: Option<String>,
43
+ }
44
+
45
+ #[derive(Debug, Clone, ValueEnum)]
46
+ enum StopAfter {
47
+ Listing,
48
+ Indexing,
49
+ Resolution,
50
+ }
51
+
52
+ fn exit(print_stats: bool) {
53
+ if print_stats {
54
+ Timer::print_breakdown();
55
+ MemoryStats::print_memory_usage();
56
+ }
57
+
58
+ std::process::exit(0);
59
+ }
60
+
61
+ fn main() {
62
+ let args = Args::parse();
63
+
64
+ if args.stats {
65
+ Timer::set_global_timer(Timer::new());
66
+ }
67
+
68
+ // Listing
69
+
70
+ let (file_paths, errors) = time_it!(listing, { listing::collect_file_paths(args.paths, &HashSet::new()) });
71
+
72
+ for error in errors {
73
+ eprintln!("{error}");
74
+ }
75
+
76
+ if let Some(StopAfter::Listing) = args.stop_after {
77
+ return exit(args.stats);
78
+ }
79
+
80
+ // Indexing
81
+
82
+ let mut graph = Graph::new();
83
+ let errors = time_it!(indexing, { indexing::index_files(&mut graph, file_paths) });
84
+
85
+ for error in errors {
86
+ eprintln!("{error}");
87
+ }
88
+
89
+ if let Some(StopAfter::Indexing) = args.stop_after {
90
+ return exit(args.stats);
91
+ }
92
+
93
+ // Resolution
94
+
95
+ time_it!(resolution, {
96
+ let mut resolver = Resolver::new(&mut graph);
97
+ resolver.resolve();
98
+ });
99
+
100
+ if let Some(StopAfter::Resolution) = args.stop_after {
101
+ return exit(args.stats);
102
+ }
103
+
104
+ // Integrity check
105
+ if args.check_integrity {
106
+ let errors = time_it!(integrity_check, { integrity::check_integrity(&graph) });
107
+
108
+ if errors.is_empty() {
109
+ println!("Integrity check passed: no issues found");
110
+ } else {
111
+ eprintln!("Integrity check found {} issue(s):", errors.len());
112
+
113
+ for error in &errors {
114
+ eprintln!(" - {error}");
115
+ }
116
+
117
+ std::process::exit(1);
118
+ }
119
+ }
120
+
121
+ // Querying
122
+
123
+ if args.stats {
124
+ time_it!(querying, {
125
+ graph.print_query_statistics();
126
+ });
127
+ }
128
+
129
+ if args.stats {
130
+ Timer::print_breakdown();
131
+ MemoryStats::print_memory_usage();
132
+ }
133
+
134
+ // Orphan report
135
+ if let Some(ref path) = args.report_orphans {
136
+ match std::fs::File::create(path) {
137
+ Ok(mut file) => {
138
+ if let Err(e) = graph.write_orphan_report(&mut file) {
139
+ eprintln!("Failed to write orphan report: {e}");
140
+ } else {
141
+ println!("Orphan report written to {path}");
142
+ }
143
+ }
144
+ Err(e) => eprintln!("Failed to create orphan report file: {e}"),
145
+ }
146
+ }
147
+
148
+ // Generate visualization or print statistics
149
+ if args.visualize {
150
+ println!("{}", dot::generate(&graph));
151
+ } else {
152
+ println!("Indexed {} files", graph.documents().len());
153
+ println!("Found {} names", graph.declarations().len());
154
+ println!("Found {} definitions", graph.definitions().len());
155
+ println!("Found {} URIs", graph.documents().len());
156
+ }
157
+
158
+ // Forget the graph so we don't have to wait for deallocation and let the system reclaim the memory at exit
159
+ mem::forget(graph);
160
+ }
@@ -0,0 +1,83 @@
1
+ use std::sync::LazyLock;
2
+
3
+ use url::Url;
4
+
5
+ use crate::{
6
+ indexing::{self, LanguageId},
7
+ model::{
8
+ declaration::{ClassDeclaration, Declaration, Namespace},
9
+ graph::Graph,
10
+ ids::DeclarationId,
11
+ },
12
+ };
13
+
14
+ pub static KERNEL_ID: LazyLock<DeclarationId> = LazyLock::new(|| DeclarationId::from("Kernel"));
15
+ pub static BASIC_OBJECT_ID: LazyLock<DeclarationId> = LazyLock::new(|| DeclarationId::from("BasicObject"));
16
+ pub static OBJECT_ID: LazyLock<DeclarationId> = LazyLock::new(|| DeclarationId::from("Object"));
17
+ pub static MODULE_ID: LazyLock<DeclarationId> = LazyLock::new(|| DeclarationId::from("Module"));
18
+ pub static CLASS_ID: LazyLock<DeclarationId> = LazyLock::new(|| DeclarationId::from("Class"));
19
+
20
+ /// Adds core classes and modules data to the graph so that resolution can provide correct results even when not
21
+ /// indexing the complete RBS core definitions
22
+ ///
23
+ /// # Panics
24
+ ///
25
+ /// Will panic if the built-in URI is invalid
26
+ pub fn add_built_in_data(graph: &mut Graph) {
27
+ // We need definitions to ensure that ancestor linearization happens naturally through the algorithm. Trying to set
28
+ // ancestors directly on declarations doesn't work because the algorithm erases the ancestors and there are no
29
+ // definitions to inform it of the superclasses and mixins.
30
+ let uri = Url::parse("rubydex:built-in").unwrap();
31
+ let source = r"
32
+ class BasicObject
33
+ end
34
+
35
+ module Kernel
36
+ end
37
+
38
+ class Object < BasicObject
39
+ include Kernel
40
+ end
41
+
42
+ class Module < Object
43
+ end
44
+
45
+ class Class < Module
46
+ end
47
+ ";
48
+ indexing::index_source(graph, uri.as_ref(), source, &LanguageId::Rbs);
49
+
50
+ // Creating declarations eagerly is still necessary because we need to associate correct ownership data no matter in
51
+ // what order we discover classes and modules
52
+ let declarations = graph.declarations_mut();
53
+
54
+ // Built-in declarations that always exist in the Ruby object model
55
+ declarations.insert(
56
+ *BASIC_OBJECT_ID,
57
+ Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
58
+ "BasicObject".to_string(),
59
+ *OBJECT_ID,
60
+ )))),
61
+ );
62
+ declarations.insert(
63
+ *OBJECT_ID,
64
+ Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
65
+ "Object".to_string(),
66
+ *OBJECT_ID,
67
+ )))),
68
+ );
69
+ declarations.insert(
70
+ *MODULE_ID,
71
+ Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
72
+ "Module".to_string(),
73
+ *OBJECT_ID,
74
+ )))),
75
+ );
76
+ declarations.insert(
77
+ *CLASS_ID,
78
+ Declaration::Namespace(Namespace::Class(Box::new(ClassDeclaration::new(
79
+ "Class".to_string(),
80
+ *OBJECT_ID,
81
+ )))),
82
+ );
83
+ }
@@ -1,24 +1,24 @@
1
- use crate::offset::Offset;
2
-
3
- #[derive(Debug, Clone)]
4
- pub struct Comment {
5
- offset: Offset,
6
- string: String,
7
- }
8
-
9
- impl Comment {
10
- #[must_use]
11
- pub fn new(offset: Offset, string: String) -> Self {
12
- Self { offset, string }
13
- }
14
-
15
- #[must_use]
16
- pub fn offset(&self) -> &Offset {
17
- &self.offset
18
- }
19
-
20
- #[must_use]
21
- pub fn string(&self) -> &String {
22
- &self.string
23
- }
24
- }
1
+ use crate::offset::Offset;
2
+
3
+ #[derive(Debug, Clone)]
4
+ pub struct Comment {
5
+ offset: Offset,
6
+ string: String,
7
+ }
8
+
9
+ impl Comment {
10
+ #[must_use]
11
+ pub fn new(offset: Offset, string: String) -> Self {
12
+ Self { offset, string }
13
+ }
14
+
15
+ #[must_use]
16
+ pub fn offset(&self) -> &Offset {
17
+ &self.offset
18
+ }
19
+
20
+ #[must_use]
21
+ pub fn string(&self) -> &String {
22
+ &self.string
23
+ }
24
+ }