rubydex 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +29 -7
- data/THIRD_PARTY_LICENSES.html +238 -2
- data/exe/rdx +2 -149
- data/ext/rubydex/config.c +140 -0
- data/ext/rubydex/config.h +16 -0
- data/ext/rubydex/definition.c +34 -0
- data/ext/rubydex/definition.h +3 -0
- data/ext/rubydex/diagnostic.c +28 -1
- data/ext/rubydex/diagnostic.h +2 -0
- data/ext/rubydex/extconf.rb +4 -2
- data/ext/rubydex/graph.c +71 -55
- data/ext/rubydex/graph.h +6 -0
- data/ext/rubydex/query.c +398 -16
- data/ext/rubydex/rubydex.c +2 -0
- data/ext/rubydex/utils.c +11 -4
- data/lib/ruby_lsp/rubydex/addon.rb +211 -0
- data/lib/rubydex/cli/command/console.rb +55 -0
- data/lib/rubydex/cli/command/lint/explain.rb +76 -0
- data/lib/rubydex/cli/command/lint.rb +208 -0
- data/lib/rubydex/cli/command/mcp.rb +30 -0
- data/lib/rubydex/cli/command/query.rb +70 -0
- data/lib/rubydex/cli/command/skill.rb +69 -0
- data/lib/rubydex/cli/command.rb +168 -0
- data/lib/rubydex/cli.rb +93 -0
- data/lib/rubydex/config.rb +59 -0
- data/lib/rubydex/diagnostic.rb +12 -3
- data/lib/rubydex/errors.rb +42 -1
- data/lib/rubydex/graph.rb +10 -3
- data/lib/rubydex/linter/custom_rule.rb +97 -0
- data/lib/rubydex/linter/helpers/path_helpers.rb +78 -0
- data/lib/rubydex/linter/helpers/source_access_helpers.rb +31 -0
- data/lib/rubydex/linter/rule_loader.rb +36 -0
- data/lib/rubydex/linter/rule_test_case.rb +343 -0
- data/lib/rubydex/linter/runner.rb +56 -0
- data/lib/rubydex/linter.rb +19 -0
- data/lib/rubydex/location.rb +3 -0
- data/lib/rubydex/mcp_server.rb +1 -2
- data/lib/rubydex/related_information.rb +17 -0
- data/lib/rubydex/rule.rb +33 -0
- 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/severity.rb +70 -0
- data/lib/rubydex/skill.rb +89 -0
- data/lib/rubydex/skill_registry.rb +62 -0
- data/lib/rubydex/version.rb +1 -1
- data/lib/rubydex.rb +8 -0
- data/lib/rubydex_linter/rules/rule_structure.rb +140 -0
- data/rbi/rubydex.rbi +464 -21
- data/rust/Cargo.lock +2 -2
- data/rust/rubydex/Cargo.toml +5 -1
- data/rust/rubydex/benches/graph_memory.rs +3 -5
- data/rust/rubydex/src/bin/generate_ruby_rules.rs +94 -0
- data/rust/rubydex/src/config.rs +538 -157
- data/rust/rubydex/src/diagnostic.rs +162 -45
- data/rust/rubydex/src/errors.rs +0 -1
- data/rust/rubydex/src/indexing/local_graph.rs +6 -5
- data/rust/rubydex/src/indexing/rbs_indexer.rs +270 -6
- data/rust/rubydex/src/indexing/ruby_indexer.rs +10 -12
- data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +134 -81
- data/rust/rubydex/src/lib.rs +1 -0
- data/rust/rubydex/src/listing.rs +26 -1
- data/rust/rubydex/src/main.rs +7 -4
- data/rust/rubydex/src/model/declaration.rs +302 -219
- data/rust/rubydex/src/model/graph.rs +27 -40
- data/rust/rubydex/src/model/name.rs +58 -17
- data/rust/rubydex/src/operation/ruby_builder.rs +30 -45
- data/rust/rubydex/src/path_helpers.rs +77 -0
- data/rust/rubydex/src/query/cypher/schema.rs +63 -0
- data/rust/rubydex/src/query/cypher/tests.rs +26 -1
- data/rust/rubydex/src/query/cypher.rs +8 -11
- data/rust/rubydex/src/query.rs +314 -44
- data/rust/rubydex/src/resolution.rs +139 -187
- data/rust/rubydex/src/resolution_tests.rs +247 -19
- data/rust/rubydex/src/test_utils/context.rs +2 -1
- data/rust/rubydex/src/test_utils/graph_test.rs +26 -12
- data/rust/rubydex/src/test_utils/local_graph_test.rs +19 -0
- data/rust/rubydex/tests/cli.rs +4 -4
- data/rust/rubydex-sys/src/config_api.rs +205 -0
- data/rust/rubydex-sys/src/cypher_api.rs +791 -0
- data/rust/rubydex-sys/src/definition_api.rs +68 -1
- data/rust/rubydex-sys/src/diagnostic_api.rs +42 -8
- data/rust/rubydex-sys/src/graph_api.rs +125 -205
- data/rust/rubydex-sys/src/lib.rs +2 -0
- data/rust/rubydex-sys/src/name_api.rs +49 -17
- data/rust/rubydex-sys/src/utils.rs +37 -0
- data/skills/send-private-method/SKILL.md +133 -0
- metadata +42 -2
data/rbi/rubydex.rbi
CHANGED
|
@@ -175,22 +175,114 @@ 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
|
|
183
192
|
|
|
184
193
|
class Rubydex::MethodAliasDefinition < Rubydex::Definition
|
|
194
|
+
sig { returns(T::Array[Rubydex::Signature]) }
|
|
195
|
+
def signatures; end
|
|
196
|
+
|
|
185
197
|
sig { returns(T.nilable(Rubydex::Method)) }
|
|
186
198
|
def target; end
|
|
187
199
|
end
|
|
188
200
|
|
|
189
|
-
class Rubydex::MethodDefinition < Rubydex::Definition
|
|
201
|
+
class Rubydex::MethodDefinition < Rubydex::Definition
|
|
202
|
+
sig { returns(T::Array[Rubydex::Signature]) }
|
|
203
|
+
def signatures; end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
class Rubydex::Signature
|
|
207
|
+
sig { params(parameters: T::Array[Rubydex::Signature::Parameter]).void }
|
|
208
|
+
def initialize(parameters); end
|
|
209
|
+
|
|
210
|
+
sig { returns(T::Array[Rubydex::Signature::Parameter]) }
|
|
211
|
+
def parameters; end
|
|
212
|
+
|
|
213
|
+
sig do
|
|
214
|
+
returns([
|
|
215
|
+
T::Array[Rubydex::Signature::PositionalParameter],
|
|
216
|
+
T::Array[Rubydex::Signature::OptionalPositionalParameter],
|
|
217
|
+
T.nilable(Rubydex::Signature::RestPositionalParameter),
|
|
218
|
+
T::Array[Rubydex::Signature::PostParameter],
|
|
219
|
+
T::Array[Rubydex::Signature::KeywordParameter],
|
|
220
|
+
T::Array[Rubydex::Signature::OptionalKeywordParameter],
|
|
221
|
+
T.nilable(Rubydex::Signature::RestKeywordParameter),
|
|
222
|
+
T.nilable(Rubydex::Signature::ForwardParameter),
|
|
223
|
+
T.nilable(Rubydex::Signature::BlockParameter),
|
|
224
|
+
])
|
|
225
|
+
end
|
|
226
|
+
def deconstruct; end
|
|
227
|
+
|
|
228
|
+
sig { params(keys: T.nilable(T::Array[Symbol])).returns(T::Hash[Symbol, T.untyped]) }
|
|
229
|
+
def deconstruct_keys(keys); end
|
|
230
|
+
|
|
231
|
+
sig { returns(T::Array[Rubydex::Signature::PositionalParameter]) }
|
|
232
|
+
def positional_parameters; end
|
|
233
|
+
|
|
234
|
+
sig { returns(T::Array[Rubydex::Signature::OptionalPositionalParameter]) }
|
|
235
|
+
def optional_positional_parameters; end
|
|
236
|
+
|
|
237
|
+
sig { returns(T.nilable(Rubydex::Signature::RestPositionalParameter)) }
|
|
238
|
+
def rest_positional_parameter; end
|
|
239
|
+
|
|
240
|
+
sig { returns(T::Array[Rubydex::Signature::PostParameter]) }
|
|
241
|
+
def post_parameters; end
|
|
242
|
+
|
|
243
|
+
sig { returns(T::Array[Rubydex::Signature::KeywordParameter]) }
|
|
244
|
+
def keyword_parameters; end
|
|
245
|
+
|
|
246
|
+
sig { returns(T::Array[Rubydex::Signature::OptionalKeywordParameter]) }
|
|
247
|
+
def optional_keyword_parameters; end
|
|
248
|
+
|
|
249
|
+
sig { returns(T.nilable(Rubydex::Signature::RestKeywordParameter)) }
|
|
250
|
+
def rest_keyword_parameter; end
|
|
251
|
+
|
|
252
|
+
sig { returns(T.nilable(Rubydex::Signature::ForwardParameter)) }
|
|
253
|
+
def forward_parameter; end
|
|
254
|
+
|
|
255
|
+
sig { returns(T.nilable(Rubydex::Signature::BlockParameter)) }
|
|
256
|
+
def block_parameter; end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
class Rubydex::Signature::Parameter
|
|
260
|
+
sig { returns(Symbol) }
|
|
261
|
+
def name; end
|
|
262
|
+
|
|
263
|
+
sig { returns(Rubydex::Location) }
|
|
264
|
+
def location; end
|
|
265
|
+
|
|
266
|
+
sig { params(name: Symbol, location: Rubydex::Location).void }
|
|
267
|
+
def initialize(name, location); end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
class Rubydex::Signature::PositionalParameter < Rubydex::Signature::Parameter; end
|
|
271
|
+
class Rubydex::Signature::OptionalPositionalParameter < Rubydex::Signature::Parameter; end
|
|
272
|
+
class Rubydex::Signature::RestPositionalParameter < Rubydex::Signature::Parameter; end
|
|
273
|
+
class Rubydex::Signature::PostParameter < Rubydex::Signature::Parameter; end
|
|
274
|
+
class Rubydex::Signature::KeywordParameter < Rubydex::Signature::Parameter; end
|
|
275
|
+
class Rubydex::Signature::OptionalKeywordParameter < Rubydex::Signature::Parameter; end
|
|
276
|
+
class Rubydex::Signature::RestKeywordParameter < Rubydex::Signature::Parameter; end
|
|
277
|
+
class Rubydex::Signature::ForwardParameter < Rubydex::Signature::Parameter; end
|
|
278
|
+
class Rubydex::Signature::BlockParameter < Rubydex::Signature::Parameter; end
|
|
190
279
|
|
|
191
280
|
class Rubydex::ModuleDefinition < Rubydex::Definition
|
|
192
281
|
sig { returns(T::Array[Rubydex::Mixin]) }
|
|
193
282
|
def mixins; end
|
|
283
|
+
|
|
284
|
+
sig { returns(String) }
|
|
285
|
+
def raw_name; end
|
|
194
286
|
end
|
|
195
287
|
|
|
196
288
|
class Rubydex::SingletonClassDefinition < Rubydex::Definition
|
|
@@ -204,6 +296,9 @@ class Rubydex::ClassDefinition < Rubydex::Definition
|
|
|
204
296
|
|
|
205
297
|
sig { returns(T::Array[Rubydex::Mixin]) }
|
|
206
298
|
def mixins; end
|
|
299
|
+
|
|
300
|
+
sig { returns(String) }
|
|
301
|
+
def raw_name; end
|
|
207
302
|
end
|
|
208
303
|
|
|
209
304
|
class Rubydex::Mixin
|
|
@@ -220,9 +315,64 @@ class Rubydex::Include < Rubydex::Mixin; end
|
|
|
220
315
|
class Rubydex::Prepend < Rubydex::Mixin; end
|
|
221
316
|
class Rubydex::Extend < Rubydex::Mixin; end
|
|
222
317
|
|
|
318
|
+
module Rubydex::Severity
|
|
319
|
+
# Every severity, ordered from the most to the least severe.
|
|
320
|
+
ALL = T.let(T.unsafe(nil), T::Array[T.class_of(Rubydex::Severity::Base)])
|
|
321
|
+
|
|
322
|
+
sig { params(value: Symbol).returns(T.class_of(Rubydex::Severity::Base)) }
|
|
323
|
+
def self.from_value(value); end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
class Rubydex::Severity::Base
|
|
327
|
+
abstract!
|
|
328
|
+
|
|
329
|
+
sig { returns(Symbol) }
|
|
330
|
+
def self.value; end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
class Rubydex::Severity::Error < Rubydex::Severity::Base; end
|
|
334
|
+
class Rubydex::Severity::Warning < Rubydex::Severity::Base; end
|
|
335
|
+
class Rubydex::Severity::Information < Rubydex::Severity::Base; end
|
|
336
|
+
class Rubydex::Severity::Hint < Rubydex::Severity::Base; end
|
|
337
|
+
|
|
338
|
+
class Rubydex::Rule
|
|
339
|
+
abstract!
|
|
340
|
+
|
|
341
|
+
class << self
|
|
342
|
+
abstract!
|
|
343
|
+
|
|
344
|
+
sig { returns(String) }
|
|
345
|
+
def rule_name; end
|
|
346
|
+
|
|
347
|
+
sig { abstract.returns(T.class_of(Rubydex::Severity::Base)) }
|
|
348
|
+
def default_severity; end
|
|
349
|
+
|
|
350
|
+
sig { params(config: Rubydex::LinterConfig).returns(T.class_of(Rubydex::Severity::Base)) }
|
|
351
|
+
def severity(config); end
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
class Rubydex::RelatedInformation
|
|
356
|
+
sig { params(message: String, location: Rubydex::Location).void }
|
|
357
|
+
def initialize(message, location); end
|
|
358
|
+
|
|
359
|
+
sig { returns(Rubydex::Location) }
|
|
360
|
+
def location; end
|
|
361
|
+
|
|
362
|
+
sig { returns(String) }
|
|
363
|
+
def message; end
|
|
364
|
+
end
|
|
365
|
+
|
|
223
366
|
class Rubydex::Diagnostic
|
|
224
|
-
sig
|
|
225
|
-
|
|
367
|
+
sig do
|
|
368
|
+
params(
|
|
369
|
+
rule: T.class_of(Rubydex::Rule),
|
|
370
|
+
message: String,
|
|
371
|
+
location: Rubydex::Location,
|
|
372
|
+
related_information: T::Array[Rubydex::RelatedInformation],
|
|
373
|
+
).void
|
|
374
|
+
end
|
|
375
|
+
def initialize(rule:, message:, location:, related_information: []); end
|
|
226
376
|
|
|
227
377
|
sig { returns(Rubydex::Location) }
|
|
228
378
|
def location; end
|
|
@@ -230,8 +380,179 @@ class Rubydex::Diagnostic
|
|
|
230
380
|
sig { returns(String) }
|
|
231
381
|
def message; end
|
|
232
382
|
|
|
233
|
-
sig { returns(
|
|
383
|
+
sig { returns(T.class_of(Rubydex::Rule)) }
|
|
234
384
|
def rule; end
|
|
385
|
+
|
|
386
|
+
sig { returns(T::Array[Rubydex::RelatedInformation]) }
|
|
387
|
+
def related_information; end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
module Rubydex::Linter; end
|
|
391
|
+
module Rubydex::Linter::Helpers; end
|
|
392
|
+
module Rubydex::Linter::Rules; end
|
|
393
|
+
|
|
394
|
+
module Rubydex::Linter::Helpers::PathHelpers
|
|
395
|
+
extend T::Helpers
|
|
396
|
+
|
|
397
|
+
requires_ancestor { Rubydex::Linter::CustomRule }
|
|
398
|
+
|
|
399
|
+
EXCLUDE_FNMATCH_FLAGS = T.let(T.unsafe(nil), Integer)
|
|
400
|
+
TEST_PATHS = T.let(T.unsafe(nil), T::Array[String])
|
|
401
|
+
|
|
402
|
+
sig do
|
|
403
|
+
params(
|
|
404
|
+
path: String,
|
|
405
|
+
patterns: T::Array[String],
|
|
406
|
+
workspace: String,
|
|
407
|
+
flags: Integer,
|
|
408
|
+
).returns(T::Boolean)
|
|
409
|
+
end
|
|
410
|
+
def self.path_matches_patterns?(path, patterns, workspace:, flags: 0); end
|
|
411
|
+
|
|
412
|
+
sig { params(location: Rubydex::Location, workspace: String).returns(String) }
|
|
413
|
+
def self.display_path(location, workspace:); end
|
|
414
|
+
|
|
415
|
+
sig do
|
|
416
|
+
params(
|
|
417
|
+
definitions: T::Enumerable[Rubydex::Definition],
|
|
418
|
+
excluded_patterns: T::Array[String],
|
|
419
|
+
).returns(T::Array[Rubydex::Definition])
|
|
420
|
+
end
|
|
421
|
+
def reject_definitions_in_paths(definitions, excluded_patterns); end
|
|
422
|
+
|
|
423
|
+
sig do
|
|
424
|
+
params(
|
|
425
|
+
definitions: T::Enumerable[Rubydex::Definition],
|
|
426
|
+
patterns: T::Array[String],
|
|
427
|
+
).returns(T::Array[Rubydex::Definition])
|
|
428
|
+
end
|
|
429
|
+
def select_definitions_in_paths(definitions, patterns); end
|
|
430
|
+
|
|
431
|
+
private
|
|
432
|
+
|
|
433
|
+
sig { params(path: String, patterns: T::Array[String]).returns(T::Boolean) }
|
|
434
|
+
def path_matches_patterns?(path, patterns); end
|
|
435
|
+
|
|
436
|
+
sig { params(path: String).returns(T::Boolean) }
|
|
437
|
+
def test_path?(path); end
|
|
438
|
+
|
|
439
|
+
sig { params(definition: Rubydex::Definition).returns(T.nilable(String)) }
|
|
440
|
+
def path_for_definition(definition); end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
module Rubydex::Linter::Helpers::SourceAccessHelpers
|
|
444
|
+
sig { params(uri: String).returns(Rubydex::Location) }
|
|
445
|
+
def file_location(uri); end
|
|
446
|
+
|
|
447
|
+
sig { params(uri: String).returns(String) }
|
|
448
|
+
def path_for_uri(uri); end
|
|
449
|
+
|
|
450
|
+
private
|
|
451
|
+
|
|
452
|
+
sig { params(location: Rubydex::Location).returns(T.nilable(String)) }
|
|
453
|
+
def source_for_location(location); end
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# Base class for semantic lint rules, which collect their diagnostics by walking a resolved graph.
|
|
457
|
+
class Rubydex::Linter::CustomRule < Rubydex::Rule
|
|
458
|
+
abstract!
|
|
459
|
+
|
|
460
|
+
sig { params(graph: Rubydex::Graph, config: Rubydex::LinterConfig).void }
|
|
461
|
+
def initialize(graph, config:); end
|
|
462
|
+
|
|
463
|
+
sig { returns(Rubydex::Graph) }
|
|
464
|
+
def graph; end
|
|
465
|
+
|
|
466
|
+
sig { returns(Rubydex::LinterConfig) }
|
|
467
|
+
def config; end
|
|
468
|
+
|
|
469
|
+
sig { returns(T::Array[Rubydex::Diagnostic]) }
|
|
470
|
+
def diagnostics; end
|
|
471
|
+
|
|
472
|
+
sig { params(definition: Rubydex::Definition).returns(Rubydex::Location) }
|
|
473
|
+
def diagnostic_location(definition); end
|
|
474
|
+
|
|
475
|
+
sig { params(base_name: String).returns(T::Enumerable[Rubydex::Class]) }
|
|
476
|
+
def child_classes(base_name); end
|
|
477
|
+
|
|
478
|
+
sig { params(name: String).returns(Rubydex::Namespace) }
|
|
479
|
+
def required_namespace(name); end
|
|
480
|
+
|
|
481
|
+
sig do
|
|
482
|
+
params(
|
|
483
|
+
namespace: Rubydex::Namespace,
|
|
484
|
+
method_name: String,
|
|
485
|
+
).returns(Rubydex::Method)
|
|
486
|
+
end
|
|
487
|
+
def required_method(namespace, method_name); end
|
|
488
|
+
|
|
489
|
+
sig { returns(String) }
|
|
490
|
+
def rule_name; end
|
|
491
|
+
|
|
492
|
+
sig { abstract.void }
|
|
493
|
+
def lint; end
|
|
494
|
+
|
|
495
|
+
protected
|
|
496
|
+
|
|
497
|
+
sig do
|
|
498
|
+
params(
|
|
499
|
+
message: String,
|
|
500
|
+
location: Rubydex::Location,
|
|
501
|
+
related_information: T::Array[Rubydex::RelatedInformation],
|
|
502
|
+
).void
|
|
503
|
+
end
|
|
504
|
+
def add_diagnostic(message, location, related_information: []); end
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
class Rubydex::Linter::MissingGraphDependencyError < StandardError
|
|
508
|
+
sig { params(rule_name: String, dependency: String).void }
|
|
509
|
+
def initialize(rule_name, dependency); end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
class Rubydex::Linter::RuleLoadError < StandardError; end
|
|
513
|
+
|
|
514
|
+
class Rubydex::Linter::RuleLoader
|
|
515
|
+
RULE_GLOB = T.let(T.unsafe(nil), String)
|
|
516
|
+
|
|
517
|
+
sig { params(workspace_path: String).void }
|
|
518
|
+
def self.load(workspace_path); end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
class Rubydex::Linter::Rules::RuleStructure < Rubydex::Linter::CustomRule
|
|
522
|
+
include Rubydex::Linter::Helpers::SourceAccessHelpers
|
|
523
|
+
|
|
524
|
+
BASE_RULE_NAME = T.let(T.unsafe(nil), String)
|
|
525
|
+
RULE_NAMESPACE = T.let(T.unsafe(nil), String)
|
|
526
|
+
RULE_FILE_PATTERNS = T.let(T.unsafe(nil), T::Array[String])
|
|
527
|
+
TEST_FILE_PATTERNS = T.let(T.unsafe(nil), T::Array[String])
|
|
528
|
+
|
|
529
|
+
class << self
|
|
530
|
+
sig { override.returns(T.class_of(Rubydex::Severity::Base)) }
|
|
531
|
+
def default_severity; end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
sig { override.void }
|
|
535
|
+
def lint; end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
class Rubydex::Linter::Runner
|
|
539
|
+
sig do
|
|
540
|
+
params(
|
|
541
|
+
graph: Rubydex::Graph,
|
|
542
|
+
custom_rules: T::Array[T.class_of(Rubydex::Linter::CustomRule)],
|
|
543
|
+
config: Rubydex::LinterConfig,
|
|
544
|
+
).void
|
|
545
|
+
end
|
|
546
|
+
def initialize(graph, custom_rules:, config:); end
|
|
547
|
+
|
|
548
|
+
sig { returns(Rubydex::Graph) }
|
|
549
|
+
def graph; end
|
|
550
|
+
|
|
551
|
+
sig { returns(T::Array[T.class_of(Rubydex::Linter::CustomRule)]) }
|
|
552
|
+
def custom_rules; end
|
|
553
|
+
|
|
554
|
+
sig { returns(T::Array[Rubydex::Diagnostic]) }
|
|
555
|
+
def run; end
|
|
235
556
|
end
|
|
236
557
|
|
|
237
558
|
class Rubydex::Keyword
|
|
@@ -273,6 +594,74 @@ end
|
|
|
273
594
|
class Rubydex::Error < StandardError; end
|
|
274
595
|
class Rubydex::AliasCycleError < Rubydex::Error; end
|
|
275
596
|
class Rubydex::ConfigError < Rubydex::Error; end
|
|
597
|
+
class Rubydex::QueryError < Rubydex::Error; end
|
|
598
|
+
class Rubydex::QuerySyntaxError < Rubydex::QueryError; end
|
|
599
|
+
class Rubydex::QueryExecutionError < Rubydex::QueryError; end
|
|
600
|
+
class Rubydex::StaleQueryResultError < Rubydex::QueryError; end
|
|
601
|
+
|
|
602
|
+
# The configuration of a workspace, parsed from its `rubydex.toml`. It carries both the settings that are global to
|
|
603
|
+
# every built-in tool, such as the workspace being analyzed, and the typed settings of each tool's own section (e.g.
|
|
604
|
+
# `[graph]`, `[linter]`).
|
|
605
|
+
class Rubydex::Config
|
|
606
|
+
class << self
|
|
607
|
+
# Loads the configuration file for `workspace_path/rubydex.toml` if it exists or uses the defaults.
|
|
608
|
+
sig { params(workspace_path: String).returns(Rubydex::Config) }
|
|
609
|
+
def load(workspace_path); end
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
# The linter's settings, read from the `[linter]` section.
|
|
613
|
+
sig { returns(Rubydex::LinterConfig) }
|
|
614
|
+
def linter; end
|
|
615
|
+
|
|
616
|
+
# The configured workspace path, which is usually PWD, except for editors that spawn language servers outside of pwd.
|
|
617
|
+
sig { returns(String) }
|
|
618
|
+
def workspace_path; end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
# The linter's settings, read from the `[linter]` section of the configuration file.
|
|
622
|
+
class Rubydex::LinterConfig
|
|
623
|
+
# The configured rules, keyed by rule name. Only rules the configuration file mentions appear here, so a rule that
|
|
624
|
+
# was never configured is absent rather than present with its defaults.
|
|
625
|
+
sig { returns(T::Hash[String, Rubydex::RuleConfig]) }
|
|
626
|
+
attr_reader :rules
|
|
627
|
+
|
|
628
|
+
sig { params(rules: T::Hash[String, Rubydex::RuleConfig]).void }
|
|
629
|
+
def initialize(rules); end
|
|
630
|
+
|
|
631
|
+
sig { params(rule_class: T.class_of(Rubydex::Rule)).returns(T::Boolean) }
|
|
632
|
+
def rule_enabled?(rule_class); end
|
|
633
|
+
|
|
634
|
+
sig { params(rule_class: T.class_of(Rubydex::Rule)).returns(T::Array[String]) }
|
|
635
|
+
def excludes_for(rule_class); end
|
|
636
|
+
|
|
637
|
+
sig { params(rule_class: T.class_of(Rubydex::Rule)).returns(T.nilable(T.class_of(Rubydex::Severity::Base))) }
|
|
638
|
+
def severity_for(rule_class); end
|
|
639
|
+
end
|
|
640
|
+
|
|
641
|
+
# The settings of a single linter rule, read from a `[linter.rules.RuleName]` table.
|
|
642
|
+
class Rubydex::RuleConfig
|
|
643
|
+
sig { returns(String) }
|
|
644
|
+
attr_reader :name
|
|
645
|
+
|
|
646
|
+
sig { returns(T::Array[String]) }
|
|
647
|
+
attr_reader :exclude_patterns
|
|
648
|
+
|
|
649
|
+
sig { returns(T.nilable(T.class_of(Rubydex::Severity::Base))) }
|
|
650
|
+
attr_reader :severity
|
|
651
|
+
|
|
652
|
+
sig do
|
|
653
|
+
params(
|
|
654
|
+
name: String,
|
|
655
|
+
enabled: T::Boolean,
|
|
656
|
+
exclude_patterns: T::Array[String],
|
|
657
|
+
severity: T.nilable(T.class_of(Rubydex::Severity::Base)),
|
|
658
|
+
).void
|
|
659
|
+
end
|
|
660
|
+
def initialize(name, enabled, exclude_patterns = [], severity = nil); end
|
|
661
|
+
|
|
662
|
+
sig { returns(T::Boolean) }
|
|
663
|
+
def enabled?; end
|
|
664
|
+
end
|
|
276
665
|
|
|
277
666
|
class Rubydex::Failure
|
|
278
667
|
sig { params(message: String).void }
|
|
@@ -293,13 +682,55 @@ class Rubydex::Query
|
|
|
293
682
|
def schema(format = :table); end
|
|
294
683
|
end
|
|
295
684
|
|
|
296
|
-
sig { params(graph: Rubydex::Graph
|
|
297
|
-
def
|
|
685
|
+
sig { params(graph: Rubydex::Graph).returns(Rubydex::Query::Result) }
|
|
686
|
+
def run(graph); end
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
# The columns and rows produced by one run of a query. Enumerable over its rows.
|
|
690
|
+
class Rubydex::Query::Result
|
|
691
|
+
include Enumerable
|
|
692
|
+
extend T::Generic
|
|
693
|
+
|
|
694
|
+
Elem = type_member { { fixed: T::Hash[String, T.untyped] } }
|
|
695
|
+
|
|
696
|
+
class << self
|
|
697
|
+
private
|
|
698
|
+
|
|
699
|
+
# A result only comes from `Query#run`. The C extension undefines `new`, so a call raises.
|
|
700
|
+
sig { returns(T.noreturn) }
|
|
701
|
+
def new; end
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
sig { returns(T::Array[String]) }
|
|
705
|
+
def columns; end
|
|
706
|
+
|
|
707
|
+
sig { returns(T::Array[T::Hash[String, T.untyped]]) }
|
|
708
|
+
def rows; end
|
|
709
|
+
|
|
710
|
+
sig { override.params(block: T.proc.params(row: T::Hash[String, T.untyped]).void).returns(T.self_type) }
|
|
711
|
+
sig { override.returns(T::Enumerator[T::Hash[String, T.untyped]]) }
|
|
712
|
+
def each(&block); end
|
|
713
|
+
|
|
714
|
+
sig { returns(Integer) }
|
|
715
|
+
def size; end
|
|
716
|
+
|
|
717
|
+
sig { returns(Integer) }
|
|
718
|
+
def length; end
|
|
719
|
+
|
|
720
|
+
sig { returns(T::Boolean) }
|
|
721
|
+
def empty?; end
|
|
722
|
+
|
|
723
|
+
sig { params(format: T.any(String, Symbol)).returns(String) }
|
|
724
|
+
def render(format = :table); end
|
|
298
725
|
end
|
|
299
726
|
|
|
300
727
|
class Rubydex::Graph
|
|
301
|
-
|
|
302
|
-
|
|
728
|
+
class << self
|
|
729
|
+
# Creates a new graph with the loaded configuration. For use cases where the graph must be shared between
|
|
730
|
+
# different tools, do not use this. Create and own a `Config` object instead.
|
|
731
|
+
sig { params(workspace_path: String).returns(T.attached_class) }
|
|
732
|
+
def configure_for_workspace(workspace_path); end
|
|
733
|
+
end
|
|
303
734
|
|
|
304
735
|
sig { params(fully_qualified_name: String).returns(T.nilable(Rubydex::Declaration)) }
|
|
305
736
|
def [](fully_qualified_name); end
|
|
@@ -332,12 +763,13 @@ class Rubydex::Graph
|
|
|
332
763
|
sig { returns(T::Array[String]) }
|
|
333
764
|
def index_workspace; end
|
|
334
765
|
|
|
335
|
-
#
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
766
|
+
# Returns the keyword object for the name, or `nil` if it is not a Ruby keyword
|
|
767
|
+
sig { params(name: String).returns(T.nilable(Rubydex::Keyword)) }
|
|
768
|
+
def keyword(name); end
|
|
769
|
+
|
|
770
|
+
# Loads the configuration in the graph.
|
|
771
|
+
sig { params(config: Rubydex::Config).void }
|
|
772
|
+
def load_config(config); end
|
|
341
773
|
|
|
342
774
|
sig { returns(T::Enumerable[Rubydex::MethodReference]) }
|
|
343
775
|
def method_references; end
|
|
@@ -348,8 +780,18 @@ class Rubydex::Graph
|
|
|
348
780
|
sig { returns(T.self_type) }
|
|
349
781
|
def resolve; end
|
|
350
782
|
|
|
351
|
-
sig
|
|
352
|
-
|
|
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
|
|
353
795
|
|
|
354
796
|
sig { params(require_path: String, load_paths: T::Array[String]).returns(T.nilable(Rubydex::Document)) }
|
|
355
797
|
def resolve_require_path(require_path, load_paths); end
|
|
@@ -360,15 +802,16 @@ class Rubydex::Graph
|
|
|
360
802
|
sig { params(queries: String).returns(T::Enumerable[Rubydex::Declaration]) }
|
|
361
803
|
def fuzzy_search(*queries); end
|
|
362
804
|
|
|
805
|
+
sig { returns(T::Enumerable[Rubydex::Declaration]) }
|
|
806
|
+
def dead_code_candidates; end
|
|
807
|
+
|
|
363
808
|
sig { params(encoding: String).void }
|
|
364
809
|
def encoding=(encoding); end
|
|
365
810
|
|
|
811
|
+
# The root directory of the workspace being analyzed, which comes from the loaded `Rubydex::Config`
|
|
366
812
|
sig { returns(String) }
|
|
367
813
|
def workspace_path; end
|
|
368
814
|
|
|
369
|
-
sig { params(workspace_path: String).returns(String) }
|
|
370
|
-
def workspace_path=(workspace_path); end
|
|
371
|
-
|
|
372
815
|
sig { returns(T::Array[String]) }
|
|
373
816
|
def workspace_paths; end
|
|
374
817
|
|
data/rust/Cargo.lock
CHANGED
|
@@ -262,9 +262,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|
|
262
262
|
|
|
263
263
|
[[package]]
|
|
264
264
|
name = "cypher-parser"
|
|
265
|
-
version = "0.
|
|
265
|
+
version = "0.8.1"
|
|
266
266
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
267
|
-
checksum = "
|
|
267
|
+
checksum = "6ada60f869dbe5818d0ee40b06ad988627cc0d692d1ed42d692353bf0af8ddb6"
|
|
268
268
|
|
|
269
269
|
[[package]]
|
|
270
270
|
name = "difflib"
|
data/rust/rubydex/Cargo.toml
CHANGED
|
@@ -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
|
|
|
@@ -27,7 +31,7 @@ jemalloc_dylib = ["jemalloc", "tikv-jemallocator/disable_initial_exec_tls"]
|
|
|
27
31
|
test_utils = ["dep:tempfile"]
|
|
28
32
|
|
|
29
33
|
[dependencies]
|
|
30
|
-
cypher-parser = "0.
|
|
34
|
+
cypher-parser = "0.8.1"
|
|
31
35
|
ruby-prism = "1.9.0"
|
|
32
36
|
ruby-rbs = "0.3"
|
|
33
37
|
url = "2.5.4"
|
|
@@ -3,6 +3,7 @@ mod imp {
|
|
|
3
3
|
use std::time::Instant;
|
|
4
4
|
|
|
5
5
|
use rubydex::{
|
|
6
|
+
config::Config,
|
|
6
7
|
indexing::{self, IndexerBackend},
|
|
7
8
|
listing,
|
|
8
9
|
model::graph::Graph,
|
|
@@ -27,11 +28,8 @@ mod imp {
|
|
|
27
28
|
assert!(workspace_path.is_dir(), "the workspace path must be a directory");
|
|
28
29
|
|
|
29
30
|
let mut graph = Graph::new();
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if let Err(error) = graph.load_config(None) {
|
|
33
|
-
eprintln!("{error}");
|
|
34
|
-
}
|
|
31
|
+
let config = Config::load(&workspace_path).expect("the workspace configuration must be valid");
|
|
32
|
+
graph.load_config(&config);
|
|
35
33
|
|
|
36
34
|
let time = Instant::now();
|
|
37
35
|
|