rubydex 0.2.9 → 0.4.0
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 +110 -6
- data/THIRD_PARTY_LICENSES.html +271 -2
- data/exe/rdx +2 -73
- data/ext/rubydex/config.c +140 -0
- data/ext/rubydex/config.h +16 -0
- data/ext/rubydex/declaration.c +1 -1
- data/ext/rubydex/definition.c +32 -4
- data/ext/rubydex/diagnostic.c +75 -1
- data/ext/rubydex/diagnostic.h +2 -0
- data/ext/rubydex/graph.c +27 -48
- data/ext/rubydex/graph.h +6 -0
- data/ext/rubydex/query.c +487 -0
- data/ext/rubydex/query.h +8 -0
- data/ext/rubydex/reference.c +60 -0
- data/ext/rubydex/rubydex.c +4 -0
- data/ext/rubydex/utils.c +23 -4
- data/ext/rubydex/utils.h +5 -0
- 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 +74 -0
- data/lib/rubydex/cli/command/lint.rb +202 -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/severity.rb +70 -0
- data/lib/rubydex/skill.rb +88 -0
- data/lib/rubydex/skill_registry.rb +62 -0
- data/lib/rubydex/version.rb +1 -1
- data/lib/rubydex.rb +6 -0
- data/lib/rubydex_linter/rules/rule_structure.rb +125 -0
- data/rbi/rubydex.rbi +578 -15
- data/rust/Cargo.lock +7 -0
- data/rust/rubydex/Cargo.toml +1 -0
- data/rust/rubydex/benches/graph_memory.rs +20 -4
- data/rust/rubydex/src/compile_assertions.rs +15 -0
- data/rust/rubydex/src/config.rs +538 -157
- data/rust/rubydex/src/diagnostic.rs +66 -40
- 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 +284 -8
- data/rust/rubydex/src/indexing/ruby_indexer.rs +59 -70
- data/rust/rubydex/src/indexing/ruby_indexer_tests.rs +195 -86
- data/rust/rubydex/src/lib.rs +1 -0
- data/rust/rubydex/src/listing.rs +26 -1
- data/rust/rubydex/src/main.rs +9 -128
- data/rust/rubydex/src/model/declaration.rs +301 -229
- data/rust/rubydex/src/model/definitions.rs +27 -26
- data/rust/rubydex/src/model/document.rs +43 -7
- data/rust/rubydex/src/model/graph.rs +67 -68
- data/rust/rubydex/src/model/id.rs +55 -0
- data/rust/rubydex/src/model/ids.rs +21 -9
- data/rust/rubydex/src/model/name.rs +88 -19
- data/rust/rubydex/src/model/references.rs +16 -13
- data/rust/rubydex/src/operation/ruby_builder.rs +78 -104
- data/rust/rubydex/src/path_helpers.rs +77 -0
- data/rust/rubydex/src/query/cypher/schema.rs +853 -0
- data/rust/rubydex/src/query/cypher/schema_info.rs +161 -0
- data/rust/rubydex/src/query/cypher/tests.rs +253 -0
- data/rust/rubydex/src/query/cypher.rs +54 -0
- data/rust/rubydex/src/query.rs +125 -43
- data/rust/rubydex/src/resolution.rs +368 -395
- data/rust/rubydex/src/resolution_tests.rs +504 -78
- 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/declaration_api.rs +6 -3
- data/rust/rubydex-sys/src/definition_api.rs +27 -7
- data/rust/rubydex-sys/src/diagnostic_api.rs +77 -8
- data/rust/rubydex-sys/src/graph_api.rs +31 -68
- data/rust/rubydex-sys/src/lib.rs +2 -0
- data/rust/rubydex-sys/src/name_api.rs +2 -6
- data/rust/rubydex-sys/src/reference_api.rs +58 -12
- data/rust/rubydex-sys/src/utils.rs +37 -0
- data/skills/send-private-method/SKILL.md +133 -0
- metadata +37 -2
|
@@ -6,6 +6,7 @@ use crate::{
|
|
|
6
6
|
assert_def_comments_eq, assert_def_mixins_eq, assert_def_name_eq, assert_def_name_offset_eq, assert_def_str_eq,
|
|
7
7
|
assert_def_superclass_ref_eq, assert_definition_at, assert_dependents, assert_local_diagnostics_eq,
|
|
8
8
|
assert_method_has_receiver, assert_name_path_eq, assert_no_local_diagnostics, assert_string_eq,
|
|
9
|
+
diagnostic::Severity,
|
|
9
10
|
model::{
|
|
10
11
|
definitions::{Definition, Parameter, Receiver, Signatures},
|
|
11
12
|
ids::{StringId, UriId},
|
|
@@ -967,7 +968,8 @@ mod class_and_module_tests {
|
|
|
967
968
|
|
|
968
969
|
assert_local_diagnostics_eq!(
|
|
969
970
|
&context,
|
|
970
|
-
["
|
|
971
|
+
["DynamicConstantReference: Dynamic constant reference (1:7-1:10)"],
|
|
972
|
+
severity: Severity::Information
|
|
971
973
|
);
|
|
972
974
|
assert!(context.graph().definitions().is_empty());
|
|
973
975
|
}
|
|
@@ -1071,7 +1073,7 @@ mod class_and_module_tests {
|
|
|
1071
1073
|
|
|
1072
1074
|
assert_local_diagnostics_eq!(
|
|
1073
1075
|
&context,
|
|
1074
|
-
["
|
|
1076
|
+
["DynamicConstantReference: Dynamic constant reference (1:8-1:11)"]
|
|
1075
1077
|
);
|
|
1076
1078
|
assert!(context.graph().definitions().is_empty());
|
|
1077
1079
|
}
|
|
@@ -1173,7 +1175,7 @@ mod method_tests {
|
|
|
1173
1175
|
|
|
1174
1176
|
assert_local_diagnostics_eq!(
|
|
1175
1177
|
&context,
|
|
1176
|
-
["
|
|
1178
|
+
["DynamicSingletonDefinition: Dynamic receiver for singleton method definition (1:1-1:17)"]
|
|
1177
1179
|
);
|
|
1178
1180
|
assert_eq!(context.graph().definitions().len(), 0);
|
|
1179
1181
|
assert_method_references_eq!(&context, ["foo"]);
|
|
@@ -1416,7 +1418,7 @@ mod singleton_class_tests {
|
|
|
1416
1418
|
|
|
1417
1419
|
assert_local_diagnostics_eq!(
|
|
1418
1420
|
&context,
|
|
1419
|
-
["
|
|
1421
|
+
["DynamicSingletonDefinition: Dynamic singleton class definition (1:1-3:4)"]
|
|
1420
1422
|
);
|
|
1421
1423
|
assert_eq!(context.graph().definitions().len(), 0);
|
|
1422
1424
|
}
|
|
@@ -1557,6 +1559,34 @@ mod visibility_tests {
|
|
|
1557
1559
|
});
|
|
1558
1560
|
}
|
|
1559
1561
|
|
|
1562
|
+
#[test]
|
|
1563
|
+
fn index_module_function_with_body() {
|
|
1564
|
+
let context = index_source({
|
|
1565
|
+
"
|
|
1566
|
+
module Foo
|
|
1567
|
+
module_function
|
|
1568
|
+
|
|
1569
|
+
def bar
|
|
1570
|
+
@value = CONST
|
|
1571
|
+
baz(1)
|
|
1572
|
+
end
|
|
1573
|
+
end
|
|
1574
|
+
"
|
|
1575
|
+
});
|
|
1576
|
+
|
|
1577
|
+
assert_no_local_diagnostics!(&context);
|
|
1578
|
+
assert_eq!(context.graph().definitions().len(), 4);
|
|
1579
|
+
assert_eq!(context.graph().document().definitions().len(), 4);
|
|
1580
|
+
assert_eq!(context.graph().document().constant_references().len(), 1);
|
|
1581
|
+
assert_eq!(context.graph().document().method_references().len(), 1);
|
|
1582
|
+
assert_constant_references_eq!(&context, ["CONST"]);
|
|
1583
|
+
assert_method_references_eq!(&context, ["baz"]);
|
|
1584
|
+
|
|
1585
|
+
let methods = context.all_definitions_at("4:3-7:6");
|
|
1586
|
+
assert_eq!(methods.len(), 2);
|
|
1587
|
+
assert_definition_at!(&context, "5:5-5:11", InstanceVariable);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1560
1590
|
#[test]
|
|
1561
1591
|
fn index_def_node_with_visibility_nested() {
|
|
1562
1592
|
let context = index_source({
|
|
@@ -1750,20 +1780,20 @@ mod visibility_tests {
|
|
|
1750
1780
|
fn index_private_constant_calls_diagnostics() {
|
|
1751
1781
|
let context = index_source({
|
|
1752
1782
|
"
|
|
1753
|
-
private_constant :
|
|
1754
|
-
self.private_constant :
|
|
1755
|
-
foo.private_constant :
|
|
1783
|
+
private_constant :BAR # not indexed, called at top level
|
|
1784
|
+
self.private_constant :BAR # not indexed, self receiver at top level
|
|
1785
|
+
foo.private_constant :BAR # not indexed, dynamic receiver
|
|
1756
1786
|
|
|
1757
1787
|
module Foo
|
|
1758
|
-
private_constant
|
|
1788
|
+
private_constant SomeConst, some_method # not indexed, non-literal arguments
|
|
1759
1789
|
private_constant # not indexed, no arguments
|
|
1760
1790
|
|
|
1761
1791
|
def self.qux
|
|
1762
|
-
private_constant :
|
|
1792
|
+
private_constant :BAR # not indexed, inside a method
|
|
1763
1793
|
end
|
|
1764
1794
|
|
|
1765
1795
|
def foo
|
|
1766
|
-
private_constant :
|
|
1796
|
+
private_constant :BAR # not indexed, inside a method
|
|
1767
1797
|
end
|
|
1768
1798
|
end
|
|
1769
1799
|
"
|
|
@@ -1772,15 +1802,53 @@ mod visibility_tests {
|
|
|
1772
1802
|
assert_local_diagnostics_eq!(
|
|
1773
1803
|
&context,
|
|
1774
1804
|
vec![
|
|
1775
|
-
"
|
|
1776
|
-
"
|
|
1777
|
-
"
|
|
1778
|
-
"
|
|
1779
|
-
"
|
|
1805
|
+
"InvalidConstantVisibility: `private_constant` called at top level (1:1-1:22)",
|
|
1806
|
+
"InvalidConstantVisibility: `private_constant` called at top level (2:1-2:27)",
|
|
1807
|
+
"InvalidConstantVisibility: Dynamic receiver for `private_constant` (3:1-3:4)",
|
|
1808
|
+
"InvalidConstantVisibility: `private_constant` called with a non-literal argument (6:20-6:29)",
|
|
1809
|
+
"InvalidConstantVisibility: `private_constant` called with a non-literal argument (6:31-6:42)",
|
|
1810
|
+
],
|
|
1811
|
+
severity: Severity::Warning
|
|
1812
|
+
);
|
|
1813
|
+
|
|
1814
|
+
assert_eq!(context.graph().definitions().len(), 3); // Foo, Foo.qux, Foo#foo
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
#[test]
|
|
1818
|
+
fn index_public_constant_calls_diagnostics() {
|
|
1819
|
+
let context = index_source({
|
|
1820
|
+
"
|
|
1821
|
+
public_constant :BAR # not indexed, called at top level
|
|
1822
|
+
self.public_constant :BAR # not indexed, self receiver at top level
|
|
1823
|
+
foo.public_constant :BAR # not indexed, dynamic receiver
|
|
1824
|
+
|
|
1825
|
+
module Foo
|
|
1826
|
+
public_constant SomeConst, some_method # not indexed, non-literal arguments
|
|
1827
|
+
public_constant # not indexed, no arguments
|
|
1828
|
+
|
|
1829
|
+
def self.qux
|
|
1830
|
+
public_constant :BAR # not indexed, inside a method
|
|
1831
|
+
end
|
|
1832
|
+
|
|
1833
|
+
def foo
|
|
1834
|
+
public_constant :BAR # not indexed, inside a method
|
|
1835
|
+
end
|
|
1836
|
+
end
|
|
1837
|
+
"
|
|
1838
|
+
});
|
|
1839
|
+
|
|
1840
|
+
assert_local_diagnostics_eq!(
|
|
1841
|
+
&context,
|
|
1842
|
+
vec![
|
|
1843
|
+
"InvalidConstantVisibility: `public_constant` called at top level (1:1-1:21)",
|
|
1844
|
+
"InvalidConstantVisibility: `public_constant` called at top level (2:1-2:26)",
|
|
1845
|
+
"InvalidConstantVisibility: Dynamic receiver for `public_constant` (3:1-3:4)",
|
|
1846
|
+
"InvalidConstantVisibility: `public_constant` called with a non-literal argument (6:19-6:28)",
|
|
1847
|
+
"InvalidConstantVisibility: `public_constant` called with a non-literal argument (6:30-6:41)",
|
|
1780
1848
|
]
|
|
1781
1849
|
);
|
|
1782
1850
|
|
|
1783
|
-
assert_eq!(context.graph().definitions().len(), 3); // Foo, Foo
|
|
1851
|
+
assert_eq!(context.graph().definitions().len(), 3); // Foo, Foo.qux, Foo#foo
|
|
1784
1852
|
}
|
|
1785
1853
|
|
|
1786
1854
|
#[test]
|
|
@@ -1853,7 +1921,7 @@ mod visibility_tests {
|
|
|
1853
1921
|
|
|
1854
1922
|
assert_local_diagnostics_eq!(
|
|
1855
1923
|
&context,
|
|
1856
|
-
vec!["
|
|
1924
|
+
vec!["InvalidMethodVisibility: `private` called with a non-literal argument (4:17-4:27)"]
|
|
1857
1925
|
);
|
|
1858
1926
|
|
|
1859
1927
|
// :foo is a literal arg, so visibility is still applied
|
|
@@ -1879,7 +1947,7 @@ mod visibility_tests {
|
|
|
1879
1947
|
|
|
1880
1948
|
assert_local_diagnostics_eq!(
|
|
1881
1949
|
&context,
|
|
1882
|
-
vec!["
|
|
1950
|
+
vec!["InvalidMethodVisibility: `private` cannot be called with an explicit receiver (4:3-4:19)"]
|
|
1883
1951
|
);
|
|
1884
1952
|
|
|
1885
1953
|
for def in context.graph().definitions().values() {
|
|
@@ -1904,7 +1972,7 @@ mod visibility_tests {
|
|
|
1904
1972
|
|
|
1905
1973
|
assert_local_diagnostics_eq!(
|
|
1906
1974
|
&context,
|
|
1907
|
-
vec!["
|
|
1975
|
+
vec!["InvalidMethodVisibility: `private` called with a non-literal argument (4:11-4:21)"]
|
|
1908
1976
|
);
|
|
1909
1977
|
|
|
1910
1978
|
// No MethodVisibilityDefinition created
|
|
@@ -1928,7 +1996,7 @@ mod visibility_tests {
|
|
|
1928
1996
|
|
|
1929
1997
|
assert_local_diagnostics_eq!(
|
|
1930
1998
|
&context,
|
|
1931
|
-
vec!["
|
|
1999
|
+
vec!["InvalidMethodVisibility: `private` called with a non-literal argument (2:11-2:23)"]
|
|
1932
2000
|
);
|
|
1933
2001
|
|
|
1934
2002
|
// No MethodVisibilityDefinition created
|
|
@@ -1952,7 +2020,7 @@ mod visibility_tests {
|
|
|
1952
2020
|
|
|
1953
2021
|
assert_local_diagnostics_eq!(
|
|
1954
2022
|
&context,
|
|
1955
|
-
vec!["
|
|
2023
|
+
vec!["InvalidMethodVisibility: `private` called with a non-literal argument (2:11-2:35)"]
|
|
1956
2024
|
);
|
|
1957
2025
|
|
|
1958
2026
|
// No MethodVisibilityDefinition or AttrReader created from that call
|
|
@@ -1995,9 +2063,7 @@ mod visibility_tests {
|
|
|
1995
2063
|
// attr_reader(:foo) returns an array in multi-arg context, invalid for `private`
|
|
1996
2064
|
assert_local_diagnostics_eq!(
|
|
1997
2065
|
&context,
|
|
1998
|
-
vec![
|
|
1999
|
-
"invalid-method-visibility: `private` with `attr_*` is only supported as a single argument (2:11-2:28)"
|
|
2000
|
-
]
|
|
2066
|
+
vec!["InvalidMethodVisibility: `private` with `attr_*` is only supported as a single argument (2:11-2:28)"]
|
|
2001
2067
|
);
|
|
2002
2068
|
|
|
2003
2069
|
// foo reader still defined via side effects, but public
|
|
@@ -2021,10 +2087,29 @@ mod visibility_tests {
|
|
|
2021
2087
|
|
|
2022
2088
|
assert_no_local_diagnostics!(&context);
|
|
2023
2089
|
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2090
|
+
let defs = context.all_definitions_at("4:20-4:23");
|
|
2091
|
+
assert_eq!(defs.len(), 2, "expected two MethodVisibility defs");
|
|
2092
|
+
|
|
2093
|
+
let mut instance_side = None;
|
|
2094
|
+
let mut singleton_side = None;
|
|
2095
|
+
for def in defs {
|
|
2096
|
+
let Definition::MethodVisibility(method_vis) = def else {
|
|
2097
|
+
panic!("expected MethodVisibility, got {:?}", def.kind());
|
|
2098
|
+
};
|
|
2099
|
+
if method_vis.flags().is_singleton_method_visibility() {
|
|
2100
|
+
singleton_side = Some(method_vis.as_ref());
|
|
2101
|
+
} else {
|
|
2102
|
+
instance_side = Some(method_vis.as_ref());
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
let instance_side = instance_side.expect("missing instance-side def");
|
|
2107
|
+
assert_def_str_eq!(&context, instance_side, "foo()");
|
|
2108
|
+
assert_eq!(instance_side.visibility(), &Visibility::ModuleFunction);
|
|
2109
|
+
|
|
2110
|
+
let singleton_side = singleton_side.expect("missing singleton-side def");
|
|
2111
|
+
assert_def_str_eq!(&context, singleton_side, "foo()");
|
|
2112
|
+
assert_eq!(singleton_side.visibility(), &Visibility::ModuleFunction);
|
|
2028
2113
|
}
|
|
2029
2114
|
|
|
2030
2115
|
#[test]
|
|
@@ -2041,7 +2126,7 @@ mod visibility_tests {
|
|
|
2041
2126
|
|
|
2042
2127
|
assert_local_diagnostics_eq!(
|
|
2043
2128
|
&context,
|
|
2044
|
-
vec!["
|
|
2129
|
+
vec!["InvalidMethodVisibility: `module_function` can only be used in modules (4:3-4:23)"]
|
|
2045
2130
|
);
|
|
2046
2131
|
|
|
2047
2132
|
for def in context.graph().definitions().values() {
|
|
@@ -2113,8 +2198,8 @@ mod visibility_tests {
|
|
|
2113
2198
|
assert_local_diagnostics_eq!(
|
|
2114
2199
|
&context,
|
|
2115
2200
|
vec![
|
|
2116
|
-
"
|
|
2117
|
-
"
|
|
2201
|
+
"InvalidMethodVisibility: `private` called with a non-literal argument (2:25-2:32)",
|
|
2202
|
+
"InvalidMethodVisibility: `private` called with a non-literal argument (3:11-3:18)",
|
|
2118
2203
|
]
|
|
2119
2204
|
);
|
|
2120
2205
|
|
|
@@ -2144,8 +2229,8 @@ mod visibility_tests {
|
|
|
2144
2229
|
assert_local_diagnostics_eq!(
|
|
2145
2230
|
&context,
|
|
2146
2231
|
vec![
|
|
2147
|
-
"
|
|
2148
|
-
"
|
|
2232
|
+
"InvalidMethodVisibility: `private` called with a non-literal argument (2:11-2:18)",
|
|
2233
|
+
"InvalidMethodVisibility: `private` called with a non-literal argument (2:20-2:27)",
|
|
2149
2234
|
]
|
|
2150
2235
|
);
|
|
2151
2236
|
|
|
@@ -2165,7 +2250,7 @@ mod visibility_tests {
|
|
|
2165
2250
|
// module_function in a class is always invalid regardless of args
|
|
2166
2251
|
assert_local_diagnostics_eq!(
|
|
2167
2252
|
&context,
|
|
2168
|
-
vec!["
|
|
2253
|
+
vec!["InvalidMethodVisibility: `module_function` can only be used in modules (2:3-2:37)"]
|
|
2169
2254
|
);
|
|
2170
2255
|
|
|
2171
2256
|
for def in context.graph().definitions().values() {
|
|
@@ -2251,12 +2336,13 @@ mod visibility_tests {
|
|
|
2251
2336
|
assert_local_diagnostics_eq!(
|
|
2252
2337
|
&context,
|
|
2253
2338
|
vec![
|
|
2254
|
-
"
|
|
2255
|
-
"
|
|
2256
|
-
"
|
|
2257
|
-
"
|
|
2258
|
-
"
|
|
2259
|
-
]
|
|
2339
|
+
"InvalidMethodVisibility: `private_class_method` called at top level (1:1-1:34)",
|
|
2340
|
+
"InvalidMethodVisibility: `private_class_method` called at top level (2:1-2:39)",
|
|
2341
|
+
"InvalidMethodVisibility: `private_class_method` called with a non-literal argument (6:24-6:35)",
|
|
2342
|
+
"InvalidMethodVisibility: `private_class_method` does not accept `attr_*` arguments (8:24-8:41)",
|
|
2343
|
+
"InvalidMethodVisibility: `private_class_method` requires a singleton method definition (9:24-9:39)",
|
|
2344
|
+
],
|
|
2345
|
+
severity: Severity::Warning
|
|
2260
2346
|
);
|
|
2261
2347
|
}
|
|
2262
2348
|
|
|
@@ -2290,7 +2376,7 @@ mod visibility_tests {
|
|
|
2290
2376
|
|
|
2291
2377
|
assert_local_diagnostics_eq!(
|
|
2292
2378
|
&context,
|
|
2293
|
-
vec!["
|
|
2379
|
+
vec!["InvalidMethodVisibility: `private_class_method` called with a non-literal argument (5:28-5:40)"]
|
|
2294
2380
|
);
|
|
2295
2381
|
|
|
2296
2382
|
assert_definition_at!(&context, "5:25-5:26", MethodVisibility, |def| {
|
|
@@ -2311,7 +2397,7 @@ mod visibility_tests {
|
|
|
2311
2397
|
|
|
2312
2398
|
assert_local_diagnostics_eq!(
|
|
2313
2399
|
&context,
|
|
2314
|
-
vec!["
|
|
2400
|
+
vec!["InvalidMethodVisibility: `private_class_method` called at top level (1:1-1:32)"]
|
|
2315
2401
|
);
|
|
2316
2402
|
assert_constant_references_eq!(&context, ["NESTED_REF"]);
|
|
2317
2403
|
}
|
|
@@ -2396,7 +2482,7 @@ mod visibility_tests {
|
|
|
2396
2482
|
assert_local_diagnostics_eq!(
|
|
2397
2483
|
&context,
|
|
2398
2484
|
vec![
|
|
2399
|
-
"
|
|
2485
|
+
"InvalidMethodVisibility: `private_class_method` array element must be a Symbol, String, or method definition (5:32-5:42)"
|
|
2400
2486
|
]
|
|
2401
2487
|
);
|
|
2402
2488
|
|
|
@@ -2424,9 +2510,7 @@ mod visibility_tests {
|
|
|
2424
2510
|
|
|
2425
2511
|
assert_local_diagnostics_eq!(
|
|
2426
2512
|
&context,
|
|
2427
|
-
vec![
|
|
2428
|
-
"invalid-method-visibility: `private_class_method` requires a singleton method definition (2:25-2:49)"
|
|
2429
|
-
]
|
|
2513
|
+
vec!["InvalidMethodVisibility: `private_class_method` requires a singleton method definition (2:25-2:49)"]
|
|
2430
2514
|
);
|
|
2431
2515
|
|
|
2432
2516
|
for def in context.graph().definitions().values() {
|
|
@@ -2458,7 +2542,7 @@ mod visibility_tests {
|
|
|
2458
2542
|
assert_local_diagnostics_eq!(
|
|
2459
2543
|
&context,
|
|
2460
2544
|
vec![
|
|
2461
|
-
"
|
|
2545
|
+
"InvalidMethodVisibility: `private_class_method` array argument must be the only argument (5:24-5:28)"
|
|
2462
2546
|
]
|
|
2463
2547
|
);
|
|
2464
2548
|
|
|
@@ -2761,8 +2845,8 @@ mod constant_reference_tests {
|
|
|
2761
2845
|
assert_local_diagnostics_eq!(
|
|
2762
2846
|
&context,
|
|
2763
2847
|
[
|
|
2764
|
-
"
|
|
2765
|
-
"
|
|
2848
|
+
"DynamicConstantReference: Dynamic constant reference (3:6-3:14)",
|
|
2849
|
+
"ParseWarning: assigned but unused variable - foo (5:1-5:4)",
|
|
2766
2850
|
]
|
|
2767
2851
|
);
|
|
2768
2852
|
|
|
@@ -2945,7 +3029,7 @@ mod method_reference_tests {
|
|
|
2945
3029
|
|
|
2946
3030
|
assert_local_diagnostics_eq!(
|
|
2947
3031
|
&context,
|
|
2948
|
-
["
|
|
3032
|
+
["ParseError: unexpected ... when the parent method is not forwarding (31:5-31:8)"]
|
|
2949
3033
|
);
|
|
2950
3034
|
|
|
2951
3035
|
assert_method_references_eq!(
|
|
@@ -3031,18 +3115,18 @@ mod method_reference_tests {
|
|
|
3031
3115
|
assert_local_diagnostics_eq!(
|
|
3032
3116
|
&context,
|
|
3033
3117
|
[
|
|
3034
|
-
"
|
|
3035
|
-
"
|
|
3036
|
-
"
|
|
3037
|
-
"
|
|
3038
|
-
"
|
|
3039
|
-
"
|
|
3040
|
-
"
|
|
3041
|
-
"
|
|
3042
|
-
"
|
|
3043
|
-
"
|
|
3044
|
-
"
|
|
3045
|
-
"
|
|
3118
|
+
"ParseWarning: possibly useless use of != in void context (1:1-1:7)",
|
|
3119
|
+
"ParseWarning: possibly useless use of % in void context (2:1-2:6)",
|
|
3120
|
+
"ParseWarning: possibly useless use of & in void context (3:1-3:6)",
|
|
3121
|
+
"ParseWarning: possibly useless use of * in void context (5:1-5:6)",
|
|
3122
|
+
"ParseWarning: possibly useless use of ** in void context (6:1-6:7)",
|
|
3123
|
+
"ParseWarning: possibly useless use of + in void context (7:1-7:6)",
|
|
3124
|
+
"ParseWarning: possibly useless use of - in void context (8:1-8:6)",
|
|
3125
|
+
"ParseWarning: possibly useless use of / in void context (9:1-9:6)",
|
|
3126
|
+
"ParseWarning: possibly useless use of == in void context (11:1-11:7)",
|
|
3127
|
+
"ParseWarning: possibly useless use of ^ in void context (14:1-14:6)",
|
|
3128
|
+
"ParseWarning: possibly useless use of | in void context (15:1-15:6)",
|
|
3129
|
+
"ParseWarning: possibly useless use of <=> in void context (17:1-17:8)"
|
|
3046
3130
|
]
|
|
3047
3131
|
);
|
|
3048
3132
|
|
|
@@ -3064,7 +3148,7 @@ mod method_reference_tests {
|
|
|
3064
3148
|
|
|
3065
3149
|
assert_local_diagnostics_eq!(
|
|
3066
3150
|
&context,
|
|
3067
|
-
["
|
|
3151
|
+
["ParseWarning: possibly useless use of < in void context (1:1-1:6)"]
|
|
3068
3152
|
);
|
|
3069
3153
|
|
|
3070
3154
|
assert_method_references_eq!(&context, ["x", "<", "<=>", "y"]);
|
|
@@ -3080,7 +3164,7 @@ mod method_reference_tests {
|
|
|
3080
3164
|
|
|
3081
3165
|
assert_local_diagnostics_eq!(
|
|
3082
3166
|
&context,
|
|
3083
|
-
["
|
|
3167
|
+
["ParseWarning: possibly useless use of <= in void context (1:1-1:7)"]
|
|
3084
3168
|
);
|
|
3085
3169
|
|
|
3086
3170
|
assert_method_references_eq!(&context, ["x", "<=", "<=>", "y"]);
|
|
@@ -3096,7 +3180,7 @@ mod method_reference_tests {
|
|
|
3096
3180
|
|
|
3097
3181
|
assert_local_diagnostics_eq!(
|
|
3098
3182
|
&context,
|
|
3099
|
-
["
|
|
3183
|
+
["ParseWarning: possibly useless use of > in void context (1:1-1:6)"]
|
|
3100
3184
|
);
|
|
3101
3185
|
|
|
3102
3186
|
assert_method_references_eq!(&context, ["x", "<=>", ">", "y"]);
|
|
@@ -3112,7 +3196,7 @@ mod method_reference_tests {
|
|
|
3112
3196
|
|
|
3113
3197
|
assert_local_diagnostics_eq!(
|
|
3114
3198
|
&context,
|
|
3115
|
-
["
|
|
3199
|
+
["ParseWarning: possibly useless use of >= in void context (1:1-1:7)"]
|
|
3116
3200
|
);
|
|
3117
3201
|
|
|
3118
3202
|
assert_method_references_eq!(&context, ["x", "<=>", ">=", "y"]);
|
|
@@ -3616,10 +3700,10 @@ mod superclass_tests {
|
|
|
3616
3700
|
assert_local_diagnostics_eq!(
|
|
3617
3701
|
&context,
|
|
3618
3702
|
[
|
|
3619
|
-
"
|
|
3620
|
-
"
|
|
3621
|
-
"
|
|
3622
|
-
"
|
|
3703
|
+
"DynamicAncestor: Dynamic superclass (1:13-1:24)",
|
|
3704
|
+
"DynamicAncestor: Dynamic superclass (2:13-2:16)",
|
|
3705
|
+
"DynamicConstantReference: Dynamic constant reference (4:13-4:16)",
|
|
3706
|
+
"DynamicAncestor: Dynamic superclass (4:13-4:21)",
|
|
3623
3707
|
]
|
|
3624
3708
|
);
|
|
3625
3709
|
|
|
@@ -3802,15 +3886,15 @@ mod mixin_tests {
|
|
|
3802
3886
|
assert_local_diagnostics_eq!(
|
|
3803
3887
|
&context,
|
|
3804
3888
|
[
|
|
3805
|
-
"
|
|
3806
|
-
"
|
|
3807
|
-
"
|
|
3808
|
-
"
|
|
3809
|
-
"
|
|
3810
|
-
"
|
|
3811
|
-
"
|
|
3812
|
-
"
|
|
3813
|
-
"
|
|
3889
|
+
"DynamicConstantReference: Dynamic constant reference (1:9-1:12)",
|
|
3890
|
+
"DynamicAncestor: Dynamic mixin argument (1:9-1:17)",
|
|
3891
|
+
"DynamicConstantReference: Dynamic constant reference (2:9-2:12)",
|
|
3892
|
+
"DynamicAncestor: Dynamic mixin argument (2:9-2:17)",
|
|
3893
|
+
"DynamicConstantReference: Dynamic constant reference (3:8-3:11)",
|
|
3894
|
+
"DynamicAncestor: Dynamic mixin argument (3:8-3:16)",
|
|
3895
|
+
"DynamicAncestor: Dynamic mixin argument (5:9-5:12)",
|
|
3896
|
+
"DynamicAncestor: Dynamic mixin argument (6:9-6:12)",
|
|
3897
|
+
"DynamicAncestor: Dynamic mixin argument (7:8-7:11)"
|
|
3814
3898
|
]
|
|
3815
3899
|
);
|
|
3816
3900
|
assert!(context.graph().definitions().is_empty());
|
|
@@ -3829,9 +3913,9 @@ mod mixin_tests {
|
|
|
3829
3913
|
assert_local_diagnostics_eq!(
|
|
3830
3914
|
&context,
|
|
3831
3915
|
[
|
|
3832
|
-
"
|
|
3833
|
-
"
|
|
3834
|
-
"
|
|
3916
|
+
"TopLevelMixinSelf: Top level mixin self (1:9-1:13)",
|
|
3917
|
+
"TopLevelMixinSelf: Top level mixin self (2:9-2:13)",
|
|
3918
|
+
"TopLevelMixinSelf: Top level mixin self (3:8-3:12)"
|
|
3835
3919
|
]
|
|
3836
3920
|
);
|
|
3837
3921
|
|
|
@@ -5112,6 +5196,29 @@ mod dynamic_namespace_tests {
|
|
|
5112
5196
|
});
|
|
5113
5197
|
}
|
|
5114
5198
|
|
|
5199
|
+
#[test]
|
|
5200
|
+
fn index_extend_self_in_anonymous_module() {
|
|
5201
|
+
let context = index_source({
|
|
5202
|
+
"
|
|
5203
|
+
Module.new do
|
|
5204
|
+
extend self
|
|
5205
|
+
end
|
|
5206
|
+
"
|
|
5207
|
+
});
|
|
5208
|
+
assert_no_local_diagnostics!(&context);
|
|
5209
|
+
|
|
5210
|
+
assert_definition_at!(&context, "1:1-3:4", Module, |anonymous_module| {
|
|
5211
|
+
let extend = anonymous_module.mixins().first().unwrap();
|
|
5212
|
+
let constant_reference = context
|
|
5213
|
+
.graph()
|
|
5214
|
+
.constant_references()
|
|
5215
|
+
.get(extend.constant_reference_id())
|
|
5216
|
+
.unwrap();
|
|
5217
|
+
|
|
5218
|
+
assert_eq!(anonymous_module.name_id(), constant_reference.name_id());
|
|
5219
|
+
});
|
|
5220
|
+
}
|
|
5221
|
+
|
|
5115
5222
|
#[test]
|
|
5116
5223
|
fn index_singleton_method_in_class_new() {
|
|
5117
5224
|
let context = index_source({
|
|
@@ -5205,9 +5312,10 @@ mod diagnostic_tests {
|
|
|
5205
5312
|
assert_local_diagnostics_eq!(
|
|
5206
5313
|
&context,
|
|
5207
5314
|
[
|
|
5208
|
-
"
|
|
5209
|
-
"
|
|
5210
|
-
]
|
|
5315
|
+
"ParseError: expected an `end` to close the `class` statement (1:1-1:6)",
|
|
5316
|
+
"ParseError: unexpected end-of-input, assuming it is closing the parent top level context (1:10-2:1)"
|
|
5317
|
+
],
|
|
5318
|
+
severity: Severity::Error
|
|
5211
5319
|
);
|
|
5212
5320
|
|
|
5213
5321
|
// We still index the definition, even though it has errors
|
|
@@ -5227,7 +5335,8 @@ mod diagnostic_tests {
|
|
|
5227
5335
|
|
|
5228
5336
|
assert_local_diagnostics_eq!(
|
|
5229
5337
|
&context,
|
|
5230
|
-
["
|
|
5338
|
+
["ParseWarning: assigned but unused variable - foo (1:1-1:4)"],
|
|
5339
|
+
severity: Severity::Warning
|
|
5231
5340
|
);
|
|
5232
5341
|
}
|
|
5233
5342
|
}
|
data/rust/rubydex/src/lib.rs
CHANGED
data/rust/rubydex/src/listing.rs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
use crate::{
|
|
2
2
|
errors::Errors,
|
|
3
3
|
job_queue::{Job, JobQueue},
|
|
4
|
+
path_helpers,
|
|
4
5
|
};
|
|
5
6
|
use crossbeam_channel::{Sender, unbounded};
|
|
6
7
|
use glob::Pattern;
|
|
@@ -129,7 +130,7 @@ pub fn collect_file_paths<S: BuildHasher>(
|
|
|
129
130
|
Arc::new(excluded.iter().filter_map(|entry| Pattern::new(entry).ok()).collect());
|
|
130
131
|
|
|
131
132
|
for path in paths {
|
|
132
|
-
let Ok(path) = std::path::absolute(&path) else {
|
|
133
|
+
let Ok(path) = std::path::absolute(&path).map(path_helpers::simplified) else {
|
|
133
134
|
errors_tx
|
|
134
135
|
.send(Errors::FileError(format!("Failed to resolve path `{path}`")))
|
|
135
136
|
.expect("errors receiver dropped before run completion");
|
|
@@ -420,6 +421,30 @@ mod tests {
|
|
|
420
421
|
assert_eq!(files, [foo.to_str().unwrap().to_string()]);
|
|
421
422
|
}
|
|
422
423
|
|
|
424
|
+
#[cfg(windows)]
|
|
425
|
+
#[test]
|
|
426
|
+
fn collect_files_excludes_a_directory_below_a_verbatim_root() {
|
|
427
|
+
// Exclusions are joined onto the workspace path the configuration resolved, which is spelled plainly. A root
|
|
428
|
+
// given verbatim only matches them once it is spelled that way too.
|
|
429
|
+
let context = Context::new();
|
|
430
|
+
context.touch(&PathBuf::from("excluded").join("skipped.rb"));
|
|
431
|
+
|
|
432
|
+
let mut excluded = HashSet::new();
|
|
433
|
+
excluded.insert(
|
|
434
|
+
context
|
|
435
|
+
.absolute_path_to("excluded")
|
|
436
|
+
.to_string_lossy()
|
|
437
|
+
.replace('\\', "/")
|
|
438
|
+
.into_boxed_str(),
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
let (files, errors) =
|
|
442
|
+
collect_file_paths(vec![format!(r"\\?\{}", context.absolute_path().display())], &excluded);
|
|
443
|
+
|
|
444
|
+
assert!(errors.is_empty());
|
|
445
|
+
assert!(files.is_empty(), "expected the exclusion to apply: {files:?}");
|
|
446
|
+
}
|
|
447
|
+
|
|
423
448
|
#[test]
|
|
424
449
|
fn collect_files_excludes_nested_files_matching_globs() {
|
|
425
450
|
let context = Context::new();
|