diff options
author | David Lattimore <[email protected]> | 2020-07-29 07:01:00 +0100 |
---|---|---|
committer | David Lattimore <[email protected]> | 2020-07-29 07:01:00 +0100 |
commit | 3600c43f49f9901ffc94a139a8a3655944e91e4e (patch) | |
tree | fab3f6475ddb107c5f19834fc914704c930a1392 /crates/ra_ssr/src/tests.rs | |
parent | 5a8124273dd663f7f1ed43b53defc4a2c52dbc12 (diff) |
SSR: Don't mix non-path-based rules with path-based
If any rules contain paths, then we reject any rules that don't contain paths. Allowing a mix leads to strange semantics, since the path-based rules only match things where the path refers to semantically the same thing, whereas the non-path-based rules could match anything. Specifically, if we have a rule like `foo ==>> bar` we only want to match the `foo` that is in the current scope, not any `foo`. However "foo" can be parsed as a pattern (BIND_PAT -> NAME -> IDENT). Allowing such a rule through would result in renaming everything called `foo` to `bar`. It'd also be slow, since without a path, we'd have to use the slow-scan search mechanism.
Diffstat (limited to 'crates/ra_ssr/src/tests.rs')
-rw-r--r-- | crates/ra_ssr/src/tests.rs | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ra_ssr/src/tests.rs index 18ef2506a..851e573ae 100644 --- a/crates/ra_ssr/src/tests.rs +++ b/crates/ra_ssr/src/tests.rs | |||
@@ -887,6 +887,45 @@ fn ufcs_matches_method_call() { | |||
887 | } | 887 | } |
888 | 888 | ||
889 | #[test] | 889 | #[test] |
890 | fn pattern_is_a_single_segment_path() { | ||
891 | mark::check!(pattern_is_a_single_segment_path); | ||
892 | // The first function should not be altered because the `foo` in scope at the cursor position is | ||
893 | // a different `foo`. This case is special because "foo" can be parsed as a pattern (BIND_PAT -> | ||
894 | // NAME -> IDENT), which contains no path. If we're not careful we'll end up matching the `foo` | ||
895 | // in `let foo` from the first function. Whether we should match the `let foo` in the second | ||
896 | // function is less clear. At the moment, we don't. Doing so sounds like a rename operation, | ||
897 | // which isn't really what SSR is for, especially since the replacement `bar` must be able to be | ||
898 | // resolved, which means if we rename `foo` we'll get a name collision. | ||
899 | assert_ssr_transform( | ||
900 | "foo ==>> bar", | ||
901 | r#" | ||
902 | fn f1() -> i32 { | ||
903 | let foo = 1; | ||
904 | let bar = 2; | ||
905 | foo | ||
906 | } | ||
907 | fn f1() -> i32 { | ||
908 | let foo = 1; | ||
909 | let bar = 2; | ||
910 | foo<|> | ||
911 | } | ||
912 | "#, | ||
913 | expect![[r#" | ||
914 | fn f1() -> i32 { | ||
915 | let foo = 1; | ||
916 | let bar = 2; | ||
917 | foo | ||
918 | } | ||
919 | fn f1() -> i32 { | ||
920 | let foo = 1; | ||
921 | let bar = 2; | ||
922 | bar | ||
923 | } | ||
924 | "#]], | ||
925 | ); | ||
926 | } | ||
927 | |||
928 | #[test] | ||
890 | fn replace_local_variable_reference() { | 929 | fn replace_local_variable_reference() { |
891 | // The pattern references a local variable `foo` in the block containing the cursor. We should | 930 | // The pattern references a local variable `foo` in the block containing the cursor. We should |
892 | // only replace references to this variable `foo`, not other variables that just happen to have | 931 | // only replace references to this variable `foo`, not other variables that just happen to have |