aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock191
-rw-r--r--crates/ra_assists/src/assist_ctx.rs52
-rw-r--r--crates/ra_assists/src/assists/add_derive.rs30
-rw-r--r--crates/ra_assists/src/assists/add_explicit_type.rs27
-rw-r--r--crates/ra_assists/src/assists/add_impl.rs31
-rw-r--r--crates/ra_assists/src/assists/add_import.rs (renamed from crates/ra_assists/src/assists/auto_import.rs)249
-rw-r--r--crates/ra_assists/src/assists/add_missing_impl_members.rs72
-rw-r--r--crates/ra_assists/src/assists/apply_demorgan.rs37
-rw-r--r--crates/ra_assists/src/assists/change_visibility.rs33
-rw-r--r--crates/ra_assists/src/assists/early_return.rs56
-rw-r--r--crates/ra_assists/src/assists/fill_match_arms.rs38
-rw-r--r--crates/ra_assists/src/assists/flip_binexpr.rs28
-rw-r--r--crates/ra_assists/src/assists/flip_comma.rs27
-rw-r--r--crates/ra_assists/src/assists/flip_trait_bound.rs117
-rw-r--r--crates/ra_assists/src/assists/inline_local_variable.rs34
-rw-r--r--crates/ra_assists/src/assists/introduce_variable.rs26
-rw-r--r--crates/ra_assists/src/assists/merge_match_arms.rs36
-rw-r--r--crates/ra_assists/src/assists/move_bounds.rs77
-rw-r--r--crates/ra_assists/src/assists/move_guard.rs70
-rw-r--r--crates/ra_assists/src/assists/raw_string.rs227
-rw-r--r--crates/ra_assists/src/assists/remove_dbg.rs30
-rw-r--r--crates/ra_assists/src/assists/replace_if_let_with_match.rs38
-rw-r--r--crates/ra_assists/src/assists/split_import.rs23
-rw-r--r--crates/ra_assists/src/doc_tests.rs34
-rw-r--r--crates/ra_assists/src/doc_tests/generated.rs526
-rw-r--r--crates/ra_assists/src/lib.rs95
-rw-r--r--crates/ra_db/src/lib.rs5
-rw-r--r--crates/ra_hir/Cargo.toml8
-rw-r--r--crates/ra_hir/src/adt.rs11
-rw-r--r--crates/ra_hir/src/code_model.rs182
-rw-r--r--crates/ra_hir/src/code_model/src.rs30
-rw-r--r--crates/ra_hir/src/db.rs94
-rw-r--r--crates/ra_hir/src/debug.rs6
-rw-r--r--crates/ra_hir/src/expr.rs6
-rw-r--r--crates/ra_hir/src/expr/lower.rs26
-rw-r--r--crates/ra_hir/src/expr/validation.rs2
-rw-r--r--crates/ra_hir/src/from_source.rs52
-rw-r--r--crates/ra_hir/src/generics.rs20
-rw-r--r--crates/ra_hir/src/ids.rs363
-rw-r--r--crates/ra_hir/src/impl_block.rs24
-rw-r--r--crates/ra_hir/src/lang_item.rs16
-rw-r--r--crates/ra_hir/src/lib.rs40
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/mock.rs1
-rw-r--r--crates/ra_hir/src/nameres.rs51
-rw-r--r--crates/ra_hir/src/nameres/collector.rs56
-rw-r--r--crates/ra_hir/src/nameres/tests/mod_resolution.rs2
-rw-r--r--crates/ra_hir/src/resolve.rs41
-rw-r--r--crates/ra_hir/src/source_binder.rs73
-rw-r--r--crates/ra_hir/src/traits.rs7
-rw-r--r--crates/ra_hir/src/ty.rs4
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs3
-rw-r--r--crates/ra_hir/src/ty/infer.rs8
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs3
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs5
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs6
-rw-r--r--crates/ra_hir/src/ty/lower.rs23
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs15
-rw-r--r--crates/ra_hir/src/ty/primitive.rs22
-rw-r--r--crates/ra_hir/src/ty/traits.rs6
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs157
-rw-r--r--crates/ra_hir/src/type_alias.rs5
-rw-r--r--crates/ra_hir_def/Cargo.toml21
-rw-r--r--crates/ra_hir_def/src/attr.rs (renamed from crates/ra_hir/src/attr.rs)28
-rw-r--r--crates/ra_hir_def/src/builtin_type.rs63
-rw-r--r--crates/ra_hir_def/src/db.rs40
-rw-r--r--crates/ra_hir_def/src/lib.rs362
-rw-r--r--crates/ra_hir_def/src/nameres.rs5
-rw-r--r--crates/ra_hir_def/src/nameres/mod_resolution.rs (renamed from crates/ra_hir/src/nameres/mod_resolution.rs)30
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs (renamed from crates/ra_hir/src/nameres/raw.rs)109
-rw-r--r--crates/ra_hir_def/src/path.rs (renamed from crates/ra_hir/src/path.rs)115
-rw-r--r--crates/ra_hir_def/src/type_ref.rs (renamed from crates/ra_hir/src/type_ref.rs)8
-rw-r--r--crates/ra_hir_expand/Cargo.toml15
-rw-r--r--crates/ra_hir_expand/src/ast_id_map.rs (renamed from crates/ra_hir/src/source_id.rs)115
-rw-r--r--crates/ra_hir_expand/src/db.rs104
-rw-r--r--crates/ra_hir_expand/src/either.rs (renamed from crates/ra_hir/src/either.rs)0
-rw-r--r--crates/ra_hir_expand/src/hygiene.rs46
-rw-r--r--crates/ra_hir_expand/src/lib.rs153
-rw-r--r--crates/ra_hir_expand/src/name.rs (renamed from crates/ra_hir/src/name.rs)78
-rw-r--r--crates/ra_ide_api/Cargo.toml5
-rw-r--r--crates/ra_ide_api/src/call_info.rs183
-rw-r--r--crates/ra_ide_api/src/change.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs4
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs6
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs12
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs74
-rw-r--r--crates/ra_ide_api/src/db.rs1
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs9
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs112
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs82
-rw-r--r--crates/ra_ide_api/src/impls.rs4
-rw-r--r--crates/ra_ide_api/src/lib.rs129
-rw-r--r--crates/ra_ide_api/src/parent_module.rs5
-rw-r--r--crates/ra_ide_api/src/references/rename.rs24
-rw-r--r--crates/ra_ide_api/src/references/search_scope.rs7
-rw-r--r--crates/ra_ide_api/src/runnables.rs14
-rw-r--r--crates/ra_ide_api/src/source_change.rs119
-rw-r--r--crates/ra_ide_api/src/typing.rs359
-rw-r--r--crates/ra_lsp_server/src/caps.rs2
-rw-r--r--crates/ra_lsp_server/src/config.rs14
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs35
-rw-r--r--crates/ra_mbe/src/mbe_expander/matcher.rs3
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs2
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs3
-rw-r--r--crates/ra_syntax/src/ast.rs24
-rw-r--r--crates/ra_syntax/src/ast/make.rs6
-rw-r--r--crates/ra_syntax/src/ast/traits.rs19
-rw-r--r--crates/ra_syntax/src/lib.rs14
-rw-r--r--crates/ra_syntax/test_data/parser/err/0024_many_type_parens.txt91
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.txt101
-rw-r--r--crates/ra_text_edit/src/text_edit.rs18
-rw-r--r--crates/test_utils/src/lib.rs34
-rw-r--r--docs/dev/README.md2
-rw-r--r--docs/user/README.md19
-rw-r--r--docs/user/assists.md505
-rw-r--r--docs/user/features.md424
-rw-r--r--editors/code/package.json5
-rw-r--r--editors/code/src/config.ts7
-rw-r--r--editors/code/src/extension.ts2
-rw-r--r--editors/code/src/server.ts2
-rw-r--r--xtask/src/codegen.rs72
-rw-r--r--xtask/src/codegen/gen_assists_docs.rs137
-rw-r--r--xtask/src/codegen/gen_parser_tests.rs71
-rw-r--r--xtask/src/codegen/gen_syntax.rs25
-rw-r--r--xtask/src/main.rs26
-rw-r--r--xtask/tests/tidy-tests/cli.rs7
-rw-r--r--xtask/tests/tidy-tests/docs.rs6
129 files changed, 4949 insertions, 2755 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c902caeb4..fdacd82a7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -108,8 +108,8 @@ version = "0.9.0"
108source = "registry+https://github.com/rust-lang/crates.io-index" 108source = "registry+https://github.com/rust-lang/crates.io-index"
109dependencies = [ 109dependencies = [
110 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 110 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
111 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 111 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
112 "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 112 "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
113 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 113 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
114] 114]
115 115
@@ -124,11 +124,21 @@ version = "0.1.10"
124source = "registry+https://github.com/rust-lang/crates.io-index" 124source = "registry+https://github.com/rust-lang/crates.io-index"
125 125
126[[package]] 126[[package]]
127name = "chalk-derive"
128version = "0.1.0"
129source = "git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809#8314f2fcec8582a58c24b638f1a259d4145a0809"
130dependencies = [
131 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
132 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
133 "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
134]
135
136[[package]]
127name = "chalk-engine" 137name = "chalk-engine"
128version = "0.9.0" 138version = "0.9.0"
129source = "git+https://github.com/rust-lang/chalk.git#13303bb0067c6ed0572322080ae367ee38f9e7c9" 139source = "git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809#8314f2fcec8582a58c24b638f1a259d4145a0809"
130dependencies = [ 140dependencies = [
131 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)", 141 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
132 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 142 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
133 "stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 143 "stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
134] 144]
@@ -136,17 +146,18 @@ dependencies = [
136[[package]] 146[[package]]
137name = "chalk-ir" 147name = "chalk-ir"
138version = "0.1.0" 148version = "0.1.0"
139source = "git+https://github.com/rust-lang/chalk.git#13303bb0067c6ed0572322080ae367ee38f9e7c9" 149source = "git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809#8314f2fcec8582a58c24b638f1a259d4145a0809"
140dependencies = [ 150dependencies = [
141 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)", 151 "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
142 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)", 152 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
153 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
143 "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", 154 "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
144] 155]
145 156
146[[package]] 157[[package]]
147name = "chalk-macros" 158name = "chalk-macros"
148version = "0.1.1" 159version = "0.1.1"
149source = "git+https://github.com/rust-lang/chalk.git#13303bb0067c6ed0572322080ae367ee38f9e7c9" 160source = "git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809#8314f2fcec8582a58c24b638f1a259d4145a0809"
150dependencies = [ 161dependencies = [
151 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 162 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
152] 163]
@@ -154,24 +165,25 @@ dependencies = [
154[[package]] 165[[package]]
155name = "chalk-rust-ir" 166name = "chalk-rust-ir"
156version = "0.1.0" 167version = "0.1.0"
157source = "git+https://github.com/rust-lang/chalk.git#13303bb0067c6ed0572322080ae367ee38f9e7c9" 168source = "git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809#8314f2fcec8582a58c24b638f1a259d4145a0809"
158dependencies = [ 169dependencies = [
159 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)", 170 "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
160 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", 171 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
161 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)", 172 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
173 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
162] 174]
163 175
164[[package]] 176[[package]]
165name = "chalk-solve" 177name = "chalk-solve"
166version = "0.1.0" 178version = "0.1.0"
167source = "git+https://github.com/rust-lang/chalk.git#13303bb0067c6ed0572322080ae367ee38f9e7c9" 179source = "git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809#8314f2fcec8582a58c24b638f1a259d4145a0809"
168dependencies = [ 180dependencies = [
169 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)", 181 "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
170 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", 182 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
171 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)", 183 "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
172 "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", 184 "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
173 "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", 185 "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
174 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 186 "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
175 "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", 187 "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
176 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 188 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
177] 189]
@@ -288,7 +300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
288dependencies = [ 300dependencies = [
289 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 301 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
290 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 302 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
291 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 303 "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
292] 304]
293 305
294[[package]] 306[[package]]
@@ -413,7 +425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
413 425
414[[package]] 426[[package]]
415name = "getrandom" 427name = "getrandom"
416version = "0.1.12" 428version = "0.1.13"
417source = "registry+https://github.com/rust-lang/crates.io-index" 429source = "registry+https://github.com/rust-lang/crates.io-index"
418dependencies = [ 430dependencies = [
419 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 431 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -443,7 +455,7 @@ name = "heck"
443version = "0.3.1" 455version = "0.3.1"
444source = "registry+https://github.com/rust-lang/crates.io-index" 456source = "registry+https://github.com/rust-lang/crates.io-index"
445dependencies = [ 457dependencies = [
446 "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 458 "unicode-segmentation 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
447] 459]
448 460
449[[package]] 461[[package]]
@@ -501,7 +513,7 @@ dependencies = [
501 "console 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 513 "console 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
502 "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 514 "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
503 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 515 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
504 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 516 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
505 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 517 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
506 "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", 518 "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)",
507 "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 519 "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -517,7 +529,7 @@ dependencies = [
517 529
518[[package]] 530[[package]]
519name = "itertools" 531name = "itertools"
520version = "0.8.0" 532version = "0.8.1"
521source = "registry+https://github.com/rust-lang/crates.io-index" 533source = "registry+https://github.com/rust-lang/crates.io-index"
522dependencies = [ 534dependencies = [
523 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 535 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -624,7 +636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
624dependencies = [ 636dependencies = [
625 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 637 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
626 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 638 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
627 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 639 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
628 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 640 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
629] 641]
630 642
@@ -634,7 +646,7 @@ version = "0.61.0"
634source = "registry+https://github.com/rust-lang/crates.io-index" 646source = "registry+https://github.com/rust-lang/crates.io-index"
635dependencies = [ 647dependencies = [
636 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 648 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
637 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 649 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
638 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 650 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
639 "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 651 "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
640 "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 652 "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -790,7 +802,7 @@ dependencies = [
790 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 802 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
791 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 803 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
792 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 804 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
793 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 805 "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
794 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 806 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
795] 807]
796 808
@@ -811,7 +823,7 @@ dependencies = [
811 "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", 823 "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)",
812 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 824 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
813 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 825 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
814 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 826 "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
815] 827]
816 828
817[[package]] 829[[package]]
@@ -845,7 +857,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
845dependencies = [ 857dependencies = [
846 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 858 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
847 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 859 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
848 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 860 "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
849] 861]
850 862
851[[package]] 863[[package]]
@@ -903,7 +915,7 @@ name = "ra_assists"
903version = "0.1.0" 915version = "0.1.0"
904dependencies = [ 916dependencies = [
905 "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 917 "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
906 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 918 "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
907 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 919 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
908 "ra_db 0.1.0", 920 "ra_db 0.1.0",
909 "ra_fmt 0.1.0", 921 "ra_fmt 0.1.0",
@@ -970,7 +982,7 @@ dependencies = [
970name = "ra_fmt" 982name = "ra_fmt"
971version = "0.1.0" 983version = "0.1.0"
972dependencies = [ 984dependencies = [
973 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 985 "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
974 "ra_syntax 0.1.0", 986 "ra_syntax 0.1.0",
975] 987]
976 988
@@ -979,9 +991,9 @@ name = "ra_hir"
979version = "0.1.0" 991version = "0.1.0"
980dependencies = [ 992dependencies = [
981 "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 993 "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
982 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", 994 "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
983 "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)", 995 "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
984 "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git)", 996 "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)",
985 "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", 997 "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
986 "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 998 "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
987 "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", 999 "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -991,6 +1003,27 @@ dependencies = [
991 "ra_arena 0.1.0", 1003 "ra_arena 0.1.0",
992 "ra_cfg 0.1.0", 1004 "ra_cfg 0.1.0",
993 "ra_db 0.1.0", 1005 "ra_db 0.1.0",
1006 "ra_hir_def 0.1.0",
1007 "ra_hir_expand 0.1.0",
1008 "ra_mbe 0.1.0",
1009 "ra_prof 0.1.0",
1010 "ra_syntax 0.1.0",
1011 "ra_tt 0.1.0",
1012 "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1013 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1014 "test_utils 0.1.0",
1015]
1016
1017[[package]]
1018name = "ra_hir_def"
1019version = "0.1.0"
1020dependencies = [
1021 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1022 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1023 "ra_arena 0.1.0",
1024 "ra_cfg 0.1.0",
1025 "ra_db 0.1.0",
1026 "ra_hir_expand 0.1.0",
994 "ra_mbe 0.1.0", 1027 "ra_mbe 0.1.0",
995 "ra_prof 0.1.0", 1028 "ra_prof 0.1.0",
996 "ra_syntax 0.1.0", 1029 "ra_syntax 0.1.0",
@@ -1001,13 +1034,26 @@ dependencies = [
1001] 1034]
1002 1035
1003[[package]] 1036[[package]]
1037name = "ra_hir_expand"
1038version = "0.1.0"
1039dependencies = [
1040 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1041 "ra_arena 0.1.0",
1042 "ra_db 0.1.0",
1043 "ra_mbe 0.1.0",
1044 "ra_prof 0.1.0",
1045 "ra_syntax 0.1.0",
1046 "ra_tt 0.1.0",
1047]
1048
1049[[package]]
1004name = "ra_ide_api" 1050name = "ra_ide_api"
1005version = "0.1.0" 1051version = "0.1.0"
1006dependencies = [ 1052dependencies = [
1007 "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 1053 "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1008 "fst 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 1054 "fst 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1009 "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 1055 "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
1010 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1056 "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
1011 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 1057 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
1012 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1058 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1013 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1059 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1049,7 +1095,7 @@ dependencies = [
1049 "ra_vfs_glob 0.1.0", 1095 "ra_vfs_glob 0.1.0",
1050 "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 1096 "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1051 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1097 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1052 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1098 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1053 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 1099 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
1054 "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1100 "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1055 "test_utils 0.1.0", 1101 "test_utils 0.1.0",
@@ -1065,7 +1111,7 @@ dependencies = [
1065 "ra_syntax 0.1.0", 1111 "ra_syntax 0.1.0",
1066 "ra_tt 0.1.0", 1112 "ra_tt 0.1.0",
1067 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1113 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1068 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 1114 "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
1069 "test_utils 0.1.0", 1115 "test_utils 0.1.0",
1070] 1116]
1071 1117
@@ -1081,7 +1127,7 @@ name = "ra_prof"
1081version = "0.1.0" 1127version = "0.1.0"
1082dependencies = [ 1128dependencies = [
1083 "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", 1129 "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
1084 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1130 "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
1085 "jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 1131 "jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
1086 "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 1132 "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
1087 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1133 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1097,7 +1143,7 @@ dependencies = [
1097 "ra_cfg 0.1.0", 1143 "ra_cfg 0.1.0",
1098 "ra_db 0.1.0", 1144 "ra_db 0.1.0",
1099 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1145 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1100 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1146 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1101 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", 1147 "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
1102] 1148]
1103 1149
@@ -1106,7 +1152,7 @@ name = "ra_syntax"
1106version = "0.1.0" 1152version = "0.1.0"
1107dependencies = [ 1153dependencies = [
1108 "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1154 "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1109 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1155 "itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
1110 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1156 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1111 "ra_parser 0.1.0", 1157 "ra_parser 0.1.0",
1112 "ra_text_edit 0.1.0", 1158 "ra_text_edit 0.1.0",
@@ -1180,7 +1226,7 @@ name = "rand"
1180version = "0.7.2" 1226version = "0.7.2"
1181source = "registry+https://github.com/rust-lang/crates.io-index" 1227source = "registry+https://github.com/rust-lang/crates.io-index"
1182dependencies = [ 1228dependencies = [
1183 "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1229 "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1184 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", 1230 "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
1185 "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 1231 "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1186 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1232 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1224,7 +1270,7 @@ name = "rand_core"
1224version = "0.5.1" 1270version = "0.5.1"
1225source = "registry+https://github.com/rust-lang/crates.io-index" 1271source = "registry+https://github.com/rust-lang/crates.io-index"
1226dependencies = [ 1272dependencies = [
1227 "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1273 "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1228] 1274]
1229 1275
1230[[package]] 1276[[package]]
@@ -1370,7 +1416,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1370dependencies = [ 1416dependencies = [
1371 "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", 1417 "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
1372 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 1418 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1373 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1419 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1374] 1420]
1375 1421
1376[[package]] 1422[[package]]
@@ -1430,7 +1476,7 @@ dependencies = [
1430 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1476 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1431 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1477 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1432 "salsa-macros 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", 1478 "salsa-macros 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
1433 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 1479 "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
1434] 1480]
1435 1481
1436[[package]] 1482[[package]]
@@ -1441,7 +1487,7 @@ dependencies = [
1441 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1487 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1442 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 1488 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
1443 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1489 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1444 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1490 "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1445] 1491]
1446 1492
1447[[package]] 1493[[package]]
@@ -1463,7 +1509,7 @@ version = "0.9.0"
1463source = "registry+https://github.com/rust-lang/crates.io-index" 1509source = "registry+https://github.com/rust-lang/crates.io-index"
1464dependencies = [ 1510dependencies = [
1465 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1511 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1466 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1512 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1467] 1513]
1468 1514
1469[[package]] 1515[[package]]
@@ -1473,20 +1519,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1473 1519
1474[[package]] 1520[[package]]
1475name = "serde" 1521name = "serde"
1476version = "1.0.101" 1522version = "1.0.102"
1477source = "registry+https://github.com/rust-lang/crates.io-index" 1523source = "registry+https://github.com/rust-lang/crates.io-index"
1478dependencies = [ 1524dependencies = [
1479 "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1525 "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1480] 1526]
1481 1527
1482[[package]] 1528[[package]]
1483name = "serde_derive" 1529name = "serde_derive"
1484version = "1.0.101" 1530version = "1.0.102"
1485source = "registry+https://github.com/rust-lang/crates.io-index" 1531source = "registry+https://github.com/rust-lang/crates.io-index"
1486dependencies = [ 1532dependencies = [
1487 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 1533 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
1488 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1534 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1489 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1535 "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1490] 1536]
1491 1537
1492[[package]] 1538[[package]]
@@ -1496,7 +1542,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1496dependencies = [ 1542dependencies = [
1497 "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 1543 "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
1498 "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1544 "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1499 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1545 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1500] 1546]
1501 1547
1502[[package]] 1548[[package]]
@@ -1506,7 +1552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1506dependencies = [ 1552dependencies = [
1507 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 1553 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
1508 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1554 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1509 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1555 "syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1510] 1556]
1511 1557
1512[[package]] 1558[[package]]
@@ -1516,7 +1562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1516dependencies = [ 1562dependencies = [
1517 "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 1563 "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
1518 "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 1564 "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
1519 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1565 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1520 "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 1566 "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
1521] 1567]
1522 1568
@@ -1527,7 +1573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1527 1573
1528[[package]] 1574[[package]]
1529name = "smallvec" 1575name = "smallvec"
1530version = "0.6.10" 1576version = "0.6.11"
1531source = "registry+https://github.com/rust-lang/crates.io-index" 1577source = "registry+https://github.com/rust-lang/crates.io-index"
1532 1578
1533[[package]] 1579[[package]]
@@ -1535,7 +1581,7 @@ name = "smol_str"
1535version = "0.1.15" 1581version = "0.1.15"
1536source = "registry+https://github.com/rust-lang/crates.io-index" 1582source = "registry+https://github.com/rust-lang/crates.io-index"
1537dependencies = [ 1583dependencies = [
1538 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1584 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1539] 1585]
1540 1586
1541[[package]] 1587[[package]]
@@ -1557,7 +1603,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1557 1603
1558[[package]] 1604[[package]]
1559name = "syn" 1605name = "syn"
1560version = "1.0.5" 1606version = "1.0.7"
1561source = "registry+https://github.com/rust-lang/crates.io-index" 1607source = "registry+https://github.com/rust-lang/crates.io-index"
1562dependencies = [ 1608dependencies = [
1563 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 1609 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1647,12 +1693,12 @@ name = "unicode-normalization"
1647version = "0.1.8" 1693version = "0.1.8"
1648source = "registry+https://github.com/rust-lang/crates.io-index" 1694source = "registry+https://github.com/rust-lang/crates.io-index"
1649dependencies = [ 1695dependencies = [
1650 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 1696 "smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
1651] 1697]
1652 1698
1653[[package]] 1699[[package]]
1654name = "unicode-segmentation" 1700name = "unicode-segmentation"
1655version = "1.3.0" 1701version = "1.4.0"
1656source = "registry+https://github.com/rust-lang/crates.io-index" 1702source = "registry+https://github.com/rust-lang/crates.io-index"
1657 1703
1658[[package]] 1704[[package]]
@@ -1673,7 +1719,7 @@ dependencies = [
1673 "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1719 "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1674 "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 1720 "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
1675 "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1721 "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1676 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1722 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1677] 1723]
1678 1724
1679[[package]] 1725[[package]]
@@ -1682,7 +1728,7 @@ version = "0.8.1"
1682source = "registry+https://github.com/rust-lang/crates.io-index" 1728source = "registry+https://github.com/rust-lang/crates.io-index"
1683dependencies = [ 1729dependencies = [
1684 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1730 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1685 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1731 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1686] 1732]
1687 1733
1688[[package]] 1734[[package]]
@@ -1759,7 +1805,7 @@ dependencies = [
1759 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 1805 "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
1760 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1806 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1761 "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1807 "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1762 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", 1808 "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
1763 "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", 1809 "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
1764] 1810]
1765 1811
@@ -1794,11 +1840,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1794"checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d" 1840"checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d"
1795"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c" 1841"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c"
1796"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 1842"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
1797"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1843"checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)" = "<none>"
1798"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1844"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)" = "<none>"
1799"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1845"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)" = "<none>"
1800"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1846"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)" = "<none>"
1801"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1847"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)" = "<none>"
1848"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=8314f2fcec8582a58c24b638f1a259d4145a0809)" = "<none>"
1802"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68" 1849"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68"
1803"checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" 1850"checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e"
1804"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 1851"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
@@ -1828,7 +1875,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1828"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 1875"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
1829"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 1876"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
1830"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 1877"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
1831"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" 1878"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
1832"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" 1879"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
1833"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" 1880"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2"
1834"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 1881"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
@@ -1839,7 +1886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1839"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" 1886"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
1840"checksum insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d499dc062e841590a67230d853bce62d0abeb91304927871670b7c55c461349" 1887"checksum insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d499dc062e841590a67230d853bce62d0abeb91304927871670b7c55c461349"
1841"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 1888"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
1842"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" 1889"checksum itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87fa75c9dea7b07be3138c49abbb83fd4bea199b5cdc76f9804458edc5da0d6e"
1843"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" 1890"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
1844"checksum jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c502a5ff9dd2924f1ed32ba96e3b65735d837b4bfd978d3161b1702e66aca4b7" 1891"checksum jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c502a5ff9dd2924f1ed32ba96e3b65735d837b4bfd978d3161b1702e66aca4b7"
1845"checksum jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45" 1892"checksum jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45"
@@ -1922,17 +1969,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1922"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 1969"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
1923"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1970"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
1924"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 1971"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1925"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" 1972"checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0"
1926"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" 1973"checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8"
1927"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" 1974"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2"
1928"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" 1975"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573"
1929"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" 1976"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
1930"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1977"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1931"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" 1978"checksum smallvec 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cefaa50e76a6f10b86f36e640eb1739eafbd4084865067778463913e43a77ff3"
1932"checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" 1979"checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b"
1933"checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" 1980"checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a"
1934"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" 1981"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
1935"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" 1982"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c"
1936"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" 1983"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
1937"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" 1984"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
1938"checksum text_unit 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e08bbcb7a3adbda0eb23431206b653bdad3d8dea311e72d36bf2215e27a42579" 1985"checksum text_unit 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e08bbcb7a3adbda0eb23431206b653bdad3d8dea311e72d36bf2215e27a42579"
@@ -1942,7 +1989,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1942"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" 1989"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150"
1943"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 1990"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
1944"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" 1991"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
1945"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" 1992"checksum unicode-segmentation 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc5415c074426c7c65db13bd647c23d78c0fb2e10dca0b8fb0f40058a59bccdf"
1946"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" 1993"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
1947"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 1994"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
1948"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" 1995"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index e270c5d60..1908bdec9 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -1,11 +1,11 @@
1//! FIXME: write short doc here 1//! This module defines `AssistCtx` -- the API surface that is exposed to assists.
2 2
3use hir::db::HirDatabase; 3use hir::db::HirDatabase;
4use ra_db::FileRange; 4use ra_db::FileRange;
5use ra_fmt::{leading_indent, reindent}; 5use ra_fmt::{leading_indent, reindent};
6use ra_syntax::{ 6use ra_syntax::{
7 algo::{self, find_covering_element, find_node_at_offset}, 7 algo::{self, find_covering_element, find_node_at_offset},
8 AstNode, SourceFile, SyntaxElement, SyntaxNode, SyntaxToken, TextRange, TextUnit, 8 AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextUnit,
9 TokenAtOffset, 9 TokenAtOffset,
10}; 10};
11use ra_text_edit::TextEditBuilder; 11use ra_text_edit::TextEditBuilder;
@@ -14,8 +14,8 @@ use crate::{AssistAction, AssistId, AssistLabel};
14 14
15#[derive(Clone, Debug)] 15#[derive(Clone, Debug)]
16pub(crate) enum Assist { 16pub(crate) enum Assist {
17 Unresolved(Vec<AssistLabel>), 17 Unresolved { label: AssistLabel },
18 Resolved(Vec<(AssistLabel, AssistAction)>), 18 Resolved { label: AssistLabel, action: AssistAction },
19} 19}
20 20
21/// `AssistCtx` allows to apply an assist or check if it could be applied. 21/// `AssistCtx` allows to apply an assist or check if it could be applied.
@@ -54,7 +54,6 @@ pub(crate) struct AssistCtx<'a, DB> {
54 pub(crate) frange: FileRange, 54 pub(crate) frange: FileRange,
55 source_file: SourceFile, 55 source_file: SourceFile,
56 should_compute_edit: bool, 56 should_compute_edit: bool,
57 assist: Assist,
58} 57}
59 58
60impl<'a, DB> Clone for AssistCtx<'a, DB> { 59impl<'a, DB> Clone for AssistCtx<'a, DB> {
@@ -64,7 +63,6 @@ impl<'a, DB> Clone for AssistCtx<'a, DB> {
64 frange: self.frange, 63 frange: self.frange,
65 source_file: self.source_file.clone(), 64 source_file: self.source_file.clone(),
66 should_compute_edit: self.should_compute_edit, 65 should_compute_edit: self.should_compute_edit,
67 assist: self.assist.clone(),
68 } 66 }
69 } 67 }
70} 68}
@@ -75,43 +73,41 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
75 F: FnOnce(AssistCtx<DB>) -> T, 73 F: FnOnce(AssistCtx<DB>) -> T,
76 { 74 {
77 let parse = db.parse(frange.file_id); 75 let parse = db.parse(frange.file_id);
78 let assist =
79 if should_compute_edit { Assist::Resolved(vec![]) } else { Assist::Unresolved(vec![]) };
80 76
81 let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit, assist }; 77 let ctx = AssistCtx { db, frange, source_file: parse.tree(), should_compute_edit };
82 f(ctx) 78 f(ctx)
83 } 79 }
84 80
85 pub(crate) fn add_action( 81 pub(crate) fn add_assist(
86 &mut self, 82 self,
87 id: AssistId, 83 id: AssistId,
88 label: impl Into<String>, 84 label: impl Into<String>,
89 f: impl FnOnce(&mut AssistBuilder), 85 f: impl FnOnce(&mut AssistBuilder),
90 ) -> &mut Self { 86 ) -> Option<Assist> {
91 let label = AssistLabel { label: label.into(), id }; 87 let label = AssistLabel { label: label.into(), id };
92 match &mut self.assist { 88 let assist = if self.should_compute_edit {
93 Assist::Unresolved(labels) => labels.push(label), 89 let action = {
94 Assist::Resolved(labels_actions) => { 90 let mut edit = AssistBuilder::default();
95 let action = { 91 f(&mut edit);
96 let mut edit = AssistBuilder::default(); 92 edit.build()
97 f(&mut edit); 93 };
98 edit.build() 94 Assist::Resolved { label, action }
99 }; 95 } else {
100 labels_actions.push((label, action)); 96 Assist::Unresolved { label }
101 } 97 };
102 }
103 self
104 }
105 98
106 pub(crate) fn build(self) -> Option<Assist> { 99 Some(assist)
107 Some(self.assist)
108 } 100 }
109 101
110 pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> { 102 pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
111 self.source_file.syntax().token_at_offset(self.frange.range.start()) 103 self.source_file.syntax().token_at_offset(self.frange.range.start())
112 } 104 }
113 105
114 pub(crate) fn node_at_offset<N: AstNode>(&self) -> Option<N> { 106 pub(crate) fn find_token_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
107 self.token_at_offset().find(|it| it.kind() == kind)
108 }
109
110 pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
115 find_node_at_offset(self.source_file.syntax(), self.frange.range.start()) 111 find_node_at_offset(self.source_file.syntax(), self.frange.range.start())
116 } 112 }
117 pub(crate) fn covering_element(&self) -> SyntaxElement { 113 pub(crate) fn covering_element(&self) -> SyntaxElement {
diff --git a/crates/ra_assists/src/assists/add_derive.rs b/crates/ra_assists/src/assists/add_derive.rs
index 77ecc33c9..764b17bd8 100644
--- a/crates/ra_assists/src/assists/add_derive.rs
+++ b/crates/ra_assists/src/assists/add_derive.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use hir::db::HirDatabase; 1use hir::db::HirDatabase;
4use ra_syntax::{ 2use ra_syntax::{
5 ast::{self, AstNode, AttrsOwner}, 3 ast::{self, AstNode, AttrsOwner},
@@ -9,10 +7,28 @@ use ra_syntax::{
9 7
10use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
11 9
12pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10// Assist: add_derive
13 let nominal = ctx.node_at_offset::<ast::NominalDef>()?; 11//
12// Adds a new `#[derive()]` clause to a struct or enum.
13//
14// ```
15// struct Point {
16// x: u32,
17// y: u32,<|>
18// }
19// ```
20// ->
21// ```
22// #[derive()]
23// struct Point {
24// x: u32,
25// y: u32,
26// }
27// ```
28pub(crate) fn add_derive(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
29 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
14 let node_start = derive_insertion_offset(&nominal)?; 30 let node_start = derive_insertion_offset(&nominal)?;
15 ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| { 31 ctx.add_assist(AssistId("add_derive"), "add `#[derive]`", |edit| {
16 let derive_attr = nominal 32 let derive_attr = nominal
17 .attrs() 33 .attrs()
18 .filter_map(|x| x.as_simple_call()) 34 .filter_map(|x| x.as_simple_call())
@@ -28,9 +44,7 @@ pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
28 }; 44 };
29 edit.target(nominal.syntax().text_range()); 45 edit.target(nominal.syntax().text_range());
30 edit.set_cursor(offset) 46 edit.set_cursor(offset)
31 }); 47 })
32
33 ctx.build()
34} 48}
35 49
36// Insert `derive` after doc comments. 50// Insert `derive` after doc comments.
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs
index 8c83dc987..ddda1a0f2 100644
--- a/crates/ra_assists/src/assists/add_explicit_type.rs
+++ b/crates/ra_assists/src/assists/add_explicit_type.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use hir::{db::HirDatabase, HirDisplay, Ty}; 1use hir::{db::HirDatabase, HirDisplay, Ty};
4use ra_syntax::{ 2use ra_syntax::{
5 ast::{self, AstNode, LetStmt, NameOwner}, 3 ast::{self, AstNode, LetStmt, NameOwner},
@@ -8,9 +6,23 @@ use ra_syntax::{
8 6
9use crate::{Assist, AssistCtx, AssistId}; 7use crate::{Assist, AssistCtx, AssistId};
10 8
11/// Add explicit type assist. 9// Assist: add_explicit_type
12pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10//
13 let stmt = ctx.node_at_offset::<LetStmt>()?; 11// Specify type for a let binding.
12//
13// ```
14// fn main() {
15// let x<|> = 92;
16// }
17// ```
18// ->
19// ```
20// fn main() {
21// let x: i32 = 92;
22// }
23// ```
24pub(crate) fn add_explicit_type(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
25 let stmt = ctx.find_node_at_offset::<LetStmt>()?;
14 let expr = stmt.initializer()?; 26 let expr = stmt.initializer()?;
15 let pat = stmt.pat()?; 27 let pat = stmt.pat()?;
16 // Must be a binding 28 // Must be a binding
@@ -35,11 +47,10 @@ pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<
35 return None; 47 return None;
36 } 48 }
37 49
38 ctx.add_action(AssistId("add_explicit_type"), "add explicit type", |edit| { 50 ctx.add_assist(AssistId("add_explicit_type"), "add explicit type", |edit| {
39 edit.target(pat_range); 51 edit.target(pat_range);
40 edit.insert(name_range.end(), format!(": {}", ty.display(db))); 52 edit.insert(name_range.end(), format!(": {}", ty.display(db)));
41 }); 53 })
42 ctx.build()
43} 54}
44 55
45/// Returns true if any type parameter is unknown 56/// Returns true if any type parameter is unknown
diff --git a/crates/ra_assists/src/assists/add_impl.rs b/crates/ra_assists/src/assists/add_impl.rs
index 94801fbc9..7da0cfd0d 100644
--- a/crates/ra_assists/src/assists/add_impl.rs
+++ b/crates/ra_assists/src/assists/add_impl.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use format_buf::format; 1use format_buf::format;
4use hir::db::HirDatabase; 2use hir::db::HirDatabase;
5use join_to_string::join; 3use join_to_string::join;
@@ -10,10 +8,29 @@ use ra_syntax::{
10 8
11use crate::{Assist, AssistCtx, AssistId}; 9use crate::{Assist, AssistCtx, AssistId};
12 10
13pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 11// Assist: add_impl
14 let nominal = ctx.node_at_offset::<ast::NominalDef>()?; 12//
13// Adds a new inherent impl for a type.
14//
15// ```
16// struct Ctx<T: Clone> {
17// data: T,<|>
18// }
19// ```
20// ->
21// ```
22// struct Ctx<T: Clone> {
23// data: T,
24// }
25//
26// impl<T: Clone> Ctx<T> {
27//
28// }
29// ```
30pub(crate) fn add_impl(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
31 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
15 let name = nominal.name()?; 32 let name = nominal.name()?;
16 ctx.add_action(AssistId("add_impl"), "add impl", |edit| { 33 ctx.add_assist(AssistId("add_impl"), "add impl", |edit| {
17 edit.target(nominal.syntax().text_range()); 34 edit.target(nominal.syntax().text_range());
18 let type_params = nominal.type_param_list(); 35 let type_params = nominal.type_param_list();
19 let start_offset = nominal.syntax().text_range().end(); 36 let start_offset = nominal.syntax().text_range().end();
@@ -37,9 +54,7 @@ pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
37 edit.set_cursor(start_offset + TextUnit::of_str(&buf)); 54 edit.set_cursor(start_offset + TextUnit::of_str(&buf));
38 buf.push_str("\n}"); 55 buf.push_str("\n}");
39 edit.insert(start_offset, buf); 56 edit.insert(start_offset, buf);
40 }); 57 })
41
42 ctx.build()
43} 58}
44 59
45#[cfg(test)] 60#[cfg(test)]
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/add_import.rs
index 02c58e7c6..363ade016 100644
--- a/crates/ra_assists/src/assists/auto_import.rs
+++ b/crates/ra_assists/src/assists/add_import.rs
@@ -1,18 +1,81 @@
1//! FIXME: write short doc here
2
3use hir::{self, db::HirDatabase}; 1use hir::{self, db::HirDatabase};
4use ra_text_edit::TextEditBuilder;
5
6use crate::{
7 assist_ctx::{Assist, AssistCtx},
8 AssistId,
9};
10use ra_syntax::{ 2use ra_syntax::{
11 ast::{self, NameOwner}, 3 ast::{self, NameOwner},
12 AstNode, Direction, SmolStr, 4 AstNode, Direction, SmolStr,
13 SyntaxKind::{PATH, PATH_SEGMENT}, 5 SyntaxKind::{PATH, PATH_SEGMENT},
14 SyntaxNode, TextRange, T, 6 SyntaxNode, TextRange, T,
15}; 7};
8use ra_text_edit::TextEditBuilder;
9
10use crate::{
11 assist_ctx::{Assist, AssistCtx},
12 AssistId,
13};
14
15/// This function produces sequence of text edits into edit
16/// to import the target path in the most appropriate scope given
17/// the cursor position
18pub fn auto_import_text_edit(
19 // Ideally the position of the cursor, used to
20 position: &SyntaxNode,
21 // The statement to use as anchor (last resort)
22 anchor: &SyntaxNode,
23 // The path to import as a sequence of strings
24 target: &[SmolStr],
25 edit: &mut TextEditBuilder,
26) {
27 let container = position.ancestors().find_map(|n| {
28 if let Some(module) = ast::Module::cast(n.clone()) {
29 return module.item_list().map(|it| it.syntax().clone());
30 }
31 ast::SourceFile::cast(n).map(|it| it.syntax().clone())
32 });
33
34 if let Some(container) = container {
35 let action = best_action_for_target(container, anchor.clone(), target);
36 make_assist(&action, target, edit);
37 }
38}
39
40// Assist: add_import
41//
42// Adds a use statement for a given fully-qualified path.
43//
44// ```
45// fn process(map: std::collections::<|>HashMap<String, String>) {}
46// ```
47// ->
48// ```
49// use std::collections::HashMap;
50//
51// fn process(map: HashMap<String, String>) {}
52// ```
53pub(crate) fn add_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
54 let path: ast::Path = ctx.find_node_at_offset()?;
55 // We don't want to mess with use statements
56 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
57 return None;
58 }
59
60 let hir_path = hir::Path::from_ast(path.clone())?;
61 let segments = collect_hir_path_segments(&hir_path)?;
62 if segments.len() < 2 {
63 return None;
64 }
65
66 let module = path.syntax().ancestors().find_map(ast::Module::cast);
67 let position = match module.and_then(|it| it.item_list()) {
68 Some(item_list) => item_list.syntax().clone(),
69 None => {
70 let current_file = path.syntax().ancestors().find_map(ast::SourceFile::cast)?;
71 current_file.syntax().clone()
72 }
73 };
74
75 ctx.add_assist(AssistId("add_import"), format!("import {}", fmt_segments(&segments)), |edit| {
76 apply_auto_import(&position, &path, &segments, edit.text_edit_builder());
77 })
78}
16 79
17fn collect_path_segments_raw( 80fn collect_path_segments_raw(
18 segments: &mut Vec<ast::PathSegment>, 81 segments: &mut Vec<ast::PathSegment>,
@@ -61,9 +124,9 @@ fn fmt_segments_raw(segments: &[SmolStr], buf: &mut String) {
61 } 124 }
62} 125}
63 126
64// Returns the numeber of common segments. 127/// Returns the number of common segments.
65fn compare_path_segments(left: &[SmolStr], right: &[ast::PathSegment]) -> usize { 128fn compare_path_segments(left: &[SmolStr], right: &[ast::PathSegment]) -> usize {
66 left.iter().zip(right).filter(|(l, r)| compare_path_segment(l, r)).count() 129 left.iter().zip(right).take_while(|(l, r)| compare_path_segment(l, r)).count()
67} 130}
68 131
69fn compare_path_segment(a: &SmolStr, b: &ast::PathSegment) -> bool { 132fn compare_path_segment(a: &SmolStr, b: &ast::PathSegment) -> bool {
@@ -84,7 +147,7 @@ fn compare_path_segment_with_name(a: &SmolStr, b: &ast::Name) -> bool {
84 a == b.text() 147 a == b.text()
85} 148}
86 149
87#[derive(Clone)] 150#[derive(Clone, Debug)]
88enum ImportAction { 151enum ImportAction {
89 Nothing, 152 Nothing,
90 // Add a brand new use statement. 153 // Add a brand new use statement.
@@ -154,9 +217,17 @@ impl ImportAction {
154 ( 217 (
155 ImportAction::AddNestedImport { common_segments: n, .. }, 218 ImportAction::AddNestedImport { common_segments: n, .. },
156 ImportAction::AddInTreeList { common_segments: m, .. }, 219 ImportAction::AddInTreeList { common_segments: m, .. },
157 ) => n > m, 220 )
158 ( 221 | (
222 ImportAction::AddInTreeList { common_segments: n, .. },
223 ImportAction::AddNestedImport { common_segments: m, .. },
224 )
225 | (
159 ImportAction::AddInTreeList { common_segments: n, .. }, 226 ImportAction::AddInTreeList { common_segments: n, .. },
227 ImportAction::AddInTreeList { common_segments: m, .. },
228 )
229 | (
230 ImportAction::AddNestedImport { common_segments: n, .. },
160 ImportAction::AddNestedImport { common_segments: m, .. }, 231 ImportAction::AddNestedImport { common_segments: m, .. },
161 ) => n > m, 232 ) => n > m,
162 (ImportAction::AddInTreeList { .. }, _) => true, 233 (ImportAction::AddInTreeList { .. }, _) => true,
@@ -226,7 +297,7 @@ fn walk_use_tree_for_best_action(
226 common if common == left.len() && left.len() == right.len() => { 297 common if common == left.len() && left.len() == right.len() => {
227 // e.g: target is std::fmt and we can have 298 // e.g: target is std::fmt and we can have
228 // 1- use std::fmt; 299 // 1- use std::fmt;
229 // 2- use std::fmt:{ ... } 300 // 2- use std::fmt::{ ... }
230 if let Some(list) = tree_list { 301 if let Some(list) = tree_list {
231 // In case 2 we need to add self to the nested list 302 // In case 2 we need to add self to the nested list
232 // unless it's already there 303 // unless it's already there
@@ -474,7 +545,7 @@ fn make_assist_add_nested_import(
474 if add_colon_colon { 545 if add_colon_colon {
475 buf.push_str("::"); 546 buf.push_str("::");
476 } 547 }
477 buf.push_str("{ "); 548 buf.push_str("{");
478 if add_self { 549 if add_self {
479 buf.push_str("self, "); 550 buf.push_str("self, ");
480 } 551 }
@@ -505,7 +576,7 @@ fn apply_auto_import(
505 } 576 }
506} 577}
507 578
508pub fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> { 579fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
509 let mut ps = Vec::<SmolStr>::with_capacity(10); 580 let mut ps = Vec::<SmolStr>::with_capacity(10);
510 match path.kind { 581 match path.kind {
511 hir::PathKind::Abs => ps.push("".into()), 582 hir::PathKind::Abs => ps.push("".into()),
@@ -521,87 +592,16 @@ pub fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
521 Some(ps) 592 Some(ps)
522} 593}
523 594
524// This function produces sequence of text edits into edit
525// to import the target path in the most appropriate scope given
526// the cursor position
527pub fn auto_import_text_edit(
528 // Ideally the position of the cursor, used to
529 position: &SyntaxNode,
530 // The statement to use as anchor (last resort)
531 anchor: &SyntaxNode,
532 // The path to import as a sequence of strings
533 target: &[SmolStr],
534 edit: &mut TextEditBuilder,
535) {
536 let container = position.ancestors().find_map(|n| {
537 if let Some(module) = ast::Module::cast(n.clone()) {
538 return module.item_list().map(|it| it.syntax().clone());
539 }
540 ast::SourceFile::cast(n).map(|it| it.syntax().clone())
541 });
542
543 if let Some(container) = container {
544 let action = best_action_for_target(container, anchor.clone(), target);
545 make_assist(&action, target, edit);
546 }
547}
548
549pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
550 let path: ast::Path = ctx.node_at_offset()?;
551 // We don't want to mess with use statements
552 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
553 return None;
554 }
555
556 let hir_path = hir::Path::from_ast(path.clone())?;
557 let segments = collect_hir_path_segments(&hir_path)?;
558 if segments.len() < 2 {
559 return None;
560 }
561
562 if let Some(module) = path.syntax().ancestors().find_map(ast::Module::cast) {
563 if let (Some(item_list), Some(name)) = (module.item_list(), module.name()) {
564 ctx.add_action(
565 AssistId("auto_import"),
566 format!("import {} in mod {}", fmt_segments(&segments), name.text()),
567 |edit| {
568 apply_auto_import(
569 item_list.syntax(),
570 &path,
571 &segments,
572 edit.text_edit_builder(),
573 );
574 },
575 );
576 }
577 } else {
578 let current_file = path.syntax().ancestors().find_map(ast::SourceFile::cast)?;
579 ctx.add_action(
580 AssistId("auto_import"),
581 format!("import {} in the current file", fmt_segments(&segments)),
582 |edit| {
583 apply_auto_import(
584 current_file.syntax(),
585 &path,
586 &segments,
587 edit.text_edit_builder(),
588 );
589 },
590 );
591 }
592
593 ctx.build()
594}
595
596#[cfg(test)] 595#[cfg(test)]
597mod tests { 596mod tests {
598 use super::*;
599 use crate::helpers::{check_assist, check_assist_not_applicable}; 597 use crate::helpers::{check_assist, check_assist_not_applicable};
600 598
599 use super::*;
600
601 #[test] 601 #[test]
602 fn test_auto_import_add_use_no_anchor() { 602 fn test_auto_import_add_use_no_anchor() {
603 check_assist( 603 check_assist(
604 auto_import, 604 add_import,
605 " 605 "
606std::fmt::Debug<|> 606std::fmt::Debug<|>
607 ", 607 ",
@@ -615,7 +615,7 @@ Debug<|>
615 #[test] 615 #[test]
616 fn test_auto_import_add_use_no_anchor_with_item_below() { 616 fn test_auto_import_add_use_no_anchor_with_item_below() {
617 check_assist( 617 check_assist(
618 auto_import, 618 add_import,
619 " 619 "
620std::fmt::Debug<|> 620std::fmt::Debug<|>
621 621
@@ -636,7 +636,7 @@ fn main() {
636 #[test] 636 #[test]
637 fn test_auto_import_add_use_no_anchor_with_item_above() { 637 fn test_auto_import_add_use_no_anchor_with_item_above() {
638 check_assist( 638 check_assist(
639 auto_import, 639 add_import,
640 " 640 "
641fn main() { 641fn main() {
642} 642}
@@ -657,7 +657,7 @@ Debug<|>
657 #[test] 657 #[test]
658 fn test_auto_import_add_use_no_anchor_2seg() { 658 fn test_auto_import_add_use_no_anchor_2seg() {
659 check_assist( 659 check_assist(
660 auto_import, 660 add_import,
661 " 661 "
662std::fmt<|>::Debug 662std::fmt<|>::Debug
663 ", 663 ",
@@ -672,7 +672,7 @@ fmt<|>::Debug
672 #[test] 672 #[test]
673 fn test_auto_import_add_use() { 673 fn test_auto_import_add_use() {
674 check_assist( 674 check_assist(
675 auto_import, 675 add_import,
676 " 676 "
677use stdx; 677use stdx;
678 678
@@ -692,7 +692,7 @@ impl Debug<|> for Foo {
692 #[test] 692 #[test]
693 fn test_auto_import_file_use_other_anchor() { 693 fn test_auto_import_file_use_other_anchor() {
694 check_assist( 694 check_assist(
695 auto_import, 695 add_import,
696 " 696 "
697impl std::fmt::Debug<|> for Foo { 697impl std::fmt::Debug<|> for Foo {
698} 698}
@@ -709,7 +709,7 @@ impl Debug<|> for Foo {
709 #[test] 709 #[test]
710 fn test_auto_import_add_use_other_anchor_indent() { 710 fn test_auto_import_add_use_other_anchor_indent() {
711 check_assist( 711 check_assist(
712 auto_import, 712 add_import,
713 " 713 "
714 impl std::fmt::Debug<|> for Foo { 714 impl std::fmt::Debug<|> for Foo {
715 } 715 }
@@ -726,7 +726,7 @@ impl Debug<|> for Foo {
726 #[test] 726 #[test]
727 fn test_auto_import_split_different() { 727 fn test_auto_import_split_different() {
728 check_assist( 728 check_assist(
729 auto_import, 729 add_import,
730 " 730 "
731use std::fmt; 731use std::fmt;
732 732
@@ -734,7 +734,7 @@ impl std::io<|> for Foo {
734} 734}
735 ", 735 ",
736 " 736 "
737use std::{ io, fmt}; 737use std::{io, fmt};
738 738
739impl io<|> for Foo { 739impl io<|> for Foo {
740} 740}
@@ -745,7 +745,7 @@ impl io<|> for Foo {
745 #[test] 745 #[test]
746 fn test_auto_import_split_self_for_use() { 746 fn test_auto_import_split_self_for_use() {
747 check_assist( 747 check_assist(
748 auto_import, 748 add_import,
749 " 749 "
750use std::fmt; 750use std::fmt;
751 751
@@ -753,7 +753,7 @@ impl std::fmt::Debug<|> for Foo {
753} 753}
754 ", 754 ",
755 " 755 "
756use std::fmt::{ self, Debug, }; 756use std::fmt::{self, Debug, };
757 757
758impl Debug<|> for Foo { 758impl Debug<|> for Foo {
759} 759}
@@ -764,7 +764,7 @@ impl Debug<|> for Foo {
764 #[test] 764 #[test]
765 fn test_auto_import_split_self_for_target() { 765 fn test_auto_import_split_self_for_target() {
766 check_assist( 766 check_assist(
767 auto_import, 767 add_import,
768 " 768 "
769use std::fmt::Debug; 769use std::fmt::Debug;
770 770
@@ -772,7 +772,7 @@ impl std::fmt<|> for Foo {
772} 772}
773 ", 773 ",
774 " 774 "
775use std::fmt::{ self, Debug}; 775use std::fmt::{self, Debug};
776 776
777impl fmt<|> for Foo { 777impl fmt<|> for Foo {
778} 778}
@@ -783,7 +783,7 @@ impl fmt<|> for Foo {
783 #[test] 783 #[test]
784 fn test_auto_import_add_to_nested_self_nested() { 784 fn test_auto_import_add_to_nested_self_nested() {
785 check_assist( 785 check_assist(
786 auto_import, 786 add_import,
787 " 787 "
788use std::fmt::{Debug, nested::{Display}}; 788use std::fmt::{Debug, nested::{Display}};
789 789
@@ -802,7 +802,7 @@ impl nested<|> for Foo {
802 #[test] 802 #[test]
803 fn test_auto_import_add_to_nested_self_already_included() { 803 fn test_auto_import_add_to_nested_self_already_included() {
804 check_assist( 804 check_assist(
805 auto_import, 805 add_import,
806 " 806 "
807use std::fmt::{Debug, nested::{self, Display}}; 807use std::fmt::{Debug, nested::{self, Display}};
808 808
@@ -821,7 +821,7 @@ impl nested<|> for Foo {
821 #[test] 821 #[test]
822 fn test_auto_import_add_to_nested_nested() { 822 fn test_auto_import_add_to_nested_nested() {
823 check_assist( 823 check_assist(
824 auto_import, 824 add_import,
825 " 825 "
826use std::fmt::{Debug, nested::{Display}}; 826use std::fmt::{Debug, nested::{Display}};
827 827
@@ -840,7 +840,7 @@ impl Debug<|> for Foo {
840 #[test] 840 #[test]
841 fn test_auto_import_split_common_target_longer() { 841 fn test_auto_import_split_common_target_longer() {
842 check_assist( 842 check_assist(
843 auto_import, 843 add_import,
844 " 844 "
845use std::fmt::Debug; 845use std::fmt::Debug;
846 846
@@ -848,7 +848,7 @@ impl std::fmt::nested::Display<|> for Foo {
848} 848}
849", 849",
850 " 850 "
851use std::fmt::{ nested::Display, Debug}; 851use std::fmt::{nested::Display, Debug};
852 852
853impl Display<|> for Foo { 853impl Display<|> for Foo {
854} 854}
@@ -859,7 +859,7 @@ impl Display<|> for Foo {
859 #[test] 859 #[test]
860 fn test_auto_import_split_common_use_longer() { 860 fn test_auto_import_split_common_use_longer() {
861 check_assist( 861 check_assist(
862 auto_import, 862 add_import,
863 " 863 "
864use std::fmt::nested::Debug; 864use std::fmt::nested::Debug;
865 865
@@ -867,7 +867,7 @@ impl std::fmt::Display<|> for Foo {
867} 867}
868", 868",
869 " 869 "
870use std::fmt::{ Display, nested::Debug}; 870use std::fmt::{Display, nested::Debug};
871 871
872impl Display<|> for Foo { 872impl Display<|> for Foo {
873} 873}
@@ -876,9 +876,32 @@ impl Display<|> for Foo {
876 } 876 }
877 877
878 #[test] 878 #[test]
879 fn test_auto_import_use_nested_import() {
880 check_assist(
881 add_import,
882 "
883use crate::{
884 ty::{Substs, Ty},
885 AssocItem,
886};
887
888fn foo() { crate::ty::lower<|>::trait_env() }
889",
890 "
891use crate::{
892 ty::{Substs, Ty, lower},
893 AssocItem,
894};
895
896fn foo() { lower<|>::trait_env() }
897",
898 );
899 }
900
901 #[test]
879 fn test_auto_import_alias() { 902 fn test_auto_import_alias() {
880 check_assist( 903 check_assist(
881 auto_import, 904 add_import,
882 " 905 "
883use std::fmt as foo; 906use std::fmt as foo;
884 907
@@ -897,7 +920,7 @@ impl Debug<|> for Foo {
897 #[test] 920 #[test]
898 fn test_auto_import_not_applicable_one_segment() { 921 fn test_auto_import_not_applicable_one_segment() {
899 check_assist_not_applicable( 922 check_assist_not_applicable(
900 auto_import, 923 add_import,
901 " 924 "
902impl foo<|> for Foo { 925impl foo<|> for Foo {
903} 926}
@@ -908,7 +931,7 @@ impl foo<|> for Foo {
908 #[test] 931 #[test]
909 fn test_auto_import_not_applicable_in_use() { 932 fn test_auto_import_not_applicable_in_use() {
910 check_assist_not_applicable( 933 check_assist_not_applicable(
911 auto_import, 934 add_import,
912 " 935 "
913use std::fmt<|>; 936use std::fmt<|>;
914", 937",
@@ -918,7 +941,7 @@ use std::fmt<|>;
918 #[test] 941 #[test]
919 fn test_auto_import_add_use_no_anchor_in_mod_mod() { 942 fn test_auto_import_add_use_no_anchor_in_mod_mod() {
920 check_assist( 943 check_assist(
921 auto_import, 944 add_import,
922 " 945 "
923mod foo { 946mod foo {
924 mod bar { 947 mod bar {
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs
index 565b96fb5..41de23921 100644
--- a/crates/ra_assists/src/assists/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use hir::{db::HirDatabase, HasSource}; 1use hir::{db::HirDatabase, HasSource};
4use ra_syntax::{ 2use ra_syntax::{
5 ast::{self, edit, make, AstNode, NameOwner}, 3 ast::{self, edit, make, AstNode, NameOwner},
@@ -14,6 +12,34 @@ enum AddMissingImplMembersMode {
14 NoDefaultMethods, 12 NoDefaultMethods,
15} 13}
16 14
15// Assist: add_impl_missing_members
16//
17// Adds scaffold for required impl members.
18//
19// ```
20// trait T {
21// Type X;
22// fn foo(&self);
23// fn bar(&self) {}
24// }
25//
26// impl T for () {<|>
27//
28// }
29// ```
30// ->
31// ```
32// trait T {
33// Type X;
34// fn foo(&self);
35// fn bar(&self) {}
36// }
37//
38// impl T for () {
39// fn foo(&self) { unimplemented!() }
40//
41// }
42// ```
17pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 43pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
18 add_missing_impl_members_inner( 44 add_missing_impl_members_inner(
19 ctx, 45 ctx,
@@ -23,6 +49,38 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Opti
23 ) 49 )
24} 50}
25 51
52// Assist: add_impl_default_members
53//
54// Adds scaffold for overriding default impl members.
55//
56// ```
57// trait T {
58// Type X;
59// fn foo(&self);
60// fn bar(&self) {}
61// }
62//
63// impl T for () {
64// Type X = ();
65// fn foo(&self) {}<|>
66//
67// }
68// ```
69// ->
70// ```
71// trait T {
72// Type X;
73// fn foo(&self);
74// fn bar(&self) {}
75// }
76//
77// impl T for () {
78// Type X = ();
79// fn foo(&self) {}
80// fn bar(&self) {}
81//
82// }
83// ```
26pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 84pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
27 add_missing_impl_members_inner( 85 add_missing_impl_members_inner(
28 ctx, 86 ctx,
@@ -33,12 +91,12 @@ pub(crate) fn add_missing_default_members(ctx: AssistCtx<impl HirDatabase>) -> O
33} 91}
34 92
35fn add_missing_impl_members_inner( 93fn add_missing_impl_members_inner(
36 mut ctx: AssistCtx<impl HirDatabase>, 94 ctx: AssistCtx<impl HirDatabase>,
37 mode: AddMissingImplMembersMode, 95 mode: AddMissingImplMembersMode,
38 assist_id: &'static str, 96 assist_id: &'static str,
39 label: &'static str, 97 label: &'static str,
40) -> Option<Assist> { 98) -> Option<Assist> {
41 let impl_node = ctx.node_at_offset::<ast::ImplBlock>()?; 99 let impl_node = ctx.find_node_at_offset::<ast::ImplBlock>()?;
42 let impl_item_list = impl_node.item_list()?; 100 let impl_item_list = impl_node.item_list()?;
43 101
44 let trait_def = { 102 let trait_def = {
@@ -75,7 +133,7 @@ fn add_missing_impl_members_inner(
75 return None; 133 return None;
76 } 134 }
77 135
78 ctx.add_action(AssistId(assist_id), label, |edit| { 136 ctx.add_assist(AssistId(assist_id), label, |edit| {
79 let n_existing_items = impl_item_list.impl_items().count(); 137 let n_existing_items = impl_item_list.impl_items().count();
80 let items = missing_items 138 let items = missing_items
81 .into_iter() 139 .into_iter()
@@ -92,9 +150,7 @@ fn add_missing_impl_members_inner(
92 150
93 edit.replace_ast(impl_item_list, new_impl_item_list); 151 edit.replace_ast(impl_item_list, new_impl_item_list);
94 edit.set_cursor(cursor_position); 152 edit.set_cursor(cursor_position);
95 }); 153 })
96
97 ctx.build()
98} 154}
99 155
100fn add_body(fn_def: ast::FnDef) -> ast::FnDef { 156fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
diff --git a/crates/ra_assists/src/assists/apply_demorgan.rs b/crates/ra_assists/src/assists/apply_demorgan.rs
index 5f2b0dd18..068da1774 100644
--- a/crates/ra_assists/src/assists/apply_demorgan.rs
+++ b/crates/ra_assists/src/assists/apply_demorgan.rs
@@ -1,20 +1,30 @@
1//! This contains the functions associated with the demorgan assist.
2//! This assist transforms boolean expressions of the form `!a || !b` into
3//! `!(a && b)`.
4use hir::db::HirDatabase; 1use hir::db::HirDatabase;
5use ra_syntax::ast::{self, AstNode}; 2use ra_syntax::ast::{self, AstNode};
6use ra_syntax::SyntaxNode; 3use ra_syntax::SyntaxNode;
7 4
8use crate::{Assist, AssistCtx, AssistId}; 5use crate::{Assist, AssistCtx, AssistId};
9 6
10/// Assist for applying demorgan's law 7// Assist: apply_demorgan
11/// 8//
12/// This transforms expressions of the form `!l || !r` into `!(l && r)`. 9// Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
13/// This also works with `&&`. This assist can only be applied with the cursor 10// This transforms expressions of the form `!l || !r` into `!(l && r)`.
14/// on either `||` or `&&`, with both operands being a negation of some kind. 11// This also works with `&&`. This assist can only be applied with the cursor
15/// This means something of the form `!x` or `x != y`. 12// on either `||` or `&&`, with both operands being a negation of some kind.
16pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 13// This means something of the form `!x` or `x != y`.
17 let expr = ctx.node_at_offset::<ast::BinExpr>()?; 14//
15// ```
16// fn main() {
17// if x != 4 ||<|> !y {}
18// }
19// ```
20// ->
21// ```
22// fn main() {
23// if !(x == 4 && y) {}
24// }
25// ```
26pub(crate) fn apply_demorgan(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
27 let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
18 let op = expr.op_kind()?; 28 let op = expr.op_kind()?;
19 let op_range = expr.op_token()?.text_range(); 29 let op_range = expr.op_token()?.text_range();
20 let opposite_op = opposite_logic_op(op)?; 30 let opposite_op = opposite_logic_op(op)?;
@@ -29,13 +39,12 @@ pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Ass
29 let not_lhs = undo_negation(lhs)?; 39 let not_lhs = undo_negation(lhs)?;
30 let not_rhs = undo_negation(rhs)?; 40 let not_rhs = undo_negation(rhs)?;
31 41
32 ctx.add_action(AssistId("apply_demorgan"), "apply demorgan's law", |edit| { 42 ctx.add_assist(AssistId("apply_demorgan"), "apply demorgan's law", |edit| {
33 edit.target(op_range); 43 edit.target(op_range);
34 edit.replace(op_range, opposite_op); 44 edit.replace(op_range, opposite_op);
35 edit.replace(lhs_range, format!("!({}", not_lhs)); 45 edit.replace(lhs_range, format!("!({}", not_lhs));
36 edit.replace(rhs_range, format!("{})", not_rhs)); 46 edit.replace(rhs_range, format!("{})", not_rhs));
37 }); 47 })
38 ctx.build()
39} 48}
40 49
41// Return the opposite text for a given logical operator, if it makes sense 50// Return the opposite text for a given logical operator, if it makes sense
diff --git a/crates/ra_assists/src/assists/change_visibility.rs b/crates/ra_assists/src/assists/change_visibility.rs
index df92c6b67..132c9dc1d 100644
--- a/crates/ra_assists/src/assists/change_visibility.rs
+++ b/crates/ra_assists/src/assists/change_visibility.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use hir::db::HirDatabase; 1use hir::db::HirDatabase;
4use ra_syntax::{ 2use ra_syntax::{
5 ast::{self, NameOwner, VisibilityOwner}, 3 ast::{self, NameOwner, VisibilityOwner},
@@ -13,14 +11,25 @@ use ra_syntax::{
13 11
14use crate::{Assist, AssistCtx, AssistId}; 12use crate::{Assist, AssistCtx, AssistId};
15 13
14// Assist: change_visibility
15//
16// Adds or changes existing visibility specifier.
17//
18// ```
19// <|>fn frobnicate() {}
20// ```
21// ->
22// ```
23// pub(crate) fn frobnicate() {}
24// ```
16pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 25pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
17 if let Some(vis) = ctx.node_at_offset::<ast::Visibility>() { 26 if let Some(vis) = ctx.find_node_at_offset::<ast::Visibility>() {
18 return change_vis(ctx, vis); 27 return change_vis(ctx, vis);
19 } 28 }
20 add_vis(ctx) 29 add_vis(ctx)
21} 30}
22 31
23fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 32fn add_vis(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
24 let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() { 33 let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() {
25 T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true, 34 T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true,
26 _ => false, 35 _ => false,
@@ -48,13 +57,11 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
48 (vis_offset(field.syntax()), ident.text_range()) 57 (vis_offset(field.syntax()), ident.text_range())
49 }; 58 };
50 59
51 ctx.add_action(AssistId("change_visibility"), "make pub(crate)", |edit| { 60 ctx.add_assist(AssistId("change_visibility"), "make pub(crate)", |edit| {
52 edit.target(target); 61 edit.target(target);
53 edit.insert(offset, "pub(crate) "); 62 edit.insert(offset, "pub(crate) ");
54 edit.set_cursor(offset); 63 edit.set_cursor(offset);
55 }); 64 })
56
57 ctx.build()
58} 65}
59 66
60fn vis_offset(node: &SyntaxNode) -> TextUnit { 67fn vis_offset(node: &SyntaxNode) -> TextUnit {
@@ -68,24 +75,20 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
68 .unwrap_or_else(|| node.text_range().start()) 75 .unwrap_or_else(|| node.text_range().start())
69} 76}
70 77
71fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> { 78fn change_vis(ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> {
72 if vis.syntax().text() == "pub" { 79 if vis.syntax().text() == "pub" {
73 ctx.add_action(AssistId("change_visibility"), "change to pub(crate)", |edit| { 80 return ctx.add_assist(AssistId("change_visibility"), "change to pub(crate)", |edit| {
74 edit.target(vis.syntax().text_range()); 81 edit.target(vis.syntax().text_range());
75 edit.replace(vis.syntax().text_range(), "pub(crate)"); 82 edit.replace(vis.syntax().text_range(), "pub(crate)");
76 edit.set_cursor(vis.syntax().text_range().start()) 83 edit.set_cursor(vis.syntax().text_range().start())
77 }); 84 });
78
79 return ctx.build();
80 } 85 }
81 if vis.syntax().text() == "pub(crate)" { 86 if vis.syntax().text() == "pub(crate)" {
82 ctx.add_action(AssistId("change_visibility"), "change to pub", |edit| { 87 return ctx.add_assist(AssistId("change_visibility"), "change to pub", |edit| {
83 edit.target(vis.syntax().text_range()); 88 edit.target(vis.syntax().text_range());
84 edit.replace(vis.syntax().text_range(), "pub"); 89 edit.replace(vis.syntax().text_range(), "pub");
85 edit.set_cursor(vis.syntax().text_range().start()); 90 edit.set_cursor(vis.syntax().text_range().start());
86 }); 91 });
87
88 return ctx.build();
89 } 92 }
90 None 93 None
91} 94}
diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs
index f7d7e12e7..ad6c5695a 100644
--- a/crates/ra_assists/src/assists/early_return.rs
+++ b/crates/ra_assists/src/assists/early_return.rs
@@ -1,26 +1,3 @@
1//! Assist: `convert_to_guarded_return`
2//!
3//! Replace a large conditional with a guarded return.
4//!
5//! ```text
6//! fn <|>main() {
7//! if cond {
8//! foo();
9//! bar();
10//! }
11//! }
12//! ```
13//! ->
14//! ```text
15//! fn main() {
16//! if !cond {
17//! return;
18//! }
19//! foo();
20//! bar();
21//! }
22//! ```
23
24use std::ops::RangeInclusive; 1use std::ops::RangeInclusive;
25 2
26use hir::db::HirDatabase; 3use hir::db::HirDatabase;
@@ -36,8 +13,30 @@ use crate::{
36 AssistId, 13 AssistId,
37}; 14};
38 15
39pub(crate) fn convert_to_guarded_return(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 16// Assist: convert_to_guarded_return
40 let if_expr: ast::IfExpr = ctx.node_at_offset()?; 17//
18// Replace a large conditional with a guarded return.
19//
20// ```
21// fn main() {
22// <|>if cond {
23// foo();
24// bar();
25// }
26// }
27// ```
28// ->
29// ```
30// fn main() {
31// if !cond {
32// return;
33// }
34// foo();
35// bar();
36// }
37// ```
38pub(crate) fn convert_to_guarded_return(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
39 let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
41 let expr = if_expr.condition()?.expr()?; 40 let expr = if_expr.condition()?.expr()?;
42 let then_block = if_expr.then_branch()?.block()?; 41 let then_block = if_expr.then_branch()?.block()?;
43 if if_expr.else_branch().is_some() { 42 if if_expr.else_branch().is_some() {
@@ -51,7 +50,7 @@ pub(crate) fn convert_to_guarded_return(mut ctx: AssistCtx<impl HirDatabase>) ->
51 } 50 }
52 51
53 // check for early return and continue 52 // check for early return and continue
54 let first_in_then_block = then_block.syntax().first_child()?.clone(); 53 let first_in_then_block = then_block.syntax().first_child()?;
55 if ast::ReturnExpr::can_cast(first_in_then_block.kind()) 54 if ast::ReturnExpr::can_cast(first_in_then_block.kind())
56 || ast::ContinueExpr::can_cast(first_in_then_block.kind()) 55 || ast::ContinueExpr::can_cast(first_in_then_block.kind())
57 || first_in_then_block 56 || first_in_then_block
@@ -76,7 +75,7 @@ pub(crate) fn convert_to_guarded_return(mut ctx: AssistCtx<impl HirDatabase>) ->
76 then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; 75 then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?;
77 let cursor_position = ctx.frange.range.start(); 76 let cursor_position = ctx.frange.range.start();
78 77
79 ctx.add_action(AssistId("convert_to_guarded_return"), "convert to guarded return", |edit| { 78 ctx.add_assist(AssistId("convert_to_guarded_return"), "convert to guarded return", |edit| {
80 let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); 79 let if_indent_level = IndentLevel::from_node(&if_expr.syntax());
81 let new_if_expr = 80 let new_if_expr =
82 if_indent_level.increase_indent(make::if_expression(&expr, early_expression)); 81 if_indent_level.increase_indent(make::if_expression(&expr, early_expression));
@@ -106,8 +105,7 @@ pub(crate) fn convert_to_guarded_return(mut ctx: AssistCtx<impl HirDatabase>) ->
106 edit.target(if_expr.syntax().text_range()); 105 edit.target(if_expr.syntax().text_range());
107 edit.replace_ast(parent_block, ast::Block::cast(new_block).unwrap()); 106 edit.replace_ast(parent_block, ast::Block::cast(new_block).unwrap());
108 edit.set_cursor(cursor_position); 107 edit.set_cursor(cursor_position);
109 }); 108 })
110 ctx.build()
111} 109}
112 110
113#[cfg(test)] 111#[cfg(test)]
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs
index e3f30b5de..2b74f355c 100644
--- a/crates/ra_assists/src/assists/fill_match_arms.rs
+++ b/crates/ra_assists/src/assists/fill_match_arms.rs
@@ -7,8 +7,32 @@ use ra_syntax::ast::{self, edit::IndentLevel, make, AstNode, NameOwner};
7 7
8use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
9 9
10pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10// Assist: fill_match_arms
11 let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?; 11//
12// Adds missing clauses to a `match` expression.
13//
14// ```
15// enum Action { Move { distance: u32 }, Stop }
16//
17// fn handle(action: Action) {
18// match action {
19// <|>
20// }
21// }
22// ```
23// ->
24// ```
25// enum Action { Move { distance: u32 }, Stop }
26//
27// fn handle(action: Action) {
28// match action {
29// Action::Move { distance } => (),
30// Action::Stop => (),
31// }
32// }
33// ```
34pub(crate) fn fill_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
35 let match_expr = ctx.find_node_at_offset::<ast::MatchExpr>()?;
12 let match_arm_list = match_expr.match_arm_list()?; 36 let match_arm_list = match_expr.match_arm_list()?;
13 37
14 // We already have some match arms, so we don't provide any assists. 38 // We already have some match arms, so we don't provide any assists.
@@ -29,7 +53,7 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
29 }; 53 };
30 let variant_list = enum_def.variant_list()?; 54 let variant_list = enum_def.variant_list()?;
31 55
32 ctx.add_action(AssistId("fill_match_arms"), "fill match arms", |edit| { 56 ctx.add_assist(AssistId("fill_match_arms"), "fill match arms", |edit| {
33 let indent_level = IndentLevel::from_node(match_arm_list.syntax()); 57 let indent_level = IndentLevel::from_node(match_arm_list.syntax());
34 58
35 let new_arm_list = { 59 let new_arm_list = {
@@ -43,9 +67,7 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
43 edit.target(match_expr.syntax().text_range()); 67 edit.target(match_expr.syntax().text_range());
44 edit.set_cursor(expr.syntax().text_range().start()); 68 edit.set_cursor(expr.syntax().text_range().start());
45 edit.replace_ast(match_arm_list, new_arm_list); 69 edit.replace_ast(match_arm_list, new_arm_list);
46 }); 70 })
47
48 ctx.build()
49} 71}
50 72
51fn is_trivial(arm: &ast::MatchArm) -> bool { 73fn is_trivial(arm: &ast::MatchArm) -> bool {
@@ -130,7 +152,7 @@ mod tests {
130 A::Bs => (), 152 A::Bs => (),
131 A::Cs(_) => (), 153 A::Cs(_) => (),
132 A::Ds(_, _) => (), 154 A::Ds(_, _) => (),
133 A::Es{ x, y } => (), 155 A::Es { x, y } => (),
134 } 156 }
135 } 157 }
136 "#, 158 "#,
@@ -183,7 +205,7 @@ mod tests {
183 205
184 fn foo(a: &mut A) { 206 fn foo(a: &mut A) {
185 match <|>a { 207 match <|>a {
186 A::Es{ x, y } => (), 208 A::Es { x, y } => (),
187 } 209 }
188 } 210 }
189 "#, 211 "#,
diff --git a/crates/ra_assists/src/assists/flip_binexpr.rs b/crates/ra_assists/src/assists/flip_binexpr.rs
index c51035282..386045eb0 100644
--- a/crates/ra_assists/src/assists/flip_binexpr.rs
+++ b/crates/ra_assists/src/assists/flip_binexpr.rs
@@ -1,13 +1,25 @@
1//! FIXME: write short doc here
2
3use hir::db::HirDatabase; 1use hir::db::HirDatabase;
4use ra_syntax::ast::{AstNode, BinExpr, BinOp}; 2use ra_syntax::ast::{AstNode, BinExpr, BinOp};
5 3
6use crate::{Assist, AssistCtx, AssistId}; 4use crate::{Assist, AssistCtx, AssistId};
7 5
8/// Flip binary expression assist. 6// Assist: flip_binexpr
9pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 7//
10 let expr = ctx.node_at_offset::<BinExpr>()?; 8// Flips operands of a binary expression.
9//
10// ```
11// fn main() {
12// let _ = 90 +<|> 2;
13// }
14// ```
15// ->
16// ```
17// fn main() {
18// let _ = 2 + 90;
19// }
20// ```
21pub(crate) fn flip_binexpr(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
22 let expr = ctx.find_node_at_offset::<BinExpr>()?;
11 let lhs = expr.lhs()?.syntax().clone(); 23 let lhs = expr.lhs()?.syntax().clone();
12 let rhs = expr.rhs()?.syntax().clone(); 24 let rhs = expr.rhs()?.syntax().clone();
13 let op_range = expr.op_token()?.text_range(); 25 let op_range = expr.op_token()?.text_range();
@@ -22,16 +34,14 @@ pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
22 return None; 34 return None;
23 } 35 }
24 36
25 ctx.add_action(AssistId("flip_binexpr"), "flip binary expression", |edit| { 37 ctx.add_assist(AssistId("flip_binexpr"), "flip binary expression", |edit| {
26 edit.target(op_range); 38 edit.target(op_range);
27 if let FlipAction::FlipAndReplaceOp(new_op) = action { 39 if let FlipAction::FlipAndReplaceOp(new_op) = action {
28 edit.replace(op_range, new_op); 40 edit.replace(op_range, new_op);
29 } 41 }
30 edit.replace(lhs.text_range(), rhs.text()); 42 edit.replace(lhs.text_range(), rhs.text());
31 edit.replace(rhs.text_range(), lhs.text()); 43 edit.replace(rhs.text_range(), lhs.text());
32 }); 44 })
33
34 ctx.build()
35} 45}
36 46
37enum FlipAction { 47enum FlipAction {
diff --git a/crates/ra_assists/src/assists/flip_comma.rs b/crates/ra_assists/src/assists/flip_comma.rs
index e31cc5e7d..9be1c1dc6 100644
--- a/crates/ra_assists/src/assists/flip_comma.rs
+++ b/crates/ra_assists/src/assists/flip_comma.rs
@@ -1,12 +1,25 @@
1//! FIXME: write short doc here
2
3use hir::db::HirDatabase; 1use hir::db::HirDatabase;
4use ra_syntax::{algo::non_trivia_sibling, Direction, T}; 2use ra_syntax::{algo::non_trivia_sibling, Direction, T};
5 3
6use crate::{Assist, AssistCtx, AssistId}; 4use crate::{Assist, AssistCtx, AssistId};
7 5
8pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 6// Assist: flip_comma
9 let comma = ctx.token_at_offset().find(|leaf| leaf.kind() == T![,])?; 7//
8// Flips two comma-separated items.
9//
10// ```
11// fn main() {
12// ((1, 2),<|> (3, 4));
13// }
14// ```
15// ->
16// ```
17// fn main() {
18// ((3, 4), (1, 2));
19// }
20// ```
21pub(crate) fn flip_comma(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
22 let comma = ctx.find_token_at_offset(T![,])?;
10 let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?; 23 let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
11 let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?; 24 let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
12 25
@@ -16,13 +29,11 @@ pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
16 return None; 29 return None;
17 } 30 }
18 31
19 ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| { 32 ctx.add_assist(AssistId("flip_comma"), "flip comma", |edit| {
20 edit.target(comma.text_range()); 33 edit.target(comma.text_range());
21 edit.replace(prev.text_range(), next.to_string()); 34 edit.replace(prev.text_range(), next.to_string());
22 edit.replace(next.text_range(), prev.to_string()); 35 edit.replace(next.text_range(), prev.to_string());
23 }); 36 })
24
25 ctx.build()
26} 37}
27 38
28#[cfg(test)] 39#[cfg(test)]
diff --git a/crates/ra_assists/src/assists/flip_trait_bound.rs b/crates/ra_assists/src/assists/flip_trait_bound.rs
new file mode 100644
index 000000000..6017b39dd
--- /dev/null
+++ b/crates/ra_assists/src/assists/flip_trait_bound.rs
@@ -0,0 +1,117 @@
1use hir::db::HirDatabase;
2use ra_syntax::{
3 algo::non_trivia_sibling,
4 ast::{self, AstNode},
5 Direction, T,
6};
7
8use crate::{Assist, AssistCtx, AssistId};
9
10// Assist: flip_trait_bound
11//
12// Flips two trait bounds.
13//
14// ```
15// fn foo<T: Clone +<|> Copy>() { }
16// ```
17// ->
18// ```
19// fn foo<T: Copy + Clone>() { }
20// ```
21pub(crate) fn flip_trait_bound(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
22 // We want to replicate the behavior of `flip_binexpr` by only suggesting
23 // the assist when the cursor is on a `+`
24 let plus = ctx.find_token_at_offset(T![+])?;
25
26 // Make sure we're in a `TypeBoundList`
27 if ast::TypeBoundList::cast(plus.parent()).is_none() {
28 return None;
29 }
30
31 let (before, after) = (
32 non_trivia_sibling(plus.clone().into(), Direction::Prev)?,
33 non_trivia_sibling(plus.clone().into(), Direction::Next)?,
34 );
35
36 ctx.add_assist(AssistId("flip_trait_bound"), "flip trait bound", |edit| {
37 edit.target(plus.text_range());
38 edit.replace(before.text_range(), after.to_string());
39 edit.replace(after.text_range(), before.to_string());
40 })
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
48
49 #[test]
50 fn flip_trait_bound_assist_available() {
51 check_assist_target(flip_trait_bound, "struct S<T> where T: A <|>+ B + C { }", "+")
52 }
53
54 #[test]
55 fn flip_trait_bound_not_applicable_for_single_trait_bound() {
56 check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: <|>A { }")
57 }
58
59 #[test]
60 fn flip_trait_bound_works_for_struct() {
61 check_assist(
62 flip_trait_bound,
63 "struct S<T> where T: A <|>+ B { }",
64 "struct S<T> where T: B <|>+ A { }",
65 )
66 }
67
68 #[test]
69 fn flip_trait_bound_works_for_trait_impl() {
70 check_assist(
71 flip_trait_bound,
72 "impl X for S<T> where T: A +<|> B { }",
73 "impl X for S<T> where T: B +<|> A { }",
74 )
75 }
76
77 #[test]
78 fn flip_trait_bound_works_for_fn() {
79 check_assist(flip_trait_bound, "fn f<T: A <|>+ B>(t: T) { }", "fn f<T: B <|>+ A>(t: T) { }")
80 }
81
82 #[test]
83 fn flip_trait_bound_works_for_fn_where_clause() {
84 check_assist(
85 flip_trait_bound,
86 "fn f<T>(t: T) where T: A +<|> B { }",
87 "fn f<T>(t: T) where T: B +<|> A { }",
88 )
89 }
90
91 #[test]
92 fn flip_trait_bound_works_for_lifetime() {
93 check_assist(
94 flip_trait_bound,
95 "fn f<T>(t: T) where T: A <|>+ 'static { }",
96 "fn f<T>(t: T) where T: 'static <|>+ A { }",
97 )
98 }
99
100 #[test]
101 fn flip_trait_bound_works_for_complex_bounds() {
102 check_assist(
103 flip_trait_bound,
104 "struct S<T> where T: A<T> <|>+ b_mod::B<T> + C<T> { }",
105 "struct S<T> where T: b_mod::B<T> <|>+ A<T> + C<T> { }",
106 )
107 }
108
109 #[test]
110 fn flip_trait_bound_works_for_long_bounds() {
111 check_assist(
112 flip_trait_bound,
113 "struct S<T> where T: A + B + C + D + E + F +<|> G + H + I + J { }",
114 "struct S<T> where T: A + B + C + D + E + G +<|> F + H + I + J { }",
115 )
116 }
117}
diff --git a/crates/ra_assists/src/assists/inline_local_variable.rs b/crates/ra_assists/src/assists/inline_local_variable.rs
index 9bd64decc..a7fd9b6d2 100644
--- a/crates/ra_assists/src/assists/inline_local_variable.rs
+++ b/crates/ra_assists/src/assists/inline_local_variable.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use hir::db::HirDatabase; 1use hir::db::HirDatabase;
4use ra_syntax::{ 2use ra_syntax::{
5 ast::{self, AstNode, AstToken}, 3 ast::{self, AstNode, AstToken},
@@ -9,8 +7,24 @@ use ra_syntax::{
9use crate::assist_ctx::AssistBuilder; 7use crate::assist_ctx::AssistBuilder;
10use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
11 9
12pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10// Assist: inline_local_variable
13 let let_stmt = ctx.node_at_offset::<ast::LetStmt>()?; 11//
12// Inlines local variable.
13//
14// ```
15// fn main() {
16// let x<|> = 1 + 2;
17// x * 4;
18// }
19// ```
20// ->
21// ```
22// fn main() {
23// (1 + 2) * 4;
24// }
25// ```
26pub(crate) fn inline_local_varialbe(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
27 let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?;
14 let bind_pat = match let_stmt.pat()? { 28 let bind_pat = match let_stmt.pat()? {
15 ast::Pat::BindPat(pat) => pat, 29 ast::Pat::BindPat(pat) => pat,
16 _ => return None, 30 _ => return None,
@@ -37,10 +51,8 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
37 let mut wrap_in_parens = vec![true; refs.len()]; 51 let mut wrap_in_parens = vec![true; refs.len()];
38 52
39 for (i, desc) in refs.iter().enumerate() { 53 for (i, desc) in refs.iter().enumerate() {
40 let usage_node = ctx 54 let usage_node =
41 .covering_node_for_range(desc.range) 55 ctx.covering_node_for_range(desc.range).ancestors().find_map(ast::PathExpr::cast)?;
42 .ancestors()
43 .find_map(|node| ast::PathExpr::cast(node))?;
44 let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast); 56 let usage_parent_option = usage_node.syntax().parent().and_then(ast::Expr::cast);
45 let usage_parent = match usage_parent_option { 57 let usage_parent = match usage_parent_option {
46 Some(u) => u, 58 Some(u) => u,
@@ -79,7 +91,7 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
79 let init_str = initializer_expr.syntax().text().to_string(); 91 let init_str = initializer_expr.syntax().text().to_string();
80 let init_in_paren = format!("({})", &init_str); 92 let init_in_paren = format!("({})", &init_str);
81 93
82 ctx.add_action( 94 ctx.add_assist(
83 AssistId("inline_local_variable"), 95 AssistId("inline_local_variable"),
84 "inline local variable", 96 "inline local variable",
85 move |edit: &mut AssistBuilder| { 97 move |edit: &mut AssistBuilder| {
@@ -93,9 +105,7 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
93 } 105 }
94 edit.set_cursor(delete_range.start()) 106 edit.set_cursor(delete_range.start())
95 }, 107 },
96 ); 108 )
97
98 ctx.build()
99} 109}
100 110
101#[cfg(test)] 111#[cfg(test)]
diff --git a/crates/ra_assists/src/assists/introduce_variable.rs b/crates/ra_assists/src/assists/introduce_variable.rs
index 43378c4b0..0623d4475 100644
--- a/crates/ra_assists/src/assists/introduce_variable.rs
+++ b/crates/ra_assists/src/assists/introduce_variable.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use format_buf::format; 1use format_buf::format;
4use hir::db::HirDatabase; 2use hir::db::HirDatabase;
5use ra_syntax::{ 3use ra_syntax::{
@@ -14,7 +12,23 @@ use test_utils::tested_by;
14 12
15use crate::{Assist, AssistCtx, AssistId}; 13use crate::{Assist, AssistCtx, AssistId};
16 14
17pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 15// Assist: introduce_variable
16//
17// Extracts subexpression into a variable.
18//
19// ```
20// fn main() {
21// <|>(1 + 2)<|> * 4;
22// }
23// ```
24// ->
25// ```
26// fn main() {
27// let var_name = (1 + 2);
28// var_name * 4;
29// }
30// ```
31pub(crate) fn introduce_variable(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
18 if ctx.frange.range.is_empty() { 32 if ctx.frange.range.is_empty() {
19 return None; 33 return None;
20 } 34 }
@@ -29,7 +43,7 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
29 if indent.kind() != WHITESPACE { 43 if indent.kind() != WHITESPACE {
30 return None; 44 return None;
31 } 45 }
32 ctx.add_action(AssistId("introduce_variable"), "introduce variable", move |edit| { 46 ctx.add_assist(AssistId("introduce_variable"), "introduce variable", move |edit| {
33 let mut buf = String::new(); 47 let mut buf = String::new();
34 48
35 let cursor_offset = if wrap_in_block { 49 let cursor_offset = if wrap_in_block {
@@ -74,9 +88,7 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
74 } 88 }
75 } 89 }
76 edit.set_cursor(anchor_stmt.text_range().start() + cursor_offset); 90 edit.set_cursor(anchor_stmt.text_range().start() + cursor_offset);
77 }); 91 })
78
79 ctx.build()
80} 92}
81 93
82/// Check whether the node is a valid expression which can be extracted to a variable. 94/// Check whether the node is a valid expression which can be extracted to a variable.
diff --git a/crates/ra_assists/src/assists/merge_match_arms.rs b/crates/ra_assists/src/assists/merge_match_arms.rs
index 17baa98f9..e9f2cae91 100644
--- a/crates/ra_assists/src/assists/merge_match_arms.rs
+++ b/crates/ra_assists/src/assists/merge_match_arms.rs
@@ -1,11 +1,33 @@
1//! FIXME: write short doc here
2
3use crate::{Assist, AssistCtx, AssistId, TextRange, TextUnit}; 1use crate::{Assist, AssistCtx, AssistId, TextRange, TextUnit};
4use hir::db::HirDatabase; 2use hir::db::HirDatabase;
5use ra_syntax::ast::{AstNode, MatchArm}; 3use ra_syntax::ast::{AstNode, MatchArm};
6 4
7pub(crate) fn merge_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 5// Assist: merge_match_arms
8 let current_arm = ctx.node_at_offset::<MatchArm>()?; 6//
7// Merges identical match arms.
8//
9// ```
10// enum Action { Move { distance: u32 }, Stop }
11//
12// fn handle(action: Action) {
13// match action {
14// <|>Action::Move(..) => foo(),
15// Action::Stop => foo(),
16// }
17// }
18// ```
19// ->
20// ```
21// enum Action { Move { distance: u32 }, Stop }
22//
23// fn handle(action: Action) {
24// match action {
25// Action::Move(..) | Action::Stop => foo(),
26// }
27// }
28// ```
29pub(crate) fn merge_match_arms(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
30 let current_arm = ctx.find_node_at_offset::<MatchArm>()?;
9 31
10 // We check if the following match arm matches this one. We could, but don't, 32 // We check if the following match arm matches this one. We could, but don't,
11 // compare to the previous match arm as well. 33 // compare to the previous match arm as well.
@@ -30,7 +52,7 @@ pub(crate) fn merge_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<A
30 52
31 let cursor_to_end = current_arm.syntax().text_range().end() - ctx.frange.range.start(); 53 let cursor_to_end = current_arm.syntax().text_range().end() - ctx.frange.range.start();
32 54
33 ctx.add_action(AssistId("merge_match_arms"), "merge match arms", |edit| { 55 ctx.add_assist(AssistId("merge_match_arms"), "merge match arms", |edit| {
34 fn contains_placeholder(a: &MatchArm) -> bool { 56 fn contains_placeholder(a: &MatchArm) -> bool {
35 a.pats().any(|x| match x { 57 a.pats().any(|x| match x {
36 ra_syntax::ast::Pat::PlaceholderPat(..) => true, 58 ra_syntax::ast::Pat::PlaceholderPat(..) => true,
@@ -58,9 +80,7 @@ pub(crate) fn merge_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<A
58 edit.target(current_arm.syntax().text_range()); 80 edit.target(current_arm.syntax().text_range());
59 edit.replace(TextRange::from_to(start, end), arm); 81 edit.replace(TextRange::from_to(start, end), arm);
60 edit.set_cursor(start + offset); 82 edit.set_cursor(start + offset);
61 }); 83 })
62
63 ctx.build()
64} 84}
65 85
66#[cfg(test)] 86#[cfg(test)]
diff --git a/crates/ra_assists/src/assists/move_bounds.rs b/crates/ra_assists/src/assists/move_bounds.rs
index d2444b6b9..3145d7625 100644
--- a/crates/ra_assists/src/assists/move_bounds.rs
+++ b/crates/ra_assists/src/assists/move_bounds.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use hir::db::HirDatabase; 1use hir::db::HirDatabase;
4use ra_syntax::{ 2use ra_syntax::{
5 ast::{self, edit, make, AstNode, NameOwner, TypeBoundsOwner}, 3 ast::{self, edit, make, AstNode, NameOwner, TypeBoundsOwner},
@@ -9,8 +7,23 @@ use ra_syntax::{
9 7
10use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
11 9
12pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10// Assist: move_bounds_to_where_clause
13 let type_param_list = ctx.node_at_offset::<ast::TypeParamList>()?; 11//
12// Moves inline type bounds to a where clause.
13//
14// ```
15// fn apply<T, U, <|>F: FnOnce(T) -> U>(f: F, x: T) -> U {
16// f(x)
17// }
18// ```
19// ->
20// ```
21// fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
22// f(x)
23// }
24// ```
25pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
26 let type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?;
14 27
15 let mut type_params = type_param_list.type_params(); 28 let mut type_params = type_param_list.type_params();
16 if type_params.all(|p| p.type_bound_list().is_none()) { 29 if type_params.all(|p| p.type_bound_list().is_none()) {
@@ -33,38 +46,30 @@ pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx<impl HirDatabase>)
33 _ => return None, 46 _ => return None,
34 }; 47 };
35 48
36 ctx.add_action( 49 ctx.add_assist(AssistId("move_bounds_to_where_clause"), "move_bounds_to_where_clause", |edit| {
37 AssistId("move_bounds_to_where_clause"), 50 let new_params = type_param_list
38 "move_bounds_to_where_clause", 51 .type_params()
39 |edit| { 52 .filter(|it| it.type_bound_list().is_some())
40 let new_params = type_param_list 53 .map(|type_param| {
41 .type_params() 54 let without_bounds = type_param.remove_bounds();
42 .filter(|it| it.type_bound_list().is_some()) 55 (type_param, without_bounds)
43 .map(|type_param| { 56 });
44 let without_bounds = type_param.remove_bounds(); 57
45 (type_param, without_bounds) 58 let new_type_param_list = edit::replace_descendants(&type_param_list, new_params);
46 }); 59 edit.replace_ast(type_param_list.clone(), new_type_param_list);
47 60
48 let new_type_param_list = edit::replace_descendants(&type_param_list, new_params); 61 let where_clause = {
49 edit.replace_ast(type_param_list.clone(), new_type_param_list); 62 let predicates = type_param_list.type_params().filter_map(build_predicate);
50 63 make::where_clause(predicates)
51 let where_clause = { 64 };
52 let predicates = type_param_list.type_params().filter_map(build_predicate); 65
53 make::where_clause(predicates) 66 let to_insert = match anchor.prev_sibling_or_token() {
54 }; 67 Some(ref elem) if elem.kind() == WHITESPACE => format!("{} ", where_clause.syntax()),
55 68 _ => format!(" {}", where_clause.syntax()),
56 let to_insert = match anchor.prev_sibling_or_token() { 69 };
57 Some(ref elem) if elem.kind() == WHITESPACE => { 70 edit.insert(anchor.text_range().start(), to_insert);
58 format!("{} ", where_clause.syntax()) 71 edit.target(type_param_list.syntax().text_range());
59 } 72 })
60 _ => format!(" {}", where_clause.syntax()),
61 };
62 edit.insert(anchor.text_range().start(), to_insert);
63 edit.target(type_param_list.syntax().text_range());
64 },
65 );
66
67 ctx.build()
68} 73}
69 74
70fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> { 75fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> {
diff --git a/crates/ra_assists/src/assists/move_guard.rs b/crates/ra_assists/src/assists/move_guard.rs
index 51aea6334..b49ec6172 100644
--- a/crates/ra_assists/src/assists/move_guard.rs
+++ b/crates/ra_assists/src/assists/move_guard.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use hir::db::HirDatabase; 1use hir::db::HirDatabase;
4use ra_syntax::{ 2use ra_syntax::{
5 ast, 3 ast,
@@ -9,8 +7,33 @@ use ra_syntax::{
9 7
10use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
11 9
12pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10// Assist: move_guard_to_arm_body
13 let match_arm = ctx.node_at_offset::<MatchArm>()?; 11//
12// Moves match guard into match arm body.
13//
14// ```
15// enum Action { Move { distance: u32 }, Stop }
16//
17// fn handle(action: Action) {
18// match action {
19// Action::Move { distance } <|>if distance > 10 => foo(),
20// _ => (),
21// }
22// }
23// ```
24// ->
25// ```
26// enum Action { Move { distance: u32 }, Stop }
27//
28// fn handle(action: Action) {
29// match action {
30// Action::Move { distance } => if distance > 10 { foo() },
31// _ => (),
32// }
33// }
34// ```
35pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
36 let match_arm = ctx.find_node_at_offset::<MatchArm>()?;
14 let guard = match_arm.guard()?; 37 let guard = match_arm.guard()?;
15 let space_before_guard = guard.syntax().prev_sibling_or_token(); 38 let space_before_guard = guard.syntax().prev_sibling_or_token();
16 39
@@ -18,7 +41,7 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
18 let arm_expr = match_arm.expr()?; 41 let arm_expr = match_arm.expr()?;
19 let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); 42 let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text());
20 43
21 ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| { 44 ctx.add_assist(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| {
22 edit.target(guard.syntax().text_range()); 45 edit.target(guard.syntax().text_range());
23 let offseting_amount = match space_before_guard.and_then(|it| it.into_token()) { 46 let offseting_amount = match space_before_guard.and_then(|it| it.into_token()) {
24 Some(tok) => { 47 Some(tok) => {
@@ -38,12 +61,36 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
38 edit.set_cursor( 61 edit.set_cursor(
39 arm_expr.syntax().text_range().start() + TextUnit::from(3) - offseting_amount, 62 arm_expr.syntax().text_range().start() + TextUnit::from(3) - offseting_amount,
40 ); 63 );
41 }); 64 })
42 ctx.build()
43} 65}
44 66
45pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 67// Assist: move_arm_cond_to_match_guard
46 let match_arm: MatchArm = ctx.node_at_offset::<MatchArm>()?; 68//
69// Moves if expression from match arm body into a guard.
70//
71// ```
72// enum Action { Move { distance: u32 }, Stop }
73//
74// fn handle(action: Action) {
75// match action {
76// Action::Move { distance } => <|>if distance > 10 { foo() },
77// _ => (),
78// }
79// }
80// ```
81// ->
82// ```
83// enum Action { Move { distance: u32 }, Stop }
84//
85// fn handle(action: Action) {
86// match action {
87// Action::Move { distance } if distance > 10 => foo(),
88// _ => (),
89// }
90// }
91// ```
92pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
93 let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
47 let last_match_pat = match_arm.pats().last()?; 94 let last_match_pat = match_arm.pats().last()?;
48 95
49 let arm_body = match_arm.expr()?; 96 let arm_body = match_arm.expr()?;
@@ -62,7 +109,7 @@ pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>)
62 109
63 let buf = format!(" if {}", cond.syntax().text()); 110 let buf = format!(" if {}", cond.syntax().text());
64 111
65 ctx.add_action( 112 ctx.add_assist(
66 AssistId("move_arm_cond_to_match_guard"), 113 AssistId("move_arm_cond_to_match_guard"),
67 "move condition to match guard", 114 "move condition to match guard",
68 |edit| { 115 |edit| {
@@ -79,8 +126,7 @@ pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>)
79 edit.insert(last_match_pat.syntax().text_range().end(), buf); 126 edit.insert(last_match_pat.syntax().text_range().end(), buf);
80 edit.set_cursor(last_match_pat.syntax().text_range().end() + TextUnit::from(1)); 127 edit.set_cursor(last_match_pat.syntax().text_range().end() + TextUnit::from(1));
81 }, 128 },
82 ); 129 )
83 ctx.build()
84} 130}
85 131
86#[cfg(test)] 132#[cfg(test)]
diff --git a/crates/ra_assists/src/assists/raw_string.rs b/crates/ra_assists/src/assists/raw_string.rs
index 2d2e31e51..58f7157ae 100644
--- a/crates/ra_assists/src/assists/raw_string.rs
+++ b/crates/ra_assists/src/assists/raw_string.rs
@@ -1,17 +1,29 @@
1//! FIXME: write short doc here
2
3use hir::db::HirDatabase; 1use hir::db::HirDatabase;
4use ra_syntax::{ast::AstNode, ast::Literal, TextRange, TextUnit}; 2use ra_syntax::{
3 SyntaxKind::{RAW_STRING, STRING},
4 TextRange, TextUnit,
5};
5use rustc_lexer; 6use rustc_lexer;
6 7
7use crate::{Assist, AssistCtx, AssistId}; 8use crate::{Assist, AssistCtx, AssistId};
8 9
9pub(crate) fn make_raw_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10// Assist: make_raw_string
10 let literal = ctx.node_at_offset::<Literal>()?; 11//
11 if literal.token().kind() != ra_syntax::SyntaxKind::STRING { 12// Adds `r#` to a plain string literal.
12 return None; 13//
13 } 14// ```
14 let token = literal.token(); 15// fn main() {
16// "Hello,<|> World!";
17// }
18// ```
19// ->
20// ```
21// fn main() {
22// r#"Hello, World!"#;
23// }
24// ```
25pub(crate) fn make_raw_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
26 let token = ctx.find_token_at_offset(STRING)?;
15 let text = token.text().as_str(); 27 let text = token.text().as_str();
16 let usual_string_range = find_usual_string_range(text)?; 28 let usual_string_range = find_usual_string_range(text)?;
17 let start_of_inside = usual_string_range.start().to_usize() + 1; 29 let start_of_inside = usual_string_range.start().to_usize() + 1;
@@ -29,97 +41,131 @@ pub(crate) fn make_raw_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
29 if error.is_err() { 41 if error.is_err() {
30 return None; 42 return None;
31 } 43 }
32 ctx.add_action(AssistId("make_raw_string"), "make raw string", |edit| { 44 ctx.add_assist(AssistId("make_raw_string"), "make raw string", |edit| {
33 edit.target(literal.syntax().text_range()); 45 edit.target(token.text_range());
34 let max_hash_streak = count_hashes(&unescaped); 46 let max_hash_streak = count_hashes(&unescaped);
35 let mut hashes = String::with_capacity(max_hash_streak + 1); 47 let mut hashes = String::with_capacity(max_hash_streak + 1);
36 for _ in 0..hashes.capacity() { 48 for _ in 0..hashes.capacity() {
37 hashes.push('#'); 49 hashes.push('#');
38 } 50 }
39 edit.replace( 51 edit.replace(token.text_range(), format!("r{}\"{}\"{}", hashes, unescaped, hashes));
40 literal.syntax().text_range(), 52 })
41 format!("r{}\"{}\"{}", hashes, unescaped, hashes),
42 );
43 });
44 ctx.build()
45}
46
47fn count_hashes(s: &str) -> usize {
48 let mut max_hash_streak = 0usize;
49 for idx in s.match_indices("\"#").map(|(i, _)| i) {
50 let (_, sub) = s.split_at(idx + 1);
51 let nb_hash = sub.chars().take_while(|c| *c == '#').count();
52 if nb_hash > max_hash_streak {
53 max_hash_streak = nb_hash;
54 }
55 }
56 max_hash_streak
57}
58
59fn find_usual_string_range(s: &str) -> Option<TextRange> {
60 Some(TextRange::from_to(
61 TextUnit::from(s.find('"')? as u32),
62 TextUnit::from(s.rfind('"')? as u32),
63 ))
64} 53}
65 54
66pub(crate) fn make_usual_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 55// Assist: make_usual_string
67 let literal = ctx.node_at_offset::<Literal>()?; 56//
68 if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { 57// Turns a raw string into a plain string.
69 return None; 58//
70 } 59// ```
71 let token = literal.token(); 60// fn main() {
61// r#"Hello,<|> "World!""#;
62// }
63// ```
64// ->
65// ```
66// fn main() {
67// "Hello, \"World!\"";
68// }
69// ```
70pub(crate) fn make_usual_string(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
71 let token = ctx.find_token_at_offset(RAW_STRING)?;
72 let text = token.text().as_str(); 72 let text = token.text().as_str();
73 let usual_string_range = find_usual_string_range(text)?; 73 let usual_string_range = find_usual_string_range(text)?;
74 ctx.add_action(AssistId("make_usual_string"), "make usual string", |edit| { 74 ctx.add_assist(AssistId("make_usual_string"), "make usual string", |edit| {
75 edit.target(literal.syntax().text_range()); 75 edit.target(token.text_range());
76 // parse inside string to escape `"` 76 // parse inside string to escape `"`
77 let start_of_inside = usual_string_range.start().to_usize() + 1; 77 let start_of_inside = usual_string_range.start().to_usize() + 1;
78 let end_of_inside = usual_string_range.end().to_usize(); 78 let end_of_inside = usual_string_range.end().to_usize();
79 let inside_str = &text[start_of_inside..end_of_inside]; 79 let inside_str = &text[start_of_inside..end_of_inside];
80 let escaped = inside_str.escape_default().to_string(); 80 let escaped = inside_str.escape_default().to_string();
81 edit.replace(literal.syntax().text_range(), format!("\"{}\"", escaped)); 81 edit.replace(token.text_range(), format!("\"{}\"", escaped));
82 }); 82 })
83 ctx.build()
84} 83}
85 84
86pub(crate) fn add_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 85// Assist: add_hash
87 let literal = ctx.node_at_offset::<Literal>()?; 86//
88 if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { 87// Adds a hash to a raw string literal.
89 return None; 88//
90 } 89// ```
91 ctx.add_action(AssistId("add_hash"), "add hash to raw string", |edit| { 90// fn main() {
92 edit.target(literal.syntax().text_range()); 91// r#"Hello,<|> World!"#;
93 edit.insert(literal.syntax().text_range().start() + TextUnit::of_char('r'), "#"); 92// }
94 edit.insert(literal.syntax().text_range().end(), "#"); 93// ```
95 }); 94// ->
96 ctx.build() 95// ```
96// fn main() {
97// r##"Hello, World!"##;
98// }
99// ```
100pub(crate) fn add_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
101 let token = ctx.find_token_at_offset(RAW_STRING)?;
102 ctx.add_assist(AssistId("add_hash"), "add hash to raw string", |edit| {
103 edit.target(token.text_range());
104 edit.insert(token.text_range().start() + TextUnit::of_char('r'), "#");
105 edit.insert(token.text_range().end(), "#");
106 })
97} 107}
98 108
99pub(crate) fn remove_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 109// Assist: remove_hash
100 let literal = ctx.node_at_offset::<Literal>()?; 110//
101 if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { 111// Removes a hash from a raw string literal.
102 return None; 112//
103 } 113// ```
104 let token = literal.token(); 114// fn main() {
115// r#"Hello,<|> World!"#;
116// }
117// ```
118// ->
119// ```
120// fn main() {
121// r"Hello, World!";
122// }
123// ```
124pub(crate) fn remove_hash(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
125 let token = ctx.find_token_at_offset(RAW_STRING)?;
105 let text = token.text().as_str(); 126 let text = token.text().as_str();
106 if text.starts_with("r\"") { 127 if text.starts_with("r\"") {
107 // no hash to remove 128 // no hash to remove
108 return None; 129 return None;
109 } 130 }
110 ctx.add_action(AssistId("remove_hash"), "remove hash from raw string", |edit| { 131 ctx.add_assist(AssistId("remove_hash"), "remove hash from raw string", |edit| {
111 edit.target(literal.syntax().text_range()); 132 edit.target(token.text_range());
112 let result = &text[2..text.len() - 1]; 133 let result = &text[2..text.len() - 1];
113 let result = if result.starts_with("\"") { 134 let result = if result.starts_with('\"') {
114 // no more hash, escape 135 // no more hash, escape
115 let internal_str = &result[1..result.len() - 1]; 136 let internal_str = &result[1..result.len() - 1];
116 format!("\"{}\"", internal_str.escape_default().to_string()) 137 format!("\"{}\"", internal_str.escape_default().to_string())
117 } else { 138 } else {
118 result.to_owned() 139 result.to_owned()
119 }; 140 };
120 edit.replace(literal.syntax().text_range(), format!("r{}", result)); 141 edit.replace(token.text_range(), format!("r{}", result));
121 }); 142 })
122 ctx.build() 143}
144
145fn count_hashes(s: &str) -> usize {
146 let mut max_hash_streak = 0usize;
147 for idx in s.match_indices("\"#").map(|(i, _)| i) {
148 let (_, sub) = s.split_at(idx + 1);
149 let nb_hash = sub.chars().take_while(|c| *c == '#').count();
150 if nb_hash > max_hash_streak {
151 max_hash_streak = nb_hash;
152 }
153 }
154 max_hash_streak
155}
156
157fn find_usual_string_range(s: &str) -> Option<TextRange> {
158 let left_quote = s.find('"')?;
159 let right_quote = s.rfind('"')?;
160 if left_quote == right_quote {
161 // `s` only contains one quote
162 None
163 } else {
164 Some(TextRange::from_to(
165 TextUnit::from(left_quote as u32),
166 TextUnit::from(right_quote as u32),
167 ))
168 }
123} 169}
124 170
125#[cfg(test)] 171#[cfg(test)]
@@ -159,6 +205,23 @@ string"#;
159 } 205 }
160 206
161 #[test] 207 #[test]
208 fn make_raw_string_works_inside_macros() {
209 check_assist(
210 make_raw_string,
211 r#"
212 fn f() {
213 format!(<|>"x = {}", 92)
214 }
215 "#,
216 r##"
217 fn f() {
218 format!(<|>r#"x = {}"#, 92)
219 }
220 "##,
221 )
222 }
223
224 #[test]
162 fn make_raw_string_hashes_inside_works() { 225 fn make_raw_string_hashes_inside_works() {
163 check_assist( 226 check_assist(
164 make_raw_string, 227 make_raw_string,
@@ -212,6 +275,30 @@ string"###;
212 } 275 }
213 276
214 #[test] 277 #[test]
278 fn make_raw_string_not_works_on_partial_string() {
279 check_assist_not_applicable(
280 make_raw_string,
281 r#"
282 fn f() {
283 let s = "foo<|>
284 }
285 "#,
286 )
287 }
288
289 #[test]
290 fn make_usual_string_not_works_on_partial_string() {
291 check_assist_not_applicable(
292 make_usual_string,
293 r#"
294 fn main() {
295 let s = r#"bar<|>
296 }
297 "#,
298 )
299 }
300
301 #[test]
215 fn add_hash_target() { 302 fn add_hash_target() {
216 check_assist_target( 303 check_assist_target(
217 add_hash, 304 add_hash,
diff --git a/crates/ra_assists/src/assists/remove_dbg.rs b/crates/ra_assists/src/assists/remove_dbg.rs
index 1a7e2b305..aedf8747f 100644
--- a/crates/ra_assists/src/assists/remove_dbg.rs
+++ b/crates/ra_assists/src/assists/remove_dbg.rs
@@ -1,14 +1,28 @@
1//! FIXME: write short doc here
2
3use crate::{Assist, AssistCtx, AssistId};
4use hir::db::HirDatabase; 1use hir::db::HirDatabase;
5use ra_syntax::{ 2use ra_syntax::{
6 ast::{self, AstNode}, 3 ast::{self, AstNode},
7 TextUnit, T, 4 TextUnit, T,
8}; 5};
9 6
10pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 7use crate::{Assist, AssistCtx, AssistId};
11 let macro_call = ctx.node_at_offset::<ast::MacroCall>()?; 8
9// Assist: remove_dbg
10//
11// Removes `dbg!()` macro call.
12//
13// ```
14// fn main() {
15// <|>dbg!(92);
16// }
17// ```
18// ->
19// ```
20// fn main() {
21// 92;
22// }
23// ```
24pub(crate) fn remove_dbg(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
25 let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
12 26
13 if !is_valid_macrocall(&macro_call, "dbg")? { 27 if !is_valid_macrocall(&macro_call, "dbg")? {
14 return None; 28 return None;
@@ -44,13 +58,11 @@ pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
44 text.slice(without_parens).to_string() 58 text.slice(without_parens).to_string()
45 }; 59 };
46 60
47 ctx.add_action(AssistId("remove_dbg"), "remove dbg!()", |edit| { 61 ctx.add_assist(AssistId("remove_dbg"), "remove dbg!()", |edit| {
48 edit.target(macro_call.syntax().text_range()); 62 edit.target(macro_call.syntax().text_range());
49 edit.replace(macro_range, macro_content); 63 edit.replace(macro_range, macro_content);
50 edit.set_cursor(cursor_pos); 64 edit.set_cursor(cursor_pos);
51 }); 65 })
52
53 ctx.build()
54} 66}
55 67
56/// Verifies that the given macro_call actually matches the given name 68/// Verifies that the given macro_call actually matches the given name
diff --git a/crates/ra_assists/src/assists/replace_if_let_with_match.rs b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
index 749ff338a..dff84d865 100644
--- a/crates/ra_assists/src/assists/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use format_buf::format; 1use format_buf::format;
4use hir::db::HirDatabase; 2use hir::db::HirDatabase;
5use ra_fmt::extract_trivial_expression; 3use ra_fmt::extract_trivial_expression;
@@ -7,8 +5,34 @@ use ra_syntax::{ast, AstNode};
7 5
8use crate::{Assist, AssistCtx, AssistId}; 6use crate::{Assist, AssistCtx, AssistId};
9 7
10pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 8// Assist: replace_if_let_with_match
11 let if_expr: ast::IfExpr = ctx.node_at_offset()?; 9//
10// Replaces `if let` with an else branch with a `match` expression.
11//
12// ```
13// enum Action { Move { distance: u32 }, Stop }
14//
15// fn handle(action: Action) {
16// <|>if let Action::Move { distance } = action {
17// foo(distance)
18// } else {
19// bar()
20// }
21// }
22// ```
23// ->
24// ```
25// enum Action { Move { distance: u32 }, Stop }
26//
27// fn handle(action: Action) {
28// match action {
29// Action::Move { distance } => foo(distance),
30// _ => bar(),
31// }
32// }
33// ```
34pub(crate) fn replace_if_let_with_match(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
35 let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
12 let cond = if_expr.condition()?; 36 let cond = if_expr.condition()?;
13 let pat = cond.pat()?; 37 let pat = cond.pat()?;
14 let expr = cond.expr()?; 38 let expr = cond.expr()?;
@@ -18,14 +42,12 @@ pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) ->
18 ast::ElseBranch::IfExpr(_) => return None, 42 ast::ElseBranch::IfExpr(_) => return None,
19 }; 43 };
20 44
21 ctx.add_action(AssistId("replace_if_let_with_match"), "replace with match", |edit| { 45 ctx.add_assist(AssistId("replace_if_let_with_match"), "replace with match", |edit| {
22 let match_expr = build_match_expr(expr, pat, then_block, else_block); 46 let match_expr = build_match_expr(expr, pat, then_block, else_block);
23 edit.target(if_expr.syntax().text_range()); 47 edit.target(if_expr.syntax().text_range());
24 edit.replace_node_and_indent(if_expr.syntax(), match_expr); 48 edit.replace_node_and_indent(if_expr.syntax(), match_expr);
25 edit.set_cursor(if_expr.syntax().text_range().start()) 49 edit.set_cursor(if_expr.syntax().text_range().start())
26 }); 50 })
27
28 ctx.build()
29} 51}
30 52
31fn build_match_expr( 53fn build_match_expr(
diff --git a/crates/ra_assists/src/assists/split_import.rs b/crates/ra_assists/src/assists/split_import.rs
index fe3e64af5..5f8d6b0be 100644
--- a/crates/ra_assists/src/assists/split_import.rs
+++ b/crates/ra_assists/src/assists/split_import.rs
@@ -1,5 +1,3 @@
1//! FIXME: write short doc here
2
3use std::iter::successors; 1use std::iter::successors;
4 2
5use hir::db::HirDatabase; 3use hir::db::HirDatabase;
@@ -7,8 +5,19 @@ use ra_syntax::{ast, AstNode, TextUnit, T};
7 5
8use crate::{Assist, AssistCtx, AssistId}; 6use crate::{Assist, AssistCtx, AssistId};
9 7
10pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 8// Assist: split_import
11 let colon_colon = ctx.token_at_offset().find(|leaf| leaf.kind() == T![::])?; 9//
10// Wraps the tail of import into braces.
11//
12// ```
13// use std::<|>collections::HashMap;
14// ```
15// ->
16// ```
17// use std::{collections::HashMap};
18// ```
19pub(crate) fn split_import(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
20 let colon_colon = ctx.find_token_at_offset(T![::])?;
12 let path = ast::Path::cast(colon_colon.parent())?; 21 let path = ast::Path::cast(colon_colon.parent())?;
13 let top_path = successors(Some(path), |it| it.parent_path()).last()?; 22 let top_path = successors(Some(path), |it| it.parent_path()).last()?;
14 23
@@ -23,14 +32,12 @@ pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assis
23 None => top_path.syntax().text_range().end(), 32 None => top_path.syntax().text_range().end(),
24 }; 33 };
25 34
26 ctx.add_action(AssistId("split_import"), "split import", |edit| { 35 ctx.add_assist(AssistId("split_import"), "split import", |edit| {
27 edit.target(colon_colon.text_range()); 36 edit.target(colon_colon.text_range());
28 edit.insert(l_curly, "{"); 37 edit.insert(l_curly, "{");
29 edit.insert(r_curly, "}"); 38 edit.insert(r_curly, "}");
30 edit.set_cursor(l_curly + TextUnit::of_str("{")); 39 edit.set_cursor(l_curly + TextUnit::of_str("{"));
31 }); 40 })
32
33 ctx.build()
34} 41}
35 42
36#[cfg(test)] 43#[cfg(test)]
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs
new file mode 100644
index 000000000..6e1e3de84
--- /dev/null
+++ b/crates/ra_assists/src/doc_tests.rs
@@ -0,0 +1,34 @@
1//! Each assist definition has a special comment, which specifies docs and
2//! example.
3//!
4//! We collect all the example and write the as tests in this module.
5
6mod generated;
7
8use hir::mock::MockDatabase;
9use ra_db::FileRange;
10use test_utils::{assert_eq_text, extract_range_or_offset};
11
12fn check(assist_id: &str, before: &str, after: &str) {
13 let (selection, before) = extract_range_or_offset(before);
14 let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
15 let frange = FileRange { file_id, range: selection.into() };
16
17 let (_assist_id, action) = crate::assists(&db, frange)
18 .into_iter()
19 .find(|(id, _)| id.id.0 == assist_id)
20 .unwrap_or_else(|| {
21 panic!(
22 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
23 assist_id,
24 crate::assists(&db, frange)
25 .into_iter()
26 .map(|(id, _)| id.id.0)
27 .collect::<Vec<_>>()
28 .join(", ")
29 )
30 });
31
32 let actual = action.edit.apply(&before);
33 assert_eq_text!(after, &actual);
34}
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs
new file mode 100644
index 000000000..1bee76f59
--- /dev/null
+++ b/crates/ra_assists/src/doc_tests/generated.rs
@@ -0,0 +1,526 @@
1//! Generated file, do not edit by hand, see `crate/ra_tools/src/codegen`
2
3use super::check;
4
5#[test]
6fn doctest_add_derive() {
7 check(
8 "add_derive",
9 r#####"
10struct Point {
11 x: u32,
12 y: u32,<|>
13}
14"#####,
15 r#####"
16#[derive()]
17struct Point {
18 x: u32,
19 y: u32,
20}
21"#####,
22 )
23}
24
25#[test]
26fn doctest_add_explicit_type() {
27 check(
28 "add_explicit_type",
29 r#####"
30fn main() {
31 let x<|> = 92;
32}
33"#####,
34 r#####"
35fn main() {
36 let x: i32 = 92;
37}
38"#####,
39 )
40}
41
42#[test]
43fn doctest_add_hash() {
44 check(
45 "add_hash",
46 r#####"
47fn main() {
48 r#"Hello,<|> World!"#;
49}
50"#####,
51 r#####"
52fn main() {
53 r##"Hello, World!"##;
54}
55"#####,
56 )
57}
58
59#[test]
60fn doctest_add_impl() {
61 check(
62 "add_impl",
63 r#####"
64struct Ctx<T: Clone> {
65 data: T,<|>
66}
67"#####,
68 r#####"
69struct Ctx<T: Clone> {
70 data: T,
71}
72
73impl<T: Clone> Ctx<T> {
74
75}
76"#####,
77 )
78}
79
80#[test]
81fn doctest_add_impl_default_members() {
82 check(
83 "add_impl_default_members",
84 r#####"
85trait T {
86 Type X;
87 fn foo(&self);
88 fn bar(&self) {}
89}
90
91impl T for () {
92 Type X = ();
93 fn foo(&self) {}<|>
94
95}
96"#####,
97 r#####"
98trait T {
99 Type X;
100 fn foo(&self);
101 fn bar(&self) {}
102}
103
104impl T for () {
105 Type X = ();
106 fn foo(&self) {}
107 fn bar(&self) {}
108
109}
110"#####,
111 )
112}
113
114#[test]
115fn doctest_add_impl_missing_members() {
116 check(
117 "add_impl_missing_members",
118 r#####"
119trait T {
120 Type X;
121 fn foo(&self);
122 fn bar(&self) {}
123}
124
125impl T for () {<|>
126
127}
128"#####,
129 r#####"
130trait T {
131 Type X;
132 fn foo(&self);
133 fn bar(&self) {}
134}
135
136impl T for () {
137 fn foo(&self) { unimplemented!() }
138
139}
140"#####,
141 )
142}
143
144#[test]
145fn doctest_add_import() {
146 check(
147 "add_import",
148 r#####"
149fn process(map: std::collections::<|>HashMap<String, String>) {}
150"#####,
151 r#####"
152use std::collections::HashMap;
153
154fn process(map: HashMap<String, String>) {}
155"#####,
156 )
157}
158
159#[test]
160fn doctest_apply_demorgan() {
161 check(
162 "apply_demorgan",
163 r#####"
164fn main() {
165 if x != 4 ||<|> !y {}
166}
167"#####,
168 r#####"
169fn main() {
170 if !(x == 4 && y) {}
171}
172"#####,
173 )
174}
175
176#[test]
177fn doctest_change_visibility() {
178 check(
179 "change_visibility",
180 r#####"
181<|>fn frobnicate() {}
182"#####,
183 r#####"
184pub(crate) fn frobnicate() {}
185"#####,
186 )
187}
188
189#[test]
190fn doctest_convert_to_guarded_return() {
191 check(
192 "convert_to_guarded_return",
193 r#####"
194fn main() {
195 <|>if cond {
196 foo();
197 bar();
198 }
199}
200"#####,
201 r#####"
202fn main() {
203 if !cond {
204 return;
205 }
206 foo();
207 bar();
208}
209"#####,
210 )
211}
212
213#[test]
214fn doctest_fill_match_arms() {
215 check(
216 "fill_match_arms",
217 r#####"
218enum Action { Move { distance: u32 }, Stop }
219
220fn handle(action: Action) {
221 match action {
222 <|>
223 }
224}
225"#####,
226 r#####"
227enum Action { Move { distance: u32 }, Stop }
228
229fn handle(action: Action) {
230 match action {
231 Action::Move { distance } => (),
232 Action::Stop => (),
233 }
234}
235"#####,
236 )
237}
238
239#[test]
240fn doctest_flip_binexpr() {
241 check(
242 "flip_binexpr",
243 r#####"
244fn main() {
245 let _ = 90 +<|> 2;
246}
247"#####,
248 r#####"
249fn main() {
250 let _ = 2 + 90;
251}
252"#####,
253 )
254}
255
256#[test]
257fn doctest_flip_comma() {
258 check(
259 "flip_comma",
260 r#####"
261fn main() {
262 ((1, 2),<|> (3, 4));
263}
264"#####,
265 r#####"
266fn main() {
267 ((3, 4), (1, 2));
268}
269"#####,
270 )
271}
272
273#[test]
274fn doctest_flip_trait_bound() {
275 check(