diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/assists/src/handlers/extract_module_to_file.rs | 169 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 34 |
2 files changed, 83 insertions, 120 deletions
diff --git a/crates/assists/src/handlers/extract_module_to_file.rs b/crates/assists/src/handlers/extract_module_to_file.rs index 5fc190fa6..3e67fdca2 100644 --- a/crates/assists/src/handlers/extract_module_to_file.rs +++ b/crates/assists/src/handlers/extract_module_to_file.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ast::edit::IndentLevel; | 1 | use ast::edit::IndentLevel; |
2 | use ide_db::base_db::{AnchoredPathBuf, SourceDatabaseExt}; | 2 | use ide_db::base_db::AnchoredPathBuf; |
3 | use syntax::{ | 3 | use syntax::{ |
4 | ast::{self, edit::AstNodeEdit, NameOwner}, | 4 | ast::{self, edit::AstNodeEdit, NameOwner}, |
5 | AstNode, | 5 | AstNode, |
@@ -21,43 +21,44 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
21 | // mod foo; | 21 | // mod foo; |
22 | // ``` | 22 | // ``` |
23 | pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 23 | pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
24 | let assist_id = AssistId("extract_module_to_file", AssistKind::RefactorExtract); | ||
25 | let assist_label = "Extract module to file"; | ||
26 | let db = ctx.db(); | ||
27 | let module_ast = ctx.find_node_at_offset::<ast::Module>()?; | 24 | let module_ast = ctx.find_node_at_offset::<ast::Module>()?; |
28 | let module_items = module_ast.item_list()?; | ||
29 | let dedent_module_items_text = module_items.dedent(IndentLevel(1)).to_string(); | ||
30 | let module_name = module_ast.name()?; | 25 | let module_name = module_ast.name()?; |
26 | |||
27 | let module_def = ctx.sema.to_def(&module_ast)?; | ||
28 | let parent_module = module_def.parent(ctx.db())?; | ||
29 | |||
30 | let module_items = module_ast.item_list()?; | ||
31 | let target = module_ast.syntax().text_range(); | 31 | let target = module_ast.syntax().text_range(); |
32 | let anchor_file_id = ctx.frange.file_id; | 32 | let anchor_file_id = ctx.frange.file_id; |
33 | let sr = db.file_source_root(anchor_file_id); | ||
34 | let sr = db.source_root(sr); | ||
35 | let file_path = sr.path_for_file(&anchor_file_id)?; | ||
36 | let (file_name, file_ext) = file_path.name_and_extension()?; | ||
37 | acc.add(assist_id, assist_label, target, |builder| { | ||
38 | builder.replace(target, format!("mod {};", module_name)); | ||
39 | let path = if is_main_or_lib(file_name) { | ||
40 | format!("./{}.{}", module_name, file_ext.unwrap()) | ||
41 | } else { | ||
42 | format!("./{}/{}.{}", file_name, module_name, file_ext.unwrap()) | ||
43 | }; | ||
44 | let dst = AnchoredPathBuf { anchor: anchor_file_id, path }; | ||
45 | let contents = update_module_items_string(dedent_module_items_text); | ||
46 | builder.create_file(dst, contents); | ||
47 | }) | ||
48 | } | ||
49 | fn is_main_or_lib(file_name: &str) -> bool { | ||
50 | file_name == "main".to_string() || file_name == "lib".to_string() | ||
51 | } | ||
52 | fn update_module_items_string(items_str: String) -> String { | ||
53 | let mut items_string_lines: Vec<&str> = items_str.lines().collect(); | ||
54 | items_string_lines.pop(); // Delete last line | ||
55 | items_string_lines.reverse(); | ||
56 | items_string_lines.pop(); // Delete first line | ||
57 | items_string_lines.reverse(); | ||
58 | 33 | ||
59 | let string = items_string_lines.join("\n"); | 34 | acc.add( |
60 | format!("{}", string) | 35 | AssistId("extract_module_to_file", AssistKind::RefactorExtract), |
36 | "Extract module to file", | ||
37 | target, | ||
38 | |builder| { | ||
39 | let path = { | ||
40 | let dir = match parent_module.name(ctx.db()) { | ||
41 | Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name), | ||
42 | _ => String::new(), | ||
43 | }; | ||
44 | format!("./{}{}.rs", dir, module_name) | ||
45 | }; | ||
46 | let contents = { | ||
47 | let items = module_items.dedent(IndentLevel(1)).to_string(); | ||
48 | let mut items = | ||
49 | items.trim_start_matches('{').trim_end_matches('}').trim().to_string(); | ||
50 | if !items.is_empty() { | ||
51 | items.push('\n'); | ||
52 | } | ||
53 | items | ||
54 | }; | ||
55 | |||
56 | builder.replace(target, format!("mod {};", module_name)); | ||
57 | |||
58 | let dst = AnchoredPathBuf { anchor: anchor_file_id, path }; | ||
59 | builder.create_file(dst, contents); | ||
60 | }, | ||
61 | ) | ||
61 | } | 62 | } |
62 | 63 | ||
63 | #[cfg(test)] | 64 | #[cfg(test)] |
@@ -67,104 +68,66 @@ mod tests { | |||
67 | use super::*; | 68 | use super::*; |
68 | 69 | ||
69 | #[test] | 70 | #[test] |
70 | fn extract_module_to_file_with_basic_module() { | 71 | fn extract_from_root() { |
71 | check_assist( | 72 | check_assist( |
72 | extract_module_to_file, | 73 | extract_module_to_file, |
73 | r#" | 74 | r#" |
74 | //- /foo.rs crate:foo | ||
75 | mod tests {<|> | 75 | mod tests {<|> |
76 | #[test] fn t() {} | 76 | #[test] fn t() {} |
77 | } | 77 | } |
78 | "#, | 78 | "#, |
79 | r#" | 79 | r#" |
80 | //- /foo.rs | 80 | //- /main.rs |
81 | mod tests; | 81 | mod tests; |
82 | //- /foo/tests.rs | 82 | //- /tests.rs |
83 | #[test] fn t() {}"#, | 83 | #[test] fn t() {} |
84 | ) | ||
85 | } | ||
86 | |||
87 | #[test] | ||
88 | fn extract_module_to_file_with_file_path() { | ||
89 | check_assist( | ||
90 | extract_module_to_file, | ||
91 | r#" | ||
92 | //- /src/foo.rs crate:foo | ||
93 | mod bar {<|> | ||
94 | fn f() { | ||
95 | |||
96 | } | ||
97 | } | ||
98 | fn main() { | ||
99 | println!("Hello, world!"); | ||
100 | } | ||
101 | "#, | 84 | "#, |
102 | r#" | 85 | ); |
103 | //- /src/foo.rs | ||
104 | mod bar; | ||
105 | fn main() { | ||
106 | println!("Hello, world!"); | ||
107 | } | ||
108 | //- /src/foo/bar.rs | ||
109 | fn f() { | ||
110 | |||
111 | }"#, | ||
112 | ) | ||
113 | } | 86 | } |
114 | 87 | ||
115 | #[test] | 88 | #[test] |
116 | fn extract_module_to_file_with_main_filw() { | 89 | fn extract_from_submodule() { |
117 | check_assist( | 90 | check_assist( |
118 | extract_module_to_file, | 91 | extract_module_to_file, |
119 | r#" | 92 | r#" |
120 | //- /main.rs | 93 | //- /main.rs |
121 | mod foo {<|> | 94 | mod submodule; |
122 | fn f() { | 95 | //- /submodule.rs |
123 | 96 | mod inner<|> { | |
124 | } | 97 | fn f() {} |
125 | } | ||
126 | fn main() { | ||
127 | println!("Hello, world!"); | ||
128 | } | 98 | } |
99 | fn g() {} | ||
129 | "#, | 100 | "#, |
130 | r#" | 101 | r#" |
131 | //- /main.rs | 102 | //- /submodule.rs |
132 | mod foo; | 103 | mod inner; |
133 | fn main() { | 104 | fn g() {} |
134 | println!("Hello, world!"); | 105 | //- /submodule/inner.rs |
135 | } | 106 | fn f() {} |
136 | //- /foo.rs | 107 | "#, |
137 | fn f() { | 108 | ); |
138 | |||
139 | }"#, | ||
140 | ) | ||
141 | } | 109 | } |
142 | 110 | ||
143 | #[test] | 111 | #[test] |
144 | fn extract_module_to_file_with_lib_file() { | 112 | fn extract_from_mod_rs() { |
145 | check_assist( | 113 | check_assist( |
146 | extract_module_to_file, | 114 | extract_module_to_file, |
147 | r#" | 115 | r#" |
148 | //- /lib.rs | 116 | //- /main.rs |
149 | mod foo {<|> | 117 | mod submodule; |
150 | fn f() { | 118 | //- /submodule/mod.rs |
151 | 119 | mod inner<|> { | |
152 | } | 120 | fn f() {} |
153 | } | ||
154 | fn main() { | ||
155 | println!("Hello, world!"); | ||
156 | } | 121 | } |
122 | fn g() {} | ||
157 | "#, | 123 | "#, |
158 | r#" | 124 | r#" |
159 | //- /lib.rs | 125 | //- /submodule/mod.rs |
160 | mod foo; | 126 | mod inner; |
161 | fn main() { | 127 | fn g() {} |
162 | println!("Hello, world!"); | 128 | //- /submodule/inner.rs |
163 | } | 129 | fn f() {} |
164 | //- /foo.rs | 130 | "#, |
165 | fn f() { | 131 | ); |
166 | |||
167 | }"#, | ||
168 | ) | ||
169 | } | 132 | } |
170 | } | 133 | } |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 1f4b5c24c..11cdae57f 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -33,7 +33,7 @@ config_data! { | |||
33 | callInfo_full: bool = "true", | 33 | callInfo_full: bool = "true", |
34 | 34 | ||
35 | /// Automatically refresh project info via `cargo metadata` on | 35 | /// Automatically refresh project info via `cargo metadata` on |
36 | /// Cargo.toml changes. | 36 | /// `Cargo.toml` changes. |
37 | cargo_autoreload: bool = "true", | 37 | cargo_autoreload: bool = "true", |
38 | /// Activate all available features. | 38 | /// Activate all available features. |
39 | cargo_allFeatures: bool = "false", | 39 | cargo_allFeatures: bool = "false", |
@@ -52,7 +52,7 @@ config_data! { | |||
52 | /// Run specified `cargo check` command for diagnostics on save. | 52 | /// Run specified `cargo check` command for diagnostics on save. |
53 | checkOnSave_enable: bool = "true", | 53 | checkOnSave_enable: bool = "true", |
54 | /// Check with all features (will be passed as `--all-features`). | 54 | /// Check with all features (will be passed as `--all-features`). |
55 | /// Defaults to `rust-analyzer.cargo.allFeatures`. | 55 | /// Defaults to `#rust-analyzer.cargo.allFeatures#`. |
56 | checkOnSave_allFeatures: Option<bool> = "null", | 56 | checkOnSave_allFeatures: Option<bool> = "null", |
57 | /// Check all targets and tests (will be passed as `--all-targets`). | 57 | /// Check all targets and tests (will be passed as `--all-targets`). |
58 | checkOnSave_allTargets: bool = "true", | 58 | checkOnSave_allTargets: bool = "true", |
@@ -61,12 +61,12 @@ config_data! { | |||
61 | /// Do not activate the `default` feature. | 61 | /// Do not activate the `default` feature. |
62 | checkOnSave_noDefaultFeatures: Option<bool> = "null", | 62 | checkOnSave_noDefaultFeatures: Option<bool> = "null", |
63 | /// Check for a specific target. Defaults to | 63 | /// Check for a specific target. Defaults to |
64 | /// `rust-analyzer.cargo.target`. | 64 | /// `#rust-analyzer.cargo.target#`. |
65 | checkOnSave_target: Option<String> = "null", | 65 | checkOnSave_target: Option<String> = "null", |
66 | /// Extra arguments for `cargo check`. | 66 | /// Extra arguments for `cargo check`. |
67 | checkOnSave_extraArgs: Vec<String> = "[]", | 67 | checkOnSave_extraArgs: Vec<String> = "[]", |
68 | /// List of features to activate. Defaults to | 68 | /// List of features to activate. Defaults to |
69 | /// `rust-analyzer.cargo.features`. | 69 | /// `#rust-analyzer.cargo.features#`. |
70 | checkOnSave_features: Option<Vec<String>> = "null", | 70 | checkOnSave_features: Option<Vec<String>> = "null", |
71 | /// Advanced option, fully override the command rust-analyzer uses for | 71 | /// Advanced option, fully override the command rust-analyzer uses for |
72 | /// checking. The command should include `--message-format=json` or | 72 | /// checking. The command should include `--message-format=json` or |
@@ -80,7 +80,7 @@ config_data! { | |||
80 | /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. | 80 | /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. |
81 | completion_postfix_enable: bool = "true", | 81 | completion_postfix_enable: bool = "true", |
82 | /// Toggles the additional completions that automatically add imports when completed. | 82 | /// Toggles the additional completions that automatically add imports when completed. |
83 | /// Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled. | 83 | /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled. |
84 | completion_autoimport_enable: bool = "true", | 84 | completion_autoimport_enable: bool = "true", |
85 | 85 | ||
86 | /// Whether to show native rust-analyzer diagnostics. | 86 | /// Whether to show native rust-analyzer diagnostics. |
@@ -90,13 +90,13 @@ config_data! { | |||
90 | diagnostics_enableExperimental: bool = "true", | 90 | diagnostics_enableExperimental: bool = "true", |
91 | /// List of rust-analyzer diagnostics to disable. | 91 | /// List of rust-analyzer diagnostics to disable. |
92 | diagnostics_disabled: FxHashSet<String> = "[]", | 92 | diagnostics_disabled: FxHashSet<String> = "[]", |
93 | /// List of warnings that should be displayed with info severity.\nThe | 93 | /// List of warnings that should be displayed with info severity.\n\nThe |
94 | /// warnings will be indicated by a blue squiggly underline in code and | 94 | /// warnings will be indicated by a blue squiggly underline in code and |
95 | /// a blue icon in the problems panel. | 95 | /// a blue icon in the `Problems Panel`. |
96 | diagnostics_warningsAsHint: Vec<String> = "[]", | 96 | diagnostics_warningsAsHint: Vec<String> = "[]", |
97 | /// List of warnings that should be displayed with hint severity.\nThe | 97 | /// List of warnings that should be displayed with hint severity.\n\nThe |
98 | /// warnings will be indicated by faded text or three dots in code and | 98 | /// warnings will be indicated by faded text or three dots in code and |
99 | /// will not show up in the problems panel. | 99 | /// will not show up in the `Problems Panel`. |
100 | diagnostics_warningsAsInfo: Vec<String> = "[]", | 100 | diagnostics_warningsAsInfo: Vec<String> = "[]", |
101 | 101 | ||
102 | /// Controls file watching implementation. | 102 | /// Controls file watching implementation. |
@@ -121,7 +121,7 @@ config_data! { | |||
121 | 121 | ||
122 | /// Whether to show inlay type hints for method chains. | 122 | /// Whether to show inlay type hints for method chains. |
123 | inlayHints_chainingHints: bool = "true", | 123 | inlayHints_chainingHints: bool = "true", |
124 | /// Maximum length for inlay hints. | 124 | /// Maximum length for inlay hints. Default is unlimited. |
125 | inlayHints_maxLength: Option<usize> = "null", | 125 | inlayHints_maxLength: Option<usize> = "null", |
126 | /// Whether to show function parameter name inlay hints at the call | 126 | /// Whether to show function parameter name inlay hints at the call |
127 | /// site. | 127 | /// site. |
@@ -145,27 +145,27 @@ config_data! { | |||
145 | lens_methodReferences: bool = "false", | 145 | lens_methodReferences: bool = "false", |
146 | 146 | ||
147 | /// Disable project auto-discovery in favor of explicitly specified set | 147 | /// Disable project auto-discovery in favor of explicitly specified set |
148 | /// of projects. \nElements must be paths pointing to Cargo.toml, | 148 | /// of projects.\n\nElements must be paths pointing to `Cargo.toml`, |
149 | /// rust-project.json, or JSON objects in rust-project.json format. | 149 | /// `rust-project.json`, or JSON objects in `rust-project.json` format. |
150 | linkedProjects: Vec<ManifestOrProjectJson> = "[]", | 150 | linkedProjects: Vec<ManifestOrProjectJson> = "[]", |
151 | /// Number of syntax trees rust-analyzer keeps in memory. | 151 | /// Number of syntax trees rust-analyzer keeps in memory. Defaults to 128. |
152 | lruCapacity: Option<usize> = "null", | 152 | lruCapacity: Option<usize> = "null", |
153 | /// Whether to show `can't find Cargo.toml` error message. | 153 | /// Whether to show `can't find Cargo.toml` error message. |
154 | notifications_cargoTomlNotFound: bool = "true", | 154 | notifications_cargoTomlNotFound: bool = "true", |
155 | /// Enable Proc macro support, cargo.loadOutDirsFromCheck must be | 155 | /// Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be |
156 | /// enabled. | 156 | /// enabled. |
157 | procMacro_enable: bool = "false", | 157 | procMacro_enable: bool = "false", |
158 | 158 | ||
159 | /// Command to be executed instead of 'cargo' for runnables. | 159 | /// Command to be executed instead of 'cargo' for runnables. |
160 | runnables_overrideCargo: Option<String> = "null", | 160 | runnables_overrideCargo: Option<String> = "null", |
161 | /// Additional arguments to be passed to cargo for runnables such as | 161 | /// Additional arguments to be passed to cargo for runnables such as |
162 | /// tests or binaries.\nFor example, it may be '--release'. | 162 | /// tests or binaries.\nFor example, it may be `--release`. |
163 | runnables_cargoExtraArgs: Vec<String> = "[]", | 163 | runnables_cargoExtraArgs: Vec<String> = "[]", |
164 | 164 | ||
165 | /// Path to the rust compiler sources, for usage in rustc_private projects. | 165 | /// Path to the rust compiler sources, for usage in rustc_private projects. |
166 | rustcSource : Option<String> = "null", | 166 | rustcSource : Option<String> = "null", |
167 | 167 | ||
168 | /// Additional arguments to rustfmt. | 168 | /// Additional arguments to `rustfmt`. |
169 | rustfmt_extraArgs: Vec<String> = "[]", | 169 | rustfmt_extraArgs: Vec<String> = "[]", |
170 | /// Advanced option, fully override the command rust-analyzer uses for | 170 | /// Advanced option, fully override the command rust-analyzer uses for |
171 | /// formatting. | 171 | /// formatting. |
@@ -758,7 +758,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json | |||
758 | ], | 758 | ], |
759 | "enumDescriptions": [ | 759 | "enumDescriptions": [ |
760 | "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.", | 760 | "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.", |
761 | "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name", | 761 | "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name.", |
762 | "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to." | 762 | "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to." |
763 | ], | 763 | ], |
764 | }, | 764 | }, |