aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/release.yaml16
-rw-r--r--Cargo.lock199
-rw-r--r--crates/ra_assists/src/assist_config.rs27
-rw-r--r--crates/ra_assists/src/assist_context.rs257
-rw-r--r--crates/ra_assists/src/assist_ctx.rs257
-rw-r--r--crates/ra_assists/src/ast_transform.rs24
-rw-r--r--crates/ra_assists/src/doc_tests.rs35
-rw-r--r--crates/ra_assists/src/handlers/add_custom_impl.rs65
-rw-r--r--crates/ra_assists/src/handlers/add_derive.rs37
-rw-r--r--crates/ra_assists/src/handlers/add_explicit_type.rs50
-rw-r--r--crates/ra_assists/src/handlers/add_from_impl_for_enum.rs44
-rw-r--r--crates/ra_assists/src/handlers/add_function.rs355
-rw-r--r--crates/ra_assists/src/handlers/add_impl.rs42
-rw-r--r--crates/ra_assists/src/handlers/add_missing_impl_members.rs341
-rw-r--r--crates/ra_assists/src/handlers/add_new.rs71
-rw-r--r--crates/ra_assists/src/handlers/add_turbo_fish.rs134
-rw-r--r--crates/ra_assists/src/handlers/apply_demorgan.rs17
-rw-r--r--crates/ra_assists/src/handlers/auto_import.rs109
-rw-r--r--crates/ra_assists/src/handlers/change_return_type_to_result.rs961
-rw-r--r--crates/ra_assists/src/handlers/change_visibility.rs96
-rw-r--r--crates/ra_assists/src/handlers/early_return.rs55
-rw-r--r--crates/ra_assists/src/handlers/fill_match_arms.rs237
-rw-r--r--crates/ra_assists/src/handlers/fix_visibility.rs559
-rw-r--r--crates/ra_assists/src/handlers/flip_binexpr.rs23
-rw-r--r--crates/ra_assists/src/handlers/flip_comma.rs11
-rw-r--r--crates/ra_assists/src/handlers/flip_trait_bound.rs24
-rw-r--r--crates/ra_assists/src/handlers/inline_local_variable.rs95
-rw-r--r--crates/ra_assists/src/handlers/introduce_variable.rs140
-rw-r--r--crates/ra_assists/src/handlers/invert_if.rs45
-rw-r--r--crates/ra_assists/src/handlers/merge_imports.rs38
-rw-r--r--crates/ra_assists/src/handlers/merge_match_arms.rs34
-rw-r--r--crates/ra_assists/src/handlers/move_bounds.rs18
-rw-r--r--crates/ra_assists/src/handlers/move_guard.rs54
-rw-r--r--crates/ra_assists/src/handlers/raw_string.rs54
-rw-r--r--crates/ra_assists/src/handlers/remove_dbg.rs47
-rw-r--r--crates/ra_assists/src/handlers/remove_mut.rs10
-rw-r--r--crates/ra_assists/src/handlers/reorder_fields.rs39
-rw-r--r--crates/ra_assists/src/handlers/replace_if_let_with_match.rs54
-rw-r--r--crates/ra_assists/src/handlers/replace_let_with_if_let.rs24
-rw-r--r--crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs61
-rw-r--r--crates/ra_assists/src/handlers/replace_unwrap_with_match.rs60
-rw-r--r--crates/ra_assists/src/handlers/split_import.rs16
-rw-r--r--crates/ra_assists/src/handlers/unwrap_block.rs512
-rw-r--r--crates/ra_assists/src/lib.rs307
-rw-r--r--crates/ra_assists/src/marks.rs12
-rw-r--r--crates/ra_assists/src/tests.rs153
-rw-r--r--crates/ra_assists/src/tests/generated.rs (renamed from crates/ra_assists/src/doc_tests/generated.rs)174
-rw-r--r--crates/ra_assists/src/utils.rs94
-rw-r--r--crates/ra_assists/src/utils/insert_use.rs11
-rw-r--r--crates/ra_cfg/src/lib.rs7
-rw-r--r--crates/ra_db/src/fixture.rs60
-rw-r--r--crates/ra_flycheck/Cargo.toml10
-rw-r--r--crates/ra_flycheck/src/conv.rs341
-rw-r--r--crates/ra_flycheck/src/conv/test.rs1072
-rw-r--r--crates/ra_flycheck/src/lib.rs108
-rw-r--r--crates/ra_fmt/src/lib.rs1
-rw-r--r--crates/ra_hir/src/code_model.rs61
-rw-r--r--crates/ra_hir/src/semantics.rs19
-rw-r--r--crates/ra_hir/src/semantics/source_to_def.rs2
-rw-r--r--crates/ra_hir/src/source_analyzer.rs52
-rw-r--r--crates/ra_hir_def/src/adt.rs15
-rw-r--r--crates/ra_hir_def/src/attr.rs1
-rw-r--r--crates/ra_hir_def/src/body.rs11
-rw-r--r--crates/ra_hir_def/src/body/lower.rs63
-rw-r--r--crates/ra_hir_def/src/body/scope.rs4
-rw-r--r--crates/ra_hir_def/src/data.rs194
-rw-r--r--crates/ra_hir_def/src/db.rs22
-rw-r--r--crates/ra_hir_def/src/expr.rs4
-rw-r--r--crates/ra_hir_def/src/find_path.rs105
-rw-r--r--crates/ra_hir_def/src/item_scope.rs11
-rw-r--r--crates/ra_hir_def/src/lib.rs2
-rw-r--r--crates/ra_hir_def/src/marks.rs17
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs29
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs8
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs51
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs10
-rw-r--r--crates/ra_hir_def/src/nameres/tests/globs.rs7
-rw-r--r--crates/ra_hir_def/src/nameres/tests/macros.rs70
-rw-r--r--crates/ra_hir_def/src/nameres/tests/mod_resolution.rs2
-rw-r--r--crates/ra_hir_def/src/path/lower.rs15
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs4
-rw-r--r--crates/ra_hir_def/src/resolver.rs18
-rw-r--r--crates/ra_hir_expand/src/builtin_derive.rs2
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs8
-rw-r--r--crates/ra_hir_expand/src/db.rs39
-rw-r--r--crates/ra_hir_expand/src/hygiene.rs31
-rw-r--r--crates/ra_hir_expand/src/lib.rs2
-rw-r--r--crates/ra_hir_ty/Cargo.toml6
-rw-r--r--crates/ra_hir_ty/src/_match.rs68
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs28
-rw-r--r--crates/ra_hir_ty/src/display.rs239
-rw-r--r--crates/ra_hir_ty/src/infer.rs148
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs36
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs116
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs35
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs8
-rw-r--r--crates/ra_hir_ty/src/lib.rs30
-rw-r--r--crates/ra_hir_ty/src/lower.rs2
-rw-r--r--crates/ra_hir_ty/src/marks.rs11
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs12
-rw-r--r--crates/ra_hir_ty/src/op.rs3
-rw-r--r--crates/ra_hir_ty/src/tests.rs62
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs50
-rw-r--r--crates/ra_hir_ty/src/tests/display_source_code.rs50
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs32
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs46
-rw-r--r--crates/ra_hir_ty/src/tests/never_type.rs177
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs43
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs75
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs182
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs178
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs57
-rw-r--r--crates/ra_ide/src/assists.rs47
-rw-r--r--crates/ra_ide/src/call_info.rs8
-rw-r--r--crates/ra_ide/src/completion.rs5
-rw-r--r--crates/ra_ide/src/completion/complete_attribute.rs300
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs256
-rw-r--r--crates/ra_ide/src/completion/complete_qualified_path.rs63
-rw-r--r--crates/ra_ide/src/completion/complete_snippet.rs26
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs46
-rw-r--r--crates/ra_ide/src/completion/complete_unqualified_path.rs29
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs14
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs7
-rw-r--r--crates/ra_ide/src/completion/presentation.rs82
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs2
-rw-r--r--crates/ra_ide/src/diagnostics.rs40
-rw-r--r--crates/ra_ide/src/display/function_signature.rs23
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs19
-rw-r--r--crates/ra_ide/src/folding_ranges.rs2
-rw-r--r--crates/ra_ide/src/goto_definition.rs51
-rw-r--r--crates/ra_ide/src/hover.rs66
-rw-r--r--crates/ra_ide/src/inlay_hints.rs74
-rw-r--r--crates/ra_ide/src/join_lines.rs33
-rw-r--r--crates/ra_ide/src/lib.rs65
-rw-r--r--crates/ra_ide/src/marks.rs14
-rw-r--r--crates/ra_ide/src/parent_module.rs8
-rw-r--r--crates/ra_ide/src/references.rs28
-rw-r--r--crates/ra_ide/src/references/rename.rs332
-rw-r--r--crates/ra_ide/src/runnables.rs113
-rw-r--r--crates/ra_ide/src/snapshots/highlight_strings.html4
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html23
-rw-r--r--crates/ra_ide/src/ssr.rs46
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs33
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs21
-rw-r--r--crates/ra_ide/src/syntax_tree.rs77
-rw-r--r--crates/ra_ide/src/test_utils.rs21
-rw-r--r--crates/ra_ide/src/typing.rs31
-rw-r--r--crates/ra_ide/src/typing/on_enter.rs32
-rw-r--r--crates/ra_ide_db/src/defs.rs22
-rw-r--r--crates/ra_ide_db/src/lib.rs3
-rw-r--r--crates/ra_ide_db/src/line_index.rs29
-rw-r--r--crates/ra_ide_db/src/line_index_utils.rs302
-rw-r--r--crates/ra_ide_db/src/marks.rs11
-rw-r--r--crates/ra_ide_db/src/search.rs2
-rw-r--r--crates/ra_ide_db/src/source_change.rs (renamed from crates/ra_ide/src/source_change.rs)52
-rw-r--r--crates/ra_mbe/src/lib.rs2
-rw-r--r--crates/ra_mbe/src/mbe_expander/transcriber.rs33
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs2
-rw-r--r--crates/ra_mbe/src/tests.rs152
-rw-r--r--crates/ra_parser/src/grammar.rs4
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs26
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs74
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_parser/src/grammar/type_args.rs2
-rw-r--r--crates/ra_parser/src/lib.rs4
-rw-r--r--crates/ra_parser/src/parser.rs2
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs2
-rw-r--r--crates/ra_proc_macro_srv/Cargo.toml4
-rw-r--r--crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt21
-rw-r--r--crates/ra_proc_macro_srv/src/tests/mod.rs6
-rw-r--r--crates/ra_proc_macro_srv/src/tests/utils.rs4
-rw-r--r--crates/ra_project_model/Cargo.toml5
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs35
-rw-r--r--crates/ra_project_model/src/lib.rs108
-rw-r--r--crates/ra_project_model/src/sysroot.rs41
-rw-r--r--crates/ra_syntax/src/algo.rs36
-rw-r--r--crates/ra_syntax/src/ast.rs4
-rw-r--r--crates/ra_syntax/src/ast/edit.rs78
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs33
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs6
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs1621
-rw-r--r--crates/ra_syntax/src/ast/make.rs55
-rw-r--r--crates/ra_syntax/src/fuzz.rs6
-rw-r--r--crates/ra_syntax/src/lib.rs22
-rw-r--r--crates/ra_syntax/src/parsing/reparsing.rs28
-rw-r--r--crates/ra_syntax/src/syntax_node.rs2
-rw-r--r--crates/ra_syntax/src/validation.rs2
-rw-r--r--crates/ra_syntax/src/validation/block.rs20
-rw-r--r--crates/ra_syntax/test_data/parser/err/0005_attribute_recover.rast7
-rw-r--r--crates/ra_syntax/test_data/parser/err/0007_stray_curly_in_file.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/err/0008_item_block_recovery.rast52
-rw-r--r--crates/ra_syntax/test_data/parser/err/0010_unsafe_lambda_block.rast63
-rw-r--r--crates/ra_syntax/test_data/parser/err/0014_where_no_bounds.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/err/0016_missing_semi.rast61
-rw-r--r--crates/ra_syntax/test_data/parser/err/0017_incomplete_binexpr.rast45
-rw-r--r--crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.rast165
-rw-r--r--crates/ra_syntax/test_data/parser/err/0019_let_recover.rast166
-rw-r--r--crates/ra_syntax/test_data/parser/err/0020_fn_recover.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/err/0021_incomplete_param.rast7
-rw-r--r--crates/ra_syntax/test_data/parser/err/0022_bad_exprs.rast229
-rw-r--r--crates/ra_syntax/test_data/parser/err/0023_mismatched_paren.rast49
-rw-r--r--crates/ra_syntax/test_data/parser/err/0024_many_type_parens.rast430
-rw-r--r--crates/ra_syntax/test_data/parser/err/0025_nope.rast360
-rw-r--r--crates/ra_syntax/test_data/parser/err/0027_incomplere_where_for.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/err/0029_field_completion.rast23
-rw-r--r--crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.rast214
-rw-r--r--crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast361
-rw-r--r--crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast103
-rw-r--r--crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rast155
-rw-r--r--crates/ra_syntax/test_data/parser/err/0035_use_recover.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/err/0038_endless_inclusive_range.rast31
-rw-r--r--crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rast121
-rw-r--r--crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rast71
-rw-r--r--crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rs6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast25
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast37
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0008_pub_expr.rast25
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast92
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast77
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast71
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0001_trait_item_list.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast7
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0005_function_type_params.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0006_self_param.rast25
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.rast169
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0009_loop_expr.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.rast95
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0015_continue_expr.rast48
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0019_unary_expr.rast65
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0021_impl_item_list.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0024_slice_pat.rast59
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast185
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0027_ref_pat.rast75
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0029_cast_expr.rast155
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0030_cond.rast365
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rast149
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0034_break_expr.rast84
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0037_qual_paths.rast67
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0038_full_range_expr.rast33
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rast13
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast7
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0042_call_expr.rast271
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0044_block_items.rast34
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0053_path_expr.rast167
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0055_literal_pattern.rast129
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0056_where_clause.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0058_range_pat.rast141
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast94
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rast225
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0062_mod_contents.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rast229
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rast279
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast79
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rast165
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0072_return_expr.rast33
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast98
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0075_block.rast86
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0076_function_where_clause.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0077_try_expr.rast27
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rast167
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast15
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rast85
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0085_expr_literals.rast247
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0086_function_ret_type.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast112
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0093_index_expr.rast43
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast33
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast229
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0099_param_list.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0100_for_expr.rast46
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast241
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0103_array_expr.rast85
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rast43
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0106_lambda_expr.rast251
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0107_method_call_expr.rast101
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0108_tuple_expr.rast53
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0109_label.rast108
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rast155
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rast231
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast90
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0118_match_guard.rast71
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast137
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast267
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast7
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast39
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast71
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast172
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast92
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rast10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.rast49
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rast231
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0130_try_block_expr.rast40
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0132_box_expr.rast155
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast102
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.rast115
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.rast106
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0142_for_range_from.rast58
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast197
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast887
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast127
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast61
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast49
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rast115
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0156_fn_def_param.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rast199
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast50
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast64
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast45
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0161_labeled_block.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0161_labeled_block.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0162_unsafe_block.rast23
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0162_unsafe_block.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0005_fn_item.rast7
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0008_mod_item.rast7
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0012_visibility.rast25
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rast21
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0025_extern_fn_in_block.rast40
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0026_const_fn_in_block.rast38
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast60
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0028_operator_binding_power.rast347
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0029_range_forms.rast279
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0030_string_suffixes.rast103
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0032_where_for.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0033_label_break.rast407
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0034_crate_path_in_call.rast59
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast3912
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0036_fully_qualified.rast27
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0038_where_pred_type.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0039_raw_fn_item.rast7
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0041_raw_keywords.rast77
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0042_ufcs_call_list.rast97
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.rast133
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0044_let_attrs.rast123
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.rast196
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast495
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0048_compound_assignment.rast373
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0049_async_block.rast47
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0050_async_block_as_argument.rast56
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast55
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0052_for_range_block.rast135
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast15
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rast49
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.rast106
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0057_loop_in_call.rast49
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rast169
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rast174
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0060_as_range.rast87
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0061_match_full_range.rast29
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rast205
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast20
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0065_comment_newline.rast5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast5
-rw-r--r--crates/ra_text_edit/src/lib.rs174
-rw-r--r--crates/ra_text_edit/src/text_edit.rs102
-rw-r--r--crates/ra_toolchain/Cargo.toml8
-rw-r--r--crates/ra_toolchain/src/lib.rs63
-rw-r--r--crates/ra_tt/src/buffer.rs4
-rw-r--r--crates/ra_tt/src/lib.rs2
-rw-r--r--crates/rust-analyzer/Cargo.toml1
-rw-r--r--crates/rust-analyzer/src/bin/main.rs7
-rw-r--r--crates/rust-analyzer/src/caps.rs18
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs26
-rw-r--r--crates/rust-analyzer/src/cli.rs1
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs2
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs4
-rw-r--r--crates/rust-analyzer/src/config.rs125
-rw-r--r--crates/rust-analyzer/src/conv.rs727
-rw-r--r--crates/rust-analyzer/src/diagnostics.rs11
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_clippy_pass_by_ref.snap (renamed from crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_clippy_pass_by_ref.snap)2
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_handles_macro_location.snap (renamed from crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_handles_macro_location.snap)2
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_macro_compiler_error.snap (renamed from crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_macro_compiler_error.snap)2
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap (renamed from crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_multi_line_fix.snap)8
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_incompatible_type_for_trait.snap (renamed from crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_incompatible_type_for_trait.snap)2
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_mismatched_type.snap (renamed from crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_mismatched_type.snap)2
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap (renamed from crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_unused_variable.snap)8
-rw-r--r--crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_wrong_number_of_parameters.snap (renamed from crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_wrong_number_of_parameters.snap)2
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs1399
-rw-r--r--crates/rust-analyzer/src/from_proto.rs42
-rw-r--r--crates/rust-analyzer/src/lib.rs5
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs (renamed from crates/rust-analyzer/src/req.rs)88
-rw-r--r--crates/rust-analyzer/src/main_loop.rs322
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs800
-rw-r--r--crates/rust-analyzer/src/to_proto.rs614
-rw-r--r--crates/rust-analyzer/src/world.rs46
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs251
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/support.rs7
-rw-r--r--crates/stdx/src/lib.rs22
-rw-r--r--crates/test_utils/src/lib.rs106
-rw-r--r--crates/test_utils/src/mark.rs (renamed from crates/test_utils/src/marks.rs)46
-rw-r--r--docs/dev/README.md6
-rw-r--r--docs/dev/debugging.md14
-rw-r--r--docs/dev/lsp-extensions.md86
-rw-r--r--docs/dev/syntax.md42
-rw-r--r--docs/user/assists.md96
-rw-r--r--docs/user/features.md14
-rw-r--r--docs/user/readme.adoc41
-rw-r--r--editors/code/.vscodeignore1
-rw-r--r--editors/code/package-lock.json97
-rw-r--r--editors/code/package.json128
-rw-r--r--editors/code/rust.tmGrammar.json681
-rw-r--r--editors/code/src/cargo.ts100
-rw-r--r--editors/code/src/client.ts65
-rw-r--r--editors/code/src/color_theme.ts129
-rw-r--r--editors/code/src/commands/index.ts56
-rw-r--r--editors/code/src/commands/join_lines.ts12
-rw-r--r--editors/code/src/commands/on_enter.ts5
-rw-r--r--editors/code/src/commands/runnables.ts197
-rw-r--r--editors/code/src/commands/ssr.ts2
-rw-r--r--editors/code/src/commands/syntax_tree.ts4
-rw-r--r--editors/code/src/config.ts20
-rw-r--r--editors/code/src/debug.ts124
-rw-r--r--editors/code/src/inlay_hints.ts14
-rw-r--r--editors/code/src/main.ts11
-rw-r--r--editors/code/src/rust-analyzer-api.ts6
-rw-r--r--editors/code/src/util.ts11
-rw-r--r--xtask/src/ast_src.rs1523
-rw-r--r--xtask/src/codegen.rs2
-rw-r--r--xtask/src/codegen/gen_assists_docs.rs4
-rw-r--r--xtask/src/codegen/gen_syntax.rs26
-rw-r--r--xtask/tests/tidy-tests/cli.rs32
-rw-r--r--xtask/tests/tidy.rs (renamed from xtask/tests/tidy-tests/main.rs)41
443 files changed, 26819 insertions, 17921 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 3f52f31f8..29ac89549 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -20,7 +20,7 @@ jobs:
20 runs-on: ${{ matrix.os }} 20 runs-on: ${{ matrix.os }}
21 strategy: 21 strategy:
22 matrix: 22 matrix:
23 os: [ubuntu-latest, windows-latest, macos-latest] 23 os: [ubuntu-16.04, windows-latest, macos-latest]
24 24
25 steps: 25 steps:
26 - name: Checkout repository 26 - name: Checkout repository
@@ -42,25 +42,25 @@ jobs:
42 override: true 42 override: true
43 43
44 - name: Install Nodejs 44 - name: Install Nodejs
45 if: matrix.os == 'ubuntu-latest' 45 if: matrix.os == 'ubuntu-16.04'
46 uses: actions/setup-node@v1 46 uses: actions/setup-node@v1
47 with: 47 with:
48 node-version: 12.x 48 node-version: 12.x
49 49
50 - name: Dist 50 - name: Dist
51 if: matrix.os == 'ubuntu-latest' && github.ref == 'refs/heads/release' 51 if: matrix.os == 'ubuntu-16.04' && github.ref == 'refs/heads/release'
52 run: cargo xtask dist --client 0.2.$GITHUB_RUN_NUMBER 52 run: cargo xtask dist --client 0.2.$GITHUB_RUN_NUMBER
53 53
54 - name: Dist 54 - name: Dist
55 if: matrix.os == 'ubuntu-latest' && github.ref != 'refs/heads/release' 55 if: matrix.os == 'ubuntu-16.04' && github.ref != 'refs/heads/release'
56 run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly 56 run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly
57 57
58 - name: Dist 58 - name: Dist
59 if: matrix.os != 'ubuntu-latest' 59 if: matrix.os != 'ubuntu-16.04'
60 run: cargo xtask dist 60 run: cargo xtask dist
61 61
62 - name: Nightly analysis-stats check 62 - name: Nightly analysis-stats check
63 if: matrix.os == 'ubuntu-latest' && github.ref != 'refs/heads/release' 63 if: matrix.os == 'ubuntu-16.04' && github.ref != 'refs/heads/release'
64 run: ./dist/rust-analyzer-linux analysis-stats . 64 run: ./dist/rust-analyzer-linux analysis-stats .
65 65
66 - name: Upload artifacts 66 - name: Upload artifacts
@@ -71,7 +71,7 @@ jobs:
71 71
72 publish: 72 publish:
73 name: publish 73 name: publish
74 runs-on: ubuntu-latest 74 runs-on: ubuntu-16.04
75 needs: ['dist'] 75 needs: ['dist']
76 steps: 76 steps:
77 - name: Install Nodejs 77 - name: Install Nodejs
@@ -94,7 +94,7 @@ jobs:
94 path: dist 94 path: dist
95 - uses: actions/download-artifact@v1 95 - uses: actions/download-artifact@v1
96 with: 96 with:
97 name: dist-ubuntu-latest 97 name: dist-ubuntu-16.04
98 path: dist 98 path: dist
99 - uses: actions/download-artifact@v1 99 - uses: actions/download-artifact@v1
100 with: 100 with:
diff --git a/Cargo.lock b/Cargo.lock
index 85ea4f178..c06236692 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,15 @@
1# This file is automatically @generated by Cargo. 1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing. 2# It is not intended for manual editing.
3[[package]] 3[[package]]
4name = "addr2line"
5version = "0.12.1"
6source = "registry+https://github.com/rust-lang/crates.io-index"
7checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543"
8dependencies = [
9 "gimli",
10]
11
12[[package]]
4name = "aho-corasick" 13name = "aho-corasick"
5version = "0.7.10" 14version = "0.7.10"
6source = "registry+https://github.com/rust-lang/crates.io-index" 15source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -11,9 +20,9 @@ dependencies = [
11 20
12[[package]] 21[[package]]
13name = "anyhow" 22name = "anyhow"
14version = "1.0.28" 23version = "1.0.31"
15source = "registry+https://github.com/rust-lang/crates.io-index" 24source = "registry+https://github.com/rust-lang/crates.io-index"
16checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff" 25checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f"
17 26
18[[package]] 27[[package]]
19name = "anymap" 28name = "anymap"
@@ -46,31 +55,22 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
46 55
47[[package]] 56[[package]]
48name = "backtrace" 57name = "backtrace"
49version = "0.3.46" 58version = "0.3.48"
50source = "registry+https://github.com/rust-lang/crates.io-index" 59source = "registry+https://github.com/rust-lang/crates.io-index"
51checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" 60checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130"
52dependencies = [ 61dependencies = [
53 "backtrace-sys", 62 "addr2line",
54 "cfg-if", 63 "cfg-if",
55 "libc", 64 "libc",
65 "object",
56 "rustc-demangle", 66 "rustc-demangle",
57] 67]
58 68
59[[package]] 69[[package]]
60name = "backtrace-sys"
61version = "0.1.37"
62source = "registry+https://github.com/rust-lang/crates.io-index"
63checksum = "18fbebbe1c9d1f383a9cc7e8ccdb471b91c8d024ee9c2ca5b5346121fe8b4399"
64dependencies = [
65 "cc",
66 "libc",
67]
68
69[[package]]
70name = "base64" 70name = "base64"
71version = "0.12.0" 71version = "0.12.1"
72source = "registry+https://github.com/rust-lang/crates.io-index" 72source = "registry+https://github.com/rust-lang/crates.io-index"
73checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3" 73checksum = "53d1ccbaf7d9ec9537465a97bf19edc1a4e158ecb49fc16178202238c569cc42"
74 74
75[[package]] 75[[package]]
76name = "bitflags" 76name = "bitflags"
@@ -80,18 +80,18 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
80 80
81[[package]] 81[[package]]
82name = "bstr" 82name = "bstr"
83version = "0.2.12" 83version = "0.2.13"
84source = "registry+https://github.com/rust-lang/crates.io-index" 84source = "registry+https://github.com/rust-lang/crates.io-index"
85checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" 85checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931"
86dependencies = [ 86dependencies = [
87 "memchr", 87 "memchr",
88] 88]
89 89
90[[package]] 90[[package]]
91name = "cargo_metadata" 91name = "cargo_metadata"
92version = "0.9.1" 92version = "0.10.0"
93source = "registry+https://github.com/rust-lang/crates.io-index" 93source = "registry+https://github.com/rust-lang/crates.io-index"
94checksum = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" 94checksum = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf"
95dependencies = [ 95dependencies = [
96 "semver", 96 "semver",
97 "serde", 97 "serde",
@@ -101,9 +101,9 @@ dependencies = [
101 101
102[[package]] 102[[package]]
103name = "cc" 103name = "cc"
104version = "1.0.52" 104version = "1.0.53"
105source = "registry+https://github.com/rust-lang/crates.io-index" 105source = "registry+https://github.com/rust-lang/crates.io-index"
106checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d" 106checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c"
107 107
108[[package]] 108[[package]]
109name = "cfg-if" 109name = "cfg-if"
@@ -113,8 +113,8 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
113 113
114[[package]] 114[[package]]
115name = "chalk-derive" 115name = "chalk-derive"
116version = "0.1.0" 116version = "0.10.1-dev"
117source = "git+https://github.com/rust-lang/chalk.git?rev=2c072cc830d04af5f10b390e6643327f85108282#2c072cc830d04af5f10b390e6643327f85108282" 117source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3"
118dependencies = [ 118dependencies = [
119 "proc-macro2", 119 "proc-macro2",
120 "quote", 120 "quote",
@@ -124,8 +124,8 @@ dependencies = [
124 124
125[[package]] 125[[package]]
126name = "chalk-engine" 126name = "chalk-engine"
127version = "0.9.0" 127version = "0.10.1-dev"
128source = "git+https://github.com/rust-lang/chalk.git?rev=2c072cc830d04af5f10b390e6643327f85108282#2c072cc830d04af5f10b390e6643327f85108282" 128source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3"
129dependencies = [ 129dependencies = [
130 "chalk-macros", 130 "chalk-macros",
131 "rustc-hash", 131 "rustc-hash",
@@ -133,8 +133,8 @@ dependencies = [
133 133
134[[package]] 134[[package]]
135name = "chalk-ir" 135name = "chalk-ir"
136version = "0.1.0" 136version = "0.10.1-dev"
137source = "git+https://github.com/rust-lang/chalk.git?rev=2c072cc830d04af5f10b390e6643327f85108282#2c072cc830d04af5f10b390e6643327f85108282" 137source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3"
138dependencies = [ 138dependencies = [
139 "chalk-derive", 139 "chalk-derive",
140 "chalk-engine", 140 "chalk-engine",
@@ -143,16 +143,16 @@ dependencies = [
143 143
144[[package]] 144[[package]]
145name = "chalk-macros" 145name = "chalk-macros"
146version = "0.1.1" 146version = "0.10.1-dev"
147source = "git+https://github.com/rust-lang/chalk.git?rev=2c072cc830d04af5f10b390e6643327f85108282#2c072cc830d04af5f10b390e6643327f85108282" 147source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3"
148dependencies = [ 148dependencies = [
149 "lazy_static", 149 "lazy_static",
150] 150]
151 151
152[[package]] 152[[package]]
153name = "chalk-rust-ir" 153name = "chalk-rust-ir"
154version = "0.1.0" 154version = "0.10.1-dev"
155source = "git+https://github.com/rust-lang/chalk.git?rev=2c072cc830d04af5f10b390e6643327f85108282#2c072cc830d04af5f10b390e6643327f85108282" 155source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3"
156dependencies = [ 156dependencies = [
157 "chalk-derive", 157 "chalk-derive",
158 "chalk-engine", 158 "chalk-engine",
@@ -162,8 +162,8 @@ dependencies = [
162 162
163[[package]] 163[[package]]
164name = "chalk-solve" 164name = "chalk-solve"
165version = "0.1.0" 165version = "0.10.1-dev"
166source = "git+https://github.com/rust-lang/chalk.git?rev=2c072cc830d04af5f10b390e6643327f85108282#2c072cc830d04af5f10b390e6643327f85108282" 166source = "git+https://github.com/rust-lang/chalk.git?rev=3e9c2503ae9c5277c2acb74624dc267876dd89b3#3e9c2503ae9c5277c2acb74624dc267876dd89b3"
167dependencies = [ 167dependencies = [
168 "chalk-derive", 168 "chalk-derive",
169 "chalk-engine", 169 "chalk-engine",
@@ -342,9 +342,9 @@ dependencies = [
342 342
343[[package]] 343[[package]]
344name = "filetime" 344name = "filetime"
345version = "0.2.9" 345version = "0.2.10"
346source = "registry+https://github.com/rust-lang/crates.io-index" 346source = "registry+https://github.com/rust-lang/crates.io-index"
347checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e" 347checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695"
348dependencies = [ 348dependencies = [
349 "cfg-if", 349 "cfg-if",
350 "libc", 350 "libc",
@@ -360,9 +360,9 @@ checksum = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
360 360
361[[package]] 361[[package]]
362name = "fnv" 362name = "fnv"
363version = "1.0.6" 363version = "1.0.7"
364source = "registry+https://github.com/rust-lang/crates.io-index" 364source = "registry+https://github.com/rust-lang/crates.io-index"
365checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 365checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
366 366
367[[package]] 367[[package]]
368name = "fs_extra" 368name = "fs_extra"
@@ -423,6 +423,12 @@ dependencies = [
423] 423]
424 424
425[[package]] 425[[package]]
426name = "gimli"
427version = "0.21.0"
428source = "registry+https://github.com/rust-lang/crates.io-index"
429checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c"
430
431[[package]]
426name = "globset" 432name = "globset"
427version = "0.4.5" 433version = "0.4.5"
428source = "registry+https://github.com/rust-lang/crates.io-index" 434source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -437,9 +443,9 @@ dependencies = [
437 443
438[[package]] 444[[package]]
439name = "goblin" 445name = "goblin"
440version = "0.2.1" 446version = "0.2.3"
441source = "registry+https://github.com/rust-lang/crates.io-index" 447source = "registry+https://github.com/rust-lang/crates.io-index"
442checksum = "ddd5e3132801a1ac34ac53b97acde50c4685414dd2f291b9ea52afa6f07468c8" 448checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884"
443dependencies = [ 449dependencies = [
444 "log", 450 "log",
445 "plain", 451 "plain",
@@ -457,14 +463,23 @@ dependencies = [
457 463
458[[package]] 464[[package]]
459name = "hermit-abi" 465name = "hermit-abi"
460version = "0.1.12" 466version = "0.1.13"
461source = "registry+https://github.com/rust-lang/crates.io-index" 467source = "registry+https://github.com/rust-lang/crates.io-index"
462checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4" 468checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
463dependencies = [ 469dependencies = [
464 "libc", 470 "libc",
465] 471]
466 472
467[[package]] 473[[package]]
474name = "home"
475version = "0.5.3"
476source = "registry+https://github.com/rust-lang/crates.io-index"
477checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
478dependencies = [
479 "winapi 0.3.8",
480]
481
482[[package]]
468name = "idna" 483name = "idna"
469version = "0.2.0" 484version = "0.2.0"
470source = "registry+https://github.com/rust-lang/crates.io-index" 485source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -604,24 +619,24 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
604 619
605[[package]] 620[[package]]
606name = "libc" 621name = "libc"
607version = "0.2.69" 622version = "0.2.70"
608source = "registry+https://github.com/rust-lang/crates.io-index" 623source = "registry+https://github.com/rust-lang/crates.io-index"
609checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" 624checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
610 625
611[[package]] 626[[package]]
612name = "libloading" 627name = "libloading"
613version = "0.6.1" 628version = "0.6.2"
614source = "registry+https://github.com/rust-lang/crates.io-index" 629source = "registry+https://github.com/rust-lang/crates.io-index"
615checksum = "3c4f51b790f5bdb65acb4cc94bb81d7b2ee60348a5431ac1467d390b017600b0" 630checksum = "2cadb8e769f070c45df05c78c7520eb4cd17061d4ab262e43cfc68b4d00ac71c"
616dependencies = [ 631dependencies = [
617 "winapi 0.3.8", 632 "winapi 0.3.8",
618] 633]
619 634
620[[package]] 635[[package]]
621name = "linked-hash-map" 636name = "linked-hash-map"
622version = "0.5.2" 637version = "0.5.3"
623source = "registry+https://github.com/rust-lang/crates.io-index" 638source = "registry+https://github.com/rust-lang/crates.io-index"
624checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" 639checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
625 640
626[[package]] 641[[package]]
627name = "lock_api" 642name = "lock_api"
@@ -655,9 +670,9 @@ dependencies = [
655 670
656[[package]] 671[[package]]
657name = "lsp-types" 672name = "lsp-types"
658version = "0.74.0" 673version = "0.74.1"
659source = "registry+https://github.com/rust-lang/crates.io-index" 674source = "registry+https://github.com/rust-lang/crates.io-index"
660checksum = "820f746e5716ab9a2d664794636188bd003023b72e55404ee27105dc22869922" 675checksum = "57c0e6a2b8837d27b29deb3f3e6dc1c6d2f57947677f9be1024e482ec5b59525"
661dependencies = [ 676dependencies = [
662 "base64", 677 "base64",
663 "bitflags", 678 "bitflags",
@@ -706,9 +721,9 @@ dependencies = [
706 721
707[[package]] 722[[package]]
708name = "mio" 723name = "mio"
709version = "0.6.21" 724version = "0.6.22"
710source = "registry+https://github.com/rust-lang/crates.io-index" 725source = "registry+https://github.com/rust-lang/crates.io-index"
711checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" 726checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
712dependencies = [ 727dependencies = [
713 "cfg-if", 728 "cfg-if",
714 "fuchsia-zircon", 729 "fuchsia-zircon",
@@ -749,9 +764,9 @@ dependencies = [
749 764
750[[package]] 765[[package]]
751name = "net2" 766name = "net2"
752version = "0.2.33" 767version = "0.2.34"
753source = "registry+https://github.com/rust-lang/crates.io-index" 768source = "registry+https://github.com/rust-lang/crates.io-index"
754checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" 769checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7"
755dependencies = [ 770dependencies = [
756 "cfg-if", 771 "cfg-if",
757 "libc", 772 "libc",
@@ -787,10 +802,16 @@ dependencies = [
787] 802]
788 803
789[[package]] 804[[package]]
805name = "object"
806version = "0.19.0"
807source = "registry+https://github.com/rust-lang/crates.io-index"
808checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
809
810[[package]]
790name = "once_cell" 811name = "once_cell"
791version = "1.3.1" 812version = "1.4.0"
792source = "registry+https://github.com/rust-lang/crates.io-index" 813source = "registry+https://github.com/rust-lang/crates.io-index"
793checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" 814checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
794 815
795[[package]] 816[[package]]
796name = "ordermap" 817name = "ordermap"
@@ -824,9 +845,9 @@ dependencies = [
824 845
825[[package]] 846[[package]]
826name = "paste" 847name = "paste"
827version = "0.1.11" 848version = "0.1.12"
828source = "registry+https://github.com/rust-lang/crates.io-index" 849source = "registry+https://github.com/rust-lang/crates.io-index"
829checksum = "a3c897744f63f34f7ae3a024d9162bb5001f4ad661dd24bea0dc9f075d2de1c6" 850checksum = "0a229b1c58c692edcaa5b9b0948084f130f55d2dcc15b02fcc5340b2b4521476"
830dependencies = [ 851dependencies = [
831 "paste-impl", 852 "paste-impl",
832 "proc-macro-hack", 853 "proc-macro-hack",
@@ -834,9 +855,9 @@ dependencies = [
834 855
835[[package]] 856[[package]]
836name = "paste-impl" 857name = "paste-impl"
837version = "0.1.11" 858version = "0.1.12"
838source = "registry+https://github.com/rust-lang/crates.io-index" 859source = "registry+https://github.com/rust-lang/crates.io-index"
839checksum = "66fd6f92e3594f2dd7b3fc23e42d82e292f7bcda6d8e5dcd167072327234ab89" 860checksum = "2e0bf239e447e67ff6d16a8bb5e4d4bd2343acf5066061c0e8e06ac5ba8ca68c"
840dependencies = [ 861dependencies = [
841 "proc-macro-hack", 862 "proc-macro-hack",
842 "proc-macro2", 863 "proc-macro2",
@@ -874,9 +895,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
874 895
875[[package]] 896[[package]]
876name = "ppv-lite86" 897name = "ppv-lite86"
877version = "0.2.6" 898version = "0.2.8"
878source = "registry+https://github.com/rust-lang/crates.io-index" 899source = "registry+https://github.com/rust-lang/crates.io-index"
879checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" 900checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
880 901
881[[package]] 902[[package]]
882name = "proc-macro-hack" 903name = "proc-macro-hack"
@@ -886,18 +907,18 @@ checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
886 907
887[[package]] 908[[package]]
888name = "proc-macro2" 909name = "proc-macro2"
889version = "1.0.10" 910version = "1.0.13"
890source = "registry+https://github.com/rust-lang/crates.io-index" 911source = "registry+https://github.com/rust-lang/crates.io-index"
891checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" 912checksum = "53f5ffe53a6b28e37c9c1ce74893477864d64f74778a93a4beb43c8fa167f639"
892dependencies = [ 913dependencies = [
893 "unicode-xid", 914 "unicode-xid",
894] 915]
895 916
896[[package]] 917[[package]]
897name = "quote" 918name = "quote"
898version = "1.0.4" 919version = "1.0.6"
899source = "registry+https://github.com/rust-lang/crates.io-index" 920source = "registry+https://github.com/rust-lang/crates.io-index"
900checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" 921checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
901dependencies = [ 922dependencies = [
902 "proc-macro2", 923 "proc-macro2",
903] 924]
@@ -954,10 +975,9 @@ version = "0.1.0"
954dependencies = [ 975dependencies = [
955 "cargo_metadata", 976 "cargo_metadata",
956 "crossbeam-channel", 977 "crossbeam-channel",
957 "insta",
958 "jod-thread", 978 "jod-thread",
959 "log", 979 "log",
960 "lsp-types", 980 "ra_toolchain",
961 "serde_json", 981 "serde_json",
962] 982]
963 983
@@ -1163,6 +1183,7 @@ dependencies = [
1163 "ra_cfg", 1183 "ra_cfg",
1164 "ra_db", 1184 "ra_db",
1165 "ra_proc_macro", 1185 "ra_proc_macro",
1186 "ra_toolchain",
1166 "rustc-hash", 1187 "rustc-hash",
1167 "serde", 1188 "serde",
1168 "serde_json", 1189 "serde_json",
@@ -1195,6 +1216,13 @@ dependencies = [
1195] 1216]
1196 1217
1197[[package]] 1218[[package]]
1219name = "ra_toolchain"
1220version = "0.1.0"
1221dependencies = [
1222 "home",
1223]
1224
1225[[package]]
1198name = "ra_tt" 1226name = "ra_tt"
1199version = "0.1.0" 1227version = "0.1.0"
1200dependencies = [ 1228dependencies = [
@@ -1203,9 +1231,9 @@ dependencies = [
1203 1231
1204[[package]] 1232[[package]]
1205name = "ra_vfs" 1233name = "ra_vfs"
1206version = "0.6.0" 1234version = "0.6.1"
1207source = "registry+https://github.com/rust-lang/crates.io-index" 1235source = "registry+https://github.com/rust-lang/crates.io-index"
1208checksum = "fcaa5615f420134aea7667253db101d03a5c5f300eac607872dc2a36407b2ac9" 1236checksum = "cbf31a173fc77ec59c27cf39af6baa137b40f4dbd45a8b3eccb1b2e4cfc922c1"
1209dependencies = [ 1237dependencies = [
1210 "crossbeam-channel", 1238 "crossbeam-channel",
1211 "jod-thread", 1239 "jod-thread",
@@ -1351,6 +1379,7 @@ dependencies = [
1351 "crossbeam-channel", 1379 "crossbeam-channel",
1352 "env_logger", 1380 "env_logger",
1353 "globset", 1381 "globset",
1382 "insta",
1354 "itertools", 1383 "itertools",
1355 "jod-thread", 1384 "jod-thread",
1356 "log", 1385 "log",
@@ -1469,9 +1498,9 @@ dependencies = [
1469 1498
1470[[package]] 1499[[package]]
1471name = "scroll_derive" 1500name = "scroll_derive"
1472version = "0.10.1" 1501version = "0.10.2"
1473source = "registry+https://github.com/rust-lang/crates.io-index" 1502source = "registry+https://github.com/rust-lang/crates.io-index"
1474checksum = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28" 1503checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9"
1475dependencies = [ 1504dependencies = [
1476 "proc-macro2", 1505 "proc-macro2",
1477 "quote", 1506 "quote",
@@ -1496,18 +1525,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1496 1525
1497[[package]] 1526[[package]]
1498name = "serde" 1527name = "serde"
1499version = "1.0.106" 1528version = "1.0.110"
1500source = "registry+https://github.com/rust-lang/crates.io-index" 1529source = "registry+https://github.com/rust-lang/crates.io-index"
1501checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" 1530checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
1502dependencies = [ 1531dependencies = [
1503 "serde_derive", 1532 "serde_derive",
1504] 1533]
1505 1534
1506[[package]] 1535[[package]]
1507name = "serde_derive" 1536name = "serde_derive"
1508version = "1.0.106" 1537version = "1.0.110"
1509source = "registry+https://github.com/rust-lang/crates.io-index" 1538source = "registry+https://github.com/rust-lang/crates.io-index"
1510checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" 1539checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
1511dependencies = [ 1540dependencies = [
1512 "proc-macro2", 1541 "proc-macro2",
1513 "quote", 1542 "quote",
@@ -1516,9 +1545,9 @@ dependencies = [
1516 1545
1517[[package]] 1546[[package]]
1518name = "serde_json" 1547name = "serde_json"
1519version = "1.0.52" 1548version = "1.0.53"
1520source = "registry+https://github.com/rust-lang/crates.io-index" 1549source = "registry+https://github.com/rust-lang/crates.io-index"
1521checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd" 1550checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
1522dependencies = [ 1551dependencies = [
1523 "itoa", 1552 "itoa",
1524 "ryu", 1553 "ryu",
@@ -1538,9 +1567,9 @@ dependencies = [
1538 1567
1539[[package]] 1568[[package]]
1540name = "serde_yaml" 1569name = "serde_yaml"
1541version = "0.8.11" 1570version = "0.8.12"
1542source = "registry+https://github.com/rust-lang/crates.io-index" 1571source = "registry+https://github.com/rust-lang/crates.io-index"
1543checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" 1572checksum = "16c7a592a1ec97c9c1c68d75b6e537dcbf60c7618e038e7841e00af1d9ccf0c4"
1544dependencies = [ 1573dependencies = [
1545 "dtoa", 1574 "dtoa",
1546 "linked-hash-map", 1575 "linked-hash-map",
@@ -1581,9 +1610,9 @@ checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
1581 1610
1582[[package]] 1611[[package]]
1583name = "syn" 1612name = "syn"
1584version = "1.0.18" 1613version = "1.0.22"
1585source = "registry+https://github.com/rust-lang/crates.io-index" 1614source = "registry+https://github.com/rust-lang/crates.io-index"
1586checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213" 1615checksum = "1425de3c33b0941002740a420b1a906a350b88d08b82b2c8a01035a3f9447bac"
1587dependencies = [ 1616dependencies = [
1588 "proc-macro2", 1617 "proc-macro2",
1589 "quote", 1618 "quote",
@@ -1667,9 +1696,9 @@ dependencies = [
1667 1696
1668[[package]] 1697[[package]]
1669name = "threadpool" 1698name = "threadpool"
1670version = "1.8.0" 1699version = "1.8.1"
1671source = "registry+https://github.com/rust-lang/crates.io-index" 1700source = "registry+https://github.com/rust-lang/crates.io-index"
1672checksum = "e8dae184447c15d5a6916d973c642aec485105a13cd238192a6927ae3e077d66" 1701checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
1673dependencies = [ 1702dependencies = [
1674 "num_cpus", 1703 "num_cpus",
1675] 1704]
diff --git a/crates/ra_assists/src/assist_config.rs b/crates/ra_assists/src/assist_config.rs
new file mode 100644
index 000000000..c0a0226fb
--- /dev/null
+++ b/crates/ra_assists/src/assist_config.rs
@@ -0,0 +1,27 @@
1//! Settings for tweaking assists.
2//!
3//! The fun thing here is `SnippetCap` -- this type can only be created in this
4//! module, and we use to statically check that we only produce snippet
5//! assists if we are allowed to.
6
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct AssistConfig {
9 pub snippet_cap: Option<SnippetCap>,
10}
11
12impl AssistConfig {
13 pub fn allow_snippets(&mut self, yes: bool) {
14 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None }
15 }
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub struct SnippetCap {
20 _private: (),
21}
22
23impl Default for AssistConfig {
24 fn default() -> Self {
25 AssistConfig { snippet_cap: Some(SnippetCap { _private: () }) }
26 }
27}
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
new file mode 100644
index 000000000..f3af70a3e
--- /dev/null
+++ b/crates/ra_assists/src/assist_context.rs
@@ -0,0 +1,257 @@
1//! See `AssistContext`
2
3use algo::find_covering_element;
4use hir::Semantics;
5use ra_db::{FileId, FileRange};
6use ra_fmt::{leading_indent, reindent};
7use ra_ide_db::{
8 source_change::{SingleFileChange, SourceChange},
9 RootDatabase,
10};
11use ra_syntax::{
12 algo::{self, find_node_at_offset, SyntaxRewriter},
13 AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize,
14 TokenAtOffset,
15};
16use ra_text_edit::TextEditBuilder;
17
18use crate::{
19 assist_config::{AssistConfig, SnippetCap},
20 Assist, AssistId, GroupLabel, ResolvedAssist,
21};
22
23/// `AssistContext` allows to apply an assist or check if it could be applied.
24///
25/// Assists use a somewhat over-engineered approach, given the current needs.
26/// The assists workflow consists of two phases. In the first phase, a user asks
27/// for the list of available assists. In the second phase, the user picks a
28/// particular assist and it gets applied.
29///
30/// There are two peculiarities here:
31///
32/// * first, we ideally avoid computing more things then necessary to answer "is
33/// assist applicable" in the first phase.
34/// * second, when we are applying assist, we don't have a guarantee that there
35/// weren't any changes between the point when user asked for assists and when
36/// they applied a particular assist. So, when applying assist, we need to do
37/// all the checks from scratch.
38///
39/// To avoid repeating the same code twice for both "check" and "apply"
40/// functions, we use an approach reminiscent of that of Django's function based
41/// views dealing with forms. Each assist receives a runtime parameter,
42/// `resolve`. It first check if an edit is applicable (potentially computing
43/// info required to compute the actual edit). If it is applicable, and
44/// `resolve` is `true`, it then computes the actual edit.
45///
46/// So, to implement the original assists workflow, we can first apply each edit
47/// with `resolve = false`, and then applying the selected edit again, with
48/// `resolve = true` this time.
49///
50/// Note, however, that we don't actually use such two-phase logic at the
51/// moment, because the LSP API is pretty awkward in this place, and it's much
52/// easier to just compute the edit eagerly :-)
53pub(crate) struct AssistContext<'a> {
54 pub(crate) config: &'a AssistConfig,
55 pub(crate) sema: Semantics<'a, RootDatabase>,
56 pub(crate) db: &'a RootDatabase,
57 pub(crate) frange: FileRange,
58 source_file: SourceFile,
59}
60
61impl<'a> AssistContext<'a> {
62 pub(crate) fn new(
63 sema: Semantics<'a, RootDatabase>,
64 config: &'a AssistConfig,
65 frange: FileRange,
66 ) -> AssistContext<'a> {
67 let source_file = sema.parse(frange.file_id);
68 let db = sema.db;
69 AssistContext { config, sema, db, frange, source_file }
70 }
71
72 // NB, this ignores active selection.
73 pub(crate) fn offset(&self) -> TextSize {
74 self.frange.range.start()
75 }
76
77 pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
78 self.source_file.syntax().token_at_offset(self.offset())
79 }
80 pub(crate) fn find_token_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
81 self.token_at_offset().find(|it| it.kind() == kind)
82 }
83 pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
84 find_node_at_offset(self.source_file.syntax(), self.offset())
85 }
86 pub(crate) fn find_node_at_offset_with_descend<N: AstNode>(&self) -> Option<N> {
87 self.sema.find_node_at_offset_with_descend(self.source_file.syntax(), self.offset())
88 }
89 pub(crate) fn covering_element(&self) -> SyntaxElement {
90 find_covering_element(self.source_file.syntax(), self.frange.range)
91 }
92 // FIXME: remove
93 pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {
94 find_covering_element(self.source_file.syntax(), range)
95 }
96}
97
98pub(crate) struct Assists {
99 resolve: bool,
100 file: FileId,
101 buf: Vec<(Assist, Option<SourceChange>)>,
102}
103
104impl Assists {
105 pub(crate) fn new_resolved(ctx: &AssistContext) -> Assists {
106 Assists { resolve: true, file: ctx.frange.file_id, buf: Vec::new() }
107 }
108 pub(crate) fn new_unresolved(ctx: &AssistContext) -> Assists {
109 Assists { resolve: false, file: ctx.frange.file_id, buf: Vec::new() }
110 }
111
112 pub(crate) fn finish_unresolved(self) -> Vec<Assist> {
113 assert!(!self.resolve);
114 self.finish()
115 .into_iter()
116 .map(|(label, edit)| {
117 assert!(edit.is_none());
118 label
119 })
120 .collect()
121 }
122
123 pub(crate) fn finish_resolved(self) -> Vec<ResolvedAssist> {
124 assert!(self.resolve);
125 self.finish()
126 .into_iter()
127 .map(|(label, edit)| ResolvedAssist { assist: label, source_change: edit.unwrap() })
128 .collect()
129 }
130
131 pub(crate) fn add(
132 &mut self,
133 id: AssistId,
134 label: impl Into<String>,
135 target: TextRange,
136 f: impl FnOnce(&mut AssistBuilder),
137 ) -> Option<()> {
138 let label = Assist::new(id, label.into(), None, target);
139 self.add_impl(label, f)
140 }
141 pub(crate) fn add_group(
142 &mut self,
143 group: &GroupLabel,
144 id: AssistId,
145 label: impl Into<String>,
146 target: TextRange,
147 f: impl FnOnce(&mut AssistBuilder),
148 ) -> Option<()> {
149 let label = Assist::new(id, label.into(), Some(group.clone()), target);
150 self.add_impl(label, f)
151 }
152 fn add_impl(&mut self, label: Assist, f: impl FnOnce(&mut AssistBuilder)) -> Option<()> {
153 let change_label = label.label.clone();
154 let source_change = if self.resolve {
155 let mut builder = AssistBuilder::new(self.file);
156 f(&mut builder);
157 Some(builder.finish(change_label))
158 } else {
159 None
160 };
161
162 self.buf.push((label, source_change));
163 Some(())
164 }
165
166 fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> {
167 self.buf.sort_by_key(|(label, _edit)| label.target.len());
168 self.buf
169 }
170}
171
172pub(crate) struct AssistBuilder {
173 edit: TextEditBuilder,
174 file: FileId,
175 is_snippet: bool,
176}
177
178impl AssistBuilder {
179 pub(crate) fn new(file: FileId) -> AssistBuilder {
180 AssistBuilder { edit: TextEditBuilder::default(), file, is_snippet: false }
181 }
182
183 /// Remove specified `range` of text.
184 pub(crate) fn delete(&mut self, range: TextRange) {
185 self.edit.delete(range)
186 }
187 /// Append specified `text` at the given `offset`
188 pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) {
189 self.edit.insert(offset, text.into())
190 }
191 /// Append specified `snippet` at the given `offset`
192 pub(crate) fn insert_snippet(
193 &mut self,
194 _cap: SnippetCap,
195 offset: TextSize,
196 snippet: impl Into<String>,
197 ) {
198 self.is_snippet = true;
199 self.insert(offset, snippet);
200 }
201 /// Replaces specified `range` of text with a given string.
202 pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) {
203 self.edit.replace(range, replace_with.into())
204 }
205 /// Replaces specified `range` of text with a given `snippet`.
206 pub(crate) fn replace_snippet(
207 &mut self,
208 _cap: SnippetCap,
209 range: TextRange,
210 snippet: impl Into<String>,
211 ) {
212 self.is_snippet = true;
213 self.replace(range, snippet);
214 }
215 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) {
216 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit)
217 }
218 /// Replaces specified `node` of text with a given string, reindenting the
219 /// string to maintain `node`'s existing indent.
220 // FIXME: remove in favor of ra_syntax::edit::IndentLevel::increase_indent
221 pub(crate) fn replace_node_and_indent(
222 &mut self,
223 node: &SyntaxNode,
224 replace_with: impl Into<String>,
225 ) {
226 let mut replace_with = replace_with.into();
227 if let Some(indent) = leading_indent(node) {
228 replace_with = reindent(&replace_with, &indent)
229 }
230 self.replace(node.text_range(), replace_with)
231 }
232 pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) {
233 let node = rewriter.rewrite_root().unwrap();
234 let new = rewriter.rewrite(&node);
235 algo::diff(&node, &new).into_text_edit(&mut self.edit)
236 }
237
238 // FIXME: better API
239 pub(crate) fn set_file(&mut self, assist_file: FileId) {
240 self.file = assist_file;
241 }
242
243 // FIXME: kill this API
244 /// Get access to the raw `TextEditBuilder`.
245 pub(crate) fn text_edit_builder(&mut self) -> &mut TextEditBuilder {
246 &mut self.edit
247 }
248
249 fn finish(self, change_label: String) -> SourceChange {
250 let edit = self.edit.finish();
251 let mut res = SingleFileChange { label: change_label, edit }.into_source_change(self.file);
252 if self.is_snippet {
253 res.is_snippet = true;
254 }
255 res
256 }
257}
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
deleted file mode 100644
index 2fe7c3de3..000000000
--- a/crates/ra_assists/src/assist_ctx.rs
+++ /dev/null
@@ -1,257 +0,0 @@
1//! This module defines `AssistCtx` -- the API surface that is exposed to assists.
2use hir::Semantics;
3use ra_db::FileRange;
4use ra_fmt::{leading_indent, reindent};
5use ra_ide_db::RootDatabase;
6use ra_syntax::{
7 algo::{self, find_covering_element, find_node_at_offset},
8 AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, TextSize,
9 TokenAtOffset,
10};
11use ra_text_edit::TextEditBuilder;
12
13use crate::{AssistAction, AssistFile, AssistId, AssistLabel, GroupLabel, ResolvedAssist};
14use algo::SyntaxRewriter;
15
16#[derive(Clone, Debug)]
17pub(crate) struct Assist(pub(crate) Vec<AssistInfo>);
18
19#[derive(Clone, Debug)]
20pub(crate) struct AssistInfo {
21 pub(crate) label: AssistLabel,
22 pub(crate) group_label: Option<GroupLabel>,
23 pub(crate) action: Option<AssistAction>,
24}
25
26impl AssistInfo {
27 fn new(label: AssistLabel) -> AssistInfo {
28 AssistInfo { label, group_label: None, action: None }
29 }
30
31 fn resolved(self, action: AssistAction) -> AssistInfo {
32 AssistInfo { action: Some(action), ..self }
33 }
34
35 fn with_group(self, group_label: GroupLabel) -> AssistInfo {
36 AssistInfo { group_label: Some(group_label), ..self }
37 }
38
39 pub(crate) fn into_resolved(self) -> Option<ResolvedAssist> {
40 let label = self.label;
41 let group_label = self.group_label;
42 self.action.map(|action| ResolvedAssist { label, group_label, action })
43 }
44}
45
46pub(crate) type AssistHandler = fn(AssistCtx) -> Option<Assist>;
47
48/// `AssistCtx` allows to apply an assist or check if it could be applied.
49///
50/// Assists use a somewhat over-engineered approach, given the current needs. The
51/// assists workflow consists of two phases. In the first phase, a user asks for
52/// the list of available assists. In the second phase, the user picks a
53/// particular assist and it gets applied.
54///
55/// There are two peculiarities here:
56///
57/// * first, we ideally avoid computing more things then necessary to answer
58/// "is assist applicable" in the first phase.
59/// * second, when we are applying assist, we don't have a guarantee that there
60/// weren't any changes between the point when user asked for assists and when
61/// they applied a particular assist. So, when applying assist, we need to do
62/// all the checks from scratch.
63///
64/// To avoid repeating the same code twice for both "check" and "apply"
65/// functions, we use an approach reminiscent of that of Django's function based
66/// views dealing with forms. Each assist receives a runtime parameter,
67/// `should_compute_edit`. It first check if an edit is applicable (potentially
68/// computing info required to compute the actual edit). If it is applicable,
69/// and `should_compute_edit` is `true`, it then computes the actual edit.
70///
71/// So, to implement the original assists workflow, we can first apply each edit
72/// with `should_compute_edit = false`, and then applying the selected edit
73/// again, with `should_compute_edit = true` this time.
74///
75/// Note, however, that we don't actually use such two-phase logic at the
76/// moment, because the LSP API is pretty awkward in this place, and it's much
77/// easier to just compute the edit eagerly :-)
78#[derive(Clone)]
79pub(crate) struct AssistCtx<'a> {
80 pub(crate) sema: &'a Semantics<'a, RootDatabase>,
81 pub(crate) db: &'a RootDatabase,
82 pub(crate) frange: FileRange,
83 source_file: SourceFile,
84 should_compute_edit: bool,
85}
86
87impl<'a> AssistCtx<'a> {
88 pub fn new(
89 sema: &'a Semantics<'a, RootDatabase>,
90 frange: FileRange,
91 should_compute_edit: bool,
92 ) -> AssistCtx<'a> {
93 let source_file = sema.parse(frange.file_id);
94 AssistCtx { sema, db: sema.db, frange, source_file, should_compute_edit }
95 }
96
97 pub(crate) fn add_assist(
98 self,
99 id: AssistId,
100 label: impl Into<String>,
101 f: impl FnOnce(&mut ActionBuilder),
102 ) -> Option<Assist> {
103 let label = AssistLabel::new(label.into(), id);
104
105 let mut info = AssistInfo::new(label);
106 if self.should_compute_edit {
107 let action = {
108 let mut edit = ActionBuilder::default();
109 f(&mut edit);
110 edit.build()
111 };
112 info = info.resolved(action)
113 };
114
115 Some(Assist(vec![info]))
116 }
117
118 pub(crate) fn add_assist_group(self, group_name: impl Into<String>) -> AssistGroup<'a> {
119 AssistGroup { ctx: self, group_name: group_name.into(), assists: Vec::new() }
120 }
121
122 pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
123 self.source_file.syntax().token_at_offset(self.frange.range.start())
124 }
125
126 pub(crate) fn find_token_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
127 self.token_at_offset().find(|it| it.kind() == kind)
128 }
129
130 pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
131 find_node_at_offset(self.source_file.syntax(), self.frange.range.start())
132 }
133 pub(crate) fn covering_element(&self) -> SyntaxElement {
134 find_covering_element(self.source_file.syntax(), self.frange.range)
135 }
136 pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {
137 find_covering_element(self.source_file.syntax(), range)
138 }
139}
140
141pub(crate) struct AssistGroup<'a> {
142 ctx: AssistCtx<'a>,
143 group_name: String,
144 assists: Vec<AssistInfo>,
145}
146
147impl<'a> AssistGroup<'a> {
148 pub(crate) fn add_assist(
149 &mut self,
150 id: AssistId,
151 label: impl Into<String>,
152 f: impl FnOnce(&mut ActionBuilder),
153 ) {
154 let label = AssistLabel::new(label.into(), id);
155
156 let mut info = AssistInfo::new(label).with_group(GroupLabel(self.group_name.clone()));
157 if self.ctx.should_compute_edit {
158 let action = {
159 let mut edit = ActionBuilder::default();
160 f(&mut edit);
161 edit.build()
162 };
163 info = info.resolved(action)
164 };
165
166 self.assists.push(info)
167 }
168
169 pub(crate) fn finish(self) -> Option<Assist> {
170 if self.assists.is_empty() {
171 None
172 } else {
173 Some(Assist(self.assists))
174 }
175 }
176}
177
178#[derive(Default)]
179pub(crate) struct ActionBuilder {
180 edit: TextEditBuilder,
181 cursor_position: Option<TextSize>,
182 target: Option<TextRange>,
183 file: AssistFile,
184}
185
186impl ActionBuilder {
187 /// Replaces specified `range` of text with a given string.
188 pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) {
189 self.edit.replace(range, replace_with.into())
190 }
191
192 /// Replaces specified `node` of text with a given string, reindenting the
193 /// string to maintain `node`'s existing indent.
194 // FIXME: remove in favor of ra_syntax::edit::IndentLevel::increase_indent
195 pub(crate) fn replace_node_and_indent(
196 &mut self,
197 node: &SyntaxNode,
198 replace_with: impl Into<String>,
199 ) {
200 let mut replace_with = replace_with.into();
201 if let Some(indent) = leading_indent(node) {
202 replace_with = reindent(&replace_with, &indent)
203 }
204 self.replace(node.text_range(), replace_with)
205 }
206
207 /// Remove specified `range` of text.
208 #[allow(unused)]
209 pub(crate) fn delete(&mut self, range: TextRange) {
210 self.edit.delete(range)
211 }
212
213 /// Append specified `text` at the given `offset`
214 pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) {
215 self.edit.insert(offset, text.into())
216 }
217
218 /// Specify desired position of the cursor after the assist is applied.
219 pub(crate) fn set_cursor(&mut self, offset: TextSize) {
220 self.cursor_position = Some(offset)
221 }
222
223 /// Specify that the assist should be active withing the `target` range.
224 ///
225 /// Target ranges are used to sort assists: the smaller the target range,
226 /// the more specific assist is, and so it should be sorted first.
227 pub(crate) fn target(&mut self, target: TextRange) {
228 self.target = Some(target)
229 }
230
231 /// Get access to the raw `TextEditBuilder`.
232 pub(crate) fn text_edit_builder(&mut self) -> &mut TextEditBuilder {
233 &mut self.edit
234 }
235
236 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) {
237 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit)
238 }
239 pub(crate) fn rewrite(&mut self, rewriter: SyntaxRewriter) {
240 let node = rewriter.rewrite_root().unwrap();
241 let new = rewriter.rewrite(&node);
242 algo::diff(&node, &new).into_text_edit(&mut self.edit)
243 }
244
245 pub(crate) fn set_file(&mut self, assist_file: AssistFile) {
246 self.file = assist_file
247 }
248
249 fn build(self) -> AssistAction {
250 AssistAction {
251 edit: self.edit.finish(),
252 cursor_position: self.cursor_position,
253 target: self.target,
254 file: self.file,
255 }
256 }
257}
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs
index 9ac65ab39..3079a02a2 100644
--- a/crates/ra_assists/src/ast_transform.rs
+++ b/crates/ra_assists/src/ast_transform.rs
@@ -1,7 +1,7 @@
1//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined. 1//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
2use rustc_hash::FxHashMap; 2use rustc_hash::FxHashMap;
3 3
4use hir::{PathResolution, SemanticsScope}; 4use hir::{HirDisplay, PathResolution, SemanticsScope};
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{ 6use ra_syntax::{
7 algo::SyntaxRewriter, 7 algo::SyntaxRewriter,
@@ -51,7 +51,27 @@ impl<'a> SubstituteTypeParams<'a> {
51 .into_iter() 51 .into_iter()
52 // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky 52 // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
53 .skip(1) 53 .skip(1)
54 .zip(substs.into_iter()) 54 // The actual list of trait type parameters may be longer than the one
55 // used in the `impl` block due to trailing default type parametrs.
56 // For that case we extend the `substs` with an empty iterator so we
57 // can still hit those trailing values and check if they actually have
58 // a default type. If they do, go for that type from `hir` to `ast` so
59 // the resulting change can be applied correctly.
60 .zip(substs.into_iter().map(Some).chain(std::iter::repeat(None)))
61 .filter_map(|(k, v)| match v {
62 Some(v) => Some((k, v)),
63 None => {
64 let default = k.default(source_scope.db)?;
65 Some((
66 k,
67 ast::make::type_ref(
68 &default
69 .display_source_code(source_scope.db, source_scope.module()?.into())
70 .ok()?,
71 ),
72 ))
73 }
74 })
55 .collect(); 75 .collect();
56 return SubstituteTypeParams { 76 return SubstituteTypeParams {
57 source_scope, 77 source_scope,
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs
deleted file mode 100644
index c0f9bc1fb..000000000
--- a/crates/ra_assists/src/doc_tests.rs
+++ /dev/null
@@ -1,35 +0,0 @@
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 ra_db::FileRange;
9use test_utils::{assert_eq_text, extract_range_or_offset};
10
11use crate::resolved_assists;
12
13fn check(assist_id: &str, before: &str, after: &str) {
14 let (selection, before) = extract_range_or_offset(before);
15 let (db, file_id) = crate::helpers::with_single_file(&before);
16 let frange = FileRange { file_id, range: selection.into() };
17
18 let assist = resolved_assists(&db, frange)
19 .into_iter()
20 .find(|assist| assist.label.id.0 == assist_id)
21 .unwrap_or_else(|| {
22 panic!(
23 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
24 assist_id,
25 resolved_assists(&db, frange)
26 .into_iter()
27 .map(|assist| assist.label.id.0)
28 .collect::<Vec<_>>()
29 .join(", ")
30 )
31 });
32
33 let actual = assist.action.edit.apply(&before);
34 assert_eq_text!(after, &actual);
35}
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs
index 4ea26a550..fa70c8496 100644
--- a/crates/ra_assists/src/handlers/add_custom_impl.rs
+++ b/crates/ra_assists/src/handlers/add_custom_impl.rs
@@ -6,7 +6,10 @@ use ra_syntax::{
6}; 6};
7use stdx::SepBy; 7use stdx::SepBy;
8 8
9use crate::{Assist, AssistCtx, AssistId}; 9use crate::{
10 assist_context::{AssistContext, Assists},
11 AssistId,
12};
10 13
11// Assist: add_custom_impl 14// Assist: add_custom_impl
12// 15//
@@ -22,10 +25,10 @@ use crate::{Assist, AssistCtx, AssistId};
22// struct S; 25// struct S;
23// 26//
24// impl Debug for S { 27// impl Debug for S {
25// 28// $0
26// } 29// }
27// ``` 30// ```
28pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> { 31pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
29 let input = ctx.find_node_at_offset::<ast::AttrInput>()?; 32 let input = ctx.find_node_at_offset::<ast::AttrInput>()?;
30 let attr = input.syntax().parent().and_then(ast::Attr::cast)?; 33 let attr = input.syntax().parent().and_then(ast::Attr::cast)?;
31 34
@@ -46,11 +49,10 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
46 let start_offset = annotated.syntax().parent()?.text_range().end(); 49 let start_offset = annotated.syntax().parent()?.text_range().end();
47 50
48 let label = 51 let label =
49 format!("Add custom impl '{}' for '{}'", trait_token.text().as_str(), annotated_name); 52 format!("Add custom impl `{}` for `{}`", trait_token.text().as_str(), annotated_name);
50
51 ctx.add_assist(AssistId("add_custom_impl"), label, |edit| {
52 edit.target(attr.syntax().text_range());
53 53
54 let target = attr.syntax().text_range();
55 acc.add(AssistId("add_custom_impl"), label, target, |builder| {
54 let new_attr_input = input 56 let new_attr_input = input
55 .syntax() 57 .syntax()
56 .descendants_with_tokens() 58 .descendants_with_tokens()
@@ -61,20 +63,11 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
61 let has_more_derives = !new_attr_input.is_empty(); 63 let has_more_derives = !new_attr_input.is_empty();
62 let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string(); 64 let new_attr_input = new_attr_input.iter().sep_by(", ").surround_with("(", ")").to_string();
63 65
64 let mut buf = String::new(); 66 if has_more_derives {
65 buf.push_str("\n\nimpl "); 67 builder.replace(input.syntax().text_range(), new_attr_input);
66 buf.push_str(trait_token.text().as_str());
67 buf.push_str(" for ");
68 buf.push_str(annotated_name.as_str());
69 buf.push_str(" {\n");
70
71 let cursor_delta = if has_more_derives {
72 let delta = input.syntax().text_range().len() - TextSize::of(&new_attr_input);
73 edit.replace(input.syntax().text_range(), new_attr_input);
74 delta
75 } else { 68 } else {
76 let attr_range = attr.syntax().text_range(); 69 let attr_range = attr.syntax().text_range();
77 edit.delete(attr_range); 70 builder.delete(attr_range);
78 71
79 let line_break_range = attr 72 let line_break_range = attr
80 .syntax() 73 .syntax()
@@ -82,20 +75,30 @@ pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option<Assist> {
82 .filter(|t| t.kind() == WHITESPACE) 75 .filter(|t| t.kind() == WHITESPACE)
83 .map(|t| t.text_range()) 76 .map(|t| t.text_range())
84 .unwrap_or_else(|| TextRange::new(TextSize::from(0), TextSize::from(0))); 77 .unwrap_or_else(|| TextRange::new(TextSize::from(0), TextSize::from(0)));
85 edit.delete(line_break_range); 78 builder.delete(line_break_range);
86 79 }
87 attr_range.len() + line_break_range.len() 80
88 }; 81 match ctx.config.snippet_cap {
89 82 Some(cap) => {
90 edit.set_cursor(start_offset + TextSize::of(&buf) - cursor_delta); 83 builder.insert_snippet(
91 buf.push_str("\n}"); 84 cap,
92 edit.insert(start_offset, buf); 85 start_offset,
86 format!("\n\nimpl {} for {} {{\n $0\n}}", trait_token, annotated_name),
87 );
88 }
89 None => {
90 builder.insert(
91 start_offset,
92 format!("\n\nimpl {} for {} {{\n\n}}", trait_token, annotated_name),
93 );
94 }
95 }
93 }) 96 })
94} 97}
95 98
96#[cfg(test)] 99#[cfg(test)]
97mod tests { 100mod tests {
98 use crate::helpers::{check_assist, check_assist_not_applicable}; 101 use crate::tests::{check_assist, check_assist_not_applicable};
99 102
100 use super::*; 103 use super::*;
101 104
@@ -115,7 +118,7 @@ struct Foo {
115} 118}
116 119
117impl Debug for Foo { 120impl Debug for Foo {
118<|> 121 $0
119} 122}
120 ", 123 ",
121 ) 124 )
@@ -137,7 +140,7 @@ pub struct Foo {
137} 140}
138 141
139impl Debug for Foo { 142impl Debug for Foo {
140<|> 143 $0
141} 144}
142 ", 145 ",
143 ) 146 )
@@ -156,7 +159,7 @@ struct Foo {}
156struct Foo {} 159struct Foo {}
157 160
158impl Debug for Foo { 161impl Debug for Foo {
159<|> 162 $0
160} 163}
161 ", 164 ",
162 ) 165 )
diff --git a/crates/ra_assists/src/handlers/add_derive.rs b/crates/ra_assists/src/handlers/add_derive.rs
index 6254eb7c4..b123b8498 100644
--- a/crates/ra_assists/src/handlers/add_derive.rs
+++ b/crates/ra_assists/src/handlers/add_derive.rs
@@ -4,7 +4,7 @@ use ra_syntax::{
4 TextSize, 4 TextSize,
5}; 5};
6 6
7use crate::{Assist, AssistCtx, AssistId}; 7use crate::{AssistContext, AssistId, Assists};
8 8
9// Assist: add_derive 9// Assist: add_derive
10// 10//
@@ -18,31 +18,37 @@ use crate::{Assist, AssistCtx, AssistId};
18// ``` 18// ```
19// -> 19// ->
20// ``` 20// ```
21// #[derive()] 21// #[derive($0)]
22// struct Point { 22// struct Point {
23// x: u32, 23// x: u32,
24// y: u32, 24// y: u32,
25// } 25// }
26// ``` 26// ```
27pub(crate) fn add_derive(ctx: AssistCtx) -> Option<Assist> { 27pub(crate) fn add_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
28 let cap = ctx.config.snippet_cap?;
28 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; 29 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
29 let node_start = derive_insertion_offset(&nominal)?; 30 let node_start = derive_insertion_offset(&nominal)?;
30 ctx.add_assist(AssistId("add_derive"), "Add `#[derive]`", |edit| { 31 let target = nominal.syntax().text_range();
32 acc.add(AssistId("add_derive"), "Add `#[derive]`", target, |builder| {
31 let derive_attr = nominal 33 let derive_attr = nominal
32 .attrs() 34 .attrs()
33 .filter_map(|x| x.as_simple_call()) 35 .filter_map(|x| x.as_simple_call())
34 .filter(|(name, _arg)| name == "derive") 36 .filter(|(name, _arg)| name == "derive")
35 .map(|(_name, arg)| arg) 37 .map(|(_name, arg)| arg)
36 .next(); 38 .next();
37 let offset = match derive_attr { 39 match derive_attr {
38 None => { 40 None => {
39 edit.insert(node_start, "#[derive()]\n"); 41 builder.insert_snippet(cap, node_start, "#[derive($0)]\n");
40 node_start + TextSize::of("#[derive(") 42 }
43 Some(tt) => {
44 // Just move the cursor.
45 builder.insert_snippet(
46 cap,
47 tt.syntax().text_range().end() - TextSize::of(')'),
48 "$0",
49 )
41 } 50 }
42 Some(tt) => tt.syntax().text_range().end() - TextSize::of(')'),
43 }; 51 };
44 edit.target(nominal.syntax().text_range());
45 edit.set_cursor(offset)
46 }) 52 })
47} 53}
48 54
@@ -57,20 +63,21 @@ fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextSize> {
57 63
58#[cfg(test)] 64#[cfg(test)]
59mod tests { 65mod tests {
66 use crate::tests::{check_assist, check_assist_target};
67
60 use super::*; 68 use super::*;
61 use crate::helpers::{check_assist, check_assist_target};
62 69
63 #[test] 70 #[test]
64 fn add_derive_new() { 71 fn add_derive_new() {
65 check_assist( 72 check_assist(
66 add_derive, 73 add_derive,
67 "struct Foo { a: i32, <|>}", 74 "struct Foo { a: i32, <|>}",
68 "#[derive(<|>)]\nstruct Foo { a: i32, }", 75 "#[derive($0)]\nstruct Foo { a: i32, }",
69 ); 76 );
70 check_assist( 77 check_assist(
71 add_derive, 78 add_derive,
72 "struct Foo { <|> a: i32, }", 79 "struct Foo { <|> a: i32, }",
73 "#[derive(<|>)]\nstruct Foo { a: i32, }", 80 "#[derive($0)]\nstruct Foo { a: i32, }",
74 ); 81 );
75 } 82 }
76 83
@@ -79,7 +86,7 @@ mod tests {
79 check_assist( 86 check_assist(
80 add_derive, 87 add_derive,
81 "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", 88 "#[derive(Clone)]\nstruct Foo { a: i32<|>, }",
82 "#[derive(Clone<|>)]\nstruct Foo { a: i32, }", 89 "#[derive(Clone$0)]\nstruct Foo { a: i32, }",
83 ); 90 );
84 } 91 }
85 92
@@ -95,7 +102,7 @@ struct Foo { a: i32<|>, }
95 " 102 "
96/// `Foo` is a pretty important struct. 103/// `Foo` is a pretty important struct.
97/// It does stuff. 104/// It does stuff.
98#[derive(<|>)] 105#[derive($0)]
99struct Foo { a: i32, } 106struct Foo { a: i32, }
100 ", 107 ",
101 ); 108 );
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs
index bc313782b..ab20c6649 100644
--- a/crates/ra_assists/src/handlers/add_explicit_type.rs
+++ b/crates/ra_assists/src/handlers/add_explicit_type.rs
@@ -4,7 +4,7 @@ use ra_syntax::{
4 TextRange, 4 TextRange,
5}; 5};
6 6
7use crate::{Assist, AssistCtx, AssistId}; 7use crate::{AssistContext, AssistId, Assists};
8 8
9// Assist: add_explicit_type 9// Assist: add_explicit_type
10// 10//
@@ -21,12 +21,12 @@ use crate::{Assist, AssistCtx, AssistId};
21// let x: i32 = 92; 21// let x: i32 = 92;
22// } 22// }
23// ``` 23// ```
24pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> { 24pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
25 let stmt = ctx.find_node_at_offset::<LetStmt>()?; 25 let stmt = ctx.find_node_at_offset::<LetStmt>()?;
26 let module = ctx.sema.scope(stmt.syntax()).module()?;
26 let expr = stmt.initializer()?; 27 let expr = stmt.initializer()?;
27 let pat = stmt.pat()?;
28 // Must be a binding 28 // Must be a binding
29 let pat = match pat { 29 let pat = match stmt.pat()? {
30 ast::Pat::BindPat(bind_pat) => bind_pat, 30 ast::Pat::BindPat(bind_pat) => bind_pat,
31 _ => return None, 31 _ => return None,
32 }; 32 };
@@ -45,7 +45,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> {
45 // Assist not applicable if the type has already been specified 45 // Assist not applicable if the type has already been specified
46 // and it has no placeholders 46 // and it has no placeholders
47 let ascribed_ty = stmt.ascribed_type(); 47 let ascribed_ty = stmt.ascribed_type();
48 if let Some(ref ty) = ascribed_ty { 48 if let Some(ty) = &ascribed_ty {
49 if ty.syntax().descendants().find_map(ast::PlaceholderType::cast).is_none() { 49 if ty.syntax().descendants().find_map(ast::PlaceholderType::cast).is_none() {
50 return None; 50 return None;
51 } 51 }
@@ -57,17 +57,17 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> {
57 return None; 57 return None;
58 } 58 }
59 59
60 let db = ctx.db; 60 let inferred_type = ty.display_source_code(ctx.db, module.into()).ok()?;
61 let new_type_string = ty.display_truncated(db, None).to_string(); 61 acc.add(
62 ctx.add_assist(
63 AssistId("add_explicit_type"), 62 AssistId("add_explicit_type"),
64 format!("Insert explicit type '{}'", new_type_string), 63 format!("Insert explicit type `{}`", inferred_type),
65 |edit| { 64 pat_range,
66 edit.target(pat_range); 65 |builder| match ascribed_ty {
67 if let Some(ascribed_ty) = ascribed_ty { 66 Some(ascribed_ty) => {
68 edit.replace(ascribed_ty.syntax().text_range(), new_type_string); 67 builder.replace(ascribed_ty.syntax().text_range(), inferred_type);
69 } else { 68 }
70 edit.insert(name_range.end(), format!(": {}", new_type_string)); 69 None => {
70 builder.insert(name_range.end(), format!(": {}", inferred_type));
71 } 71 }
72 }, 72 },
73 ) 73 )
@@ -77,7 +77,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> {
77mod tests { 77mod tests {
78 use super::*; 78 use super::*;
79 79
80 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 80 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
81 81
82 #[test] 82 #[test]
83 fn add_explicit_type_target() { 83 fn add_explicit_type_target() {
@@ -86,11 +86,7 @@ mod tests {
86 86
87 #[test] 87 #[test]
88 fn add_explicit_type_works_for_simple_expr() { 88 fn add_explicit_type_works_for_simple_expr() {
89 check_assist( 89 check_assist(add_explicit_type, "fn f() { let a<|> = 1; }", "fn f() { let a: i32 = 1; }");
90 add_explicit_type,
91 "fn f() { let a<|> = 1; }",
92 "fn f() { let a<|>: i32 = 1; }",
93 );
94 } 90 }
95 91
96 #[test] 92 #[test]
@@ -98,7 +94,7 @@ mod tests {
98 check_assist( 94 check_assist(
99 add_explicit_type, 95 add_explicit_type,
100 "fn f() { let a<|>: _ = 1; }", 96 "fn f() { let a<|>: _ = 1; }",
101 "fn f() { let a<|>: i32 = 1; }", 97 "fn f() { let a: i32 = 1; }",
102 ); 98 );
103 } 99 }
104 100
@@ -122,7 +118,7 @@ mod tests {
122 } 118 }
123 119
124 fn f() { 120 fn f() {
125 let a<|>: Option<i32> = Option::Some(1); 121 let a: Option<i32> = Option::Some(1);
126 }"#, 122 }"#,
127 ); 123 );
128 } 124 }
@@ -132,7 +128,7 @@ mod tests {
132 check_assist( 128 check_assist(
133 add_explicit_type, 129 add_explicit_type,
134 r"macro_rules! v { () => {0u64} } fn f() { let a<|> = v!(); }", 130 r"macro_rules! v { () => {0u64} } fn f() { let a<|> = v!(); }",
135 r"macro_rules! v { () => {0u64} } fn f() { let a<|>: u64 = v!(); }", 131 r"macro_rules! v { () => {0u64} } fn f() { let a: u64 = v!(); }",
136 ); 132 );
137 } 133 }
138 134
@@ -140,8 +136,8 @@ mod tests {
140 fn add_explicit_type_works_for_macro_call_recursive() { 136 fn add_explicit_type_works_for_macro_call_recursive() {
141 check_assist( 137 check_assist(
142 add_explicit_type, 138 add_explicit_type,
143 "macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|> = v!(); }", 139 r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|> = v!(); }"#,
144 "macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a<|>: u64 = v!(); }", 140 r#"macro_rules! u { () => {0u64} } macro_rules! v { () => {u!()} } fn f() { let a: u64 = v!(); }"#,
145 ); 141 );
146 } 142 }
147 143
@@ -208,7 +204,7 @@ struct Test<K, T = u8> {
208} 204}
209 205
210fn main() { 206fn main() {
211 let test<|>: Test<i32> = Test { t: 23, k: 33 }; 207 let test: Test<i32> = Test { t: 23, k: 33 };
212}"#, 208}"#,
213 ); 209 );
214 } 210 }
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
index 49deb6701..6a675e812 100644
--- a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
+++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
@@ -1,12 +1,8 @@
1use ra_ide_db::RootDatabase; 1use ra_ide_db::RootDatabase;
2use ra_syntax::{ 2use ra_syntax::ast::{self, AstNode, NameOwner};
3 ast::{self, AstNode, NameOwner}, 3use test_utils::mark;
4 TextSize,
5};
6use stdx::format_to;
7 4
8use crate::{utils::FamousDefs, Assist, AssistCtx, AssistId}; 5use crate::{utils::FamousDefs, AssistContext, AssistId, Assists};
9use test_utils::tested_by;
10 6
11// Assist add_from_impl_for_enum 7// Assist add_from_impl_for_enum
12// 8//
@@ -25,7 +21,7 @@ use test_utils::tested_by;
25// } 21// }
26// } 22// }
27// ``` 23// ```
28pub(crate) fn add_from_impl_for_enum(ctx: AssistCtx) -> Option<Assist> { 24pub(crate) fn add_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
29 let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?; 25 let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?;
30 let variant_name = variant.name()?; 26 let variant_name = variant.name()?;
31 let enum_name = variant.parent_enum().name()?; 27 let enum_name = variant.parent_enum().name()?;
@@ -38,23 +34,23 @@ pub(crate) fn add_from_impl_for_enum(ctx: AssistCtx) -> Option<Assist> {
38 } 34 }
39 let field_type = field_list.fields().next()?.type_ref()?; 35 let field_type = field_list.fields().next()?.type_ref()?;
40 let path = match field_type { 36 let path = match field_type {
41 ast::TypeRef::PathType(p) => p, 37 ast::TypeRef::PathType(it) => it,
42 _ => return None, 38 _ => return None,
43 }; 39 };
44 40
45 if existing_from_impl(ctx.sema, &variant).is_some() { 41 if existing_from_impl(&ctx.sema, &variant).is_some() {
46 tested_by!(test_add_from_impl_already_exists); 42 mark::hit!(test_add_from_impl_already_exists);
47 return None; 43 return None;
48 } 44 }
49 45
50 ctx.add_assist( 46 let target = variant.syntax().text_range();
47 acc.add(
51 AssistId("add_from_impl_for_enum"), 48 AssistId("add_from_impl_for_enum"),
52 "Add From impl for this enum variant", 49 "Add From impl for this enum variant",
50 target,
53 |edit| { 51 |edit| {
54 let start_offset = variant.parent_enum().syntax().text_range().end(); 52 let start_offset = variant.parent_enum().syntax().text_range().end();
55 let mut buf = String::new(); 53 let buf = format!(
56 format_to!(
57 buf,
58 r#" 54 r#"
59 55
60impl From<{0}> for {1} {{ 56impl From<{0}> for {1} {{
@@ -67,7 +63,6 @@ impl From<{0}> for {1} {{
67 variant_name 63 variant_name
68 ); 64 );
69 edit.insert(start_offset, buf); 65 edit.insert(start_offset, buf);
70 edit.set_cursor(start_offset + TextSize::of("\n\n"));
71 }, 66 },
72 ) 67 )
73} 68}
@@ -95,10 +90,11 @@ fn existing_from_impl(
95 90
96#[cfg(test)] 91#[cfg(test)]
97mod tests { 92mod tests {
98 use super::*; 93 use test_utils::mark;
94
95 use crate::tests::{check_assist, check_assist_not_applicable};
99 96
100 use crate::helpers::{check_assist, check_assist_not_applicable}; 97 use super::*;
101 use test_utils::covers;
102 98
103 #[test] 99 #[test]
104 fn test_add_from_impl_for_enum() { 100 fn test_add_from_impl_for_enum() {
@@ -107,7 +103,7 @@ mod tests {
107 "enum A { <|>One(u32) }", 103 "enum A { <|>One(u32) }",
108 r#"enum A { One(u32) } 104 r#"enum A { One(u32) }
109 105
110<|>impl From<u32> for A { 106impl From<u32> for A {
111 fn from(v: u32) -> Self { 107 fn from(v: u32) -> Self {
112 A::One(v) 108 A::One(v)
113 } 109 }
@@ -119,10 +115,10 @@ mod tests {
119 fn test_add_from_impl_for_enum_complicated_path() { 115 fn test_add_from_impl_for_enum_complicated_path() {
120 check_assist( 116 check_assist(
121 add_from_impl_for_enum, 117 add_from_impl_for_enum,
122 "enum A { <|>One(foo::bar::baz::Boo) }", 118 r#"enum A { <|>One(foo::bar::baz::Boo) }"#,
123 r#"enum A { One(foo::bar::baz::Boo) } 119 r#"enum A { One(foo::bar::baz::Boo) }
124 120
125<|>impl From<foo::bar::baz::Boo> for A { 121impl From<foo::bar::baz::Boo> for A {
126 fn from(v: foo::bar::baz::Boo) -> Self { 122 fn from(v: foo::bar::baz::Boo) -> Self {
127 A::One(v) 123 A::One(v)
128 } 124 }
@@ -153,7 +149,7 @@ mod tests {
153 149
154 #[test] 150 #[test]
155 fn test_add_from_impl_already_exists() { 151 fn test_add_from_impl_already_exists() {
156 covers!(test_add_from_impl_already_exists); 152 mark::check!(test_add_from_impl_already_exists);
157 check_not_applicable( 153 check_not_applicable(
158 r#" 154 r#"
159enum A { <|>One(u32), } 155enum A { <|>One(u32), }
@@ -184,7 +180,7 @@ pub trait From<T> {
184}"#, 180}"#,
185 r#"enum A { One(u32), Two(String), } 181 r#"enum A { One(u32), Two(String), }
186 182
187<|>impl From<u32> for A { 183impl From<u32> for A {
188 fn from(v: u32) -> Self { 184 fn from(v: u32) -> Self {
189 A::One(v) 185 A::One(v)
190 } 186 }
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs
index 6c7456579..24f931a85 100644
--- a/crates/ra_assists/src/handlers/add_function.rs
+++ b/crates/ra_assists/src/handlers/add_function.rs
@@ -1,13 +1,21 @@
1use hir::HirDisplay;
2use ra_db::FileId;
1use ra_syntax::{ 3use ra_syntax::{
2 ast::{self, AstNode}, 4 ast::{
5 self,
6 edit::{AstNodeEdit, IndentLevel},
7 make, ArgListOwner, AstNode, ModuleItemOwner,
8 },
3 SyntaxKind, SyntaxNode, TextSize, 9 SyntaxKind, SyntaxNode, TextSize,
4}; 10};
5
6use crate::{Assist, AssistCtx, AssistFile, AssistId};
7use ast::{edit::IndentLevel, ArgListOwner, ModuleItemOwner};
8use hir::HirDisplay;
9use rustc_hash::{FxHashMap, FxHashSet}; 11use rustc_hash::{FxHashMap, FxHashSet};
10 12
13use crate::{
14 assist_config::SnippetCap,
15 utils::{render_snippet, Cursor},
16 AssistContext, AssistId, Assists,
17};
18
11// Assist: add_function 19// Assist: add_function
12// 20//
13// Adds a stub function with a signature matching the function under the cursor. 21// Adds a stub function with a signature matching the function under the cursor.
@@ -29,11 +37,11 @@ use rustc_hash::{FxHashMap, FxHashSet};
29// } 37// }
30// 38//
31// fn bar(arg: &str, baz: Baz) { 39// fn bar(arg: &str, baz: Baz) {
32// todo!() 40// ${0:todo!()}
33// } 41// }
34// 42//
35// ``` 43// ```
36pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> { 44pub(crate) fn add_function(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
37 let path_expr: ast::PathExpr = ctx.find_node_at_offset()?; 45 let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
38 let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?; 46 let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?;
39 let path = path_expr.path()?; 47 let path = path_expr.path()?;
@@ -43,36 +51,49 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> {
43 return None; 51 return None;
44 } 52 }
45 53
46 let target_module = if let Some(qualifier) = path.qualifier() { 54 let target_module = match path.qualifier() {
47 if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = 55 Some(qualifier) => match ctx.sema.resolve_path(&qualifier) {
48 ctx.sema.resolve_path(&qualifier) 56 Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) => Some(module),
49 { 57 _ => return None,
50 Some(module.definition_source(ctx.sema.db)) 58 },
51 } else { 59 None => None,
52 return None;
53 }
54 } else {
55 None
56 }; 60 };
57 61
58 let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; 62 let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?;
59 63
60 ctx.add_assist(AssistId("add_function"), "Add function", |edit| { 64 let target = call.syntax().text_range();
61 edit.target(call.syntax().text_range()); 65 acc.add(AssistId("add_function"), "Add function", target, |builder| {
62 66 let function_template = function_builder.render();
63 if let Some(function_template) = function_builder.render() { 67 builder.set_file(function_template.file);
64 edit.set_file(function_template.file); 68 let new_fn = function_template.to_string(ctx.config.snippet_cap);
65 edit.set_cursor(function_template.cursor_offset); 69 match ctx.config.snippet_cap {
66 edit.insert(function_template.insert_offset, function_template.fn_def.to_string()); 70 Some(cap) => builder.insert_snippet(cap, function_template.insert_offset, new_fn),
71 None => builder.insert(function_template.insert_offset, new_fn),
67 } 72 }
68 }) 73 })
69} 74}
70 75
71struct FunctionTemplate { 76struct FunctionTemplate {
72 insert_offset: TextSize, 77 insert_offset: TextSize,
73 cursor_offset: TextSize, 78 placeholder_expr: ast::MacroCall,
74 fn_def: ast::SourceFile, 79 leading_ws: String,
75 file: AssistFile, 80 fn_def: ast::FnDef,
81 trailing_ws: String,
82 file: FileId,
83}
84
85impl FunctionTemplate {
86 fn to_string(&self, cap: Option<SnippetCap>) -> String {
87 let f = match cap {
88 Some(cap) => render_snippet(
89 cap,
90 self.fn_def.syntax(),
91 Cursor::Replace(self.placeholder_expr.syntax()),
92 ),
93 None => self.fn_def.to_string(),
94 };
95 format!("{}{}{}", self.leading_ws, f, self.trailing_ws)
96 }
76} 97}
77 98
78struct FunctionBuilder { 99struct FunctionBuilder {
@@ -80,68 +101,73 @@ struct FunctionBuilder {
80 fn_name: ast::Name, 101 fn_name: ast::Name,
81 type_params: Option<ast::TypeParamList>, 102 type_params: Option<ast::TypeParamList>,
82 params: ast::ParamList, 103 params: ast::ParamList,
83 file: AssistFile, 104 file: FileId,
84 needs_pub: bool, 105 needs_pub: bool,
85} 106}
86 107
87impl FunctionBuilder { 108impl FunctionBuilder {
88 /// Prepares a generated function that matches `call` in `generate_in` 109 /// Prepares a generated function that matches `call`.
89 /// (or as close to `call` as possible, if `generate_in` is `None`) 110 /// The function is generated in `target_module` or next to `call`
90 fn from_call( 111 fn from_call(
91 ctx: &AssistCtx, 112 ctx: &AssistContext,
92 call: &ast::CallExpr, 113 call: &ast::CallExpr,
93 path: &ast::Path, 114 path: &ast::Path,
94 target_module: Option<hir::InFile<hir::ModuleSource>>, 115 target_module: Option<hir::Module>,
95 ) -> Option<Self> { 116 ) -> Option<Self> {
96 let needs_pub = target_module.is_some(); 117 let mut file = ctx.frange.file_id;
97 let mut file = AssistFile::default(); 118 let target = match &target_module {
98 let target = if let Some(target_module) = target_module { 119 Some(target_module) => {
99 let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, target_module)?; 120 let module_source = target_module.definition_source(ctx.db);
100 file = in_file; 121 let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, &module_source)?;
101 target 122 file = in_file;
102 } else { 123 target
103 next_space_for_fn_after_call_site(&call)? 124 }
125 None => next_space_for_fn_after_call_site(&call)?,
104 }; 126 };
127 let needs_pub = target_module.is_some();
128 let target_module = target_module.or_else(|| ctx.sema.scope(target.syntax()).module())?;
105 let fn_name = fn_name(&path)?; 129 let fn_name = fn_name(&path)?;
106 let (type_params, params) = fn_args(ctx, &call)?; 130 let (type_params, params) = fn_args(ctx, target_module, &call)?;
131
107 Some(Self { target, fn_name, type_params, params, file, needs_pub }) 132 Some(Self { target, fn_name, type_params, params, file, needs_pub })
108 } 133 }
109 134
110 fn render(self) -> Option<FunctionTemplate> { 135 fn render(self) -> FunctionTemplate {
111 let placeholder_expr = ast::make::expr_todo(); 136 let placeholder_expr = make::expr_todo();
112 let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); 137 let fn_body = make::block_expr(vec![], Some(placeholder_expr));
113 let mut fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); 138 let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
114 if self.needs_pub { 139 let mut fn_def =
115 fn_def = ast::make::add_pub_crate_modifier(fn_def); 140 make::fn_def(visibility, self.fn_name, self.type_params, self.params, fn_body);
116 } 141 let leading_ws;
142 let trailing_ws;
117 143
118 let (fn_def, insert_offset) = match self.target { 144 let insert_offset = match self.target {
119 GeneratedFunctionTarget::BehindItem(it) => { 145 GeneratedFunctionTarget::BehindItem(it) => {
120 let with_leading_blank_line = ast::make::add_leading_newlines(2, fn_def); 146 let indent = IndentLevel::from_node(&it);
121 let indented = IndentLevel::from_node(&it).increase_indent(with_leading_blank_line); 147 leading_ws = format!("\n\n{}", indent);
122 (indented, it.text_range().end()) 148 fn_def = fn_def.indent(indent);
149 trailing_ws = String::new();
150 it.text_range().end()
123 } 151 }
124 GeneratedFunctionTarget::InEmptyItemList(it) => { 152 GeneratedFunctionTarget::InEmptyItemList(it) => {
125 let indent_once = IndentLevel(1);
126 let indent = IndentLevel::from_node(it.syntax()); 153 let indent = IndentLevel::from_node(it.syntax());
127 154 leading_ws = format!("\n{}", indent + 1);
128 let fn_def = ast::make::add_leading_newlines(1, fn_def); 155 fn_def = fn_def.indent(indent + 1);
129 let fn_def = indent_once.increase_indent(fn_def); 156 trailing_ws = format!("\n{}", indent);
130 let fn_def = ast::make::add_trailing_newlines(1, fn_def); 157 it.syntax().text_range().start() + TextSize::of('{')
131 let fn_def = indent.increase_indent(fn_def);
132 (fn_def, it.syntax().text_range().start() + TextSize::of('{'))
133 } 158 }
134 }; 159 };
135 160
136 let cursor_offset_from_fn_start = fn_def 161 let placeholder_expr =
137 .syntax() 162 fn_def.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
138 .descendants() 163 FunctionTemplate {
139 .find_map(ast::MacroCall::cast)? 164 insert_offset,
140 .syntax() 165 placeholder_expr,
141 .text_range() 166 leading_ws,
142 .start(); 167 fn_def,
143 let cursor_offset = insert_offset + cursor_offset_from_fn_start; 168 trailing_ws,
144 Some(FunctionTemplate { insert_offset, cursor_offset, fn_def, file: self.file }) 169 file: self.file,
170 }
145 } 171 }
146} 172}
147 173
@@ -150,32 +176,41 @@ enum GeneratedFunctionTarget {
150 InEmptyItemList(ast::ItemList), 176 InEmptyItemList(ast::ItemList),
151} 177}
152 178
179impl GeneratedFunctionTarget {
180 fn syntax(&self) -> &SyntaxNode {
181 match self {
182 GeneratedFunctionTarget::BehindItem(it) => it,
183 GeneratedFunctionTarget::InEmptyItemList(it) => it.syntax(),
184 }
185 }
186}
187
153fn fn_name(call: &ast::Path) -> Option<ast::Name> { 188fn fn_name(call: &ast::Path) -> Option<ast::Name> {
154 let name = call.segment()?.syntax().to_string(); 189 let name = call.segment()?.syntax().to_string();
155 Some(ast::make::name(&name)) 190 Some(make::name(&name))
156} 191}
157 192
158/// Computes the type variables and arguments required for the generated function 193/// Computes the type variables and arguments required for the generated function
159fn fn_args( 194fn fn_args(
160 ctx: &AssistCtx, 195 ctx: &AssistContext,
196 target_module: hir::Module,
161 call: &ast::CallExpr, 197 call: &ast::CallExpr,
162) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> { 198) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> {
163 let mut arg_names = Vec::new(); 199 let mut arg_names = Vec::new();
164 let mut arg_types = Vec::new(); 200 let mut arg_types = Vec::new();
165 for arg in call.arg_list()?.args() { 201 for arg in call.arg_list()?.args() {
166 let arg_name = match fn_arg_name(&arg) { 202 arg_names.push(match fn_arg_name(&arg) {
167 Some(name) => name, 203 Some(name) => name,
168 None => String::from("arg"), 204 None => String::from("arg"),
169 }; 205 });
170 arg_names.push(arg_name); 206 arg_types.push(match fn_arg_type(ctx, target_module, &arg) {
171 arg_types.push(match fn_arg_type(ctx, &arg) {
172 Some(ty) => ty, 207 Some(ty) => ty,
173 None => String::from("()"), 208 None => String::from("()"),
174 }); 209 });
175 } 210 }
176 deduplicate_arg_names(&mut arg_names); 211 deduplicate_arg_names(&mut arg_names);
177 let params = arg_names.into_iter().zip(arg_types).map(|(name, ty)| ast::make::param(name, ty)); 212 let params = arg_names.into_iter().zip(arg_types).map(|(name, ty)| make::param(name, ty));
178 Some((None, ast::make::param_list(params))) 213 Some((None, make::param_list(params)))
179} 214}
180 215
181/// Makes duplicate argument names unique by appending incrementing numbers. 216/// Makes duplicate argument names unique by appending incrementing numbers.
@@ -224,12 +259,21 @@ fn fn_arg_name(fn_arg: &ast::Expr) -> Option<String> {
224 } 259 }
225} 260}
226 261
227fn fn_arg_type(ctx: &AssistCtx, fn_arg: &ast::Expr) -> Option<String> { 262fn fn_arg_type(
263 ctx: &AssistContext,
264 target_module: hir::Module,
265 fn_arg: &ast::Expr,
266) -> Option<String> {
228 let ty = ctx.sema.type_of_expr(fn_arg)?; 267 let ty = ctx.sema.type_of_expr(fn_arg)?;
229 if ty.is_unknown() { 268 if ty.is_unknown() {
230 return None; 269 return None;
231 } 270 }
232 Some(ty.display(ctx.sema.db).to_string()) 271
272 if let Ok(rendered) = ty.display_source_code(ctx.db, target_module.into()) {
273 Some(rendered)
274 } else {
275 None
276 }
233} 277}
234 278
235/// Returns the position inside the current mod or file 279/// Returns the position inside the current mod or file
@@ -258,11 +302,10 @@ fn next_space_for_fn_after_call_site(expr: &ast::CallExpr) -> Option<GeneratedFu
258 302
259fn next_space_for_fn_in_module( 303fn next_space_for_fn_in_module(
260 db: &dyn hir::db::AstDatabase, 304 db: &dyn hir::db::AstDatabase,
261 module: hir::InFile<hir::ModuleSource>, 305 module_source: &hir::InFile<hir::ModuleSource>,
262) -> Option<(AssistFile, GeneratedFunctionTarget)> { 306) -> Option<(FileId, GeneratedFunctionTarget)> {
263 let file = module.file_id.original_file(db); 307 let file = module_source.file_id.original_file(db);
264 let assist_file = AssistFile::TargetFile(file); 308 let assist_item = match &module_source.value {
265 let assist_item = match module.value {
266 hir::ModuleSource::SourceFile(it) => { 309 hir::ModuleSource::SourceFile(it) => {
267 if let Some(last_item) = it.items().last() { 310 if let Some(last_item) = it.items().last() {
268 GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) 311 GeneratedFunctionTarget::BehindItem(last_item.syntax().clone())
@@ -278,12 +321,12 @@ fn next_space_for_fn_in_module(
278 } 321 }
279 } 322 }
280 }; 323 };
281 Some((assist_file, assist_item)) 324 Some((file, assist_item))
282} 325}
283 326
284#[cfg(test)] 327#[cfg(test)]
285mod tests { 328mod tests {
286 use crate::helpers::{check_assist, check_assist_not_applicable}; 329 use crate::tests::{check_assist, check_assist_not_applicable};
287 330
288 use super::*; 331 use super::*;
289 332
@@ -302,7 +345,7 @@ fn foo() {
302} 345}
303 346
304fn bar() { 347fn bar() {
305 <|>todo!() 348 ${0:todo!()}
306} 349}
307", 350",
308 ) 351 )
@@ -329,7 +372,7 @@ impl Foo {
329} 372}
330 373
331fn bar() { 374fn bar() {
332 <|>todo!() 375 ${0:todo!()}
333} 376}
334", 377",
335 ) 378 )
@@ -353,7 +396,7 @@ fn foo1() {
353} 396}
354 397
355fn bar() { 398fn bar() {
356 <|>todo!() 399 ${0:todo!()}
357} 400}
358 401
359fn foo2() {} 402fn foo2() {}
@@ -379,7 +422,7 @@ mod baz {
379 } 422 }
380 423
381 fn bar() { 424 fn bar() {
382 <|>todo!() 425 ${0:todo!()}
383 } 426 }
384} 427}
385", 428",
@@ -405,7 +448,7 @@ fn foo() {
405} 448}
406 449
407fn bar(baz: Baz) { 450fn bar(baz: Baz) {
408 <|>todo!() 451 ${0:todo!()}
409} 452}
410", 453",
411 ); 454 );
@@ -438,7 +481,7 @@ impl Baz {
438} 481}
439 482
440fn bar(baz: Baz) { 483fn bar(baz: Baz) {
441 <|>todo!() 484 ${0:todo!()}
442} 485}
443", 486",
444 ) 487 )
@@ -459,7 +502,7 @@ fn foo() {
459} 502}
460 503
461fn bar(arg: &str) { 504fn bar(arg: &str) {
462 <|>todo!() 505 ${0:todo!()}
463} 506}
464"#, 507"#,
465 ) 508 )
@@ -480,7 +523,7 @@ fn foo() {
480} 523}
481 524
482fn bar(arg: char) { 525fn bar(arg: char) {
483 <|>todo!() 526 ${0:todo!()}
484} 527}
485"#, 528"#,
486 ) 529 )
@@ -501,7 +544,7 @@ fn foo() {
501} 544}
502 545
503fn bar(arg: i32) { 546fn bar(arg: i32) {
504 <|>todo!() 547 ${0:todo!()}
505} 548}
506", 549",
507 ) 550 )
@@ -522,7 +565,7 @@ fn foo() {
522} 565}
523 566
524fn bar(arg: u8) { 567fn bar(arg: u8) {
525 <|>todo!() 568 ${0:todo!()}
526} 569}
527", 570",
528 ) 571 )
@@ -547,7 +590,7 @@ fn foo() {
547} 590}
548 591
549fn bar(x: u8) { 592fn bar(x: u8) {
550 <|>todo!() 593 ${0:todo!()}
551} 594}
552", 595",
553 ) 596 )
@@ -570,7 +613,7 @@ fn foo() {
570} 613}
571 614
572fn bar(worble: ()) { 615fn bar(worble: ()) {
573 <|>todo!() 616 ${0:todo!()}
574} 617}
575", 618",
576 ) 619 )
@@ -599,15 +642,40 @@ fn baz() {
599} 642}
600 643
601fn bar(foo: impl Foo) { 644fn bar(foo: impl Foo) {
602 <|>todo!() 645 ${0:todo!()}
646}
647",
648 )
649 }
650
651 #[test]
652 fn borrowed_arg() {
653 check_assist(
654 add_function,
655 r"
656struct Baz;
657fn baz() -> Baz { todo!() }
658
659fn foo() {
660 bar<|>(&baz())
661}
662",
663 r"
664struct Baz;
665fn baz() -> Baz { todo!() }
666
667fn foo() {
668 bar(&baz())
669}
670
671fn bar(baz: &Baz) {
672 ${0:todo!()}
603} 673}
604", 674",
605 ) 675 )
606 } 676 }
607 677
608 #[test] 678 #[test]
609 #[ignore]
610 // FIXME print paths properly to make this test pass
611 fn add_function_with_qualified_path_arg() { 679 fn add_function_with_qualified_path_arg() {
612 check_assist( 680 check_assist(
613 add_function, 681 add_function,
@@ -616,10 +684,8 @@ mod Baz {
616 pub struct Bof; 684 pub struct Bof;
617 pub fn baz() -> Bof { Bof } 685 pub fn baz() -> Bof { Bof }
618} 686}
619mod Foo { 687fn foo() {
620 fn foo() { 688 <|>bar(Baz::baz())
621 <|>bar(super::Baz::baz())
622 }
623} 689}
624", 690",
625 r" 691 r"
@@ -627,14 +693,12 @@ mod Baz {
627 pub struct Bof; 693 pub struct Bof;
628 pub fn baz() -> Bof { Bof } 694 pub fn baz() -> Bof { Bof }
629} 695}
630mod Foo { 696fn foo() {
631 fn foo() { 697 bar(Baz::baz())
632 bar(super::Baz::baz()) 698}
633 }
634 699
635 fn bar(baz: super::Baz::Bof) { 700fn bar(baz: Baz::Bof) {
636 <|>todo!() 701 ${0:todo!()}
637 }
638} 702}
639", 703",
640 ) 704 )
@@ -657,7 +721,7 @@ fn foo<T>(t: T) {
657} 721}
658 722
659fn bar<T>(t: T) { 723fn bar<T>(t: T) {
660 <|>todo!() 724 ${0:todo!()}
661} 725}
662", 726",
663 ) 727 )
@@ -688,7 +752,7 @@ fn foo() {
688} 752}
689 753
690fn bar(arg: fn() -> Baz) { 754fn bar(arg: fn() -> Baz) {
691 <|>todo!() 755 ${0:todo!()}
692} 756}
693", 757",
694 ) 758 )
@@ -713,7 +777,7 @@ fn foo() {
713} 777}
714 778
715fn bar(closure: impl Fn(i64) -> i64) { 779fn bar(closure: impl Fn(i64) -> i64) {
716 <|>todo!() 780 ${0:todo!()}
717} 781}
718", 782",
719 ) 783 )
@@ -734,7 +798,7 @@ fn foo() {
734} 798}
735 799
736fn bar(baz: ()) { 800fn bar(baz: ()) {
737 <|>todo!() 801 ${0:todo!()}
738} 802}
739", 803",
740 ) 804 )
@@ -759,7 +823,7 @@ fn foo() {
759} 823}
760 824
761fn bar(baz_1: Baz, baz_2: Baz) { 825fn bar(baz_1: Baz, baz_2: Baz) {
762 <|>todo!() 826 ${0:todo!()}
763} 827}
764", 828",
765 ) 829 )
@@ -784,7 +848,7 @@ fn foo() {
784} 848}
785 849
786fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) { 850fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) {
787 <|>todo!() 851 ${0:todo!()}
788} 852}
789"#, 853"#,
790 ) 854 )
@@ -804,7 +868,7 @@ fn foo() {
804 r" 868 r"
805mod bar { 869mod bar {
806 pub(crate) fn my_fn() { 870 pub(crate) fn my_fn() {
807 <|>todo!() 871 ${0:todo!()}
808 } 872 }
809} 873}
810 874
@@ -816,6 +880,40 @@ fn foo() {
816 } 880 }
817 881
818 #[test] 882 #[test]
883 #[ignore]
884 // Ignored until local imports are supported.
885 // See https://github.com/rust-analyzer/rust-analyzer/issues/1165
886 fn qualified_path_uses_correct_scope() {
887 check_assist(
888 add_function,
889 "
890mod foo {
891 pub struct Foo;
892}
893fn bar() {
894 use foo::Foo;
895 let foo = Foo;
896 baz<|>(foo)
897}
898",
899 "
900mod foo {
901 pub struct Foo;
902}
903fn bar() {
904 use foo::Foo;
905