aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalilée 'Bill' Enguehard <[email protected]>2020-05-21 22:27:38 +0100
committerGalilée 'Bill' Enguehard <[email protected]>2020-05-21 22:27:38 +0100
commit7fece3bdd2450c0807f7dd742239cae95f0cc65e (patch)
tree866c4db826c959e79c63a6727bdb9f2c61e6fc4f
parentdb926218b2082077750291f8426ddd28b284cd08 (diff)
parent59732df8d40dfadc6dcf5951265416576399712a (diff)
Merge branch 'master' of github.com:rust-analyzer/rust-analyzer into modname_spacing
-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 let foo = Foo;
906 baz(foo)
907}
908
909fn baz(foo: foo::Foo) {
910 ${0:todo!()}
911}
912",
913 )
914 }
915
916 #[test]
819 fn add_function_in_module_containing_other_items() { 917 fn add_function_in_module_containing_other_items() {
820 check_assist( 918 check_assist(
821 add_function, 919 add_function,
@@ -833,7 +931,7 @@ mod bar {
833 fn something_else() {} 931 fn something_else() {}
834 932
835 pub(crate) fn my_fn() { 933 pub(crate) fn my_fn() {
836 <|>todo!() 934 ${0:todo!()}
837 } 935 }
838} 936}
839 937
@@ -861,7 +959,7 @@ fn foo() {
861mod bar { 959mod bar {
862 mod baz { 960 mod baz {
863 pub(crate) fn my_fn() { 961 pub(crate) fn my_fn() {
864 <|>todo!() 962 ${0:todo!()}
865 } 963 }
866 } 964 }
867} 965}
@@ -890,7 +988,7 @@ fn main() {
890 988
891 989
892pub(crate) fn bar() { 990pub(crate) fn bar() {
893 <|>todo!() 991 ${0:todo!()}
894}", 992}",
895 ) 993 )
896 } 994 }
@@ -927,21 +1025,6 @@ fn bar(baz: ()) {}
927 } 1025 }
928 1026
929 #[test] 1027 #[test]
930 fn add_function_not_applicable_if_function_path_not_singleton() {
931 // In the future this assist could be extended to generate functions
932 // if the path is in the same crate (or even the same workspace).
933 // For the beginning, I think this is fine.
934 check_assist_not_applicable(
935 add_function,
936 r"
937fn foo() {
938 other_crate::bar<|>();
939}
940 ",
941 )
942 }
943
944 #[test]
945 #[ignore] 1028 #[ignore]
946 fn create_method_with_no_args() { 1029 fn create_method_with_no_args() {
947 check_assist( 1030 check_assist(
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs
index d26f8b93d..eceba7d0a 100644
--- a/crates/ra_assists/src/handlers/add_impl.rs
+++ b/crates/ra_assists/src/handlers/add_impl.rs
@@ -1,10 +1,7 @@
1use ra_syntax::{ 1use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner};
2 ast::{self, AstNode, NameOwner, TypeParamsOwner},
3 TextSize,
4};
5use stdx::{format_to, SepBy}; 2use stdx::{format_to, SepBy};
6 3
7use crate::{Assist, AssistCtx, AssistId}; 4use crate::{AssistContext, AssistId, Assists};
8 5
9// Assist: add_impl 6// Assist: add_impl
10// 7//
@@ -12,24 +9,24 @@ use crate::{Assist, AssistCtx, AssistId};
12// 9//
13// ``` 10// ```
14// struct Ctx<T: Clone> { 11// struct Ctx<T: Clone> {
15// data: T,<|> 12// data: T,<|>
16// } 13// }
17// ``` 14// ```
18// -> 15// ->
19// ``` 16// ```
20// struct Ctx<T: Clone> { 17// struct Ctx<T: Clone> {
21// data: T, 18// data: T,
22// } 19// }
23// 20//
24// impl<T: Clone> Ctx<T> { 21// impl<T: Clone> Ctx<T> {
25// 22// $0
26// } 23// }
27// ``` 24// ```
28pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> { 25pub(crate) fn add_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
29 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?; 26 let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
30 let name = nominal.name()?; 27 let name = nominal.name()?;
31 ctx.add_assist(AssistId("add_impl"), format!("Implement {}", name.text().as_str()), |edit| { 28 let target = nominal.syntax().text_range();
32 edit.target(nominal.syntax().text_range()); 29 acc.add(AssistId("add_impl"), format!("Implement {}", name.text().as_str()), target, |edit| {
33 let type_params = nominal.type_param_list(); 30 let type_params = nominal.type_param_list();
34 let start_offset = nominal.syntax().text_range().end(); 31 let start_offset = nominal.syntax().text_range().end();
35 let mut buf = String::new(); 32 let mut buf = String::new();
@@ -50,30 +47,37 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> {
50 let generic_params = lifetime_params.chain(type_params).sep_by(", "); 47 let generic_params = lifetime_params.chain(type_params).sep_by(", ");
51 format_to!(buf, "<{}>", generic_params) 48 format_to!(buf, "<{}>", generic_params)
52 } 49 }
53 buf.push_str(" {\n"); 50 match ctx.config.snippet_cap {
54 edit.set_cursor(start_offset + TextSize::of(&buf)); 51 Some(cap) => {
55 buf.push_str("\n}"); 52 buf.push_str(" {\n $0\n}");
56 edit.insert(start_offset, buf); 53 edit.insert_snippet(cap, start_offset, buf);
54 }
55 None => {
56 buf.push_str(" {\n}");
57 edit.insert(start_offset, buf);
58 }
59 }
57 }) 60 })
58} 61}
59 62
60#[cfg(test)] 63#[cfg(test)]
61mod tests { 64mod tests {
65 use crate::tests::{check_assist, check_assist_target};
66
62 use super::*; 67 use super::*;
63 use crate::helpers::{check_assist, check_assist_target};
64 68
65 #[test] 69 #[test]
66 fn test_add_impl() { 70 fn test_add_impl() {
67 check_assist(add_impl, "struct Foo {<|>}\n", "struct Foo {}\n\nimpl Foo {\n<|>\n}\n"); 71 check_assist(add_impl, "struct Foo {<|>}\n", "struct Foo {}\n\nimpl Foo {\n $0\n}\n");
68 check_assist( 72 check_assist(
69 add_impl, 73 add_impl,
70 "struct Foo<T: Clone> {<|>}", 74 "struct Foo<T: Clone> {<|>}",
71 "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n<|>\n}", 75 "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n $0\n}",
72 ); 76 );
73 check_assist( 77 check_assist(
74 add_impl, 78 add_impl,
75 "struct Foo<'a, T: Foo<'a>> {<|>}", 79 "struct Foo<'a, T: Foo<'a>> {<|>}",
76 "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n<|>\n}", 80 "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n $0\n}",
77 ); 81 );
78 } 82 }
79 83
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
index 2d6d44980..abacd4065 100644
--- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
@@ -1,13 +1,18 @@
1use hir::HasSource; 1use hir::HasSource;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, edit, make, AstNode, NameOwner}, 3 ast::{
4 self,
5 edit::{self, AstNodeEdit, IndentLevel},
6 make, AstNode, NameOwner,
7 },
4 SmolStr, 8 SmolStr,
5}; 9};
6 10
7use crate::{ 11use crate::{
12 assist_context::{AssistContext, Assists},
8 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, 13 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
9 utils::{get_missing_impl_items, resolve_target_trait}, 14 utils::{get_missing_assoc_items, render_snippet, resolve_target_trait, Cursor},
10 Assist, AssistCtx, AssistId, 15 AssistId,
11}; 16};
12 17
13#[derive(PartialEq)] 18#[derive(PartialEq)]
@@ -40,12 +45,15 @@ enum AddMissingImplMembersMode {
40// } 45// }
41// 46//
42// impl Trait<u32> for () { 47// impl Trait<u32> for () {
43// fn foo(&self) -> u32 { todo!() } 48// fn foo(&self) -> u32 {
49// ${0:todo!()}
50// }
44// 51//
45// } 52// }
46// ``` 53// ```
47pub(crate) fn add_missing_impl_members(ctx: AssistCtx) -> Option<Assist> { 54pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
48 add_missing_impl_members_inner( 55 add_missing_impl_members_inner(
56 acc,
49 ctx, 57 ctx,
50 AddMissingImplMembersMode::NoDefaultMethods, 58 AddMissingImplMembersMode::NoDefaultMethods,
51 "add_impl_missing_members", 59 "add_impl_missing_members",
@@ -81,12 +89,13 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx) -> Option<Assist> {
81// impl Trait for () { 89// impl Trait for () {
82// Type X = (); 90// Type X = ();
83// fn foo(&self) {} 91// fn foo(&self) {}
84// fn bar(&self) {} 92// $0fn bar(&self) {}
85// 93//
86// } 94// }
87// ``` 95// ```
88pub(crate) fn add_missing_default_members(ctx: AssistCtx) -> Option<Assist> { 96pub(crate) fn add_missing_default_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
89 add_missing_impl_members_inner( 97 add_missing_impl_members_inner(
98 acc,
90 ctx, 99 ctx,
91 AddMissingImplMembersMode::DefaultMethodsOnly, 100 AddMissingImplMembersMode::DefaultMethodsOnly,
92 "add_impl_default_members", 101 "add_impl_default_members",
@@ -95,36 +104,37 @@ pub(crate) fn add_missing_default_members(ctx: AssistCtx) -> Option<Assist> {
95} 104}
96 105
97fn add_missing_impl_members_inner( 106fn add_missing_impl_members_inner(
98 ctx: AssistCtx, 107 acc: &mut Assists,
108 ctx: &AssistContext,
99 mode: AddMissingImplMembersMode, 109 mode: AddMissingImplMembersMode,
100 assist_id: &'static str, 110 assist_id: &'static str,
101 label: &'static str, 111 label: &'static str,
102) -> Option<Assist> { 112) -> Option<()> {
103 let _p = ra_prof::profile("add_missing_impl_members_inner"); 113 let _p = ra_prof::profile("add_missing_impl_members_inner");
104 let impl_node = ctx.find_node_at_offset::<ast::ImplDef>()?; 114 let impl_def = ctx.find_node_at_offset::<ast::ImplDef>()?;
105 let impl_item_list = impl_node.item_list()?; 115 let impl_item_list = impl_def.item_list()?;
106 116
107 let trait_ = resolve_target_trait(&ctx.sema, &impl_node)?; 117 let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
108 118
109 let def_name = |item: &ast::ImplItem| -> Option<SmolStr> { 119 let def_name = |item: &ast::AssocItem| -> Option<SmolStr> {
110 match item { 120 match item {
111 ast::ImplItem::FnDef(def) => def.name(), 121 ast::AssocItem::FnDef(def) => def.name(),
112 ast::ImplItem::TypeAliasDef(def) => def.name(), 122 ast::AssocItem::TypeAliasDef(def) => def.name(),
113 ast::ImplItem::ConstDef(def) => def.name(), 123 ast::AssocItem::ConstDef(def) => def.name(),
114 } 124 }
115 .map(|it| it.text().clone()) 125 .map(|it| it.text().clone())
116 }; 126 };
117 127
118 let missing_items = get_missing_impl_items(&ctx.sema, &impl_node) 128 let missing_items = get_missing_assoc_items(&ctx.sema, &impl_def)
119 .iter() 129 .iter()
120 .map(|i| match i { 130 .map(|i| match i {
121 hir::AssocItem::Function(i) => ast::ImplItem::FnDef(i.source(ctx.db).value), 131 hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db).value),
122 hir::AssocItem::TypeAlias(i) => ast::ImplItem::TypeAliasDef(i.source(ctx.db).value), 132 hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAliasDef(i.source(ctx.db).value),
123 hir::AssocItem::Const(i) => ast::ImplItem::ConstDef(i.source(ctx.db).value), 133 hir::AssocItem::Const(i) => ast::AssocItem::ConstDef(i.source(ctx.db).value),
124 }) 134 })
125 .filter(|t| def_name(&t).is_some()) 135 .filter(|t| def_name(&t).is_some())
126 .filter(|t| match t { 136 .filter(|t| match t {
127 ast::ImplItem::FnDef(def) => match mode { 137 ast::AssocItem::FnDef(def) => match mode {
128 AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), 138 AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(),
129 AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), 139 AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(),
130 }, 140 },
@@ -136,44 +146,59 @@ fn add_missing_impl_members_inner(
136 return None; 146 return None;
137 } 147 }
138 148
139 let sema = ctx.sema; 149 let target = impl_def.syntax().text_range();
140 150 acc.add(AssistId(assist_id), label, target, |builder| {
141 ctx.add_assist(AssistId(assist_id), label, |edit| { 151 let n_existing_items = impl_item_list.assoc_items().count();
142 let n_existing_items = impl_item_list.impl_items().count(); 152 let source_scope = ctx.sema.scope_for_def(trait_);
143 let source_scope = sema.scope_for_def(trait_); 153 let target_scope = ctx.sema.scope(impl_item_list.syntax());
144 let target_scope = sema.scope(impl_item_list.syntax());
145 let ast_transform = QualifyPaths::new(&target_scope, &source_scope) 154 let ast_transform = QualifyPaths::new(&target_scope, &source_scope)
146 .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_node)); 155 .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_def));
147 let items = missing_items 156 let items = missing_items
148 .into_iter() 157 .into_iter()
149 .map(|it| ast_transform::apply(&*ast_transform, it)) 158 .map(|it| ast_transform::apply(&*ast_transform, it))
150 .map(|it| match it { 159 .map(|it| match it {
151 ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), 160 ast::AssocItem::FnDef(def) => ast::AssocItem::FnDef(add_body(def)),
152 _ => it, 161 _ => it,
153 }) 162 })
154 .map(|it| edit::remove_attrs_and_docs(&it)); 163 .map(|it| edit::remove_attrs_and_docs(&it));
155 let new_impl_item_list = impl_item_list.append_items(items); 164 let new_impl_item_list = impl_item_list.append_items(items);
156 let cursor_position = { 165 let first_new_item = new_impl_item_list.assoc_items().nth(n_existing_items).unwrap();
157 let first_new_item = new_impl_item_list.impl_items().nth(n_existing_items).unwrap(); 166
158 first_new_item.syntax().text_range().start() 167 let original_range = impl_item_list.syntax().text_range();
168 match ctx.config.snippet_cap {
169 None => builder.replace(original_range, new_impl_item_list.to_string()),
170 Some(cap) => {
171 let mut cursor = Cursor::Before(first_new_item.syntax());
172 let placeholder;
173 if let ast::AssocItem::FnDef(func) = &first_new_item {
174 if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) {
175 if m.syntax().text() == "todo!()" {
176 placeholder = m;
177 cursor = Cursor::Replace(placeholder.syntax());
178 }
179 }
180 }
181 builder.replace_snippet(
182 cap,
183 original_range,
184 render_snippet(cap, new_impl_item_list.syntax(), cursor),
185 )
186 }
159 }; 187 };
160
161 edit.replace_ast(impl_item_list, new_impl_item_list);
162 edit.set_cursor(cursor_position);
163 }) 188 })
164} 189}
165 190
166fn add_body(fn_def: ast::FnDef) -> ast::FnDef { 191fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
167 if fn_def.body().is_none() { 192 if fn_def.body().is_some() {
168 fn_def.with_body(make::block_from_expr(make::expr_todo())) 193 return fn_def;
169 } else {
170 fn_def
171 } 194 }
195 let body = make::block_expr(None, Some(make::expr_todo())).indent(IndentLevel(1));
196 fn_def.with_body(body)
172} 197}
173 198
174#[cfg(test)] 199#[cfg(test)]
175mod tests { 200mod tests {
176 use crate::helpers::{check_assist, check_assist_not_applicable}; 201 use crate::tests::{check_assist, check_assist_not_applicable};
177 202
178 use super::*; 203 use super::*;
179 204
@@ -181,7 +206,7 @@ mod tests {
181 fn test_add_missing_impl_members() { 206 fn test_add_missing_impl_members() {
182 check_assist( 207 check_assist(
183 add_missing_impl_members, 208 add_missing_impl_members,
184 " 209 r#"
185trait Foo { 210trait Foo {
186 type Output; 211 type Output;
187 212
@@ -197,8 +222,8 @@ struct S;
197impl Foo for S { 222impl Foo for S {
198 fn bar(&self) {} 223 fn bar(&self) {}
199<|> 224<|>
200}", 225}"#,
201 " 226 r#"
202trait Foo { 227trait Foo {
203 type Output; 228 type Output;
204 229
@@ -213,12 +238,16 @@ struct S;
213 238
214impl Foo for S { 239impl Foo for S {
215 fn bar(&self) {} 240 fn bar(&self) {}
216 <|>type Output; 241 $0type Output;
217 const CONST: usize = 42; 242 const CONST: usize = 42;
218 fn foo(&self) { todo!() } 243 fn foo(&self) {
219 fn baz(&self) { todo!() } 244 todo!()
245 }
246 fn baz(&self) {
247 todo!()
248 }
220 249
221}", 250}"#,
222 ); 251 );
223 } 252 }
224 253
@@ -226,7 +255,7 @@ impl Foo for S {
226 fn test_copied_overriden_members() { 255 fn test_copied_overriden_members() {
227 check_assist( 256 check_assist(
228 add_missing_impl_members, 257 add_missing_impl_members,
229 " 258 r#"
230trait Foo { 259trait Foo {
231 fn foo(&self); 260 fn foo(&self);
232 fn bar(&self) -> bool { true } 261 fn bar(&self) -> bool { true }
@@ -238,8 +267,8 @@ struct S;
238impl Foo for S { 267impl Foo for S {
239 fn bar(&self) {} 268 fn bar(&self) {}
240<|> 269<|>
241}", 270}"#,
242 " 271 r#"
243trait Foo { 272trait Foo {
244 fn foo(&self); 273 fn foo(&self);
245 fn bar(&self) -> bool { true } 274 fn bar(&self) -> bool { true }
@@ -250,9 +279,11 @@ struct S;
250 279
251impl Foo for S { 280impl Foo for S {
252 fn bar(&self) {} 281 fn bar(&self) {}
253 <|>fn foo(&self) { todo!() } 282 fn foo(&self) {
283 ${0:todo!()}
284 }
254 285
255}", 286}"#,
256 ); 287 );
257 } 288 }
258 289
@@ -260,16 +291,18 @@ impl Foo for S {
260 fn test_empty_impl_def() { 291 fn test_empty_impl_def() {
261 check_assist( 292 check_assist(
262 add_missing_impl_members, 293 add_missing_impl_members,
263 " 294 r#"
264trait Foo { fn foo(&self); } 295trait Foo { fn foo(&self); }
265struct S; 296struct S;
266impl Foo for S { <|> }", 297impl Foo for S { <|> }"#,
267 " 298 r#"
268trait Foo { fn foo(&self); } 299trait Foo { fn foo(&self); }
269struct S; 300struct S;
270impl Foo for S { 301impl Foo for S {
271 <|>fn foo(&self) { todo!() } 302 fn foo(&self) {
272}", 303 ${0:todo!()}
304 }
305}"#,
273 ); 306 );
274 } 307 }
275 308
@@ -277,16 +310,18 @@ impl Foo for S {
277 fn fill_in_type_params_1() { 310 fn fill_in_type_params_1() {
278 check_assist( 311 check_assist(
279 add_missing_impl_members, 312 add_missing_impl_members,
280 " 313 r#"
281trait Foo<T> { fn foo(&self, t: T) -> &T; } 314trait Foo<T> { fn foo(&self, t: T) -> &T; }
282struct S; 315struct S;
283impl Foo<u32> for S { <|> }", 316impl Foo<u32> for S { <|> }"#,
284 " 317 r#"
285trait Foo<T> { fn foo(&self, t: T) -> &T; } 318trait Foo<T> { fn foo(&self, t: T) -> &T; }
286struct S; 319struct S;
287impl Foo<u32> for S { 320impl Foo<u32> for S {
288 <|>fn foo(&self, t: u32) -> &u32 { todo!() } 321 fn foo(&self, t: u32) -> &u32 {
289}", 322 ${0:todo!()}
323 }
324}"#,
290 ); 325 );
291 } 326 }
292 327
@@ -294,16 +329,18 @@ impl Foo<u32> for S {
294 fn fill_in_type_params_2() { 329 fn fill_in_type_params_2() {
295 check_assist( 330 check_assist(
296 add_missing_impl_members, 331 add_missing_impl_members,
297 " 332 r#"
298trait Foo<T> { fn foo(&self, t: T) -> &T; } 333trait Foo<T> { fn foo(&self, t: T) -> &T; }
299struct S; 334struct S;
300impl<U> Foo<U> for S { <|> }", 335impl<U> Foo<U> for S { <|> }"#,
301 " 336 r#"
302trait Foo<T> { fn foo(&self, t: T) -> &T; } 337trait Foo<T> { fn foo(&self, t: T) -> &T; }
303struct S; 338struct S;
304impl<U> Foo<U> for S { 339impl<U> Foo<U> for S {
305 <|>fn foo(&self, t: U) -> &U { todo!() } 340 fn foo(&self, t: U) -> &U {
306}", 341 ${0:todo!()}
342 }
343}"#,
307 ); 344 );
308 } 345 }
309 346
@@ -311,16 +348,18 @@ impl<U> Foo<U> for S {
311 fn test_cursor_after_empty_impl_def() { 348 fn test_cursor_after_empty_impl_def() {
312 check_assist( 349 check_assist(
313 add_missing_impl_members, 350 add_missing_impl_members,
314 " 351 r#"
315trait Foo { fn foo(&self); } 352trait Foo { fn foo(&self); }
316struct S; 353struct S;
317impl Foo for S {}<|>", 354impl Foo for S {}<|>"#,
318 " 355 r#"
319trait Foo { fn foo(&self); } 356trait Foo { fn foo(&self); }
320struct S; 357struct S;
321impl Foo for S { 358impl Foo for S {
322 <|>fn foo(&self) { todo!() } 359 fn foo(&self) {
323}", 360 ${0:todo!()}
361 }
362}"#,
324 ) 363 )
325 } 364 }
326 365
@@ -328,22 +367,24 @@ impl Foo for S {
328 fn test_qualify_path_1() { 367 fn test_qualify_path_1() {
329 check_assist( 368 check_assist(
330 add_missing_impl_members, 369 add_missing_impl_members,
331 " 370 r#"
332mod foo { 371mod foo {
333 pub struct Bar; 372 pub struct Bar;
334 trait Foo { fn foo(&self, bar: Bar); } 373 trait Foo { fn foo(&self, bar: Bar); }
335} 374}
336struct S; 375struct S;
337impl foo::Foo for S { <|> }", 376impl foo::Foo for S { <|> }"#,
338 " 377 r#"
339mod foo { 378mod foo {
340 pub struct Bar; 379 pub struct Bar;
341 trait Foo { fn foo(&self, bar: Bar); } 380 trait Foo { fn foo(&self, bar: Bar); }
342} 381}
343struct S; 382struct S;
344impl foo::Foo for S { 383impl foo::Foo for S {
345 <|>fn foo(&self, bar: foo::Bar) { todo!() } 384 fn foo(&self, bar: foo::Bar) {
346}", 385 ${0:todo!()}
386 }
387}"#,
347 ); 388 );
348 } 389 }
349 390
@@ -351,22 +392,24 @@ impl foo::Foo for S {
351 fn test_qualify_path_generic() { 392 fn test_qualify_path_generic() {
352 check_assist( 393 check_assist(
353 add_missing_impl_members, 394 add_missing_impl_members,
354 " 395 r#"
355mod foo { 396mod foo {
356 pub struct Bar<T>; 397 pub struct Bar<T>;
357 trait Foo { fn foo(&self, bar: Bar<u32>); } 398 trait Foo { fn foo(&self, bar: Bar<u32>); }
358} 399}
359struct S; 400struct S;
360impl foo::Foo for S { <|> }", 401impl foo::Foo for S { <|> }"#,
361 " 402 r#"
362mod foo { 403mod foo {
363 pub struct Bar<T>; 404 pub struct Bar<T>;
364 trait Foo { fn foo(&self, bar: Bar<u32>); } 405 trait Foo { fn foo(&self, bar: Bar<u32>); }
365} 406}
366struct S; 407struct S;
367impl foo::Foo for S { 408impl foo::Foo for S {
368 <|>fn foo(&self, bar: foo::Bar<u32>) { todo!() } 409 fn foo(&self, bar: foo::Bar<u32>) {
369}", 410 ${0:todo!()}
411 }
412}"#,
370 ); 413 );
371 } 414 }
372 415
@@ -374,22 +417,24 @@ impl foo::Foo for S {
374 fn test_qualify_path_and_substitute_param() { 417 fn test_qualify_path_and_substitute_param() {
375 check_assist( 418 check_assist(
376 add_missing_impl_members, 419 add_missing_impl_members,
377 " 420 r#"
378mod foo { 421mod foo {
379 pub struct Bar<T>; 422 pub struct Bar<T>;
380 trait Foo<T> { fn foo(&self, bar: Bar<T>); } 423 trait Foo<T> { fn foo(&self, bar: Bar<T>); }
381} 424}
382struct S; 425struct S;
383impl foo::Foo<u32> for S { <|> }", 426impl foo::Foo<u32> for S { <|> }"#,
384 " 427 r#"
385mod foo { 428mod foo {
386 pub struct Bar<T>; 429 pub struct Bar<T>;
387 trait Foo<T> { fn foo(&self, bar: Bar<T>); } 430 trait Foo<T> { fn foo(&self, bar: Bar<T>); }
388} 431}
389struct S; 432struct S;
390impl foo::Foo<u32> for S { 433impl foo::Foo<u32> for S {
391 <|>fn foo(&self, bar: foo::Bar<u32>) { todo!() } 434 fn foo(&self, bar: foo::Bar<u32>) {
392}", 435 ${0:todo!()}
436 }
437}"#,
393 ); 438 );
394 } 439 }
395 440
@@ -398,15 +443,15 @@ impl foo::Foo<u32> for S {
398 // when substituting params, the substituted param should not be qualified! 443 // when substituting params, the substituted param should not be qualified!
399 check_assist( 444 check_assist(
400 add_missing_impl_members, 445 add_missing_impl_members,
401 " 446 r#"
402mod foo { 447mod foo {
403 trait Foo<T> { fn foo(&self, bar: T); } 448 trait Foo<T> { fn foo(&self, bar: T); }
404 pub struct Param; 449 pub struct Param;
405} 450}
406struct Param; 451struct Param;
407struct S; 452struct S;
408impl foo::Foo<Param> for S { <|> }", 453impl foo::Foo<Param> for S { <|> }"#,
409 " 454 r#"
410mod foo { 455mod foo {
411 trait Foo<T> { fn foo(&self, bar: T); } 456 trait Foo<T> { fn foo(&self, bar: T); }
412 pub struct Param; 457 pub struct Param;
@@ -414,8 +459,10 @@ mod foo {
414struct Param; 459struct Param;
415struct S; 460struct S;
416impl foo::Foo<Param> for S { 461impl foo::Foo<Param> for S {
417 <|>fn foo(&self, bar: Param) { todo!() } 462 fn foo(&self, bar: Param) {
418}", 463 ${0:todo!()}
464 }
465}"#,
419 ); 466 );
420 } 467 }
421 468
@@ -423,15 +470,15 @@ impl foo::Foo<Param> for S {
423 fn test_qualify_path_associated_item() { 470 fn test_qualify_path_associated_item() {
424 check_assist( 471 check_assist(
425 add_missing_impl_members, 472 add_missing_impl_members,
426 " 473 r#"
427mod foo { 474mod foo {
428 pub struct Bar<T>; 475 pub struct Bar<T>;
429 impl Bar<T> { type Assoc = u32; } 476 impl Bar<T> { type Assoc = u32; }
430 trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); } 477 trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
431} 478}
432struct S; 479struct S;
433impl foo::Foo for S { <|> }", 480impl foo::Foo for S { <|> }"#,
434 " 481 r#"
435mod foo { 482mod foo {
436 pub struct Bar<T>; 483 pub struct Bar<T>;
437 impl Bar<T> { type Assoc = u32; } 484 impl Bar<T> { type Assoc = u32; }
@@ -439,8 +486,10 @@ mod foo {
439} 486}
440struct S; 487struct S;
441impl foo::Foo for S { 488impl foo::Foo for S {
442 <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { todo!() } 489 fn foo(&self, bar: foo::Bar<u32>::Assoc) {
443}", 490 ${0:todo!()}
491 }
492}"#,
444 ); 493 );
445 } 494 }
446 495
@@ -448,15 +497,15 @@ impl foo::Foo for S {
448 fn test_qualify_path_nested() { 497 fn test_qualify_path_nested() {
449 check_assist( 498 check_assist(
450 add_missing_impl_members, 499 add_missing_impl_members,
451 " 500 r#"
452mod foo { 501mod foo {
453 pub struct Bar<T>; 502 pub struct Bar<T>;
454 pub struct Baz; 503 pub struct Baz;
455 trait Foo { fn foo(&self, bar: Bar<Baz>); } 504 trait Foo { fn foo(&self, bar: Bar<Baz>); }
456} 505}
457struct S; 506struct S;
458impl foo::Foo for S { <|> }", 507impl foo::Foo for S { <|> }"#,
459 " 508 r#"
460mod foo { 509mod foo {
461 pub struct Bar<T>; 510 pub struct Bar<T>;
462 pub struct Baz; 511 pub struct Baz;
@@ -464,8 +513,10 @@ mod foo {
464} 513}
465struct S; 514struct S;
466impl foo::Foo for S { 515impl foo::Foo for S {
467 <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { todo!() } 516 fn foo(&self, bar: foo::Bar<foo::Baz>) {
468}", 517 ${0:todo!()}
518 }
519}"#,
469 ); 520 );
470 } 521 }
471 522
@@ -473,22 +524,24 @@ impl foo::Foo for S {
473 fn test_qualify_path_fn_trait_notation() { 524 fn test_qualify_path_fn_trait_notation() {
474 check_assist( 525 check_assist(
475 add_missing_impl_members, 526 add_missing_impl_members,
476 " 527 r#"
477mod foo { 528mod foo {
478 pub trait Fn<Args> { type Output; } 529 pub trait Fn<Args> { type Output; }
479 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); } 530 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
480} 531}
481struct S; 532struct S;
482impl foo::Foo for S { <|> }", 533impl foo::Foo for S { <|> }"#,
483 " 534 r#"
484mod foo { 535mod foo {
485 pub trait Fn<Args> { type Output; } 536 pub trait Fn<Args> { type Output; }
486 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); } 537 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
487} 538}
488struct S; 539struct S;
489impl foo::Foo for S { 540impl foo::Foo for S {
490 <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { todo!() } 541 fn foo(&self, bar: dyn Fn(u32) -> i32) {
491}", 542 ${0:todo!()}
543 }
544}"#,
492 ); 545 );
493 } 546 }
494 547
@@ -496,10 +549,10 @@ impl foo::Foo for S {
496 fn test_empty_trait() { 549 fn test_empty_trait() {
497 check_assist_not_applicable( 550 check_assist_not_applicable(
498 add_missing_impl_members, 551 add_missing_impl_members,
499 " 552 r#"
500trait Foo; 553trait Foo;
501struct S; 554struct S;
502impl Foo for S { <|> }", 555impl Foo for S { <|> }"#,
503 ) 556 )
504 } 557 }
505 558
@@ -507,13 +560,13 @@ impl Foo for S { <|> }",
507 fn test_ignore_unnamed_trait_members_and_default_methods() { 560 fn test_ignore_unnamed_trait_members_and_default_methods() {
508 check_assist_not_applicable( 561 check_assist_not_applicable(
509 add_missing_impl_members, 562 add_missing_impl_members,
510 " 563 r#"
511trait Foo { 564trait Foo {
512 fn (arg: u32); 565 fn (arg: u32);
513 fn valid(some: u32) -> bool { false } 566 fn valid(some: u32) -> bool { false }
514} 567}
515struct S; 568struct S;
516impl Foo for S { <|> }", 569impl Foo for S { <|> }"#,
517 ) 570 )
518 } 571 }
519 572
@@ -543,8 +596,10 @@ trait Foo {
543} 596}
544struct S; 597struct S;
545impl Foo for S { 598impl Foo for S {
546 <|>type Output; 599 $0type Output;
547 fn foo(&self) { todo!() } 600 fn foo(&self) {
601 todo!()
602 }
548}"#, 603}"#,
549 ) 604 )
550 } 605 }
@@ -553,7 +608,7 @@ impl Foo for S {
553 fn test_default_methods() { 608 fn test_default_methods() {
554 check_assist( 609 check_assist(
555 add_missing_default_members, 610 add_missing_default_members,
556 " 611 r#"
557trait Foo { 612trait Foo {
558 type Output; 613 type Output;
559 614
@@ -563,8 +618,8 @@ trait Foo {
563 fn foo(some: u32) -> bool; 618 fn foo(some: u32) -> bool;
564} 619}
565struct S; 620struct S;
566impl Foo for S { <|> }", 621impl Foo for S { <|> }"#,
567 " 622 r#"
568trait Foo { 623trait Foo {
569 type Output; 624 type Output;
570 625
@@ -575,8 +630,58 @@ trait Foo {
575} 630}
576struct S; 631struct S;
577impl Foo for S { 632impl Foo for S {
578 <|>fn valid(some: u32) -> bool { false } 633 $0fn valid(some: u32) -> bool { false }
579}", 634}"#,
635 )
636 }
637
638 #[test]
639 fn test_generic_single_default_parameter() {
640 check_assist(
641 add_missing_impl_members,
642 r#"
643trait Foo<T = Self> {
644 fn bar(&self, other: &T);
645}
646
647struct S;
648impl Foo for S { <|> }"#,
649 r#"
650trait Foo<T = Self> {
651 fn bar(&self, other: &T);
652}
653
654struct S;
655impl Foo for S {
656 fn bar(&self, other: &Self) {
657 ${0:todo!()}
658 }
659}"#,
660 )
661 }
662
663 #[test]
664 fn test_generic_default_parameter_is_second() {
665 check_assist(
666 add_missing_impl_members,
667 r#"
668trait Foo<T1, T2 = Self> {
669 fn bar(&self, this: &T1, that: &T2);
670}
671
672struct S<T>;
673impl Foo<T> for S<T> { <|> }"#,
674 r#"
675trait Foo<T1, T2 = Self> {
676 fn bar(&self, this: &T1, that: &T2);
677}
678
679struct S<T>;
680impl Foo<T> for S<T> {
681 fn bar(&self, this: &T, that: &Self) {
682 ${0:todo!()}
683 }
684}"#,
580 ) 685 )
581 } 686 }
582} 687}
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs
index 0f9174a29..837aa8377 100644
--- a/crates/ra_assists/src/handlers/add_new.rs
+++ b/crates/ra_assists/src/handlers/add_new.rs
@@ -3,11 +3,11 @@ use ra_syntax::{
3 ast::{ 3 ast::{
4 self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, 4 self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner,
5 }, 5 },
6 TextSize, T, 6 T,
7}; 7};
8use stdx::{format_to, SepBy}; 8use stdx::{format_to, SepBy};
9 9
10use crate::{Assist, AssistCtx, AssistId}; 10use crate::{AssistContext, AssistId, Assists};
11 11
12// Assist: add_new 12// Assist: add_new
13// 13//
@@ -25,11 +25,11 @@ use crate::{Assist, AssistCtx, AssistId};
25// } 25// }
26// 26//
27// impl<T: Clone> Ctx<T> { 27// impl<T: Clone> Ctx<T> {
28// fn new(data: T) -> Self { Self { data } } 28// fn $0new(data: T) -> Self { Self { data } }
29// } 29// }
30// 30//
31// ``` 31// ```
32pub(crate) fn add_new(ctx: AssistCtx) -> Option<Assist> { 32pub(crate) fn add_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
33 let strukt = ctx.find_node_at_offset::<ast::StructDef>()?; 33 let strukt = ctx.find_node_at_offset::<ast::StructDef>()?;
34 34
35 // We want to only apply this to non-union structs with named fields 35 // We want to only apply this to non-union structs with named fields
@@ -41,33 +41,27 @@ pub(crate) fn add_new(ctx: AssistCtx) -> Option<Assist> {
41 // Return early if we've found an existing new fn 41 // Return early if we've found an existing new fn
42 let impl_def = find_struct_impl(&ctx, &strukt)?; 42 let impl_def = find_struct_impl(&ctx, &strukt)?;
43 43
44 ctx.add_assist(AssistId("add_new"), "Add default constructor", |edit| { 44 let target = strukt.syntax().text_range();
45 edit.target(strukt.syntax().text_range()); 45 acc.add(AssistId("add_new"), "Add default constructor", target, |builder| {
46
47 let mut buf = String::with_capacity(512); 46 let mut buf = String::with_capacity(512);
48 47
49 if impl_def.is_some() { 48 if impl_def.is_some() {
50 buf.push('\n'); 49 buf.push('\n');
51 } 50 }
52 51
53 let vis = strukt.visibility().map(|v| format!("{} ", v)); 52 let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
54 let vis = vis.as_deref().unwrap_or("");
55 53
56 let params = field_list 54 let params = field_list
57 .fields() 55 .fields()
58 .filter_map(|f| { 56 .filter_map(|f| {
59 Some(format!( 57 Some(format!("{}: {}", f.name()?.syntax(), f.ascribed_type()?.syntax()))
60 "{}: {}",
61 f.name()?.syntax().text(),
62 f.ascribed_type()?.syntax().text()
63 ))
64 }) 58 })
65 .sep_by(", "); 59 .sep_by(", ");
66 let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", "); 60 let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", ");
67 61
68 format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields); 62 format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);
69 63
70 let (start_offset, end_offset) = impl_def 64 let start_offset = impl_def
71 .and_then(|impl_def| { 65 .and_then(|impl_def| {
72 buf.push('\n'); 66 buf.push('\n');
73 let start = impl_def 67 let start = impl_def
@@ -77,17 +71,20 @@ pub(crate) fn add_new(ctx: AssistCtx) -> Option<Assist> {
77 .text_range() 71 .text_range()
78 .end(); 72 .end();
79 73
80 Some((start, TextSize::of("\n"))) 74 Some(start)
81 }) 75 })
82 .unwrap_or_else(|| { 76 .unwrap_or_else(|| {
83 buf = generate_impl_text(&strukt, &buf); 77 buf = generate_impl_text(&strukt, &buf);
84 let start = strukt.syntax().text_range().end(); 78 strukt.syntax().text_range().end()
85
86 (start, TextSize::of("\n}\n"))
87 }); 79 });
88 80
89 edit.set_cursor(start_offset + TextSize::of(&buf) - end_offset); 81 match ctx.config.snippet_cap {
90 edit.insert(start_offset, buf); 82 None => builder.insert(start_offset, buf),
83 Some(cap) => {
84 buf = buf.replace("fn new", "fn $0new");
85 builder.insert_snippet(cap, start_offset, buf);
86 }
87 }
91 }) 88 })
92} 89}
93 90
@@ -124,7 +121,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
124// 121//
125// FIXME: change the new fn checking to a more semantic approach when that's more 122// FIXME: change the new fn checking to a more semantic approach when that's more
126// viable (e.g. we process proc macros, etc) 123// viable (e.g. we process proc macros, etc)
127fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option<Option<ast::ImplDef>> { 124fn find_struct_impl(ctx: &AssistContext, strukt: &ast::StructDef) -> Option<Option<ast::ImplDef>> {
128 let db = ctx.db; 125 let db = ctx.db;
129 let module = strukt.syntax().ancestors().find(|node| { 126 let module = strukt.syntax().ancestors().find(|node| {
130 ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind()) 127 ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
@@ -162,8 +159,8 @@ fn find_struct_impl(ctx: &AssistCtx, strukt: &ast::StructDef) -> Option<Option<a
162 159
163fn has_new_fn(imp: &ast::ImplDef) -> bool { 160fn has_new_fn(imp: &ast::ImplDef) -> bool {
164 if let Some(il) = imp.item_list() { 161 if let Some(il) = imp.item_list() {
165 for item in il.impl_items() { 162 for item in il.assoc_items() {
166 if let ast::ImplItem::FnDef(f) = item { 163 if let ast::AssocItem::FnDef(f) = item {
167 if let Some(name) = f.name() { 164 if let Some(name) = f.name() {
168 if name.text().eq_ignore_ascii_case("new") { 165 if name.text().eq_ignore_ascii_case("new") {
169 return true; 166 return true;
@@ -178,7 +175,7 @@ fn has_new_fn(imp: &ast::ImplDef) -> bool {
178 175
179#[cfg(test)] 176#[cfg(test)]
180mod tests { 177mod tests {
181 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 178 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
182 179
183 use super::*; 180 use super::*;
184 181
@@ -192,7 +189,7 @@ mod tests {
192"struct Foo {} 189"struct Foo {}
193 190
194impl Foo { 191impl Foo {
195 fn new() -> Self { Self { } }<|> 192 fn $0new() -> Self { Self { } }
196} 193}
197", 194",
198 ); 195 );
@@ -202,7 +199,7 @@ impl Foo {
202"struct Foo<T: Clone> {} 199"struct Foo<T: Clone> {}
203 200
204impl<T: Clone> Foo<T> { 201impl<T: Clone> Foo<T> {
205 fn new() -> Self { Self { } }<|> 202 fn $0new() -> Self { Self { } }
206} 203}
207", 204",
208 ); 205 );
@@ -212,7 +209,7 @@ impl<T: Clone> Foo<T> {
212"struct Foo<'a, T: Foo<'a>> {} 209"struct Foo<'a, T: Foo<'a>> {}
213 210
214impl<'a, T: Foo<'a>> Foo<'a, T> { 211impl<'a, T: Foo<'a>> Foo<'a, T> {
215 fn new() -> Self { Self { } }<|> 212 fn $0new() -> Self { Self { } }
216} 213}
217", 214",
218 ); 215 );
@@ -222,7 +219,7 @@ impl<'a, T: Foo<'a>> Foo<'a, T> {
222"struct Foo { baz: String } 219"struct Foo { baz: String }
223 220
224impl Foo { 221impl Foo {
225 fn new(baz: String) -> Self { Self { baz } }<|> 222 fn $0new(baz: String) -> Self { Self { baz } }
226} 223}
227", 224",
228 ); 225 );
@@ -232,7 +229,7 @@ impl Foo {
232"struct Foo { baz: String, qux: Vec<i32> } 229"struct Foo { baz: String, qux: Vec<i32> }
233 230
234impl Foo { 231impl Foo {
235 fn new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }<|> 232 fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }
236} 233}
237", 234",
238 ); 235 );
@@ -244,7 +241,7 @@ impl Foo {
244"struct Foo { pub baz: String, pub qux: Vec<i32> } 241"struct Foo { pub baz: String, pub qux: Vec<i32> }
245 242
246impl Foo { 243impl Foo {
247 fn new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }<|> 244 fn $0new(baz: String, qux: Vec<i32>) -> Self { Self { baz, qux } }
248} 245}
249", 246",
250 ); 247 );
@@ -259,7 +256,7 @@ impl Foo {}
259"struct Foo {} 256"struct Foo {}
260 257
261impl Foo { 258impl Foo {
262 fn new() -> Self { Self { } }<|> 259 fn $0new() -> Self { Self { } }
263} 260}
264", 261",
265 ); 262 );
@@ -274,7 +271,7 @@ impl Foo {
274"struct Foo {} 271"struct Foo {}
275 272
276impl Foo { 273impl Foo {
277 fn new() -> Self { Self { } }<|> 274 fn $0new() -> Self { Self { } }
278 275
279 fn qux(&self) {} 276 fn qux(&self) {}
280} 277}
@@ -295,7 +292,7 @@ impl Foo {
295"struct Foo {} 292"struct Foo {}
296 293
297impl Foo { 294impl Foo {
298 fn new() -> Self { Self { } }<|> 295 fn $0new() -> Self { Self { } }
299 296
300 fn qux(&self) {} 297 fn qux(&self) {}
301 fn baz() -> i32 { 298 fn baz() -> i32 {
@@ -312,7 +309,7 @@ impl Foo {
312"pub struct Foo {} 309"pub struct Foo {}
313 310
314impl Foo { 311impl Foo {
315 pub fn new() -> Self { Self { } }<|> 312 pub fn $0new() -> Self { Self { } }
316} 313}
317", 314",
318 ); 315 );
@@ -322,7 +319,7 @@ impl Foo {
322"pub(crate) struct Foo {} 319"pub(crate) struct Foo {}
323 320
324impl Foo { 321impl Foo {
325 pub(crate) fn new() -> Self { Self { } }<|> 322 pub(crate) fn $0new() -> Self { Self { } }
326} 323}
327", 324",
328 ); 325 );
@@ -415,7 +412,7 @@ pub struct Source<T> {
415} 412}
416 413
417impl<T> Source<T> { 414impl<T> Source<T> {
418 pub fn new(file_id: HirFileId, ast: T) -> Self { Self { file_id, ast } }<|> 415 pub fn $0new(file_id: HirFileId, ast: T) -> Self { Self { file_id, ast } }
419 416
420 pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { 417 pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
421 Source { file_id: self.file_id, ast: f(self.ast) } 418 Source { file_id: self.file_id, ast: f(self.ast) }
diff --git a/crates/ra_assists/src/handlers/add_turbo_fish.rs b/crates/ra_assists/src/handlers/add_turbo_fish.rs
new file mode 100644
index 000000000..26acf81f2
--- /dev/null
+++ b/crates/ra_assists/src/handlers/add_turbo_fish.rs
@@ -0,0 +1,134 @@
1use ra_ide_db::defs::{classify_name_ref, Definition, NameRefClass};
2use ra_syntax::{ast, AstNode, SyntaxKind, T};
3use test_utils::mark;
4
5use crate::{
6 assist_context::{AssistContext, Assists},
7 AssistId,
8};
9
10// Assist: add_turbo_fish
11//
12// Adds `::<_>` to a call of a generic method or function.
13//
14// ```
15// fn make<T>() -> T { todo!() }
16// fn main() {
17// let x = make<|>();
18// }
19// ```
20// ->
21// ```
22// fn make<T>() -> T { todo!() }
23// fn main() {
24// let x = make::<${0:_}>();
25// }
26// ```
27pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
28 let ident = ctx.find_token_at_offset(SyntaxKind::IDENT)?;
29 let next_token = ident.next_token()?;
30 if next_token.kind() == T![::] {
31 mark::hit!(add_turbo_fish_one_fish_is_enough);
32 return None;
33 }
34 let name_ref = ast::NameRef::cast(ident.parent())?;
35 let def = match classify_name_ref(&ctx.sema, &name_ref)? {
36 NameRefClass::Definition(def) => def,
37 NameRefClass::FieldShorthand { .. } => return None,
38 };
39 let fun = match def {
40 Definition::ModuleDef(hir::ModuleDef::Function(it)) => it,
41 _ => return None,
42 };
43 let generics = hir::GenericDef::Function(fun).params(ctx.sema.db);
44 if generics.is_empty() {
45 mark::hit!(add_turbo_fish_non_generic);
46 return None;
47 }
48 acc.add(AssistId("add_turbo_fish"), "Add `::<>`", ident.text_range(), |builder| {
49 match ctx.config.snippet_cap {
50 Some(cap) => builder.insert_snippet(cap, ident.text_range().end(), "::<${0:_}>"),
51 None => builder.insert(ident.text_range().end(), "::<_>"),
52 }
53 })
54}
55
56#[cfg(test)]
57mod tests {
58 use crate::tests::{check_assist, check_assist_not_applicable};
59
60 use super::*;
61 use test_utils::mark;
62
63 #[test]
64 fn add_turbo_fish_function() {
65 check_assist(
66 add_turbo_fish,
67 r#"
68fn make<T>() -> T {}
69fn main() {
70 make<|>();
71}
72"#,
73 r#"
74fn make<T>() -> T {}
75fn main() {
76 make::<${0:_}>();
77}
78"#,
79 );
80 }
81
82 #[test]
83 fn add_turbo_fish_method() {
84 check_assist(
85 add_turbo_fish,
86 r#"
87struct S;
88impl S {
89 fn make<T>(&self) -> T {}
90}
91fn main() {
92 S.make<|>();
93}
94"#,
95 r#"
96struct S;
97impl S {
98 fn make<T>(&self) -> T {}
99}
100fn main() {
101 S.make::<${0:_}>();
102}
103"#,
104 );
105 }
106
107 #[test]
108 fn add_turbo_fish_one_fish_is_enough() {
109 mark::check!(add_turbo_fish_one_fish_is_enough);
110 check_assist_not_applicable(
111 add_turbo_fish,
112 r#"
113fn make<T>() -> T {}
114fn main() {
115 make<|>::<()>();
116}
117"#,
118 );
119 }
120
121 #[test]
122 fn add_turbo_fish_non_generic() {
123 mark::check!(add_turbo_fish_non_generic);
124 check_assist_not_applicable(
125 add_turbo_fish,
126 r#"
127fn make() -> () {}
128fn main() {
129 make<|>();
130}
131"#,
132 );
133 }
134}
diff --git a/crates/ra_assists/src/handlers/apply_demorgan.rs b/crates/ra_assists/src/handlers/apply_demorgan.rs
index 260b9e073..233e8fb8e 100644
--- a/crates/ra_assists/src/handlers/apply_demorgan.rs
+++ b/crates/ra_assists/src/handlers/apply_demorgan.rs
@@ -1,6 +1,6 @@
1use ra_syntax::ast::{self, AstNode}; 1use ra_syntax::ast::{self, AstNode};
2 2
3use crate::{utils::invert_boolean_expression, Assist, AssistCtx, AssistId}; 3use crate::{utils::invert_boolean_expression, AssistContext, AssistId, Assists};
4 4
5// Assist: apply_demorgan 5// Assist: apply_demorgan
6// 6//
@@ -21,7 +21,7 @@ use crate::{utils::invert_boolean_expression, Assist, AssistCtx, AssistId};
21// if !(x == 4 && y) {} 21// if !(x == 4 && y) {}
22// } 22// }
23// ``` 23// ```
24pub(crate) fn apply_demorgan(ctx: AssistCtx) -> Option<Assist> { 24pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
25 let expr = ctx.find_node_at_offset::<ast::BinExpr>()?; 25 let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
26 let op = expr.op_kind()?; 26 let op = expr.op_kind()?;
27 let op_range = expr.op_token()?.text_range(); 27 let op_range = expr.op_token()?.text_range();
@@ -39,8 +39,7 @@ pub(crate) fn apply_demorgan(ctx: AssistCtx) -> Option<Assist> {
39 let rhs_range = rhs.syntax().text_range(); 39 let rhs_range = rhs.syntax().text_range();
40 let not_rhs = invert_boolean_expression(rhs); 40 let not_rhs = invert_boolean_expression(rhs);
41 41
42 ctx.add_assist(AssistId("apply_demorgan"), "Apply De Morgan's law", |edit| { 42 acc.add(AssistId("apply_demorgan"), "Apply De Morgan's law", op_range, |edit| {
43 edit.target(op_range);
44 edit.replace(op_range, opposite_op); 43 edit.replace(op_range, opposite_op);
45 edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text())); 44 edit.replace(lhs_range, format!("!({}", not_lhs.syntax().text()));
46 edit.replace(rhs_range, format!("{})", not_rhs.syntax().text())); 45 edit.replace(rhs_range, format!("{})", not_rhs.syntax().text()));
@@ -60,26 +59,26 @@ fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> {
60mod tests { 59mod tests {
61 use super::*; 60 use super::*;
62 61
63 use crate::helpers::{check_assist, check_assist_not_applicable}; 62 use crate::tests::{check_assist, check_assist_not_applicable};
64 63
65 #[test] 64 #[test]
66 fn demorgan_turns_and_into_or() { 65 fn demorgan_turns_and_into_or() {
67 check_assist(apply_demorgan, "fn f() { !x &&<|> !x }", "fn f() { !(x ||<|> x) }") 66 check_assist(apply_demorgan, "fn f() { !x &&<|> !x }", "fn f() { !(x || x) }")
68 } 67 }
69 68
70 #[test] 69 #[test]
71 fn demorgan_turns_or_into_and() { 70 fn demorgan_turns_or_into_and() {
72 check_assist(apply_demorgan, "fn f() { !x ||<|> !x }", "fn f() { !(x &&<|> x) }") 71 check_assist(apply_demorgan, "fn f() { !x ||<|> !x }", "fn f() { !(x && x) }")
73 } 72 }
74 73
75 #[test] 74 #[test]
76 fn demorgan_removes_inequality() { 75 fn demorgan_removes_inequality() {
77 check_assist(apply_demorgan, "fn f() { x != x ||<|> !x }", "fn f() { !(x == x &&<|> x) }") 76 check_assist(apply_demorgan, "fn f() { x != x ||<|> !x }", "fn f() { !(x == x && x) }")
78 } 77 }
79 78
80 #[test] 79 #[test]
81 fn demorgan_general_case() { 80 fn demorgan_general_case() {
82 check_assist(apply_demorgan, "fn f() { x ||<|> x }", "fn f() { !(!x &&<|> !x) }") 81 check_assist(apply_demorgan, "fn f() { x ||<|> x }", "fn f() { !(!x && !x) }")
83 } 82 }
84 83
85 #[test] 84 #[test]
diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs
index 99682e023..edf96d50e 100644
--- a/crates/ra_assists/src/handlers/auto_import.rs
+++ b/crates/ra_assists/src/handlers/auto_import.rs
@@ -1,5 +1,6 @@
1use std::collections::BTreeSet; 1use std::collections::BTreeSet;
2 2
3use either::Either;
3use hir::{ 4use hir::{
4 AsAssocItem, AssocItemContainer, ModPath, Module, ModuleDef, PathResolution, Semantics, Trait, 5 AsAssocItem, AssocItemContainer, ModPath, Module, ModuleDef, PathResolution, Semantics, Trait,
5 Type, 6 Type,
@@ -12,12 +13,7 @@ use ra_syntax::{
12}; 13};
13use rustc_hash::FxHashSet; 14use rustc_hash::FxHashSet;
14 15
15use crate::{ 16use crate::{utils::insert_use_statement, AssistContext, AssistId, Assists, GroupLabel};
16 assist_ctx::{Assist, AssistCtx},
17 utils::insert_use_statement,
18 AssistId,
19};
20use either::Either;
21 17
22// Assist: auto_import 18// Assist: auto_import
23// 19//
@@ -38,25 +34,32 @@ use either::Either;
38// } 34// }
39// # pub mod std { pub mod collections { pub struct HashMap { } } } 35// # pub mod std { pub mod collections { pub struct HashMap { } } }
40// ``` 36// ```
41pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> { 37pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
42 let auto_import_assets = AutoImportAssets::new(&ctx)?; 38 let auto_import_assets = AutoImportAssets::new(&ctx)?;
43 let proposed_imports = auto_import_assets.search_for_imports(ctx.db); 39 let proposed_imports = auto_import_assets.search_for_imports(ctx.db);
44 if proposed_imports.is_empty() { 40 if proposed_imports.is_empty() {
45 return None; 41 return None;
46 } 42 }
47 43
48 let mut group = ctx.add_assist_group(auto_import_assets.get_import_group_message()); 44 let range = ctx.sema.original_range(&auto_import_assets.syntax_under_caret).range;
45 let group = auto_import_assets.get_import_group_message();
49 for import in proposed_imports { 46 for import in proposed_imports {
50 group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| { 47 acc.add_group(
51 edit.target(auto_import_assets.syntax_under_caret.text_range()); 48 &group,
52 insert_use_statement( 49 AssistId("auto_import"),
53 &auto_import_assets.syntax_under_caret, 50 format!("Import `{}`", &import),
54 &import, 51 range,
55 edit.text_edit_builder(), 52 |builder| {
56 ); 53 insert_use_statement(
57 }); 54 &auto_import_assets.syntax_under_caret,
58 } 55 &import,
59 group.finish() 56 ctx,
57 builder.text_edit_builder(),
58 );
59 },
60 );
61 }
62 Some(())
60} 63}
61 64
62#[derive(Debug)] 65#[derive(Debug)]
@@ -67,15 +70,15 @@ struct AutoImportAssets {
67} 70}
68 71
69impl AutoImportAssets { 72impl AutoImportAssets {
70 fn new(ctx: &AssistCtx) -> Option<Self> { 73 fn new(ctx: &AssistContext) -> Option<Self> {
71 if let Some(path_under_caret) = ctx.find_node_at_offset::<ast::Path>() { 74 if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
72 Self::for_regular_path(path_under_caret, &ctx) 75 Self::for_regular_path(path_under_caret, &ctx)
73 } else { 76 } else {
74 Self::for_method_call(ctx.find_node_at_offset()?, &ctx) 77 Self::for_method_call(ctx.find_node_at_offset_with_descend()?, &ctx)
75 } 78 }
76 } 79 }
77 80
78 fn for_method_call(method_call: ast::MethodCallExpr, ctx: &AssistCtx) -> Option<Self> { 81 fn for_method_call(method_call: ast::MethodCallExpr, ctx: &AssistContext) -> Option<Self> {
79 let syntax_under_caret = method_call.syntax().to_owned(); 82 let syntax_under_caret = method_call.syntax().to_owned();
80 let module_with_name_to_import = ctx.sema.scope(&syntax_under_caret).module()?; 83 let module_with_name_to_import = ctx.sema.scope(&syntax_under_caret).module()?;
81 Some(Self { 84 Some(Self {
@@ -85,7 +88,7 @@ impl AutoImportAssets {
85 }) 88 })
86 } 89 }
87 90
88 fn for_regular_path(path_under_caret: ast::Path, ctx: &AssistCtx) -> Option<Self> { 91 fn for_regular_path(path_under_caret: ast::Path, ctx: &AssistContext) -> Option<Self> {
89 let syntax_under_caret = path_under_caret.syntax().to_owned(); 92 let syntax_under_caret = path_under_caret.syntax().to_owned();
90 if syntax_under_caret.ancestors().find_map(ast::UseItem::cast).is_some() { 93 if syntax_under_caret.ancestors().find_map(ast::UseItem::cast).is_some() {
91 return None; 94 return None;
@@ -108,8 +111,8 @@ impl AutoImportAssets {
108 } 111 }
109 } 112 }
110 113
111 fn get_import_group_message(&self) -> String { 114 fn get_import_group_message(&self) -> GroupLabel {
112 match &self.import_candidate { 115 let name = match &self.import_candidate {
113 ImportCandidate::UnqualifiedName(name) => format!("Import {}", name), 116 ImportCandidate::UnqualifiedName(name) => format!("Import {}", name),
114 ImportCandidate::QualifierStart(qualifier_start) => { 117 ImportCandidate::QualifierStart(qualifier_start) => {
115 format!("Import {}", qualifier_start) 118 format!("Import {}", qualifier_start)
@@ -120,7 +123,8 @@ impl AutoImportAssets {
120 ImportCandidate::TraitMethod(_, trait_method_name) => { 123 ImportCandidate::TraitMethod(_, trait_method_name) => {
121 format!("Import a trait for method {}", trait_method_name) 124 format!("Import a trait for method {}", trait_method_name)
122 } 125 }
123 } 126 };
127 GroupLabel(name)
124 } 128 }
125 129
126 fn search_for_imports(&self, db: &RootDatabase) -> BTreeSet<ModPath> { 130 fn search_for_imports(&self, db: &RootDatabase) -> BTreeSet<ModPath> {
@@ -280,7 +284,7 @@ impl ImportCandidate {
280#[cfg(test)] 284#[cfg(test)]
281mod tests { 285mod tests {
282 use super::*; 286 use super::*;
283 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 287 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
284 288
285 #[test] 289 #[test]
286 fn applicable_when_found_an_import() { 290 fn applicable_when_found_an_import() {
@@ -294,7 +298,7 @@ mod tests {
294 } 298 }
295 ", 299 ",
296 r" 300 r"
297 <|>use PubMod::PubStruct; 301 use PubMod::PubStruct;
298 302
299 PubStruct 303 PubStruct
300 304
@@ -306,6 +310,35 @@ mod tests {
306 } 310 }
307 311
308 #[test] 312 #[test]
313 fn applicable_when_found_an_import_in_macros() {
314 check_assist(
315 auto_import,
316 r"
317 macro_rules! foo {
318 ($i:ident) => { fn foo(a: $i) {} }
319 }
320 foo!(Pub<|>Struct);
321
322 pub mod PubMod {
323 pub struct PubStruct;
324 }
325 ",
326 r"
327 use PubMod::PubStruct;
328
329 macro_rules! foo {
330 ($i:ident) => { fn foo(a: $i) {} }
331 }
332 foo!(PubStruct);
333
334 pub mod PubMod {
335 pub struct PubStruct;
336 }
337 ",
338 );
339 }
340
341 #[test]
309 fn auto_imports_are_merged() { 342 fn auto_imports_are_merged() {
310 check_assist( 343 check_assist(
311 auto_import, 344 auto_import,
@@ -327,7 +360,7 @@ mod tests {
327 use PubMod::{PubStruct2, PubStruct1}; 360 use PubMod::{PubStruct2, PubStruct1};
328 361
329 struct Test { 362 struct Test {
330 test: Pub<|>Struct2<u8>, 363 test: PubStruct2<u8>,
331 } 364 }
332 365
333 pub mod PubMod { 366 pub mod PubMod {
@@ -358,9 +391,9 @@ mod tests {
358 } 391 }
359 ", 392 ",
360 r" 393 r"
361 use PubMod1::PubStruct; 394 use PubMod3::PubStruct;
362 395
363 PubSt<|>ruct 396 PubStruct
364 397
365 pub mod PubMod1 { 398 pub mod PubMod1 {
366 pub struct PubStruct; 399 pub struct PubStruct;
@@ -441,7 +474,7 @@ mod tests {
441 r" 474 r"
442 use PubMod::test_function; 475 use PubMod::test_function;
443 476
444 test_function<|> 477 test_function
445 478
446 pub mod PubMod { 479 pub mod PubMod {
447 pub fn test_function() {}; 480 pub fn test_function() {};
@@ -468,7 +501,7 @@ mod tests {
468 r"use crate_with_macro::foo; 501 r"use crate_with_macro::foo;
469 502
470fn main() { 503fn main() {
471 foo<|> 504 foo
472} 505}
473", 506",
474 ); 507 );
@@ -554,7 +587,7 @@ fn main() {
554 } 587 }
555 588
556 fn main() { 589 fn main() {
557 TestStruct::test_function<|> 590 TestStruct::test_function
558 } 591 }
559 ", 592 ",
560 ); 593 );
@@ -587,7 +620,7 @@ fn main() {
587 } 620 }
588 621
589 fn main() { 622 fn main() {
590 TestStruct::TEST_CONST<|> 623 TestStruct::TEST_CONST
591 } 624 }
592 ", 625 ",
593 ); 626 );
@@ -626,7 +659,7 @@ fn main() {
626 } 659 }
627 660
628 fn main() { 661 fn main() {
629 test_mod::TestStruct::test_function<|> 662 test_mod::TestStruct::test_function
630 } 663 }
631 ", 664 ",
632 ); 665 );
@@ -697,7 +730,7 @@ fn main() {
697 } 730 }
698 731
699 fn main() { 732 fn main() {
700 test_mod::TestStruct::TEST_CONST<|> 733 test_mod::TestStruct::TEST_CONST
701 } 734 }
702 ", 735 ",
703 ); 736 );
@@ -770,7 +803,7 @@ fn main() {
770 803
771 fn main() { 804 fn main() {
772 let test_struct = test_mod::TestStruct {}; 805 let test_struct = test_mod::TestStruct {};
773 test_struct.test_meth<|>od() 806 test_struct.test_method()
774 } 807 }
775 ", 808 ",
776 ); 809 );
diff --git a/crates/ra_assists/src/handlers/change_return_type_to_result.rs b/crates/ra_assists/src/handlers/change_return_type_to_result.rs
new file mode 100644
index 000000000..c6baa0a57
--- /dev/null
+++ b/crates/ra_assists/src/handlers/change_return_type_to_result.rs
@@ -0,0 +1,961 @@
1use ra_syntax::{
2 ast::{self, BlockExpr, Expr, LoopBodyOwner},
3 AstNode, SyntaxNode,
4};
5
6use crate::{AssistContext, AssistId, Assists};
7
8// Assist: change_return_type_to_result
9//
10// Change the function's return type to Result.
11//
12// ```
13// fn foo() -> i32<|> { 42i32 }
14// ```
15// ->
16// ```
17// fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
18// ```
19pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
20 let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
21 // FIXME: extend to lambdas as well
22 let fn_def = ret_type.syntax().parent().and_then(ast::FnDef::cast)?;
23
24 let type_ref = &ret_type.type_ref()?;
25 if type_ref.syntax().text().to_string().starts_with("Result<") {
26 return None;
27 }
28
29 let block_expr = &fn_def.body()?;
30
31 acc.add(
32 AssistId("change_return_type_to_result"),
33 "Change return type to Result",
34 type_ref.syntax().text_range(),
35 |builder| {
36 let mut tail_return_expr_collector = TailReturnCollector::new();
37 tail_return_expr_collector.collect_jump_exprs(block_expr, false);
38 tail_return_expr_collector.collect_tail_exprs(block_expr);
39
40 for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap {
41 builder.replace_node_and_indent(&ret_expr_arg, format!("Ok({})", ret_expr_arg));
42 }
43
44 match ctx.config.snippet_cap {
45 Some(cap) => {
46 let snippet = format!("Result<{}, ${{0:_}}>", type_ref);
47 builder.replace_snippet(cap, type_ref.syntax().text_range(), snippet)
48 }
49 None => builder
50 .replace(type_ref.syntax().text_range(), format!("Result<{}, _>", type_ref)),
51 }
52 },
53 )
54}
55
56struct TailReturnCollector {
57 exprs_to_wrap: Vec<SyntaxNode>,
58}
59
60impl TailReturnCollector {
61 fn new() -> Self {
62 Self { exprs_to_wrap: vec![] }
63 }
64 /// Collect all`return` expression
65 fn collect_jump_exprs(&mut self, block_expr: &BlockExpr, collect_break: bool) {
66 let statements = block_expr.statements();
67 for stmt in statements {
68 let expr = match &stmt {
69 ast::Stmt::ExprStmt(stmt) => stmt.expr(),
70 ast::Stmt::LetStmt(stmt) => stmt.initializer(),
71 };
72 if let Some(expr) = &expr {
73 self.handle_exprs(expr, collect_break);
74 }
75 }
76
77 // Browse tail expressions for each block
78 if let Some(expr) = block_expr.expr() {
79 if let Some(last_exprs) = get_tail_expr_from_block(&expr) {
80 for last_expr in last_exprs {
81 let last_expr = match last_expr {
82 NodeType::Node(expr) | NodeType::Leaf(expr) => expr,
83 };
84
85 if let Some(last_expr) = Expr::cast(last_expr.clone()) {
86 self.handle_exprs(&last_expr, collect_break);
87 } else if let Some(expr_stmt) = ast::Stmt::cast(last_expr) {
88 let expr_stmt = match &expr_stmt {
89 ast::Stmt::ExprStmt(stmt) => stmt.expr(),
90 ast::Stmt::LetStmt(stmt) => stmt.initializer(),
91 };
92 if let Some(expr) = &expr_stmt {
93 self.handle_exprs(expr, collect_break);
94 }
95 }
96 }
97 }
98 }
99 }
100
101 fn handle_exprs(&mut self, expr: &Expr, collect_break: bool) {
102 match expr {
103 Expr::BlockExpr(block_expr) => {
104 self.collect_jump_exprs(&block_expr, collect_break);
105 }
106 Expr::ReturnExpr(ret_expr) => {
107 if let Some(ret_expr_arg) = &ret_expr.expr() {
108 self.exprs_to_wrap.push(ret_expr_arg.syntax().clone());
109 }
110 }
111 Expr::BreakExpr(break_expr) if collect_break => {
112 if let Some(break_expr_arg) = &break_expr.expr() {
113 self.exprs_to_wrap.push(break_expr_arg.syntax().clone());
114 }
115 }
116 Expr::IfExpr(if_expr) => {
117 for block in if_expr.blocks() {
118 self.collect_jump_exprs(&block, collect_break);
119 }
120 }
121 Expr::LoopExpr(loop_expr) => {
122 if let Some(block_expr) = loop_expr.loop_body() {
123 self.collect_jump_exprs(&block_expr, collect_break);
124 }
125 }
126 Expr::ForExpr(for_expr) => {
127 if let Some(block_expr) = for_expr.loop_body() {
128 self.collect_jump_exprs(&block_expr, collect_break);
129 }
130 }
131 Expr::WhileExpr(while_expr) => {
132 if let Some(block_expr) = while_expr.loop_body() {
133 self.collect_jump_exprs(&block_expr, collect_break);
134 }
135 }
136 Expr::MatchExpr(match_expr) => {
137 if let Some(arm_list) = match_expr.match_arm_list() {
138 arm_list.arms().filter_map(|match_arm| match_arm.expr()).for_each(|expr| {
139 self.handle_exprs(&expr, collect_break);
140 });
141 }
142 }
143 _ => {}
144 }
145 }
146
147 fn collect_tail_exprs(&mut self, block: &BlockExpr) {
148 if let Some(expr) = block.expr() {
149 self.handle_exprs(&expr, true);
150 self.fetch_tail_exprs(&expr);
151 }
152 }
153
154 fn fetch_tail_exprs(&mut self, expr: &Expr) {
155 if let Some(exprs) = get_tail_expr_from_block(expr) {
156 for node_type in &exprs {
157 match node_type {
158 NodeType::Leaf(expr) => {
159 self.exprs_to_wrap.push(expr.clone());
160 }
161 NodeType::Node(expr) => match &Expr::cast(expr.clone()) {
162 Some(last_expr) => {
163 self.fetch_tail_exprs(last_expr);
164 }
165 None => {
166 self.exprs_to_wrap.push(expr.clone());
167 }
168 },
169 }
170 }
171 }
172 }
173}
174
175#[derive(Debug)]
176enum NodeType {
177 Leaf(SyntaxNode),
178 Node(SyntaxNode),
179}
180
181/// Get a tail expression inside a block
182fn get_tail_expr_from_block(expr: &Expr) -> Option<Vec<NodeType>> {
183 match expr {
184 Expr::IfExpr(if_expr) => {
185 let mut nodes = vec![];
186 for block in if_expr.blocks() {
187 if let Some(block_expr) = block.expr() {
188 if let Some(tail_exprs) = get_tail_expr_from_block(&block_expr) {
189 nodes.extend(tail_exprs);
190 }
191 } else if let Some(last_expr) = block.syntax().last_child() {
192 nodes.push(NodeType::Node(last_expr));
193 } else {
194 nodes.push(NodeType::Node(block.syntax().clone()));
195 }
196 }
197 Some(nodes)
198 }
199 Expr::LoopExpr(loop_expr) => {
200 loop_expr.syntax().last_child().map(|lc| vec![NodeType::Node(lc)])
201 }
202 Expr::ForExpr(for_expr) => {
203 for_expr.syntax().last_child().map(|lc| vec![NodeType::Node(lc)])
204 }
205 Expr::WhileExpr(while_expr) => {
206 while_expr.syntax().last_child().map(|lc| vec![NodeType::Node(lc)])
207 }
208 Expr::BlockExpr(block_expr) => {
209 block_expr.expr().map(|lc| vec![NodeType::Node(lc.syntax().clone())])
210 }
211 Expr::MatchExpr(match_expr) => {
212 let arm_list = match_expr.match_arm_list()?;
213 let arms: Vec<NodeType> = arm_list
214 .arms()
215 .filter_map(|match_arm| match_arm.expr())
216 .map(|expr| match expr {
217 Expr::ReturnExpr(ret_expr) => NodeType::Node(ret_expr.syntax().clone()),
218 Expr::BreakExpr(break_expr) => NodeType::Node(break_expr.syntax().clone()),
219 _ => match expr.syntax().last_child() {
220 Some(last_expr) => NodeType::Node(last_expr),
221 None => NodeType::Node(expr.syntax().clone()),
222 },
223 })
224 .collect();
225
226 Some(arms)
227 }
228 Expr::BreakExpr(expr) => expr.expr().map(|e| vec![NodeType::Leaf(e.syntax().clone())]),
229 Expr::ReturnExpr(ret_expr) => Some(vec![NodeType::Node(ret_expr.syntax().clone())]),
230 Expr::CallExpr(call_expr) => Some(vec![NodeType::Leaf(call_expr.syntax().clone())]),
231 Expr::Literal(lit_expr) => Some(vec![NodeType::Leaf(lit_expr.syntax().clone())]),
232 Expr::TupleExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
233 Expr::ArrayExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
234 Expr::ParenExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
235 Expr::PathExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
236 Expr::Label(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
237 Expr::RecordLit(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
238 Expr::IndexExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
239 Expr::MethodCallExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
240 Expr::AwaitExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
241 Expr::CastExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
242 Expr::RefExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
243 Expr::PrefixExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
244 Expr::RangeExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
245 Expr::BinExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
246 Expr::MacroCall(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
247 Expr::BoxExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
248 _ => None,
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use crate::tests::{check_assist, check_assist_not_applicable};
255
256 use super::*;
257
258 #[test]
259 fn change_return_type_to_result_simple() {
260 check_assist(
261 change_return_type_to_result,
262 r#"fn foo() -> i3<|>2 {
263 let test = "test";
264 return 42i32;
265 }"#,
266 r#"fn foo() -> Result<i32, ${0:_}> {
267 let test = "test";
268 return Ok(42i32);
269 }"#,
270 );
271 }
272
273 #[test]
274 fn change_return_type_to_result_simple_return_type() {
275 check_assist(
276 change_return_type_to_result,
277 r#"fn foo() -> i32<|> {
278 let test = "test";
279 return 42i32;
280 }"#,
281 r#"fn foo() -> Result<i32, ${0:_}> {
282 let test = "test";
283 return Ok(42i32);
284 }"#,
285 );
286 }
287
288 #[test]
289 fn change_return_type_to_result_simple_return_type_bad_cursor() {
290 check_assist_not_applicable(
291 change_return_type_to_result,
292 r#"fn foo() -> i32 {
293 let test = "test";<|>
294 return 42i32;
295 }"#,
296 );
297 }
298
299 #[test]
300 fn change_return_type_to_result_simple_with_cursor() {
301 check_assist(
302 change_return_type_to_result,
303 r#"fn foo() -> <|>i32 {
304 let test = "test";
305 return 42i32;
306 }"#,
307 r#"fn foo() -> Result<i32, ${0:_}> {
308 let test = "test";
309 return Ok(42i32);
310 }"#,
311 );
312 }
313
314 #[test]
315 fn change_return_type_to_result_simple_with_tail() {
316 check_assist(
317 change_return_type_to_result,
318 r#"fn foo() -><|> i32 {
319 let test = "test";
320 42i32
321 }"#,
322 r#"fn foo() -> Result<i32, ${0:_}> {
323 let test = "test";
324 Ok(42i32)
325 }"#,
326 );
327 }
328
329 #[test]
330 fn change_return_type_to_result_simple_with_tail_only() {
331 check_assist(
332 change_return_type_to_result,
333 r#"fn foo() -> i32<|> {
334 42i32
335 }"#,
336 r#"fn foo() -> Result<i32, ${0:_}> {
337 Ok(42i32)
338 }"#,
339 );
340 }
341 #[test]
342 fn change_return_type_to_result_simple_with_tail_block_like() {
343 check_assist(
344 change_return_type_to_result,
345 r#"fn foo() -> i32<|> {
346 if true {
347 42i32
348 } else {
349 24i32
350 }
351 }"#,
352 r#"fn foo() -> Result<i32, ${0:_}> {
353 if true {
354 Ok(42i32)
355 } else {
356 Ok(24i32)
357 }
358 }"#,
359 );
360 }
361
362 #[test]
363 fn change_return_type_to_result_simple_with_nested_if() {
364 check_assist(
365 change_return_type_to_result,
366 r#"fn foo() -> i32<|> {
367 if true {
368 if false {
369 1
370 } else {
371 2
372 }
373 } else {
374 24i32
375 }
376 }"#,
377 r#"fn foo() -> Result<i32, ${0:_}> {
378 if true {
379 if false {
380 Ok(1)
381 } else {
382 Ok(2)
383 }
384 } else {
385 Ok(24i32)
386 }
387 }"#,
388 );
389 }
390
391 #[test]
392 fn change_return_type_to_result_simple_with_await() {
393 check_assist(
394 change_return_type_to_result,
395 r#"async fn foo() -> i<|>32 {
396 if true {
397 if false {
398 1.await
399 } else {
400 2.await
401 }
402 } else {
403 24i32.await
404 }
405 }"#,
406 r#"async fn foo() -> Result<i32, ${0:_}> {
407 if true {
408 if false {
409 Ok(1.await)
410 } else {
411 Ok(2.await)
412 }
413 } else {
414 Ok(24i32.await)
415 }
416 }"#,
417 );
418 }
419
420 #[test]
421 fn change_return_type_to_result_simple_with_array() {
422 check_assist(
423 change_return_type_to_result,
424 r#"fn foo() -> [i32;<|> 3] {
425 [1, 2, 3]
426 }"#,
427 r#"fn foo() -> Result<[i32; 3], ${0:_}> {
428 Ok([1, 2, 3])
429 }"#,
430 );
431 }
432
433 #[test]
434 fn change_return_type_to_result_simple_with_cast() {
435 check_assist(
436 change_return_type_to_result,
437 r#"fn foo() -<|>> i32 {
438 if true {
439 if false {
440 1 as i32
441 } else {
442 2 as i32
443 }
444 } else {
445 24 as i32
446 }
447 }"#,
448 r#"fn foo() -> Result<i32, ${0:_}> {
449 if true {
450 if false {
451 Ok(1 as i32)
452 } else {
453 Ok(2 as i32)
454 }
455 } else {
456 Ok(24 as i32)
457 }
458 }"#,
459 );
460 }
461
462 #[test]
463 fn change_return_type_to_result_simple_with_tail_block_like_match() {
464 check_assist(
465 change_return_type_to_result,
466 r#"fn foo() -> i32<|> {
467 let my_var = 5;
468 match my_var {
469 5 => 42i32,
470 _ => 24i32,
471 }
472 }"#,
473 r#"fn foo() -> Result<i32, ${0:_}> {
474 let my_var = 5;
475 match my_var {
476 5 => Ok(42i32),
477 _ => Ok(24i32),
478 }
479 }"#,
480 );
481 }
482
483 #[test]
484 fn change_return_type_to_result_simple_with_loop_with_tail() {
485 check_assist(
486 change_return_type_to_result,
487 r#"fn foo() -> i32<|> {
488 let my_var = 5;
489 loop {
490 println!("test");
491 5
492 }
493
494 my_var
495 }"#,
496 r#"fn foo() -> Result<i32, ${0:_}> {
497 let my_var = 5;
498 loop {
499 println!("test");
500 5
501 }
502
503 Ok(my_var)
504 }"#,
505 );
506 }
507
508 #[test]
509 fn change_return_type_to_result_simple_with_loop_in_let_stmt() {
510 check_assist(
511 change_return_type_to_result,
512 r#"fn foo() -> i32<|> {
513 let my_var = let x = loop {
514 break 1;
515 };
516
517 my_var
518 }"#,
519 r#"fn foo() -> Result<i32, ${0:_}> {
520 let my_var = let x = loop {
521 break 1;
522 };
523
524 Ok(my_var)
525 }"#,
526 );
527 }
528
529 #[test]
530 fn change_return_type_to_result_simple_with_tail_block_like_match_return_expr() {
531 check_assist(
532 change_return_type_to_result,
533 r#"fn foo() -> i32<|> {
534 let my_var = 5;
535 let res = match my_var {
536 5 => 42i32,
537 _ => return 24i32,
538 };
539
540 res
541 }"#,
542 r#"fn foo() -> Result<i32, ${0:_}> {
543 let my_var = 5;
544 let res = match my_var {
545 5 => 42i32,
546 _ => return Ok(24i32),
547 };
548
549 Ok(res)
550 }"#,
551 );
552
553 check_assist(
554 change_return_type_to_result,
555 r#"fn foo() -> i32<|> {
556 let my_var = 5;
557 let res = if my_var == 5 {
558 42i32
559 } else {
560 return 24i32;
561 };
562
563 res
564 }"#,
565 r#"fn foo() -> Result<i32, ${0:_}> {
566 let my_var = 5;
567 let res = if my_var == 5 {
568 42i32
569 } else {
570 return Ok(24i32);
571 };
572
573 Ok(res)
574 }"#,
575 );
576 }
577
578 #[test]
579 fn change_return_type_to_result_simple_with_tail_block_like_match_deeper() {
580 check_assist(
581 change_return_type_to_result,
582 r#"fn foo() -> i32<|> {
583 let my_var = 5;
584 match my_var {
585 5 => {
586 if true {
587 42i32
588 } else {
589 25i32
590 }
591 },
592 _ => {
593 let test = "test";
594 if test == "test" {
595 return bar();
596 }
597 53i32
598 },
599 }
600 }"#,
601 r#"fn foo() -> Result<i32, ${0:_}> {
602 let my_var = 5;
603 match my_var {
604 5 => {
605 if true {
606 Ok(42i32)
607 } else {
608 Ok(25i32)
609 }
610 },
611 _ => {
612 let test = "test";
613 if test == "test" {
614 return Ok(bar());
615 }
616 Ok(53i32)
617 },
618 }
619 }"#,
620 );
621 }
622
623 #[test]
624 fn change_return_type_to_result_simple_with_tail_block_like_early_return() {
625 check_assist(
626 change_return_type_to_result,
627 r#"fn foo() -> i<|>32 {
628 let test = "test";
629 if test == "test" {
630 return 24i32;
631 }
632 53i32
633 }"#,
634 r#"fn foo() -> Result<i32, ${0:_}> {
635 let test = "test";
636 if test == "test" {
637 return Ok(24i32);
638 }
639 Ok(53i32)
640 }"#,
641 );
642 }
643
644 #[test]
645 fn change_return_type_to_result_simple_with_closure() {
646 check_assist(
647 change_return_type_to_result,
648 r#"fn foo(the_field: u32) -><|> u32 {
649 let true_closure = || {
650 return true;
651 };
652 if the_field < 5 {
653 let mut i = 0;
654
655
656 if true_closure() {
657 return 99;
658 } else {
659 return 0;
660 }
661 }
662
663 the_field
664 }"#,
665 r#"fn foo(the_field: u32) -> Result<u32, ${0:_}> {
666 let true_closure = || {
667 return true;
668 };
669 if the_field < 5 {
670 let mut i = 0;
671
672
673 if true_closure() {
674 return Ok(99);
675 } else {
676 return Ok(0);
677 }
678 }
679
680 Ok(the_field)
681 }"#,
682 );
683
684 check_assist(
685 change_return_type_to_result,
686 r#"fn foo(the_field: u32) -> u32<|> {
687 let true_closure = || {
688 return true;
689 };
690 if the_field < 5 {
691 let mut i = 0;
692
693
694 if true_closure() {
695 return 99;
696 } else {
697 return 0;
698 }
699 }
700 let t = None;
701
702 t.unwrap_or_else(|| the_field)
703 }"#,
704 r#"fn foo(the_field: u32) -> Result<u32, ${0:_}> {
705 let true_closure = || {
706 return true;
707 };
708 if the_field < 5 {
709 let mut i = 0;
710
711
712 if true_closure() {
713 return Ok(99);
714 } else {
715 return Ok(0);
716 }
717 }
718 let t = None;
719
720 Ok(t.unwrap_or_else(|| the_field))
721 }"#,
722 );
723 }
724
725 #[test]
726 fn change_return_type_to_result_simple_with_weird_forms() {
727 check_assist(
728 change_return_type_to_result,
729 r#"fn foo() -> i32<|> {
730 let test = "test";
731 if test == "test" {
732 return 24i32;
733 }
734 let mut i = 0;
735 loop {
736 if i == 1 {
737 break 55;
738 }
739 i += 1;
740 }
741 }"#,
742 r#"fn foo() -> Result<i32, ${0:_}> {
743 let test = "test";
744 if test == "test" {
745 return Ok(24i32);
746 }
747 let mut i = 0;
748 loop {
749 if i == 1 {
750 break Ok(55);
751 }
752 i += 1;
753 }
754 }"#,
755 );
756
757 check_assist(
758 change_return_type_to_result,
759 r#"fn foo() -> i32<|> {
760 let test = "test";
761 if test == "test" {
762 return 24i32;
763 }
764 let mut i = 0;
765 loop {
766 loop {
767 if i == 1 {
768 break 55;
769 }
770 i += 1;
771 }
772 }
773 }"#,
774 r#"fn foo() -> Result<i32, ${0:_}> {
775 let test = "test";
776 if test == "test" {
777 return Ok(24i32);
778 }
779 let mut i = 0;
780 loop {
781 loop {
782 if i == 1 {
783 break Ok(55);
784 }
785 i += 1;
786 }
787 }
788 }"#,
789 );
790
791 check_assist(
792 change_return_type_to_result,
793 r#"fn foo() -> i3<|>2 {
794 let test = "test";
795 let other = 5;
796 if test == "test" {
797 let res = match other {
798 5 => 43,
799 _ => return 56,
800 };
801 }
802 let mut i = 0;
803 loop {
804 loop {
805 if i == 1 {
806 break 55;
807 }
808 i += 1;
809 }
810 }
811 }"#,
812 r#"fn foo() -> Result<i32, ${0:_}> {
813 let test = "test";
814 let other = 5;
815 if test == "test" {
816 let res = match other {
817 5 => 43,
818 _ => return Ok(56),
819 };
820 }
821 let mut i = 0;
822 loop {
823 loop {
824 if i == 1 {
825 break Ok(55);
826 }
827 i += 1;
828 }
829 }
830 }"#,
831 );
832
833 check_assist(
834 change_return_type_to_result,
835 r#"fn foo(the_field: u32) -> u32<|> {
836 if the_field < 5 {
837 let mut i = 0;
838 loop {
839 if i > 5 {
840 return 55u32;
841 }
842 i += 3;
843 }
844
845 match i {
846 5 => return 99,
847 _ => return 0,
848 };
849 }
850
851 the_field
852 }"#,
853 r#"fn foo(the_field: u32) -> Result<u32, ${0:_}> {
854 if the_field < 5 {
855 let mut i = 0;
856 loop {
857 if i > 5 {
858 return Ok(55u32);
859 }
860 i += 3;
861 }
862
863 match i {
864 5 => return Ok(99),
865 _ => return Ok(0),
866 };
867 }
868
869 Ok(the_field)
870 }"#,
871 );
872
873 check_assist(
874 change_return_type_to_result,
875 r#"fn foo(the_field: u32) -> u3<|>2 {
876 if the_field < 5 {
877 let mut i = 0;
878
879 match i {
880 5 => return 99,
881 _ => return 0,
882 }
883 }
884
885 the_field
886 }"#,
887 r#"fn foo(the_field: u32) -> Result<u32, ${0:_}> {
888 if the_field < 5 {
889 let mut i = 0;
890
891 match i {
892 5 => return Ok(99),
893 _ => return Ok(0),
894 }
895 }
896
897 Ok(the_field)
898 }"#,
899 );
900
901 check_assist(
902 change_return_type_to_result,
903 r#"fn foo(the_field: u32) -> u32<|> {
904 if the_field < 5 {
905 let mut i = 0;
906
907 if i == 5 {
908 return 99
909 } else {
910 return 0
911 }
912 }
913
914 the_field
915 }"#,
916 r#"fn foo(the_field: u32) -> Result<u32, ${0:_}> {
917 if the_field < 5 {
918 let mut i = 0;
919
920 if i == 5 {
921 return Ok(99)
922 } else {
923 return Ok(0)
924 }
925 }
926
927 Ok(the_field)
928 }"#,
929 );
930
931 check_assist(
932 change_return_type_to_result,
933 r#"fn foo(the_field: u32) -> <|>u32 {
934 if the_field < 5 {
935 let mut i = 0;
936
937 if i == 5 {
938 return 99;
939 } else {
940 return 0;
941 }
942 }
943
944 the_field
945 }"#,
946 r#"fn foo(the_field: u32) -> Result<u32, ${0:_}> {
947 if the_field < 5 {
948 let mut i = 0;
949
950 if i == 5 {
951 return Ok(99);
952 } else {
953 return Ok(0);
954 }
955 }
956
957 Ok(the_field)
958 }"#,
959 );
960 }
961}
diff --git a/crates/ra_assists/src/handlers/change_visibility.rs b/crates/ra_assists/src/handlers/change_visibility.rs
index 44f6a1dae..c21d75be0 100644
--- a/crates/ra_assists/src/handlers/change_visibility.rs
+++ b/crates/ra_assists/src/handlers/change_visibility.rs
@@ -7,9 +7,9 @@ use ra_syntax::{
7 }, 7 },
8 SyntaxNode, TextSize, T, 8 SyntaxNode, TextSize, T,
9}; 9};
10use test_utils::mark;
10 11
11use crate::{Assist, AssistCtx, AssistId}; 12use crate::{AssistContext, AssistId, Assists};
12use test_utils::tested_by;
13 13
14// Assist: change_visibility 14// Assist: change_visibility
15// 15//
@@ -22,14 +22,14 @@ use test_utils::tested_by;
22// ``` 22// ```
23// pub(crate) fn frobnicate() {} 23// pub(crate) fn frobnicate() {}
24// ``` 24// ```
25pub(crate) fn change_visibility(ctx: AssistCtx) -> Option<Assist> { 25pub(crate) fn change_visibility(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 if let Some(vis) = ctx.find_node_at_offset::<ast::Visibility>() { 26 if let Some(vis) = ctx.find_node_at_offset::<ast::Visibility>() {
27 return change_vis(ctx, vis); 27 return change_vis(acc, vis);
28 } 28 }
29 add_vis(ctx) 29 add_vis(acc, ctx)
30} 30}
31 31
32fn add_vis(ctx: AssistCtx) -> Option<Assist> { 32fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
33 let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() { 33 let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() {
34 T![const] | T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true, 34 T![const] | T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true,
35 _ => false, 35 _ => false,
@@ -47,23 +47,27 @@ fn add_vis(ctx: AssistCtx) -> Option<Assist> {
47 return None; 47 return None;
48 } 48 }
49 (vis_offset(&parent), keyword.text_range()) 49 (vis_offset(&parent), keyword.text_range())
50 } else { 50 } else if let Some(field_name) = ctx.find_node_at_offset::<ast::Name>() {
51 let field_name: ast::Name = ctx.find_node_at_offset()?;
52 let field = field_name.syntax().ancestors().find_map(ast::RecordFieldDef::cast)?; 51 let field = field_name.syntax().ancestors().find_map(ast::RecordFieldDef::cast)?;
53 if field.name()? != field_name { 52 if field.name()? != field_name {
54 tested_by!(change_visibility_field_false_positive); 53 mark::hit!(change_visibility_field_false_positive);
55 return None; 54 return None;
56 } 55 }
57 if field.visibility().is_some() { 56 if field.visibility().is_some() {
58 return None; 57 return None;
59 } 58 }
60 (vis_offset(field.syntax()), field_name.syntax().text_range()) 59 (vis_offset(field.syntax()), field_name.syntax().text_range())
60 } else if let Some(field) = ctx.find_node_at_offset::<ast::TupleFieldDef>() {
61 if field.visibility().is_some() {
62 return None;
63 }
64 (vis_offset(field.syntax()), field.syntax().text_range())
65 } else {
66 return None;
61 }; 67 };
62 68
63 ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub(crate)", |edit| { 69 acc.add(AssistId("change_visibility"), "Change visibility to pub(crate)", target, |edit| {
64 edit.target(target);
65 edit.insert(offset, "pub(crate) "); 70 edit.insert(offset, "pub(crate) ");
66 edit.set_cursor(offset);
67 }) 71 })
68} 72}
69 73
@@ -78,49 +82,49 @@ fn vis_offset(node: &SyntaxNode) -> TextSize {
78 .unwrap_or_else(|| node.text_range().start()) 82 .unwrap_or_else(|| node.text_range().start())
79} 83}
80 84
81fn change_vis(ctx: AssistCtx, vis: ast::Visibility) -> Option<Assist> { 85fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> {
82 if vis.syntax().text() == "pub" { 86 if vis.syntax().text() == "pub" {
83 return ctx.add_assist( 87 let target = vis.syntax().text_range();
88 return acc.add(
84 AssistId("change_visibility"), 89 AssistId("change_visibility"),
85 "Change Visibility to pub(crate)", 90 "Change Visibility to pub(crate)",
91 target,
86 |edit| { 92 |edit| {
87 edit.target(vis.syntax().text_range());
88 edit.replace(vis.syntax().text_range(), "pub(crate)"); 93 edit.replace(vis.syntax().text_range(), "pub(crate)");
89 edit.set_cursor(vis.syntax().text_range().start())
90 }, 94 },
91 ); 95 );
92 } 96 }
93 if vis.syntax().text() == "pub(crate)" { 97 if vis.syntax().text() == "pub(crate)" {
94 return ctx.add_assist(AssistId("change_visibility"), "Change visibility to pub", |edit| { 98 let target = vis.syntax().text_range();
95 edit.target(vis.syntax().text_range()); 99 return acc.add(
96 edit.replace(vis.syntax().text_range(), "pub"); 100 AssistId("change_visibility"),
97 edit.set_cursor(vis.syntax().text_range().start()); 101 "Change visibility to pub",
98 }); 102 target,
103 |edit| {
104 edit.replace(vis.syntax().text_range(), "pub");
105 },
106 );
99 } 107 }
100 None 108 None
101} 109}
102 110
103#[cfg(test)] 111#[cfg(test)]
104mod tests { 112mod tests {
105 use test_utils::covers; 113 use test_utils::mark;
106 114
107 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 115 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
108 116
109 use super::*; 117 use super::*;
110 118
111 #[test] 119 #[test]
112 fn change_visibility_adds_pub_crate_to_items() { 120 fn change_visibility_adds_pub_crate_to_items() {
113 check_assist(change_visibility, "<|>fn foo() {}", "<|>pub(crate) fn foo() {}"); 121 check_assist(change_visibility, "<|>fn foo() {}", "pub(crate) fn foo() {}");
114 check_assist(change_visibility, "f<|>n foo() {}", "<|>pub(crate) fn foo() {}"); 122 check_assist(change_visibility, "f<|>n foo() {}", "pub(crate) fn foo() {}");
115 check_assist(change_visibility, "<|>struct Foo {}", "<|>pub(crate) struct Foo {}"); 123 check_assist(change_visibility, "<|>struct Foo {}", "pub(crate) struct Foo {}");
116 check_assist(change_visibility, "<|>mod foo {}", "<|>pub(crate) mod foo {}"); 124 check_assist(change_visibility, "<|>mod foo {}", "pub(crate) mod foo {}");
117 check_assist(change_visibility, "<|>trait Foo {}", "<|>pub(crate) trait Foo {}"); 125 check_assist(change_visibility, "<|>trait Foo {}", "pub(crate) trait Foo {}");
118 check_assist(change_visibility, "m<|>od {}", "<|>pub(crate) mod {}"); 126 check_assist(change_visibility, "m<|>od {}", "pub(crate) mod {}");
119 check_assist( 127 check_assist(change_visibility, "unsafe f<|>n foo() {}", "pub(crate) unsafe fn foo() {}");
120 change_visibility,
121 "unsafe f<|>n foo() {}",
122 "<|>pub(crate) unsafe fn foo() {}",
123 );
124 } 128 }
125 129
126 #[test] 130 #[test]
@@ -128,13 +132,14 @@ mod tests {
128 check_assist( 132 check_assist(
129 change_visibility, 133 change_visibility,
130 r"struct S { <|>field: u32 }", 134 r"struct S { <|>field: u32 }",
131 r"struct S { <|>pub(crate) field: u32 }", 135 r"struct S { pub(crate) field: u32 }",
132 ) 136 );
137 check_assist(change_visibility, r"struct S ( <|>u32 )", r"struct S ( pub(crate) u32 )");
133 } 138 }
134 139
135 #[test] 140 #[test]
136 fn change_visibility_field_false_positive() { 141 fn change_visibility_field_false_positive() {
137 covers!(change_visibility_field_false_positive); 142 mark::check!(change_visibility_field_false_positive);
138 check_assist_not_applicable( 143 check_assist_not_applicable(
139 change_visibility, 144 change_visibility,
140 r"struct S { field: [(); { let <|>x = ();}] }", 145 r"struct S { field: [(); { let <|>x = ();}] }",
@@ -143,17 +148,17 @@ mod tests {
143 148
144 #[test] 149 #[test]
145 fn change_visibility_pub_to_pub_crate() { 150 fn change_visibility_pub_to_pub_crate() {
146 check_assist(change_visibility, "<|>pub fn foo() {}", "<|>pub(crate) fn foo() {}") 151 check_assist(change_visibility, "<|>pub fn foo() {}", "pub(crate) fn foo() {}")
147 } 152 }
148 153
149 #[test] 154 #[test]
150 fn change_visibility_pub_crate_to_pub() { 155 fn change_visibility_pub_crate_to_pub() {
151 check_assist(change_visibility, "<|>pub(crate) fn foo() {}", "<|>pub fn foo() {}") 156 check_assist(change_visibility, "<|>pub(crate) fn foo() {}", "pub fn foo() {}")
152 } 157 }
153 158
154 #[test] 159 #[test]
155 fn change_visibility_const() { 160 fn change_visibility_const() {
156 check_assist(change_visibility, "<|>const FOO = 3u8;", "<|>pub(crate) const FOO = 3u8;"); 161 check_assist(change_visibility, "<|>const FOO = 3u8;", "pub(crate) const FOO = 3u8;");
157 } 162 }
158 163
159 #[test] 164 #[test]
@@ -174,12 +179,21 @@ mod tests {
174 // comments 179 // comments
175 180
176 #[derive(Debug)] 181 #[derive(Debug)]
177 <|>pub(crate) struct Foo; 182 pub(crate) struct Foo;
178 ", 183 ",
179 ) 184 )
180 } 185 }
181 186
182 #[test] 187 #[test]
188 fn not_applicable_for_enum_variants() {
189 check_assist_not_applicable(
190 change_visibility,
191 r"mod foo { pub enum Foo {Foo1} }
192 fn main() { foo::Foo::Foo1<|> } ",
193 );
194 }
195
196 #[test]
183 fn change_visibility_target() { 197 fn change_visibility_target() {
184 check_assist_target(change_visibility, "<|>fn foo() {}", "fn"); 198 check_assist_target(change_visibility, "<|>fn foo() {}", "fn");
185 check_assist_target(change_visibility, "pub(crate)<|> fn foo() {}", "pub(crate)"); 199 check_assist_target(change_visibility, "pub(crate)<|> fn foo() {}", "pub(crate)");
diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs
index ea6c56f8c..4cc75a7ce 100644
--- a/crates/ra_assists/src/handlers/early_return.rs
+++ b/crates/ra_assists/src/handlers/early_return.rs
@@ -2,14 +2,18 @@ use std::{iter::once, ops::RangeInclusive};
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 algo::replace_children, 4 algo::replace_children,
5 ast::{self, edit::IndentLevel, make, Block, Pat::TupleStructPat}, 5 ast::{
6 self,
7 edit::{AstNodeEdit, IndentLevel},
8 make,
9 },
6 AstNode, 10 AstNode,
7 SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE}, 11 SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
8 SyntaxNode, 12 SyntaxNode,
9}; 13};
10 14
11use crate::{ 15use crate::{
12 assist_ctx::{Assist, AssistCtx}, 16 assist_context::{AssistContext, Assists},
13 utils::invert_boolean_expression, 17 utils::invert_boolean_expression,
14 AssistId, 18 AssistId,
15}; 19};
@@ -36,7 +40,7 @@ use crate::{
36// bar(); 40// bar();
37// } 41// }
38// ``` 42// ```
39pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> { 43pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
40 let if_expr: ast::IfExpr = ctx.find_node_at_offset()?; 44 let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
41 if if_expr.else_branch().is_some() { 45 if if_expr.else_branch().is_some() {
42 return None; 46 return None;
@@ -47,7 +51,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
47 // Check if there is an IfLet that we can handle. 51 // Check if there is an IfLet that we can handle.
48 let if_let_pat = match cond.pat() { 52 let if_let_pat = match cond.pat() {
49 None => None, // No IfLet, supported. 53 None => None, // No IfLet, supported.
50 Some(TupleStructPat(pat)) if pat.args().count() == 1 => { 54 Some(ast::Pat::TupleStructPat(pat)) if pat.args().count() == 1 => {
51 let path = pat.path()?; 55 let path = pat.path()?;
52 match path.qualifier() { 56 match path.qualifier() {
53 None => { 57 None => {
@@ -61,9 +65,9 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
61 }; 65 };
62 66
63 let cond_expr = cond.expr()?; 67 let cond_expr = cond.expr()?;
64 let then_block = if_expr.then_branch()?.block()?; 68 let then_block = if_expr.then_branch()?;
65 69
66 let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::Block::cast)?; 70 let parent_block = if_expr.syntax().parent()?.ancestors().find_map(ast::BlockExpr::cast)?;
67 71
68 if parent_block.expr()? != if_expr.clone().into() { 72 if parent_block.expr()? != if_expr.clone().into() {
69 return None; 73 return None;
@@ -80,7 +84,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
80 return None; 84 return None;
81 } 85 }
82 86
83 let parent_container = parent_block.syntax().parent()?.parent()?; 87 let parent_container = parent_block.syntax().parent()?;
84 88
85 let early_expression: ast::Expr = match parent_container.kind() { 89 let early_expression: ast::Expr = match parent_container.kind() {
86 WHILE_EXPR | LOOP_EXPR => make::expr_continue(), 90 WHILE_EXPR | LOOP_EXPR => make::expr_continue(),
@@ -93,9 +97,9 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
93 } 97 }
94 98
95 then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?; 99 then_block.syntax().last_child_or_token().filter(|t| t.kind() == R_CURLY)?;
96 let cursor_position = ctx.frange.range.start();
97 100
98 ctx.add_assist(AssistId("convert_to_guarded_return"), "Convert to guarded return", |edit| { 101 let target = if_expr.syntax().text_range();
102 acc.add(AssistId("convert_to_guarded_return"), "Convert to guarded return", target, |edit| {
99 let if_indent_level = IndentLevel::from_node(&if_expr.syntax()); 103 let if_indent_level = IndentLevel::from_node(&if_expr.syntax());
100 let new_block = match if_let_pat { 104 let new_block = match if_let_pat {
101 None => { 105 None => {
@@ -104,8 +108,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
104 let then_branch = 108 let then_branch =
105 make::block_expr(once(make::expr_stmt(early_expression).into()), None); 109 make::block_expr(once(make::expr_stmt(early_expression).into()), None);
106 let cond = invert_boolean_expression(cond_expr); 110 let cond = invert_boolean_expression(cond_expr);
107 let e = make::expr_if(make::condition(cond, None), then_branch); 111 make::expr_if(make::condition(cond, None), then_branch).indent(if_indent_level)
108 if_indent_level.increase_indent(e)
109 }; 112 };
110 replace(new_expr.syntax(), &then_block, &parent_block, &if_expr) 113 replace(new_expr.syntax(), &then_block, &parent_block, &if_expr)
111 } 114 }
@@ -139,21 +142,19 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
139 make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), 142 make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(),
140 Some(match_expr), 143 Some(match_expr),
141 ); 144 );
142 let let_stmt = if_indent_level.increase_indent(let_stmt); 145 let let_stmt = let_stmt.indent(if_indent_level);
143 replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) 146 replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr)
144 } 147 }
145 }; 148 };
146 edit.target(if_expr.syntax().text_range()); 149 edit.replace_ast(parent_block, ast::BlockExpr::cast(new_block).unwrap());
147 edit.replace_ast(parent_block, ast::Block::cast(new_block).unwrap());
148 edit.set_cursor(cursor_position);
149 150
150 fn replace( 151 fn replace(
151 new_expr: &SyntaxNode, 152 new_expr: &SyntaxNode,
152 then_block: &Block, 153 then_block: &ast::BlockExpr,
153 parent_block: &Block, 154 parent_block: &ast::BlockExpr,
154 if_expr: &ast::IfExpr, 155 if_expr: &ast::IfExpr,
155 ) -> SyntaxNode { 156 ) -> SyntaxNode {
156 let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone()); 157 let then_block_items = then_block.dedent(IndentLevel::from(1));
157 let end_of_then = then_block_items.syntax().last_child_or_token().unwrap(); 158 let end_of_then = then_block_items.syntax().last_child_or_token().unwrap();
158 let end_of_then = 159 let end_of_then =
159 if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) { 160 if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
@@ -182,7 +183,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Option<Assist> {
182 183
183#[cfg(test)] 184#[cfg(test)]
184mod tests { 185mod tests {
185 use crate::helpers::{check_assist, check_assist_not_applicable}; 186 use crate::tests::{check_assist, check_assist_not_applicable};
186 187
187 use super::*; 188 use super::*;
188 189
@@ -204,7 +205,7 @@ mod tests {
204 r#" 205 r#"
205 fn main() { 206 fn main() {
206 bar(); 207 bar();
207 if<|> !true { 208 if !true {
208 return; 209 return;
209 } 210 }
210 foo(); 211 foo();
@@ -234,7 +235,7 @@ mod tests {
234 r#" 235 r#"
235 fn main(n: Option<String>) { 236 fn main(n: Option<String>) {
236 bar(); 237 bar();
237 le<|>t n = match n { 238 let n = match n {
238 Some(it) => it, 239 Some(it) => it,
239 _ => return, 240 _ => return,
240 }; 241 };
@@ -260,7 +261,7 @@ mod tests {
260 "#, 261 "#,
261 r#" 262 r#"
262 fn main() { 263 fn main() {
263 le<|>t x = match Err(92) { 264 let x = match Err(92) {
264 Ok(it) => it, 265 Ok(it) => it,
265 _ => return, 266 _ => return,
266 }; 267 };
@@ -288,7 +289,7 @@ mod tests {
288 r#" 289 r#"
289 fn main(n: Option<String>) { 290 fn main(n: Option<String>) {
290 bar(); 291 bar();
291 le<|>t n = match n { 292 let n = match n {
292 Ok(it) => it, 293 Ok(it) => it,
293 _ => return, 294 _ => return,
294 }; 295 };
@@ -318,7 +319,7 @@ mod tests {
318 r#" 319 r#"
319 fn main() { 320 fn main() {
320 while true { 321 while true {
321 if<|> !true { 322 if !true {
322 continue; 323 continue;
323 } 324 }
324 foo(); 325 foo();
@@ -346,7 +347,7 @@ mod tests {
346 r#" 347 r#"
347 fn main() { 348 fn main() {
348 while true { 349 while true {
349 le<|>t n = match n { 350 let n = match n {
350 Some(it) => it, 351 Some(it) => it,
351 _ => continue, 352 _ => continue,
352 }; 353 };
@@ -375,7 +376,7 @@ mod tests {
375 r#" 376 r#"
376 fn main() { 377 fn main() {
377 loop { 378 loop {
378 if<|> !true { 379 if !true {
379 continue; 380 continue;
380 } 381 }
381 foo(); 382 foo();
@@ -403,7 +404,7 @@ mod tests {
403 r#" 404 r#"
404 fn main() { 405 fn main() {
405 loop { 406 loop {
406 le<|>t n = match n { 407 let n = match n {
407 Some(it) => it, 408 Some(it) => it,
408 _ => continue, 409 _ => continue,
409 }; 410 };
diff --git a/crates/ra_assists/src/handlers/fill_match_arms.rs b/crates/ra_assists/src/handlers/fill_match_arms.rs
index 8d1af9933..cc303285b 100644
--- a/crates/ra_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ra_assists/src/handlers/fill_match_arms.rs
@@ -4,8 +4,12 @@ use hir::{Adt, HasSource, ModuleDef, Semantics};
4use itertools::Itertools; 4use itertools::Itertools;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat}; 6use ra_syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat};
7use test_utils::mark;
7 8
8use crate::{Assist, AssistCtx, AssistId}; 9use crate::{
10 utils::{render_snippet, Cursor, FamousDefs},
11 AssistContext, AssistId, Assists,
12};
9 13
10// Assist: fill_match_arms 14// Assist: fill_match_arms
11// 15//
@@ -26,12 +30,12 @@ use crate::{Assist, AssistCtx, AssistId};
26// 30//
27// fn handle(action: Action) { 31// fn handle(action: Action) {
28// match action { 32// match action {
29// Action::Move { distance } => {} 33// $0Action::Move { distance } => {}
30// Action::Stop => {} 34// Action::Stop => {}
31// } 35// }
32// } 36// }
33// ``` 37// ```
34pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option<Assist> { 38pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
35 let match_expr = ctx.find_node_at_offset::<ast::MatchExpr>()?; 39 let match_expr = ctx.find_node_at_offset::<ast::MatchExpr>()?;
36 let match_arm_list = match_expr.match_arm_list()?; 40 let match_arm_list = match_expr.match_arm_list()?;
37 41
@@ -49,12 +53,18 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option<Assist> {
49 let missing_arms: Vec<MatchArm> = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) { 53 let missing_arms: Vec<MatchArm> = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) {
50 let variants = enum_def.variants(ctx.db); 54 let variants = enum_def.variants(ctx.db);
51 55
52 variants 56 let mut variants = variants
53 .into_iter() 57 .into_iter()
54 .filter_map(|variant| build_pat(ctx.db, module, variant)) 58 .filter_map(|variant| build_pat(ctx.db, module, variant))
55 .filter(|variant_pat| is_variant_missing(&mut arms, variant_pat)) 59 .filter(|variant_pat| is_variant_missing(&mut arms, variant_pat))
56 .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) 60 .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block()))
57 .collect() 61 .collect::<Vec<_>>();
62 if Some(enum_def) == FamousDefs(&ctx.sema, module.krate()).core_option_Option() {
63 // Match `Some` variant first.
64 mark::hit!(option_order);
65 variants.reverse()
66 }
67 variants
58 } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) { 68 } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) {
59 // Partial fill not currently supported for tuple of enums. 69 // Partial fill not currently supported for tuple of enums.
60 if !arms.is_empty() { 70 if !arms.is_empty() {
@@ -92,12 +102,24 @@ pub(crate) fn fill_match_arms(ctx: AssistCtx) -> Option<Assist> {
92 return None; 102 return None;
93 } 103 }
94 104
95 ctx.add_assist(AssistId("fill_match_arms"), "Fill match arms", |edit| { 105 let target = match_expr.syntax().text_range();
96 let new_arm_list = match_arm_list.remove_placeholder().append_arms(missing_arms); 106 acc.add(AssistId("fill_match_arms"), "Fill match arms", target, |builder| {
97 107 let new_arm_list = match_arm_list.remove_placeholder();
98 edit.target(match_expr.syntax().text_range()); 108 let n_old_arms = new_arm_list.arms().count();
99 edit.set_cursor(expr.syntax().text_range().start()); 109 let new_arm_list = new_arm_list.append_arms(missing_arms);
100 edit.replace_ast(match_arm_list, new_arm_list); 110 let first_new_arm = new_arm_list.arms().nth(n_old_arms);
111 let old_range = match_arm_list.syntax().text_range();
112 match (first_new_arm, ctx.config.snippet_cap) {
113 (Some(first_new_arm), Some(cap)) => {
114 let snippet = render_snippet(
115 cap,
116 new_arm_list.syntax(),
117 Cursor::Before(first_new_arm.syntax()),
118 );
119 builder.replace_snippet(cap, old_range, snippet);
120 }
121 _ => builder.replace(old_range, new_arm_list.to_string()),
122 }
101 }) 123 })
102} 124}
103 125
@@ -168,7 +190,12 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> O
168 190
169#[cfg(test)] 191#[cfg(test)]
170mod tests { 192mod tests {
171 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 193 use test_utils::mark;
194
195 use crate::{
196 tests::{check_assist, check_assist_not_applicable, check_assist_target},
197 utils::FamousDefs,
198 };
172 199
173 use super::fill_match_arms; 200 use super::fill_match_arms;
174 201
@@ -215,12 +242,12 @@ mod tests {
215 r#" 242 r#"
216 enum A { 243 enum A {
217 As, 244 As,
218 Bs{x:i32, y:Option<i32>}, 245 Bs { x: i32, y: Option<i32> },
219 Cs(i32, Option<i32>), 246 Cs(i32, Option<i32>),
220 } 247 }
221 fn main() { 248 fn main() {
222 match A::As<|> { 249 match A::As<|> {
223 A::Bs{x,y:Some(_)} => {} 250 A::Bs { x, y: Some(_) } => {}
224 A::Cs(_, Some(_)) => {} 251 A::Cs(_, Some(_)) => {}
225 } 252 }
226 } 253 }
@@ -228,14 +255,14 @@ mod tests {
228 r#" 255 r#"
229 enum A { 256 enum A {
230 As, 257 As,
231 Bs{x:i32, y:Option<i32>}, 258 Bs { x: i32, y: Option<i32> },
232 Cs(i32, Option<i32>), 259 Cs(i32, Option<i32>),
233 } 260 }
234 fn main() { 261 fn main() {
235 match <|>A::As { 262 match A::As {
236 A::Bs{x,y:Some(_)} => {} 263 A::Bs { x, y: Some(_) } => {}
237 A::Cs(_, Some(_)) => {} 264 A::Cs(_, Some(_)) => {}
238 A::As => {} 265 $0A::As => {}
239 } 266 }
240 } 267 }
241 "#, 268 "#,
@@ -265,9 +292,9 @@ mod tests {
265 Cs(Option<i32>), 292 Cs(Option<i32>),
266 } 293 }
267 fn main() { 294 fn main() {
268 match <|>A::As { 295 match A::As {
269 A::Cs(_) | A::Bs => {} 296 A::Cs(_) | A::Bs => {}
270 A::As => {} 297 $0A::As => {}
271 } 298 }
272 } 299 }
273 "#, 300 "#,
@@ -311,11 +338,11 @@ mod tests {
311 Ys, 338 Ys,
312 } 339 }
313 fn main() { 340 fn main() {
314 match <|>A::As { 341 match A::As {
315 A::Bs if 0 < 1 => {} 342 A::Bs if 0 < 1 => {}
316 A::Ds(_value) => { let x = 1; } 343 A::Ds(_value) => { let x = 1; }
317 A::Es(B::Xs) => (), 344 A::Es(B::Xs) => (),
318 A::As => {} 345 $0A::As => {}
319 A::Cs => {} 346 A::Cs => {}
320 } 347 }
321 } 348 }
@@ -333,7 +360,7 @@ mod tests {
333 Bs, 360 Bs,
334 Cs(String), 361 Cs(String),
335 Ds(String, String), 362 Ds(String, String),
336 Es{ x: usize, y: usize } 363 Es { x: usize, y: usize }
337 } 364 }
338 365
339 fn main() { 366 fn main() {
@@ -347,13 +374,13 @@ mod tests {
347 Bs, 374 Bs,
348 Cs(String), 375 Cs(String),
349 Ds(String, String), 376 Ds(String, String),
350 Es{ x: usize, y: usize } 377 Es { x: usize, y: usize }
351 } 378 }
352 379
353 fn main() { 380 fn main() {
354 let a = A::As; 381 let a = A::As;
355 match <|>a { 382 match a {
356 A::As => {} 383 $0A::As => {}
357 A::Bs => {} 384 A::Bs => {}
358 A::Cs(_) => {} 385 A::Cs(_) => {}
359 A::Ds(_, _) => {} 386 A::Ds(_, _) => {}
@@ -369,14 +396,8 @@ mod tests {
369 check_assist( 396 check_assist(
370 fill_match_arms, 397 fill_match_arms,
371 r#" 398 r#"
372 enum A { 399 enum A { One, Two }
373 One, 400 enum B { One, Two }
374 Two,
375 }
376 enum B {
377 One,
378 Two,
379 }
380 401
381 fn main() { 402 fn main() {
382 let a = A::One; 403 let a = A::One;
@@ -385,20 +406,14 @@ mod tests {
385 } 406 }
386 "#, 407 "#,
387 r#" 408 r#"
388 enum A { 409 enum A { One, Two }
389 One, 410 enum B { One, Two }
390 Two,
391 }
392 enum B {
393 One,
394 Two,
395 }
396 411
397 fn main() { 412 fn main() {
398 let a = A::One; 413 let a = A::One;
399 let b = B::One; 414 let b = B::One;
400 match <|>(a, b) { 415 match (a, b) {
401 (A::One, B::One) => {} 416 $0(A::One, B::One) => {}
402 (A::One, B::Two) => {} 417 (A::One, B::Two) => {}
403 (A::Two, B::One) => {} 418 (A::Two, B::One) => {}
404 (A::Two, B::Two) => {} 419 (A::Two, B::Two) => {}
@@ -413,14 +428,8 @@ mod tests {
413 check_assist( 428 check_assist(
414 fill_match_arms, 429 fill_match_arms,
415 r#" 430 r#"
416 enum A { 431 enum A { One, Two }
417 One, 432 enum B { One, Two }
418 Two,
419 }
420 enum B {
421 One,
422 Two,
423 }
424 433
425 fn main() { 434 fn main() {
426 let a = A::One; 435 let a = A::One;
@@ -429,20 +438,14 @@ mod tests {
429 } 438 }
430 "#, 439 "#,
431 r#" 440 r#"
432 enum A { 441 enum A { One, Two }
433 One, 442 enum B { One, Two }
434 Two,
435 }
436 enum B {
437 One,
438 Two,
439 }
440 443
441 fn main() { 444 fn main() {
442 let a = A::One; 445 let a = A::One;
443 let b = B::One; 446 let b = B::One;
444 match <|>(&a, &b) { 447 match (&a, &b) {
445 (A::One, B::One) => {} 448 $0(A::One, B::One) => {}
446 (A::One, B::Two) => {} 449 (A::One, B::Two) => {}
447 (A::Two, B::One) => {} 450 (A::Two, B::One) => {}
448 (A::Two, B::Two) => {} 451 (A::Two, B::Two) => {}
@@ -457,14 +460,8 @@ mod tests {
457 check_assist_not_applicable( 460 check_assist_not_applicable(
458 fill_match_arms, 461 fill_match_arms,
459 r#" 462 r#"
460 enum A { 463 enum A { One, Two }
461 One, 464 enum B { One, Two }
462 Two,
463 }
464 enum B {
465 One,
466 Two,
467 }
468 465
469 fn main() { 466 fn main() {
470 let a = A::One; 467 let a = A::One;
@@ -482,14 +479,8 @@ mod tests {
482 check_assist_not_applicable( 479 check_assist_not_applicable(
483 fill_match_arms, 480 fill_match_arms,
484 r#" 481 r#"
485 enum A { 482 enum A { One, Two }
486 One, 483 enum B { One, Two }
487 Two,
488 }
489 enum B {
490 One,
491 Two,
492 }
493 484
494 fn main() { 485 fn main() {
495 let a = A::One; 486 let a = A::One;
@@ -513,10 +504,7 @@ mod tests {
513 check_assist_not_applicable( 504 check_assist_not_applicable(
514 fill_match_arms, 505 fill_match_arms,
515 r#" 506 r#"
516 enum A { 507 enum A { One, Two }
517 One,
518 Two,
519 }
520 508
521 fn main() { 509 fn main() {
522 let a = A::One; 510 let a = A::One;
@@ -532,9 +520,7 @@ mod tests {
532 check_assist( 520 check_assist(
533 fill_match_arms, 521 fill_match_arms,
534 r#" 522 r#"
535 enum A { 523 enum A { As }
536 As,
537 }
538 524
539 fn foo(a: &A) { 525 fn foo(a: &A) {
540 match a<|> { 526 match a<|> {
@@ -542,13 +528,11 @@ mod tests {
542 } 528 }
543 "#, 529 "#,
544 r#" 530 r#"
545 enum A { 531 enum A { As }
546 As,
547 }
548 532
549 fn foo(a: &A) { 533 fn foo(a: &A) {
550 match <|>a { 534 match a {
551 A::As => {} 535 $0A::As => {}
552 } 536 }
553 } 537 }
554 "#, 538 "#,
@@ -558,7 +542,7 @@ mod tests {
558 fill_match_arms, 542 fill_match_arms,
559 r#" 543 r#"
560 enum A { 544 enum A {
561 Es{ x: usize, y: usize } 545 Es { x: usize, y: usize }
562 } 546 }
563 547
564 fn foo(a: &mut A) { 548 fn foo(a: &mut A) {
@@ -568,12 +552,12 @@ mod tests {
568 "#, 552 "#,
569 r#" 553 r#"
570 enum A { 554 enum A {
571 Es{ x: usize, y: usize } 555 Es { x: usize, y: usize }
572 } 556 }
573 557
574 fn foo(a: &mut A) { 558 fn foo(a: &mut A) {
575 match <|>a { 559 match a {
576 A::Es { x, y } => {} 560 $0A::Es { x, y } => {}
577 } 561 }
578 } 562 }
579 "#, 563 "#,
@@ -612,8 +596,8 @@ mod tests {
612 enum E { X, Y } 596 enum E { X, Y }
613 597
614 fn main() { 598 fn main() {
615 match <|>E::X { 599 match E::X {
616 E::X => {} 600 $0E::X => {}
617 E::Y => {} 601 E::Y => {}
618 } 602 }
619 } 603 }
@@ -640,8 +624,8 @@ mod tests {
640 use foo::E::X; 624 use foo::E::X;
641 625
642 fn main() { 626 fn main() {
643 match <|>X { 627 match X {
644 X => {} 628 $0X => {}
645 foo::E::Y => {} 629 foo::E::Y => {}
646 } 630 }
647 } 631 }
@@ -654,10 +638,7 @@ mod tests {
654 check_assist( 638 check_assist(
655 fill_match_arms, 639 fill_match_arms,
656 r#" 640 r#"
657 enum A { 641 enum A { One, Two }
658 One,
659 Two,
660 }
661 fn foo(a: A) { 642 fn foo(a: A) {
662 match a { 643 match a {
663 // foo bar baz<|> 644 // foo bar baz<|>
@@ -667,16 +648,13 @@ mod tests {
667 } 648 }
668 "#, 649 "#,
669 r#" 650 r#"
670 enum A { 651 enum A { One, Two }
671 One,
672 Two,
673 }
674 fn foo(a: A) { 652 fn foo(a: A) {
675 match <|>a { 653 match a {
676 // foo bar baz 654 // foo bar baz
677 A::One => {} 655 A::One => {}
678 // This is where the rest should be 656 // This is where the rest should be
679 A::Two => {} 657 $0A::Two => {}
680 } 658 }
681 } 659 }
682 "#, 660 "#,
@@ -688,10 +666,7 @@ mod tests {
688 check_assist( 666 check_assist(
689 fill_match_arms, 667 fill_match_arms,
690 r#" 668 r#"
691 enum A { 669 enum A { One, Two }
692 One,
693 Two,
694 }
695 fn foo(a: A) { 670 fn foo(a: A) {
696 match a { 671 match a {
697 // foo bar baz<|> 672 // foo bar baz<|>
@@ -699,14 +674,11 @@ mod tests {
699 } 674 }
700 "#, 675 "#,
701 r#" 676 r#"
702 enum A { 677 enum A { One, Two }
703 One,
704 Two,
705 }
706 fn foo(a: A) { 678 fn foo(a: A) {
707 match <|>a { 679 match a {
708 // foo bar baz 680 // foo bar baz
709 A::One => {} 681 $0A::One => {}
710 A::Two => {} 682 A::Two => {}
711 } 683 }
712 } 684 }
@@ -729,12 +701,37 @@ mod tests {
729 r#" 701 r#"
730 enum A { One, Two, } 702 enum A { One, Two, }
731 fn foo(a: A) { 703 fn foo(a: A) {
732 match <|>a { 704 match a {
733 A::One => {} 705 $0A::One => {}
734 A::Two => {} 706 A::Two => {}
735 } 707 }
736 } 708 }
737 "#, 709 "#,
738 ); 710 );
739 } 711 }
712
713 #[test]
714 fn option_order() {
715 mark::check!(option_order);
716 let before = r#"
717fn foo(opt: Option<i32>) {
718 match opt<|> {
719 }
720}"#;
721 let before =
722 &format!("//- main.rs crate:main deps:core\n{}{}", before, FamousDefs::FIXTURE);
723
724 check_assist(
725 fill_match_arms,
726 before,
727 r#"
728fn foo(opt: Option<i32>) {
729 match opt {
730 $0Some(_) => {}
731 None => {}
732 }
733}
734"#,
735 );
736 }
740} 737}
diff --git a/crates/ra_assists/src/handlers/fix_visibility.rs b/crates/ra_assists/src/handlers/fix_visibility.rs
new file mode 100644
index 000000000..9ec42f568
--- /dev/null
+++ b/crates/ra_assists/src/handlers/fix_visibility.rs
@@ -0,0 +1,559 @@
1use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution};
2use ra_db::FileId;
3use ra_syntax::{
4 ast, AstNode,
5 SyntaxKind::{ATTR, COMMENT, WHITESPACE},
6 SyntaxNode, TextRange, TextSize,
7};
8
9use crate::{AssistContext, AssistId, Assists};
10
11// FIXME: this really should be a fix for diagnostic, rather than an assist.
12
13// Assist: fix_visibility
14//
15// Makes inaccessible item public.
16//
17// ```
18// mod m {
19// fn frobnicate() {}
20// }
21// fn main() {
22// m::frobnicate<|>() {}
23// }
24// ```
25// ->
26// ```
27// mod m {
28// $0pub(crate) fn frobnicate() {}
29// }
30// fn main() {
31// m::frobnicate() {}
32// }
33// ```
34pub(crate) fn fix_visibility(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
35 add_vis_to_referenced_module_def(acc, ctx)
36 .or_else(|| add_vis_to_referenced_record_field(acc, ctx))
37}
38
39fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
40 let path: ast::Path = ctx.find_node_at_offset()?;
41 let path_res = ctx.sema.resolve_path(&path)?;
42 let def = match path_res {
43 PathResolution::Def(def) => def,
44 _ => return None,
45 };
46
47 let current_module = ctx.sema.scope(&path.syntax()).module()?;
48 let target_module = def.module(ctx.db)?;
49
50 let vis = target_module.visibility_of(ctx.db, &def)?;
51 if vis.is_visible_from(ctx.db, current_module.into()) {
52 return None;
53 };
54
55 let (offset, target, target_file, target_name) = target_data_for_def(ctx.db, def)?;
56
57 let missing_visibility =
58 if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" };
59
60 let assist_label = match target_name {
61 None => format!("Change visibility to {}", missing_visibility),
62 Some(name) => format!("Change visibility of {} to {}", name, missing_visibility),
63 };
64
65 acc.add(AssistId("fix_visibility"), assist_label, target, |builder| {
66 builder.set_file(target_file);
67 match ctx.config.snippet_cap {
68 Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)),
69 None => builder.insert(offset, format!("{} ", missing_visibility)),
70 }
71 })
72}
73
74fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
75 let record_field: ast::RecordField = ctx.find_node_at_offset()?;
76 let (record_field_def, _) = ctx.sema.resolve_record_field(&record_field)?;
77
78 let current_module = ctx.sema.scope(record_field.syntax()).module()?;
79 let visibility = record_field_def.visibility(ctx.db);
80 if visibility.is_visible_from(ctx.db, current_module.into()) {
81 return None;
82 }
83
84 let parent = record_field_def.parent_def(ctx.db);
85 let parent_name = parent.name(ctx.db);
86 let target_module = parent.module(ctx.db);
87
88 let in_file_source = record_field_def.source(ctx.db);
89 let (offset, target) = match in_file_source.value {
90 hir::FieldSource::Named(it) => {
91 let s = it.syntax();
92 (vis_offset(s), s.text_range())
93 }
94 hir::FieldSource::Pos(it) => {
95 let s = it.syntax();
96 (vis_offset(s), s.text_range())
97 }
98 };
99
100 let missing_visibility =
101 if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" };
102 let target_file = in_file_source.file_id.original_file(ctx.db);
103
104 let target_name = record_field_def.name(ctx.db);
105 let assist_label =
106 format!("Change visibility of {}.{} to {}", parent_name, target_name, missing_visibility);
107
108 acc.add(AssistId("fix_visibility"), assist_label, target, |builder| {
109 builder.set_file(target_file);
110 match ctx.config.snippet_cap {
111 Some(cap) => builder.insert_snippet(cap, offset, format!("$0{} ", missing_visibility)),
112 None => builder.insert(offset, format!("{} ", missing_visibility)),
113 }
114 })
115}
116
117fn target_data_for_def(
118 db: &dyn HirDatabase,
119 def: hir::ModuleDef,
120) -> Option<(TextSize, TextRange, FileId, Option<hir::Name>)> {
121 fn offset_target_and_file_id<S, Ast>(
122 db: &dyn HirDatabase,
123 x: S,
124 ) -> (TextSize, TextRange, FileId)
125 where
126 S: HasSource<Ast = Ast>,
127 Ast: AstNode,
128 {
129 let source = x.source(db);
130 let in_file_syntax = source.syntax();
131 let file_id = in_file_syntax.file_id;
132 let syntax = in_file_syntax.value;
133 (vis_offset(syntax), syntax.text_range(), file_id.original_file(db.upcast()))
134 }
135
136 let target_name;
137 let (offset, target, target_file) = match def {
138 hir::ModuleDef::Function(f) => {
139 target_name = Some(f.name(db));
140 offset_target_and_file_id(db, f)
141 }
142 hir::ModuleDef::Adt(adt) => {
143 target_name = Some(adt.name(db));
144 match adt {
145 hir::Adt::Struct(s) => offset_target_and_file_id(db, s),
146 hir::Adt::Union(u) => offset_target_and_file_id(db, u),
147 hir::Adt::Enum(e) => offset_target_and_file_id(db, e),
148 }
149 }
150 hir::ModuleDef::Const(c) => {
151 target_name = c.name(db);
152 offset_target_and_file_id(db, c)
153 }
154 hir::ModuleDef::Static(s) => {
155 target_name = s.name(db);
156 offset_target_and_file_id(db, s)
157 }
158 hir::ModuleDef::Trait(t) => {
159 target_name = Some(t.name(db));
160 offset_target_and_file_id(db, t)
161 }
162 hir::ModuleDef::TypeAlias(t) => {
163 target_name = Some(t.name(db));
164 offset_target_and_file_id(db, t)
165 }
166 hir::ModuleDef::Module(m) => {
167 target_name = m.name(db);
168 let in_file_source = m.declaration_source(db)?;
169 let file_id = in_file_source.file_id.original_file(db.upcast());
170 let syntax = in_file_source.value.syntax();
171 (vis_offset(syntax), syntax.text_range(), file_id)
172 }
173 // Enum variants can't be private, we can't modify builtin types
174 hir::ModuleDef::EnumVariant(_) | hir::ModuleDef::BuiltinType(_) => return None,
175 };
176
177 Some((offset, target, target_file, target_name))
178}
179
180fn vis_offset(node: &SyntaxNode) -> TextSize {
181 node.children_with_tokens()
182 .skip_while(|it| match it.kind() {
183 WHITESPACE | COMMENT | ATTR => true,
184 _ => false,
185 })
186 .next()
187 .map(|it| it.text_range().start())
188 .unwrap_or_else(|| node.text_range().start())
189}
190
191#[cfg(test)]
192mod tests {
193 use crate::tests::{check_assist, check_assist_not_applicable};
194
195 use super::*;
196
197 #[test]
198 fn fix_visibility_of_fn() {
199 check_assist(
200 fix_visibility,
201 r"mod foo { fn foo() {} }
202 fn main() { foo::foo<|>() } ",
203 r"mod foo { $0pub(crate) fn foo() {} }
204 fn main() { foo::foo() } ",
205 );
206 check_assist_not_applicable(
207 fix_visibility,
208 r"mod foo { pub fn foo() {} }
209 fn main() { foo::foo<|>() } ",
210 )
211 }
212
213 #[test]
214 fn fix_visibility_of_adt_in_submodule() {
215 check_assist(
216 fix_visibility,
217 r"mod foo { struct Foo; }
218 fn main() { foo::Foo<|> } ",
219 r"mod foo { $0pub(crate) struct Foo; }
220 fn main() { foo::Foo } ",
221 );
222 check_assist_not_applicable(
223 fix_visibility,
224 r"mod foo { pub struct Foo; }
225 fn main() { foo::Foo<|> } ",
226 );
227 check_assist(
228 fix_visibility,
229 r"mod foo { enum Foo; }
230 fn main() { foo::Foo<|> } ",
231 r"mod foo { $0pub(crate) enum Foo; }
232 fn main() { foo::Foo } ",
233 );
234 check_assist_not_applicable(
235 fix_visibility,
236 r"mod foo { pub enum Foo; }
237 fn main() { foo::Foo<|> } ",
238 );
239 check_assist(
240 fix_visibility,
241 r"mod foo { union Foo; }
242 fn main() { foo::Foo<|> } ",
243 r"mod foo { $0pub(crate) union Foo; }
244 fn main() { foo::Foo } ",
245 );
246 check_assist_not_applicable(
247 fix_visibility,
248 r"mod foo { pub union Foo; }
249 fn main() { foo::Foo<|> } ",
250 );
251 }
252
253 #[test]
254 fn fix_visibility_of_adt_in_other_file() {
255 check_assist(
256 fix_visibility,
257 r"
258 //- /main.rs
259 mod foo;
260 fn main() { foo::Foo<|> }
261
262 //- /foo.rs
263 struct Foo;
264 ",
265 r"$0pub(crate) struct Foo;
266
267",
268 );
269 }
270
271 #[test]
272 fn fix_visibility_of_struct_field() {
273 check_assist(
274 fix_visibility,
275 r"mod foo { pub struct Foo { bar: (), } }
276 fn main() { foo::Foo { <|>bar: () }; } ",
277 r"mod foo { pub struct Foo { $0pub(crate) bar: (), } }
278 fn main() { foo::Foo { bar: () }; } ",
279 );
280 check_assist(
281 fix_visibility,
282 r"//- /lib.rs
283 mod foo;
284 fn main() { foo::Foo { <|>bar: () }; }
285 //- /foo.rs
286 pub struct Foo { bar: () }
287 ",
288 r"pub struct Foo { $0pub(crate) bar: () }
289
290",
291 );
292 check_assist_not_applicable(
293 fix_visibility,
294 r"mod foo { pub struct Foo { pub bar: (), } }
295 fn main() { foo::Foo { <|>bar: () }; } ",
296 );
297 check_assist_not_applicable(
298 fix_visibility,
299 r"//- /lib.rs
300 mod foo;
301 fn main() { foo::Foo { <|>bar: () }; }
302 //- /foo.rs
303 pub struct Foo { pub bar: () }
304 ",
305 );
306 }
307
308 #[test]
309 fn fix_visibility_of_enum_variant_field() {
310 check_assist(
311 fix_visibility,
312 r"mod foo { pub enum Foo { Bar { bar: () } } }
313 fn main() { foo::Foo::Bar { <|>bar: () }; } ",
314 r"mod foo { pub enum Foo { Bar { $0pub(crate) bar: () } } }
315 fn main() { foo::Foo::Bar { bar: () }; } ",
316 );
317 check_assist(
318 fix_visibility,
319 r"//- /lib.rs
320 mod foo;
321 fn main() { foo::Foo::Bar { <|>bar: () }; }
322 //- /foo.rs
323 pub enum Foo { Bar { bar: () } }
324 ",
325 r"pub enum Foo { Bar { $0pub(crate) bar: () } }
326
327",
328 );
329 check_assist_not_applicable(
330 fix_visibility,
331 r"mod foo { pub struct Foo { pub bar: (), } }
332 fn main() { foo::Foo { <|>bar: () }; } ",
333 );
334 check_assist_not_applicable(
335 fix_visibility,
336 r"//- /lib.rs
337 mod foo;
338 fn main() { foo::Foo { <|>bar: () }; }
339 //- /foo.rs
340 pub struct Foo { pub bar: () }
341 ",
342 );
343 }
344
345 #[test]
346 #[ignore]
347 // FIXME reenable this test when `Semantics::resolve_record_field` works with union fields
348 fn fix_visibility_of_union_field() {
349 check_assist(
350 fix_visibility,
351 r"mod foo { pub union Foo { bar: (), } }
352 fn main() { foo::Foo { <|>bar: () }; } ",
353 r"mod foo { pub union Foo { $0pub(crate) bar: (), } }
354 fn main() { foo::Foo { bar: () }; } ",
355 );
356 check_assist(
357 fix_visibility,
358 r"//- /lib.rs
359 mod foo;
360 fn main() { foo::Foo { <|>bar: () }; }
361 //- /foo.rs
362 pub union Foo { bar: () }
363 ",
364 r"pub union Foo { $0pub(crate) bar: () }
365
366",
367 );
368 check_assist_not_applicable(
369 fix_visibility,
370 r"mod foo { pub union Foo { pub bar: (), } }
371 fn main() { foo::Foo { <|>bar: () }; } ",
372 );
373 check_assist_not_applicable(
374 fix_visibility,
375 r"//- /lib.rs
376 mod foo;
377 fn main() { foo::Foo { <|>bar: () }; }
378 //- /foo.rs
379 pub union Foo { pub bar: () }
380 ",
381 );
382 }
383
384 #[test]
385 fn fix_visibility_of_const() {
386 check_assist(
387 fix_visibility,
388 r"mod foo { const FOO: () = (); }
389 fn main() { foo::FOO<|> } ",
390 r"mod foo { $0pub(crate) const FOO: () = (); }
391 fn main() { foo::FOO } ",
392 );
393 check_assist_not_applicable(
394 fix_visibility,
395 r"mod foo { pub const FOO: () = (); }
396 fn main() { foo::FOO<|> } ",
397 );
398 }
399
400 #[test]
401 fn fix_visibility_of_static() {
402 check_assist(
403 fix_visibility,
404 r"mod foo { static FOO: () = (); }
405 fn main() { foo::FOO<|> } ",
406 r"mod foo { $0pub(crate) static FOO: () = (); }
407 fn main() { foo::FOO } ",
408 );
409 check_assist_not_applicable(
410 fix_visibility,
411 r"mod foo { pub static FOO: () = (); }
412 fn main() { foo::FOO<|> } ",
413 );
414 }
415
416 #[test]
417 fn fix_visibility_of_trait() {
418 check_assist(
419 fix_visibility,
420 r"mod foo { trait Foo { fn foo(&self) {} } }
421 fn main() { let x: &dyn foo::<|>Foo; } ",
422 r"mod foo { $0pub(crate) trait Foo { fn foo(&self) {} } }
423 fn main() { let x: &dyn foo::Foo; } ",
424 );
425 check_assist_not_applicable(
426 fix_visibility,
427 r"mod foo { pub trait Foo { fn foo(&self) {} } }
428 fn main() { let x: &dyn foo::Foo<|>; } ",
429 );
430 }
431
432 #[test]
433 fn fix_visibility_of_type_alias() {
434 check_assist(
435 fix_visibility,
436 r"mod foo { type Foo = (); }
437 fn main() { let x: foo::Foo<|>; } ",
438 r"mod foo { $0pub(crate) type Foo = (); }
439 fn main() { let x: foo::Foo; } ",
440 );
441 check_assist_not_applicable(
442 fix_visibility,
443 r"mod foo { pub type Foo = (); }
444 fn main() { let x: foo::Foo<|>; } ",
445 );
446 }
447
448 #[test]
449 fn fix_visibility_of_module() {
450 check_assist(
451 fix_visibility,
452 r"mod foo { mod bar { fn bar() {} } }
453 fn main() { foo::bar<|>::bar(); } ",
454 r"mod foo { $0pub(crate) mod bar { fn bar() {} } }
455 fn main() { foo::bar::bar(); } ",
456 );
457
458 check_assist(
459 fix_visibility,
460 r"
461 //- /main.rs
462 mod foo;
463 fn main() { foo::bar<|>::baz(); }
464
465 //- /foo.rs
466 mod bar {
467 pub fn baz() {}
468 }
469 ",
470 r"$0pub(crate) mod bar {
471 pub fn baz() {}
472}
473
474",
475 );
476
477 check_assist_not_applicable(
478 fix_visibility,
479 r"mod foo { pub mod bar { pub fn bar() {} } }
480 fn main() { foo::bar<|>::bar(); } ",
481 );
482 }
483
484 #[test]
485 fn fix_visibility_of_inline_module_in_other_file() {
486 check_assist(
487 fix_visibility,
488 r"
489 //- /main.rs
490 mod foo;
491 fn main() { foo::bar<|>::baz(); }
492
493 //- /foo.rs
494 mod bar;
495
496 //- /foo/bar.rs
497 pub fn baz() {}
498 }
499 ",
500 r"$0pub(crate) mod bar;
501",
502 );
503 }
504
505 #[test]
506 fn fix_visibility_of_module_declaration_in_other_file() {
507 check_assist(
508 fix_visibility,
509 r"//- /main.rs
510 mod foo;
511 fn main() { foo::bar<|>>::baz(); }
512
513 //- /foo.rs
514 mod bar {
515 pub fn baz() {}
516 }",
517 r"$0pub(crate) mod bar {
518 pub fn baz() {}
519}
520",
521 );
522 }
523
524 #[test]
525 fn adds_pub_when_target_is_in_another_crate() {
526 check_assist(
527 fix_visibility,
528 r"//- /main.rs crate:a deps:foo
529 foo::Bar<|>
530 //- /lib.rs crate:foo
531 struct Bar;",
532 r"$0pub struct Bar;
533",
534 )
535 }
536
537 #[test]
538 #[ignore]
539 // FIXME handle reexports properly
540 fn fix_visibility_of_reexport() {
541 check_assist(
542 fix_visibility,
543 r"
544 mod foo {
545 use bar::Baz;
546 mod bar { pub(super) struct Baz; }
547 }
548 foo::Baz<|>
549 ",
550 r"
551 mod foo {
552 $0pub(crate) use bar::Baz;
553 mod bar { pub(super) struct Baz; }
554 }
555 foo::Baz
556 ",
557 )
558 }
559}
diff --git a/crates/ra_assists/src/handlers/flip_binexpr.rs b/crates/ra_assists/src/handlers/flip_binexpr.rs
index 8030efb35..573196576 100644
--- a/crates/ra_assists/src/handlers/flip_binexpr.rs
+++ b/crates/ra_assists/src/handlers/flip_binexpr.rs
@@ -1,6 +1,6 @@
1use ra_syntax::ast::{AstNode, BinExpr, BinOp}; 1use ra_syntax::ast::{AstNode, BinExpr, BinOp};
2 2
3use crate::{Assist, AssistCtx, AssistId}; 3use crate::{AssistContext, AssistId, Assists};
4 4
5// Assist: flip_binexpr 5// Assist: flip_binexpr
6// 6//
@@ -17,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
17// let _ = 2 + 90; 17// let _ = 2 + 90;
18// } 18// }
19// ``` 19// ```
20pub(crate) fn flip_binexpr(ctx: AssistCtx) -> Option<Assist> { 20pub(crate) fn flip_binexpr(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
21 let expr = ctx.find_node_at_offset::<BinExpr>()?; 21 let expr = ctx.find_node_at_offset::<BinExpr>()?;
22 let lhs = expr.lhs()?.syntax().clone(); 22 let lhs = expr.lhs()?.syntax().clone();
23 let rhs = expr.rhs()?.syntax().clone(); 23 let rhs = expr.rhs()?.syntax().clone();
@@ -33,8 +33,7 @@ pub(crate) fn flip_binexpr(ctx: AssistCtx) -> Option<Assist> {
33 return None; 33 return None;
34 } 34 }
35 35
36 ctx.add_assist(AssistId("flip_binexpr"), "Flip binary expression", |edit| { 36 acc.add(AssistId("flip_binexpr"), "Flip binary expression", op_range, |edit| {
37 edit.target(op_range);
38 if let FlipAction::FlipAndReplaceOp(new_op) = action { 37 if let FlipAction::FlipAndReplaceOp(new_op) = action {
39 edit.replace(op_range, new_op); 38 edit.replace(op_range, new_op);
40 } 39 }
@@ -69,7 +68,7 @@ impl From<BinOp> for FlipAction {
69mod tests { 68mod tests {
70 use super::*; 69 use super::*;
71 70
72 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 71 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
73 72
74 #[test] 73 #[test]
75 fn flip_binexpr_target_is_the_op() { 74 fn flip_binexpr_target_is_the_op() {
@@ -86,17 +85,13 @@ mod tests {
86 check_assist( 85 check_assist(
87 flip_binexpr, 86 flip_binexpr,
88 "fn f() { let res = 1 ==<|> 2; }", 87 "fn f() { let res = 1 ==<|> 2; }",
89 "fn f() { let res = 2 ==<|> 1; }", 88 "fn f() { let res = 2 == 1; }",
90 ) 89 )
91 } 90 }
92 91
93 #[test] 92 #[test]
94 fn flip_binexpr_works_for_gt() { 93 fn flip_binexpr_works_for_gt() {
95 check_assist( 94 check_assist(flip_binexpr, "fn f() { let res = 1 ><|> 2; }", "fn f() { let res = 2 < 1; }")
96 flip_binexpr,
97 "fn f() { let res = 1 ><|> 2; }",
98 "fn f() { let res = 2 <<|> 1; }",
99 )
100 } 95 }
101 96
102 #[test] 97 #[test]
@@ -104,7 +99,7 @@ mod tests {
104 check_assist( 99 check_assist(
105 flip_binexpr, 100 flip_binexpr,
106 "fn f() { let res = 1 <=<|> 2; }", 101 "fn f() { let res = 1 <=<|> 2; }",
107 "fn f() { let res = 2 >=<|> 1; }", 102 "fn f() { let res = 2 >= 1; }",
108 ) 103 )
109 } 104 }
110 105
@@ -113,7 +108,7 @@ mod tests {
113 check_assist( 108 check_assist(
114 flip_binexpr, 109 flip_binexpr,
115 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }", 110 "fn f() { let res = (1 + 1) ==<|> (2 + 2); }",
116 "fn f() { let res = (2 + 2) ==<|> (1 + 1); }", 111 "fn f() { let res = (2 + 2) == (1 + 1); }",
117 ) 112 )
118 } 113 }
119 114
@@ -133,7 +128,7 @@ mod tests {
133 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool { 128 fn dyn_eq(&self, other: &dyn Diagnostic) -> bool {
134 match other.downcast_ref::<Self>() { 129 match other.downcast_ref::<Self>() {
135 None => false, 130 None => false,
136 Some(it) => self ==<|> it, 131 Some(it) => self == it,
137 } 132 }
138 } 133 }
139 "#, 134 "#,
diff --git a/crates/ra_assists/src/handlers/flip_comma.rs b/crates/ra_assists/src/handlers/flip_comma.rs
index 1dacf29f8..a57a1c463 100644
--- a/crates/ra_assists/src/handlers/flip_comma.rs
+++ b/crates/ra_assists/src/handlers/flip_comma.rs
@@ -1,6 +1,6 @@
1use ra_syntax::{algo::non_trivia_sibling, Direction, T}; 1use ra_syntax::{algo::non_trivia_sibling, Direction, T};
2 2
3use crate::{Assist, AssistCtx, AssistId}; 3use crate::{AssistContext, AssistId, Assists};
4 4
5// Assist: flip_comma 5// Assist: flip_comma
6// 6//
@@ -17,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
17// ((3, 4), (1, 2)); 17// ((3, 4), (1, 2));
18// } 18// }
19// ``` 19// ```
20pub(crate) fn flip_comma(ctx: AssistCtx) -> Option<Assist> { 20pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
21 let comma = ctx.find_token_at_offset(T![,])?; 21 let comma = ctx.find_token_at_offset(T![,])?;
22 let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?; 22 let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
23 let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?; 23 let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
@@ -28,8 +28,7 @@ pub(crate) fn flip_comma(ctx: AssistCtx) -> Option<Assist> {
28 return None; 28 return None;
29 } 29 }
30 30
31 ctx.add_assist(AssistId("flip_comma"), "Flip comma", |edit| { 31 acc.add(AssistId("flip_comma"), "Flip comma", comma.text_range(), |edit| {
32 edit.target(comma.text_range());
33 edit.replace(prev.text_range(), next.to_string()); 32 edit.replace(prev.text_range(), next.to_string());
34 edit.replace(next.text_range(), prev.to_string()); 33 edit.replace(next.text_range(), prev.to_string());
35 }) 34 })
@@ -39,14 +38,14 @@ pub(crate) fn flip_comma(ctx: AssistCtx) -> Option<Assist> {
39mod tests { 38mod tests {
40 use super::*; 39 use super::*;
41 40
42 use crate::helpers::{check_assist, check_assist_target}; 41 use crate::tests::{check_assist, check_assist_target};
43 42
44 #[test] 43 #[test]
45 fn flip_comma_works_for_function_parameters() { 44 fn flip_comma_works_for_function_parameters() {
46 check_assist( 45 check_assist(
47 flip_comma, 46 flip_comma,
48 "fn foo(x: i32,<|> y: Result<(), ()>) {}", 47 "fn foo(x: i32,<|> y: Result<(), ()>) {}",
49 "fn foo(y: Result<(), ()>,<|> x: i32) {}", 48 "fn foo(y: Result<(), ()>, x: i32) {}",
50 ) 49 )
51 } 50 }
52 51
diff --git a/crates/ra_assists/src/handlers/flip_trait_bound.rs b/crates/ra_assists/src/handlers/flip_trait_bound.rs
index f56769624..0115adc8b 100644
--- a/crates/ra_assists/src/handlers/flip_trait_bound.rs
+++ b/crates/ra_assists/src/handlers/flip_trait_bound.rs
@@ -4,7 +4,7 @@ use ra_syntax::{
4 Direction, T, 4 Direction, T,
5}; 5};
6 6
7use crate::{Assist, AssistCtx, AssistId}; 7use crate::{AssistContext, AssistId, Assists};
8 8
9// Assist: flip_trait_bound 9// Assist: flip_trait_bound
10// 10//
@@ -17,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
17// ``` 17// ```
18// fn foo<T: Copy + Clone>() { } 18// fn foo<T: Copy + Clone>() { }
19// ``` 19// ```
20pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option<Assist> { 20pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
21 // We want to replicate the behavior of `flip_binexpr` by only suggesting 21 // We want to replicate the behavior of `flip_binexpr` by only suggesting
22 // the assist when the cursor is on a `+` 22 // the assist when the cursor is on a `+`
23 let plus = ctx.find_token_at_offset(T![+])?; 23 let plus = ctx.find_token_at_offset(T![+])?;
@@ -32,8 +32,8 @@ pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option<Assist> {
32 non_trivia_sibling(plus.clone().into(), Direction::Next)?, 32 non_trivia_sibling(plus.clone().into(), Direction::Next)?,
33 ); 33 );
34 34
35 ctx.add_assist(AssistId("flip_trait_bound"), "Flip trait bounds", |edit| { 35 let target = plus.text_range();
36 edit.target(plus.text_range()); 36 acc.add(AssistId("flip_trait_bound"), "Flip trait bounds", target, |edit| {
37 edit.replace(before.text_range(), after.to_string()); 37 edit.replace(before.text_range(), after.to_string());
38 edit.replace(after.text_range(), before.to_string()); 38 edit.replace(after.text_range(), before.to_string());
39 }) 39 })
@@ -43,7 +43,7 @@ pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option<Assist> {
43mod tests { 43mod tests {
44 use super::*; 44 use super::*;
45 45
46 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 46 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
47 47
48 #[test] 48 #[test]
49 fn flip_trait_bound_assist_available() { 49 fn flip_trait_bound_assist_available() {
@@ -60,7 +60,7 @@ mod tests {
60 check_assist( 60 check_assist(
61 flip_trait_bound, 61 flip_trait_bound,
62 "struct S<T> where T: A <|>+ B { }", 62 "struct S<T> where T: A <|>+ B { }",
63 "struct S<T> where T: B <|>+ A { }", 63 "struct S<T> where T: B + A { }",
64 ) 64 )
65 } 65 }
66 66
@@ -69,13 +69,13 @@ mod tests {
69 check_assist( 69 check_assist(
70 flip_trait_bound, 70 flip_trait_bound,
71 "impl X for S<T> where T: A +<|> B { }", 71 "impl X for S<T> where T: A +<|> B { }",
72 "impl X for S<T> where T: B +<|> A { }", 72 "impl X for S<T> where T: B + A { }",
73 ) 73 )
74 } 74 }
75 75
76 #[test] 76 #[test]
77 fn flip_trait_bound_works_for_fn() { 77 fn flip_trait_bound_works_for_fn() {
78 check_assist(flip_trait_bound, "fn f<T: A <|>+ B>(t: T) { }", "fn f<T: B <|>+ A>(t: T) { }") 78 check_assist(flip_trait_bound, "fn f<T: A <|>+ B>(t: T) { }", "fn f<T: B + A>(t: T) { }")
79 } 79 }
80 80
81 #[test] 81 #[test]
@@ -83,7 +83,7 @@ mod tests {
83 check_assist( 83 check_assist(
84 flip_trait_bound, 84 flip_trait_bound,
85 "fn f<T>(t: T) where T: A +<|> B { }", 85 "fn f<T>(t: T) where T: A +<|> B { }",
86 "fn f<T>(t: T) where T: B +<|> A { }", 86 "fn f<T>(t: T) where T: B + A { }",
87 ) 87 )
88 } 88 }
89 89
@@ -92,7 +92,7 @@ mod tests {
92 check_assist( 92 check_assist(
93 flip_trait_bound, 93 flip_trait_bound,
94 "fn f<T>(t: T) where T: A <|>+ 'static { }", 94 "fn f<T>(t: T) where T: A <|>+ 'static { }",
95 "fn f<T>(t: T) where T: 'static <|>+ A { }", 95 "fn f<T>(t: T) where T: 'static + A { }",
96 ) 96 )
97 } 97 }
98 98
@@ -101,7 +101,7 @@ mod tests {
101 check_assist( 101 check_assist(
102 flip_trait_bound, 102 flip_trait_bound,
103 "struct S<T> where T: A<T> <|>+ b_mod::B<T> + C<T> { }", 103 "struct S<T> where T: A<T> <|>+ b_mod::B<T> + C<T> { }",
104 "struct S<T> where T: b_mod::B<T> <|>+ A<T> + C<T> { }", 104 "struct S<T> where T: b_mod::B<T> + A<T> + C<T> { }",
105 ) 105 )
106 } 106 }
107 107
@@ -110,7 +110,7 @@ mod tests {
110 check_assist( 110 check_assist(
111 flip_trait_bound, 111 flip_trait_bound,
112 "struct S<T> where T: A + B + C + D + E + F +<|> G + H + I + J { }", 112 "struct S<T> where T: A + B + C + D + E + F +<|> G + H + I + J { }",
113 "struct S<T> where T: A + B + C + D + E + G +<|> F + H + I + J { }", 113 "struct S<T> where T: A + B + C + D + E + G + F + H + I + J { }",
114 ) 114 )
115 } 115 }
116} 116}
diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs
index f5702f6e0..d26e68847 100644
--- a/crates/ra_assists/src/handlers/inline_local_variable.rs
+++ b/crates/ra_assists/src/handlers/inline_local_variable.rs
@@ -3,9 +3,12 @@ use ra_syntax::{
3 ast::{self, AstNode, AstToken}, 3 ast::{self, AstNode, AstToken},
4 TextRange, 4 TextRange,
5}; 5};
6use test_utils::tested_by; 6use test_utils::mark;
7 7
8use crate::{assist_ctx::ActionBuilder, Assist, AssistCtx, AssistId}; 8use crate::{
9 assist_context::{AssistContext, Assists},
10 AssistId,
11};
9 12
10// Assist: inline_local_variable 13// Assist: inline_local_variable
11// 14//
@@ -23,18 +26,18 @@ use crate::{assist_ctx::ActionBuilder, Assist, AssistCtx, AssistId};
23// (1 + 2) * 4; 26// (1 + 2) * 4;
24// } 27// }
25// ``` 28// ```
26pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> { 29pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
27 let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?; 30 let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?;
28 let bind_pat = match let_stmt.pat()? { 31 let bind_pat = match let_stmt.pat()? {
29 ast::Pat::BindPat(pat) => pat, 32 ast::Pat::BindPat(pat) => pat,
30 _ => return None, 33 _ => return None,
31 }; 34 };
32 if bind_pat.mut_token().is_some() { 35 if bind_pat.mut_token().is_some() {
33 tested_by!(test_not_inline_mut_variable); 36 mark::hit!(test_not_inline_mut_variable);
34 return None; 37 return None;
35 } 38 }
36 if !bind_pat.syntax().text_range().contains_inclusive(ctx.frange.range.start()) { 39 if !bind_pat.syntax().text_range().contains_inclusive(ctx.offset()) {
37 tested_by!(not_applicable_outside_of_bind_pat); 40 mark::hit!(not_applicable_outside_of_bind_pat);
38 return None; 41 return None;
39 } 42 }
40 let initializer_expr = let_stmt.initializer()?; 43 let initializer_expr = let_stmt.initializer()?;
@@ -43,7 +46,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> {
43 let def = Definition::Local(def); 46 let def = Definition::Local(def);
44 let refs = def.find_usages(ctx.db, None); 47 let refs = def.find_usages(ctx.db, None);
45 if refs.is_empty() { 48 if refs.is_empty() {
46 tested_by!(test_not_applicable_if_variable_unused); 49 mark::hit!(test_not_applicable_if_variable_unused);
47 return None; 50 return None;
48 }; 51 };
49 52
@@ -89,6 +92,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> {
89 | (ast::Expr::ParenExpr(_), _) 92 | (ast::Expr::ParenExpr(_), _)
90 | (ast::Expr::PathExpr(_), _) 93 | (ast::Expr::PathExpr(_), _)
91 | (ast::Expr::BlockExpr(_), _) 94 | (ast::Expr::BlockExpr(_), _)
95 | (ast::Expr::EffectExpr(_), _)
92 | (_, ast::Expr::CallExpr(_)) 96 | (_, ast::Expr::CallExpr(_))
93 | (_, ast::Expr::TupleExpr(_)) 97 | (_, ast::Expr::TupleExpr(_))
94 | (_, ast::Expr::ArrayExpr(_)) 98 | (_, ast::Expr::ArrayExpr(_))
@@ -105,26 +109,21 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option<Assist> {
105 let init_str = initializer_expr.syntax().text().to_string(); 109 let init_str = initializer_expr.syntax().text().to_string();
106 let init_in_paren = format!("({})", &init_str); 110 let init_in_paren = format!("({})", &init_str);
107 111
108 ctx.add_assist( 112 let target = bind_pat.syntax().text_range();
109 AssistId("inline_local_variable"), 113 acc.add(AssistId("inline_local_variable"), "Inline variable", target, move |builder| {
110 "Inline variable", 114 builder.delete(delete_range);
111 move |edit: &mut ActionBuilder| { 115 for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) {
112 edit.delete(delete_range); 116 let replacement = if should_wrap { init_in_paren.clone() } else { init_str.clone() };
113 for (desc, should_wrap) in refs.iter().zip(wrap_in_parens) { 117 builder.replace(desc.file_range.range, replacement)
114 let replacement = 118 }
115 if should_wrap { init_in_paren.clone() } else { init_str.clone() }; 119 })
116 edit.replace(desc.file_range.range, replacement)
117 }
118 edit.set_cursor(delete_range.start())
119 },
120 )
121} 120}
122 121
123#[cfg(test)] 122#[cfg(test)]
124mod tests { 123mod tests {
125 use test_utils::covers; 124 use test_utils::mark;
126 125
127 use crate::helpers::{check_assist, check_assist_not_applicable}; 126 use crate::tests::{check_assist, check_assist_not_applicable};
128 127
129 use super::*; 128 use super::*;
130 129
@@ -149,7 +148,7 @@ fn foo() {
149 r" 148 r"
150fn bar(a: usize) {} 149fn bar(a: usize) {}
151fn foo() { 150fn foo() {
152 <|>1 + 1; 151 1 + 1;
153 if 1 > 10 { 152 if 1 > 10 {
154 } 153 }
155 154
@@ -183,7 +182,7 @@ fn foo() {
183 r" 182 r"
184fn bar(a: usize) {} 183fn bar(a: usize) {}
185fn foo() { 184fn foo() {
186 <|>(1 + 1) + 1; 185 (1 + 1) + 1;
187 if (1 + 1) > 10 { 186 if (1 + 1) > 10 {
188 } 187 }
189 188
@@ -217,7 +216,7 @@ fn foo() {
217 r" 216 r"
218fn bar(a: usize) {} 217fn bar(a: usize) {}
219fn foo() { 218fn foo() {
220 <|>bar(1) + 1; 219 bar(1) + 1;
221 if bar(1) > 10 { 220 if bar(1) > 10 {
222 } 221 }
223 222
@@ -251,7 +250,7 @@ fn foo() {
251 r" 250 r"
252fn bar(a: usize): usize { a } 251fn bar(a: usize): usize { a }
253fn foo() { 252fn foo() {
254 <|>(bar(1) as u64) + 1; 253 (bar(1) as u64) + 1;
255 if (bar(1) as u64) > 10 { 254 if (bar(1) as u64) > 10 {
256 } 255 }
257 256
@@ -283,7 +282,7 @@ fn foo() {
283}", 282}",
284 r" 283 r"
285fn foo() { 284fn foo() {
286 <|>{ 10 + 1 } + 1; 285 { 10 + 1 } + 1;
287 if { 10 + 1 } > 10 { 286 if { 10 + 1 } > 10 {
288 } 287 }
289 288
@@ -315,7 +314,7 @@ fn foo() {
315}", 314}",
316 r" 315 r"
317fn foo() { 316fn foo() {
318 <|>( 10 + 1 ) + 1; 317 ( 10 + 1 ) + 1;
319 if ( 10 + 1 ) > 10 { 318 if ( 10 + 1 ) > 10 {
320 } 319 }
321 320
@@ -330,7 +329,7 @@ fn foo() {
330 329
331 #[test] 330 #[test]
332 fn test_not_inline_mut_variable() { 331 fn test_not_inline_mut_variable() {
333 covers!(test_not_inline_mut_variable); 332 mark::check!(test_not_inline_mut_variable);
334 check_assist_not_applicable( 333 check_assist_not_applicable(
335 inline_local_variable, 334 inline_local_variable,
336 r" 335 r"
@@ -353,7 +352,7 @@ fn foo() {
353}", 352}",
354 r" 353 r"
355fn foo() { 354fn foo() {
356 <|>let b = bar(10 + 1) * 10; 355 let b = bar(10 + 1) * 10;
357 let c = bar(10 + 1) as usize; 356 let c = bar(10 + 1) as usize;
358}", 357}",
359 ); 358 );
@@ -373,7 +372,7 @@ fn foo() {
373 r" 372 r"
374fn foo() { 373fn foo() {
375 let x = vec![1, 2, 3]; 374 let x = vec![1, 2, 3];
376 <|>let b = x[0] * 10; 375 let b = x[0] * 10;
377 let c = x[0] as usize; 376 let c = x[0] as usize;
378}", 377}",
379 ); 378 );
@@ -393,7 +392,7 @@ fn foo() {
393 r" 392 r"
394fn foo() { 393fn foo() {
395 let bar = vec![1]; 394 let bar = vec![1];
396 <|>let b = bar.len() * 10; 395 let b = bar.len() * 10;
397 let c = bar.len() as usize; 396 let c = bar.len() as usize;
398}", 397}",
399 ); 398 );
@@ -421,7 +420,7 @@ struct Bar {
421 420
422fn foo() { 421fn foo() {
423 let bar = Bar { foo: 1 }; 422 let bar = Bar { foo: 1 };
424 <|>let b = bar.foo * 10; 423 let b = bar.foo * 10;
425 let c = bar.foo as usize; 424 let c = bar.foo as usize;
426}", 425}",
427 ); 426 );
@@ -442,7 +441,7 @@ fn foo() -> Option<usize> {
442 r" 441 r"
443fn foo() -> Option<usize> { 442fn foo() -> Option<usize> {
444 let bar = Some(1); 443 let bar = Some(1);
445 <|>let b = bar? * 10; 444 let b = bar? * 10;
446 let c = bar? as usize; 445 let c = bar? as usize;
447 None 446 None
448}", 447}",
@@ -462,7 +461,7 @@ fn foo() {
462 r" 461 r"
463fn foo() { 462fn foo() {
464 let bar = 10; 463 let bar = 10;
465 <|>let b = &bar * 10; 464 let b = &bar * 10;
466}", 465}",
467 ); 466 );
468 } 467 }
@@ -478,7 +477,7 @@ fn foo() {
478}", 477}",
479 r" 478 r"
480fn foo() { 479fn foo() {
481 <|>let b = (10, 20)[0]; 480 let b = (10, 20)[0];
482}", 481}",
483 ); 482 );
484 } 483 }
@@ -494,7 +493,7 @@ fn foo() {
494}", 493}",
495 r" 494 r"
496fn foo() { 495fn foo() {
497 <|>let b = [1, 2, 3].len(); 496 let b = [1, 2, 3].len();
498}", 497}",
499 ); 498 );
500 } 499 }
@@ -511,7 +510,7 @@ fn foo() {
511}", 510}",
512 r" 511 r"
513fn foo() { 512fn foo() {
514 <|>let b = (10 + 20) * 10; 513 let b = (10 + 20) * 10;
515 let c = (10 + 20) as usize; 514 let c = (10 + 20) as usize;
516}", 515}",
517 ); 516 );
@@ -531,7 +530,7 @@ fn foo() {
531 r" 530 r"
532fn foo() { 531fn foo() {
533 let d = 10; 532 let d = 10;
534 <|>let b = d * 10; 533 let b = d * 10;
535 let c = d as usize; 534 let c = d as usize;
536}", 535}",
537 ); 536 );
@@ -549,7 +548,7 @@ fn foo() {
549}", 548}",
550 r" 549 r"
551fn foo() { 550fn foo() {
552 <|>let b = { 10 } * 10; 551 let b = { 10 } * 10;
553 let c = { 10 } as usize; 552 let c = { 10 } as usize;
554}", 553}",
555 ); 554 );
@@ -569,7 +568,7 @@ fn foo() {
569}", 568}",
570 r" 569 r"
571fn foo() { 570fn foo() {
572 <|>let b = (10 + 20) * 10; 571 let b = (10 + 20) * 10;
573 let c = (10 + 20, 20); 572 let c = (10 + 20, 20);
574 let d = [10 + 20, 10]; 573 let d = [10 + 20, 10];
575 let e = (10 + 20); 574 let e = (10 + 20);
@@ -588,7 +587,7 @@ fn foo() {
588}", 587}",
589 r" 588 r"
590fn foo() { 589fn foo() {
591 <|>for i in vec![10, 20] {} 590 for i in vec![10, 20] {}
592}", 591}",
593 ); 592 );
594 } 593 }
@@ -604,7 +603,7 @@ fn foo() {
604}", 603}",
605 r" 604 r"
606fn foo() { 605fn foo() {
607 <|>while 1 > 0 {} 606 while 1 > 0 {}
608}", 607}",
609 ); 608 );
610 } 609 }
@@ -622,7 +621,7 @@ fn foo() {
622}", 621}",
623 r" 622 r"
624fn foo() { 623fn foo() {
625 <|>loop { 624 loop {
626 break 1 + 1; 625 break 1 + 1;
627 } 626 }
628}", 627}",
@@ -640,7 +639,7 @@ fn foo() {
640}", 639}",
641 r" 640 r"
642fn foo() { 641fn foo() {
643 <|>return 1 > 0; 642 return 1 > 0;
644}", 643}",
645 ); 644 );
646 } 645 }
@@ -656,14 +655,14 @@ fn foo() {
656}", 655}",
657 r" 656 r"
658fn foo() { 657fn foo() {
659 <|>match 1 > 0 {} 658 match 1 > 0 {}
660}", 659}",
661 ); 660 );
662 } 661 }
663 662
664 #[test] 663 #[test]
665 fn test_not_applicable_if_variable_unused() { 664 fn test_not_applicable_if_variable_unused() {
666 covers!(test_not_applicable_if_variable_unused); 665 mark::check!(test_not_applicable_if_variable_unused);
667 check_assist_not_applicable( 666 check_assist_not_applicable(
668 inline_local_variable, 667 inline_local_variable,
669 r" 668 r"
@@ -676,7 +675,7 @@ fn foo() {
676 675
677 #[test] 676 #[test]
678 fn not_applicable_outside_of_bind_pat() { 677 fn not_applicable_outside_of_bind_pat() {
679 covers!(not_applicable_outside_of_bind_pat); 678 mark::check!(not_applicable_outside_of_bind_pat);
680 check_assist_not_applicable( 679 check_assist_not_applicable(
681 inline_local_variable, 680 inline_local_variable,
682 r" 681 r"
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs
index eda9ac296..31d6539f7 100644
--- a/crates/ra_assists/src/handlers/introduce_variable.rs
+++ b/crates/ra_assists/src/handlers/introduce_variable.rs
@@ -4,12 +4,12 @@ use ra_syntax::{
4 BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, 4 BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
5 WHITESPACE, 5 WHITESPACE,
6 }, 6 },
7 SyntaxNode, TextSize, 7 SyntaxNode,
8}; 8};
9use stdx::format_to; 9use stdx::format_to;
10use test_utils::tested_by; 10use test_utils::mark;
11 11
12use crate::{Assist, AssistCtx, AssistId}; 12use crate::{AssistContext, AssistId, Assists};
13 13
14// Assist: introduce_variable 14// Assist: introduce_variable
15// 15//
@@ -23,17 +23,17 @@ use crate::{Assist, AssistCtx, AssistId};
23// -> 23// ->
24// ``` 24// ```
25// fn main() { 25// fn main() {
26// let var_name = (1 + 2); 26// let $0var_name = (1 + 2);
27// var_name * 4; 27// var_name * 4;
28// } 28// }
29// ``` 29// ```
30pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> { 30pub(crate) fn introduce_variable(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
31 if ctx.frange.range.is_empty() { 31 if ctx.frange.range.is_empty() {
32 return None; 32 return None;
33 } 33 }
34 let node = ctx.covering_element(); 34 let node = ctx.covering_element();
35 if node.kind() == COMMENT { 35 if node.kind() == COMMENT {
36 tested_by!(introduce_var_in_comment_is_not_applicable); 36 mark::hit!(introduce_var_in_comment_is_not_applicable);
37 return None; 37 return None;
38 } 38 }
39 let expr = node.ancestors().find_map(valid_target_expr)?; 39 let expr = node.ancestors().find_map(valid_target_expr)?;
@@ -42,17 +42,17 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> {
42 if indent.kind() != WHITESPACE { 42 if indent.kind() != WHITESPACE {
43 return None; 43 return None;
44 } 44 }
45 ctx.add_assist(AssistId("introduce_variable"), "Extract into variable", move |edit| { 45 let target = expr.syntax().text_range();
46 acc.add(AssistId("introduce_variable"), "Extract into variable", target, move |edit| {
46 let mut buf = String::new(); 47 let mut buf = String::new();
47 48
48 let cursor_offset = if wrap_in_block { 49 if wrap_in_block {
49 buf.push_str("{ let var_name = "); 50 buf.push_str("{ let var_name = ");
50 TextSize::of("{ let ")
51 } else { 51 } else {
52 buf.push_str("let var_name = "); 52 buf.push_str("let var_name = ");
53 TextSize::of("let ")
54 }; 53 };
55 format_to!(buf, "{}", expr.syntax()); 54 format_to!(buf, "{}", expr.syntax());
55
56 let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone()); 56 let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone());
57 let is_full_stmt = if let Some(expr_stmt) = &full_stmt { 57 let is_full_stmt = if let Some(expr_stmt) = &full_stmt {
58 Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone()) 58 Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone())
@@ -60,33 +60,47 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option<Assist> {
60 false 60 false
61 }; 61 };
62 if is_full_stmt { 62 if is_full_stmt {
63 tested_by!(test_introduce_var_expr_stmt); 63 mark::hit!(test_introduce_var_expr_stmt);
64 if full_stmt.unwrap().semicolon_token().is_none() { 64 if full_stmt.unwrap().semicolon_token().is_none() {
65 buf.push_str(";"); 65 buf.push_str(";");
66 } 66 }
67 edit.replace(expr.syntax().text_range(), buf); 67 let offset = expr.syntax().text_range();
68 } else { 68 match ctx.config.snippet_cap {
69 buf.push_str(";"); 69 Some(cap) => {
70 70 let snip = buf.replace("let var_name", "let $0var_name");
71 // We want to maintain the indent level, 71 edit.replace_snippet(cap, offset, snip)
72 // but we do not want to duplicate possible 72 }
73 // extra newlines in the indent block 73 None => edit.replace(offset, buf),
74 let text = indent.text();
75 if text.starts_with('\n') {
76 buf.push_str("\n");
77 buf.push_str(text.trim_start_matches('\n'));
78 } else {
79 buf.push_str(text);
80 } 74 }
75 return;
76 }
81 77
82 edit.target(expr.syntax().text_range()); 78 buf.push_str(";");
83 edit.replace(expr.syntax().text_range(), "var_name".to_string()); 79
84 edit.insert(anchor_stmt.text_range().start(), buf); 80 // We want to maintain the indent level,
85 if wrap_in_block { 81 // but we do not want to duplicate possible
86 edit.insert(anchor_stmt.text_range().end(), " }"); 82 // extra newlines in the indent block
83 let text = indent.text();
84 if text.starts_with('\n') {
85 buf.push_str("\n");
86 buf.push_str(text.trim_start_matches('\n'));
87 } else {
88 buf.push_str(text);
89 }
90
91 edit.replace(expr.syntax().text_range(), "var_name".to_string());
92 let offset = anchor_stmt.text_range().start();
93 match ctx.config.snippet_cap {
94 Some(cap) => {
95 let snip = buf.replace("let var_name", "let $0var_name");
96 edit.insert_snippet(cap, offset, snip)
87 } 97 }
98 None => edit.insert(offset, buf),
99 }
100
101 if wrap_in_block {
102 edit.insert(anchor_stmt.text_range().end(), " }");
88 } 103 }
89 edit.set_cursor(anchor_stmt.text_range().start() + cursor_offset);
90 }) 104 })
91} 105}
92 106
@@ -111,9 +125,9 @@ fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> {
111/// expression like a lambda or match arm. 125/// expression like a lambda or match arm.
112fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> { 126fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
113 expr.syntax().ancestors().find_map(|node| { 127 expr.syntax().ancestors().find_map(|node| {
114 if let Some(expr) = node.parent().and_then(ast::Block::cast).and_then(|it| it.expr()) { 128 if let Some(expr) = node.parent().and_then(ast::BlockExpr::cast).and_then(|it| it.expr()) {
115 if expr.syntax() == &node { 129 if expr.syntax() == &node {
116 tested_by!(test_introduce_var_last_expr); 130 mark::hit!(test_introduce_var_last_expr);
117 return Some((node, false)); 131 return Some((node, false));
118 } 132 }
119 } 133 }
@@ -134,9 +148,9 @@ fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
134 148
135#[cfg(test)] 149#[cfg(test)]
136mod tests { 150mod tests {
137 use test_utils::covers; 151 use test_utils::mark;
138 152
139 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 153 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
140 154
141 use super::*; 155 use super::*;
142 156
@@ -144,37 +158,37 @@ mod tests {
144 fn test_introduce_var_simple() { 158 fn test_introduce_var_simple() {
145 check_assist( 159 check_assist(
146 introduce_variable, 160 introduce_variable,
147 " 161 r#"
148fn foo() { 162fn foo() {
149 foo(<|>1 + 1<|>); 163 foo(<|>1 + 1<|>);
150}", 164}"#,
151 " 165 r#"
152fn foo() { 166fn foo() {
153 let <|>var_name = 1 + 1; 167 let $0var_name = 1 + 1;
154 foo(var_name); 168 foo(var_name);
155}", 169}"#,
156 ); 170 );
157 } 171 }
158 172
159 #[test] 173 #[test]
160 fn introduce_var_in_comment_is_not_applicable() { 174 fn introduce_var_in_comment_is_not_applicable() {
161 covers!(introduce_var_in_comment_is_not_applicable); 175 mark::check!(introduce_var_in_comment_is_not_applicable);
162 check_assist_not_applicable(introduce_variable, "fn main() { 1 + /* <|>comment<|> */ 1; }"); 176 check_assist_not_applicable(introduce_variable, "fn main() { 1 + /* <|>comment<|> */ 1; }");
163 } 177 }
164 178
165 #[test] 179 #[test]
166 fn test_introduce_var_expr_stmt() { 180 fn test_introduce_var_expr_stmt() {
167 covers!(test_introduce_var_expr_stmt); 181 mark::check!(test_introduce_var_expr_stmt);
168 check_assist( 182 check_assist(
169 introduce_variable, 183 introduce_variable,
170 " 184 r#"
171fn foo() { 185fn foo() {
172 <|>1 + 1<|>; 186 <|>1 + 1<|>;
173}", 187}"#,
174 " 188 r#"
175fn foo() { 189fn foo() {
176 let <|>var_name = 1 + 1; 190 let $0var_name = 1 + 1;
177}", 191}"#,
178 ); 192 );
179 check_assist( 193 check_assist(
180 introduce_variable, 194 introduce_variable,
@@ -185,7 +199,7 @@ fn foo() {
185}", 199}",
186 " 200 "
187fn foo() { 201fn foo() {
188 let <|>var_name = { let x = 0; x }; 202 let $0var_name = { let x = 0; x };
189 something_else(); 203 something_else();
190}", 204}",
191 ); 205 );
@@ -201,7 +215,7 @@ fn foo() {
201}", 215}",
202 " 216 "
203fn foo() { 217fn foo() {
204 let <|>var_name = 1; 218 let $0var_name = 1;
205 var_name + 1; 219 var_name + 1;
206}", 220}",
207 ); 221 );
@@ -209,7 +223,7 @@ fn foo() {
209 223
210 #[test] 224 #[test]
211 fn test_introduce_var_last_expr() { 225 fn test_introduce_var_last_expr() {
212 covers!(test_introduce_var_last_expr); 226 mark::check!(test_introduce_var_last_expr);
213 check_assist( 227 check_assist(
214 introduce_variable, 228 introduce_variable,
215 " 229 "
@@ -218,7 +232,7 @@ fn foo() {
218}", 232}",
219 " 233 "
220fn foo() { 234fn foo() {
221 let <|>var_name = 1 + 1; 235 let $0var_name = 1 + 1;
222 bar(var_name) 236 bar(var_name)
223}", 237}",
224 ); 238 );
@@ -230,7 +244,7 @@ fn foo() {
230}", 244}",
231 " 245 "
232fn foo() { 246fn foo() {
233 let <|>var_name = bar(1 + 1); 247 let $0var_name = bar(1 + 1);
234 var_name 248 var_name
235}", 249}",
236 ) 250 )
@@ -253,7 +267,7 @@ fn main() {
253fn main() { 267fn main() {
254 let x = true; 268 let x = true;
255 let tuple = match x { 269 let tuple = match x {
256 true => { let <|>var_name = 2 + 2; (var_name, true) } 270 true => { let $0var_name = 2 + 2; (var_name, true) }
257 _ => (0, false) 271 _ => (0, false)
258 }; 272 };
259} 273}
@@ -283,7 +297,7 @@ fn main() {
283 let tuple = match x { 297 let tuple = match x {
284 true => { 298 true => {
285 let y = 1; 299 let y = 1;
286 let <|>var_name = 2 + y; 300 let $0var_name = 2 + y;
287 (var_name, true) 301 (var_name, true)
288 } 302 }
289 _ => (0, false) 303 _ => (0, false)
@@ -304,7 +318,7 @@ fn main() {
304", 318",
305 " 319 "
306fn main() { 320fn main() {
307 let lambda = |x: u32| { let <|>var_name = x * 2; var_name }; 321 let lambda = |x: u32| { let $0var_name = x * 2; var_name };
308} 322}
309", 323",
310 ); 324 );
@@ -321,7 +335,7 @@ fn main() {
321", 335",
322 " 336 "
323fn main() { 337fn main() {
324 let lambda = |x: u32| { let <|>var_name = x * 2; var_name }; 338 let lambda = |x: u32| { let $0var_name = x * 2; var_name };
325} 339}
326", 340",
327 ); 341 );
@@ -338,7 +352,7 @@ fn main() {
338", 352",
339 " 353 "
340fn main() { 354fn main() {
341 let <|>var_name = Some(true); 355 let $0var_name = Some(true);
342 let o = var_name; 356 let o = var_name;
343} 357}
344", 358",
@@ -356,7 +370,7 @@ fn main() {
356", 370",
357 " 371 "
358fn main() { 372fn main() {
359 let <|>var_name = bar.foo(); 373 let $0var_name = bar.foo();
360 let v = var_name; 374 let v = var_name;
361} 375}
362", 376",
@@ -374,7 +388,7 @@ fn foo() -> u32 {
374", 388",
375 " 389 "
376fn foo() -> u32 { 390fn foo() -> u32 {
377 let <|>var_name = 2 + 2; 391 let $0var_name = 2 + 2;
378 return var_name; 392 return var_name;
379} 393}
380", 394",
@@ -396,7 +410,7 @@ fn foo() -> u32 {
396fn foo() -> u32 { 410fn foo() -> u32 {
397 411
398 412
399 let <|>var_name = 2 + 2; 413 let $0var_name = 2 + 2;
400 return var_name; 414 return var_name;
401} 415}
402", 416",
@@ -413,7 +427,7 @@ fn foo() -> u32 {
413 " 427 "
414fn foo() -> u32 { 428fn foo() -> u32 {
415 429
416 let <|>var_name = 2 + 2; 430 let $0var_name = 2 + 2;
417 return var_name; 431 return var_name;
418} 432}
419", 433",
@@ -438,7 +452,7 @@ fn foo() -> u32 {
438 // bar 452 // bar
439 453
440 454
441 let <|>var_name = 2 + 2; 455 let $0var_name = 2 + 2;
442 return var_name; 456 return var_name;
443} 457}
444", 458",
@@ -459,7 +473,7 @@ fn main() {
459 " 473 "
460fn main() { 474fn main() {
461 let result = loop { 475 let result = loop {
462 let <|>var_name = 2 + 2; 476 let $0var_name = 2 + 2;
463 break var_name; 477 break var_name;
464 }; 478 };
465} 479}
@@ -478,7 +492,7 @@ fn main() {
478", 492",
479 " 493 "
480fn main() { 494fn main() {
481 let <|>var_name = 0f32 as u32; 495 let $0var_name = 0f32 as u32;
482 let v = var_name; 496 let v = var_name;
483} 497}
484", 498",
diff --git a/crates/ra_assists/src/handlers/invert_if.rs b/crates/ra_assists/src/handlers/invert_if.rs
index 682e08512..59d278eb9 100644
--- a/crates/ra_assists/src/handlers/invert_if.rs
+++ b/crates/ra_assists/src/handlers/invert_if.rs
@@ -3,7 +3,11 @@ use ra_syntax::{
3 T, 3 T,
4}; 4};
5 5
6use crate::{utils::invert_boolean_expression, Assist, AssistCtx, AssistId}; 6use crate::{
7 assist_context::{AssistContext, Assists},
8 utils::invert_boolean_expression,
9 AssistId,
10};
7 11
8// Assist: invert_if 12// Assist: invert_if
9// 13//
@@ -24,7 +28,7 @@ use crate::{utils::invert_boolean_expression, Assist, AssistCtx, AssistId};
24// } 28// }
25// ``` 29// ```
26 30
27pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> { 31pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
28 let if_keyword = ctx.find_token_at_offset(T![if])?; 32 let if_keyword = ctx.find_token_at_offset(T![if])?;
29 let expr = ast::IfExpr::cast(if_keyword.parent())?; 33 let expr = ast::IfExpr::cast(if_keyword.parent())?;
30 let if_range = if_keyword.text_range(); 34 let if_range = if_keyword.text_range();
@@ -40,36 +44,35 @@ pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
40 44
41 let cond = expr.condition()?.expr()?; 45 let cond = expr.condition()?.expr()?;
42 let then_node = expr.then_branch()?.syntax().clone(); 46 let then_node = expr.then_branch()?.syntax().clone();
47 let else_block = match expr.else_branch()? {
48 ast::ElseBranch::Block(it) => it,
49 ast::ElseBranch::IfExpr(_) => return None,
50 };
43 51
44 if let ast::ElseBranch::Block(else_block) = expr.else_branch()? { 52 let cond_range = cond.syntax().text_range();
45 let cond_range = cond.syntax().text_range(); 53 let flip_cond = invert_boolean_expression(cond);
46 let flip_cond = invert_boolean_expression(cond); 54 let else_node = else_block.syntax();
47 let else_node = else_block.syntax(); 55 let else_range = else_node.text_range();
48 let else_range = else_node.text_range(); 56 let then_range = then_node.text_range();
49 let then_range = then_node.text_range(); 57 acc.add(AssistId("invert_if"), "Invert if", if_range, |edit| {
50 return ctx.add_assist(AssistId("invert_if"), "Invert if", |edit| { 58 edit.replace(cond_range, flip_cond.syntax().text());
51 edit.target(if_range); 59 edit.replace(else_range, then_node.text());
52 edit.replace(cond_range, flip_cond.syntax().text()); 60 edit.replace(then_range, else_node.text());
53 edit.replace(else_range, then_node.text()); 61 })
54 edit.replace(then_range, else_node.text());
55 });
56 }
57
58 None
59} 62}
60 63
61#[cfg(test)] 64#[cfg(test)]
62mod tests { 65mod tests {
63 use super::*; 66 use super::*;
64 67
65 use crate::helpers::{check_assist, check_assist_not_applicable}; 68 use crate::tests::{check_assist, check_assist_not_applicable};
66 69
67 #[test] 70 #[test]
68 fn invert_if_remove_inequality() { 71 fn invert_if_remove_inequality() {
69 check_assist( 72 check_assist(
70 invert_if, 73 invert_if,
71 "fn f() { i<|>f x != 3 { 1 } else { 3 + 2 } }", 74 "fn f() { i<|>f x != 3 { 1 } else { 3 + 2 } }",
72 "fn f() { i<|>f x == 3 { 3 + 2 } else { 1 } }", 75 "fn f() { if x == 3 { 3 + 2 } else { 1 } }",
73 ) 76 )
74 } 77 }
75 78
@@ -78,7 +81,7 @@ mod tests {
78 check_assist( 81 check_assist(
79 invert_if, 82 invert_if,
80 "fn f() { <|>if !cond { 3 * 2 } else { 1 } }", 83 "fn f() { <|>if !cond { 3 * 2 } else { 1 } }",
81 "fn f() { <|>if cond { 1 } else { 3 * 2 } }", 84 "fn f() { if cond { 1 } else { 3 * 2 } }",
82 ) 85 )
83 } 86 }
84 87
@@ -87,7 +90,7 @@ mod tests {
87 check_assist( 90 check_assist(
88 invert_if, 91 invert_if,
89 "fn f() { i<|>f cond { 3 * 2 } else { 1 } }", 92 "fn f() { i<|>f cond { 3 * 2 } else { 1 } }",
90 "fn f() { i<|>f !cond { 1 } else { 3 * 2 } }", 93 "fn f() { if !cond { 1 } else { 3 * 2 } }",
91 ) 94 )
92 } 95 }
93 96
diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs
index 4be1238f1..972d16241 100644
--- a/crates/ra_assists/src/handlers/merge_imports.rs
+++ b/crates/ra_assists/src/handlers/merge_imports.rs
@@ -6,7 +6,10 @@ use ra_syntax::{
6 AstNode, Direction, InsertPosition, SyntaxElement, T, 6 AstNode, Direction, InsertPosition, SyntaxElement, T,
7}; 7};
8 8
9use crate::{Assist, AssistCtx, AssistId}; 9use crate::{
10 assist_context::{AssistContext, Assists},
11 AssistId,
12};
10 13
11// Assist: merge_imports 14// Assist: merge_imports
12// 15//
@@ -20,10 +23,10 @@ use crate::{Assist, AssistCtx, AssistId};
20// ``` 23// ```
21// use std::{fmt::Formatter, io}; 24// use std::{fmt::Formatter, io};
22// ``` 25// ```
23pub(crate) fn merge_imports(ctx: AssistCtx) -> Option<Assist> { 26pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24 let tree: ast::UseTree = ctx.find_node_at_offset()?; 27 let tree: ast::UseTree = ctx.find_node_at_offset()?;
25 let mut rewriter = SyntaxRewriter::default(); 28 let mut rewriter = SyntaxRewriter::default();
26 let mut offset = ctx.frange.range.start(); 29 let mut offset = ctx.offset();
27 30
28 if let Some(use_item) = tree.syntax().parent().and_then(ast::UseItem::cast) { 31 if let Some(use_item) = tree.syntax().parent().and_then(ast::UseItem::cast) {
29 let (merged, to_delete) = next_prev() 32 let (merged, to_delete) = next_prev()
@@ -52,10 +55,9 @@ pub(crate) fn merge_imports(ctx: AssistCtx) -> Option<Assist> {
52 } 55 }
53 }; 56 };
54 57
55 ctx.add_assist(AssistId("merge_imports"), "Merge imports", |edit| { 58 let target = tree.syntax().text_range();
56 edit.rewrite(rewriter); 59 acc.add(AssistId("merge_imports"), "Merge imports", target, |builder| {
57 // FIXME: we only need because our diff is imprecise 60 builder.rewrite(rewriter);
58 edit.set_cursor(offset);
59 }) 61 })
60} 62}
61 63
@@ -125,7 +127,7 @@ fn first_path(path: &ast::Path) -> ast::Path {
125 127
126#[cfg(test)] 128#[cfg(test)]
127mod tests { 129mod tests {
128 use crate::helpers::check_assist; 130 use crate::tests::check_assist;
129 131
130 use super::*; 132 use super::*;
131 133
@@ -138,7 +140,7 @@ use std::fmt<|>::Debug;
138use std::fmt::Display; 140use std::fmt::Display;
139", 141",
140 r" 142 r"
141use std::fmt<|>::{Debug, Display}; 143use std::fmt::{Debug, Display};
142", 144",
143 ) 145 )
144 } 146 }
@@ -152,7 +154,7 @@ use std::fmt::Debug;
152use std::fmt<|>::Display; 154use std::fmt<|>::Display;
153", 155",
154 r" 156 r"
155use std::fmt:<|>:{Display, Debug}; 157use std::fmt::{Display, Debug};
156", 158",
157 ); 159 );
158 } 160 }
@@ -165,7 +167,7 @@ use std::fmt:<|>:{Display, Debug};
165use std::{fmt<|>::Debug, fmt::Display}; 167use std::{fmt<|>::Debug, fmt::Display};
166", 168",
167 r" 169 r"
168use std::{fmt<|>::{Debug, Display}}; 170use std::{fmt::{Debug, Display}};
169", 171",
170 ); 172 );
171 check_assist( 173 check_assist(
@@ -174,7 +176,7 @@ use std::{fmt<|>::{Debug, Display}};
174use std::{fmt::Debug, fmt<|>::Display}; 176use std::{fmt::Debug, fmt<|>::Display};
175", 177",
176 r" 178 r"
177use std::{fmt::<|>{Display, Debug}}; 179use std::{fmt::{Display, Debug}};
178", 180",
179 ); 181 );
180 } 182 }
@@ -188,7 +190,7 @@ use std<|>::cell::*;
188use std::str; 190use std::str;
189", 191",
190 r" 192 r"
191use std<|>::{cell::*, str}; 193use std::{cell::*, str};
192", 194",
193 ) 195 )
194 } 196 }
@@ -202,7 +204,7 @@ use std<|>::cell::*;
202use std::str::*; 204use std::str::*;
203", 205",
204 r" 206 r"
205use std<|>::{cell::*, str::*}; 207use std::{cell::*, str::*};
206", 208",
207 ) 209 )
208 } 210 }
@@ -218,7 +220,7 @@ use foo::baz;
218/// Doc comment 220/// Doc comment
219", 221",
220 r" 222 r"
221use foo<|>::{bar, baz}; 223use foo::{bar, baz};
222 224
223/// Doc comment 225/// Doc comment
224", 226",
@@ -237,7 +239,7 @@ use {
237", 239",
238 r" 240 r"
239use { 241use {
240 foo<|>::{bar, baz}, 242 foo::{bar, baz},
241}; 243};
242", 244",
243 ); 245 );
@@ -251,7 +253,7 @@ use {
251", 253",
252 r" 254 r"
253use { 255use {
254 foo::{bar<|>, baz}, 256 foo::{bar, baz},
255}; 257};
256", 258",
257 ); 259 );
@@ -268,7 +270,7 @@ use foo::<|>{
268}; 270};
269", 271",
270 r" 272 r"
271use foo::{<|> 273use foo::{
272 FooBar, 274 FooBar,
273bar::baz}; 275bar::baz};
274", 276",
diff --git a/crates/ra_assists/src/handlers/merge_match_arms.rs b/crates/ra_assists/src/handlers/merge_match_arms.rs
index 5a77d3dbc..ca04ec671 100644
--- a/crates/ra_assists/src/handlers/merge_match_arms.rs
+++ b/crates/ra_assists/src/handlers/merge_match_arms.rs
@@ -3,10 +3,10 @@ use std::iter::successors;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::neighbor, 4 algo::neighbor,
5 ast::{self, AstNode}, 5 ast::{self, AstNode},
6 Direction, TextSize, 6 Direction,
7}; 7};
8 8
9use crate::{Assist, AssistCtx, AssistId, TextRange}; 9use crate::{AssistContext, AssistId, Assists, TextRange};
10 10
11// Assist: merge_match_arms 11// Assist: merge_match_arms
12// 12//
@@ -32,7 +32,7 @@ use crate::{Assist, AssistCtx, AssistId, TextRange};
32// } 32// }
33// } 33// }
34// ``` 34// ```
35pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> { 35pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
36 let current_arm = ctx.find_node_at_offset::<ast::MatchArm>()?; 36 let current_arm = ctx.find_node_at_offset::<ast::MatchArm>()?;
37 // Don't try to handle arms with guards for now - can add support for this later 37 // Don't try to handle arms with guards for now - can add support for this later
38 if current_arm.guard().is_some() { 38 if current_arm.guard().is_some() {
@@ -41,17 +41,6 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> {
41 let current_expr = current_arm.expr()?; 41 let current_expr = current_arm.expr()?;
42 let current_text_range = current_arm.syntax().text_range(); 42 let current_text_range = current_arm.syntax().text_range();
43 43
44 enum CursorPos {
45 InExpr(TextSize),
46 InPat(TextSize),
47 }
48 let cursor_pos = ctx.frange.range.start();
49 let cursor_pos = if current_expr.syntax().text_range().contains(cursor_pos) {
50 CursorPos::InExpr(current_text_range.end() - cursor_pos)
51 } else {
52 CursorPos::InPat(cursor_pos)
53 };
54
55 // We check if the following match arms match this one. We could, but don't, 44 // We check if the following match arms match this one. We could, but don't,
56 // compare to the previous match arm as well. 45 // compare to the previous match arm as well.
57 let arms_to_merge = successors(Some(current_arm), |it| neighbor(it, Direction::Next)) 46 let arms_to_merge = successors(Some(current_arm), |it| neighbor(it, Direction::Next))
@@ -70,7 +59,7 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> {
70 return None; 59 return None;
71 } 60 }
72 61
73 ctx.add_assist(AssistId("merge_match_arms"), "Merge match arms", |edit| { 62 acc.add(AssistId("merge_match_arms"), "Merge match arms", current_text_range, |edit| {
74 let pats = if arms_to_merge.iter().any(contains_placeholder) { 63 let pats = if arms_to_merge.iter().any(contains_placeholder) {
75 "_".into() 64 "_".into()
76 } else { 65 } else {
@@ -87,11 +76,6 @@ pub(crate) fn merge_match_arms(ctx: AssistCtx) -> Option<Assist> {
87 let start = arms_to_merge.first().unwrap().syntax().text_range().start(); 76 let start = arms_to_merge.first().unwrap().syntax().text_range().start();
88 let end = arms_to_merge.last().unwrap().syntax().text_range().end(); 77 let end = arms_to_merge.last().unwrap().syntax().text_range().end();
89 78
90 edit.target(current_text_range);
91 edit.set_cursor(match cursor_pos {
92 CursorPos::InExpr(back_offset) => start + TextSize::of(&arm) - back_offset,
93 CursorPos::InPat(offset) => offset,
94 });
95 edit.replace(TextRange::new(start, end), arm); 79 edit.replace(TextRange::new(start, end), arm);
96 }) 80 })
97} 81}
@@ -105,7 +89,7 @@ fn contains_placeholder(a: &ast::MatchArm) -> bool {
105 89
106#[cfg(test)] 90#[cfg(test)]
107mod tests { 91mod tests {
108 use crate::helpers::{check_assist, check_assist_not_applicable}; 92 use crate::tests::{check_assist, check_assist_not_applicable};
109 93
110 use super::*; 94 use super::*;
111 95
@@ -133,7 +117,7 @@ mod tests {
133 fn main() { 117 fn main() {
134 let x = X::A; 118 let x = X::A;
135 let y = match x { 119 let y = match x {
136 X::A | X::B => { 1i32<|> } 120 X::A | X::B => { 1i32 }
137 X::C => { 2i32 } 121 X::C => { 2i32 }
138 } 122 }
139 } 123 }
@@ -165,7 +149,7 @@ mod tests {
165 fn main() { 149 fn main() {
166 let x = X::A; 150 let x = X::A;
167 let y = match x { 151 let y = match x {
168 X::A | X::B | X::C | X::D => {<|> 1i32 }, 152 X::A | X::B | X::C | X::D => { 1i32 },
169 X::E => { 2i32 }, 153 X::E => { 2i32 },
170 } 154 }
171 } 155 }
@@ -198,7 +182,7 @@ mod tests {
198 let x = X::A; 182 let x = X::A;
199 let y = match x { 183 let y = match x {
200 X::A => { 1i32 }, 184 X::A => { 1i32 },
201 _ => { 2i<|>32 } 185 _ => { 2i32 }
202 } 186 }
203 } 187 }
204 "#, 188 "#,
@@ -227,7 +211,7 @@ mod tests {
227 211
228 fn main() { 212 fn main() {
229 match X::A { 213 match X::A {
230 X::A<|> | X::B | X::C => 92, 214 X::A | X::B | X::C => 92,
231 X::D => 62, 215 X::D => 62,
232 _ => panic!(), 216 _ => panic!(),
233 } 217 }
diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs
index 0f26884dc..be2a7eddc 100644
--- a/crates/ra_assists/src/handlers/move_bounds.rs
+++ b/crates/ra_assists/src/handlers/move_bounds.rs
@@ -5,7 +5,7 @@ use ra_syntax::{
5 T, 5 T,
6}; 6};
7 7
8use crate::{Assist, AssistCtx, AssistId}; 8use crate::{AssistContext, AssistId, Assists};
9 9
10// Assist: move_bounds_to_where_clause 10// Assist: move_bounds_to_where_clause
11// 11//
@@ -22,7 +22,7 @@ use crate::{Assist, AssistCtx, AssistId};
22// f(x) 22// f(x)
23// } 23// }
24// ``` 24// ```
25pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> { 25pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 let type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?; 26 let type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?;
27 27
28 let mut type_params = type_param_list.type_params(); 28 let mut type_params = type_param_list.type_params();
@@ -49,7 +49,8 @@ pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> {
49 } 49 }
50 }; 50 };
51 51
52 ctx.add_assist(AssistId("move_bounds_to_where_clause"), "Move to where clause", |edit| { 52 let target = type_param_list.syntax().text_range();
53 acc.add(AssistId("move_bounds_to_where_clause"), "Move to where clause", target, |edit| {
53 let new_params = type_param_list 54 let new_params = type_param_list
54 .type_params() 55 .type_params()
55 .filter(|it| it.type_bound_list().is_some()) 56 .filter(|it| it.type_bound_list().is_some())
@@ -71,7 +72,6 @@ pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option<Assist> {
71 _ => format!(" {}", where_clause.syntax()), 72 _ => format!(" {}", where_clause.syntax()),
72 }; 73 };
73 edit.insert(anchor.text_range().start(), to_insert); 74 edit.insert(anchor.text_range().start(), to_insert);
74 edit.target(type_param_list.syntax().text_range());
75 }) 75 })
76} 76}
77 77
@@ -89,7 +89,7 @@ fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> {
89mod tests { 89mod tests {
90 use super::*; 90 use super::*;
91 91
92 use crate::helpers::check_assist; 92 use crate::tests::check_assist;
93 93
94 #[test] 94 #[test]
95 fn move_bounds_to_where_clause_fn() { 95 fn move_bounds_to_where_clause_fn() {
@@ -99,7 +99,7 @@ mod tests {
99 fn foo<T: u32, <|>F: FnOnce(T) -> T>() {} 99 fn foo<T: u32, <|>F: FnOnce(T) -> T>() {}
100 "#, 100 "#,
101 r#" 101 r#"
102 fn foo<T, <|>F>() where T: u32, F: FnOnce(T) -> T {} 102 fn foo<T, F>() where T: u32, F: FnOnce(T) -> T {}
103 "#, 103 "#,
104 ); 104 );
105 } 105 }
@@ -112,7 +112,7 @@ mod tests {
112 impl<U: u32, <|>T> A<U, T> {} 112 impl<U: u32, <|>T> A<U, T> {}
113 "#, 113 "#,
114 r#" 114 r#"
115 impl<U, <|>T> A<U, T> where U: u32 {} 115 impl<U, T> A<U, T> where U: u32 {}
116 "#, 116 "#,
117 ); 117 );
118 } 118 }
@@ -125,7 +125,7 @@ mod tests {
125 struct A<<|>T: Iterator<Item = u32>> {} 125 struct A<<|>T: Iterator<Item = u32>> {}
126 "#, 126 "#,
127 r#" 127 r#"
128 struct A<<|>T> where T: Iterator<Item = u32> {} 128 struct A<T> where T: Iterator<Item = u32> {}
129 "#, 129 "#,
130 ); 130 );
131 } 131 }
@@ -138,7 +138,7 @@ mod tests {
138 struct Pair<<|>T: u32>(T, T); 138 struct Pair<<|>T: u32>(T, T);
139 "#, 139 "#,
140 r#" 140 r#"
141 struct Pair<<|>T>(T, T) where T: u32; 141 struct Pair<T>(T, T) where T: u32;
142 "#, 142 "#,
143 ); 143 );
144 } 144 }
diff --git a/crates/ra_assists/src/handlers/move_guard.rs b/crates/ra_assists/src/handlers/move_guard.rs
index d5ccdd91c..7edcf0748 100644
--- a/crates/ra_assists/src/handlers/move_guard.rs
+++ b/crates/ra_assists/src/handlers/move_guard.rs
@@ -1,10 +1,9 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast, 2 ast::{AstNode, IfExpr, MatchArm},
3 ast::{AstNode, AstToken, IfExpr, MatchArm}, 3 SyntaxKind::WHITESPACE,
4 TextSize,
5}; 4};
6 5
7use crate::{Assist, AssistCtx, AssistId}; 6use crate::{AssistContext, AssistId, Assists};
8 7
9// Assist: move_guard_to_arm_body 8// Assist: move_guard_to_arm_body
10// 9//
@@ -31,7 +30,7 @@ use crate::{Assist, AssistCtx, AssistId};
31// } 30// }
32// } 31// }
33// ``` 32// ```
34pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option<Assist> { 33pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
35 let match_arm = ctx.find_node_at_offset::<MatchArm>()?; 34 let match_arm = ctx.find_node_at_offset::<MatchArm>()?;
36 let guard = match_arm.guard()?; 35 let guard = match_arm.guard()?;
37 let space_before_guard = guard.syntax().prev_sibling_or_token(); 36 let space_before_guard = guard.syntax().prev_sibling_or_token();
@@ -40,26 +39,17 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option<Assist> {
40 let arm_expr = match_arm.expr()?; 39 let arm_expr = match_arm.expr()?;
41 let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text()); 40 let buf = format!("if {} {{ {} }}", guard_conditions.syntax().text(), arm_expr.syntax().text());
42 41
43 ctx.add_assist(AssistId("move_guard_to_arm_body"), "Move guard to arm body", |edit| { 42 let target = guard.syntax().text_range();
44 edit.target(guard.syntax().text_range()); 43 acc.add(AssistId("move_guard_to_arm_body"), "Move guard to arm body", target, |edit| {
45 let offseting_amount = match space_before_guard.and_then(|it| it.into_token()) { 44 match space_before_guard {
46 Some(tok) => { 45 Some(element) if element.kind() == WHITESPACE => {
47 if ast::Whitespace::cast(tok.clone()).is_some() { 46 edit.delete(element.text_range());
48 let ele = tok.text_range();
49 edit.delete(ele);
50 ele.len()
51 } else {
52 TextSize::from(0)
53 }
54 } 47 }
55 _ => TextSize::from(0), 48 _ => (),
56 }; 49 };
57 50
58 edit.delete(guard.syntax().text_range()); 51 edit.delete(guard.syntax().text_range());
59 edit.replace_node_and_indent(arm_expr.syntax(), buf); 52 edit.replace_node_and_indent(arm_expr.syntax(), buf);
60 edit.set_cursor(
61 arm_expr.syntax().text_range().start() + TextSize::from(3) - offseting_amount,
62 );
63 }) 53 })
64} 54}
65 55
@@ -88,7 +78,7 @@ pub(crate) fn move_guard_to_arm_body(ctx: AssistCtx) -> Option<Assist> {
88// } 78// }
89// } 79// }
90// ``` 80// ```
91pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> { 81pub(crate) fn move_arm_cond_to_match_guard(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
92 let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?; 82 let match_arm: MatchArm = ctx.find_node_at_offset::<MatchArm>()?;
93 let match_pat = match_arm.pat()?; 83 let match_pat = match_arm.pat()?;
94 84
@@ -108,14 +98,15 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> {
108 98
109 let buf = format!(" if {}", cond.syntax().text()); 99 let buf = format!(" if {}", cond.syntax().text());
110 100
111 ctx.add_assist( 101 let target = if_expr.syntax().text_range();
102 acc.add(
112 AssistId("move_arm_cond_to_match_guard"), 103 AssistId("move_arm_cond_to_match_guard"),
113 "Move condition to match guard", 104 "Move condition to match guard",
105 target,
114 |edit| { 106 |edit| {
115 edit.target(if_expr.syntax().text_range()); 107 let then_only_expr = then_block.statements().next().is_none();
116 let then_only_expr = then_block.block().and_then(|it| it.statements().next()).is_none();
117 108
118 match &then_block.block().and_then(|it| it.expr()) { 109 match &then_block.expr() {
119 Some(then_expr) if then_only_expr => { 110 Some(then_expr) if then_only_expr => {
120 edit.replace(if_expr.syntax().text_range(), then_expr.syntax().text()) 111 edit.replace(if_expr.syntax().text_range(), then_expr.syntax().text())
121 } 112 }
@@ -123,7 +114,6 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> {
123 } 114 }
124 115
125 edit.insert(match_pat.syntax().text_range().end(), buf); 116 edit.insert(match_pat.syntax().text_range().end(), buf);
126 edit.set_cursor(match_pat.syntax().text_range().end() + TextSize::from(1));
127 }, 117 },
128 ) 118 )
129} 119}
@@ -132,7 +122,7 @@ pub(crate) fn move_arm_cond_to_match_guard(ctx: AssistCtx) -> Option<Assist> {
132mod tests { 122mod tests {
133 use super::*; 123 use super::*;
134 124
135 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 125 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
136 126
137 #[test] 127 #[test]
138 fn move_guard_to_arm_body_target() { 128 fn move_guard_to_arm_body_target() {
@@ -171,7 +161,7 @@ mod tests {
171 let t = 'a'; 161 let t = 'a';
172 let chars = "abcd"; 162 let chars = "abcd";
173 match t { 163 match t {
174 '\r' => if chars.clone().next() == Some('\n') { <|>false }, 164 '\r' => if chars.clone().next() == Some('\n') { false },
175 _ => true 165 _ => true
176 } 166 }
177 } 167 }
@@ -194,7 +184,7 @@ mod tests {
194 r#" 184 r#"
195 fn f() { 185 fn f() {
196 match x { 186 match x {
197 y @ 4 | y @ 5 => if y > 5 { <|>true }, 187 y @ 4 | y @ 5 => if y > 5 { true },
198 _ => false 188 _ => false
199 } 189 }
200 } 190 }
@@ -221,7 +211,7 @@ mod tests {
221 let t = 'a'; 211 let t = 'a';
222 let chars = "abcd"; 212 let chars = "abcd";
223 match t { 213 match t {
224 '\r' <|>if chars.clone().next() == Some('\n') => false, 214 '\r' if chars.clone().next() == Some('\n') => false,
225 _ => true 215 _ => true
226 } 216 }
227 } 217 }
@@ -265,7 +255,7 @@ mod tests {
265 let t = 'a'; 255 let t = 'a';
266 let chars = "abcd"; 256 let chars = "abcd";
267 match t { 257 match t {
268 '\r' <|>if chars.clone().next().is_some() => { }, 258 '\r' if chars.clone().next().is_some() => { },
269 _ => true 259 _ => true
270 } 260 }
271 } 261 }
@@ -295,7 +285,7 @@ mod tests {
295 let mut t = 'a'; 285 let mut t = 'a';
296 let chars = "abcd"; 286 let chars = "abcd";
297 match t { 287 match t {
298 '\r' <|>if chars.clone().next().is_some() => { 288 '\r' if chars.clone().next().is_some() => {
299 t = 'e'; 289 t = 'e';
300 false 290 false
301 }, 291 },
diff --git a/crates/ra_assists/src/handlers/raw_string.rs b/crates/ra_assists/src/handlers/raw_string.rs
index 567400b9c..16002d2ac 100644
--- a/crates/ra_assists/src/handlers/raw_string.rs
+++ b/crates/ra_assists/src/handlers/raw_string.rs
@@ -5,7 +5,7 @@ use ra_syntax::{
5 TextSize, 5 TextSize,
6}; 6};
7 7
8use crate::{Assist, AssistCtx, AssistId}; 8use crate::{AssistContext, AssistId, Assists};
9 9
10// Assist: make_raw_string 10// Assist: make_raw_string
11// 11//
@@ -22,11 +22,11 @@ use crate::{Assist, AssistCtx, AssistId};
22// r#"Hello, World!"#; 22// r#"Hello, World!"#;
23// } 23// }
24// ``` 24// ```
25pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option<Assist> { 25pub(crate) fn make_raw_string(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?; 26 let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?;
27 let value = token.value()?; 27 let value = token.value()?;
28 ctx.add_assist(AssistId("make_raw_string"), "Rewrite as raw string", |edit| { 28 let target = token.syntax().text_range();
29 edit.target(token.syntax().text_range()); 29 acc.add(AssistId("make_raw_string"), "Rewrite as raw string", target, |edit| {
30 let max_hash_streak = count_hashes(&value); 30 let max_hash_streak = count_hashes(&value);
31 let mut hashes = String::with_capacity(max_hash_streak + 1); 31 let mut hashes = String::with_capacity(max_hash_streak + 1);
32 for _ in 0..hashes.capacity() { 32 for _ in 0..hashes.capacity() {
@@ -51,11 +51,11 @@ pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option<Assist> {
51// "Hello, \"World!\""; 51// "Hello, \"World!\"";
52// } 52// }
53// ``` 53// ```
54pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option<Assist> { 54pub(crate) fn make_usual_string(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
55 let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?; 55 let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?;
56 let value = token.value()?; 56 let value = token.value()?;
57 ctx.add_assist(AssistId("make_usual_string"), "Rewrite as regular string", |edit| { 57 let target = token.syntax().text_range();
58 edit.target(token.syntax().text_range()); 58 acc.add(AssistId("make_usual_string"), "Rewrite as regular string", target, |edit| {
59 // parse inside string to escape `"` 59 // parse inside string to escape `"`
60 let escaped = value.escape_default().to_string(); 60 let escaped = value.escape_default().to_string();
61 edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); 61 edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped));
@@ -77,10 +77,10 @@ pub(crate) fn make_usual_string(ctx: AssistCtx) -> Option<Assist> {
77// r##"Hello, World!"##; 77// r##"Hello, World!"##;
78// } 78// }
79// ``` 79// ```
80pub(crate) fn add_hash(ctx: AssistCtx) -> Option<Assist> { 80pub(crate) fn add_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
81 let token = ctx.find_token_at_offset(RAW_STRING)?; 81 let token = ctx.find_token_at_offset(RAW_STRING)?;
82 ctx.add_assist(AssistId("add_hash"), "Add # to raw string", |edit| { 82 let target = token.text_range();
83 edit.target(token.text_range()); 83 acc.add(AssistId("add_hash"), "Add # to raw string", target, |edit| {
84 edit.insert(token.text_range().start() + TextSize::of('r'), "#"); 84 edit.insert(token.text_range().start() + TextSize::of('r'), "#");
85 edit.insert(token.text_range().end(), "#"); 85 edit.insert(token.text_range().end(), "#");
86 }) 86 })
@@ -101,15 +101,15 @@ pub(crate) fn add_hash(ctx: AssistCtx) -> Option<Assist> {
101// r"Hello, World!"; 101// r"Hello, World!";
102// } 102// }
103// ``` 103// ```
104pub(crate) fn remove_hash(ctx: AssistCtx) -> Option<Assist> { 104pub(crate) fn remove_hash(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
105 let token = ctx.find_token_at_offset(RAW_STRING)?; 105 let token = ctx.find_token_at_offset(RAW_STRING)?;
106 let text = token.text().as_str(); 106 let text = token.text().as_str();
107 if text.starts_with("r\"") { 107 if text.starts_with("r\"") {
108 // no hash to remove 108 // no hash to remove
109 return None; 109 return None;
110 } 110 }
111 ctx.add_assist(AssistId("remove_hash"), "Remove hash from raw string", |edit| { 111 let target = token.text_range();
112 edit.target(token.text_range()); 112 acc.add(AssistId("remove_hash"), "Remove hash from raw string", target, |edit| {
113 let result = &text[2..text.len() - 1]; 113 let result = &text[2..text.len() - 1];
114 let result = if result.starts_with('\"') { 114 let result = if result.starts_with('\"') {
115 // FIXME: this logic is wrong, not only the last has has to handled specially 115 // FIXME: this logic is wrong, not only the last has has to handled specially
@@ -138,7 +138,7 @@ fn count_hashes(s: &str) -> usize {
138#[cfg(test)] 138#[cfg(test)]
139mod test { 139mod test {
140 use super::*; 140 use super::*;
141 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 141 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
142 142
143 #[test] 143 #[test]
144 fn make_raw_string_target() { 144 fn make_raw_string_target() {
@@ -164,7 +164,7 @@ mod test {
164 "#, 164 "#,
165 r##" 165 r##"
166 fn f() { 166 fn f() {
167 let s = <|>r#"random 167 let s = r#"random
168string"#; 168string"#;
169 } 169 }
170 "##, 170 "##,
@@ -182,7 +182,7 @@ string"#;
182 "#, 182 "#,
183 r##" 183 r##"
184 fn f() { 184 fn f() {
185 format!(<|>r#"x = {}"#, 92) 185 format!(r#"x = {}"#, 92)
186 } 186 }
187 "##, 187 "##,
188 ) 188 )
@@ -199,7 +199,7 @@ string"#;
199 "###, 199 "###,
200 r####" 200 r####"
201 fn f() { 201 fn f() {
202 let s = <|>r#"#random## 202 let s = r#"#random##
203string"#; 203string"#;
204 } 204 }
205 "####, 205 "####,
@@ -217,7 +217,7 @@ string"#;
217 "###, 217 "###,
218 r####" 218 r####"
219 fn f() { 219 fn f() {
220 let s = <|>r###"#random"## 220 let s = r###"#random"##
221string"###; 221string"###;
222 } 222 }
223 "####, 223 "####,
@@ -235,7 +235,7 @@ string"###;
235 "#, 235 "#,
236 r##" 236 r##"
237 fn f() { 237 fn f() {
238 let s = <|>r#"random string"#; 238 let s = r#"random string"#;
239 } 239 }
240 "##, 240 "##,
241 ) 241 )
@@ -289,7 +289,7 @@ string"###;
289 "#, 289 "#,
290 r##" 290 r##"
291 fn f() { 291 fn f() {
292 let s = <|>r#"random string"#; 292 let s = r#"random string"#;
293 } 293 }
294 "##, 294 "##,
295 ) 295 )
@@ -306,7 +306,7 @@ string"###;
306 "##, 306 "##,
307 r###" 307 r###"
308 fn f() { 308 fn f() {
309 let s = <|>r##"random"string"##; 309 let s = r##"random"string"##;
310 } 310 }
311 "###, 311 "###,
312 ) 312 )
@@ -348,7 +348,7 @@ string"###;
348 "##, 348 "##,
349 r#" 349 r#"
350 fn f() { 350 fn f() {
351 let s = <|>r"random string"; 351 let s = r"random string";
352 } 352 }
353 "#, 353 "#,
354 ) 354 )
@@ -365,7 +365,7 @@ string"###;
365 "##, 365 "##,
366 r#" 366 r#"
367 fn f() { 367 fn f() {
368 let s = <|>r"random\"str\"ing"; 368 let s = r"random\"str\"ing";
369 } 369 }
370 "#, 370 "#,
371 ) 371 )
@@ -382,7 +382,7 @@ string"###;
382 "###, 382 "###,
383 r##" 383 r##"
384 fn f() { 384 fn f() {
385 let s = <|>r#"random string"#; 385 let s = r#"random string"#;
386 } 386 }
387 "##, 387 "##,
388 ) 388 )
@@ -436,7 +436,7 @@ string"###;
436 "##, 436 "##,
437 r#" 437 r#"
438 fn f() { 438 fn f() {
439 let s = <|>"random string"; 439 let s = "random string";
440 } 440 }
441 "#, 441 "#,
442 ) 442 )
@@ -453,7 +453,7 @@ string"###;
453 "##, 453 "##,
454 r#" 454 r#"
455 fn f() { 455 fn f() {
456 let s = <|>"random\"str\"ing"; 456 let s = "random\"str\"ing";
457 } 457 }
458 "#, 458 "#,
459 ) 459 )
@@ -470,7 +470,7 @@ string"###;
470 "###, 470 "###,
471 r##" 471 r##"
472 fn f() { 472 fn f() {
473 let s = <|>"random string"; 473 let s = "random string";
474 } 474 }
475 "##, 475 "##,
476 ) 476 )
diff --git a/crates/ra_assists/src/handlers/remove_dbg.rs b/crates/ra_assists/src/handlers/remove_dbg.rs
index 4e5eb4350..961ee1731 100644
--- a/crates/ra_assists/src/handlers/remove_dbg.rs
+++ b/crates/ra_assists/src/handlers/remove_dbg.rs
@@ -3,7 +3,7 @@ use ra_syntax::{
3 TextSize, T, 3 TextSize, T,
4}; 4};
5 5
6use crate::{Assist, AssistCtx, AssistId}; 6use crate::{AssistContext, AssistId, Assists};
7 7
8// Assist: remove_dbg 8// Assist: remove_dbg
9// 9//
@@ -20,7 +20,7 @@ use crate::{Assist, AssistCtx, AssistId};
20// 92; 20// 92;
21// } 21// }
22// ``` 22// ```
23pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option<Assist> { 23pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24 let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?; 24 let macro_call = ctx.find_node_at_offset::<ast::MacroCall>()?;
25 25
26 if !is_valid_macrocall(&macro_call, "dbg")? { 26 if !is_valid_macrocall(&macro_call, "dbg")? {
@@ -29,26 +29,6 @@ pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option<Assist> {
29 29
30 let macro_range = macro_call.syntax().text_range(); 30 let macro_range = macro_call.syntax().text_range();
31 31
32 // If the cursor is inside the macro call, we'll try to maintain the cursor
33 // position by subtracting the length of dbg!( from the start of the file
34 // range, otherwise we'll default to using the start of the macro call
35 let cursor_pos = {
36 let file_range = ctx.frange.range;
37
38 let offset_start = file_range
39 .start()
40 .checked_sub(macro_range.start())
41 .unwrap_or_else(|| TextSize::from(0));
42
43 let dbg_size = TextSize::of("dbg!(");
44
45 if offset_start > dbg_size {
46 file_range.start() - dbg_size
47 } else {
48 macro_range.start()
49 }
50 };
51
52 let macro_content = { 32 let macro_content = {
53 let macro_args = macro_call.token_tree()?.syntax().clone(); 33 let macro_args = macro_call.token_tree()?.syntax().clone();
54 34
@@ -57,10 +37,9 @@ pub(crate) fn remove_dbg(ctx: AssistCtx) -> Option<Assist> {
57 text.slice(without_parens).to_string() 37 text.slice(without_parens).to_string()
58 }; 38 };
59 39
60 ctx.add_assist(AssistId("remove_dbg"), "Remove dbg!()", |edit| { 40 let target = macro_call.syntax().text_range();
61 edit.target(macro_call.syntax().text_range()); 41 acc.add(AssistId("remove_dbg"), "Remove dbg!()", target, |builder| {
62 edit.replace(macro_range, macro_content); 42 builder.replace(macro_range, macro_content);
63 edit.set_cursor(cursor_pos);
64 }) 43 })
65} 44}
66 45
@@ -90,17 +69,17 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b
90#[cfg(test)] 69#[cfg(test)]
91mod tests { 70mod tests {
92 use super::*; 71 use super::*;
93 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 72 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
94 73
95 #[test] 74 #[test]
96 fn test_remove_dbg() { 75 fn test_remove_dbg() {
97 check_assist(remove_dbg, "<|>dbg!(1 + 1)", "<|>1 + 1"); 76 check_assist(remove_dbg, "<|>dbg!(1 + 1)", "1 + 1");
98 77
99 check_assist(remove_dbg, "dbg!<|>((1 + 1))", "<|>(1 + 1)"); 78 check_assist(remove_dbg, "dbg!<|>((1 + 1))", "(1 + 1)");
100 79
101 check_assist(remove_dbg, "dbg!(1 <|>+ 1)", "1 <|>+ 1"); 80 check_assist(remove_dbg, "dbg!(1 <|>+ 1)", "1 + 1");
102 81
103 check_assist(remove_dbg, "let _ = <|>dbg!(1 + 1)", "let _ = <|>1 + 1"); 82 check_assist(remove_dbg, "let _ = <|>dbg!(1 + 1)", "let _ = 1 + 1");
104 83
105 check_assist( 84 check_assist(
106 remove_dbg, 85 remove_dbg,
@@ -113,7 +92,7 @@ fn foo(n: usize) {
113", 92",
114 " 93 "
115fn foo(n: usize) { 94fn foo(n: usize) {
116 if let Some(_) = n.<|>checked_sub(4) { 95 if let Some(_) = n.checked_sub(4) {
117 // ... 96 // ...
118 } 97 }
119} 98}
@@ -122,8 +101,8 @@ fn foo(n: usize) {
122 } 101 }
123 #[test] 102 #[test]
124 fn test_remove_dbg_with_brackets_and_braces() { 103 fn test_remove_dbg_with_brackets_and_braces() {
125 check_assist(remove_dbg, "dbg![<|>1 + 1]", "<|>1 + 1"); 104 check_assist(remove_dbg, "dbg![<|>1 + 1]", "1 + 1");
126 check_assist(remove_dbg, "dbg!{<|>1 + 1}", "<|>1 + 1"); 105 check_assist(remove_dbg, "dbg!{<|>1 + 1}", "1 + 1");
127 } 106 }
128 107
129 #[test] 108 #[test]
diff --git a/crates/ra_assists/src/handlers/remove_mut.rs b/crates/ra_assists/src/handlers/remove_mut.rs
index e598023b2..fe4eada03 100644
--- a/crates/ra_assists/src/handlers/remove_mut.rs
+++ b/crates/ra_assists/src/handlers/remove_mut.rs
@@ -1,6 +1,6 @@
1use ra_syntax::{SyntaxKind, TextRange, T}; 1use ra_syntax::{SyntaxKind, TextRange, T};
2 2
3use crate::{Assist, AssistCtx, AssistId}; 3use crate::{AssistContext, AssistId, Assists};
4 4
5// Assist: remove_mut 5// Assist: remove_mut
6// 6//
@@ -17,7 +17,7 @@ use crate::{Assist, AssistCtx, AssistId};
17// fn feed(&self, amount: u32) {} 17// fn feed(&self, amount: u32) {}
18// } 18// }
19// ``` 19// ```
20pub(crate) fn remove_mut(ctx: AssistCtx) -> Option<Assist> { 20pub(crate) fn remove_mut(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
21 let mut_token = ctx.find_token_at_offset(T![mut])?; 21 let mut_token = ctx.find_token_at_offset(T![mut])?;
22 let delete_from = mut_token.text_range().start(); 22 let delete_from = mut_token.text_range().start();
23 let delete_to = match mut_token.next_token() { 23 let delete_to = match mut_token.next_token() {
@@ -25,8 +25,8 @@ pub(crate) fn remove_mut(ctx: AssistCtx) -> Option<Assist> {
25 _ => mut_token.text_range().end(), 25 _ => mut_token.text_range().end(),
26 }; 26 };
27 27
28 ctx.add_assist(AssistId("remove_mut"), "Remove `mut` keyword", |edit| { 28 let target = mut_token.text_range();
29 edit.set_cursor(delete_from); 29 acc.add(AssistId("remove_mut"), "Remove `mut` keyword", target, |builder| {
30 edit.delete(TextRange::new(delete_from, delete_to)); 30 builder.delete(TextRange::new(delete_from, delete_to));
31 }) 31 })
32} 32}
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs
index 5cbb98d73..30229edc2 100644
--- a/crates/ra_assists/src/handlers/reorder_fields.rs
+++ b/crates/ra_assists/src/handlers/reorder_fields.rs
@@ -3,18 +3,9 @@ use std::collections::HashMap;
3use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; 3use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct};
4use itertools::Itertools; 4use itertools::Itertools;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{ 6use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode};
7 algo, 7
8 ast::{self, Path, RecordLit, RecordPat}, 8use crate::{AssistContext, AssistId, Assists};
9 match_ast, AstNode, SyntaxKind,
10 SyntaxKind::*,
11 SyntaxNode,
12};
13
14use crate::{
15 assist_ctx::{Assist, AssistCtx},
16 AssistId,
17};
18 9
19// Assist: reorder_fields 10// Assist: reorder_fields
20// 11//
@@ -31,13 +22,13 @@ use crate::{
31// const test: Foo = Foo {foo: 1, bar: 0} 22// const test: Foo = Foo {foo: 1, bar: 0}
32// ``` 23// ```
33// 24//
34pub(crate) fn reorder_fields(ctx: AssistCtx) -> Option<Assist> { 25pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
35 reorder::<RecordLit>(ctx.clone()).or_else(|| reorder::<RecordPat>(ctx)) 26 reorder::<ast::RecordLit>(acc, ctx.clone()).or_else(|| reorder::<ast::RecordPat>(acc, ctx))
36} 27}
37 28
38fn reorder<R: AstNode>(ctx: AssistCtx) -> Option<Assist> { 29fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
39 let record = ctx.find_node_at_offset::<R>()?; 30 let record = ctx.find_node_at_offset::<R>()?;
40 let path = record.syntax().children().find_map(Path::cast)?; 31 let path = record.syntax().children().find_map(ast::Path::cast)?;
41 32
42 let ranks = compute_fields_ranks(&path, &ctx)?; 33 let ranks = compute_fields_ranks(&path, &ctx)?;
43 34
@@ -50,11 +41,11 @@ fn reorder<R: AstNode>(ctx: AssistCtx) -> Option<Assist> {
50 return None; 41 return None;
51 } 42 }
52 43
53 ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", |edit| { 44 let target = record.syntax().text_range();
45 acc.add(AssistId("reorder_fields"), "Reorder record fields", target, |edit| {
54 for (old, new) in fields.iter().zip(&sorted_fields) { 46 for (old, new) in fields.iter().zip(&sorted_fields) {
55 algo::diff(old, new).into_text_edit(edit.text_edit_builder()); 47 algo::diff(old, new).into_text_edit(edit.text_edit_builder());
56 } 48 }
57 edit.target(record.syntax().text_range())
58 }) 49 })
59} 50}
60 51
@@ -96,9 +87,9 @@ fn struct_definition(path: &ast::Path, sema: &Semantics<RootDatabase>) -> Option
96 } 87 }
97} 88}
98 89
99fn compute_fields_ranks(path: &Path, ctx: &AssistCtx) -> Option<HashMap<String, usize>> { 90fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<HashMap<String, usize>> {
100 Some( 91 Some(
101 struct_definition(path, ctx.sema)? 92 struct_definition(path, &ctx.sema)?
102 .fields(ctx.db) 93 .fields(ctx.db)
103 .iter() 94 .iter()
104 .enumerate() 95 .enumerate()
@@ -109,7 +100,7 @@ fn compute_fields_ranks(path: &Path, ctx: &AssistCtx) -> Option<HashMap<String,
109 100
110#[cfg(test)] 101#[cfg(test)]
111mod tests { 102mod tests {
112 use crate::helpers::{check_assist, check_assist_not_applicable}; 103 use crate::tests::{check_assist, check_assist_not_applicable};
113 104
114 use super::*; 105 use super::*;
115 106
@@ -149,7 +140,7 @@ mod tests {
149 "#, 140 "#,
150 r#" 141 r#"
151 struct Foo {foo: i32, bar: i32}; 142 struct Foo {foo: i32, bar: i32};
152 const test: Foo = <|>Foo {foo: 1, bar: 0} 143 const test: Foo = Foo {foo: 1, bar: 0}
153 "#, 144 "#,
154 ) 145 )
155 } 146 }
@@ -173,7 +164,7 @@ mod tests {
173 164
174 fn f(f: Foo) -> { 165 fn f(f: Foo) -> {
175 match f { 166 match f {
176 <|>Foo { ref mut bar, baz: 0, .. } => (), 167 Foo { ref mut bar, baz: 0, .. } => (),
177 _ => () 168 _ => ()
178 } 169 }
179 } 170 }
@@ -211,7 +202,7 @@ mod tests {
211 impl Foo { 202 impl Foo {
212 fn new() -> Foo { 203 fn new() -> Foo {
213 let foo = String::new(); 204 let foo = String::new();
214 <|>Foo { 205 Foo {
215 foo, 206 foo,
216 bar: foo.clone(), 207 bar: foo.clone(),
217 extra: "Extra field", 208 extra: "Extra field",
diff --git a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
index 9841f6980..e016f51c3 100644
--- a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
@@ -1,10 +1,14 @@
1use ra_fmt::unwrap_trivial_block; 1use ra_fmt::unwrap_trivial_block;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, edit::IndentLevel, make}, 3 ast::{
4 self,
5 edit::{AstNodeEdit, IndentLevel},
6 make,
7 },
4 AstNode, 8 AstNode,
5}; 9};
6 10
7use crate::{utils::TryEnum, Assist, AssistCtx, AssistId}; 11use crate::{utils::TryEnum, AssistContext, AssistId, Assists};
8 12
9// Assist: replace_if_let_with_match 13// Assist: replace_if_let_with_match
10// 14//
@@ -32,7 +36,7 @@ use crate::{utils::TryEnum, Assist, AssistCtx, AssistId};
32// } 36// }
33// } 37// }
34// ``` 38// ```
35pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> { 39pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
36 let if_expr: ast::IfExpr = ctx.find_node_at_offset()?; 40 let if_expr: ast::IfExpr = ctx.find_node_at_offset()?;
37 let cond = if_expr.condition()?; 41 let cond = if_expr.condition()?;
38 let pat = cond.pat()?; 42 let pat = cond.pat()?;
@@ -43,29 +47,27 @@ pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> {
43 ast::ElseBranch::IfExpr(_) => return None, 47 ast::ElseBranch::IfExpr(_) => return None,
44 }; 48 };
45 49
46 let sema = ctx.sema; 50 let target = if_expr.syntax().text_range();
47 ctx.add_assist(AssistId("replace_if_let_with_match"), "Replace with match", move |edit| { 51 acc.add(AssistId("replace_if_let_with_match"), "Replace with match", target, move |edit| {
48 let match_expr = { 52 let match_expr = {
49 let then_arm = { 53 let then_arm = {
50 let then_expr = unwrap_trivial_block(then_block); 54 let then_expr = unwrap_trivial_block(then_block);
51 make::match_arm(vec![pat.clone()], then_expr) 55 make::match_arm(vec![pat.clone()], then_expr)
52 }; 56 };
53 let else_arm = { 57 let else_arm = {
54 let pattern = sema 58 let pattern = ctx
59 .sema
55 .type_of_pat(&pat) 60 .type_of_pat(&pat)
56 .and_then(|ty| TryEnum::from_ty(sema, &ty)) 61 .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty))
57 .map(|it| it.sad_pattern()) 62 .map(|it| it.sad_pattern())
58 .unwrap_or_else(|| make::placeholder_pat().into()); 63 .unwrap_or_else(|| make::placeholder_pat().into());
59 let else_expr = unwrap_trivial_block(else_block); 64 let else_expr = unwrap_trivial_block(else_block);
60 make::match_arm(vec![pattern], else_expr) 65 make::match_arm(vec![pattern], else_expr)
61 }; 66 };
62 make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm])) 67 make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm]))
68 .indent(IndentLevel::from_node(if_expr.syntax()))
63 }; 69 };
64 70
65 let match_expr = IndentLevel::from_node(if_expr.syntax()).increase_indent(match_expr);
66
67 edit.target(if_expr.syntax().text_range());
68 edit.set_cursor(if_expr.syntax().text_range().start());
69 edit.replace_ast::<ast::Expr>(if_expr.into(), match_expr); 71 edit.replace_ast::<ast::Expr>(if_expr.into(), match_expr);
70 }) 72 })
71} 73}
@@ -74,13 +76,13 @@ pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> {
74mod tests { 76mod tests {
75 use super::*; 77 use super::*;
76 78
77 use crate::helpers::{check_assist, check_assist_target}; 79 use crate::tests::{check_assist, check_assist_target};
78 80
79 #[test] 81 #[test]
80 fn test_replace_if_let_with_match_unwraps_simple_expressions() { 82 fn test_replace_if_let_with_match_unwraps_simple_expressions() {
81 check_assist( 83 check_assist(
82 replace_if_let_with_match, 84 replace_if_let_with_match,
83 " 85 r#"
84impl VariantData { 86impl VariantData {
85 pub fn is_struct(&self) -> bool { 87 pub fn is_struct(&self) -> bool {
86 if <|>let VariantData::Struct(..) = *self { 88 if <|>let VariantData::Struct(..) = *self {
@@ -89,16 +91,16 @@ impl VariantData {
89 false 91 false
90 } 92 }
91 } 93 }
92} ", 94} "#,
93 " 95 r#"
94impl VariantData { 96impl VariantData {
95 pub fn is_struct(&self) -> bool { 97 pub fn is_struct(&self) -> bool {
96 <|>match *self { 98 match *self {
97 VariantData::Struct(..) => true, 99 VariantData::Struct(..) => true,
98 _ => false, 100 _ => false,
99 } 101 }
100 } 102 }
101} ", 103} "#,
102 ) 104 )
103 } 105 }
104 106
@@ -106,7 +108,7 @@ impl VariantData {
106 fn test_replace_if_let_with_match_doesnt_unwrap_multiline_expressions() { 108 fn test_replace_if_let_with_match_doesnt_unwrap_multiline_expressions() {
107 check_assist( 109 check_assist(
108 replace_if_let_with_match, 110 replace_if_let_with_match,
109 " 111 r#"
110fn foo() { 112fn foo() {
111 if <|>let VariantData::Struct(..) = a { 113 if <|>let VariantData::Struct(..) = a {
112 bar( 114 bar(
@@ -115,10 +117,10 @@ fn foo() {
115 } else { 117 } else {
116 false 118 false
117 } 119 }
118} ", 120} "#,
119 " 121 r#"
120fn foo() { 122fn foo() {
121 <|>match a { 123 match a {
122 VariantData::Struct(..) => { 124 VariantData::Struct(..) => {
123 bar( 125 bar(
124 123 126 123
@@ -126,7 +128,7 @@ fn foo() {
126 } 128 }
127 _ => false, 129 _ => false,
128 } 130 }
129} ", 131} "#,
130 ) 132 )
131 } 133 }
132 134
@@ -134,7 +136,7 @@ fn foo() {
134 fn replace_if_let_with_match_target() { 136 fn replace_if_let_with_match_target() {
135 check_assist_target( 137 check_assist_target(
136 replace_if_let_with_match, 138 replace_if_let_with_match,
137 " 139 r#"
138impl VariantData { 140impl VariantData {
139 pub fn is_struct(&self) -> bool { 141 pub fn is_struct(&self) -> bool {
140 if <|>let VariantData::Struct(..) = *self { 142 if <|>let VariantData::Struct(..) = *self {
@@ -143,7 +145,7 @@ impl VariantData {
143 false 145 false
144 } 146 }
145 } 147 }
146} ", 148} "#,
147 "if let VariantData::Struct(..) = *self { 149 "if let VariantData::Struct(..) = *self {
148 true 150 true
149 } else { 151 } else {
@@ -173,7 +175,7 @@ enum Option<T> { Some(T), None }
173use Option::*; 175use Option::*;
174 176
175fn foo(x: Option<i32>) { 177fn foo(x: Option<i32>) {
176 <|>match x { 178 match x {
177 Some(x) => println!("{}", x), 179 Some(x) => println!("{}", x),
178 None => println!("none"), 180 None => println!("none"),
179 } 181 }
@@ -203,7 +205,7 @@ enum Result<T, E> { Ok(T), Err(E) }
203use Result::*; 205use Result::*;
204 206
205fn foo(x: Result<i32, ()>) { 207fn foo(x: Result<i32, ()>) {
206 <|>match x { 208 match x {
207 Ok(x) => println!("{}", x), 209 Ok(x) => println!("{}", x),
208 Err(_) => println!("none"), 210 Err(_) => println!("none"),
209 } 211 }
diff --git a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
index 0cf23b754..761557ac0 100644
--- a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
@@ -9,11 +9,7 @@ use ra_syntax::{
9 AstNode, T, 9 AstNode, T,
10}; 10};
11 11
12use crate::{ 12use crate::{utils::TryEnum, AssistContext, AssistId, Assists};
13 assist_ctx::{Assist, AssistCtx},
14 utils::TryEnum,
15 AssistId,
16};
17 13
18// Assist: replace_let_with_if_let 14// Assist: replace_let_with_if_let
19// 15//
@@ -39,15 +35,16 @@ use crate::{
39// 35//
40// fn compute() -> Option<i32> { None } 36// fn compute() -> Option<i32> { None }
41// ``` 37// ```
42pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option<Assist> { 38pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
43 let let_kw = ctx.find_token_at_offset(T![let])?; 39 let let_kw = ctx.find_token_at_offset(T![let])?;
44 let let_stmt = let_kw.ancestors().find_map(ast::LetStmt::cast)?; 40 let let_stmt = let_kw.ancestors().find_map(ast::LetStmt::cast)?;
45 let init = let_stmt.initializer()?; 41 let init = let_stmt.initializer()?;
46 let original_pat = let_stmt.pat()?; 42 let original_pat = let_stmt.pat()?;
47 let ty = ctx.sema.type_of_expr(&init)?; 43 let ty = ctx.sema.type_of_expr(&init)?;
48 let happy_variant = TryEnum::from_ty(ctx.sema, &ty).map(|it| it.happy_case()); 44 let happy_variant = TryEnum::from_ty(&ctx.sema, &ty).map(|it| it.happy_case());
49 45
50 ctx.add_assist(AssistId("replace_let_with_if_let"), "Replace with if-let", |edit| { 46 let target = let_kw.text_range();
47 acc.add(AssistId("replace_let_with_if_let"), "Replace with if-let", target, |edit| {
51 let with_placeholder: ast::Pat = match happy_variant { 48 let with_placeholder: ast::Pat = match happy_variant {
52 None => make::placeholder_pat().into(), 49 None => make::placeholder_pat().into(),
53 Some(var_name) => make::tuple_struct_pat( 50 Some(var_name) => make::tuple_struct_pat(
@@ -56,25 +53,20 @@ pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option<Assist> {
56 ) 53 )
57 .into(), 54 .into(),
58 }; 55 };
59 let block = 56 let block = make::block_expr(None, None).indent(IndentLevel::from_node(let_stmt.syntax()));
60 IndentLevel::from_node(let_stmt.syntax()).increase_indent(make::block_expr(None, None));
61 let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block); 57 let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block);
62 let stmt = make::expr_stmt(if_); 58 let stmt = make::expr_stmt(if_);
63 59
64 let placeholder = stmt.syntax().descendants().find_map(ast::PlaceholderPat::cast).unwrap(); 60 let placeholder = stmt.syntax().descendants().find_map(ast::PlaceholderPat::cast).unwrap();
65 let target_offset =
66 let_stmt.syntax().text_range().start() + placeholder.syntax().text_range().start();
67 let stmt = stmt.replace_descendant(placeholder.into(), original_pat); 61 let stmt = stmt.replace_descendant(placeholder.into(), original_pat);
68 62
69 edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); 63 edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt));
70 edit.target(let_kw.text_range());
71 edit.set_cursor(target_offset);
72 }) 64 })
73} 65}
74 66
75#[cfg(test)] 67#[cfg(test)]
76mod tests { 68mod tests {
77 use crate::helpers::check_assist; 69 use crate::tests::check_assist;
78 70
79 use super::*; 71 use super::*;
80 72
@@ -93,7 +85,7 @@ fn main() {
93enum E<T> { X(T), Y(T) } 85enum E<T> { X(T), Y(T) }
94 86
95fn main() { 87fn main() {
96 if let <|>x = E::X(92) { 88 if let x = E::X(92) {
97 } 89 }
98} 90}
99 ", 91 ",
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
index 918e8dd8d..0197a8cf0 100644
--- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -1,11 +1,7 @@
1use hir; 1use hir;
2use ra_syntax::{ast, AstNode, SmolStr, TextRange}; 2use ra_syntax::{ast, AstNode, SmolStr, TextRange};
3 3
4use crate::{ 4use crate::{utils::insert_use_statement, AssistContext, AssistId, Assists};
5 assist_ctx::{Assist, AssistCtx},
6 utils::insert_use_statement,
7 AssistId,
8};
9 5
10// Assist: replace_qualified_name_with_use 6// Assist: replace_qualified_name_with_use
11// 7//
@@ -20,7 +16,10 @@ use crate::{
20// 16//
21// fn process(map: HashMap<String, String>) {} 17// fn process(map: HashMap<String, String>) {}
22// ``` 18// ```
23pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option<Assist> { 19pub(crate) fn replace_qualified_name_with_use(
20 acc: &mut Assists,
21 ctx: &AssistContext,
22) -> Option<()> {
24 let path: ast::Path = ctx.find_node_at_offset()?; 23 let path: ast::Path = ctx.find_node_at_offset()?;
25 // We don't want to mess with use statements 24 // We don't want to mess with use statements
26 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() { 25 if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
@@ -33,17 +32,19 @@ pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option<Assist>
33 return None; 32 return None;
34 } 33 }
35 34
36 ctx.add_assist( 35 let target = path.syntax().text_range();
36 acc.add(
37 AssistId("replace_qualified_name_with_use"), 37 AssistId("replace_qualified_name_with_use"),
38 "Replace qualified path with use", 38 "Replace qualified path with use",
39 |edit| { 39 target,
40 |builder| {
40 let path_to_import = hir_path.mod_path().clone(); 41 let path_to_import = hir_path.mod_path().clone();
41 insert_use_statement(path.syntax(), &path_to_import, edit.text_edit_builder()); 42 insert_use_statement(path.syntax(), &path_to_import, ctx, builder.text_edit_builder());
42 43
43 if let Some(last) = path.segment() { 44 if let Some(last) = path.segment() {
44 // Here we are assuming the assist will provide a correct use statement 45 // Here we are assuming the assist will provide a correct use statement
45 // so we can delete the path qualifier 46 // so we can delete the path qualifier
46 edit.delete(TextRange::new( 47 builder.delete(TextRange::new(
47 path.syntax().text_range().start(), 48 path.syntax().text_range().start(),
48 last.syntax().text_range().start(), 49 last.syntax().text_range().start(),
49 )); 50 ));
@@ -74,7 +75,7 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
74 75
75#[cfg(test)] 76#[cfg(test)]
76mod tests { 77mod tests {
77 use crate::helpers::{check_assist, check_assist_not_applicable}; 78 use crate::tests::{check_assist, check_assist_not_applicable};
78 79
79 use super::*; 80 use super::*;
80 81
@@ -88,7 +89,7 @@ std::fmt::Debug<|>
88 " 89 "
89use std::fmt::Debug; 90use std::fmt::Debug;
90 91
91Debug<|> 92Debug
92 ", 93 ",
93 ); 94 );
94 } 95 }
@@ -105,7 +106,7 @@ fn main() {
105 " 106 "
106use std::fmt::Debug; 107use std::fmt::Debug;
107 108
108Debug<|> 109Debug
109 110
110fn main() { 111fn main() {
111} 112}
@@ -129,7 +130,7 @@ use std::fmt::Debug;
129fn main() { 130fn main() {
130} 131}
131 132
132Debug<|> 133Debug
133 ", 134 ",
134 ); 135 );
135 } 136 }
@@ -144,7 +145,7 @@ std::fmt<|>::Debug
144 " 145 "
145use std::fmt; 146use std::fmt;
146 147
147fmt<|>::Debug 148fmt::Debug
148 ", 149 ",
149 ); 150 );
150 } 151 }
@@ -163,7 +164,7 @@ impl std::fmt::Debug<|> for Foo {
163use stdx; 164use stdx;
164use std::fmt::Debug; 165use std::fmt::Debug;
165 166
166impl Debug<|> for Foo { 167impl Debug for Foo {
167} 168}
168 ", 169 ",
169 ); 170 );
@@ -180,7 +181,7 @@ impl std::fmt::Debug<|> for Foo {
180 " 181 "
181use std::fmt::Debug; 182use std::fmt::Debug;
182 183
183impl Debug<|> for Foo { 184impl Debug for Foo {
184} 185}
185 ", 186 ",
186 ); 187 );
@@ -197,7 +198,7 @@ impl Debug<|> for Foo {
197 " 198 "
198 use std::fmt::Debug; 199 use std::fmt::Debug;
199 200
200 impl Debug<|> for Foo { 201 impl Debug for Foo {
201 } 202 }
202 ", 203 ",
203 ); 204 );
@@ -216,7 +217,7 @@ impl std::io<|> for Foo {
216 " 217 "
217use std::{io, fmt}; 218use std::{io, fmt};
218 219
219impl io<|> for Foo { 220impl io for Foo {
220} 221}
221 ", 222 ",
222 ); 223 );
@@ -235,7 +236,7 @@ impl std::fmt::Debug<|> for Foo {
235 " 236 "
236use std::fmt::{self, Debug, }; 237use std::fmt::{self, Debug, };
237 238
238impl Debug<|> for Foo { 239impl Debug for Foo {
239} 240}
240 ", 241 ",
241 ); 242 );
@@ -254,7 +255,7 @@ impl std::fmt<|> for Foo {
254 " 255 "
255use std::fmt::{self, Debug}; 256use std::fmt::{self, Debug};
256 257
257impl fmt<|> for Foo { 258impl fmt for Foo {
258} 259}
259 ", 260 ",
260 ); 261 );
@@ -273,7 +274,7 @@ impl std::fmt::nested<|> for Foo {
273 " 274 "
274use std::fmt::{Debug, nested::{Display, self}}; 275use std::fmt::{Debug, nested::{Display, self}};
275 276
276impl nested<|> for Foo { 277impl nested for Foo {
277} 278}
278", 279",
279 ); 280 );
@@ -292,7 +293,7 @@ impl std::fmt::nested<|> for Foo {
292 " 293 "
293use std::fmt::{Debug, nested::{self, Display}}; 294use std::fmt::{Debug, nested::{self, Display}};
294 295
295impl nested<|> for Foo { 296impl nested for Foo {
296} 297}
297", 298",
298 ); 299 );
@@ -311,7 +312,7 @@ impl std::fmt::nested::Debug<|> for Foo {
311 " 312 "
312use std::fmt::{Debug, nested::{Display, Debug}}; 313use std::fmt::{Debug, nested::{Display, Debug}};
313 314
314impl Debug<|> for Foo { 315impl Debug for Foo {
315} 316}
316", 317",
317 ); 318 );
@@ -330,7 +331,7 @@ impl std::fmt::nested::Display<|> for Foo {
330 " 331 "
331use std::fmt::{nested::Display, Debug}; 332use std::fmt::{nested::Display, Debug};
332 333
333impl Display<|> for Foo { 334impl Display for Foo {
334} 335}
335", 336",
336 ); 337 );
@@ -349,7 +350,7 @@ impl std::fmt::Display<|> for Foo {
349 " 350 "
350use std::fmt::{Display, nested::Debug}; 351use std::fmt::{Display, nested::Debug};
351 352
352impl Display<|> for Foo { 353impl Display for Foo {
353} 354}
354", 355",
355 ); 356 );
@@ -373,7 +374,7 @@ use crate::{
373 AssocItem, 374 AssocItem,
374}; 375};
375 376
376fn foo() { lower<|>::trait_env() } 377fn foo() { lower::trait_env() }
377", 378",
378 ); 379 );
379 } 380 }
@@ -391,7 +392,7 @@ impl foo::Debug<|> for Foo {
391 " 392 "
392use std::fmt as foo; 393use std::fmt as foo;
393 394
394impl Debug<|> for Foo { 395impl Debug for Foo {
395} 396}
396", 397",
397 ); 398 );
@@ -434,7 +435,7 @@ mod foo {
434 mod bar { 435 mod bar {
435 use std::fmt::Debug; 436 use std::fmt::Debug;
436 437
437 Debug<|> 438 Debug
438 } 439 }
439} 440}
440 ", 441 ",
@@ -457,7 +458,7 @@ fn main() {
457use std::fmt::Debug; 458use std::fmt::Debug;
458 459
459fn main() { 460fn main() {
460 Debug<|> 461 Debug
461} 462}
462 ", 463 ",
463 ); 464 );
diff --git a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
index 62d4ea522..cff7dfb81 100644
--- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
@@ -1,11 +1,18 @@
1use std::iter; 1use std::iter;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, edit::IndentLevel, make}, 4 ast::{
5 self,
6 edit::{AstNodeEdit, IndentLevel},
7 make,
8 },
5 AstNode, 9 AstNode,
6}; 10};
7 11
8use crate::{utils::TryEnum, Assist, AssistCtx, AssistId}; 12use crate::{
13 utils::{render_snippet, Cursor, TryEnum},
14 AssistContext, AssistId, Assists,
15};
9 16
10// Assist: replace_unwrap_with_match 17// Assist: replace_unwrap_with_match
11// 18//
@@ -25,11 +32,11 @@ use crate::{utils::TryEnum, Assist, AssistCtx, AssistId};
25// let x: Result<i32, i32> = Result::Ok(92); 32// let x: Result<i32, i32> = Result::Ok(92);
26// let y = match x { 33// let y = match x {
27// Ok(a) => a, 34// Ok(a) => a,
28// _ => unreachable!(), 35// $0_ => unreachable!(),
29// }; 36// };
30// } 37// }
31// ``` 38// ```
32pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> { 39pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
33 let method_call: ast::MethodCallExpr = ctx.find_node_at_offset()?; 40 let method_call: ast::MethodCallExpr = ctx.find_node_at_offset()?;
34 let name = method_call.name_ref()?; 41 let name = method_call.name_ref()?;
35 if name.text() != "unwrap" { 42 if name.text() != "unwrap" {
@@ -37,9 +44,9 @@ pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> {
37 } 44 }
38 let caller = method_call.expr()?; 45 let caller = method_call.expr()?;
39 let ty = ctx.sema.type_of_expr(&caller)?; 46 let ty = ctx.sema.type_of_expr(&caller)?;
40 let happy_variant = TryEnum::from_ty(ctx.sema, &ty)?.happy_case(); 47 let happy_variant = TryEnum::from_ty(&ctx.sema, &ty)?.happy_case();
41 48 let target = method_call.syntax().text_range();
42 ctx.add_assist(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", |edit| { 49 acc.add(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", target, |builder| {
43 let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); 50 let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant)));
44 let it = make::bind_pat(make::name("a")).into(); 51 let it = make::bind_pat(make::name("a")).into();
45 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); 52 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
@@ -47,23 +54,36 @@ pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> {
47 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); 54 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a")));
48 let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); 55 let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path));
49 56
50 let unreachable_call = make::unreachable_macro_call().into(); 57 let unreachable_call = make::expr_unreachable();
51 let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); 58 let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call);
52 59
53 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); 60 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]);
54 let match_expr = make::expr_match(caller.clone(), match_arm_list); 61 let match_expr = make::expr_match(caller.clone(), match_arm_list)
55 let match_expr = IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr); 62 .indent(IndentLevel::from_node(method_call.syntax()));
56 63
57 edit.target(method_call.syntax().text_range()); 64 let range = method_call.syntax().text_range();
58 edit.set_cursor(caller.syntax().text_range().start()); 65 match ctx.config.snippet_cap {
59 edit.replace_ast::<ast::Expr>(method_call.into(), match_expr); 66 Some(cap) => {
67 let err_arm = match_expr
68 .syntax()
69 .descendants()
70 .filter_map(ast::MatchArm::cast)
71 .last()
72 .unwrap();
73 let snippet =
74 render_snippet(cap, match_expr.syntax(), Cursor::Before(err_arm.syntax()));
75 builder.replace_snippet(cap, range, snippet)
76 }
77 None => builder.replace(range, match_expr.to_string()),
78 }
60 }) 79 })
61} 80}
62 81
63#[cfg(test)] 82#[cfg(test)]
64mod tests { 83mod tests {
84 use crate::tests::{check_assist, check_assist_target};
85
65 use super::*; 86 use super::*;
66 use crate::helpers::{check_assist, check_assist_target};
67 87
68 #[test] 88 #[test]
69 fn test_replace_result_unwrap_with_match() { 89 fn test_replace_result_unwrap_with_match() {
@@ -82,9 +102,9 @@ enum Result<T, E> { Ok(T), Err(E) }
82fn i<T>(a: T) -> T { a } 102fn i<T>(a: T) -> T { a }
83fn main() { 103fn main() {
84 let x: Result<i32, i32> = Result::Ok(92); 104 let x: Result<i32, i32> = Result::Ok(92);
85 let y = <|>match i(x) { 105 let y = match i(x) {
86 Ok(a) => a, 106 Ok(a) => a,
87 _ => unreachable!(), 107 $0_ => unreachable!(),
88 }; 108 };
89} 109}
90 ", 110 ",
@@ -108,9 +128,9 @@ enum Option<T> { Some(T), None }
108fn i<T>(a: T) -> T { a } 128fn i<T>(a: T) -> T { a }
109fn main() { 129fn main() {
110 let x = Option::Some(92); 130 let x = Option::Some(92);
111 let y = <|>match i(x) { 131 let y = match i(x) {
112 Some(a) => a, 132 Some(a) => a,
113 _ => unreachable!(), 133 $0_ => unreachable!(),
114 }; 134 };
115} 135}
116 ", 136 ",
@@ -134,9 +154,9 @@ enum Result<T, E> { Ok(T), Err(E) }
134fn i<T>(a: T) -> T { a } 154fn i<T>(a: T) -> T { a }
135fn main() { 155fn main() {
136 let x: Result<i32, i32> = Result::Ok(92); 156 let x: Result<i32, i32> = Result::Ok(92);
137 let y = <|>match i(x) { 157 let y = match i(x) {
138 Ok(a) => a, 158 Ok(a) => a,
139 _ => unreachable!(), 159 $0_ => unreachable!(),
140 }.count_zeroes(); 160 }.count_zeroes();
141} 161}
142 ", 162 ",
diff --git a/crates/ra_assists/src/handlers/split_import.rs b/crates/ra_assists/src/handlers/split_import.rs
index f25826796..c7a874480 100644
--- a/crates/ra_assists/src/handlers/split_import.rs
+++ b/crates/ra_assists/src/handlers/split_import.rs
@@ -2,7 +2,7 @@ use std::iter::successors;
2 2
3use ra_syntax::{ast, AstNode, T}; 3use ra_syntax::{ast, AstNode, T};
4 4
5use crate::{Assist, AssistCtx, AssistId}; 5use crate::{AssistContext, AssistId, Assists};
6 6
7// Assist: split_import 7// Assist: split_import
8// 8//
@@ -15,7 +15,7 @@ use crate::{Assist, AssistCtx, AssistId};
15// ``` 15// ```
16// use std::{collections::HashMap}; 16// use std::{collections::HashMap};
17// ``` 17// ```
18pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> { 18pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
19 let colon_colon = ctx.find_token_at_offset(T![::])?; 19 let colon_colon = ctx.find_token_at_offset(T![::])?;
20 let path = ast::Path::cast(colon_colon.parent())?.qualifier()?; 20 let path = ast::Path::cast(colon_colon.parent())?.qualifier()?;
21 let top_path = successors(Some(path.clone()), |it| it.parent_path()).last()?; 21 let top_path = successors(Some(path.clone()), |it| it.parent_path()).last()?;
@@ -26,18 +26,16 @@ pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> {
26 if new_tree == use_tree { 26 if new_tree == use_tree {
27 return None; 27 return None;
28 } 28 }
29 let cursor = ctx.frange.range.start();
30 29
31 ctx.add_assist(AssistId("split_import"), "Split import", |edit| { 30 let target = colon_colon.text_range();
32 edit.target(colon_colon.text_range()); 31 acc.add(AssistId("split_import"), "Split import", target, |edit| {
33 edit.replace_ast(use_tree, new_tree); 32 edit.replace_ast(use_tree, new_tree);
34 edit.set_cursor(cursor);
35 }) 33 })
36} 34}
37 35
38#[cfg(test)] 36#[cfg(test)]
39mod tests { 37mod tests {
40 use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; 38 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
41 39
42 use super::*; 40 use super::*;
43 41
@@ -46,7 +44,7 @@ mod tests {
46 check_assist( 44 check_assist(
47 split_import, 45 split_import,
48 "use crate::<|>db::RootDatabase;", 46 "use crate::<|>db::RootDatabase;",
49 "use crate::<|>{db::RootDatabase};", 47 "use crate::{db::RootDatabase};",
50 ) 48 )
51 } 49 }
52 50
@@ -55,7 +53,7 @@ mod tests {
55 check_assist( 53 check_assist(
56 split_import, 54 split_import,
57 "use crate:<|>:db::{RootDatabase, FileSymbol}", 55 "use crate:<|>:db::{RootDatabase, FileSymbol}",
58 "use crate:<|>:{db::{RootDatabase, FileSymbol}}", 56 "use crate::{db::{RootDatabase, FileSymbol}}",
59 ) 57 )
60 } 58 }
61 59
diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs
new file mode 100644
index 000000000..8440c7d0f
--- /dev/null
+++ b/crates/ra_assists/src/handlers/unwrap_block.rs
@@ -0,0 +1,512 @@
1use ra_fmt::unwrap_trivial_block;
2use ra_syntax::{
3 ast::{self, ElseBranch, Expr, LoopBodyOwner},
4 match_ast, AstNode, TextRange, T,
5};
6
7use crate::{AssistContext, AssistId, Assists};
8
9// Assist: unwrap_block
10//
11// This assist removes if...else, for, while and loop control statements to just keep the body.
12//
13// ```
14// fn foo() {
15// if true {<|>
16// println!("foo");
17// }
18// }
19// ```
20// ->
21// ```
22// fn foo() {
23// println!("foo");
24// }
25// ```
26pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
27 let l_curly_token = ctx.find_token_at_offset(T!['{'])?;
28 let block = ast::BlockExpr::cast(l_curly_token.parent())?;
29 let parent = block.syntax().parent()?;
30 let assist_id = AssistId("unwrap_block");
31 let assist_label = "Unwrap block";
32
33 let (expr, expr_to_unwrap) = match_ast! {
34 match parent {
35 ast::ForExpr(for_expr) => {
36 let block_expr = for_expr.loop_body()?;
37 let expr_to_unwrap = extract_expr(ctx.frange.range, block_expr)?;
38 (ast::Expr::ForExpr(for_expr), expr_to_unwrap)
39 },
40 ast::WhileExpr(while_expr) => {
41 let block_expr = while_expr.loop_body()?;
42 let expr_to_unwrap = extract_expr(ctx.frange.range, block_expr)?;
43 (ast::Expr::WhileExpr(while_expr), expr_to_unwrap)
44 },
45 ast::LoopExpr(loop_expr) => {
46 let block_expr = loop_expr.loop_body()?;
47 let expr_to_unwrap = extract_expr(ctx.frange.range, block_expr)?;
48 (ast::Expr::LoopExpr(loop_expr), expr_to_unwrap)
49 },
50 ast::IfExpr(if_expr) => {
51 let mut resp = None;
52
53 let then_branch = if_expr.then_branch()?;
54 if then_branch.l_curly_token()?.text_range().contains_range(ctx.frange.range) {
55 if let Some(ancestor) = if_expr.syntax().parent().and_then(ast::IfExpr::cast) {
56 // For `else if` blocks
57 let ancestor_then_branch = ancestor.then_branch()?;
58 let l_curly_token = then_branch.l_curly_token()?;
59
60 let target = then_branch.syntax().text_range();
61 return acc.add(assist_id, assist_label, target, |edit| {
62 let range_to_del_else_if = TextRange::new(ancestor_then_branch.syntax().text_range().end(), l_curly_token.text_range().start());
63 let range_to_del_rest = TextRange::new(then_branch.syntax().text_range().end(), if_expr.syntax().text_range().end());
64
65 edit.delete(range_to_del_rest);
66 edit.delete(range_to_del_else_if);
67 edit.replace(target, update_expr_string(then_branch.to_string(), &[' ', '{']));
68 });
69 } else {
70 resp = Some((ast::Expr::IfExpr(if_expr.clone()), Expr::BlockExpr(then_branch)));
71 }
72 } else if let Some(else_branch) = if_expr.else_branch() {
73 match else_branch {
74 ElseBranch::Block(else_block) => {
75 let l_curly_token = else_block.l_curly_token()?;
76 if l_curly_token.text_range().contains_range(ctx.frange.range) {
77 let target = else_block.syntax().text_range();
78 return acc.add(assist_id, assist_label, target, |edit| {
79 let range_to_del = TextRange::new(then_branch.syntax().text_range().end(), l_curly_token.text_range().start());
80
81 edit.delete(range_to_del);
82 edit.replace(target, update_expr_string(else_block.to_string(), &[' ', '{']));
83 });
84 }
85 },
86 ElseBranch::IfExpr(_) => {},
87 }
88 }
89
90 resp?
91 },
92 _ => return None,
93 }
94 };
95
96 let target = expr_to_unwrap.syntax().text_range();
97 acc.add(assist_id, assist_label, target, |edit| {
98 edit.replace(
99 expr.syntax().text_range(),
100 update_expr_string(expr_to_unwrap.to_string(), &[' ', '{', '\n']),
101 );
102 })
103}
104
105fn extract_expr(cursor_range: TextRange, block: ast::BlockExpr) -> Option<ast::Expr> {
106 let cursor_in_range = block.l_curly_token()?.text_range().contains_range(cursor_range);
107
108 if cursor_in_range {
109 Some(unwrap_trivial_block(block))
110 } else {
111 None
112 }
113}
114
115fn update_expr_string(expr_str: String, trim_start_pat: &[char]) -> String {
116 let expr_string = expr_str.trim_start_matches(trim_start_pat);
117 let mut expr_string_lines: Vec<&str> = expr_string.lines().collect();
118 expr_string_lines.pop(); // Delete last line
119
120 expr_string_lines
121 .into_iter()
122 .map(|line| line.replacen(" ", "", 1)) // Delete indentation
123 .collect::<Vec<String>>()
124 .join("\n")
125}
126
127#[cfg(test)]
128mod tests {
129 use crate::tests::{check_assist, check_assist_not_applicable};
130
131 use super::*;
132
133 #[test]
134 fn simple_if() {
135 check_assist(
136 unwrap_block,
137 r#"
138 fn main() {
139 bar();
140 if true {<|>
141 foo();
142
143 //comment
144 bar();
145 } else {
146 println!("bar");
147 }
148 }
149 "#,
150 r#"
151 fn main() {
152 bar();
153 foo();
154
155 //comment
156 bar();
157 }
158 "#,
159 );
160 }
161
162 #[test]
163 fn simple_if_else() {
164 check_assist(
165 unwrap_block,
166 r#"
167 fn main() {
168 bar();
169 if true {
170 foo();
171
172 //comment
173 bar();
174 } else {<|>
175 println!("bar");
176 }
177 }
178 "#,
179 r#"
180 fn main() {
181 bar();
182 if true {
183 foo();
184
185 //comment
186 bar();
187 }
188 println!("bar");
189 }
190 "#,
191 );
192 }
193
194 #[test]
195 fn simple_if_else_if() {
196 check_assist(
197 unwrap_block,
198 r#"
199 fn main() {
200 //bar();
201 if true {
202 println!("true");
203
204 //comment
205 //bar();
206 } else if false {<|>
207 println!("bar");
208 } else {
209 println!("foo");
210 }
211 }
212 "#,
213 r#"
214 fn main() {
215 //bar();
216 if true {
217 println!("true");
218
219 //comment
220 //bar();
221 }
222 println!("bar");
223 }
224 "#,
225 );
226 }
227
228 #[test]
229 fn simple_if_else_if_nested() {
230 check_assist(
231 unwrap_block,
232 r#"
233 fn main() {
234 //bar();
235 if true {
236 println!("true");
237
238 //comment
239 //bar();
240 } else if false {
241 println!("bar");
242 } else if true {<|>
243 println!("foo");
244 }
245 }
246 "#,
247 r#"
248 fn main() {
249 //bar();
250 if true {
251 println!("true");
252
253 //comment
254 //bar();
255 } else if false {
256 println!("bar");
257 }
258 println!("foo");
259 }
260 "#,
261 );
262 }
263
264 #[test]
265 fn simple_if_else_if_nested_else() {
266 check_assist(
267 unwrap_block,
268 r#"
269 fn main() {
270 //bar();
271 if true {
272 println!("true");
273
274 //comment
275 //bar();
276 } else if false {
277 println!("bar");
278 } else if true {
279 println!("foo");
280 } else {<|>
281 println!("else");
282 }
283 }
284 "#,
285 r#"
286 fn main() {
287 //bar();
288 if true {
289 println!("true");
290
291 //comment
292 //bar();
293 } else if false {
294 println!("bar");
295 } else if true {
296 println!("foo");
297 }
298 println!("else");
299 }
300 "#,
301 );
302 }
303
304 #[test]
305 fn simple_if_else_if_nested_middle() {
306 check_assist(
307 unwrap_block,
308 r#"
309 fn main() {
310 //bar();
311 if true {
312 println!("true");
313
314 //comment
315 //bar();
316 } else if false {
317 println!("bar");
318 } else if true {<|>
319 println!("foo");
320 } else {
321 println!("else");
322 }
323 }
324 "#,
325 r#"
326 fn main() {
327 //bar();
328 if true {
329 println!("true");
330
331 //comment
332 //bar();
333 } else if false {
334 println!("bar");
335 }
336 println!("foo");
337 }
338 "#,
339 );
340 }
341
342 #[test]
343 fn simple_if_bad_cursor_position() {
344 check_assist_not_applicable(
345 unwrap_block,
346 r#"
347 fn main() {
348 bar();<|>
349 if true {
350 foo();
351
352 //comment
353 bar();
354 } else {
355 println!("bar");
356 }
357 }
358 "#,
359 );
360 }
361
362 #[test]
363 fn simple_for() {
364 check_assist(
365 unwrap_block,
366 r#"
367 fn main() {
368 for i in 0..5 {<|>
369 if true {
370 foo();
371
372 //comment
373 bar();
374 } else {
375 println!("bar");
376 }
377 }
378 }
379 "#,
380 r#"
381 fn main() {
382 if true {
383 foo();
384
385 //comment
386 bar();
387 } else {
388 println!("bar");
389 }
390 }
391 "#,
392 );
393 }
394
395 #[test]
396 fn simple_if_in_for() {
397 check_assist(
398 unwrap_block,
399 r#"
400 fn main() {
401 for i in 0..5 {
402 if true {<|>
403 foo();
404
405 //comment
406 bar();
407 } else {
408 println!("bar");
409 }
410 }
411 }
412 "#,
413 r#"
414 fn main() {
415 for i in 0..5 {
416 foo();
417
418 //comment
419 bar();
420 }
421 }
422 "#,
423 );
424 }
425
426 #[test]
427 fn simple_loop() {
428 check_assist(
429 unwrap_block,
430 r#"
431 fn main() {
432 loop {<|>
433 if true {
434 foo();
435
436 //comment
437 bar();
438 } else {
439 println!("bar");
440 }
441 }
442 }
443 "#,
444 r#"
445 fn main() {
446 if true {
447 foo();
448
449 //comment
450 bar();
451 } else {
452 println!("bar");
453 }
454 }
455 "#,
456 );
457 }
458
459 #[test]
460 fn simple_while() {
461 check_assist(
462 unwrap_block,
463 r#"
464 fn main() {
465 while true {<|>
466 if true {
467 foo();
468
469 //comment
470 bar();
471 } else {
472 println!("bar");
473 }
474 }
475 }
476 "#,
477 r#"
478 fn main() {
479 if true {
480 foo();
481
482 //comment
483 bar();
484 } else {
485 println!("bar");
486 }
487 }
488 "#,
489 );
490 }
491
492 #[test]
493 fn simple_if_in_while_bad_cursor_position() {
494 check_assist_not_applicable(
495 unwrap_block,
496 r#"
497 fn main() {
498 while true {
499 if true {
500 foo();<|>
501
502 //comment
503 bar();
504 } else {
505 println!("bar");
506 }
507 }
508 }
509 "#,
510 );
511 }
512}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 64bd87afb..464bc03dd 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -10,119 +10,113 @@ macro_rules! eprintln {
10 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; 10 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
11} 11}
12 12
13mod assist_ctx; 13mod assist_config;
14mod marks; 14mod assist_context;
15#[cfg(test)] 15#[cfg(test)]
16mod doc_tests; 16mod tests;
17pub mod utils; 17pub mod utils;
18pub mod ast_transform; 18pub mod ast_transform;
19 19
20use ra_db::{FileId, FileRange};
21use ra_ide_db::RootDatabase;
22use ra_syntax::{TextRange, TextSize};
23use ra_text_edit::TextEdit;
24
25pub(crate) use crate::assist_ctx::{Assist, AssistCtx, AssistHandler};
26use hir::Semantics; 20use hir::Semantics;
21use ra_db::FileRange;
22use ra_ide_db::{source_change::SourceChange, RootDatabase};
23use ra_syntax::TextRange;
24
25pub(crate) use crate::assist_context::{AssistContext, Assists};
26
27pub use assist_config::AssistConfig;
27 28
28/// Unique identifier of the assist, should not be shown to the user 29/// Unique identifier of the assist, should not be shown to the user
29/// directly. 30/// directly.
30#[derive(Debug, Clone, Copy, PartialEq, Eq)] 31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub struct AssistId(pub &'static str); 32pub struct AssistId(pub &'static str);
32 33
33#[derive(Debug, Clone)]
34pub struct AssistLabel {
35 /// Short description of the assist, as shown in the UI.
36 pub label: String,
37 pub id: AssistId,
38}
39
40#[derive(Clone, Debug)] 34#[derive(Clone, Debug)]
41pub struct GroupLabel(pub String); 35pub struct GroupLabel(pub String);
42 36
43impl AssistLabel {
44 pub(crate) fn new(label: String, id: AssistId) -> AssistLabel {
45 // FIXME: make fields private, so that this invariant can't be broken
46 assert!(label.starts_with(|c: char| c.is_uppercase()));
47 AssistLabel { label, id }
48 }
49}
50
51#[derive(Debug, Clone)] 37#[derive(Debug, Clone)]
52pub struct AssistAction { 38pub struct Assist {
53 pub edit: TextEdit, 39 pub id: AssistId,
54 pub cursor_position: Option<TextSize>, 40 /// Short description of the assist, as shown in the UI.
55 // FIXME: This belongs to `AssistLabel` 41 pub label: String,
56 pub target: Option<TextRange>, 42 pub group: Option<GroupLabel>,
57 pub file: AssistFile, 43 /// Target ranges are used to sort assists: the smaller the target range,
44 /// the more specific assist is, and so it should be sorted first.
45 pub target: TextRange,
58} 46}
59 47
60#[derive(Debug, Clone)] 48#[derive(Debug, Clone)]
61pub struct ResolvedAssist { 49pub struct ResolvedAssist {
62 pub label: AssistLabel, 50 pub assist: Assist,
63 pub group_label: Option<GroupLabel>, 51 pub source_change: SourceChange,
64 pub action: AssistAction,
65} 52}
66 53
67#[derive(Debug, Clone, Copy)] 54impl Assist {
68pub enum AssistFile { 55 /// Return all the assists applicable at the given position.
69 CurrentFile, 56 ///
70 TargetFile(FileId), 57 /// Assists are returned in the "unresolved" state, that is only labels are
71} 58 /// returned, without actual edits.
72 59 pub fn unresolved(db: &RootDatabase, config: &AssistConfig, range: FileRange) -> Vec<Assist> {
73impl Default for AssistFile { 60 let sema = Semantics::new(db);
74 fn default() -> Self { 61 let ctx = AssistContext::new(sema, config, range);
75 Self::CurrentFile 62 let mut acc = Assists::new_unresolved(&ctx);
63 handlers::all().iter().for_each(|handler| {
64 handler(&mut acc, &ctx);
65 });
66 acc.finish_unresolved()
76 } 67 }
77}
78 68
79/// Return all the assists applicable at the given position. 69 /// Return all the assists applicable at the given position.
80/// 70 ///
81/// Assists are returned in the "unresolved" state, that is only labels are 71 /// Assists are returned in the "resolved" state, that is with edit fully
82/// returned, without actual edits. 72 /// computed.
83pub fn unresolved_assists(db: &RootDatabase, range: FileRange) -> Vec<AssistLabel> { 73 pub fn resolved(
84 let sema = Semantics::new(db); 74 db: &RootDatabase,
85 let ctx = AssistCtx::new(&sema, range, false); 75 config: &AssistConfig,
86 handlers::all() 76 range: FileRange,
87 .iter() 77 ) -> Vec<ResolvedAssist> {
88 .filter_map(|f| f(ctx.clone())) 78 let sema = Semantics::new(db);
89 .flat_map(|it| it.0) 79 let ctx = AssistContext::new(sema, config, range);
90 .map(|a| a.label) 80 let mut acc = Assists::new_resolved(&ctx);
91 .collect() 81 handlers::all().iter().for_each(|handler| {
92} 82 handler(&mut acc, &ctx);
83 });
84 acc.finish_resolved()
85 }
93 86
94/// Return all the assists applicable at the given position. 87 pub(crate) fn new(
95/// 88 id: AssistId,
96/// Assists are returned in the "resolved" state, that is with edit fully 89 label: String,
97/// computed. 90 group: Option<GroupLabel>,
98pub fn resolved_assists(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssist> { 91 target: TextRange,
99 let sema = Semantics::new(db); 92 ) -> Assist {
100 let ctx = AssistCtx::new(&sema, range, true); 93 // FIXME: make fields private, so that this invariant can't be broken
101 let mut a = handlers::all() 94 assert!(label.starts_with(|c: char| c.is_uppercase()));
102 .iter() 95 Assist { id, label, group, target }
103 .filter_map(|f| f(ctx.clone())) 96 }
104 .flat_map(|it| it.0)
105 .map(|it| it.into_resolved().unwrap())
106 .collect::<Vec<_>>();
107 a.sort_by_key(|it| it.action.target.map_or(TextSize::from(!0u32), |it| it.len()));
108 a
109} 97}
110 98
111mod handlers { 99mod handlers {
112 use crate::AssistHandler; 100 use crate::{AssistContext, Assists};
101
102 pub(crate) type Handler = fn(&mut Assists, &AssistContext) -> Option<()>;
113 103
114 mod add_custom_impl; 104 mod add_custom_impl;
115 mod add_derive; 105 mod add_derive;
116 mod add_explicit_type; 106 mod add_explicit_type;
107 mod add_from_impl_for_enum;
117 mod add_function; 108 mod add_function;
118 mod add_impl; 109 mod add_impl;
119 mod add_missing_impl_members; 110 mod add_missing_impl_members;
120 mod add_new; 111 mod add_new;
112 mod add_turbo_fish;
121 mod apply_demorgan; 113 mod apply_demorgan;
122 mod auto_import; 114 mod auto_import;
115 mod change_return_type_to_result;
123 mod change_visibility; 116 mod change_visibility;
124 mod early_return; 117 mod early_return;
125 mod fill_match_arms; 118 mod fill_match_arms;
119 mod fix_visibility;
126 mod flip_binexpr; 120 mod flip_binexpr;
127 mod flip_comma; 121 mod flip_comma;
128 mod flip_trait_bound; 122 mod flip_trait_bound;
@@ -136,28 +130,32 @@ mod handlers {
136 mod raw_string; 130 mod raw_string;
137 mod remove_dbg; 131 mod remove_dbg;
138 mod remove_mut; 132 mod remove_mut;
133 mod reorder_fields;
139 mod replace_if_let_with_match; 134 mod replace_if_let_with_match;
140 mod replace_let_with_if_let; 135 mod replace_let_with_if_let;
141 mod replace_qualified_name_with_use; 136 mod replace_qualified_name_with_use;
142 mod replace_unwrap_with_match; 137 mod replace_unwrap_with_match;
143 mod split_import; 138 mod split_import;
144 mod add_from_impl_for_enum; 139 mod unwrap_block;
145 mod reorder_fields;
146 140
147 pub(crate) fn all() -> &'static [AssistHandler] { 141 pub(crate) fn all() -> &'static [Handler] {
148 &[ 142 &[
149 // These are alphabetic for the foolish consistency 143 // These are alphabetic for the foolish consistency
150 add_custom_impl::add_custom_impl, 144 add_custom_impl::add_custom_impl,
151 add_derive::add_derive, 145 add_derive::add_derive,
152 add_explicit_type::add_explicit_type, 146 add_explicit_type::add_explicit_type,
147 add_from_impl_for_enum::add_from_impl_for_enum,
153 add_function::add_function, 148 add_function::add_function,
154 add_impl::add_impl, 149 add_impl::add_impl,
155 add_new::add_new, 150 add_new::add_new,
151 add_turbo_fish::add_turbo_fish,
156 apply_demorgan::apply_demorgan, 152 apply_demorgan::apply_demorgan,
157 auto_import::auto_import, 153 auto_import::auto_import,
154 change_return_type_to_result::change_return_type_to_result,
158 change_visibility::change_visibility, 155 change_visibility::change_visibility,
159 early_return::convert_to_guarded_return, 156 early_return::convert_to_guarded_return,
160 fill_match_arms::fill_match_arms, 157 fill_match_arms::fill_match_arms,
158 fix_visibility::fix_visibility,
161 flip_binexpr::flip_binexpr, 159 flip_binexpr::flip_binexpr,
162 flip_comma::flip_comma, 160 flip_comma::flip_comma,
163 flip_trait_bound::flip_trait_bound, 161 flip_trait_bound::flip_trait_bound,
@@ -175,167 +173,18 @@ mod handlers {
175 raw_string::remove_hash, 173 raw_string::remove_hash,
176 remove_dbg::remove_dbg, 174 remove_dbg::remove_dbg,
177 remove_mut::remove_mut, 175 remove_mut::remove_mut,
176 reorder_fields::reorder_fields,
178 replace_if_let_with_match::replace_if_let_with_match, 177 replace_if_let_with_match::replace_if_let_with_match,
179 replace_let_with_if_let::replace_let_with_if_let, 178 replace_let_with_if_let::replace_let_with_if_let,
180 replace_qualified_name_with_use::replace_qualified_name_with_use, 179 replace_qualified_name_with_use::replace_qualified_name_with_use,
181 replace_unwrap_with_match::replace_unwrap_with_match, 180 replace_unwrap_with_match::replace_unwrap_with_match,
182 split_import::split_import, 181 split_import::split_import,
183 add_from_impl_for_enum::add_from_impl_for_enum, 182 unwrap_block::unwrap_block,
184 // These are manually sorted for better priorities 183 // These are manually sorted for better priorities
185 add_missing_impl_members::add_missing_impl_members, 184 add_missing_impl_members::add_missing_impl_members,
186 add_missing_impl_members::add_missing_default_members, 185 add_missing_impl_members::add_missing_default_members,
187 reorder_fields::reorder_fields, 186 // Are you sure you want to add new assist here, and not to the
187 // sorted list above?
188 ] 188 ]
189 } 189 }
190} 190}
191
192#[cfg(test)]
193mod helpers {
194 use std::sync::Arc;
195
196 use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
197 use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
198 use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset};
199
200 use crate::{AssistCtx, AssistFile, AssistHandler};
201 use hir::Semantics;
202
203 pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
204 let (mut db, file_id) = RootDatabase::with_single_file(text);
205 // FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`,
206 // but it looks like this might need specialization? :(
207 db.set_local_roots(Arc::new(vec![db.file_source_root(file_id)]));
208 (db, file_id)
209 }
210
211 pub(crate) fn check_assist(
212 assist: AssistHandler,
213 ra_fixture_before: &str,
214 ra_fixture_after: &str,
215 ) {
216 check(assist, ra_fixture_before, ExpectedResult::After(ra_fixture_after));
217 }
218
219 // FIXME: instead of having a separate function here, maybe use
220 // `extract_ranges` and mark the target as `<target> </target>` in the
221 // fixuture?
222 pub(crate) fn check_assist_target(assist: AssistHandler, ra_fixture: &str, target: &str) {
223 check(assist, ra_fixture, ExpectedResult::Target(target));
224 }
225
226 pub(crate) fn check_assist_not_applicable(assist: AssistHandler, ra_fixture: &str) {
227 check(assist, ra_fixture, ExpectedResult::NotApplicable);
228 }
229
230 enum ExpectedResult<'a> {
231 NotApplicable,
232 After(&'a str),
233 Target(&'a str),
234 }
235
236 fn check(assist: AssistHandler, before: &str, expected: ExpectedResult) {
237 let (text_without_caret, file_with_caret_id, range_or_offset, db) =
238 if before.contains("//-") {
239 let (mut db, position) = RootDatabase::with_position(before);
240 db.set_local_roots(Arc::new(vec![db.file_source_root(position.file_id)]));
241 (
242 db.file_text(position.file_id).as_ref().to_owned(),
243 position.file_id,
244 RangeOrOffset::Offset(position.offset),
245 db,
246 )
247 } else {
248 let (range_or_offset, text_without_caret) = extract_range_or_offset(before);
249 let (db, file_id) = with_single_file(&text_without_caret);
250 (text_without_caret, file_id, range_or_offset, db)
251 };
252
253 let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };
254
255 let sema = Semantics::new(&db);
256 let assist_ctx = AssistCtx::new(&sema, frange, true);
257
258 match (assist(assist_ctx), expected) {
259 (Some(assist), ExpectedResult::After(after)) => {
260 let action = assist.0[0].action.clone().unwrap();
261
262 let assisted_file_text = if let AssistFile::TargetFile(file_id) = action.file {
263 db.file_text(file_id).as_ref().to_owned()
264 } else {
265 text_without_caret
266 };
267
268 let mut actual = action.edit.apply(&assisted_file_text);
269 match action.cursor_position {
270 None => {
271 if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset {
272 let off = action
273 .edit
274 .apply_to_offset(before_cursor_pos)
275 .expect("cursor position is affected by the edit");
276 actual = add_cursor(&actual, off)
277 }
278 }
279 Some(off) => actual = add_cursor(&actual, off),
280 };
281
282 assert_eq_text!(after, &actual);
283 }
284 (Some(assist), ExpectedResult::Target(target)) => {
285 let action = assist.0[0].action.clone().unwrap();
286 let range = action.target.expect("expected target on action");
287 assert_eq_text!(&text_without_caret[range], target);
288 }
289 (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
290 (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => {
291 panic!("code action is not applicable")
292 }
293 (None, ExpectedResult::NotApplicable) => (),
294 };
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use ra_db::FileRange;
301 use ra_syntax::TextRange;
302 use test_utils::{extract_offset, extract_range};
303
304 use crate::{helpers, resolved_assists};
305
306 #[test]
307 fn assist_order_field_struct() {
308 let before = "struct Foo { <|>bar: u32 }";
309 let (before_cursor_pos, before) = extract_offset(before);
310 let (db, file_id) = helpers::with_single_file(&before);
311 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
312 let assists = resolved_assists(&db, frange);
313 let mut assists = assists.iter();
314
315 assert_eq!(
316 assists.next().expect("expected assist").label.label,
317 "Change visibility to pub(crate)"
318 );
319 assert_eq!(assists.next().expect("expected assist").label.label, "Add `#[derive]`");
320 }
321
322 #[test]
323 fn assist_order_if_expr() {
324 let before = "
325 pub fn test_some_range(a: int) -> bool {
326 if let 2..6 = <|>5<|> {
327 true
328 } else {
329 false
330 }
331 }";
332 let (range, before) = extract_range(before);
333 let (db, file_id) = helpers::with_single_file(&before);
334 let frange = FileRange { file_id, range };
335 let assists = resolved_assists(&db, frange);
336 let mut assists = assists.iter();
337
338 assert_eq!(assists.next().expect("expected assist").label.label, "Extract into variable");
339 assert_eq!(assists.next().expect("expected assist").label.label, "Replace with match");
340 }
341}
diff --git a/crates/ra_assists/src/marks.rs b/crates/ra_assists/src/marks.rs
deleted file mode 100644
index 8d910205f..000000000
--- a/crates/ra_assists/src/marks.rs
+++ /dev/null
@@ -1,12 +0,0 @@
1//! See test_utils/src/marks.rs
2
3test_utils::marks![
4 introduce_var_in_comment_is_not_applicable
5 test_introduce_var_expr_stmt
6 test_introduce_var_last_expr
7 not_applicable_outside_of_bind_pat
8 test_not_inline_mut_variable
9 test_not_applicable_if_variable_unused
10 change_visibility_field_false_positive
11 test_add_from_impl_already_exists
12];
diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs
new file mode 100644
index 000000000..62dd3547f
--- /dev/null
+++ b/crates/ra_assists/src/tests.rs
@@ -0,0 +1,153 @@
1mod generated;
2
3use std::sync::Arc;
4
5use hir::Semantics;
6use ra_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
7use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
8use ra_syntax::TextRange;
9use test_utils::{
10 assert_eq_text, extract_offset, extract_range, extract_range_or_offset, RangeOrOffset,
11};
12
13use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, Assists};
14
15pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
16 let (mut db, file_id) = RootDatabase::with_single_file(text);
17 // FIXME: ideally, this should be done by the above `RootDatabase::with_single_file`,
18 // but it looks like this might need specialization? :(
19 db.set_local_roots(Arc::new(vec![db.file_source_root(file_id)]));
20 (db, file_id)
21}
22
23pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) {
24 check(assist, ra_fixture_before, ExpectedResult::After(ra_fixture_after));
25}
26
27// FIXME: instead of having a separate function here, maybe use
28// `extract_ranges` and mark the target as `<target> </target>` in the
29// fixuture?
30pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) {
31 check(assist, ra_fixture, ExpectedResult::Target(target));
32}
33
34pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) {
35 check(assist, ra_fixture, ExpectedResult::NotApplicable);
36}
37
38fn check_doc_test(assist_id: &str, before: &str, after: &str) {
39 let (selection, before) = extract_range_or_offset(before);
40 let (db, file_id) = crate::tests::with_single_file(&before);
41 let frange = FileRange { file_id, range: selection.into() };
42
43 let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange)
44 .into_iter()
45 .find(|assist| assist.assist.id.0 == assist_id)
46 .unwrap_or_else(|| {
47 panic!(
48 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
49 assist_id,
50 Assist::resolved(&db, &AssistConfig::default(), frange)
51 .into_iter()
52 .map(|assist| assist.assist.id.0)
53 .collect::<Vec<_>>()
54 .join(", ")
55 )
56 });
57
58 let actual = {
59 let change = assist.source_change.source_file_edits.pop().unwrap();
60 let mut actual = before.clone();
61 change.edit.apply(&mut actual);
62 actual
63 };
64 assert_eq_text!(after, &actual);
65}
66
67enum ExpectedResult<'a> {
68 NotApplicable,
69 After(&'a str),
70 Target(&'a str),
71}
72
73fn check(handler: Handler, before: &str, expected: ExpectedResult) {
74 let (text_without_caret, file_with_caret_id, range_or_offset, db) = if before.contains("//-") {
75 let (mut db, position) = RootDatabase::with_position(before);
76 db.set_local_roots(Arc::new(vec![db.file_source_root(position.file_id)]));
77 (
78 db.file_text(position.file_id).as_ref().to_owned(),
79 position.file_id,
80 RangeOrOffset::Offset(position.offset),
81 db,
82 )
83 } else {
84 let (range_or_offset, text_without_caret) = extract_range_or_offset(before);
85 let (db, file_id) = with_single_file(&text_without_caret);
86 (text_without_caret, file_id, range_or_offset, db)
87 };
88
89 let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };
90
91 let sema = Semantics::new(&db);
92 let config = AssistConfig::default();
93 let ctx = AssistContext::new(sema, &config, frange);
94 let mut acc = Assists::new_resolved(&ctx);
95 handler(&mut acc, &ctx);
96 let mut res = acc.finish_resolved();
97 let assist = res.pop();
98 match (assist, expected) {
99 (Some(assist), ExpectedResult::After(after)) => {
100 let mut source_change = assist.source_change;
101 let change = source_change.source_file_edits.pop().unwrap();
102
103 let mut actual = db.file_text(change.file_id).as_ref().to_owned();
104 change.edit.apply(&mut actual);
105 assert_eq_text!(after, &actual);
106 }
107 (Some(assist), ExpectedResult::Target(target)) => {
108 let range = assist.assist.target;
109 assert_eq_text!(&text_without_caret[range], target);
110 }
111 (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
112 (None, ExpectedResult::After(_)) | (None, ExpectedResult::Target(_)) => {
113 panic!("code action is not applicable")
114 }
115 (None, ExpectedResult::NotApplicable) => (),
116 };
117}
118
119#[test]
120fn assist_order_field_struct() {
121 let before = "struct Foo { <|>bar: u32 }";
122 let (before_cursor_pos, before) = extract_offset(before);
123 let (db, file_id) = with_single_file(&before);
124 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
125 let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
126 let mut assists = assists.iter();
127
128 assert_eq!(
129 assists.next().expect("expected assist").assist.label,
130 "Change visibility to pub(crate)"
131 );
132 assert_eq!(assists.next().expect("expected assist").assist.label, "Add `#[derive]`");
133}
134
135#[test]
136fn assist_order_if_expr() {
137 let before = "
138 pub fn test_some_range(a: int) -> bool {
139 if let 2..6 = <|>5<|> {
140 true
141 } else {
142 false
143 }
144 }";
145 let (range, before) = extract_range(before);
146 let (db, file_id) = with_single_file(&before);
147 let frange = FileRange { file_id, range };
148 let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
149 let mut assists = assists.iter();
150
151 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
152 assert_eq!(assists.next().expect("expected assist").assist.label, "Replace with match");
153}
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/tests/generated.rs
index e4fa9ee36..250e56a69 100644
--- a/crates/ra_assists/src/doc_tests/generated.rs
+++ b/crates/ra_assists/src/tests/generated.rs
@@ -1,10 +1,10 @@
1//! Generated file, do not edit by hand, see `xtask/src/codegen` 1//! Generated file, do not edit by hand, see `xtask/src/codegen`
2 2
3use super::check; 3use super::check_doc_test;
4 4
5#[test] 5#[test]
6fn doctest_add_custom_impl() { 6fn doctest_add_custom_impl() {
7 check( 7 check_doc_test(
8 "add_custom_impl", 8 "add_custom_impl",
9 r#####" 9 r#####"
10#[derive(Deb<|>ug, Display)] 10#[derive(Deb<|>ug, Display)]
@@ -15,7 +15,7 @@ struct S;
15struct S; 15struct S;
16 16
17impl Debug for S { 17impl Debug for S {
18 18 $0
19} 19}
20"#####, 20"#####,
21 ) 21 )
@@ -23,7 +23,7 @@ impl Debug for S {
23 23
24#[test] 24#[test]
25fn doctest_add_derive() { 25fn doctest_add_derive() {
26 check( 26 check_doc_test(
27 "add_derive", 27 "add_derive",
28 r#####" 28 r#####"
29struct Point { 29struct Point {
@@ -32,7 +32,7 @@ struct Point {
32} 32}
33"#####, 33"#####,
34 r#####" 34 r#####"
35#[derive()] 35#[derive($0)]
36struct Point { 36struct Point {
37 x: u32, 37 x: u32,
38 y: u32, 38 y: u32,
@@ -43,7 +43,7 @@ struct Point {
43 43
44#[test] 44#[test]
45fn doctest_add_explicit_type() { 45fn doctest_add_explicit_type() {
46 check( 46 check_doc_test(
47 "add_explicit_type", 47 "add_explicit_type",
48 r#####" 48 r#####"
49fn main() { 49fn main() {
@@ -60,7 +60,7 @@ fn main() {
60 60
61#[test] 61#[test]
62fn doctest_add_function() { 62fn doctest_add_function() {
63 check( 63 check_doc_test(
64 "add_function", 64 "add_function",
65 r#####" 65 r#####"
66struct Baz; 66struct Baz;
@@ -78,7 +78,7 @@ fn foo() {
78} 78}
79 79
80fn bar(arg: &str, baz: Baz) { 80fn bar(arg: &str, baz: Baz) {
81 todo!() 81 ${0:todo!()}
82} 82}
83 83
84"#####, 84"#####,
@@ -87,7 +87,7 @@ fn bar(arg: &str, baz: Baz) {
87 87
88#[test] 88#[test]
89fn doctest_add_hash() { 89fn doctest_add_hash() {
90 check( 90 check_doc_test(
91 "add_hash", 91 "add_hash",
92 r#####" 92 r#####"
93fn main() { 93fn main() {
@@ -104,20 +104,20 @@ fn main() {
104 104
105#[test] 105#[test]
106fn doctest_add_impl() { 106fn doctest_add_impl() {
107 check( 107 check_doc_test(
108 "add_impl", 108 "add_impl",
109 r#####" 109 r#####"
110struct Ctx<T: Clone> { 110struct Ctx<T: Clone> {
111 data: T,<|> 111 data: T,<|>
112} 112}
113"#####, 113"#####,
114 r#####" 114 r#####"
115struct Ctx<T: Clone> { 115struct Ctx<T: Clone> {
116 data: T, 116 data: T,
117} 117}
118 118
119impl<T: Clone> Ctx<T> { 119impl<T: Clone> Ctx<T> {
120 120 $0
121} 121}
122"#####, 122"#####,
123 ) 123 )
@@ -125,7 +125,7 @@ impl<T: Clone> Ctx<T> {
125 125
126#[test] 126#[test]
127fn doctest_add_impl_default_members() { 127fn doctest_add_impl_default_members() {
128 check( 128 check_doc_test(
129 "add_impl_default_members", 129 "add_impl_default_members",
130 r#####" 130 r#####"
131trait Trait { 131trait Trait {
@@ -150,7 +150,7 @@ trait Trait {
150impl Trait for () { 150impl Trait for () {
151 Type X = (); 151 Type X = ();
152 fn foo(&self) {} 152 fn foo(&self) {}
153 fn bar(&self) {} 153 $0fn bar(&self) {}
154 154
155} 155}
156"#####, 156"#####,
@@ -159,7 +159,7 @@ impl Trait for () {
159 159
160#[test] 160#[test]
161fn doctest_add_impl_missing_members() { 161fn doctest_add_impl_missing_members() {
162 check( 162 check_doc_test(
163 "add_impl_missing_members", 163 "add_impl_missing_members",
164 r#####" 164 r#####"
165trait Trait<T> { 165trait Trait<T> {
@@ -180,7 +180,9 @@ trait Trait<T> {
180} 180}
181 181
182impl Trait<u32> for () { 182impl Trait<u32> for () {
183 fn foo(&self) -> u32 { todo!() } 183 fn foo(&self) -> u32 {
184 ${0:todo!()}
185 }
184 186
185} 187}
186"#####, 188"#####,
@@ -189,7 +191,7 @@ impl Trait<u32> for () {
189 191
190#[test] 192#[test]
191fn doctest_add_new() { 193fn doctest_add_new() {
192 check( 194 check_doc_test(
193 "add_new", 195 "add_new",
194 r#####" 196 r#####"
195struct Ctx<T: Clone> { 197struct Ctx<T: Clone> {
@@ -202,7 +204,7 @@ struct Ctx<T: Clone> {
202} 204}
203 205
204impl<T: Clone> Ctx<T> { 206impl<T: Clone> Ctx<T> {
205 fn new(data: T) -> Self { Self { data } } 207 fn $0new(data: T) -> Self { Self { data } }
206} 208}
207 209
208"#####, 210"#####,
@@ -210,8 +212,27 @@ impl<T: Clone> Ctx<T> {
210} 212}
211 213
212#[test] 214#[test]
215fn doctest_add_turbo_fish() {
216 check_doc_test(
217 "add_turbo_fish",
218 r#####"
219fn make<T>() -> T { todo!() }
220fn main() {
221 let x = make<|>();
222}
223"#####,
224 r#####"
225fn make<T>() -> T { todo!() }
226fn main() {
227 let x = make::<${0:_}>();
228}
229"#####,
230 )
231}
232
233#[test]
213fn doctest_apply_demorgan() { 234fn doctest_apply_demorgan() {
214 check( 235 check_doc_test(
215 "apply_demorgan", 236 "apply_demorgan",
216 r#####" 237 r#####"
217fn main() { 238fn main() {
@@ -228,7 +249,7 @@ fn main() {
228 249
229#[test] 250#[test]
230fn doctest_auto_import() { 251fn doctest_auto_import() {
231 check( 252 check_doc_test(
232 "auto_import", 253 "auto_import",
233 r#####" 254 r#####"
234fn main() { 255fn main() {
@@ -248,8 +269,21 @@ pub mod std { pub mod collections { pub struct HashMap { } } }
248} 269}
249 270
250#[test] 271#[test]
272fn doctest_change_return_type_to_result() {
273 check_doc_test(
274 "change_return_type_to_result",
275 r#####"
276fn foo() -> i32<|> { 42i32 }
277"#####,
278 r#####"
279fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
280"#####,
281 )
282}
283
284#[test]
251fn doctest_change_visibility() { 285fn doctest_change_visibility() {
252 check( 286 check_doc_test(
253 "change_visibility", 287 "change_visibility",
254 r#####" 288 r#####"
255<|>fn frobnicate() {} 289<|>fn frobnicate() {}
@@ -262,7 +296,7 @@ pub(crate) fn frobnicate() {}
262 296
263#[test] 297#[test]
264fn doctest_convert_to_guarded_return() { 298fn doctest_convert_to_guarded_return() {
265 check( 299 check_doc_test(
266 "convert_to_guarded_return", 300 "convert_to_guarded_return",
267 r#####" 301 r#####"
268fn main() { 302fn main() {
@@ -286,7 +320,7 @@ fn main() {
286 320
287#[test] 321#[test]
288fn doctest_fill_match_arms() { 322fn doctest_fill_match_arms() {
289 check( 323 check_doc_test(
290 "fill_match_arms", 324 "fill_match_arms",
291 r#####" 325 r#####"
292enum Action { Move { distance: u32 }, Stop } 326enum Action { Move { distance: u32 }, Stop }
@@ -302,7 +336,7 @@ enum Action { Move { distance: u32 }, Stop }
302 336
303fn handle(action: Action) { 337fn handle(action: Action) {
304 match action { 338 match action {
305 Action::Move { distance } => {} 339 $0Action::Move { distance } => {}
306 Action::Stop => {} 340 Action::Stop => {}
307 } 341 }
308} 342}
@@ -311,8 +345,31 @@ fn handle(action: Action) {
311} 345}
312 346
313#[test] 347#[test]
348fn doctest_fix_visibility() {
349 check_doc_test(
350 "fix_visibility",
351 r#####"
352mod m {
353 fn frobnicate() {}
354}
355fn main() {
356 m::frobnicate<|>() {}
357}
358"#####,
359 r#####"
360mod m {
361 $0pub(crate) fn frobnicate() {}
362}
363fn main() {
364 m::frobnicate() {}
365}
366"#####,
367 )
368}
369
370#[test]
314fn doctest_flip_binexpr() { 371fn doctest_flip_binexpr() {
315 check( 372 check_doc_test(
316 "flip_binexpr", 373 "flip_binexpr",
317 r#####" 374 r#####"
318fn main() { 375fn main() {
@@ -329,7 +386,7 @@ fn main() {
329 386
330#[test] 387#[test]
331fn doctest_flip_comma() { 388fn doctest_flip_comma() {
332 check( 389 check_doc_test(
333 "flip_comma", 390 "flip_comma",
334 r#####" 391 r#####"
335fn main() { 392fn main() {
@@ -346,7 +403,7 @@ fn main() {
346 403
347#[test] 404#[test]
348fn doctest_flip_trait_bound() { 405fn doctest_flip_trait_bound() {
349 check( 406 check_doc_test(
350 "flip_trait_bound", 407 "flip_trait_bound",
351 r#####" 408 r#####"
352fn foo<T: Clone +<|> Copy>() { } 409fn foo<T: Clone +<|> Copy>() { }
@@ -359,7 +416,7 @@ fn foo<T: Copy + Clone>() { }
359 416
360#[test] 417#[test]
361fn doctest_inline_local_variable() { 418fn doctest_inline_local_variable() {
362 check( 419 check_doc_test(
363 "inline_local_variable", 420 "inline_local_variable",
364 r#####" 421 r#####"
365fn main() { 422fn main() {
@@ -377,7 +434,7 @@ fn main() {
377 434
378#[test] 435#[test]
379fn doctest_introduce_variable() { 436fn doctest_introduce_variable() {
380 check( 437 check_doc_test(
381 "introduce_variable", 438 "introduce_variable",
382 r#####" 439 r#####"
383fn main() { 440fn main() {
@@ -386,7 +443,7 @@ fn main() {
386"#####, 443"#####,
387 r#####" 444 r#####"
388fn main() { 445fn main() {
389 let var_name = (1 + 2); 446 let $0var_name = (1 + 2);
390 var_name * 4; 447 var_name * 4;
391} 448}
392"#####, 449"#####,
@@ -395,7 +452,7 @@ fn main() {
395 452
396#[test] 453#[test]
397fn doctest_invert_if() { 454fn doctest_invert_if() {
398 check( 455 check_doc_test(
399 "invert_if", 456 "invert_if",
400 r#####" 457 r#####"
401fn main() { 458fn main() {
@@ -412,7 +469,7 @@ fn main() {
412 469
413#[test] 470#[test]
414fn doctest_make_raw_string() { 471fn doctest_make_raw_string() {
415 check( 472 check_doc_test(
416 "make_raw_string", 473 "make_raw_string",
417 r#####" 474 r#####"
418fn main() { 475fn main() {
@@ -429,7 +486,7 @@ fn main() {
429 486
430#[test] 487#[test]
431fn doctest_make_usual_string() { 488fn doctest_make_usual_string() {
432 check( 489 check_doc_test(
433 "make_usual_string", 490 "make_usual_string",
434 r#####" 491 r#####"
435fn main() { 492fn main() {
@@ -446,7 +503,7 @@ fn main() {
446 503
447#[test] 504#[test]
448fn doctest_merge_imports() { 505fn doctest_merge_imports() {
449 check( 506 check_doc_test(
450 "merge_imports", 507 "merge_imports",
451 r#####" 508 r#####"
452use std::<|>fmt::Formatter; 509use std::<|>fmt::Formatter;
@@ -460,7 +517,7 @@ use std::{fmt::Formatter, io};
460 517
461#[test] 518#[test]
462fn doctest_merge_match_arms() { 519fn doctest_merge_match_arms() {
463 check( 520 check_doc_test(
464 "merge_match_arms", 521 "merge_match_arms",
465 r#####" 522 r#####"
466enum Action { Move { distance: u32 }, Stop } 523enum Action { Move { distance: u32 }, Stop }
@@ -486,7 +543,7 @@ fn handle(action: Action) {
486 543
487#[test] 544#[test]
488fn doctest_move_arm_cond_to_match_guard() { 545fn doctest_move_arm_cond_to_match_guard() {
489 check( 546 check_doc_test(
490 "move_arm_cond_to_match_guard", 547 "move_arm_cond_to_match_guard",
491 r#####" 548 r#####"
492enum Action { Move { distance: u32 }, Stop } 549enum Action { Move { distance: u32 }, Stop }
@@ -513,7 +570,7 @@ fn handle(action: Action) {
513 570
514#[test] 571#[test]
515fn doctest_move_bounds_to_where_clause() { 572fn doctest_move_bounds_to_where_clause() {
516 check( 573 check_doc_test(
517 "move_bounds_to_where_clause", 574 "move_bounds_to_where_clause",
518 r#####" 575 r#####"
519fn apply<T, U, <|>F: FnOnce(T) -> U>(f: F, x: T) -> U { 576fn apply<T, U, <|>F: FnOnce(T) -> U>(f: F, x: T) -> U {
@@ -530,7 +587,7 @@ fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
530 587
531#[test] 588#[test]
532fn doctest_move_guard_to_arm_body() { 589fn doctest_move_guard_to_arm_body() {
533 check( 590 check_doc_test(
534 "move_guard_to_arm_body", 591 "move_guard_to_arm_body",
535 r#####" 592 r#####"
536enum Action { Move { distance: u32 }, Stop } 593enum Action { Move { distance: u32 }, Stop }
@@ -557,7 +614,7 @@ fn handle(action: Action) {
557 614
558#[test] 615#[test]
559fn doctest_remove_dbg() { 616fn doctest_remove_dbg() {
560 check( 617 check_doc_test(
561 "remove_dbg", 618 "remove_dbg",
562 r#####" 619 r#####"
563fn main() { 620fn main() {
@@ -574,7 +631,7 @@ fn main() {
574 631
575#[test] 632#[test]
576fn doctest_remove_hash() { 633fn doctest_remove_hash() {
577 check( 634 check_doc_test(
578 "remove_hash", 635 "remove_hash",
579 r#####" 636 r#####"
580fn main() { 637fn main() {
@@ -591,7 +648,7 @@ fn main() {
591 648
592#[test] 649#[test]
593fn doctest_remove_mut() { 650fn doctest_remove_mut() {
594 check( 651 check_doc_test(
595 "remove_mut", 652 "remove_mut",
596 r#####" 653 r#####"
597impl Walrus { 654impl Walrus {
@@ -608,7 +665,7 @@ impl Walrus {
608 665
609#[test] 666#[test]
610fn doctest_reorder_fields() { 667fn doctest_reorder_fields() {
611 check( 668 check_doc_test(
612 "reorder_fields", 669 "reorder_fields",
613 r#####" 670 r#####"
614struct Foo {foo: i32, bar: i32}; 671struct Foo {foo: i32, bar: i32};
@@ -623,7 +680,7 @@ const test: Foo = Foo {foo: 1, bar: 0}
623 680
624#[test] 681#[test]
625fn doctest_replace_if_let_with_match() { 682fn doctest_replace_if_let_with_match() {
626 check( 683 check_doc_test(
627 "replace_if_let_with_match", 684 "replace_if_let_with_match",
628 r#####" 685 r#####"
629enum Action { Move { distance: u32 }, Stop } 686enum Action { Move { distance: u32 }, Stop }
@@ -651,7 +708,7 @@ fn handle(action: Action) {
651 708
652#[test] 709#[test]
653fn doctest_replace_let_with_if_let() { 710fn doctest_replace_let_with_if_let() {
654 check( 711 check_doc_test(
655 "replace_let_with_if_let", 712 "replace_let_with_if_let",
656 r#####" 713 r#####"
657enum Option<T> { Some(T), None } 714enum Option<T> { Some(T), None }
@@ -677,7 +734,7 @@ fn compute() -> Option<i32> { None }
677 734
678#[test] 735#[test]
679fn doctest_replace_qualified_name_with_use() { 736fn doctest_replace_qualified_name_with_use() {
680 check( 737 check_doc_test(
681 "replace_qualified_name_with_use", 738 "replace_qualified_name_with_use",
682 r#####" 739 r#####"
683fn process(map: std::collections::<|>HashMap<String, String>) {} 740fn process(map: std::collections::<|>HashMap<String, String>) {}
@@ -692,7 +749,7 @@ fn process(map: HashMap<String, String>) {}
692 749
693#[test] 750#[test]
694fn doctest_replace_unwrap_with_match() { 751fn doctest_replace_unwrap_with_match() {
695 check( 752 check_doc_test(
696 "replace_unwrap_with_match", 753 "replace_unwrap_with_match",
697 r#####" 754 r#####"
698enum Result<T, E> { Ok(T), Err(E) } 755enum Result<T, E> { Ok(T), Err(E) }
@@ -707,7 +764,7 @@ fn main() {
707 let x: Result<i32, i32> = Result::Ok(92); 764 let x: Result<i32, i32> = Result::Ok(92);
708 let y = match x { 765 let y = match x {
709 Ok(a) => a, 766 Ok(a) => a,
710 _ => unreachable!(), 767 $0_ => unreachable!(),
711 }; 768 };
712} 769}
713"#####, 770"#####,
@@ -716,7 +773,7 @@ fn main() {
716 773
717#[test] 774#[test]
718fn doctest_split_import() { 775fn doctest_split_import() {
719 check( 776 check_doc_test(
720 "split_import", 777 "split_import",
721 r#####" 778 r#####"
722use std::<|>collections::HashMap; 779use std::<|>collections::HashMap;
@@ -726,3 +783,22 @@ use std::{collections::HashMap};
726"#####, 783"#####,
727 ) 784 )
728} 785}
786
787#[test]
788fn doctest_unwrap_block() {
789 check_doc_test(
790 "unwrap_block",
791 r#####"
792fn foo() {
793 if true {<|>
794 println!("foo");
795 }
796}
797"#####,
798 r#####"
799fn foo() {
800 println!("foo");
801}
802"#####,
803 )
804}
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index efd988697..0038a9764 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -1,19 +1,58 @@
1//! Assorted functions shared by several assists. 1//! Assorted functions shared by several assists.
2pub(crate) mod insert_use; 2pub(crate) mod insert_use;
3 3
4use std::iter; 4use std::{iter, ops};
5 5
6use hir::{Adt, Crate, Semantics, Trait, Type}; 6use hir::{Adt, Crate, Enum, ScopeDef, Semantics, Trait, Type};
7use ra_ide_db::RootDatabase; 7use ra_ide_db::RootDatabase;
8use ra_syntax::{ 8use ra_syntax::{
9 ast::{self, make, NameOwner}, 9 ast::{self, make, NameOwner},
10 AstNode, T, 10 AstNode, SyntaxNode, T,
11}; 11};
12use rustc_hash::FxHashSet; 12use rustc_hash::FxHashSet;
13 13
14pub use insert_use::insert_use_statement; 14use crate::assist_config::SnippetCap;
15 15
16pub fn get_missing_impl_items( 16pub(crate) use insert_use::insert_use_statement;
17
18#[derive(Clone, Copy, Debug)]
19pub(crate) enum Cursor<'a> {
20 Replace(&'a SyntaxNode),
21 Before(&'a SyntaxNode),
22}
23
24impl<'a> Cursor<'a> {
25 fn node(self) -> &'a SyntaxNode {
26 match self {
27 Cursor::Replace(node) | Cursor::Before(node) => node,
28 }
29 }
30}
31
32pub(crate) fn render_snippet(_cap: SnippetCap, node: &SyntaxNode, cursor: Cursor) -> String {
33 assert!(cursor.node().ancestors().any(|it| it == *node));
34 let range = cursor.node().text_range() - node.text_range().start();
35 let range: ops::Range<usize> = range.into();
36
37 let mut placeholder = cursor.node().to_string();
38 escape(&mut placeholder);
39 let tab_stop = match cursor {
40 Cursor::Replace(placeholder) => format!("${{0:{}}}", placeholder),
41 Cursor::Before(placeholder) => format!("$0{}", placeholder),
42 };
43
44 let mut buf = node.to_string();
45 buf.replace_range(range, &tab_stop);
46 return buf;
47
48 fn escape(buf: &mut String) {
49 stdx::replace(buf, '{', r"\{");
50 stdx::replace(buf, '}', r"\}");
51 stdx::replace(buf, '$', r"\$");
52 }
53}
54
55pub fn get_missing_assoc_items(
17 sema: &Semantics<RootDatabase>, 56 sema: &Semantics<RootDatabase>,
18 impl_def: &ast::ImplDef, 57 impl_def: &ast::ImplDef,
19) -> Vec<hir::AssocItem> { 58) -> Vec<hir::AssocItem> {
@@ -23,21 +62,21 @@ pub fn get_missing_impl_items(
23 let mut impl_type = FxHashSet::default(); 62 let mut impl_type = FxHashSet::default();
24 63
25 if let Some(item_list) = impl_def.item_list() { 64 if let Some(item_list) = impl_def.item_list() {
26 for item in item_list.impl_items() { 65 for item in item_list.assoc_items() {
27 match item { 66 match item {
28 ast::ImplItem::FnDef(f) => { 67 ast::AssocItem::FnDef(f) => {
29 if let Some(n) = f.name() { 68 if let Some(n) = f.name() {
30 impl_fns_consts.insert(n.syntax().to_string()); 69 impl_fns_consts.insert(n.syntax().to_string());
31 } 70 }
32 } 71 }
33 72
34 ast::ImplItem::TypeAliasDef(t) => { 73 ast::AssocItem::TypeAliasDef(t) => {
35 if let Some(n) = t.name() { 74 if let Some(n) = t.name() {
36 impl_type.insert(n.syntax().to_string()); 75 impl_type.insert(n.syntax().to_string());
37 } 76 }
38 } 77 }
39 78
40 ast::ImplItem::ConstDef(c) => { 79 ast::AssocItem::ConstDef(c) => {
41 if let Some(n) = c.name() { 80 if let Some(n) = c.name() {
42 impl_fns_consts.insert(n.syntax().to_string()); 81 impl_fns_consts.insert(n.syntax().to_string());
43 } 82 }
@@ -103,7 +142,7 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
103} 142}
104 143
105#[derive(Clone, Copy)] 144#[derive(Clone, Copy)]
106pub(crate) enum TryEnum { 145pub enum TryEnum {
107 Result, 146 Result,
108 Option, 147 Option,
109} 148}
@@ -111,7 +150,7 @@ pub(crate) enum TryEnum {
111impl TryEnum { 150impl TryEnum {
112 const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result]; 151 const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result];
113 152
114 pub(crate) fn from_ty(sema: &Semantics<RootDatabase>, ty: &Type) -> Option<TryEnum> { 153 pub fn from_ty(sema: &Semantics<RootDatabase>, ty: &Type) -> Option<TryEnum> {
115 let enum_ = match ty.as_adt() { 154 let enum_ = match ty.as_adt() {
116 Some(Adt::Enum(it)) => it, 155 Some(Adt::Enum(it)) => it,
117 _ => return None, 156 _ => return None,
@@ -161,13 +200,19 @@ impl FamousDefs<'_, '_> {
161 #[cfg(test)] 200 #[cfg(test)]
162 pub(crate) const FIXTURE: &'static str = r#" 201 pub(crate) const FIXTURE: &'static str = r#"
163//- /libcore.rs crate:core 202//- /libcore.rs crate:core
164pub mod convert{ 203pub mod convert {
165 pub trait From<T> { 204 pub trait From<T> {
166 fn from(T) -> Self; 205 fn from(T) -> Self;
167 } 206 }
168} 207}
169 208
170pub mod prelude { pub use crate::convert::From } 209pub mod option {
210 pub enum Option<T> { None, Some(T)}
211}
212
213pub mod prelude {
214 pub use crate::{convert::From, option::Option::{self, *}};
215}
171#[prelude_import] 216#[prelude_import]
172pub use prelude::*; 217pub use prelude::*;
173"#; 218"#;
@@ -176,7 +221,25 @@ pub use prelude::*;
176 self.find_trait("core:convert:From") 221 self.find_trait("core:convert:From")
177 } 222 }
178 223
224 pub(crate) fn core_option_Option(&self) -> Option<Enum> {
225 self.find_enum("core:option:Option")
226 }
227
179 fn find_trait(&self, path: &str) -> Option<Trait> { 228 fn find_trait(&self, path: &str) -> Option<Trait> {
229 match self.find_def(path)? {
230 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
231 _ => None,
232 }
233 }
234
235 fn find_enum(&self, path: &str) -> Option<Enum> {
236 match self.find_def(path)? {
237 hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
238 _ => None,
239 }
240 }
241
242 fn find_def(&self, path: &str) -> Option<ScopeDef> {
180 let db = self.0.db; 243 let db = self.0.db;
181 let mut path = path.split(':'); 244 let mut path = path.split(':');
182 let trait_ = path.next_back()?; 245 let trait_ = path.next_back()?;
@@ -201,9 +264,6 @@ pub use prelude::*;
201 } 264 }
202 let def = 265 let def =
203 module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1; 266 module.scope(db, None).into_iter().find(|(name, _def)| &name.to_string() == trait_)?.1;
204 match def { 267 Some(def)
205 hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
206 _ => None,
207 }
208 } 268 }
209} 269}
diff --git a/crates/ra_assists/src/utils/insert_use.rs b/crates/ra_assists/src/utils/insert_use.rs
index c507e71e0..0ee43482f 100644
--- a/crates/ra_assists/src/utils/insert_use.rs
+++ b/crates/ra_assists/src/utils/insert_use.rs
@@ -11,17 +11,20 @@ use ra_syntax::{
11}; 11};
12use ra_text_edit::TextEditBuilder; 12use ra_text_edit::TextEditBuilder;
13 13
14use crate::assist_context::AssistContext;
15
14/// Creates and inserts a use statement for the given path to import. 16/// Creates and inserts a use statement for the given path to import.
15/// The use statement is inserted in the scope most appropriate to the 17/// The use statement is inserted in the scope most appropriate to the
16/// the cursor position given, additionally merged with the existing use imports. 18/// the cursor position given, additionally merged with the existing use imports.
17pub fn insert_use_statement( 19pub(crate) fn insert_use_statement(
18 // Ideally the position of the cursor, used to 20 // Ideally the position of the cursor, used to
19 position: &SyntaxNode, 21 position: &SyntaxNode,
20 path_to_import: &ModPath, 22 path_to_import: &ModPath,
21 edit: &mut TextEditBuilder, 23 ctx: &AssistContext,
24 builder: &mut TextEditBuilder,
22) { 25) {
23 let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>(); 26 let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>();
24 let container = position.ancestors().find_map(|n| { 27 let container = ctx.sema.ancestors_with_macros(position.clone()).find_map(|n| {
25 if let Some(module) = ast::Module::cast(n.clone()) { 28 if let Some(module) = ast::Module::cast(n.clone()) {
26 return module.item_list().map(|it| it.syntax().clone()); 29 return module.item_list().map(|it| it.syntax().clone());
27 } 30 }
@@ -30,7 +33,7 @@ pub fn insert_use_statement(
30 33
31 if let Some(container) = container { 34 if let Some(container) = container {
32 let action = best_action_for_target(container, position.clone(), &target); 35 let action = best_action_for_target(container, position.clone(), &target);
33 make_assist(&action, &target, edit); 36 make_assist(&action, &target, builder);
34 } 37 }
35} 38}
36 39
diff --git a/crates/ra_cfg/src/lib.rs b/crates/ra_cfg/src/lib.rs
index 51d953f6e..57feabcb2 100644
--- a/crates/ra_cfg/src/lib.rs
+++ b/crates/ra_cfg/src/lib.rs
@@ -2,8 +2,6 @@
2 2
3mod cfg_expr; 3mod cfg_expr;
4 4
5use std::iter::IntoIterator;
6
7use ra_syntax::SmolStr; 5use ra_syntax::SmolStr;
8use rustc_hash::FxHashSet; 6use rustc_hash::FxHashSet;
9 7
@@ -48,9 +46,4 @@ impl CfgOptions {
48 pub fn insert_key_value(&mut self, key: SmolStr, value: SmolStr) { 46 pub fn insert_key_value(&mut self, key: SmolStr, value: SmolStr) {
49 self.key_values.insert((key, value)); 47 self.key_values.insert((key, value));
50 } 48 }
51
52 /// Shortcut to set features
53 pub fn insert_features(&mut self, iter: impl IntoIterator<Item = SmolStr>) {
54 iter.into_iter().for_each(|feat| self.insert_key_value("feature".into(), feat));
55 }
56} 49}
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs
index 8248684ee..f8f767091 100644
--- a/crates/ra_db/src/fixture.rs
+++ b/crates/ra_db/src/fixture.rs
@@ -1,4 +1,62 @@
1//! FIXME: write short doc here 1//! Fixtures are strings containing rust source code with optional metadata.
2//! A fixture without metadata is parsed into a single source file.
3//! Use this to test functionality local to one file.
4//!
5//! Simple Example:
6//! ```
7//! r#"
8//! fn main() {
9//! println!("Hello World")
10//! }
11//! "#
12//! ```
13//!
14//! Metadata can be added to a fixture after a `//-` comment.
15//! The basic form is specifying filenames,
16//! which is also how to define multiple files in a single test fixture
17//!
18//! Example using two files in the same crate:
19//! ```
20//! "
21//! //- /main.rs
22//! mod foo;
23//! fn main() {
24//! foo::bar();
25//! }
26//!
27//! //- /foo.rs
28//! pub fn bar() {}
29//! "
30//! ```
31//!
32//! Example using two crates with one file each, with one crate depending on the other:
33//! ```
34//! r#"
35//! //- /main.rs crate:a deps:b
36//! fn main() {
37//! b::foo();
38//! }
39//! //- /lib.rs crate:b
40//! pub fn b() {
41//! println!("Hello World")
42//! }
43//! "#
44//! ```
45//!
46//! Metadata allows specifying all settings and variables
47//! that are available in a real rust project:
48//! - crate names via `crate:cratename`
49//! - dependencies via `deps:dep1,dep2`
50//! - configuration settings via `cfg:dbg=false,opt_level=2`
51//! - environment variables via `env:PATH=/bin,RUST_LOG=debug`
52//!
53//! Example using all available metadata:
54//! ```
55//! "
56//! //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
57//! fn insert_source_code_here() {}
58//! "
59//! ```
2 60
3use std::str::FromStr; 61use std::str::FromStr;
4use std::sync::Arc; 62use std::sync::Arc;
diff --git a/crates/ra_flycheck/Cargo.toml b/crates/ra_flycheck/Cargo.toml
index 324c33d9d..1aa39bade 100644
--- a/crates/ra_flycheck/Cargo.toml
+++ b/crates/ra_flycheck/Cargo.toml
@@ -4,13 +4,13 @@ name = "ra_flycheck"
4version = "0.1.0" 4version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6 6
7[lib]
8doctest = false
9
7[dependencies] 10[dependencies]
8crossbeam-channel = "0.4.0" 11crossbeam-channel = "0.4.0"
9lsp-types = { version = "0.74.0", features = ["proposed"] }
10log = "0.4.8" 12log = "0.4.8"
11cargo_metadata = "0.9.1" 13cargo_metadata = "0.10.0"
12serde_json = "1.0.48" 14serde_json = "1.0.48"
13jod-thread = "0.1.1" 15jod-thread = "0.1.1"
14 16ra_toolchain = { path = "../ra_toolchain" }
15[dev-dependencies]
16insta = "0.16.0"
diff --git a/crates/ra_flycheck/src/conv.rs b/crates/ra_flycheck/src/conv.rs
deleted file mode 100644
index 817543deb..000000000
--- a/crates/ra_flycheck/src/conv.rs
+++ /dev/null
@@ -1,341 +0,0 @@
1//! This module provides the functionality needed to convert diagnostics from
2//! `cargo check` json format to the LSP diagnostic format.
3use cargo_metadata::diagnostic::{
4 Applicability, Diagnostic as RustDiagnostic, DiagnosticLevel, DiagnosticSpan,
5 DiagnosticSpanMacroExpansion,
6};
7use lsp_types::{
8 CodeAction, Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag,
9 Location, NumberOrString, Position, Range, TextEdit, Url, WorkspaceEdit,
10};
11use std::{
12 collections::HashMap,
13 fmt::Write,
14 path::{Component, Path, PathBuf, Prefix},
15 str::FromStr,
16};
17
18#[cfg(test)]
19mod test;
20
21/// Converts a Rust level string to a LSP severity
22fn map_level_to_severity(val: DiagnosticLevel) -> Option<DiagnosticSeverity> {
23 match val {
24 DiagnosticLevel::Ice => Some(DiagnosticSeverity::Error),
25 DiagnosticLevel::Error => Some(DiagnosticSeverity::Error),
26 DiagnosticLevel::Warning => Some(DiagnosticSeverity::Warning),
27 DiagnosticLevel::Note => Some(DiagnosticSeverity::Information),
28 DiagnosticLevel::Help => Some(DiagnosticSeverity::Hint),
29 DiagnosticLevel::Unknown => None,
30 }
31}
32
33/// Check whether a file name is from macro invocation
34fn is_from_macro(file_name: &str) -> bool {
35 file_name.starts_with('<') && file_name.ends_with('>')
36}
37
38/// Converts a Rust macro span to a LSP location recursively
39fn map_macro_span_to_location(
40 span_macro: &DiagnosticSpanMacroExpansion,
41 workspace_root: &PathBuf,
42) -> Option<Location> {
43 if !is_from_macro(&span_macro.span.file_name) {
44 return Some(map_span_to_location(&span_macro.span, workspace_root));
45 }
46
47 if let Some(expansion) = &span_macro.span.expansion {
48 return map_macro_span_to_location(&expansion, workspace_root);
49 }
50
51 None
52}
53
54/// Converts a Rust span to a LSP location, resolving macro expansion site if neccesary
55fn map_span_to_location(span: &DiagnosticSpan, workspace_root: &PathBuf) -> Location {
56 if span.expansion.is_some() {
57 let expansion = span.expansion.as_ref().unwrap();
58 if let Some(macro_range) = map_macro_span_to_location(&expansion, workspace_root) {
59 return macro_range;
60 }
61 }
62
63 map_span_to_location_naive(span, workspace_root)
64}
65
66/// Converts a Rust span to a LSP location
67fn map_span_to_location_naive(span: &DiagnosticSpan, workspace_root: &PathBuf) -> Location {
68 let mut file_name = workspace_root.clone();
69 file_name.push(&span.file_name);
70 let uri = url_from_path_with_drive_lowercasing(file_name).unwrap();
71
72 let range = Range::new(
73 Position::new(span.line_start as u64 - 1, span.column_start as u64 - 1),
74 Position::new(span.line_end as u64 - 1, span.column_end as u64 - 1),
75 );
76
77 Location { uri, range }
78}
79
80/// Converts a secondary Rust span to a LSP related information
81///
82/// If the span is unlabelled this will return `None`.
83fn map_secondary_span_to_related(
84 span: &DiagnosticSpan,
85 workspace_root: &PathBuf,
86) -> Option<DiagnosticRelatedInformation> {
87 if let Some(label) = &span.label {
88 let location = map_span_to_location(span, workspace_root);
89 Some(DiagnosticRelatedInformation { location, message: label.clone() })
90 } else {
91 // Nothing to label this with
92 None
93 }
94}
95
96/// Determines if diagnostic is related to unused code
97fn is_unused_or_unnecessary(rd: &RustDiagnostic) -> bool {
98 if let Some(code) = &rd.code {
99 match code.code.as_str() {
100 "dead_code" | "unknown_lints" | "unreachable_code" | "unused_attributes"
101 | "unused_imports" | "unused_macros" | "unused_variables" => true,
102 _ => false,
103 }
104 } else {
105 false
106 }
107}
108
109/// Determines if diagnostic is related to deprecated code
110fn is_deprecated(rd: &RustDiagnostic) -> bool {
111 if let Some(code) = &rd.code {
112 match code.code.as_str() {
113 "deprecated" => true,
114 _ => false,
115 }
116 } else {
117 false
118 }
119}
120
121enum MappedRustChildDiagnostic {
122 Related(DiagnosticRelatedInformation),
123 SuggestedFix(CodeAction),
124 MessageLine(String),
125}
126
127fn map_rust_child_diagnostic(
128 rd: &RustDiagnostic,
129 workspace_root: &PathBuf,
130) -> MappedRustChildDiagnostic {
131 let spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect();
132 if spans.is_empty() {
133 // `rustc` uses these spanless children as a way to print multi-line
134 // messages
135 return MappedRustChildDiagnostic::MessageLine(rd.message.clone());
136 }
137
138 let mut edit_map: HashMap<Url, Vec<TextEdit>> = HashMap::new();
139 for &span in &spans {
140 match (&span.suggestion_applicability, &span.suggested_replacement) {
141 (Some(Applicability::MachineApplicable), Some(suggested_replacement)) => {
142 let location = map_span_to_location(span, workspace_root);
143 let edit = TextEdit::new(location.range, suggested_replacement.clone());
144 edit_map.entry(location.uri).or_default().push(edit);
145 }
146 _ => {}
147 }
148 }
149
150 if !edit_map.is_empty() {
151 MappedRustChildDiagnostic::SuggestedFix(CodeAction {
152 title: rd.message.clone(),
153 kind: Some("quickfix".to_string()),
154 diagnostics: None,
155 edit: Some(WorkspaceEdit::new(edit_map)),
156 command: None,
157 is_preferred: None,
158 })
159 } else {
160 MappedRustChildDiagnostic::Related(DiagnosticRelatedInformation {
161 location: map_span_to_location(spans[0], workspace_root),
162 message: rd.message.clone(),
163 })
164 }
165}
166
167#[derive(Debug)]
168pub(crate) struct MappedRustDiagnostic {
169 pub location: Location,
170 pub diagnostic: Diagnostic,
171 pub fixes: Vec<CodeAction>,
172}
173
174/// Converts a Rust root diagnostic to LSP form
175///
176/// This flattens the Rust diagnostic by:
177///
178/// 1. Creating a LSP diagnostic with the root message and primary span.
179/// 2. Adding any labelled secondary spans to `relatedInformation`
180/// 3. Categorising child diagnostics as either `SuggestedFix`es,
181/// `relatedInformation` or additional message lines.
182///
183/// If the diagnostic has no primary span this will return `None`
184pub(crate) fn map_rust_diagnostic_to_lsp(
185 rd: &RustDiagnostic,
186 workspace_root: &PathBuf,
187) -> Vec<MappedRustDiagnostic> {
188 let primary_spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect();
189 if primary_spans.is_empty() {
190 return vec![];
191 }
192
193 let severity = map_level_to_severity(rd.level);
194
195 let mut source = String::from("rustc");
196 let mut code = rd.code.as_ref().map(|c| c.code.clone());
197 if let Some(code_val) = &code {
198 // See if this is an RFC #2103 scoped lint (e.g. from Clippy)
199 let scoped_code: Vec<&str> = code_val.split("::").collect();
200 if scoped_code.len() == 2 {
201 source = String::from(scoped_code[0]);
202 code = Some(String::from(scoped_code[1]));
203 }
204 }
205
206 let mut needs_primary_span_label = true;
207 let mut related_information = vec![];
208 let mut tags = vec![];
209
210 for secondary_span in rd.spans.iter().filter(|s| !s.is_primary) {
211 let related = map_secondary_span_to_related(secondary_span, workspace_root);
212 if let Some(related) = related {
213 related_information.push(related);
214 }
215 }
216
217 let mut fixes = vec![];
218 let mut message = rd.message.clone();
219 for child in &rd.children {
220 let child = map_rust_child_diagnostic(&child, workspace_root);
221 match child {
222 MappedRustChildDiagnostic::Related(related) => related_information.push(related),
223 MappedRustChildDiagnostic::SuggestedFix(code_action) => fixes.push(code_action),
224 MappedRustChildDiagnostic::MessageLine(message_line) => {
225 write!(&mut message, "\n{}", message_line).unwrap();
226
227 // These secondary messages usually duplicate the content of the
228 // primary span label.
229 needs_primary_span_label = false;
230 }
231 }
232 }
233
234 if is_unused_or_unnecessary(rd) {
235 tags.push(DiagnosticTag::Unnecessary);
236 }
237
238 if is_deprecated(rd) {
239 tags.push(DiagnosticTag::Deprecated);
240 }
241
242 primary_spans
243 .iter()
244 .map(|primary_span| {
245 let location = map_span_to_location(&primary_span, workspace_root);
246
247 let mut message = message.clone();
248 if needs_primary_span_label {
249 if let Some(primary_span_label) = &primary_span.label {
250 write!(&mut message, "\n{}", primary_span_label).unwrap();
251 }
252 }
253
254 // If error occurs from macro expansion, add related info pointing to
255 // where the error originated
256 if !is_from_macro(&primary_span.file_name) && primary_span.expansion.is_some() {
257 let def_loc = map_span_to_location_naive(&primary_span, workspace_root);
258 related_information.push(DiagnosticRelatedInformation {
259 location: def_loc,
260 message: "Error originated from macro here".to_string(),
261 });
262 }
263
264 let diagnostic = Diagnostic {
265 range: location.range,
266 severity,
267 code: code.clone().map(NumberOrString::String),
268 source: Some(source.clone()),
269 message,
270 related_information: if !related_information.is_empty() {
271 Some(related_information.clone())
272 } else {
273 None
274 },
275 tags: if !tags.is_empty() { Some(tags.clone()) } else { None },
276 };
277
278 MappedRustDiagnostic { location, diagnostic, fixes: fixes.clone() }
279 })
280 .collect()
281}
282
283/// Returns a `Url` object from a given path, will lowercase drive letters if present.
284/// This will only happen when processing windows paths.
285///
286/// When processing non-windows path, this is essentially the same as `Url::from_file_path`.
287pub fn url_from_path_with_drive_lowercasing(
288 path: impl AsRef<Path>,
289) -> Result<Url, Box<dyn std::error::Error + Send + Sync>> {
290 let component_has_windows_drive = path.as_ref().components().any(|comp| {
291 if let Component::Prefix(c) = comp {
292 match c.kind() {
293 Prefix::Disk(_) | Prefix::VerbatimDisk(_) => return true,
294 _ => return false,
295 }
296 }
297 false
298 });
299
300 // VSCode expects drive letters to be lowercased, where rust will uppercase the drive letters.
301 if component_has_windows_drive {
302 let url_original = Url::from_file_path(&path)
303 .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?;
304
305 let drive_partition: Vec<&str> = url_original.as_str().rsplitn(2, ':').collect();
306
307 // There is a drive partition, but we never found a colon.
308 // This should not happen, but in this case we just pass it through.
309 if drive_partition.len() == 1 {
310 return Ok(url_original);
311 }
312
313 let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0];
314 let url = Url::from_str(&joined).expect("This came from a valid `Url`");
315
316 Ok(url)
317 } else {
318 Ok(Url::from_file_path(&path)
319 .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?)
320 }
321}
322
323// `Url` is not able to parse windows paths on unix machines.
324#[cfg(target_os = "windows")]
325#[cfg(test)]
326mod path_conversion_windows_tests {
327 use super::url_from_path_with_drive_lowercasing;
328 #[test]
329 fn test_lowercase_drive_letter_with_drive() {
330 let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap();
331
332 assert_eq!(url.to_string(), "file:///c:/Test");
333 }
334
335 #[test]
336 fn test_drive_without_colon_passthrough() {
337 let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap();
338
339 assert_eq!(url.to_string(), "file://localhost/C$/my_dir");
340 }
341}
diff --git a/crates/ra_flycheck/src/conv/test.rs b/crates/ra_flycheck/src/conv/test.rs
deleted file mode 100644
index 4e81455ca..000000000
--- a/crates/ra_flycheck/src/conv/test.rs
+++ /dev/null
@@ -1,1072 +0,0 @@
1//! This module contains the large and verbose snapshot tests for the
2//! conversions between `cargo check` json and LSP diagnostics.
3#[cfg(not(windows))]
4use crate::*;
5
6#[cfg(not(windows))]
7fn parse_diagnostic(val: &str) -> cargo_metadata::diagnostic::Diagnostic {
8 serde_json::from_str::<cargo_metadata::diagnostic::Diagnostic>(val).unwrap()
9}
10
11#[test]
12#[cfg(not(windows))]
13fn snap_rustc_incompatible_type_for_trait() {
14 let diag = parse_diagnostic(
15 r##"{
16 "message": "method `next` has an incompatible type for trait",
17 "code": {
18 "code": "E0053",
19 "explanation": "\nThe parameters of any trait method must match between a trait implementation\nand the trait definition.\n\nHere are a couple examples of this error:\n\n```compile_fail,E0053\ntrait Foo {\n fn foo(x: u16);\n fn bar(&self);\n}\n\nstruct Bar;\n\nimpl Foo for Bar {\n // error, expected u16, found i16\n fn foo(x: i16) { }\n\n // error, types differ in mutability\n fn bar(&mut self) { }\n}\n```\n"
20 },
21 "level": "error",
22 "spans": [
23 {
24 "file_name": "compiler/ty/list_iter.rs",
25 "byte_start": 1307,
26 "byte_end": 1350,
27 "line_start": 52,
28 "line_end": 52,
29 "column_start": 5,
30 "column_end": 48,
31 "is_primary": true,
32 "text": [
33 {
34 "text": " fn next(&self) -> Option<&'list ty::Ref<M>> {",
35 "highlight_start": 5,
36 "highlight_end": 48
37 }
38 ],
39 "label": "types differ in mutability",
40 "suggested_replacement": null,
41 "suggestion_applicability": null,
42 "expansion": null
43 }
44 ],
45 "children": [
46 {
47 "message": "expected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>`",
48 "code": null,
49 "level": "note",
50 "spans": [],
51 "children": [],
52 "rendered": null
53 }
54 ],
55 "rendered": "error[E0053]: method `next` has an incompatible type for trait\n --> compiler/ty/list_iter.rs:52:5\n |\n52 | fn next(&self) -> Option<&'list ty::Ref<M>> {\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability\n |\n = note: expected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>`\n\n"
56 }
57 "##,
58 );
59
60 let workspace_root = PathBuf::from("/test/");
61 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
62 insta::assert_debug_snapshot!(diag);
63}
64
65#[test]
66#[cfg(not(windows))]
67fn snap_rustc_unused_variable() {
68 let diag = parse_diagnostic(
69 r##"{
70"message": "unused variable: `foo`",
71"code": {
72 "code": "unused_variables",
73 "explanation": null
74},
75"level": "warning",
76"spans": [
77 {
78 "file_name": "driver/subcommand/repl.rs",
79 "byte_start": 9228,
80 "byte_end": 9231,
81 "line_start": 291,
82 "line_end": 291,
83 "column_start": 9,
84 "column_end": 12,
85 "is_primary": true,
86 "text": [
87 {
88 "text": " let foo = 42;",
89 "highlight_start": 9,
90 "highlight_end": 12
91 }
92 ],
93 "label": null,
94 "suggested_replacement": null,
95 "suggestion_applicability": null,
96 "expansion": null
97 }
98],
99"children": [
100 {
101 "message": "#[warn(unused_variables)] on by default",
102 "code": null,
103 "level": "note",
104 "spans": [],
105 "children": [],
106 "rendered": null
107 },
108 {
109 "message": "consider prefixing with an underscore",
110 "code": null,
111 "level": "help",
112 "spans": [
113 {
114 "file_name": "driver/subcommand/repl.rs",
115 "byte_start": 9228,
116 "byte_end": 9231,
117 "line_start": 291,
118 "line_end": 291,
119 "column_start": 9,
120 "column_end": 12,
121 "is_primary": true,
122 "text": [
123 {
124 "text": " let foo = 42;",
125 "highlight_start": 9,
126 "highlight_end": 12
127 }
128 ],
129 "label": null,
130 "suggested_replacement": "_foo",
131 "suggestion_applicability": "MachineApplicable",
132 "expansion": null
133 }
134 ],
135 "children": [],
136 "rendered": null
137 }
138],
139"rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n"
140}"##,
141 );
142
143 let workspace_root = PathBuf::from("/test/");
144 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
145 insta::assert_debug_snapshot!(diag);
146}
147
148#[test]
149#[cfg(not(windows))]
150fn snap_rustc_wrong_number_of_parameters() {
151 let diag = parse_diagnostic(
152 r##"{
153"message": "this function takes 2 parameters but 3 parameters were supplied",
154"code": {
155 "code": "E0061",
156 "explanation": "\nThe number of arguments passed to a function must match the number of arguments\nspecified in the function signature.\n\nFor example, a function like:\n\n```\nfn f(a: u16, b: &str) {}\n```\n\nMust always be called with exactly two arguments, e.g., `f(2, \"test\")`.\n\nNote that Rust does not have a notion of optional function arguments or\nvariadic functions (except for its C-FFI).\n"
157},
158"level": "error",
159"spans": [
160 {
161 "file_name": "compiler/ty/select.rs",
162 "byte_start": 8787,
163 "byte_end": 9241,
164 "line_start": 219,
165 "line_end": 231,
166 "column_start": 5,
167 "column_end": 6,
168 "is_primary": false,
169 "text": [
170 {
171 "text": " pub fn add_evidence(",
172 "highlight_start": 5,
173 "highlight_end": 25
174 },
175 {
176 "text": " &mut self,",
177 "highlight_start": 1,
178 "highlight_end": 19
179 },
180 {
181 "text": " target_poly: &ty::Ref<ty::Poly>,",
182 "highlight_start": 1,
183 "highlight_end": 41
184 },
185 {
186 "text": " evidence_poly: &ty::Ref<ty::Poly>,",
187 "highlight_start": 1,
188 "highlight_end": 43
189 },
190 {
191 "text": " ) {",
192 "highlight_start": 1,
193 "highlight_end": 8
194 },
195 {
196 "text": " match target_poly {",
197 "highlight_start": 1,
198 "highlight_end": 28
199 },
200 {
201 "text": " ty::Ref::Var(tvar, _) => self.add_var_evidence(tvar, evidence_poly),",
202 "highlight_start": 1,
203 "highlight_end": 81
204 },
205 {
206 "text": " ty::Ref::Fixed(target_ty) => {",
207 "highlight_start": 1,
208 "highlight_end": 43
209 },
210 {
211 "text": " let evidence_ty = evidence_poly.resolve_to_ty();",
212 "highlight_start": 1,
213 "highlight_end": 65
214 },
215 {
216 "text": " self.add_evidence_ty(target_ty, evidence_poly, evidence_ty)",
217 "highlight_start": 1,
218 "highlight_end": 76
219 },
220 {
221 "text": " }",
222 "highlight_start": 1,
223 "highlight_end": 14
224 },
225 {
226 "text": " }",
227 "highlight_start": 1,
228 "highlight_end": 10
229 },
230 {
231 "text": " }",
232 "highlight_start": 1,
233 "highlight_end": 6
234 }
235 ],
236 "label": "defined here",
237 "suggested_replacement": null,
238 "suggestion_applicability": null,
239 "expansion": null
240 },
241 {
242 "file_name": "compiler/ty/select.rs",
243 "byte_start": 4045,
244 "byte_end": 4057,
245 "line_start": 104,
246 "line_end": 104,
247 "column_start": 18,
248 "column_end": 30,
249 "is_primary": true,
250 "text": [
251 {
252 "text": " self.add_evidence(target_fixed, evidence_fixed, false);",
253 "highlight_start": 18,
254 "highlight_end": 30
255 }
256 ],
257 "label": "expected 2 parameters",
258 "suggested_replacement": null,
259 "suggestion_applicability": null,
260 "expansion": null
261 }
262],
263"children": [],
264"rendered": "error[E0061]: this function takes 2 parameters but 3 parameters were supplied\n --> compiler/ty/select.rs:104:18\n |\n104 | self.add_evidence(target_fixed, evidence_fixed, false);\n | ^^^^^^^^^^^^ expected 2 parameters\n...\n219 | / pub fn add_evidence(\n220 | | &mut self,\n221 | | target_poly: &ty::Ref<ty::Poly>,\n222 | | evidence_poly: &ty::Ref<ty::Poly>,\n... |\n230 | | }\n231 | | }\n | |_____- defined here\n\n"
265}"##,
266 );
267
268 let workspace_root = PathBuf::from("/test/");
269 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
270 insta::assert_debug_snapshot!(diag);
271}
272
273#[test]
274#[cfg(not(windows))]
275fn snap_clippy_pass_by_ref() {
276 let diag = parse_diagnostic(
277 r##"{
278"message": "this argument is passed by reference, but would be more efficient if passed by value",
279"code": {
280 "code": "clippy::trivially_copy_pass_by_ref",
281 "explanation": null
282},
283"level": "warning",
284"spans": [
285 {
286 "file_name": "compiler/mir/tagset.rs",
287 "byte_start": 941,
288 "byte_end": 946,
289 "line_start": 42,
290 "line_end": 42,
291 "column_start": 24,
292 "column_end": 29,
293 "is_primary": true,
294 "text": [
295 {
296 "text": " pub fn is_disjoint(&self, other: Self) -> bool {",
297 "highlight_start": 24,
298 "highlight_end": 29
299 }
300 ],
301 "label": null,
302 "suggested_replacement": null,
303 "suggestion_applicability": null,
304 "expansion": null
305 }
306],
307"children": [
308 {
309 "message": "lint level defined here",
310 "code": null,
311 "level": "note",
312 "spans": [
313 {
314 "file_name": "compiler/lib.rs",
315 "byte_start": 8,
316 "byte_end": 19,
317 "line_start": 1,
318 "line_end": 1,
319 "column_start": 9,
320 "column_end": 20,
321 "is_primary": true,
322 "text": [
323 {
324 "text": "#![warn(clippy::all)]",
325 "highlight_start": 9,
326 "highlight_end": 20
327 }
328 ],
329 "label": null,
330 "suggested_replacement": null,
331 "suggestion_applicability": null,
332 "expansion": null
333 }
334 ],
335 "children": [],
336 "rendered": null
337 },
338 {
339 "message": "#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]",
340 "code": null,
341 "level": "note",
342 "spans": [],
343 "children": [],
344 "rendered": null
345 },
346 {
347 "message": "for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref",
348 "code": null,
349 "level": "help",
350 "spans": [],
351 "children": [],
352 "rendered": null
353 },
354 {
355 "message": "consider passing by value instead",
356 "code": null,
357 "level": "help",
358 "spans": [
359 {
360 "file_name": "compiler/mir/tagset.rs",
361 "byte_start": 941,
362 "byte_end": 946,
363 "line_start": 42,
364 "line_end": 42,
365 "column_start": 24,
366 "column_end": 29,
367 "is_primary": true,
368 "text": [
369 {
370 "text": " pub fn is_disjoint(&self, other: Self) -> bool {",
371 "highlight_start": 24,
372 "highlight_end": 29
373 }
374 ],
375 "label": null,
376 "suggested_replacement": "self",
377 "suggestion_applicability": "Unspecified",
378 "expansion": null
379 }
380 ],
381 "children": [],
382 "rendered": null
383 }
384],
385"rendered": "warning: this argument is passed by reference, but would be more efficient if passed by value\n --> compiler/mir/tagset.rs:42:24\n |\n42 | pub fn is_disjoint(&self, other: Self) -> bool {\n | ^^^^^ help: consider passing by value instead: `self`\n |\nnote: lint level defined here\n --> compiler/lib.rs:1:9\n |\n1 | #![warn(clippy::all)]\n | ^^^^^^^^^^^\n = note: #[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref\n\n"
386}"##,
387 );
388
389 let workspace_root = PathBuf::from("/test/");
390 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
391 insta::assert_debug_snapshot!(diag);
392}
393
394#[test]
395#[cfg(not(windows))]
396fn snap_rustc_mismatched_type() {
397 let diag = parse_diagnostic(
398 r##"{
399"message": "mismatched types",
400"code": {
401 "code": "E0308",
402 "explanation": "\nThis error occurs when the compiler was unable to infer the concrete type of a\nvariable. It can occur for several cases, the most common of which is a\nmismatch in the expected type that the compiler inferred for a variable's\ninitializing expression, and the actual type explicitly assigned to the\nvariable.\n\nFor example:\n\n```compile_fail,E0308\nlet x: i32 = \"I am not a number!\";\n// ~~~ ~~~~~~~~~~~~~~~~~~~~\n// | |\n// | initializing expression;\n// | compiler infers type `&str`\n// |\n// type `i32` assigned to variable `x`\n```\n"
403},
404"level": "error",
405"spans": [
406 {
407 "file_name": "runtime/compiler_support.rs",
408 "byte_start": 1589,
409 "byte_end": 1594,
410 "line_start": 48,
411 "line_end": 48,
412 "column_start": 65,
413 "column_end": 70,
414 "is_primary": true,
415 "text": [
416 {
417 "text": " let layout = alloc::Layout::from_size_align_unchecked(size, align);",
418 "highlight_start": 65,
419 "highlight_end": 70
420 }
421 ],
422 "label": "expected usize, found u32",
423 "suggested_replacement": null,
424 "suggestion_applicability": null,
425 "expansion": null
426 }
427],
428"children": [],
429"rendered": "error[E0308]: mismatched types\n --> runtime/compiler_support.rs:48:65\n |\n48 | let layout = alloc::Layout::from_size_align_unchecked(size, align);\n | ^^^^^ expected usize, found u32\n\n"
430}"##,
431 );
432
433 let workspace_root = PathBuf::from("/test/");
434 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
435 insta::assert_debug_snapshot!(diag);
436}
437
438#[test]
439#[cfg(not(windows))]
440fn snap_handles_macro_location() {
441 let diag = parse_diagnostic(
442 r##"{
443"rendered": "error[E0277]: can't compare `{integer}` with `&str`\n --> src/main.rs:2:5\n |\n2 | assert_eq!(1, \"love\");\n | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &str`\n |\n = help: the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`\n = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)\n\n",
444"children": [
445 {
446 "children": [],
447 "code": null,
448 "level": "help",
449 "message": "the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
450 "rendered": null,
451 "spans": []
452 }
453],
454"code": {
455 "code": "E0277",
456 "explanation": "\nYou tried to use a type which doesn't implement some trait in a place which\nexpected that trait. Erroneous code example:\n\n```compile_fail,E0277\n// here we declare the Foo trait with a bar method\ntrait Foo {\n fn bar(&self);\n}\n\n// we now declare a function which takes an object implementing the Foo trait\nfn some_func<T: Foo>(foo: T) {\n foo.bar();\n}\n\nfn main() {\n // we now call the method with the i32 type, which doesn't implement\n // the Foo trait\n some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied\n}\n```\n\nIn order to fix this error, verify that the type you're using does implement\nthe trait. Example:\n\n```\ntrait Foo {\n fn bar(&self);\n}\n\nfn some_func<T: Foo>(foo: T) {\n foo.bar(); // we can now use this method since i32 implements the\n // Foo trait\n}\n\n// we implement the trait on the i32 type\nimpl Foo for i32 {\n fn bar(&self) {}\n}\n\nfn main() {\n some_func(5i32); // ok!\n}\n```\n\nOr in a generic context, an erroneous code example would look like:\n\n```compile_fail,E0277\nfn some_func<T>(foo: T) {\n println!(\"{:?}\", foo); // error: the trait `core::fmt::Debug` is not\n // implemented for the type `T`\n}\n\nfn main() {\n // We now call the method with the i32 type,\n // which *does* implement the Debug trait.\n some_func(5i32);\n}\n```\n\nNote that the error here is in the definition of the generic function: Although\nwe only call it with a parameter that does implement `Debug`, the compiler\nstill rejects the function: It must work with all possible input types. In\norder to make this example compile, we need to restrict the generic type we're\naccepting:\n\n```\nuse std::fmt;\n\n// Restrict the input type to types that implement Debug.\nfn some_func<T: fmt::Debug>(foo: T) {\n println!(\"{:?}\", foo);\n}\n\nfn main() {\n // Calling the method is still fine, as i32 implements Debug.\n some_func(5i32);\n\n // This would fail to compile now:\n // struct WithoutDebug;\n // some_func(WithoutDebug);\n}\n```\n\nRust only looks at the signature of the called function, as such it must\nalready specify all requirements that will be used for every type parameter.\n"
457},
458"level": "error",
459"message": "can't compare `{integer}` with `&str`",
460"spans": [
461 {
462 "byte_end": 155,
463 "byte_start": 153,
464 "column_end": 33,
465 "column_start": 31,
466 "expansion": {
467 "def_site_span": {
468 "byte_end": 940,
469 "byte_start": 0,
470 "column_end": 6,
471 "column_start": 1,
472 "expansion": null,
473 "file_name": "<::core::macros::assert_eq macros>",
474 "is_primary": false,
475 "label": null,
476 "line_end": 36,
477 "line_start": 1,
478 "suggested_replacement": null,
479 "suggestion_applicability": null,
480 "text": [
481 {
482 "highlight_end": 35,
483 "highlight_start": 1,
484 "text": "($ left : expr, $ right : expr) =>"
485 },
486 {
487 "highlight_end": 3,
488 "highlight_start": 1,
489 "text": "({"
490 },
491 {
492 "highlight_end": 33,
493 "highlight_start": 1,
494 "text": " match (& $ left, & $ right)"
495 },
496 {
497 "highlight_end": 7,
498 "highlight_start": 1,
499 "text": " {"
500 },
501 {
502 "highlight_end": 34,
503 "highlight_start": 1,
504 "text": " (left_val, right_val) =>"
505 },
506 {
507 "highlight_end": 11,
508 "highlight_start": 1,
509 "text": " {"
510 },
511 {
512 "highlight_end": 46,
513 "highlight_start": 1,
514 "text": " if ! (* left_val == * right_val)"
515 },
516 {
517 "highlight_end": 15,
518 "highlight_start": 1,
519 "text": " {"
520 },
521 {
522 "highlight_end": 25,
523 "highlight_start": 1,
524 "text": " panic !"
525 },
526 {
527 "highlight_end": 57,
528 "highlight_start": 1,
529 "text": " (r#\"assertion failed: `(left == right)`"
530 },
531 {
532 "highlight_end": 16,
533 "highlight_start": 1,
534 "text": " left: `{:?}`,"
535 },
536 {
537 "highlight_end": 18,
538 "highlight_start": 1,
539 "text": " right: `{:?}`\"#,"
540 },
541 {
542 "highlight_end": 47,
543 "highlight_start": 1,
544 "text": " & * left_val, & * right_val)"
545 },
546 {
547 "highlight_end": 15,
548 "highlight_start": 1,
549 "text": " }"
550 },
551 {
552 "highlight_end": 11,
553 "highlight_start": 1,
554 "text": " }"
555 },
556 {
557 "highlight_end": 7,
558 "highlight_start": 1,
559 "text": " }"
560 },
561 {
562 "highlight_end": 42,
563 "highlight_start": 1,
564 "text": " }) ; ($ left : expr, $ right : expr,) =>"
565 },
566 {
567 "highlight_end": 49,
568 "highlight_start": 1,
569 "text": "({ $ crate :: assert_eq ! ($ left, $ right) }) ;"
570 },
571 {
572 "highlight_end": 53,
573 "highlight_start": 1,
574 "text": "($ left : expr, $ right : expr, $ ($ arg : tt) +) =>"
575 },
576 {
577 "highlight_end": 3,
578 "highlight_start": 1,
579 "text": "({"
580 },
581 {
582 "highlight_end": 37,
583 "highlight_start": 1,
584 "text": " match (& ($ left), & ($ right))"
585 },
586 {
587 "highlight_end": 7,
588 "highlight_start": 1,
589 "text": " {"
590 },
591 {
592 "highlight_end": 34,
593 "highlight_start": 1,
594 "text": " (left_val, right_val) =>"
595 },
596 {
597 "highlight_end": 11,
598 "highlight_start": 1,
599 "text": " {"
600 },
601 {
602 "highlight_end": 46,
603 "highlight_start": 1,
604 "text": " if ! (* left_val == * right_val)"
605 },
606 {
607 "highlight_end": 15,
608 "highlight_start": 1,
609 "text": " {"
610 },
611 {
612 "highlight_end": 25,
613 "highlight_start": 1,
614 "text": " panic !"
615 },
616 {
617 "highlight_end": 57,
618 "highlight_start": 1,
619 "text": " (r#\"assertion failed: `(left == right)`"
620 },
621 {
622 "highlight_end": 16,
623 "highlight_start": 1,
624 "text": " left: `{:?}`,"
625 },
626 {
627 "highlight_end": 22,
628 "highlight_start": 1,
629 "text": " right: `{:?}`: {}\"#,"
630 },
631 {
632 "highlight_end": 72,
633 "highlight_start": 1,
634 "text": " & * left_val, & * right_val, $ crate :: format_args !"
635 },
636 {
637 "highlight_end": 33,
638 "highlight_start": 1,
639 "text": " ($ ($ arg) +))"
640 },
641 {
642 "highlight_end": 15,
643 "highlight_start": 1,
644 "text": " }"
645 },
646 {
647 "highlight_end": 11,
648 "highlight_start": 1,
649 "text": " }"
650 },
651 {
652 "highlight_end": 7,
653 "highlight_start": 1,
654 "text": " }"
655 },
656 {
657 "highlight_end": 6,
658 "highlight_start": 1,
659 "text": " }) ;"
660 }
661 ]
662 },
663 "macro_decl_name": "assert_eq!",
664 "span": {
665 "byte_end": 38,
666 "byte_start": 16,
667 "column_end": 27,
668 "column_start": 5,
669 "expansion": null,
670 "file_name": "src/main.rs",
671 "is_primary": false,
672 "label": null,
673 "line_end": 2,
674 "line_start": 2,
675 "suggested_replacement": null,
676 "suggestion_applicability": null,
677 "text": [
678 {
679 "highlight_end": 27,
680 "highlight_start": 5,
681 "text": " assert_eq!(1, \"love\");"
682 }
683 ]
684 }
685 },
686 "file_name": "<::core::macros::assert_eq macros>",
687 "is_primary": true,
688 "label": "no implementation for `{integer} == &str`",
689 "line_end": 7,
690 "line_start": 7,
691 "suggested_replacement": null,
692 "suggestion_applicability": null,
693 "text": [
694 {
695 "highlight_end": 33,
696 "highlight_start": 31,
697 "text": " if ! (* left_val == * right_val)"
698 }
699 ]
700 }
701]
702}"##,
703 );
704
705 let workspace_root = PathBuf::from("/test/");
706 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
707 insta::assert_debug_snapshot!(diag);
708}
709
710#[test]
711#[cfg(not(windows))]
712fn snap_macro_compiler_error() {
713 let diag = parse_diagnostic(
714 r##"{
715 "rendered": "error: Please register your known path in the path module\n --> crates/ra_hir_def/src/path.rs:265:9\n |\n265 | compile_error!(\"Please register your known path in the path module\")\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | \n ::: crates/ra_hir_def/src/data.rs:80:16\n |\n80 | let path = path![std::future::Future];\n | -------------------------- in this macro invocation\n\n",
716 "children": [],
717 "code": null,
718 "level": "error",
719 "message": "Please register your known path in the path module",
720 "spans": [
721 {
722 "byte_end": 8285,
723 "byte_start": 8217,
724 "column_end": 77,
725 "column_start": 9,
726 "expansion": {
727 "def_site_span": {
728 "byte_end": 8294,
729 "byte_start": 7858,
730 "column_end": 2,
731 "column_start": 1,
732 "expansion": null,
733 "file_name": "crates/ra_hir_def/src/path.rs",
734 "is_primary": false,
735 "label": null,
736 "line_end": 267,
737 "line_start": 254,
738 "suggested_replacement": null,
739 "suggestion_applicability": null,
740 "text": [
741 {
742 "highlight_end": 28,
743 "highlight_start": 1,
744 "text": "macro_rules! __known_path {"
745 },
746 {
747 "highlight_end": 37,
748 "highlight_start": 1,
749 "text": " (std::iter::IntoIterator) => {};"
750 },
751 {
752 "highlight_end": 33,
753 "highlight_start": 1,
754 "text": " (std::result::Result) => {};"
755 },
756 {
757 "highlight_end": 29,
758 "highlight_start": 1,
759 "text": " (std::ops::Range) => {};"
760 },
761 {
762 "highlight_end": 33,
763 "highlight_start": 1,
764 "text": " (std::ops::RangeFrom) => {};"
765 },
766 {
767 "highlight_end": 33,
768 "highlight_start": 1,
769 "text": " (std::ops::RangeFull) => {};"
770 },
771 {
772 "highlight_end": 31,
773 "highlight_start": 1,
774 "text": " (std::ops::RangeTo) => {};"
775 },
776 {
777 "highlight_end": 40,
778 "highlight_start": 1,
779 "text": " (std::ops::RangeToInclusive) => {};"
780 },
781 {
782 "highlight_end": 38,
783 "highlight_start": 1,
784 "text": " (std::ops::RangeInclusive) => {};"
785 },
786 {
787 "highlight_end": 27,
788 "highlight_start": 1,
789 "text": " (std::ops::Try) => {};"
790 },
791 {
792 "highlight_end": 22,
793 "highlight_start": 1,
794 "text": " ($path:path) => {"
795 },
796 {
797 "highlight_end": 77,
798 "highlight_start": 1,
799 "text": " compile_error!(\"Please register your known path in the path module\")"
800 },
801 {
802 "highlight_end": 7,
803 "highlight_start": 1,
804 "text": " };"
805 },
806 {
807 "highlight_end": 2,
808 "highlight_start": 1,
809 "text": "}"
810 }
811 ]
812 },
813 "macro_decl_name": "$crate::__known_path!",
814 "span": {
815 "byte_end": 8427,
816 "byte_start": 8385,
817 "column_end": 51,
818 "column_start": 9,
819 "expansion": {
820 "def_site_span": {
821 "byte_end": 8611,
822 "byte_start": 8312,
823 "column_end": 2,
824 "column_start": 1,
825 "expansion": null,
826 "file_name": "crates/ra_hir_def/src/path.rs",
827 "is_primary": false,
828 "label": null,
829 "line_end": 277,
830 "line_start": 270,
831 "suggested_replacement": null,
832 "suggestion_applicability": null,
833 "text": [
834 {
835 "highlight_end": 22,
836 "highlight_start": 1,
837 "text": "macro_rules! __path {"
838 },
839 {
840 "highlight_end": 43,
841 "highlight_start": 1,
842 "text": " ($start:ident $(:: $seg:ident)*) => ({"
843 },
844 {
845 "highlight_end": 51,
846 "highlight_start": 1,
847 "text": " $crate::__known_path!($start $(:: $seg)*);"
848 },
849 {
850 "highlight_end": 87,
851 "highlight_start": 1,
852 "text": " $crate::path::ModPath::from_simple_segments($crate::path::PathKind::Abs, vec!["
853 },
854 {
855 "highlight_end": 76,
856 "highlight_start": 1,
857 "text": " $crate::path::__name![$start], $($crate::path::__name![$seg],)*"
858 },
859 {
860 "highlight_end": 11,
861 "highlight_start": 1,
862 "text": " ])"
863 },
864 {
865 "highlight_end": 8,
866 "highlight_start": 1,
867 "text": " });"
868 },
869 {
870 "highlight_end": 2,
871 "highlight_start": 1,
872 "text": "}"
873 }
874 ]
875 },
876 "macro_decl_name": "path!",
877 "span": {
878 "byte_end": 2966,
879 "byte_start": 2940,
880 "column_end": 42,
881 "column_start": 16,
882 "expansion": null,
883 "file_name": "crates/ra_hir_def/src/data.rs",
884 "is_primary": false,
885 "label": null,
886 "line_end": 80,
887 "line_start": 80,
888 "suggested_replacement": null,
889 "suggestion_applicability": null,
890 "text": [
891 {
892 "highlight_end": 42,
893 "highlight_start": 16,
894 "text": " let path = path![std::future::Future];"
895 }
896 ]
897 }
898 },
899 "file_name": "crates/ra_hir_def/src/path.rs",
900 "is_primary": false,
901 "label": null,
902 "line_end": 272,
903 "line_start": 272,
904 "suggested_replacement": null,
905 "suggestion_applicability": null,
906 "text": [
907 {
908 "highlight_end": 51,
909 "highlight_start": 9,
910 "text": " $crate::__known_path!($start $(:: $seg)*);"
911 }
912 ]
913 }
914 },
915 "file_name": "crates/ra_hir_def/src/path.rs",
916 "is_primary": true,
917 "label": null,
918 "line_end": 265,
919 "line_start": 265,
920 "suggested_replacement": null,
921 "suggestion_applicability": null,
922 "text": [
923 {
924 "highlight_end": 77,
925 "highlight_start": 9,
926 "text": " compile_error!(\"Please register your known path in the path module\")"
927 }
928 ]
929 }
930 ]
931}
932 "##,
933 );
934
935 let workspace_root = PathBuf::from("/test/");
936 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
937 insta::assert_debug_snapshot!(diag);
938}
939
940#[test]
941#[cfg(not(windows))]
942fn snap_multi_line_fix() {
943 let diag = parse_diagnostic(
944 r##"{
945 "rendered": "warning: returning the result of a let binding from a block\n --> src/main.rs:4:5\n |\n3 | let a = (0..10).collect();\n | -------------------------- unnecessary let binding\n4 | a\n | ^\n |\n = note: `#[warn(clippy::let_and_return)]` on by default\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return\nhelp: return the expression directly\n |\n3 | \n4 | (0..10).collect()\n |\n\n",
946 "children": [
947 {
948 "children": [],
949 "code": null,
950 "level": "note",
951 "message": "`#[warn(clippy::let_and_return)]` on by default",
952 "rendered": null,
953 "spans": []
954 },
955 {
956 "children": [],
957 "code": null,
958 "level": "help",
959 "message": "for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return",
960 "rendered": null,
961 "spans": []
962 },
963 {
964 "children": [],
965 "code": null,
966 "level": "help",
967 "message": "return the expression directly",
968 "rendered": null,
969 "spans": [
970 {
971 "byte_end": 55,
972 "byte_start": 29,
973 "column_end": 31,
974 "column_start": 5,
975 "expansion": null,
976 "file_name": "src/main.rs",
977 "is_primary": true,
978 "label": null,
979 "line_end": 3,
980 "line_start": 3,
981 "suggested_replacement": "",
982 "suggestion_applicability": "MachineApplicable",
983 "text": [
984 {
985 "highlight_end": 31,
986 "highlight_start": 5,
987 "text": " let a = (0..10).collect();"
988 }
989 ]
990 },
991 {
992 "byte_end": 61,
993 "byte_start": 60,
994 "column_end": 6,
995 "column_start": 5,
996 "expansion": null,
997 "file_name": "src/main.rs",
998 "is_primary": true,
999 "label": null,
1000 "line_end": 4,
1001 "line_start": 4,
1002 "suggested_replacement": "(0..10).collect()",
1003 "suggestion_applicability": "MachineApplicable",
1004 "text": [
1005 {
1006 "highlight_end": 6,
1007 "highlight_start": 5,
1008 "text": " a"
1009 }
1010 ]
1011 }
1012 ]
1013 }
1014 ],
1015 "code": {
1016 "code": "clippy::let_and_return",
1017 "explanation": null
1018 },
1019 "level": "warning",
1020 "message": "returning the result of a let binding from a block",
1021 "spans": [
1022 {
1023 "byte_end": 55,
1024 "byte_start": 29,
1025 "column_end": 31,
1026 "column_start": 5,
1027 "expansion": null,
1028 "file_name": "src/main.rs",
1029 "is_primary": false,
1030 "label": "unnecessary let binding",
1031 "line_end": 3,
1032 "line_start": 3,
1033 "suggested_replacement": null,
1034 "suggestion_applicability": null,
1035 "text": [
1036 {
1037 "highlight_end": 31,
1038 "highlight_start": 5,
1039 "text": " let a = (0..10).collect();"
1040 }
1041 ]
1042 },
1043 {
1044 "byte_end": 61,
1045 "byte_start": 60,
1046 "column_end": 6,
1047 "column_start": 5,
1048 "expansion": null,
1049 "file_name": "src/main.rs",
1050 "is_primary": true,
1051 "label": null,
1052 "line_end": 4,
1053 "line_start": 4,
1054 "suggested_replacement": null,
1055 "suggestion_applicability": null,
1056 "text": [
1057 {
1058 "highlight_end": 6,
1059 "highlight_start": 5,
1060 "text": " a"
1061 }
1062 ]
1063 }
1064 ]
1065 }
1066 "##,
1067 );
1068
1069 let workspace_root = PathBuf::from("/test/");
1070 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
1071 insta::assert_debug_snapshot!(diag);
1072}
diff --git a/crates/ra_flycheck/src/lib.rs b/crates/ra_flycheck/src/lib.rs
index b54a30ab8..041e38a9f 100644
--- a/crates/ra_flycheck/src/lib.rs
+++ b/crates/ra_flycheck/src/lib.rs
@@ -1,11 +1,9 @@
1//! cargo_check provides the functionality needed to run `cargo check` or 1//! cargo_check provides the functionality needed to run `cargo check` or
2//! another compatible command (f.x. clippy) in a background thread and provide 2//! another compatible command (f.x. clippy) in a background thread and provide
3//! LSP diagnostics based on the output of the command. 3//! LSP diagnostics based on the output of the command.
4mod conv;
5 4
6use std::{ 5use std::{
7 env, 6 io::{self, BufReader},
8 io::{self, BufRead, BufReader},
9 path::PathBuf, 7 path::PathBuf,
10 process::{Command, Stdio}, 8 process::{Command, Stdio},
11 time::Instant, 9 time::Instant,
@@ -13,18 +11,14 @@ use std::{
13 11
14use cargo_metadata::Message; 12use cargo_metadata::Message;
15use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender}; 13use crossbeam_channel::{never, select, unbounded, Receiver, RecvError, Sender};
16use lsp_types::{
17 CodeAction, CodeActionOrCommand, Diagnostic, Url, WorkDoneProgress, WorkDoneProgressBegin,
18 WorkDoneProgressEnd, WorkDoneProgressReport,
19};
20
21use crate::conv::{map_rust_diagnostic_to_lsp, MappedRustDiagnostic};
22 14
23pub use crate::conv::url_from_path_with_drive_lowercasing; 15pub use cargo_metadata::diagnostic::{
16 Applicability, Diagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion,
17};
24 18
25#[derive(Clone, Debug, PartialEq, Eq)] 19#[derive(Clone, Debug, PartialEq, Eq)]
26pub enum FlycheckConfig { 20pub enum FlycheckConfig {
27 CargoCommand { command: String, all_targets: bool, extra_args: Vec<String> }, 21 CargoCommand { command: String, all_targets: bool, all_features: bool, extra_args: Vec<String> },
28 CustomCommand { command: String, args: Vec<String> }, 22 CustomCommand { command: String, args: Vec<String> },
29} 23}
30 24
@@ -62,10 +56,17 @@ pub enum CheckTask {
62 ClearDiagnostics, 56 ClearDiagnostics,
63 57
64 /// Request adding a diagnostic with fixes included to a file 58 /// Request adding a diagnostic with fixes included to a file
65 AddDiagnostic { url: Url, diagnostic: Diagnostic, fixes: Vec<CodeActionOrCommand> }, 59 AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic },
66 60
67 /// Request check progress notification to client 61 /// Request check progress notification to client
68 Status(WorkDoneProgress), 62 Status(Status),
63}
64
65#[derive(Debug)]
66pub enum Status {
67 Being,
68 Progress(String),
69 End,
69} 70}
70 71
71pub enum CheckCommand { 72pub enum CheckCommand {
@@ -132,9 +133,7 @@ impl FlycheckThread {
132 133
133 fn clean_previous_results(&self, task_send: &Sender<CheckTask>) { 134 fn clean_previous_results(&self, task_send: &Sender<CheckTask>) {
134 task_send.send(CheckTask::ClearDiagnostics).unwrap(); 135 task_send.send(CheckTask::ClearDiagnostics).unwrap();
135 task_send 136 task_send.send(CheckTask::Status(Status::End)).unwrap();
136 .send(CheckTask::Status(WorkDoneProgress::End(WorkDoneProgressEnd { message: None })))
137 .unwrap();
138 } 137 }
139 138
140 fn should_recheck(&mut self) -> bool { 139 fn should_recheck(&mut self) -> bool {
@@ -156,55 +155,29 @@ impl FlycheckThread {
156 fn handle_message(&self, msg: CheckEvent, task_send: &Sender<CheckTask>) { 155 fn handle_message(&self, msg: CheckEvent, task_send: &Sender<CheckTask>) {
157 match msg { 156 match msg {
158 CheckEvent::Begin => { 157 CheckEvent::Begin => {
159 task_send 158 task_send.send(CheckTask::Status(Status::Being)).unwrap();
160 .send(CheckTask::Status(WorkDoneProgress::Begin(WorkDoneProgressBegin {
161 title: "Running 'cargo check'".to_string(),
162 cancellable: Some(false),
163 message: None,
164 percentage: None,
165 })))
166 .unwrap();
167 } 159 }
168 160
169 CheckEvent::End => { 161 CheckEvent::End => {
170 task_send 162 task_send.send(CheckTask::Status(Status::End)).unwrap();
171 .send(CheckTask::Status(WorkDoneProgress::End(WorkDoneProgressEnd {
172 message: None,
173 })))
174 .unwrap();
175 } 163 }
176 164
177 CheckEvent::Msg(Message::CompilerArtifact(msg)) => { 165 CheckEvent::Msg(Message::CompilerArtifact(msg)) => {
178 task_send 166 task_send.send(CheckTask::Status(Status::Progress(msg.target.name))).unwrap();
179 .send(CheckTask::Status(WorkDoneProgress::Report(WorkDoneProgressReport {
180 cancellable: Some(false),
181 message: Some(msg.target.name),
182 percentage: None,
183 })))
184 .unwrap();
185 } 167 }
186 168
187 CheckEvent::Msg(Message::CompilerMessage(msg)) => { 169 CheckEvent::Msg(Message::CompilerMessage(msg)) => {
188 let map_result = map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root); 170 task_send
189 if map_result.is_empty() { 171 .send(CheckTask::AddDiagnostic {
190 return; 172 workspace_root: self.workspace_root.clone(),
191 } 173 diagnostic: msg.message,
192 174 })
193 for MappedRustDiagnostic { location, diagnostic, fixes } in map_result { 175 .unwrap();
194 let fixes = fixes
195 .into_iter()
196 .map(|fix| {
197 CodeAction { diagnostics: Some(vec![diagnostic.clone()]), ..fix }.into()
198 })
199 .collect();
200
201 task_send
202 .send(CheckTask::AddDiagnostic { url: location.uri, diagnostic, fixes })
203 .unwrap();
204 }
205 } 176 }
206 177
207 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} 178 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {}
179 CheckEvent::Msg(Message::BuildFinished(_)) => {}
180 CheckEvent::Msg(Message::TextLine(_)) => {}
208 CheckEvent::Msg(Message::Unknown) => {} 181 CheckEvent::Msg(Message::Unknown) => {}
209 } 182 }
210 } 183 }
@@ -215,14 +188,17 @@ impl FlycheckThread {
215 self.check_process = None; 188 self.check_process = None;
216 189
217 let mut cmd = match &self.config { 190 let mut cmd = match &self.config {
218 FlycheckConfig::CargoCommand { command, all_targets, extra_args } => { 191 FlycheckConfig::CargoCommand { command, all_targets, all_features, extra_args } => {
219 let mut cmd = Command::new(cargo_binary()); 192 let mut cmd = Command::new(ra_toolchain::cargo());
220 cmd.arg(command); 193 cmd.arg(command);
221 cmd.args(&["--workspace", "--message-format=json", "--manifest-path"]); 194 cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
222 cmd.arg(self.workspace_root.join("Cargo.toml")); 195 .arg(self.workspace_root.join("Cargo.toml"));
223 if *all_targets { 196 if *all_targets {
224 cmd.arg("--all-targets"); 197 cmd.arg("--all-targets");
225 } 198 }
199 if *all_features {
200 cmd.arg("--all-features");
201 }
226 cmd.args(extra_args); 202 cmd.args(extra_args);
227 cmd 203 cmd
228 } 204 }
@@ -267,12 +243,6 @@ impl FlycheckThread {
267 } 243 }
268} 244}
269 245
270#[derive(Debug)]
271pub struct DiagnosticWithFixes {
272 diagnostic: Diagnostic,
273 fixes: Vec<CodeAction>,
274}
275
276enum CheckEvent { 246enum CheckEvent {
277 Begin, 247 Begin,
278 Msg(cargo_metadata::Message), 248 Msg(cargo_metadata::Message),
@@ -296,15 +266,11 @@ fn run_cargo(
296 // erroneus output. 266 // erroneus output.
297 let stdout = BufReader::new(child.stdout.take().unwrap()); 267 let stdout = BufReader::new(child.stdout.take().unwrap());
298 let mut read_at_least_one_message = false; 268 let mut read_at_least_one_message = false;
299 269 for message in cargo_metadata::Message::parse_stream(stdout) {
300 for line in stdout.lines() {
301 let line = line?;
302
303 let message = serde_json::from_str::<cargo_metadata::Message>(&line);
304 let message = match message { 270 let message = match message {
305 Ok(message) => message, 271 Ok(message) => message,
306 Err(err) => { 272 Err(err) => {
307 log::error!("Invalid json from cargo check, ignoring ({}): {:?} ", err, line); 273 log::error!("Invalid json from cargo check, ignoring ({})", err);
308 continue; 274 continue;
309 } 275 }
310 }; 276 };
@@ -334,7 +300,3 @@ fn run_cargo(
334 300
335 Ok(()) 301 Ok(())
336} 302}
337
338fn cargo_binary() -> String {
339 env::var("CARGO").unwrap_or_else(|_| "cargo".to_string())
340}
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs
index 1a30b2b3a..f910ded9d 100644
--- a/crates/ra_fmt/src/lib.rs
+++ b/crates/ra_fmt/src/lib.rs
@@ -42,7 +42,6 @@ pub fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr {
42} 42}
43 43
44pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> { 44pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
45 let block = block.block()?;
46 let has_anything_else = |thing: &SyntaxNode| -> bool { 45 let has_anything_else = |thing: &SyntaxNode| -> bool {
47 let mut non_trivial_children = 46 let mut non_trivial_children =
48 block.syntax().children_with_tokens().filter(|it| match it.kind() { 47 block.syntax().children_with_tokens().filter(|it| match it.kind() {
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index af59aa1b6..840cfdfc8 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -19,11 +19,14 @@ use hir_def::{
19use hir_expand::{ 19use hir_expand::{
20 diagnostics::DiagnosticSink, 20 diagnostics::DiagnosticSink,
21 name::{name, AsName}, 21 name::{name, AsName},
22 MacroDefId, 22 MacroDefId, MacroDefKind,
23}; 23};
24use hir_ty::{ 24use hir_ty::{
25 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy, 25 autoderef,
26 Canonical, InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor, 26 display::{HirDisplayError, HirFormatter},
27 expr::ExprValidator,
28 method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty,
29 TyDefId, TypeCtor,
27}; 30};
28use ra_db::{CrateId, CrateName, Edition, FileId}; 31use ra_db::{CrateId, CrateName, Edition, FileId};
29use ra_prof::profile; 32use ra_prof::profile;
@@ -145,6 +148,26 @@ impl ModuleDef {
145 ModuleDef::BuiltinType(_) => None, 148 ModuleDef::BuiltinType(_) => None,
146 } 149 }
147 } 150 }
151
152 pub fn definition_visibility(&self, db: &dyn HirDatabase) -> Option<Visibility> {
153 let module = match self {
154 ModuleDef::Module(it) => it.parent(db)?,
155 ModuleDef::Function(it) => return Some(it.visibility(db)),
156 ModuleDef::Adt(it) => it.module(db),
157 ModuleDef::EnumVariant(it) => {
158 let parent = it.parent_enum(db);
159 let module = it.module(db);
160 return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent)));
161 }
162 ModuleDef::Const(it) => return Some(it.visibility(db)),
163 ModuleDef::Static(it) => it.module(db),
164 ModuleDef::Trait(it) => it.module(db),
165 ModuleDef::TypeAlias(it) => return Some(it.visibility(db)),
166 ModuleDef::BuiltinType(_) => return None,
167 };
168
169 module.visibility_of(db, self)
170 }
148} 171}
149 172
150pub use hir_def::{ 173pub use hir_def::{
@@ -675,6 +698,10 @@ impl Static {
675 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 698 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
676 db.static_data(self.id).name.clone() 699 db.static_data(self.id).name.clone()
677 } 700 }
701
702 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
703 db.static_data(self.id).mutable
704 }
678} 705}
679 706
680#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 707#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -762,13 +789,12 @@ impl MacroDef {
762 789
763 /// Indicate it is a proc-macro 790 /// Indicate it is a proc-macro
764 pub fn is_proc_macro(&self) -> bool { 791 pub fn is_proc_macro(&self) -> bool {
765 match self.id.kind { 792 matches!(self.id.kind, MacroDefKind::CustomDerive(_))
766 hir_expand::MacroDefKind::Declarative => false, 793 }
767 hir_expand::MacroDefKind::BuiltIn(_) => false, 794
768 hir_expand::MacroDefKind::BuiltInDerive(_) => false, 795 /// Indicate it is a derive macro
769 hir_expand::MacroDefKind::BuiltInEager(_) => false, 796 pub fn is_derive_macro(&self) -> bool {
770 hir_expand::MacroDefKind::CustomDerive(_) => true, 797 matches!(self.id.kind, MacroDefKind::CustomDerive(_) | MacroDefKind::BuiltInDerive(_))
771 }
772 } 798 }
773} 799}
774 800
@@ -963,6 +989,17 @@ impl TypeParam {
963 ty: InEnvironment { value: ty, environment }, 989 ty: InEnvironment { value: ty, environment },
964 } 990 }
965 } 991 }
992
993 pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
994 let params = db.generic_defaults(self.id.parent);
995 let local_idx = hir_ty::param_idx(db, self.id)?;
996 let resolver = self.id.parent.resolver(db.upcast());
997 let environment = TraitEnvironment::lower(db, &resolver);
998 params.get(local_idx).cloned().map(|ty| Type {
999 krate: self.id.parent.module(db.upcast()).krate,
1000 ty: InEnvironment { value: ty, environment },
1001 })
1002 }
966} 1003}
967 1004
968// FIXME: rename from `ImplDef` to `Impl` 1005// FIXME: rename from `ImplDef` to `Impl`
@@ -1212,7 +1249,7 @@ impl Type {
1212 1249
1213 // This would be nicer if it just returned an iterator, but that runs into 1250 // This would be nicer if it just returned an iterator, but that runs into
1214 // lifetime problems, because we need to borrow temp `CrateImplDefs`. 1251 // lifetime problems, because we need to borrow temp `CrateImplDefs`.
1215 pub fn iterate_impl_items<T>( 1252 pub fn iterate_assoc_items<T>(
1216 self, 1253 self,
1217 db: &dyn HirDatabase, 1254 db: &dyn HirDatabase,
1218 krate: Crate, 1255 krate: Crate,
@@ -1320,7 +1357,7 @@ impl Type {
1320} 1357}
1321 1358
1322impl HirDisplay for Type { 1359impl HirDisplay for Type {
1323 fn hir_fmt(&self, f: &mut HirFormatter) -> std::fmt::Result { 1360 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1324 self.ty.value.hir_fmt(f) 1361 self.ty.value.hir_fmt(f)
1325 } 1362 }
1326} 1363}
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 515e5eb17..7c1f79f27 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -23,7 +23,7 @@ use crate::{
23 db::HirDatabase, 23 db::HirDatabase,
24 diagnostics::Diagnostic, 24 diagnostics::Diagnostic,
25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
26 source_analyzer::{resolve_hir_path, SourceAnalyzer}, 26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer},
27 AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, 27 AssocItem, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef,
28 Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, 28 Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
29}; 29};
@@ -451,6 +451,23 @@ impl<'a, DB: HirDatabase> SemanticsScope<'a, DB> {
451 pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> { 451 pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> {
452 resolve_hir_path(self.db, &self.resolver, path) 452 resolve_hir_path(self.db, &self.resolver, path)
453 } 453 }
454
455 /// Resolves a path where we know it is a qualifier of another path.
456 ///
457 /// For example, if we have:
458 /// ```
459 /// mod my {
460 /// pub mod foo {
461 /// struct Bar;
462 /// }
463 ///
464 /// pub fn foo() {}
465 /// }
466 /// ```
467 /// then we know that `foo` in `my::foo::Bar` refers to the module, not the function.
468 pub fn resolve_hir_path_qualifier(&self, path: &Path) -> Option<PathResolution> {
469 resolve_hir_path_qualifier(self.db, &self.resolver, path)
470 }
454} 471}
455 472
456// FIXME: Change `HasSource` trait to work with `Semantics` and remove this? 473// FIXME: Change `HasSource` trait to work with `Semantics` and remove this?
diff --git a/crates/ra_hir/src/semantics/source_to_def.rs b/crates/ra_hir/src/semantics/source_to_def.rs
index 6f3b5b2da..8af64fdc1 100644
--- a/crates/ra_hir/src/semantics/source_to_def.rs
+++ b/crates/ra_hir/src/semantics/source_to_def.rs
@@ -151,7 +151,7 @@ impl SourceToDefCtx<'_, '_> {
151 let krate = self.file_to_def(file_id)?.krate; 151 let krate = self.file_to_def(file_id)?.krate;
152 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); 152 let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value);
153 let ast_id = Some(AstId::new(src.file_id, file_ast_id)); 153 let ast_id = Some(AstId::new(src.file_id, file_ast_id));
154 Some(MacroDefId { krate: Some(krate), ast_id, kind }) 154 Some(MacroDefId { krate: Some(krate), ast_id, kind, local_inner: false })
155 } 155 }
156 156
157 pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { 157 pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index c63d1b847..4b509f07c 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -226,6 +226,17 @@ impl SourceAnalyzer {
226 // This must be a normal source file rather than macro file. 226 // This must be a normal source file rather than macro file.
227 let hir_path = 227 let hir_path =
228 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?; 228 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?;
229
230 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we
231 // trying to resolve foo::bar.
232 if let Some(outer_path) = path.syntax().parent().and_then(ast::Path::cast) {
233 if let Some(qualifier) = outer_path.qualifier() {
234 if path == &qualifier {
235 return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
236 }
237 }
238 }
239
229 resolve_hir_path(db, &self.resolver, &hir_path) 240 resolve_hir_path(db, &self.resolver, &hir_path)
230 } 241 }
231 242
@@ -404,6 +415,7 @@ pub(crate) fn resolve_hir_path(
404 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), 415 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
405 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), 416 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
406 }); 417 });
418
407 let body_owner = resolver.body_owner(); 419 let body_owner = resolver.body_owner();
408 let values = 420 let values =
409 resolver.resolve_path_in_value_ns_fully(db.upcast(), path.mod_path()).and_then(|val| { 421 resolver.resolve_path_in_value_ns_fully(db.upcast(), path.mod_path()).and_then(|val| {
@@ -417,6 +429,7 @@ pub(crate) fn resolve_hir_path(
417 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), 429 ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
418 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), 430 ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
419 ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), 431 ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
432 ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
420 }; 433 };
421 Some(res) 434 Some(res)
422 }); 435 });
@@ -425,9 +438,48 @@ pub(crate) fn resolve_hir_path(
425 .resolve_module_path_in_items(db.upcast(), path.mod_path()) 438 .resolve_module_path_in_items(db.upcast(), path.mod_path())
426 .take_types() 439 .take_types()
427 .map(|it| PathResolution::Def(it.into())); 440 .map(|it| PathResolution::Def(it.into()));
441
428 types.or(values).or(items).or_else(|| { 442 types.or(values).or(items).or_else(|| {
429 resolver 443 resolver
430 .resolve_path_as_macro(db.upcast(), path.mod_path()) 444 .resolve_path_as_macro(db.upcast(), path.mod_path())
431 .map(|def| PathResolution::Macro(def.into())) 445 .map(|def| PathResolution::Macro(def.into()))
432 }) 446 })
433} 447}
448
449/// Resolves a path where we know it is a qualifier of another path.
450///
451/// For example, if we have:
452/// ```
453/// mod my {
454/// pub mod foo {
455/// struct Bar;
456/// }
457///
458/// pub fn foo() {}
459/// }
460/// ```
461/// then we know that `foo` in `my::foo::Bar` refers to the module, not the function.
462pub(crate) fn resolve_hir_path_qualifier(
463 db: &dyn HirDatabase,
464 resolver: &Resolver,
465 path: &crate::Path,
466) -> Option<PathResolution> {
467 let items = resolver
468 .resolve_module_path_in_items(db.upcast(), path.mod_path())
469 .take_types()
470 .map(|it| PathResolution::Def(it.into()));
471
472 if items.is_some() {
473 return items;
474 }
475
476 resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty {
477 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
478 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
479 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()),
480 TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
481 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
482 TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
483 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
484 })
485}
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 8eef51828..2bc34d449 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -117,7 +117,14 @@ fn lower_enum(
117 ast: &InFile<ast::EnumDef>, 117 ast: &InFile<ast::EnumDef>,
118 module_id: ModuleId, 118 module_id: ModuleId,
119) { 119) {
120 for var in ast.value.variant_list().into_iter().flat_map(|it| it.variants()) { 120 let expander = CfgExpander::new(db, ast.file_id, module_id.krate);
121 let variants = ast
122 .value
123 .variant_list()
124 .into_iter()
125 .flat_map(|it| it.variants())
126 .filter(|var| expander.is_cfg_enabled(var));
127 for var in variants {
121 trace.alloc( 128 trace.alloc(
122 || var.clone(), 129 || var.clone(),
123 || EnumVariantData { 130 || EnumVariantData {
@@ -209,8 +216,7 @@ fn lower_struct(
209 match &ast.value { 216 match &ast.value {
210 ast::StructKind::Tuple(fl) => { 217 ast::StructKind::Tuple(fl) => {
211 for (i, fd) in fl.fields().enumerate() { 218 for (i, fd) in fl.fields().enumerate() {
212 let attrs = expander.parse_attrs(&fd); 219 if !expander.is_cfg_enabled(&fd) {
213 if !expander.is_cfg_enabled(&attrs) {
214 continue; 220 continue;
215 } 221 }
216 222
@@ -227,8 +233,7 @@ fn lower_struct(
227 } 233 }
228 ast::StructKind::Record(fl) => { 234 ast::StructKind::Record(fl) => {
229 for fd in fl.fields() { 235 for fd in fl.fields() {
230 let attrs = expander.parse_attrs(&fd); 236 if !expander.is_cfg_enabled(&fd) {
231 if !expander.is_cfg_enabled(&attrs) {
232 continue; 237 continue;
233 } 238 }
234 239
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 5a86af8ba..576cd0c65 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -140,6 +140,7 @@ impl Attr {
140 } 140 }
141} 141}
142 142
143#[derive(Debug, Clone, Copy)]
143pub struct AttrQuery<'a> { 144pub struct AttrQuery<'a> {
144 attrs: &'a Attrs, 145 attrs: &'a Attrs,
145 key: &'static str, 146 key: &'static str,
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 4edaad960..f5a7305dc 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -60,7 +60,8 @@ impl CfgExpander {
60 Attrs::new(owner, &self.hygiene) 60 Attrs::new(owner, &self.hygiene)
61 } 61 }
62 62
63 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { 63 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
64 let attrs = self.parse_attrs(owner);
64 attrs.is_cfg_enabled(&self.cfg_options) 65 attrs.is_cfg_enabled(&self.cfg_options)
65 } 66 }
66} 67}
@@ -141,12 +142,8 @@ impl Expander {
141 InFile { file_id: self.current_file_id, value } 142 InFile { file_id: self.current_file_id, value }
142 } 143 }
143 144
144 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { 145 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
145 self.cfg_expander.parse_attrs(owner) 146 self.cfg_expander.is_cfg_enabled(owner)
146 }
147
148 pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
149 self.cfg_expander.is_cfg_enabled(attrs)
150 } 147 }
151 148
152 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 149 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index e9dd65b0a..e08d62dd6 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -15,7 +15,7 @@ use ra_syntax::{
15 }, 15 },
16 AstNode, AstPtr, 16 AstNode, AstPtr,
17}; 17};
18use test_utils::tested_by; 18use test_utils::mark;
19 19
20use crate::{ 20use crate::{
21 adt::StructKind, 21 adt::StructKind,
@@ -60,13 +60,10 @@ pub(super) fn lower(
60 params: Option<ast::ParamList>, 60 params: Option<ast::ParamList>,
61 body: Option<ast::Expr>, 61 body: Option<ast::Expr>,
62) -> (Body, BodySourceMap) { 62) -> (Body, BodySourceMap) {
63 let ctx = LowerCtx::new(db, expander.current_file_id.clone());
64
65 ExprCollector { 63 ExprCollector {
66 db, 64 db,
67 def, 65 def,
68 expander, 66 expander,
69 ctx,
70 source_map: BodySourceMap::default(), 67 source_map: BodySourceMap::default(),
71 body: Body { 68 body: Body {
72 exprs: Arena::default(), 69 exprs: Arena::default(),
@@ -83,7 +80,6 @@ struct ExprCollector<'a> {
83 db: &'a dyn DefDatabase, 80 db: &'a dyn DefDatabase,
84 def: DefWithBodyId, 81 def: DefWithBodyId,
85 expander: Expander, 82 expander: Expander,
86 ctx: LowerCtx,
87 body: Body, 83 body: Body,
88 source_map: BodySourceMap, 84 source_map: BodySourceMap,
89} 85}
@@ -122,6 +118,10 @@ impl ExprCollector<'_> {
122 (self.body, self.source_map) 118 (self.body, self.source_map)
123 } 119 }
124 120
121 fn ctx(&self) -> LowerCtx {
122 LowerCtx::new(self.db, self.expander.current_file_id)
123 }
124
125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
126 let src = self.expander.to_source(ptr); 126 let src = self.expander.to_source(ptr);
127 let id = self.make_expr(expr, Ok(src.clone())); 127 let id = self.make_expr(expr, Ok(src.clone()));
@@ -162,8 +162,7 @@ impl ExprCollector<'_> {
162 162
163 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId { 163 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
164 let syntax_ptr = AstPtr::new(&expr); 164 let syntax_ptr = AstPtr::new(&expr);
165 let attrs = self.expander.parse_attrs(&expr); 165 if !self.expander.is_cfg_enabled(&expr) {
166 if !self.expander.is_cfg_enabled(&attrs) {
167 return self.missing_expr(); 166 return self.missing_expr();
168 } 167 }
169 match expr { 168 match expr {
@@ -203,6 +202,16 @@ impl ExprCollector<'_> {
203 202
204 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr) 203 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
205 } 204 }
205 ast::Expr::EffectExpr(e) => match e.effect() {
206 ast::Effect::Try(_) => {
207 let body = self.collect_block_opt(e.block_expr());
208 self.alloc_expr(Expr::TryBlock { body }, syntax_ptr)
209 }
210 // FIXME: we need to record these effects somewhere...
211 ast::Effect::Async(_) | ast::Effect::Label(_) | ast::Effect::Unsafe(_) => {
212 self.collect_block_opt(e.block_expr())
213 }
214 },
206 ast::Expr::BlockExpr(e) => self.collect_block(e), 215 ast::Expr::BlockExpr(e) => self.collect_block(e),
207 ast::Expr::LoopExpr(e) => { 216 ast::Expr::LoopExpr(e) => {
208 let body = self.collect_block_opt(e.loop_body()); 217 let body = self.collect_block_opt(e.loop_body());
@@ -217,7 +226,7 @@ impl ExprCollector<'_> {
217 None => self.collect_expr_opt(condition.expr()), 226 None => self.collect_expr_opt(condition.expr()),
218 // if let -- desugar to match 227 // if let -- desugar to match
219 Some(pat) => { 228 Some(pat) => {
220 tested_by!(infer_resolve_while_let); 229 mark::hit!(infer_resolve_while_let);
221 let pat = self.collect_pat(pat); 230 let pat = self.collect_pat(pat);
222 let match_expr = self.collect_expr_opt(condition.expr()); 231 let match_expr = self.collect_expr_opt(condition.expr());
223 let placeholder_pat = self.missing_pat(); 232 let placeholder_pat = self.missing_pat();
@@ -259,7 +268,7 @@ impl ExprCollector<'_> {
259 }; 268 };
260 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 269 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
261 let generic_args = 270 let generic_args =
262 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it)); 271 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
263 self.alloc_expr( 272 self.alloc_expr(
264 Expr::MethodCall { receiver, method_name, args, generic_args }, 273 Expr::MethodCall { receiver, method_name, args, generic_args },
265 syntax_ptr, 274 syntax_ptr,
@@ -319,8 +328,7 @@ impl ExprCollector<'_> {
319 .fields() 328 .fields()
320 .inspect(|field| field_ptrs.push(AstPtr::new(field))) 329 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
321 .filter_map(|field| { 330 .filter_map(|field| {
322 let attrs = self.expander.parse_attrs(&field); 331 if !self.expander.is_cfg_enabled(&field) {
323 if !self.expander.is_cfg_enabled(&attrs) {
324 return None; 332 return None;
325 } 333 }
326 let name = field.field_name()?.as_name(); 334 let name = field.field_name()?.as_name();
@@ -365,7 +373,7 @@ impl ExprCollector<'_> {
365 } 373 }
366 ast::Expr::CastExpr(e) => { 374 ast::Expr::CastExpr(e) => {
367 let expr = self.collect_expr_opt(e.expr()); 375 let expr = self.collect_expr_opt(e.expr());
368 let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref()); 376 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
369 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 377 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
370 } 378 }
371 ast::Expr::RefExpr(e) => { 379 ast::Expr::RefExpr(e) => {
@@ -388,7 +396,7 @@ impl ExprCollector<'_> {
388 for param in pl.params() { 396 for param in pl.params() {
389 let pat = self.collect_pat_opt(param.pat()); 397 let pat = self.collect_pat_opt(param.pat());
390 let type_ref = 398 let type_ref =
391 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); 399 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
392 args.push(pat); 400 args.push(pat);
393 arg_types.push(type_ref); 401 arg_types.push(type_ref);
394 } 402 }
@@ -396,7 +404,7 @@ impl ExprCollector<'_> {
396 let ret_type = e 404 let ret_type = e
397 .ret_type() 405 .ret_type()
398 .and_then(|r| r.type_ref()) 406 .and_then(|r| r.type_ref())
399 .map(|it| TypeRef::from_ast(&self.ctx, it)); 407 .map(|it| TypeRef::from_ast(&self.ctx(), it));
400 let body = self.collect_expr_opt(e.body()); 408 let body = self.collect_expr_opt(e.body());
401 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 409 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
402 } 410 }
@@ -456,6 +464,7 @@ impl ExprCollector<'_> {
456 krate: Some(self.expander.module.krate), 464 krate: Some(self.expander.module.krate),
457 ast_id: Some(self.expander.ast_id(&e)), 465 ast_id: Some(self.expander.ast_id(&e)),
458 kind: MacroDefKind::Declarative, 466 kind: MacroDefKind::Declarative,
467 local_inner: false,
459 }; 468 };
460 self.body.item_scope.define_legacy_macro(name, mac); 469 self.body.item_scope.define_legacy_macro(name, mac);
461 470
@@ -490,19 +499,16 @@ impl ExprCollector<'_> {
490 } 499 }
491 } 500 }
492 501
493 fn collect_block(&mut self, expr: ast::BlockExpr) -> ExprId { 502 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
494 let syntax_node_ptr = AstPtr::new(&expr.clone().into()); 503 let syntax_node_ptr = AstPtr::new(&block.clone().into());
495 let block = match expr.block() {
496 Some(block) => block,
497 None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
498 };
499 self.collect_block_items(&block); 504 self.collect_block_items(&block);
500 let statements = block 505 let statements = block
501 .statements() 506 .statements()
502 .map(|s| match s { 507 .map(|s| match s {
503 ast::Stmt::LetStmt(stmt) => { 508 ast::Stmt::LetStmt(stmt) => {
504 let pat = self.collect_pat_opt(stmt.pat()); 509 let pat = self.collect_pat_opt(stmt.pat());
505 let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); 510 let type_ref =
511 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
506 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 512 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
507 Statement::Let { pat, type_ref, initializer } 513 Statement::Let { pat, type_ref, initializer }
508 } 514 }
@@ -513,7 +519,7 @@ impl ExprCollector<'_> {
513 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 519 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
514 } 520 }
515 521
516 fn collect_block_items(&mut self, block: &ast::Block) { 522 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
517 let container = ContainerId::DefWithBodyId(self.def); 523 let container = ContainerId::DefWithBodyId(self.def);
518 for item in block.items() { 524 for item in block.items() {
519 let (def, name): (ModuleDefId, Option<ast::Name>) = match item { 525 let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
@@ -568,9 +574,16 @@ impl ExprCollector<'_> {
568 self.body.item_scope.define_def(def); 574 self.body.item_scope.define_def(def);
569 if let Some(name) = name { 575 if let Some(name) = name {
570 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly 576 let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
571 self.body 577 let has_constructor = match def {
572 .item_scope 578 ModuleDefId::AdtId(AdtId::StructId(s)) => {
573 .push_res(name.as_name(), crate::per_ns::PerNs::from_def(def, vis)); 579 self.db.struct_data(s).variant_data.kind() != StructKind::Record
580 }
581 _ => true,
582 };
583 self.body.item_scope.push_res(
584 name.as_name(),
585 crate::per_ns::PerNs::from_def(def, vis, has_constructor),
586 );
574 } 587 }
575 } 588 }
576 } 589 }
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 86f953c80..09e92b74e 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -174,7 +174,7 @@ mod tests {
174 use hir_expand::{name::AsName, InFile}; 174 use hir_expand::{name::AsName, InFile};
175 use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; 175 use ra_db::{fixture::WithFixture, FileId, SourceDatabase};
176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 176 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
177 use test_utils::{assert_eq_text, covers, extract_offset}; 177 use test_utils::{assert_eq_text, extract_offset, mark};
178 178
179 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId}; 179 use crate::{db::DefDatabase, test_db::TestDB, FunctionId, ModuleDefId};
180 180
@@ -388,7 +388,7 @@ mod tests {
388 388
389 #[test] 389 #[test]
390 fn while_let_desugaring() { 390 fn while_let_desugaring() {
391 covers!(infer_resolve_while_let); 391 mark::check!(infer_resolve_while_let);
392 do_check_local_name( 392 do_check_local_name(
393 r#" 393 r#"
394fn test() { 394fn test() {
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 7a2067e49..e2130d931 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -9,7 +9,7 @@ use hir_expand::{
9}; 9};
10use ra_prof::profile; 10use ra_prof::profile;
11use ra_syntax::ast::{ 11use ra_syntax::ast::{
12 self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, 12 self, AssocItem, AstNode, ModuleItemOwner, NameOwner, TypeAscriptionOwner, TypeBoundsOwner,
13 VisibilityOwner, 13 VisibilityOwner,
14}; 14};
15 15
@@ -150,51 +150,31 @@ pub struct TraitData {
150 150
151impl TraitData { 151impl TraitData {
152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> { 152 pub(crate) fn trait_data_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitData> {
153 let src = tr.lookup(db).source(db); 153 let tr_loc = tr.lookup(db);
154 let src = tr_loc.source(db);
154 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); 155 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
155 let auto = src.value.auto_token().is_some(); 156 let auto = src.value.auto_token().is_some();
156 let ast_id_map = db.ast_id_map(src.file_id); 157 let module_id = tr_loc.container.module(db);
157 158
158 let container = AssocContainerId::TraitId(tr); 159 let container = AssocContainerId::TraitId(tr);
159 let items = if let Some(item_list) = src.value.item_list() { 160 let mut items = Vec::new();
160 item_list 161
161 .impl_items() 162 if let Some(item_list) = src.value.item_list() {
162 .map(|item_node| match item_node { 163 let mut expander = Expander::new(db, tr_loc.ast_id.file_id, module_id);
163 ast::ImplItem::FnDef(it) => { 164 items.extend(collect_items(
164 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 165 db,
165 let def = FunctionLoc { 166 &mut expander,
166 container, 167 item_list.assoc_items(),
167 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 168 src.file_id,
168 } 169 container,
169 .intern(db) 170 ));
170 .into(); 171 items.extend(collect_items_in_macros(
171 (name, def) 172 db,
172 } 173 &mut expander,
173 ast::ImplItem::ConstDef(it) => { 174 &src.with_value(item_list),
174 let name = it.name().map_or_else(Name::missing, |it| it.as_name()); 175 container,
175 let def = ConstLoc { 176 ));
176 container, 177 }
177 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
178 }
179 .intern(db)
180 .into();
181 (name, def)
182 }
183 ast::ImplItem::TypeAliasDef(it) => {
184 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
185 let def = TypeAliasLoc {
186 container,
187 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
188 }
189 .intern(db)
190 .into();
191 (name, def)
192 }
193 })
194 .collect()
195 } else {
196 Vec::new()
197 };
198 Arc::new(TraitData { name, items, auto }) 178 Arc::new(TraitData { name, items, auto })
199 } 179 }
200 180
@@ -232,24 +212,22 @@ impl ImplData {
232 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type()); 212 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
233 let is_negative = src.value.excl_token().is_some(); 213 let is_negative = src.value.excl_token().is_some();
234 let module_id = impl_loc.container.module(db); 214 let module_id = impl_loc.container.module(db);
215 let container = AssocContainerId::ImplId(id);
235 216
236 let mut items = Vec::new(); 217 let mut items: Vec<AssocItemId> = Vec::new();
237 218
238 if let Some(item_list) = src.value.item_list() { 219 if let Some(item_list) = src.value.item_list() {
239 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id); 220 let mut expander = Expander::new(db, impl_loc.ast_id.file_id, module_id);
240 items.extend(collect_impl_items( 221 items.extend(
241 db, 222 collect_items(db, &mut expander, item_list.assoc_items(), src.file_id, container)
242 &mut expander, 223 .into_iter()
243 item_list.impl_items(), 224 .map(|(_, item)| item),
244 src.file_id, 225 );
245 id, 226 items.extend(
246 )); 227 collect_items_in_macros(db, &mut expander, &src.with_value(item_list), container)
247 items.extend(collect_impl_items_in_macros( 228 .into_iter()
248 db, 229 .map(|(_, item)| item),
249 &mut expander, 230 );
250 &src.with_value(item_list),
251 id,
252 ));
253 } 231 }
254 232
255 let res = ImplData { target_trait, target_type, items, is_negative }; 233 let res = ImplData { target_trait, target_type, items, is_negative };
@@ -273,11 +251,6 @@ impl ConstData {
273 Arc::new(ConstData::new(db, vis_default, node)) 251 Arc::new(ConstData::new(db, vis_default, node))
274 } 252 }
275 253
276 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<ConstData> {
277 let node = konst.lookup(db).source(db);
278 Arc::new(ConstData::new(db, RawVisibility::private(), node))
279 }
280
281 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>( 254 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(
282 db: &dyn DefDatabase, 255 db: &dyn DefDatabase,
283 vis_default: RawVisibility, 256 vis_default: RawVisibility,
@@ -292,49 +265,76 @@ impl ConstData {
292 } 265 }
293} 266}
294 267
295fn collect_impl_items_in_macros( 268#[derive(Debug, Clone, PartialEq, Eq)]
269pub struct StaticData {
270 pub name: Option<Name>,
271 pub type_ref: TypeRef,
272 pub visibility: RawVisibility,
273 pub mutable: bool,
274}
275
276impl StaticData {
277 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
278 let node = konst.lookup(db).source(db);
279 let ctx = LowerCtx::new(db, node.file_id);
280
281 let name = node.value.name().map(|n| n.as_name());
282 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
283 let mutable = node.value.mut_token().is_some();
284 let visibility = RawVisibility::from_ast_with_default(
285 db,
286 RawVisibility::private(),
287 node.map(|n| n.visibility()),
288 );
289
290 Arc::new(StaticData { name, type_ref, visibility, mutable })
291 }
292}
293
294fn collect_items_in_macros(
296 db: &dyn DefDatabase, 295 db: &dyn DefDatabase,
297 expander: &mut Expander, 296 expander: &mut Expander,
298 impl_def: &InFile<ast::ItemList>, 297 impl_def: &InFile<ast::ItemList>,
299 id: ImplId, 298 container: AssocContainerId,
300) -> Vec<AssocItemId> { 299) -> Vec<(Name, AssocItemId)> {
301 let mut res = Vec::new(); 300 let mut res = Vec::new();
302 301
303 // We set a limit to protect against infinite recursion 302 // We set a limit to protect against infinite recursion
304 let limit = 100; 303 let limit = 100;
305 304
306 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) { 305 for m in impl_def.value.syntax().children().filter_map(ast::MacroCall::cast) {
307 res.extend(collect_impl_items_in_macro(db, expander, m, id, limit)) 306 res.extend(collect_items_in_macro(db, expander, m, container, limit))
308 } 307 }
309 308
310 res 309 res
311} 310}
312 311
313fn collect_impl_items_in_macro( 312fn collect_items_in_macro(
314 db: &dyn DefDatabase, 313 db: &dyn DefDatabase,
315 expander: &mut Expander, 314 expander: &mut Expander,
316 m: ast::MacroCall, 315 m: ast::MacroCall,
317 id: ImplId, 316 container: AssocContainerId,
318 limit: usize, 317 limit: usize,
319) -> Vec<AssocItemId> { 318) -> Vec<(Name, AssocItemId)> {
320 if limit == 0 { 319 if limit == 0 {
321 return Vec::new(); 320 return Vec::new();
322 } 321 }
323 322
324 if let Some((mark, items)) = expander.enter_expand(db, None, m) { 323 if let Some((mark, items)) = expander.enter_expand(db, None, m) {
325 let items: InFile<ast::MacroItems> = expander.to_source(items); 324 let items: InFile<ast::MacroItems> = expander.to_source(items);
326 let mut res = collect_impl_items( 325 let mut res = collect_items(
327 db, 326 db,
328 expander, 327 expander,
329 items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), 328 items.value.items().filter_map(|it| AssocItem::cast(it.syntax().clone())),
330 items.file_id, 329 items.file_id,
331 id, 330 container,
332 ); 331 );
332
333 // Recursive collect macros 333 // Recursive collect macros
334 // Note that ast::ModuleItem do not include ast::MacroCall 334 // Note that ast::ModuleItem do not include ast::MacroCall
335 // We cannot use ModuleItemOwner::items here 335 // We cannot use ModuleItemOwner::items here
336 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { 336 for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
337 res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) 337 res.extend(collect_items_in_macro(db, expander, it, container, limit - 1))
338 } 338 }
339 expander.exit(db, mark); 339 expander.exit(db, mark);
340 res 340 res
@@ -343,44 +343,38 @@ fn collect_impl_items_in_macro(
343 } 343 }
344} 344}
345 345
346fn collect_impl_items( 346fn collect_items(
347 db: &dyn DefDatabase, 347 db: &dyn DefDatabase,
348 expander: &mut Expander, 348 expander: &mut Expander,
349 impl_items: impl Iterator<Item = ImplItem>, 349 assoc_items: impl Iterator<Item = AssocItem>,
350 file_id: crate::HirFileId, 350 file_id: crate::HirFileId,
351 id: ImplId, 351 container: AssocContainerId,
352) -> Vec<AssocItemId> { 352) -> Vec<(Name, AssocItemId)> {
353 let items = db.ast_id_map(file_id); 353 let items = db.ast_id_map(file_id);
354 354
355 impl_items 355 assoc_items
356 .filter_map(|item_node| match item_node { 356 .filter_map(|item_node| match item_node {
357 ast::ImplItem::FnDef(it) => { 357 ast::AssocItem::FnDef(it) => {
358 let attrs = expander.parse_attrs(&it); 358 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
359 if !expander.is_cfg_enabled(&attrs) { 359 if !expander.is_cfg_enabled(&it) {
360 return None; 360 return None;
361 } 361 }
362 let def = FunctionLoc { 362 let def = FunctionLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
363 container: AssocContainerId::ImplId(id), 363 .intern(db);
364 ast_id: AstId::new(file_id, items.ast_id(&it)), 364 Some((name, def.into()))
365 }
366 .intern(db);
367 Some(def.into())
368 } 365 }
369 ast::ImplItem::ConstDef(it) => { 366 ast::AssocItem::ConstDef(it) => {
370 let def = ConstLoc { 367 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
371 container: AssocContainerId::ImplId(id), 368 let def = ConstLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
372 ast_id: AstId::new(file_id, items.ast_id(&it)), 369 .intern(db);
373 } 370 Some((name, def.into()))
374 .intern(db);
375 Some(def.into())
376 } 371 }
377 ast::ImplItem::TypeAliasDef(it) => { 372 ast::AssocItem::TypeAliasDef(it) => {
378 let def = TypeAliasLoc { 373 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
379 container: AssocContainerId::ImplId(id), 374 let def =
380 ast_id: AstId::new(file_id, items.ast_id(&it)), 375 TypeAliasLoc { container, ast_id: AstId::new(file_id, items.ast_id(&it)) }
381 } 376 .intern(db);
382 .intern(db); 377 Some((name, def.into()))
383 Some(def.into())
384 } 378 }
385 }) 379 })
386 .collect() 380 .collect()
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 5dc7395f5..945a0025e 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -1,7 +1,7 @@
1//! Defines database & queries for name resolution. 1//! Defines database & queries for name resolution.
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_expand::{db::AstDatabase, HirFileId}; 4use hir_expand::{db::AstDatabase, name::Name, HirFileId};
5use ra_db::{salsa, CrateId, SourceDatabase, Upcast}; 5use ra_db::{salsa, CrateId, SourceDatabase, Upcast};
6use ra_prof::profile; 6use ra_prof::profile;
7use ra_syntax::SmolStr; 7use ra_syntax::SmolStr;
@@ -10,11 +10,15 @@ use crate::{
10 adt::{EnumData, StructData}, 10 adt::{EnumData, StructData},
11 attr::Attrs, 11 attr::Attrs,
12 body::{scope::ExprScopes, Body, BodySourceMap}, 12 body::{scope::ExprScopes, Body, BodySourceMap},
13 data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData}, 13 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData},
14 docs::Documentation, 14 docs::Documentation,
15 find_path,
15 generics::GenericParams, 16 generics::GenericParams,
17 item_scope::ItemInNs,
16 lang_item::{LangItemTarget, LangItems}, 18 lang_item::{LangItemTarget, LangItems},
17 nameres::{raw::RawItems, CrateDefMap}, 19 nameres::{raw::RawItems, CrateDefMap},
20 path::ModPath,
21 visibility::Visibility,
18 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, 22 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc,
19 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, 23 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId,
20 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, 24 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
@@ -77,8 +81,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
77 #[salsa::invoke(ConstData::const_data_query)] 81 #[salsa::invoke(ConstData::const_data_query)]
78 fn const_data(&self, konst: ConstId) -> Arc<ConstData>; 82 fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
79 83
80 #[salsa::invoke(ConstData::static_data_query)] 84 #[salsa::invoke(StaticData::static_data_query)]
81 fn static_data(&self, konst: StaticId) -> Arc<ConstData>; 85 fn static_data(&self, konst: StaticId) -> Arc<StaticData>;
82 86
83 #[salsa::invoke(Body::body_with_source_map_query)] 87 #[salsa::invoke(Body::body_with_source_map_query)]
84 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 88 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
@@ -108,6 +112,16 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
108 // Remove this query completely, in favor of `Attrs::docs` method 112 // Remove this query completely, in favor of `Attrs::docs` method
109 #[salsa::invoke(Documentation::documentation_query)] 113 #[salsa::invoke(Documentation::documentation_query)]
110 fn documentation(&self, def: AttrDefId) -> Option<Documentation>; 114 fn documentation(&self, def: AttrDefId) -> Option<Documentation>;
115
116 #[salsa::invoke(find_path::importable_locations_of_query)]
117 fn importable_locations_of(
118 &self,
119 item: ItemInNs,
120 krate: CrateId,
121 ) -> Arc<[(ModuleId, Name, Visibility)]>;
122
123 #[salsa::invoke(find_path::find_path_inner_query)]
124 fn find_path_inner(&self, item: ItemInNs, from: ModuleId, max_len: usize) -> Option<ModPath>;
111} 125}
112 126
113fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { 127fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> {
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index aad12e123..a0cdad529 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -101,6 +101,9 @@ pub enum Expr {
101 Try { 101 Try {
102 expr: ExprId, 102 expr: ExprId,
103 }, 103 },
104 TryBlock {
105 body: ExprId,
106 },
104 Cast { 107 Cast {
105 expr: ExprId, 108 expr: ExprId,
106 type_ref: TypeRef, 109 type_ref: TypeRef,
@@ -236,6 +239,7 @@ impl Expr {
236 f(*expr); 239 f(*expr);
237 } 240 }
238 } 241 }
242 Expr::TryBlock { body } => f(*body),
239 Expr::Loop { body } => f(*body), 243 Expr::Loop { body } => f(*body),
240 Expr::While { condition, body } => { 244 Expr::While { condition, body } => {
241 f(*condition); 245 f(*condition);
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs
index 70dcb03e6..4db798473 100644
--- a/crates/ra_hir_def/src/find_path.rs
+++ b/crates/ra_hir_def/src/find_path.rs
@@ -1,5 +1,11 @@
1//! An algorithm to find a path to refer to a certain item. 1//! An algorithm to find a path to refer to a certain item.
2 2
3use std::sync::Arc;
4
5use hir_expand::name::{known, AsName, Name};
6use ra_prof::profile;
7use test_utils::mark;
8
3use crate::{ 9use crate::{
4 db::DefDatabase, 10 db::DefDatabase,
5 item_scope::ItemInNs, 11 item_scope::ItemInNs,
@@ -7,25 +13,28 @@ use crate::{
7 visibility::Visibility, 13 visibility::Visibility,
8 CrateId, ModuleDefId, ModuleId, 14 CrateId, ModuleDefId, ModuleId,
9}; 15};
10use hir_expand::name::{known, AsName, Name}; 16
11use test_utils::tested_by; 17// FIXME: handle local items
18
19/// Find a path that can be used to refer to a certain item. This can depend on
20/// *from where* you're referring to the item, hence the `from` parameter.
21pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
22 let _p = profile("find_path");
23 db.find_path_inner(item, from, MAX_PATH_LEN)
24}
12 25
13const MAX_PATH_LEN: usize = 15; 26const MAX_PATH_LEN: usize = 15;
14 27
15impl ModPath { 28impl ModPath {
16 fn starts_with_std(&self) -> bool { 29 fn starts_with_std(&self) -> bool {
17 self.segments.first().filter(|&first_segment| first_segment == &known::std).is_some() 30 self.segments.first() == Some(&known::std)
18 } 31 }
19 32
20 // When std library is present, paths starting with `std::` 33 // When std library is present, paths starting with `std::`
21 // should be preferred over paths starting with `core::` and `alloc::` 34 // should be preferred over paths starting with `core::` and `alloc::`
22 fn can_start_with_std(&self) -> bool { 35 fn can_start_with_std(&self) -> bool {
23 self.segments 36 let first_segment = self.segments.first();
24 .first() 37 first_segment == Some(&known::alloc) || first_segment == Some(&known::core)
25 .filter(|&first_segment| {
26 first_segment == &known::alloc || first_segment == &known::core
27 })
28 .is_some()
29 } 38 }
30 39
31 fn len(&self) -> usize { 40 fn len(&self) -> usize {
@@ -40,15 +49,7 @@ impl ModPath {
40 } 49 }
41} 50}
42 51
43// FIXME: handle local items 52pub(crate) fn find_path_inner_query(
44
45/// Find a path that can be used to refer to a certain item. This can depend on
46/// *from where* you're referring to the item, hence the `from` parameter.
47pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
48 find_path_inner(db, item, from, MAX_PATH_LEN)
49}
50
51fn find_path_inner(
52 db: &dyn DefDatabase, 53 db: &dyn DefDatabase,
53 item: ItemInNs, 54 item: ItemInNs,
54 from: ModuleId, 55 from: ModuleId,
@@ -139,8 +140,7 @@ fn find_path_inner(
139 let mut best_path = None; 140 let mut best_path = None;
140 let mut best_path_len = max_len; 141 let mut best_path_len = max_len;
141 for (module_id, name) in importable_locations { 142 for (module_id, name) in importable_locations {
142 let mut path = match find_path_inner( 143 let mut path = match db.find_path_inner(
143 db,
144 ItemInNs::Types(ModuleDefId::ModuleId(module_id)), 144 ItemInNs::Types(ModuleDefId::ModuleId(module_id)),
145 from, 145 from,
146 best_path_len - 1, 146 best_path_len - 1,
@@ -163,17 +163,19 @@ fn find_path_inner(
163 163
164fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath { 164fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath {
165 if old_path.starts_with_std() && new_path.can_start_with_std() { 165 if old_path.starts_with_std() && new_path.can_start_with_std() {
166 tested_by!(prefer_std_paths);
167 if prefer_no_std { 166 if prefer_no_std {
167 mark::hit!(prefer_no_std_paths);
168 new_path 168 new_path
169 } else { 169 } else {
170 mark::hit!(prefer_std_paths);
170 old_path 171 old_path
171 } 172 }
172 } else if new_path.starts_with_std() && old_path.can_start_with_std() { 173 } else if new_path.starts_with_std() && old_path.can_start_with_std() {
173 tested_by!(prefer_std_paths);
174 if prefer_no_std { 174 if prefer_no_std {
175 mark::hit!(prefer_no_std_paths);
175 old_path 176 old_path
176 } else { 177 } else {
178 mark::hit!(prefer_std_paths);
177 new_path 179 new_path
178 } 180 }
179 } else if new_path.len() < old_path.len() { 181 } else if new_path.len() < old_path.len() {
@@ -198,7 +200,7 @@ fn find_importable_locations(
198 .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id)) 200 .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id))
199 { 201 {
200 result.extend( 202 result.extend(
201 importable_locations_in_crate(db, item, krate) 203 db.importable_locations_of(item, krate)
202 .iter() 204 .iter()
203 .filter(|(_, _, vis)| vis.is_visible_from(db, from)) 205 .filter(|(_, _, vis)| vis.is_visible_from(db, from))
204 .map(|(m, n, _)| (*m, n.clone())), 206 .map(|(m, n, _)| (*m, n.clone())),
@@ -213,11 +215,12 @@ fn find_importable_locations(
213/// 215///
214/// Note that the crate doesn't need to be the one in which the item is defined; 216/// Note that the crate doesn't need to be the one in which the item is defined;
215/// it might be re-exported in other crates. 217/// it might be re-exported in other crates.
216fn importable_locations_in_crate( 218pub(crate) fn importable_locations_of_query(
217 db: &dyn DefDatabase, 219 db: &dyn DefDatabase,
218 item: ItemInNs, 220 item: ItemInNs,
219 krate: CrateId, 221 krate: CrateId,
220) -> Vec<(ModuleId, Name, Visibility)> { 222) -> Arc<[(ModuleId, Name, Visibility)]> {
223 let _p = profile("importable_locations_of_query");
221 let def_map = db.crate_def_map(krate); 224 let def_map = db.crate_def_map(krate);
222 let mut result = Vec::new(); 225 let mut result = Vec::new();
223 for (local_id, data) in def_map.modules.iter() { 226 for (local_id, data) in def_map.modules.iter() {
@@ -243,17 +246,20 @@ fn importable_locations_in_crate(
243 result.push((ModuleId { krate, local_id }, name.clone(), vis)); 246 result.push((ModuleId { krate, local_id }, name.clone(), vis));
244 } 247 }
245 } 248 }
246 result 249
250 Arc::from(result)
247} 251}
248 252
249#[cfg(test)] 253#[cfg(test)]
250mod tests { 254mod tests {
251 use super::*;
252 use crate::test_db::TestDB;
253 use hir_expand::hygiene::Hygiene; 255 use hir_expand::hygiene::Hygiene;
254 use ra_db::fixture::WithFixture; 256 use ra_db::fixture::WithFixture;
255 use ra_syntax::ast::AstNode; 257 use ra_syntax::ast::AstNode;
256 use test_utils::covers; 258 use test_utils::mark;
259
260 use crate::test_db::TestDB;
261
262 use super::*;
257 263
258 /// `code` needs to contain a cursor marker; checks that `find_path` for the 264 /// `code` needs to contain a cursor marker; checks that `find_path` for the
259 /// item the `path` refers to returns that same path when called from the 265 /// item the `path` refers to returns that same path when called from the
@@ -508,7 +514,7 @@ mod tests {
508 514
509 #[test] 515 #[test]
510 fn prefer_std_paths_over_alloc() { 516 fn prefer_std_paths_over_alloc() {
511 covers!(prefer_std_paths); 517 mark::check!(prefer_std_paths);
512 let code = r#" 518 let code = r#"
513 //- /main.rs crate:main deps:alloc,std 519 //- /main.rs crate:main deps:alloc,std
514 <|> 520 <|>
@@ -527,51 +533,50 @@ mod tests {
527 } 533 }
528 534
529 #[test] 535 #[test]
530 fn prefer_alloc_paths_over_std() { 536 fn prefer_core_paths_over_std() {
531 covers!(prefer_std_paths); 537 mark::check!(prefer_no_std_paths);
532 let code = r#" 538 let code = r#"
533 //- /main.rs crate:main deps:alloc,std 539 //- /main.rs crate:main deps:core,std
534 #![no_std] 540 #![no_std]
535 541
536 <|> 542 <|>
537 543
538 //- /std.rs crate:std deps:alloc 544 //- /std.rs crate:std deps:core
539 545
540 pub mod sync { 546 pub mod fmt {
541 pub use alloc::sync::Arc; 547 pub use core::fmt::Error;
542 } 548 }
543 549
544 //- /zzz.rs crate:alloc 550 //- /zzz.rs crate:core
545 551
546 pub mod sync { 552 pub mod fmt {
547 pub struct Arc; 553 pub struct Error;
548 } 554 }
549 "#; 555 "#;
550 check_found_path(code, "alloc::sync::Arc"); 556 check_found_path(code, "core::fmt::Error");
551 } 557 }
552 558
553 #[test] 559 #[test]
554 fn prefer_core_paths_over_std() { 560 fn prefer_alloc_paths_over_std() {
555 covers!(prefer_std_paths);
556 let code = r#" 561 let code = r#"
557 //- /main.rs crate:main deps:core,std 562 //- /main.rs crate:main deps:alloc,std
558 #![no_std] 563 #![no_std]
559 564
560 <|> 565 <|>
561 566
562 //- /std.rs crate:std deps:core 567 //- /std.rs crate:std deps:alloc
563 568
564 pub mod fmt { 569 pub mod sync {
565 pub use core::fmt::Error; 570 pub use alloc::sync::Arc;
566 } 571 }
567 572
568 //- /zzz.rs crate:core 573 //- /zzz.rs crate:alloc
569 574
570 pub mod fmt { 575 pub mod sync {
571 pub struct Error; 576 pub struct Arc;
572 } 577 }
573 "#; 578 "#;
574 check_found_path(code, "core::fmt::Error"); 579 check_found_path(code, "alloc::sync::Arc");
575 } 580 }
576 581
577 #[test] 582 #[test]
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
index 259b9ff03..fc15948ad 100644
--- a/crates/ra_hir_def/src/item_scope.rs
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -151,13 +151,20 @@ impl ItemScope {
151} 151}
152 152
153impl PerNs { 153impl PerNs {
154 pub(crate) fn from_def(def: ModuleDefId, v: Visibility) -> PerNs { 154 pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs {
155 match def { 155 match def {
156 ModuleDefId::ModuleId(_) => PerNs::types(def, v), 156 ModuleDefId::ModuleId(_) => PerNs::types(def, v),
157 ModuleDefId::FunctionId(_) => PerNs::values(def, v), 157 ModuleDefId::FunctionId(_) => PerNs::values(def, v),
158 ModuleDefId::AdtId(adt) => match adt { 158 ModuleDefId::AdtId(adt) => match adt {
159 AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def, v), 159 AdtId::UnionId(_) => PerNs::types(def, v),
160 AdtId::EnumId(_) => PerNs::types(def, v), 160 AdtId::EnumId(_) => PerNs::types(def, v),
161 AdtId::StructId(_) => {
162 if has_constructor {
163 PerNs::both(def, def, v)
164 } else {
165 PerNs::types(def, v)
166 }
167 }
161 }, 168 },
162 ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), 169 ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v),
163 ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), 170 ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v),
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 518772e8a..5325a2760 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -46,8 +46,6 @@ pub mod find_path;
46 46
47#[cfg(test)] 47#[cfg(test)]
48mod test_db; 48mod test_db;
49#[cfg(test)]
50mod marks;
51 49
52use std::hash::Hash; 50use std::hash::Hash;
53 51
diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs
deleted file mode 100644
index daa49d5f1..000000000
--- a/crates/ra_hir_def/src/marks.rs
+++ /dev/null
@@ -1,17 +0,0 @@
1//! See test_utils/src/marks.rs
2
3test_utils::marks!(
4 bogus_paths
5 name_res_works_for_broken_modules
6 can_import_enum_variant
7 glob_enum
8 glob_enum_group
9 glob_across_crates
10 std_prelude
11 macro_rules_from_other_crates_are_visible_with_macro_use
12 prelude_is_macro_use
13 macro_dollar_crate_self
14 macro_dollar_crate_other
15 infer_resolve_while_let
16 prefer_std_paths
17);
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 98c74fe25..353a31ad4 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -14,7 +14,7 @@ use ra_cfg::CfgOptions;
14use ra_db::{CrateId, FileId, ProcMacroId}; 14use ra_db::{CrateId, FileId, ProcMacroId};
15use ra_syntax::ast; 15use ra_syntax::ast;
16use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
17use test_utils::tested_by; 17use test_utils::mark;
18 18
19use crate::{ 19use crate::{
20 attr::Attrs, 20 attr::Attrs,
@@ -204,6 +204,7 @@ impl DefCollector<'_> {
204 ast_id: None, 204 ast_id: None,
205 krate: Some(krate), 205 krate: Some(krate),
206 kind: MacroDefKind::CustomDerive(expander), 206 kind: MacroDefKind::CustomDerive(expander),
207 local_inner: false,
207 }; 208 };
208 209
209 self.define_proc_macro(name.clone(), macro_id); 210 self.define_proc_macro(name.clone(), macro_id);
@@ -301,7 +302,7 @@ impl DefCollector<'_> {
301 ); 302 );
302 303
303 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() { 304 if let Some(ModuleDefId::ModuleId(m)) = res.take_types() {
304 tested_by!(macro_rules_from_other_crates_are_visible_with_macro_use); 305 mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
305 self.import_all_macros_exported(current_module_id, m.krate); 306 self.import_all_macros_exported(current_module_id, m.krate);
306 } 307 }
307 } 308 }
@@ -411,10 +412,10 @@ impl DefCollector<'_> {
411 match def.take_types() { 412 match def.take_types() {
412 Some(ModuleDefId::ModuleId(m)) => { 413 Some(ModuleDefId::ModuleId(m)) => {
413 if import.is_prelude { 414 if import.is_prelude {
414 tested_by!(std_prelude); 415 mark::hit!(std_prelude);
415 self.def_map.prelude = Some(m); 416 self.def_map.prelude = Some(m);
416 } else if m.krate != self.def_map.krate { 417 } else if m.krate != self.def_map.krate {
417 tested_by!(glob_across_crates); 418 mark::hit!(glob_across_crates);
418 // glob import from other crate => we can just import everything once 419 // glob import from other crate => we can just import everything once
419 let item_map = self.db.crate_def_map(m.krate); 420 let item_map = self.db.crate_def_map(m.krate);
420 let scope = &item_map[m.local_id].scope; 421 let scope = &item_map[m.local_id].scope;
@@ -460,7 +461,7 @@ impl DefCollector<'_> {
460 } 461 }
461 } 462 }
462 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { 463 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
463 tested_by!(glob_enum); 464 mark::hit!(glob_enum);
464 // glob import from enum => just import all the variants 465 // glob import from enum => just import all the variants
465 466
466 // XXX: urgh, so this works by accident! Here, we look at 467 // XXX: urgh, so this works by accident! Here, we look at
@@ -509,7 +510,7 @@ impl DefCollector<'_> {
509 510
510 self.update(module_id, &[(name, def)], vis); 511 self.update(module_id, &[(name, def)], vis);
511 } 512 }
512 None => tested_by!(bogus_paths), 513 None => mark::hit!(bogus_paths),
513 } 514 }
514 } 515 }
515 } 516 }
@@ -682,7 +683,7 @@ impl ModCollector<'_, '_> {
682 // Prelude module is always considered to be `#[macro_use]`. 683 // Prelude module is always considered to be `#[macro_use]`.
683 if let Some(prelude_module) = self.def_collector.def_map.prelude { 684 if let Some(prelude_module) = self.def_collector.def_map.prelude {
684 if prelude_module.krate != self.def_collector.def_map.krate { 685 if prelude_module.krate != self.def_collector.def_map.krate {
685 tested_by!(prelude_is_macro_use); 686 mark::hit!(prelude_is_macro_use);
686 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate); 687 self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
687 } 688 }
688 } 689 }
@@ -829,7 +830,7 @@ impl ModCollector<'_, '_> {
829 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; 830 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res };
830 let def: ModuleDefId = module.into(); 831 let def: ModuleDefId = module.into();
831 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 832 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
832 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis); 833 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis, false))], vis);
833 res 834 res
834 } 835 }
835 836
@@ -843,6 +844,8 @@ impl ModCollector<'_, '_> {
843 let name = def.name.clone(); 844 let name = def.name.clone();
844 let container = ContainerId::ModuleId(module); 845 let container = ContainerId::ModuleId(module);
845 let vis = &def.visibility; 846 let vis = &def.visibility;
847 let mut has_constructor = false;
848
846 let def: ModuleDefId = match def.kind { 849 let def: ModuleDefId = match def.kind {
847 raw::DefKind::Function(ast_id) => FunctionLoc { 850 raw::DefKind::Function(ast_id) => FunctionLoc {
848 container: container.into(), 851 container: container.into(),
@@ -850,7 +853,8 @@ impl ModCollector<'_, '_> {
850 } 853 }
851 .intern(self.def_collector.db) 854 .intern(self.def_collector.db)
852 .into(), 855 .into(),
853 raw::DefKind::Struct(ast_id) => { 856 raw::DefKind::Struct(ast_id, mode) => {
857 has_constructor = mode != raw::StructDefKind::Record;
854 StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } 858 StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
855 .intern(self.def_collector.db) 859 .intern(self.def_collector.db)
856 .into() 860 .into()
@@ -893,7 +897,11 @@ impl ModCollector<'_, '_> {
893 .def_map 897 .def_map
894 .resolve_visibility(self.def_collector.db, self.module_id, vis) 898 .resolve_visibility(self.def_collector.db, self.module_id, vis)
895 .unwrap_or(Visibility::Public); 899 .unwrap_or(Visibility::Public);
896 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis) 900 self.def_collector.update(
901 self.module_id,
902 &[(name, PerNs::from_def(def, vis, has_constructor))],
903 vis,
904 )
897 } 905 }
898 906
899 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { 907 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
@@ -941,6 +949,7 @@ impl ModCollector<'_, '_> {
941 ast_id: Some(ast_id.ast_id), 949 ast_id: Some(ast_id.ast_id),
942 krate: Some(self.def_collector.def_map.krate), 950 krate: Some(self.def_collector.def_map.krate),
943 kind: MacroDefKind::Declarative, 951 kind: MacroDefKind::Declarative,
952 local_inner: mac.local_inner,
944 }; 953 };
945 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); 954 self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export);
946 } 955 }
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 35a0a0c98..19692e70c 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -14,7 +14,7 @@ use std::iter::successors;
14 14
15use hir_expand::name::Name; 15use hir_expand::name::Name;
16use ra_db::Edition; 16use ra_db::Edition;
17use test_utils::tested_by; 17use test_utils::mark;
18 18
19use crate::{ 19use crate::{
20 db::DefDatabase, 20 db::DefDatabase,
@@ -108,7 +108,7 @@ impl CrateDefMap {
108 let mut curr_per_ns: PerNs = match path.kind { 108 let mut curr_per_ns: PerNs = match path.kind {
109 PathKind::DollarCrate(krate) => { 109 PathKind::DollarCrate(krate) => {
110 if krate == self.krate { 110 if krate == self.krate {
111 tested_by!(macro_dollar_crate_self); 111 mark::hit!(macro_dollar_crate_self);
112 PerNs::types( 112 PerNs::types(
113 ModuleId { krate: self.krate, local_id: self.root }.into(), 113 ModuleId { krate: self.krate, local_id: self.root }.into(),
114 Visibility::Public, 114 Visibility::Public,
@@ -116,7 +116,7 @@ impl CrateDefMap {
116 } else { 116 } else {
117 let def_map = db.crate_def_map(krate); 117 let def_map = db.crate_def_map(krate);
118 let module = ModuleId { krate, local_id: def_map.root }; 118 let module = ModuleId { krate, local_id: def_map.root };
119 tested_by!(macro_dollar_crate_other); 119 mark::hit!(macro_dollar_crate_other);
120 PerNs::types(module.into(), Visibility::Public) 120 PerNs::types(module.into(), Visibility::Public)
121 } 121 }
122 } 122 }
@@ -221,7 +221,7 @@ impl CrateDefMap {
221 } 221 }
222 ModuleDefId::AdtId(AdtId::EnumId(e)) => { 222 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
223 // enum variant 223 // enum variant
224 tested_by!(can_import_enum_variant); 224 mark::hit!(can_import_enum_variant);
225 let enum_data = db.enum_data(e); 225 let enum_data = db.enum_data(e);
226 match enum_data.variant(&segment) { 226 match enum_data.variant(&segment) {
227 Some(local_id) => { 227 Some(local_id) => {
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 39b011ad7..4e628b14d 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -18,7 +18,7 @@ use ra_syntax::{
18 ast::{self, AttrsOwner, NameOwner, VisibilityOwner}, 18 ast::{self, AttrsOwner, NameOwner, VisibilityOwner},
19 AstNode, 19 AstNode,
20}; 20};
21use test_utils::tested_by; 21use test_utils::mark;
22 22
23use crate::{ 23use crate::{
24 attr::Attrs, 24 attr::Attrs,
@@ -156,9 +156,16 @@ pub(super) struct DefData {
156} 156}
157 157
158#[derive(Debug, PartialEq, Eq, Clone, Copy)] 158#[derive(Debug, PartialEq, Eq, Clone, Copy)]
159pub(super) enum StructDefKind {
160 Record,
161 Tuple,
162 Unit,
163}
164
165#[derive(Debug, PartialEq, Eq, Clone, Copy)]
159pub(super) enum DefKind { 166pub(super) enum DefKind {
160 Function(FileAstId<ast::FnDef>), 167 Function(FileAstId<ast::FnDef>),
161 Struct(FileAstId<ast::StructDef>), 168 Struct(FileAstId<ast::StructDef>, StructDefKind),
162 Union(FileAstId<ast::UnionDef>), 169 Union(FileAstId<ast::UnionDef>),
163 Enum(FileAstId<ast::EnumDef>), 170 Enum(FileAstId<ast::EnumDef>),
164 Const(FileAstId<ast::ConstDef>), 171 Const(FileAstId<ast::ConstDef>),
@@ -171,7 +178,7 @@ impl DefKind {
171 pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> { 178 pub fn ast_id(&self) -> FileAstId<ast::ModuleItem> {
172 match self { 179 match self {
173 DefKind::Function(it) => it.upcast(), 180 DefKind::Function(it) => it.upcast(),
174 DefKind::Struct(it) => it.upcast(), 181 DefKind::Struct(it, _) => it.upcast(),
175 DefKind::Union(it) => it.upcast(), 182 DefKind::Union(it) => it.upcast(),
176 DefKind::Enum(it) => it.upcast(), 183 DefKind::Enum(it) => it.upcast(),
177 DefKind::Const(it) => it.upcast(), 184 DefKind::Const(it) => it.upcast(),
@@ -188,6 +195,7 @@ pub(super) struct MacroData {
188 pub(super) path: ModPath, 195 pub(super) path: ModPath,
189 pub(super) name: Option<Name>, 196 pub(super) name: Option<Name>,
190 pub(super) export: bool, 197 pub(super) export: bool,
198 pub(super) local_inner: bool,
191 pub(super) builtin: bool, 199 pub(super) builtin: bool,
192} 200}
193 201
@@ -235,9 +243,14 @@ impl RawItemsCollector {
235 return; 243 return;
236 } 244 }
237 ast::ModuleItem::StructDef(it) => { 245 ast::ModuleItem::StructDef(it) => {
246 let kind = match it.kind() {
247 ast::StructKind::Record(_) => StructDefKind::Record,
248 ast::StructKind::Tuple(_) => StructDefKind::Tuple,
249 ast::StructKind::Unit => StructDefKind::Unit,
250 };
238 let id = self.source_ast_id_map.ast_id(&it); 251 let id = self.source_ast_id_map.ast_id(&it);
239 let name = it.name(); 252 let name = it.name();
240 (DefKind::Struct(id), name) 253 (DefKind::Struct(id, kind), name)
241 } 254 }
242 ast::ModuleItem::UnionDef(it) => { 255 ast::ModuleItem::UnionDef(it) => {
243 let id = self.source_ast_id_map.ast_id(&it); 256 let id = self.source_ast_id_map.ast_id(&it);
@@ -333,7 +346,7 @@ impl RawItemsCollector {
333 self.push_item(current_module, attrs, RawItemKind::Module(item)); 346 self.push_item(current_module, attrs, RawItemKind::Module(item));
334 return; 347 return;
335 } 348 }
336 tested_by!(name_res_works_for_broken_modules); 349 mark::hit!(name_res_works_for_broken_modules);
337 } 350 }
338 351
339 fn add_use_item(&mut self, current_module: Option<Idx<ModuleData>>, use_item: ast::UseItem) { 352 fn add_use_item(&mut self, current_module: Option<Idx<ModuleData>>, use_item: ast::UseItem) {
@@ -401,14 +414,32 @@ impl RawItemsCollector {
401 414
402 let name = m.name().map(|it| it.as_name()); 415 let name = m.name().map(|it| it.as_name());
403 let ast_id = self.source_ast_id_map.ast_id(&m); 416 let ast_id = self.source_ast_id_map.ast_id(&m);
404 // FIXME: cfg_attr
405 let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
406 417
407 // FIXME: cfg_attr 418 // FIXME: cfg_attr
408 let builtin = 419 let export_attr = attrs.by_key("macro_export");
409 m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "rustc_builtin_macro"); 420
421 let export = export_attr.exists();
422 let local_inner = if export {
423 export_attr.tt_values().map(|it| &it.token_trees).flatten().any(|it| match it {
424 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
425 ident.text.contains("local_inner_macros")
426 }
427 _ => false,
428 })
429 } else {
430 false
431 };
432
433 let builtin = attrs.by_key("rustc_builtin_macro").exists();
410 434
411 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export, builtin }); 435 let m = self.raw_items.macros.alloc(MacroData {
436 ast_id,
437 path,
438 name,
439 export,
440 local_inner,
441 builtin,
442 });
412 self.push_item(current_module, attrs, RawItemKind::Macro(m)); 443 self.push_item(current_module, attrs, RawItemKind::Macro(m));
413 } 444 }
414 445
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index 83120fa36..05cd0297d 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -8,7 +8,7 @@ use std::sync::Arc;
8 8
9use insta::assert_snapshot; 9use insta::assert_snapshot;
10use ra_db::{fixture::WithFixture, SourceDatabase}; 10use ra_db::{fixture::WithFixture, SourceDatabase};
11use test_utils::covers; 11use test_utils::mark;
12 12
13use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; 13use crate::{db::DefDatabase, nameres::*, test_db::TestDB};
14 14
@@ -67,7 +67,7 @@ fn crate_def_map_smoke_test() {
67 ⋮Baz: t v 67 ⋮Baz: t v
68 ⋮E: t 68 ⋮E: t
69 ⋮EXT: v 69 ⋮EXT: v
70 ⋮U: t v 70 ⋮U: t
71 ⋮ext: v 71 ⋮ext: v
72 "###) 72 "###)
73} 73}
@@ -132,7 +132,7 @@ fn crate_def_map_fn_mod_same_name() {
132 132
133#[test] 133#[test]
134fn bogus_paths() { 134fn bogus_paths() {
135 covers!(bogus_paths); 135 mark::check!(bogus_paths);
136 let map = def_map( 136 let map = def_map(
137 " 137 "
138 //- /lib.rs 138 //- /lib.rs
@@ -247,7 +247,7 @@ fn re_exports() {
247 247
248#[test] 248#[test]
249fn std_prelude() { 249fn std_prelude() {
250 covers!(std_prelude); 250 mark::check!(std_prelude);
251 let map = def_map( 251 let map = def_map(
252 " 252 "
253 //- /main.rs crate:main deps:test_crate 253 //- /main.rs crate:main deps:test_crate
@@ -271,7 +271,7 @@ fn std_prelude() {
271 271
272#[test] 272#[test]
273fn can_import_enum_variant() { 273fn can_import_enum_variant() {
274 covers!(can_import_enum_variant); 274 mark::check!(can_import_enum_variant);
275 let map = def_map( 275 let map = def_map(
276 " 276 "
277 //- /lib.rs 277 //- /lib.rs
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs
index ee8df3a26..2b12c0daa 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir_def/src/nameres/tests/globs.rs
@@ -152,7 +152,7 @@ fn glob_privacy_2() {
152 152
153#[test] 153#[test]
154fn glob_across_crates() { 154fn glob_across_crates() {
155 covers!(glob_across_crates); 155 mark::check!(glob_across_crates);
156 let map = def_map( 156 let map = def_map(
157 r" 157 r"
158 //- /main.rs crate:main deps:test_crate 158 //- /main.rs crate:main deps:test_crate
@@ -171,7 +171,6 @@ fn glob_across_crates() {
171 171
172#[test] 172#[test]
173fn glob_privacy_across_crates() { 173fn glob_privacy_across_crates() {
174 covers!(glob_across_crates);
175 let map = def_map( 174 let map = def_map(
176 r" 175 r"
177 //- /main.rs crate:main deps:test_crate 176 //- /main.rs crate:main deps:test_crate
@@ -191,7 +190,7 @@ fn glob_privacy_across_crates() {
191 190
192#[test] 191#[test]
193fn glob_enum() { 192fn glob_enum() {
194 covers!(glob_enum); 193 mark::check!(glob_enum);
195 let map = def_map( 194 let map = def_map(
196 " 195 "
197 //- /lib.rs 196 //- /lib.rs
@@ -212,7 +211,7 @@ fn glob_enum() {
212 211
213#[test] 212#[test]
214fn glob_enum_group() { 213fn glob_enum_group() {
215 covers!(glob_enum_group); 214 mark::check!(glob_enum_group);
216 let map = def_map( 215 let map = def_map(
217 r" 216 r"
218 //- /lib.rs 217 //- /lib.rs
diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs
index b0befdfbd..84480d9f6 100644
--- a/crates/ra_hir_def/src/nameres/tests/macros.rs
+++ b/crates/ra_hir_def/src/nameres/tests/macros.rs
@@ -19,12 +19,12 @@ fn macro_rules_are_globally_visible() {
19 ); 19 );
20 assert_snapshot!(map, @r###" 20 assert_snapshot!(map, @r###"
21 ⋮crate 21 ⋮crate
22 ⋮Foo: t v 22 ⋮Foo: t
23 ⋮nested: t 23 ⋮nested: t
24 24
25 ⋮crate::nested 25 ⋮crate::nested
26 ⋮Bar: t v 26 ⋮Bar: t
27 ⋮Baz: t v 27 ⋮Baz: t
28 "###); 28 "###);
29} 29}
30 30
@@ -91,13 +91,13 @@ fn macro_rules_from_other_crates_are_visible() {
91 ); 91 );
92 assert_snapshot!(map, @r###" 92 assert_snapshot!(map, @r###"
93 ⋮crate 93 ⋮crate
94 ⋮Bar: t v 94 ⋮Bar: t
95 ⋮Foo: t v 95 ⋮Foo: t
96 ⋮bar: t 96 ⋮bar: t
97 97
98 ⋮crate::bar 98 ⋮crate::bar
99 ⋮Bar: t v 99 ⋮Bar: t
100 ⋮Foo: t v 100 ⋮Foo: t
101 ⋮bar: t 101 ⋮bar: t
102 "###); 102 "###);
103} 103}
@@ -124,13 +124,50 @@ fn macro_rules_export_with_local_inner_macros_are_visible() {
124 ); 124 );
125 assert_snapshot!(map, @r###" 125 assert_snapshot!(map, @r###"
126 ⋮crate 126 ⋮crate
127 ⋮Bar: t v 127 ⋮Bar: t
128 ⋮Foo: t v 128 ⋮Foo: t
129 ⋮bar: t 129 ⋮bar: t
130 130
131 ⋮crate::bar 131 ⋮crate::bar
132 ⋮Bar: t v 132 ⋮Bar: t
133 ⋮Foo: t v 133 ⋮Foo: t
134 ⋮bar: t
135 "###);
136}
137
138#[test]
139fn local_inner_macros_makes_local_macros_usable() {
140 let map = def_map(
141 "
142 //- /main.rs crate:main deps:foo
143 foo::structs!(Foo, Bar);
144 mod bar;
145 //- /bar.rs
146 use crate::*;
147 //- /lib.rs crate:foo
148 #[macro_export(local_inner_macros)]
149 macro_rules! structs {
150 ($($i:ident),*) => {
151 inner!($($i),*);
152 }
153 }
154 #[macro_export]
155 macro_rules! inner {
156 ($($i:ident),*) => {
157 $(struct $i { field: u32 } )*
158 }
159 }
160 ",
161 );
162 assert_snapshot!(map, @r###"
163 ⋮crate
164 ⋮Bar: t
165 ⋮Foo: t
166 ⋮bar: t
167
168 ⋮crate::bar
169 ⋮Bar: t
170 ⋮Foo: t
134 ⋮bar: t 171 ⋮bar: t
135 "###); 172 "###);
136} 173}
@@ -167,7 +204,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
167 ); 204 );
168 assert_snapshot!(map, @r###" 205 assert_snapshot!(map, @r###"
169 ⋮crate 206 ⋮crate
170 ⋮Foo: t v 207 ⋮Foo: t
171 ⋮bar: m 208 ⋮bar: m
172 ⋮foo: m 209 ⋮foo: m
173 "###); 210 "###);
@@ -175,7 +212,7 @@ fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
175 212
176#[test] 213#[test]
177fn macro_rules_from_other_crates_are_visible_with_macro_use() { 214fn macro_rules_from_other_crates_are_visible_with_macro_use() {
178 covers!(macro_rules_from_other_crates_are_visible_with_macro_use); 215 mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use);
179 let map = def_map( 216 let map = def_map(
180 " 217 "
181 //- /main.rs crate:main deps:foo 218 //- /main.rs crate:main deps:foo
@@ -225,7 +262,7 @@ fn macro_rules_from_other_crates_are_visible_with_macro_use() {
225 262
226#[test] 263#[test]
227fn prelude_is_macro_use() { 264fn prelude_is_macro_use() {
228 covers!(prelude_is_macro_use); 265 mark::check!(prelude_is_macro_use);
229 let map = def_map( 266 let map = def_map(
230 " 267 "
231 //- /main.rs crate:main deps:foo 268 //- /main.rs crate:main deps:foo
@@ -507,8 +544,7 @@ fn path_qualified_macros() {
507 544
508#[test] 545#[test]
509fn macro_dollar_crate_is_correct_in_item() { 546fn macro_dollar_crate_is_correct_in_item() {
510 covers!(macro_dollar_crate_self); 547 mark::check!(macro_dollar_crate_self);
511 covers!(macro_dollar_crate_other);
512 let map = def_map( 548 let map = def_map(
513 " 549 "
514 //- /main.rs crate:main deps:foo 550 //- /main.rs crate:main deps:foo
@@ -566,7 +602,7 @@ fn macro_dollar_crate_is_correct_in_item() {
566 602
567#[test] 603#[test]
568fn macro_dollar_crate_is_correct_in_indirect_deps() { 604fn macro_dollar_crate_is_correct_in_indirect_deps() {
569 covers!(macro_dollar_crate_other); 605 mark::check!(macro_dollar_crate_other);
570 // From std 606 // From std
571 let map = def_map( 607 let map = def_map(
572 r#" 608 r#"
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
index 37fcdfb8c..b43b294ca 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
@@ -2,7 +2,7 @@ use super::*;
2 2
3#[test] 3#[test]
4fn name_res_works_for_broken_modules() { 4fn name_res_works_for_broken_modules() {
5 covers!(name_res_works_for_broken_modules); 5 mark::check!(name_res_works_for_broken_modules);
6 let map = def_map( 6 let map = def_map(
7 r" 7 r"
8 //- /lib.rs 8 //- /lib.rs
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index e3d237a0a..6a0c019fd 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -116,6 +116,21 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
116 } 116 }
117 segments.reverse(); 117 segments.reverse();
118 generic_args.reverse(); 118 generic_args.reverse();
119
120 // handle local_inner_macros :
121 // Basically, even in rustc it is quite hacky:
122 // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456
123 // We follow what it did anyway :)
124 if segments.len() == 1 && kind == PathKind::Plain {
125 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
126 if macro_call.is_bang() {
127 if let Some(crate_id) = hygiene.local_inner_macros() {
128 kind = PathKind::DollarCrate(crate_id);
129 }
130 }
131 }
132 }
133
119 let mod_path = ModPath { kind, segments }; 134 let mod_path = ModPath { kind, segments };
120 return Some(Path { type_anchor, mod_path, generic_args }); 135 return Some(Path { type_anchor, mod_path, generic_args });
121 136
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs
index 5b6854b0f..7cc655487 100644
--- a/crates/ra_hir_def/src/path/lower/lower_use.rs
+++ b/crates/ra_hir_def/src/path/lower/lower_use.rs
@@ -6,7 +6,7 @@ use std::iter;
6use either::Either; 6use either::Either;
7use hir_expand::{hygiene::Hygiene, name::AsName}; 7use hir_expand::{hygiene::Hygiene, name::AsName};
8use ra_syntax::ast::{self, NameOwner}; 8use ra_syntax::ast::{self, NameOwner};
9use test_utils::tested_by; 9use test_utils::mark;
10 10
11use crate::path::{ImportAlias, ModPath, PathKind}; 11use crate::path::{ImportAlias, ModPath, PathKind};
12 12
@@ -54,7 +54,7 @@ pub(crate) fn lower_use_tree(
54 // FIXME: report errors somewhere 54 // FIXME: report errors somewhere
55 // We get here if we do 55 // We get here if we do
56 } else if is_glob { 56 } else if is_glob {
57 tested_by!(glob_enum_group); 57 mark::hit!(glob_enum_group);
58 if let Some(prefix) = prefix { 58 if let Some(prefix) = prefix {
59 cb(prefix, &tree, is_glob, None) 59 cb(prefix, &tree, is_glob, None)
60 } 60 }
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 717506358..15fdd9019 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -86,6 +86,7 @@ pub enum ResolveValueResult {
86 86
87#[derive(Debug, Clone, PartialEq, Eq, Hash)] 87#[derive(Debug, Clone, PartialEq, Eq, Hash)]
88pub enum ValueNs { 88pub enum ValueNs {
89 ImplSelf(ImplId),
89 LocalBinding(PatId), 90 LocalBinding(PatId),
90 FunctionId(FunctionId), 91 FunctionId(FunctionId),
91 ConstId(ConstId), 92 ConstId(ConstId),
@@ -291,19 +292,26 @@ impl Resolver {
291 } 292 }
292 Scope::GenericParams { .. } => continue, 293 Scope::GenericParams { .. } => continue,
293 294
294 Scope::ImplDefScope(impl_) if n_segments > 1 => { 295 Scope::ImplDefScope(impl_) => {
295 if first_name == &name![Self] { 296 if first_name == &name![Self] {
296 let ty = TypeNs::SelfType(*impl_); 297 if n_segments > 1 {
297 return Some(ResolveValueResult::Partial(ty, 1)); 298 let ty = TypeNs::SelfType(*impl_);
299 return Some(ResolveValueResult::Partial(ty, 1));
300 } else {
301 return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(*impl_)));
302 }
298 } 303 }
299 } 304 }
300 Scope::AdtScope(adt) if n_segments > 1 => { 305 Scope::AdtScope(adt) => {
306 if n_segments == 1 {
307 // bare `Self` doesn't work in the value namespace in a struct/enum definition
308 continue;
309 }
301 if first_name == &name![Self] { 310 if first_name == &name![Self] {
302 let ty = TypeNs::AdtSelfType(*adt); 311 let ty = TypeNs::AdtSelfType(*adt);
303 return Some(ResolveValueResult::Partial(ty, 1)); 312 return Some(ResolveValueResult::Partial(ty, 1));
304 } 313 }
305 } 314 }
306 Scope::ImplDefScope(_) | Scope::AdtScope(_) => continue,
307 315
308 Scope::ModuleScope(m) => { 316 Scope::ModuleScope(m) => {
309 let (module_def, idx) = m.crate_def_map.resolve_path( 317 let (module_def, idx) = m.crate_def_map.resolve_path(
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs
index e60f879a3..1dc9cac66 100644
--- a/crates/ra_hir_expand/src/builtin_derive.rs
+++ b/crates/ra_hir_expand/src/builtin_derive.rs
@@ -38,7 +38,7 @@ macro_rules! register_builtin {
38 _ => return None, 38 _ => return None,
39 }; 39 };
40 40
41 Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind) }) 41 Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind), local_inner: false })
42 } 42 }
43 }; 43 };
44} 44}
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
index e0fef613d..3bce8f673 100644
--- a/crates/ra_hir_expand/src/builtin_macro.rs
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -73,11 +73,13 @@ pub fn find_builtin_macro(
73 krate: Some(krate), 73 krate: Some(krate),
74 ast_id: Some(ast_id), 74 ast_id: Some(ast_id),
75 kind: MacroDefKind::BuiltIn(kind), 75 kind: MacroDefKind::BuiltIn(kind),
76 local_inner: false,
76 }), 77 }),
77 Either::Right(kind) => Some(MacroDefId { 78 Either::Right(kind) => Some(MacroDefId {
78 krate: Some(krate), 79 krate: Some(krate),
79 ast_id: Some(ast_id), 80 ast_id: Some(ast_id),
80 kind: MacroDefKind::BuiltInEager(kind), 81 kind: MacroDefKind::BuiltInEager(kind),
82 local_inner: false,
81 }), 83 }),
82 } 84 }
83} 85}
@@ -358,7 +360,7 @@ fn env_expand(
358 // However, we cannot use an empty string here, because for 360 // However, we cannot use an empty string here, because for
359 // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become 361 // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become
360 // `include!("foo.rs"), which might go to infinite loop 362 // `include!("foo.rs"), which might go to infinite loop
361 let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTATED__".to_string()); 363 let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTED__".to_string());
362 let expanded = quote! { #s }; 364 let expanded = quote! { #s };
363 365
364 Ok((expanded, FragmentKind::Expr)) 366 Ok((expanded, FragmentKind::Expr))
@@ -406,6 +408,7 @@ mod tests {
406 krate: Some(CrateId(0)), 408 krate: Some(CrateId(0)),
407 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))), 409 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))),
408 kind: MacroDefKind::BuiltIn(expander), 410 kind: MacroDefKind::BuiltIn(expander),
411 local_inner: false,
409 }; 412 };
410 413
411 let loc = MacroCallLoc { 414 let loc = MacroCallLoc {
@@ -425,6 +428,7 @@ mod tests {
425 krate: Some(CrateId(0)), 428 krate: Some(CrateId(0)),
426 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))), 429 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))),
427 kind: MacroDefKind::BuiltInEager(expander), 430 kind: MacroDefKind::BuiltInEager(expander),
431 local_inner: false,
428 }; 432 };
429 433
430 let args = macro_calls[1].token_tree().unwrap(); 434 let args = macro_calls[1].token_tree().unwrap();
@@ -504,7 +508,7 @@ mod tests {
504 "#, 508 "#,
505 ); 509 );
506 510
507 assert_eq!(expanded, "\"__RA_UNIMPLEMENTATED__\""); 511 assert_eq!(expanded, "\"__RA_UNIMPLEMENTED__\"");
508 } 512 }
509 513
510 #[test] 514 #[test]
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs
index 047452306..bf30d7151 100644
--- a/crates/ra_hir_expand/src/db.rs
+++ b/crates/ra_hir_expand/src/db.rs
@@ -34,7 +34,12 @@ impl TokenExpander {
34 // FIXME switch these to ExpandResult as well 34 // FIXME switch these to ExpandResult as well
35 TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), 35 TokenExpander::Builtin(it) => it.expand(db, id, tt).into(),
36 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), 36 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
37 TokenExpander::ProcMacro(it) => it.expand(db, id, tt).into(), 37 TokenExpander::ProcMacro(_) => {
38 // We store the result in salsa db to prevent non-determinisc behavior in
39 // some proc-macro implementation
40 // See #4315 for details
41 db.expand_proc_macro(id.into()).into()
42 }
38 } 43 }
39 } 44 }
40 45
@@ -75,6 +80,8 @@ pub trait AstDatabase: SourceDatabase {
75 80
76 #[salsa::interned] 81 #[salsa::interned]
77 fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; 82 fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId;
83
84 fn expand_proc_macro(&self, call: MacroCallId) -> Result<tt::Subtree, mbe::ExpandError>;
78} 85}
79 86
80/// This expands the given macro call, but with different arguments. This is 87/// This expands the given macro call, but with different arguments. This is
@@ -216,6 +223,33 @@ fn macro_expand_with_arg(
216 (Some(Arc::new(tt)), err.map(|e| format!("{:?}", e))) 223 (Some(Arc::new(tt)), err.map(|e| format!("{:?}", e)))
217} 224}
218 225
226pub(crate) fn expand_proc_macro(
227 db: &dyn AstDatabase,
228 id: MacroCallId,
229) -> Result<tt::Subtree, mbe::ExpandError> {
230 let lazy_id = match id {
231 MacroCallId::LazyMacro(id) => id,
232 MacroCallId::EagerMacro(_) => unreachable!(),
233 };
234
235 let loc = db.lookup_intern_macro(lazy_id);
236 let macro_arg = match db.macro_arg(id) {
237 Some(it) => it,
238 None => {
239 return Err(
240 tt::ExpansionError::Unknown("No arguments for proc-macro".to_string()).into()
241 )
242 }
243 };
244
245 let expander = match loc.def.kind {
246 MacroDefKind::CustomDerive(expander) => expander,
247 _ => unreachable!(),
248 };
249
250 expander.expand(db, lazy_id, &macro_arg.0)
251}
252
219pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { 253pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
220 match file_id.0 { 254 match file_id.0 {
221 HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), 255 HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
@@ -330,7 +364,7 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
330 FragmentKind::Expr 364 FragmentKind::Expr
331 } 365 }
332 // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that 366 // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that
333 EXPR_STMT | BLOCK => FragmentKind::Expr, 367 EXPR_STMT | BLOCK_EXPR => FragmentKind::Expr,
334 ARG_LIST => FragmentKind::Expr, 368 ARG_LIST => FragmentKind::Expr,
335 TRY_EXPR => FragmentKind::Expr, 369 TRY_EXPR => FragmentKind::Expr,
336 TUPLE_EXPR => FragmentKind::Expr, 370 TUPLE_EXPR => FragmentKind::Expr,
@@ -342,7 +376,6 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
342 CONDITION => FragmentKind::Expr, 376 CONDITION => FragmentKind::Expr,
343 BREAK_EXPR => FragmentKind::Expr, 377 BREAK_EXPR => FragmentKind::Expr,
344 RETURN_EXPR => FragmentKind::Expr, 378 RETURN_EXPR => FragmentKind::Expr,
345 BLOCK_EXPR => FragmentKind::Expr,
346 MATCH_EXPR => FragmentKind::Expr, 379 MATCH_EXPR => FragmentKind::Expr,
347 MATCH_ARM => FragmentKind::Expr, 380 MATCH_ARM => FragmentKind::Expr,
348 MATCH_GUARD => FragmentKind::Expr, 381 MATCH_GUARD => FragmentKind::Expr,
diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs
index 53866bbcb..6b482a60c 100644
--- a/crates/ra_hir_expand/src/hygiene.rs
+++ b/crates/ra_hir_expand/src/hygiene.rs
@@ -16,31 +16,34 @@ use crate::{
16pub struct Hygiene { 16pub struct Hygiene {
17 // This is what `$crate` expands to 17 // This is what `$crate` expands to
18 def_crate: Option<CrateId>, 18 def_crate: Option<CrateId>,
19
20 // Indiciate this is a local inner macro
21 local_inner: bool,
19} 22}
20 23
21impl Hygiene { 24impl Hygiene {
22 pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene { 25 pub fn new(db: &dyn AstDatabase, file_id: HirFileId) -> Hygiene {
23 let def_crate = match file_id.0 { 26 let (def_crate, local_inner) = match file_id.0 {
24 HirFileIdRepr::FileId(_) => None, 27 HirFileIdRepr::FileId(_) => (None, false),
25 HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { 28 HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
26 MacroCallId::LazyMacro(id) => { 29 MacroCallId::LazyMacro(id) => {
27 let loc = db.lookup_intern_macro(id); 30 let loc = db.lookup_intern_macro(id);
28 match loc.def.kind { 31 match loc.def.kind {
29 MacroDefKind::Declarative => loc.def.krate, 32 MacroDefKind::Declarative => (loc.def.krate, loc.def.local_inner),
30 MacroDefKind::BuiltIn(_) => None, 33 MacroDefKind::BuiltIn(_) => (None, false),
31 MacroDefKind::BuiltInDerive(_) => None, 34 MacroDefKind::BuiltInDerive(_) => (None, false),
32 MacroDefKind::BuiltInEager(_) => None, 35 MacroDefKind::BuiltInEager(_) => (None, false),
33 MacroDefKind::CustomDerive(_) => None, 36 MacroDefKind::CustomDerive(_) => (None, false),
34 } 37 }
35 } 38 }
36 MacroCallId::EagerMacro(_id) => None, 39 MacroCallId::EagerMacro(_id) => (None, false),
37 }, 40 },
38 }; 41 };
39 Hygiene { def_crate } 42 Hygiene { def_crate, local_inner }
40 } 43 }
41 44
42 pub fn new_unhygienic() -> Hygiene { 45 pub fn new_unhygienic() -> Hygiene {
43 Hygiene { def_crate: None } 46 Hygiene { def_crate: None, local_inner: false }
44 } 47 }
45 48
46 // FIXME: this should just return name 49 // FIXME: this should just return name
@@ -52,4 +55,12 @@ impl Hygiene {
52 } 55 }
53 Either::Left(name_ref.as_name()) 56 Either::Left(name_ref.as_name())
54 } 57 }
58
59 pub fn local_inner_macros(&self) -> Option<CrateId> {
60 if self.local_inner {
61 self.def_crate
62 } else {
63 None
64 }
65 }
55} 66}
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index 754a0f005..f440c073b 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -204,6 +204,8 @@ pub struct MacroDefId {
204 pub krate: Option<CrateId>, 204 pub krate: Option<CrateId>,
205 pub ast_id: Option<AstId<ast::MacroCall>>, 205 pub ast_id: Option<AstId<ast::MacroCall>>,
206 pub kind: MacroDefKind, 206 pub kind: MacroDefKind,
207
208 pub local_inner: bool,
207} 209}
208 210
209impl MacroDefId { 211impl MacroDefId {
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index 65db6d1b0..5fc0ec5e3 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -27,9 +27,9 @@ test_utils = { path = "../test_utils" }
27 27
28scoped-tls = "1" 28scoped-tls = "1"
29 29
30chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" } 30chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" }
31chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" } 31chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" }
32chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" } 32chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "3e9c2503ae9c5277c2acb74624dc267876dd89b3" }
33 33
34[dev-dependencies] 34[dev-dependencies]
35insta = "0.16.0" 35insta = "0.16.0"
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs
index 779e78574..3e6e1e333 100644
--- a/crates/ra_hir_ty/src/_match.rs
+++ b/crates/ra_hir_ty/src/_match.rs
@@ -573,14 +573,20 @@ pub(crate) fn is_useful(
573 matrix: &Matrix, 573 matrix: &Matrix,
574 v: &PatStack, 574 v: &PatStack,
575) -> MatchCheckResult<Usefulness> { 575) -> MatchCheckResult<Usefulness> {
576 // Handle the special case of enums with no variants. In that case, no match 576 // Handle two special cases:
577 // arm is useful. 577 // - enum with no variants
578 if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) = 578 // - `!` type
579 cx.infer[cx.match_expr].strip_references() 579 // In those cases, no match arm is useful.
580 { 580 match cx.infer[cx.match_expr].strip_references() {
581 if cx.db.enum_data(*enum_id).variants.is_empty() { 581 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) => {
582 if cx.db.enum_data(*enum_id).variants.is_empty() {
583 return Ok(Usefulness::NotUseful);
584 }
585 }
586 Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }) => {
582 return Ok(Usefulness::NotUseful); 587 return Ok(Usefulness::NotUseful);
583 } 588 }
589 _ => (),
584 } 590 }
585 591
586 if v.is_empty() { 592 if v.is_empty() {
@@ -1918,6 +1924,17 @@ mod tests {
1918 } 1924 }
1919 1925
1920 #[test] 1926 #[test]
1927 fn type_never() {
1928 let content = r"
1929 fn test_fn(never: !) {
1930 match never {}
1931 }
1932 ";
1933
1934 check_no_diagnostic(content);
1935 }
1936
1937 #[test]
1921 fn enum_never_ref() { 1938 fn enum_never_ref() {
1922 let content = r" 1939 let content = r"
1923 enum Never {} 1940 enum Never {}
@@ -1929,6 +1946,23 @@ mod tests {
1929 1946
1930 check_no_diagnostic(content); 1947 check_no_diagnostic(content);
1931 } 1948 }
1949
1950 #[test]
1951 fn expr_diverges_missing_arm() {
1952 let content = r"
1953 enum Either {
1954 A,
1955 B,
1956 }
1957 fn test_fn() {
1958 match loop {} {
1959 Either::A => (),
1960 }
1961 }
1962 ";
1963
1964 check_no_diagnostic(content);
1965 }
1932} 1966}
1933 1967
1934#[cfg(test)] 1968#[cfg(test)]
@@ -1981,26 +2015,6 @@ mod false_negatives {
1981 } 2015 }
1982 2016
1983 #[test] 2017 #[test]
1984 fn expr_diverges_missing_arm() {
1985 let content = r"
1986 enum Either {
1987 A,
1988 B,
1989 }
1990 fn test_fn() {
1991 match loop {} {
1992 Either::A => (),
1993 }
1994 }
1995 ";
1996
1997 // This is a false negative.
1998 // Even though the match expression diverges, rustc fails
1999 // to compile here since `Either::B` is missing.
2000 check_no_diagnostic(content);
2001 }
2002
2003 #[test]
2004 fn expr_loop_missing_arm() { 2018 fn expr_loop_missing_arm() {
2005 let content = r" 2019 let content = r"
2006 enum Either { 2020 enum Either {
@@ -2018,7 +2032,7 @@ mod false_negatives {
2018 // We currently infer the type of `loop { break Foo::A }` to `!`, which 2032 // We currently infer the type of `loop { break Foo::A }` to `!`, which
2019 // causes us to skip the diagnostic since `Either::A` doesn't type check 2033 // causes us to skip the diagnostic since `Either::A` doesn't type check
2020 // with `!`. 2034 // with `!`.
2021 check_no_diagnostic(content); 2035 check_diagnostic(content);
2022 } 2036 }
2023 2037
2024 #[test] 2038 #[test]
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index c8fd54861..41ac70272 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -131,3 +131,31 @@ impl AstDiagnostic for MissingOkInTailExpr {
131 ast::Expr::cast(node).unwrap() 131 ast::Expr::cast(node).unwrap()
132 } 132 }
133} 133}
134
135#[derive(Debug)]
136pub struct BreakOutsideOfLoop {
137 pub file: HirFileId,
138 pub expr: AstPtr<ast::Expr>,
139}
140
141impl Diagnostic for BreakOutsideOfLoop {
142 fn message(&self) -> String {
143 "break outside of loop".to_string()
144 }
145 fn source(&self) -> InFile<SyntaxNodePtr> {
146 InFile { file_id: self.file, value: self.expr.clone().into() }
147 }
148 fn as_any(&self) -> &(dyn Any + Send + 'static) {
149 self
150 }
151}
152
153impl AstDiagnostic for BreakOutsideOfLoop {
154 type AST = ast::Expr;
155
156 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
157 let root = db.parse_or_expand(self.file).unwrap();
158 let node = self.source().value.to_node(&root);
159 ast::Expr::cast(node).unwrap()
160 }
161}
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index d03bbd5a7..b9c4d2e89 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -6,28 +6,42 @@ use crate::{
6 db::HirDatabase, utils::generics, ApplicationTy, CallableDef, FnSig, GenericPredicate, 6 db::HirDatabase, utils::generics, ApplicationTy, CallableDef, FnSig, GenericPredicate,
7 Obligation, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 7 Obligation, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
8}; 8};
9use hir_def::{generics::TypeParamProvenance, AdtId, AssocContainerId, Lookup}; 9use hir_def::{
10 find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId,
11 Lookup, ModuleId,
12};
10use hir_expand::name::Name; 13use hir_expand::name::Name;
11 14
12pub struct HirFormatter<'a, 'b> { 15pub struct HirFormatter<'a> {
13 pub db: &'a dyn HirDatabase, 16 pub db: &'a dyn HirDatabase,
14 fmt: &'a mut fmt::Formatter<'b>, 17 fmt: &'a mut dyn fmt::Write,
15 buf: String, 18 buf: String,
16 curr_size: usize, 19 curr_size: usize,
17 pub(crate) max_size: Option<usize>, 20 pub(crate) max_size: Option<usize>,
18 omit_verbose_types: bool, 21 omit_verbose_types: bool,
22 display_target: DisplayTarget,
19} 23}
20 24
21pub trait HirDisplay { 25pub trait HirDisplay {
22 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result; 26 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError>;
23 27
28 /// Returns a `Display`able type that is human-readable.
29 /// Use this for showing types to the user (e.g. diagnostics)
24 fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> 30 fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
25 where 31 where
26 Self: Sized, 32 Self: Sized,
27 { 33 {
28 HirDisplayWrapper(db, self, None, false) 34 HirDisplayWrapper {
35 db,
36 t: self,
37 max_size: None,
38 omit_verbose_types: false,
39 display_target: DisplayTarget::Diagnostics,
40 }
29 } 41 }
30 42
43 /// Returns a `Display`able type that is human-readable and tries to be succinct.
44 /// Use this for showing types to the user where space is constrained (e.g. doc popups)
31 fn display_truncated<'a>( 45 fn display_truncated<'a>(
32 &'a self, 46 &'a self,
33 db: &'a dyn HirDatabase, 47 db: &'a dyn HirDatabase,
@@ -36,16 +50,46 @@ pub trait HirDisplay {
36 where 50 where
37 Self: Sized, 51 Self: Sized,
38 { 52 {
39 HirDisplayWrapper(db, self, max_size, true) 53 HirDisplayWrapper {
54 db,
55 t: self,
56 max_size,
57 omit_verbose_types: true,
58 display_target: DisplayTarget::Diagnostics,
59 }
60 }
61
62 /// Returns a String representation of `self` that can be inserted into the given module.
63 /// Use this when generating code (e.g. assists)
64 fn display_source_code<'a>(
65 &'a self,
66 db: &'a dyn HirDatabase,
67 module_id: ModuleId,
68 ) -> Result<String, DisplaySourceCodeError> {
69 let mut result = String::new();
70 match self.hir_fmt(&mut HirFormatter {
71 db,
72 fmt: &mut result,
73 buf: String::with_capacity(20),
74 curr_size: 0,
75 max_size: None,
76 omit_verbose_types: false,
77 display_target: DisplayTarget::SourceCode { module_id },
78 }) {
79 Ok(()) => {}
80 Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
81 Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),
82 };
83 Ok(result)
40 } 84 }
41} 85}
42 86
43impl<'a, 'b> HirFormatter<'a, 'b> { 87impl<'a> HirFormatter<'a> {
44 pub fn write_joined<T: HirDisplay>( 88 pub fn write_joined<T: HirDisplay>(
45 &mut self, 89 &mut self,
46 iter: impl IntoIterator<Item = T>, 90 iter: impl IntoIterator<Item = T>,
47 sep: &str, 91 sep: &str,
48 ) -> fmt::Result { 92 ) -> Result<(), HirDisplayError> {
49 let mut first = true; 93 let mut first = true;
50 for e in iter { 94 for e in iter {
51 if !first { 95 if !first {
@@ -58,14 +102,14 @@ impl<'a, 'b> HirFormatter<'a, 'b> {
58 } 102 }
59 103
60 /// This allows using the `write!` macro directly with a `HirFormatter`. 104 /// This allows using the `write!` macro directly with a `HirFormatter`.
61 pub fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result { 105 pub fn write_fmt(&mut self, args: fmt::Arguments) -> Result<(), HirDisplayError> {
62 // We write to a buffer first to track output size 106 // We write to a buffer first to track output size
63 self.buf.clear(); 107 self.buf.clear();
64 fmt::write(&mut self.buf, args)?; 108 fmt::write(&mut self.buf, args)?;
65 self.curr_size += self.buf.len(); 109 self.curr_size += self.buf.len();
66 110
67 // Then we write to the internal formatter from the buffer 111 // Then we write to the internal formatter from the buffer
68 self.fmt.write_str(&self.buf) 112 self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)
69 } 113 }
70 114
71 pub fn should_truncate(&self) -> bool { 115 pub fn should_truncate(&self) -> bool {
@@ -81,34 +125,82 @@ impl<'a, 'b> HirFormatter<'a, 'b> {
81 } 125 }
82} 126}
83 127
84pub struct HirDisplayWrapper<'a, T>(&'a dyn HirDatabase, &'a T, Option<usize>, bool); 128#[derive(Clone, Copy)]
129enum DisplayTarget {
130 /// Display types for inlays, doc popups, autocompletion, etc...
131 /// Showing `{unknown}` or not qualifying paths is fine here.
132 /// There's no reason for this to fail.
133 Diagnostics,
134 /// Display types for inserting them in source files.
135 /// The generated code should compile, so paths need to be qualified.
136 SourceCode { module_id: ModuleId },
137}
138
139impl DisplayTarget {
140 fn is_source_code(&self) -> bool {
141 matches!(self, Self::SourceCode {..})
142 }
143}
144
145#[derive(Debug)]
146pub enum DisplaySourceCodeError {
147 PathNotFound,
148}
149
150pub enum HirDisplayError {
151 /// Errors that can occur when generating source code
152 DisplaySourceCodeError(DisplaySourceCodeError),
153 /// `FmtError` is required to be compatible with std::fmt::Display
154 FmtError,
155}
156impl From<fmt::Error> for HirDisplayError {
157 fn from(_: fmt::Error) -> Self {
158 Self::FmtError
159 }
160}
161
162pub struct HirDisplayWrapper<'a, T> {
163 db: &'a dyn HirDatabase,
164 t: &'a T,
165 max_size: Option<usize>,
166 omit_verbose_types: bool,
167 display_target: DisplayTarget,
168}
85 169
86impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T> 170impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T>
87where 171where
88 T: HirDisplay, 172 T: HirDisplay,
89{ 173{
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 self.1.hir_fmt(&mut HirFormatter { 175 match self.t.hir_fmt(&mut HirFormatter {
92 db: self.0, 176 db: self.db,
93 fmt: f, 177 fmt: f,
94 buf: String::with_capacity(20), 178 buf: String::with_capacity(20),
95 curr_size: 0, 179 curr_size: 0,
96 max_size: self.2, 180 max_size: self.max_size,
97 omit_verbose_types: self.3, 181 omit_verbose_types: self.omit_verbose_types,
98 }) 182 display_target: self.display_target,
183 }) {
184 Ok(()) => Ok(()),
185 Err(HirDisplayError::FmtError) => Err(fmt::Error),
186 Err(HirDisplayError::DisplaySourceCodeError(_)) => {
187 // This should never happen
188 panic!("HirDisplay failed when calling Display::fmt!")
189 }
190 }
99 } 191 }
100} 192}
101 193
102const TYPE_HINT_TRUNCATION: &str = "…"; 194const TYPE_HINT_TRUNCATION: &str = "…";
103 195
104impl HirDisplay for &Ty { 196impl HirDisplay for &Ty {
105 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { 197 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
106 HirDisplay::hir_fmt(*self, f) 198 HirDisplay::hir_fmt(*self, f)
107 } 199 }
108} 200}
109 201
110impl HirDisplay for ApplicationTy { 202impl HirDisplay for ApplicationTy {
111 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { 203 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
112 if f.should_truncate() { 204 if f.should_truncate() {
113 return write!(f, "{}", TYPE_HINT_TRUNCATION); 205 return write!(f, "{}", TYPE_HINT_TRUNCATION);
114 } 206 }
@@ -191,45 +283,66 @@ impl HirDisplay for ApplicationTy {
191 } 283 }
192 } 284 }
193 TypeCtor::Adt(def_id) => { 285 TypeCtor::Adt(def_id) => {
194 let name = match def_id { 286 match f.display_target {
195 AdtId::StructId(it) => f.db.struct_data(it).name.clone(), 287 DisplayTarget::Diagnostics => {
196 AdtId::UnionId(it) => f.db.union_data(it).name.clone(), 288 let name = match def_id {
197 AdtId::EnumId(it) => f.db.enum_data(it).name.clone(), 289 AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
198 }; 290 AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
199 write!(f, "{}", name)?; 291 AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
292 };
293 write!(f, "{}", name)?;
294 }
295 DisplayTarget::SourceCode { module_id } => {
296 if let Some(path) = find_path::find_path(
297 f.db.upcast(),
298 ItemInNs::Types(def_id.into()),
299 module_id,
300 ) {
301 write!(f, "{}", path)?;
302 } else {
303 return Err(HirDisplayError::DisplaySourceCodeError(
304 DisplaySourceCodeError::PathNotFound,
305 ));
306 }
307 }
308 }
309
200 if self.parameters.len() > 0 { 310 if self.parameters.len() > 0 {
201 let mut non_default_parameters = Vec::with_capacity(self.parameters.len()); 311 let mut non_default_parameters = Vec::with_capacity(self.parameters.len());
202 let parameters_to_write = if f.omit_verbose_types() { 312 let parameters_to_write =
203 match self 313 if f.display_target.is_source_code() || f.omit_verbose_types() {
204 .ctor 314 match self
205 .as_generic_def() 315 .ctor
206 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 316 .as_generic_def()
207 .filter(|defaults| !defaults.is_empty()) 317 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
208 { 318 .filter(|defaults| !defaults.is_empty())
209 None => self.parameters.0.as_ref(), 319 {
210 Some(default_parameters) => { 320 None => self.parameters.0.as_ref(),
211 for (i, parameter) in self.parameters.iter().enumerate() { 321 Some(default_parameters) => {
212 match (parameter, default_parameters.get(i)) { 322 for (i, parameter) in self.parameters.iter().enumerate() {
213 (&Ty::Unknown, _) | (_, None) => { 323 match (parameter, default_parameters.get(i)) {
214 non_default_parameters.push(parameter.clone()) 324 (&Ty::Unknown, _) | (_, None) => {
325 non_default_parameters.push(parameter.clone())
326 }
327 (_, Some(default_parameter))
328 if parameter != default_parameter =>
329 {
330 non_default_parameters.push(parameter.clone())
331 }
332 _ => (),
215 } 333 }
216 (_, Some(default_parameter))
217 if parameter != default_parameter =>
218 {
219 non_default_parameters.push(parameter.clone())
220 }
221 _ => (),
222 } 334 }
335 &non_default_parameters
223 } 336 }
224 &non_default_parameters
225 } 337 }
226 } 338 } else {
227 } else { 339 self.parameters.0.as_ref()
228 self.parameters.0.as_ref() 340 };
229 }; 341 if !parameters_to_write.is_empty() {
230 write!(f, "<")?; 342 write!(f, "<")?;
231 f.write_joined(parameters_to_write, ", ")?; 343 f.write_joined(parameters_to_write, ", ")?;
232 write!(f, ">")?; 344 write!(f, ">")?;
345 }
233 } 346 }
234 } 347 }
235 TypeCtor::AssociatedType(type_alias) => { 348 TypeCtor::AssociatedType(type_alias) => {
@@ -269,7 +382,7 @@ impl HirDisplay for ApplicationTy {
269} 382}
270 383
271impl HirDisplay for ProjectionTy { 384impl HirDisplay for ProjectionTy {
272 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { 385 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
273 if f.should_truncate() { 386 if f.should_truncate() {
274 return write!(f, "{}", TYPE_HINT_TRUNCATION); 387 return write!(f, "{}", TYPE_HINT_TRUNCATION);
275 } 388 }
@@ -287,7 +400,7 @@ impl HirDisplay for ProjectionTy {
287} 400}
288 401
289impl HirDisplay for Ty { 402impl HirDisplay for Ty {
290 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { 403 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
291 if f.should_truncate() { 404 if f.should_truncate() {
292 return write!(f, "{}", TYPE_HINT_TRUNCATION); 405 return write!(f, "{}", TYPE_HINT_TRUNCATION);
293 } 406 }
@@ -332,7 +445,7 @@ impl HirDisplay for Ty {
332fn write_bounds_like_dyn_trait( 445fn write_bounds_like_dyn_trait(
333 predicates: &[GenericPredicate], 446 predicates: &[GenericPredicate],
334 f: &mut HirFormatter, 447 f: &mut HirFormatter,
335) -> fmt::Result { 448) -> Result<(), HirDisplayError> {
336 // Note: This code is written to produce nice results (i.e. 449 // Note: This code is written to produce nice results (i.e.
337 // corresponding to surface Rust) for types that can occur in 450 // corresponding to surface Rust) for types that can occur in
338 // actual Rust. It will have weird results if the predicates 451 // actual Rust. It will have weird results if the predicates
@@ -394,7 +507,7 @@ fn write_bounds_like_dyn_trait(
394} 507}
395 508
396impl TraitRef { 509impl TraitRef {
397 fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> fmt::Result { 510 fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> {
398 if f.should_truncate() { 511 if f.should_truncate() {
399 return write!(f, "{}", TYPE_HINT_TRUNCATION); 512 return write!(f, "{}", TYPE_HINT_TRUNCATION);
400 } 513 }
@@ -416,19 +529,19 @@ impl TraitRef {
416} 529}
417 530
418impl HirDisplay for TraitRef { 531impl HirDisplay for TraitRef {
419 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { 532 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
420 self.hir_fmt_ext(f, false) 533 self.hir_fmt_ext(f, false)
421 } 534 }
422} 535}
423 536
424impl HirDisplay for &GenericPredicate { 537impl HirDisplay for &GenericPredicate {
425 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { 538 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
426 HirDisplay::hir_fmt(*self, f) 539 HirDisplay::hir_fmt(*self, f)
427 } 540 }
428} 541}
429 542
430impl HirDisplay for GenericPredicate { 543impl HirDisplay for GenericPredicate {
431 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { 544 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
432 if f.should_truncate() { 545 if f.should_truncate() {
433 return write!(f, "{}", TYPE_HINT_TRUNCATION); 546 return write!(f, "{}", TYPE_HINT_TRUNCATION);
434 } 547 }
@@ -452,15 +565,15 @@ impl HirDisplay for GenericPredicate {
452} 565}
453 566
454impl HirDisplay for Obligation { 567impl HirDisplay for Obligation {
455 fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result { 568 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
456 match self { 569 Ok(match self {
457 Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db)), 570 Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db))?,
458 Obligation::Projection(proj) => write!( 571 Obligation::Projection(proj) => write!(
459 f, 572 f,
460 "Normalize({} => {})", 573 "Normalize({} => {})",
461 proj.projection_ty.display(f.db), 574 proj.projection_ty.display(f.db),
462 proj.ty.display(f.db) 575 proj.ty.display(f.db)
463 ), 576 )?,
464 } 577 })
465 } 578 }
466} 579}
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index bd4ef69a0..957d6e0b5 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -22,13 +22,14 @@ use rustc_hash::FxHashMap;
22 22
23use hir_def::{ 23use hir_def::{
24 body::Body, 24 body::Body,
25 data::{ConstData, FunctionData}, 25 data::{ConstData, FunctionData, StaticData},
26 expr::{BindingAnnotation, ExprId, PatId}, 26 expr::{BindingAnnotation, ExprId, PatId},
27 lang_item::LangItemTarget, 27 lang_item::LangItemTarget,
28 path::{path, Path}, 28 path::{path, Path},
29 resolver::{HasResolver, Resolver, TypeNs}, 29 resolver::{HasResolver, Resolver, TypeNs},
30 type_ref::{Mutability, TypeRef}, 30 type_ref::{Mutability, TypeRef},
31 AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, TraitId, TypeAliasId, VariantId, 31 AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, TraitId, TypeAliasId,
32 VariantId,
32}; 33};
33use hir_expand::{diagnostics::DiagnosticSink, name::name}; 34use hir_expand::{diagnostics::DiagnosticSink, name::name};
34use ra_arena::map::ArenaMap; 35use ra_arena::map::ArenaMap;
@@ -71,7 +72,7 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
71 match def { 72 match def {
72 DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)), 73 DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
73 DefWithBodyId::FunctionId(f) => ctx.collect_fn(&db.function_data(f)), 74 DefWithBodyId::FunctionId(f) => ctx.collect_fn(&db.function_data(f)),
74 DefWithBodyId::StaticId(s) => ctx.collect_const(&db.static_data(s)), 75 DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
75 } 76 }
76 77
77 ctx.infer_body(); 78 ctx.infer_body();
@@ -210,6 +211,14 @@ struct InferenceContext<'a> {
210 /// closures, but currently this is the only field that will change there, 211 /// closures, but currently this is the only field that will change there,
211 /// so it doesn't make sense. 212 /// so it doesn't make sense.
212 return_ty: Ty, 213 return_ty: Ty,
214 diverges: Diverges,
215 breakables: Vec<BreakableContext>,
216}
217
218#[derive(Clone, Debug)]
219struct BreakableContext {
220 pub may_break: bool,
221 pub break_ty: Ty,
213} 222}
214 223
215impl<'a> InferenceContext<'a> { 224impl<'a> InferenceContext<'a> {
@@ -224,6 +233,8 @@ impl<'a> InferenceContext<'a> {
224 owner, 233 owner,
225 body: db.body(owner), 234 body: db.body(owner),
226 resolver, 235 resolver,
236 diverges: Diverges::Maybe,
237 breakables: Vec::new(),
227 } 238 }
228 } 239 }
229 240
@@ -429,43 +440,95 @@ impl<'a> InferenceContext<'a> {
429 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); 440 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
430 // FIXME: this should resolve assoc items as well, see this example: 441 // FIXME: this should resolve assoc items as well, see this example:
431 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 442 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
432 return match resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path.mod_path()) { 443 let (resolution, unresolved) =
433 Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { 444 match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
445 Some(it) => it,
446 None => return (Ty::Unknown, None),
447 };
448 return match resolution {
449 TypeNs::AdtId(AdtId::StructId(strukt)) => {
434 let substs = Ty::substs_from_path(&ctx, path, strukt.into()); 450 let substs = Ty::substs_from_path(&ctx, path, strukt.into());
435 let ty = self.db.ty(strukt.into()); 451 let ty = self.db.ty(strukt.into());
436 let ty = self.insert_type_vars(ty.subst(&substs)); 452 let ty = self.insert_type_vars(ty.subst(&substs));
437 (ty, Some(strukt.into())) 453 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
438 } 454 }
439 Some(TypeNs::EnumVariantId(var)) => { 455 TypeNs::EnumVariantId(var) => {
440 let substs = Ty::substs_from_path(&ctx, path, var.into()); 456 let substs = Ty::substs_from_path(&ctx, path, var.into());
441 let ty = self.db.ty(var.parent.into()); 457 let ty = self.db.ty(var.parent.into());
442 let ty = self.insert_type_vars(ty.subst(&substs)); 458 let ty = self.insert_type_vars(ty.subst(&substs));
443 (ty, Some(var.into())) 459 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
444 } 460 }
445 Some(TypeNs::SelfType(impl_id)) => { 461 TypeNs::SelfType(impl_id) => {
446 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 462 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
447 let substs = Substs::type_params_for_generics(&generics); 463 let substs = Substs::type_params_for_generics(&generics);
448 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 464 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
449 let variant = ty_variant(&ty); 465 match unresolved {
450 (ty, variant) 466 None => {
467 let variant = ty_variant(&ty);
468 (ty, variant)
469 }
470 Some(1) => {
471 let segment = path.mod_path().segments.last().unwrap();
472 // this could be an enum variant or associated type
473 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
474 let enum_data = self.db.enum_data(enum_id);
475 if let Some(local_id) = enum_data.variant(segment) {
476 let variant = EnumVariantId { parent: enum_id, local_id };
477 return (ty, Some(variant.into()));
478 }
479 }
480 // FIXME potentially resolve assoc type
481 (Ty::Unknown, None)
482 }
483 Some(_) => {
484 // FIXME diagnostic
485 (Ty::Unknown, None)
486 }
487 }
451 } 488 }
452 Some(TypeNs::TypeAliasId(it)) => { 489 TypeNs::TypeAliasId(it) => {
453 let substs = Substs::build_for_def(self.db, it) 490 let substs = Substs::build_for_def(self.db, it)
454 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 491 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
455 .build(); 492 .build();
456 let ty = self.db.ty(it.into()).subst(&substs); 493 let ty = self.db.ty(it.into()).subst(&substs);
457 let variant = ty_variant(&ty); 494 let variant = ty_variant(&ty);
458 (ty, variant) 495 forbid_unresolved_segments((ty, variant), unresolved)
496 }
497 TypeNs::AdtSelfType(_) => {
498 // FIXME this could happen in array size expressions, once we're checking them
499 (Ty::Unknown, None)
500 }
501 TypeNs::GenericParam(_) => {
502 // FIXME potentially resolve assoc type
503 (Ty::Unknown, None)
504 }
505 TypeNs::AdtId(AdtId::EnumId(_))
506 | TypeNs::AdtId(AdtId::UnionId(_))
507 | TypeNs::BuiltinType(_)
508 | TypeNs::TraitId(_) => {
509 // FIXME diagnostic
510 (Ty::Unknown, None)
459 } 511 }
460 Some(_) | None => (Ty::Unknown, None),
461 }; 512 };
462 513
514 fn forbid_unresolved_segments(
515 result: (Ty, Option<VariantId>),
516 unresolved: Option<usize>,
517 ) -> (Ty, Option<VariantId>) {
518 if unresolved.is_none() {
519 result
520 } else {
521 // FIXME diagnostic
522 (Ty::Unknown, None)
523 }
524 }
525
463 fn ty_variant(ty: &Ty) -> Option<VariantId> { 526 fn ty_variant(ty: &Ty) -> Option<VariantId> {
464 ty.as_adt().and_then(|(adt_id, _)| match adt_id { 527 ty.as_adt().and_then(|(adt_id, _)| match adt_id {
465 AdtId::StructId(s) => Some(VariantId::StructId(s)), 528 AdtId::StructId(s) => Some(VariantId::StructId(s)),
466 AdtId::UnionId(u) => Some(VariantId::UnionId(u)), 529 AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
467 AdtId::EnumId(_) => { 530 AdtId::EnumId(_) => {
468 // Error E0071, expected struct, variant or union type, found enum `Foo` 531 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
469 None 532 None
470 } 533 }
471 }) 534 })
@@ -476,6 +539,10 @@ impl<'a> InferenceContext<'a> {
476 self.return_ty = self.make_ty(&data.type_ref); 539 self.return_ty = self.make_ty(&data.type_ref);
477 } 540 }
478 541
542 fn collect_static(&mut self, data: &StaticData) {
543 self.return_ty = self.make_ty(&data.type_ref);
544 }
545
479 fn collect_fn(&mut self, data: &FunctionData) { 546 fn collect_fn(&mut self, data: &FunctionData) {
480 let body = Arc::clone(&self.body); // avoid borrow checker problem 547 let body = Arc::clone(&self.body); // avoid borrow checker problem
481 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) 548 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
@@ -666,15 +733,57 @@ impl Expectation {
666 } 733 }
667} 734}
668 735
736#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
737enum Diverges {
738 Maybe,
739 Always,
740}
741
742impl Diverges {
743 fn is_always(self) -> bool {
744 self == Diverges::Always
745 }
746}
747
748impl std::ops::BitAnd for Diverges {
749 type Output = Self;
750 fn bitand(self, other: Self) -> Self {
751 std::cmp::min(self, other)
752 }
753}
754
755impl std::ops::BitOr for Diverges {
756 type Output = Self;
757 fn bitor(self, other: Self) -> Self {
758 std::cmp::max(self, other)
759 }
760}
761
762impl std::ops::BitAndAssign for Diverges {
763 fn bitand_assign(&mut self, other: Self) {
764 *self = *self & other;
765 }
766}
767
768impl std::ops::BitOrAssign for Diverges {
769 fn bitor_assign(&mut self, other: Self) {
770 *self = *self | other;
771 }
772}
773
669mod diagnostics { 774mod diagnostics {
670 use hir_def::{expr::ExprId, FunctionId}; 775 use hir_def::{expr::ExprId, FunctionId};
671 use hir_expand::diagnostics::DiagnosticSink; 776 use hir_expand::diagnostics::DiagnosticSink;
672 777
673 use crate::{db::HirDatabase, diagnostics::NoSuchField}; 778 use crate::{
779 db::HirDatabase,
780 diagnostics::{BreakOutsideOfLoop, NoSuchField},
781 };
674 782
675 #[derive(Debug, PartialEq, Eq, Clone)] 783 #[derive(Debug, PartialEq, Eq, Clone)]
676 pub(super) enum InferenceDiagnostic { 784 pub(super) enum InferenceDiagnostic {
677 NoSuchField { expr: ExprId, field: usize }, 785 NoSuchField { expr: ExprId, field: usize },
786 BreakOutsideOfLoop { expr: ExprId },
678 } 787 }
679 788
680 impl InferenceDiagnostic { 789 impl InferenceDiagnostic {
@@ -690,6 +799,13 @@ mod diagnostics {
690 let field = source_map.field_syntax(*expr, *field); 799 let field = source_map.field_syntax(*expr, *field);
691 sink.push(NoSuchField { file: field.file_id, field: field.value }) 800 sink.push(NoSuchField { file: field.file_id, field: field.value })
692 } 801 }
802 InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
803 let (_, source_map) = db.body_with_source_map(owner.into());
804 let ptr = source_map
805 .expr_syntax(*expr)
806 .expect("break outside of loop in synthetic syntax");
807 sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value })
808 }
693 } 809 }
694 } 810 }
695 } 811 }
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 89200255a..2ee9adb16 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -5,7 +5,7 @@
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See: https://doc.rust-lang.org/nomicon/coercions.html
6 6
7use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; 7use hir_def::{lang_item::LangItemTarget, type_ref::Mutability};
8use test_utils::tested_by; 8use test_utils::mark;
9 9
10use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor}; 10use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty, TypeCtor};
11 11
@@ -20,21 +20,35 @@ impl<'a> InferenceContext<'a> {
20 self.coerce_inner(from_ty, &to_ty) 20 self.coerce_inner(from_ty, &to_ty)
21 } 21 }
22 22
23 /// Merge two types from different branches, with possible implicit coerce. 23 /// Merge two types from different branches, with possible coercion.
24 /// 24 ///
25 /// Note that it is only possible that one type are coerced to another. 25 /// Mostly this means trying to coerce one to the other, but
26 /// Coercing both types to another least upper bound type is not possible in rustc, 26 /// - if we have two function types for different functions, we need to
27 /// which will simply result in "incompatible types" error. 27 /// coerce both to function pointers;
28 /// - if we were concerned with lifetime subtyping, we'd need to look for a
29 /// least upper bound.
28 pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty { 30 pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty {
29 if self.coerce(ty1, ty2) { 31 if self.coerce(ty1, ty2) {
30 ty2.clone() 32 ty2.clone()
31 } else if self.coerce(ty2, ty1) { 33 } else if self.coerce(ty2, ty1) {
32 ty1.clone() 34 ty1.clone()
33 } else { 35 } else {
34 tested_by!(coerce_merge_fail_fallback); 36 if let (ty_app!(TypeCtor::FnDef(_)), ty_app!(TypeCtor::FnDef(_))) = (ty1, ty2) {
35 // For incompatible types, we use the latter one as result 37 mark::hit!(coerce_fn_reification);
36 // to be better recovery for `if` without `else`. 38 // Special case: two function types. Try to coerce both to
37 ty2.clone() 39 // pointers to have a chance at getting a match. See
40 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
41 let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig");
42 let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig");
43 let ptr_ty1 = Ty::fn_ptr(sig1);
44 let ptr_ty2 = Ty::fn_ptr(sig2);
45 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2)
46 } else {
47 mark::hit!(coerce_merge_fail_fallback);
48 // For incompatible types, we use the latter one as result
49 // to be better recovery for `if` without `else`.
50 ty2.clone()
51 }
38 } 52 }
39 } 53 }
40 54
@@ -84,9 +98,7 @@ impl<'a> InferenceContext<'a> {
84 match from_ty.callable_sig(self.db) { 98 match from_ty.callable_sig(self.db) {
85 None => return false, 99 None => return false,
86 Some(sig) => { 100 Some(sig) => {
87 let num_args = sig.params_and_return.len() as u16 - 1; 101 from_ty = Ty::fn_ptr(sig);
88 from_ty =
89 Ty::apply(TypeCtor::FnPtr { num_args }, Substs(sig.params_and_return));
90 } 102 }
91 } 103 }
92 } 104 }
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index efc60986b..b28724f0e 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -1,7 +1,7 @@
1//! Type inference for expressions. 1//! Type inference for expressions.
2 2
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::sync::Arc; 4use std::{mem, sync::Arc};
5 5
6use hir_def::{ 6use hir_def::{
7 builtin_type::Signedness, 7 builtin_type::Signedness,
@@ -21,11 +21,18 @@ use crate::{
21 Ty, TypeCtor, Uncertain, 21 Ty, TypeCtor, Uncertain,
22}; 22};
23 23
24use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 24use super::{
25 BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, InferenceDiagnostic,
26 TypeMismatch,
27};
25 28
26impl<'a> InferenceContext<'a> { 29impl<'a> InferenceContext<'a> {
27 pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 30 pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
28 let ty = self.infer_expr_inner(tgt_expr, expected); 31 let ty = self.infer_expr_inner(tgt_expr, expected);
32 if ty.is_never() {
33 // Any expression that produces a value of type `!` must have diverged
34 self.diverges = Diverges::Always;
35 }
29 let could_unify = self.unify(&ty, &expected.ty); 36 let could_unify = self.unify(&ty, &expected.ty);
30 if !could_unify { 37 if !could_unify {
31 self.result.type_mismatches.insert( 38 self.result.type_mismatches.insert(
@@ -64,34 +71,68 @@ impl<'a> InferenceContext<'a> {
64 // if let is desugared to match, so this is always simple if 71 // if let is desugared to match, so this is always simple if
65 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 72 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
66 73
74 let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
75 let mut both_arms_diverge = Diverges::Always;
76
67 let then_ty = self.infer_expr_inner(*then_branch, &expected); 77 let then_ty = self.infer_expr_inner(*then_branch, &expected);
78 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
68 let else_ty = match else_branch { 79 let else_ty = match else_branch {
69 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), 80 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected),
70 None => Ty::unit(), 81 None => Ty::unit(),
71 }; 82 };
83 both_arms_diverge &= self.diverges;
84
85 self.diverges = condition_diverges | both_arms_diverge;
72 86
73 self.coerce_merge_branch(&then_ty, &else_ty) 87 self.coerce_merge_branch(&then_ty, &else_ty)
74 } 88 }
75 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), 89 Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected),
90 Expr::TryBlock { body } => {
91 let _inner = self.infer_expr(*body, expected);
92 // FIXME should be std::result::Result<{inner}, _>
93 Ty::Unknown
94 }
76 Expr::Loop { body } => { 95 Expr::Loop { body } => {
96 self.breakables.push(BreakableContext {
97 may_break: false,
98 break_ty: self.table.new_type_var(),
99 });
77 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 100 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
78 // FIXME handle break with value 101
79 Ty::simple(TypeCtor::Never) 102 let ctxt = self.breakables.pop().expect("breakable stack broken");
103 if ctxt.may_break {
104 self.diverges = Diverges::Maybe;
105 }
106
107 if ctxt.may_break {
108 ctxt.break_ty
109 } else {
110 Ty::simple(TypeCtor::Never)
111 }
80 } 112 }
81 Expr::While { condition, body } => { 113 Expr::While { condition, body } => {
114 self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown });
82 // while let is desugared to a match loop, so this is always simple while 115 // while let is desugared to a match loop, so this is always simple while
83 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool))); 116 self.infer_expr(*condition, &Expectation::has_type(Ty::simple(TypeCtor::Bool)));
84 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 117 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
118 let _ctxt = self.breakables.pop().expect("breakable stack broken");
119 // the body may not run, so it diverging doesn't mean we diverge
120 self.diverges = Diverges::Maybe;
85 Ty::unit() 121 Ty::unit()
86 } 122 }
87 Expr::For { iterable, body, pat } => { 123 Expr::For { iterable, body, pat } => {
88 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 124 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
89 125
126 self.breakables.push(BreakableContext { may_break: false, break_ty: Ty::Unknown });
90 let pat_ty = 127 let pat_ty =
91 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); 128 self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
92 129
93 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 130 self.infer_pat(*pat, &pat_ty, BindingMode::default());
131
94 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 132 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
133 let _ctxt = self.breakables.pop().expect("breakable stack broken");
134 // the body may not run, so it diverging doesn't mean we diverge
135 self.diverges = Diverges::Maybe;
95 Ty::unit() 136 Ty::unit()
96 } 137 }
97 Expr::Lambda { body, args, ret_type, arg_types } => { 138 Expr::Lambda { body, args, ret_type, arg_types } => {
@@ -127,10 +168,12 @@ impl<'a> InferenceContext<'a> {
127 // infer the body. 168 // infer the body.
128 self.coerce(&closure_ty, &expected.ty); 169 self.coerce(&closure_ty, &expected.ty);
129 170
130 let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone()); 171 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
172 let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
131 173
132 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); 174 self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
133 175
176 self.diverges = prev_diverges;
134 self.return_ty = prev_ret_ty; 177 self.return_ty = prev_ret_ty;
135 178
136 closure_ty 179 closure_ty
@@ -160,7 +203,11 @@ impl<'a> InferenceContext<'a> {
160 self.table.new_type_var() 203 self.table.new_type_var()
161 }; 204 };
162 205
206 let matchee_diverges = self.diverges;
207 let mut all_arms_diverge = Diverges::Always;
208
163 for arm in arms { 209 for arm in arms {
210 self.diverges = Diverges::Maybe;
164 let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default()); 211 let _pat_ty = self.infer_pat(arm.pat, &input_ty, BindingMode::default());
165 if let Some(guard_expr) = arm.guard { 212 if let Some(guard_expr) = arm.guard {
166 self.infer_expr( 213 self.infer_expr(
@@ -170,9 +217,12 @@ impl<'a> InferenceContext<'a> {
170 } 217 }
171 218
172 let arm_ty = self.infer_expr_inner(arm.expr, &expected); 219 let arm_ty = self.infer_expr_inner(arm.expr, &expected);
220 all_arms_diverge &= self.diverges;
173 result_ty = self.coerce_merge_branch(&result_ty, &arm_ty); 221 result_ty = self.coerce_merge_branch(&result_ty, &arm_ty);
174 } 222 }
175 223
224 self.diverges = matchee_diverges | all_arms_diverge;
225
176 result_ty 226 result_ty
177 } 227 }
178 Expr::Path(p) => { 228 Expr::Path(p) => {
@@ -182,10 +232,29 @@ impl<'a> InferenceContext<'a> {
182 } 232 }
183 Expr::Continue => Ty::simple(TypeCtor::Never), 233 Expr::Continue => Ty::simple(TypeCtor::Never),
184 Expr::Break { expr } => { 234 Expr::Break { expr } => {
185 if let Some(expr) = expr { 235 let val_ty = if let Some(expr) = expr {
186 // FIXME handle break with value 236 self.infer_expr(*expr, &Expectation::none())
187 self.infer_expr(*expr, &Expectation::none()); 237 } else {
238 Ty::unit()
239 };
240
241 let last_ty = if let Some(ctxt) = self.breakables.last() {
242 ctxt.break_ty.clone()
243 } else {
244 Ty::Unknown
245 };
246
247 let merged_type = self.coerce_merge_branch(&last_ty, &val_ty);
248
249 if let Some(ctxt) = self.breakables.last_mut() {
250 ctxt.break_ty = merged_type;
251 ctxt.may_break = true;
252 } else {
253 self.push_diagnostic(InferenceDiagnostic::BreakOutsideOfLoop {
254 expr: tgt_expr,
255 });
188 } 256 }
257
189 Ty::simple(TypeCtor::Never) 258 Ty::simple(TypeCtor::Never)
190 } 259 }
191 Expr::Return { expr } => { 260 Expr::Return { expr } => {
@@ -496,8 +565,8 @@ impl<'a> InferenceContext<'a> {
496 } 565 }
497 Literal::ByteString(..) => { 566 Literal::ByteString(..) => {
498 let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8()))); 567 let byte_type = Ty::simple(TypeCtor::Int(Uncertain::Known(IntTy::u8())));
499 let slice_type = Ty::apply_one(TypeCtor::Slice, byte_type); 568 let array_type = Ty::apply_one(TypeCtor::Array, byte_type);
500 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), slice_type) 569 Ty::apply_one(TypeCtor::Ref(Mutability::Shared), array_type)
501 } 570 }
502 Literal::Char(..) => Ty::simple(TypeCtor::Char), 571 Literal::Char(..) => Ty::simple(TypeCtor::Char),
503 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())), 572 Literal::Int(_v, ty) => Ty::simple(TypeCtor::Int((*ty).into())),
@@ -517,7 +586,6 @@ impl<'a> InferenceContext<'a> {
517 tail: Option<ExprId>, 586 tail: Option<ExprId>,
518 expected: &Expectation, 587 expected: &Expectation,
519 ) -> Ty { 588 ) -> Ty {
520 let mut diverges = false;
521 for stmt in statements { 589 for stmt in statements {
522 match stmt { 590 match stmt {
523 Statement::Let { pat, type_ref, initializer } => { 591 Statement::Let { pat, type_ref, initializer } => {
@@ -539,9 +607,7 @@ impl<'a> InferenceContext<'a> {
539 self.infer_pat(*pat, &ty, BindingMode::default()); 607 self.infer_pat(*pat, &ty, BindingMode::default());
540 } 608 }
541 Statement::Expr(expr) => { 609 Statement::Expr(expr) => {
542 if let ty_app!(TypeCtor::Never) = self.infer_expr(*expr, &Expectation::none()) { 610 self.infer_expr(*expr, &Expectation::none());
543 diverges = true;
544 }
545 } 611 }
546 } 612 }
547 } 613 }
@@ -549,14 +615,22 @@ impl<'a> InferenceContext<'a> {
549 let ty = if let Some(expr) = tail { 615 let ty = if let Some(expr) = tail {
550 self.infer_expr_coerce(expr, expected) 616 self.infer_expr_coerce(expr, expected)
551 } else { 617 } else {
552 self.coerce(&Ty::unit(), expected.coercion_target()); 618 // Citing rustc: if there is no explicit tail expression,
553 Ty::unit() 619 // that is typically equivalent to a tail expression
620 // of `()` -- except if the block diverges. In that
621 // case, there is no value supplied from the tail
622 // expression (assuming there are no other breaks,
623 // this implies that the type of the block will be
624 // `!`).
625 if self.diverges.is_always() {
626 // we don't even make an attempt at coercion
627 self.table.new_maybe_never_type_var()
628 } else {
629 self.coerce(&Ty::unit(), expected.coercion_target());
630 Ty::unit()
631 }
554 }; 632 };
555 if diverges { 633 ty
556 Ty::simple(TypeCtor::Never)
557 } else {
558 ty
559 }
560 } 634 }
561 635
562 fn infer_method_call( 636 fn infer_method_call(
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index 54ec870df..4006f595d 100644
--- a/crates/ra_hir_ty/src/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -10,7 +10,7 @@ use hir_def::{
10 FieldId, 10 FieldId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use test_utils::tested_by; 13use test_utils::mark;
14 14
15use super::{BindingMode, Expectation, InferenceContext}; 15use super::{BindingMode, Expectation, InferenceContext};
16use crate::{utils::variant_data, Substs, Ty, TypeCtor}; 16use crate::{utils::variant_data, Substs, Ty, TypeCtor};
@@ -111,7 +111,7 @@ impl<'a> InferenceContext<'a> {
111 } 111 }
112 } 112 }
113 } else if let Pat::Ref { .. } = &body[pat] { 113 } else if let Pat::Ref { .. } = &body[pat] {
114 tested_by!(match_ergonomics_ref); 114 mark::hit!(match_ergonomics_ref);
115 // When you encounter a `&pat` pattern, reset to Move. 115 // When you encounter a `&pat` pattern, reset to Move.
116 // This is so that `w` is by value: `let (_, &w) = &(1, &2);` 116 // This is so that `w` is by value: `let (_, &w) = &(1, &2);`
117 default_bm = BindingMode::Move; 117 default_bm = BindingMode::Move;
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index 2b6bc0f79..1c2e56fb0 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -5,7 +5,7 @@ use std::iter;
5use hir_def::{ 5use hir_def::{
6 path::{Path, PathSegment}, 6 path::{Path, PathSegment},
7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
8 AssocContainerId, AssocItemId, Lookup, 8 AdtId, AssocContainerId, AssocItemId, EnumVariantId, Lookup,
9}; 9};
10use hir_expand::name::Name; 10use hir_expand::name::Name;
11 11
@@ -77,6 +77,18 @@ impl<'a> InferenceContext<'a> {
77 77
78 it.into() 78 it.into()
79 } 79 }
80 ValueNs::ImplSelf(impl_id) => {
81 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
82 let substs = Substs::type_params_for_generics(&generics);
83 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
84 if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() {
85 let ty = self.db.value_ty(struct_id.into()).subst(&substs);
86 return Some(ty);
87 } else {
88 // FIXME: diagnostic, invalid Self reference
89 return None;
90 }
91 }
80 }; 92 };
81 93
82 let ty = self.db.value_ty(typable); 94 let ty = self.db.value_ty(typable);
@@ -199,6 +211,10 @@ impl<'a> InferenceContext<'a> {
199 return None; 211 return None;
200 } 212 }
201 213
214 if let Some(result) = self.resolve_enum_variant_on_ty(&ty, name, id) {
215 return Some(result);
216 }
217
202 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); 218 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
203 let krate = self.resolver.krate()?; 219 let krate = self.resolver.krate()?;
204 let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast()); 220 let traits_in_scope = self.resolver.traits_in_scope(self.db.upcast());
@@ -250,4 +266,21 @@ impl<'a> InferenceContext<'a> {
250 }, 266 },
251 ) 267 )
252 } 268 }
269
270 fn resolve_enum_variant_on_ty(
271 &mut self,
272 ty: &Ty,
273 name: &Name,
274 id: ExprOrPatId,
275 ) -> Option<(ValueNs, Option<Substs>)> {
276 let (enum_id, subst) = match ty.as_adt() {
277 Some((AdtId::EnumId(e), subst)) => (e, subst),
278 _ => return None,
279 };
280 let enum_data = self.db.enum_data(enum_id);
281 let local_id = enum_data.variant(name)?;
282 let variant = EnumVariantId { parent: enum_id, local_id };
283 self.write_variant_resolution(id, variant.into());
284 Some((ValueNs::EnumVariantId(variant), Some(subst.clone())))
285 }
253} 286}
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index ab0bc8b70..269495ca0 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -4,7 +4,7 @@ use std::borrow::Cow;
4 4
5use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 5use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
6 6
7use test_utils::tested_by; 7use test_utils::mark;
8 8
9use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
10use crate::{ 10use crate::{
@@ -313,7 +313,7 @@ impl InferenceTable {
313 // more than once 313 // more than once
314 for i in 0..3 { 314 for i in 0..3 {
315 if i > 0 { 315 if i > 0 {
316 tested_by!(type_var_resolves_to_int_var); 316 mark::hit!(type_var_resolves_to_int_var);
317 } 317 }
318 match &*ty { 318 match &*ty {
319 Ty::Infer(tv) => { 319 Ty::Infer(tv) => {
@@ -342,7 +342,7 @@ impl InferenceTable {
342 Ty::Infer(tv) => { 342 Ty::Infer(tv) => {
343 let inner = tv.to_inner(); 343 let inner = tv.to_inner();
344 if tv_stack.contains(&inner) { 344 if tv_stack.contains(&inner) {
345 tested_by!(type_var_cycles_resolve_as_possible); 345 mark::hit!(type_var_cycles_resolve_as_possible);
346 // recursive type 346 // recursive type
347 return tv.fallback_value(); 347 return tv.fallback_value();
348 } 348 }
@@ -369,7 +369,7 @@ impl InferenceTable {
369 Ty::Infer(tv) => { 369 Ty::Infer(tv) => {
370 let inner = tv.to_inner(); 370 let inner = tv.to_inner();
371 if tv_stack.contains(&inner) { 371 if tv_stack.contains(&inner) {
372 tested_by!(type_var_cycles_resolve_completely); 372 mark::hit!(type_var_cycles_resolve_completely);
373 // recursive type 373 // recursive type
374 return tv.fallback_value(); 374 return tv.fallback_value();
375 } 375 }
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index a6f56c661..c87ee06ce 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -42,7 +42,6 @@ pub mod expr;
42mod tests; 42mod tests;
43#[cfg(test)] 43#[cfg(test)]
44mod test_db; 44mod test_db;
45mod marks;
46mod _match; 45mod _match;
47 46
48use std::ops::Deref; 47use std::ops::Deref;
@@ -427,6 +426,11 @@ impl Substs {
427 } 426 }
428} 427}
429 428
429/// Return an index of a parameter in the generic type parameter list by it's id.
430pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
431 generics(db.upcast(), id.parent).param_idx(id)
432}
433
430#[derive(Debug, Clone)] 434#[derive(Debug, Clone)]
431pub struct SubstsBuilder { 435pub struct SubstsBuilder {
432 vec: Vec<Ty>, 436 vec: Vec<Ty>,
@@ -683,6 +687,12 @@ impl Ty {
683 pub fn unit() -> Self { 687 pub fn unit() -> Self {
684 Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty()) 688 Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty())
685 } 689 }
690 pub fn fn_ptr(sig: FnSig) -> Self {
691 Ty::apply(
692 TypeCtor::FnPtr { num_args: sig.params().len() as u16 },
693 Substs(sig.params_and_return),
694 )
695 }
686 696
687 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 697 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
688 match self { 698 match self {
@@ -730,6 +740,10 @@ impl Ty {
730 } 740 }
731 } 741 }
732 742
743 pub fn is_never(&self) -> bool {
744 matches!(self, Ty::Apply(ApplicationTy { ctor: TypeCtor::Never, .. }))
745 }
746
733 /// If this is a `dyn Trait` type, this returns the `Trait` part. 747 /// If this is a `dyn Trait` type, this returns the `Trait` part.
734 pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { 748 pub fn dyn_trait_ref(&self) -> Option<&TraitRef> {
735 match self { 749 match self {
@@ -793,15 +807,13 @@ impl Ty {
793 } 807 }
794 } 808 }
795 809
796 /// If this is an `impl Trait` or `dyn Trait`, returns that trait. 810 /// If this is a `dyn Trait`, returns that trait.
797 pub fn inherent_trait(&self) -> Option<TraitId> { 811 pub fn dyn_trait(&self) -> Option<TraitId> {
798 match self { 812 match self {
799 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 813 Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred {
800 predicates.iter().find_map(|pred| match pred { 814 GenericPredicate::Implemented(tr) => Some(tr.trait_),
801 GenericPredicate::Implemented(tr) => Some(tr.trait_), 815 _ => None,
802 _ => None, 816 }),
803 })
804 }
805 _ => None, 817 _ => None,
806 } 818 }
807 } 819 }
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 9ad6dbe07..35ac86a46 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -812,7 +812,7 @@ impl TraitEnvironment {
812 // add `Self: Trait<T1, T2, ...>` to the environment in trait 812 // add `Self: Trait<T1, T2, ...>` to the environment in trait
813 // function default implementations (and hypothetical code 813 // function default implementations (and hypothetical code
814 // inside consts or type aliases) 814 // inside consts or type aliases)
815 test_utils::tested_by!(trait_self_implements_self); 815 test_utils::mark::hit!(trait_self_implements_self);
816 let substs = Substs::type_params(db, trait_id); 816 let substs = Substs::type_params(db, trait_id);
817 let trait_ref = TraitRef { trait_: trait_id, substs }; 817 let trait_ref = TraitRef { trait_: trait_id, substs };
818 let pred = GenericPredicate::Implemented(trait_ref); 818 let pred = GenericPredicate::Implemented(trait_ref);
diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs
deleted file mode 100644
index de5cb1d6b..000000000
--- a/crates/ra_hir_ty/src/marks.rs
+++ /dev/null
@@ -1,11 +0,0 @@
1//! See test_utils/src/marks.rs
2
3test_utils::marks!(
4 type_var_cycles_resolve_completely
5 type_var_cycles_resolve_as_possible
6 type_var_resolves_to_int_var
7 impl_self_type_match_without_receiver
8 match_ergonomics_ref
9 coerce_merge_fail_fallback
10 trait_self_implements_self
11);
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 657284fd0..e19628fdf 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -408,8 +408,9 @@ fn iterate_trait_method_candidates<T>(
408 receiver_ty: Option<&Canonical<Ty>>, 408 receiver_ty: Option<&Canonical<Ty>>,
409 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 409 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
410) -> Option<T> { 410) -> Option<T> {
411 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope 411 // if ty is `dyn Trait`, the trait doesn't need to be in scope
412 let inherent_trait = self_ty.value.inherent_trait().into_iter(); 412 let inherent_trait =
413 self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
413 let env_traits = if let Ty::Placeholder(_) = self_ty.value { 414 let env_traits = if let Ty::Placeholder(_) = self_ty.value {
414 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope 415 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
415 env.trait_predicates_for_self_ty(&self_ty.value) 416 env.trait_predicates_for_self_ty(&self_ty.value)
@@ -468,7 +469,7 @@ fn iterate_inherent_methods<T>(
468 // already happens in `is_valid_candidate` above; if not, we 469 // already happens in `is_valid_candidate` above; if not, we
469 // check it here 470 // check it here
470 if receiver_ty.is_none() && inherent_impl_substs(db, impl_def, self_ty).is_none() { 471 if receiver_ty.is_none() && inherent_impl_substs(db, impl_def, self_ty).is_none() {
471 test_utils::tested_by!(impl_self_type_match_without_receiver); 472 test_utils::mark::hit!(impl_self_type_match_without_receiver);
472 continue; 473 continue;
473 } 474 }
474 if let Some(result) = callback(&self_ty.value, item) { 475 if let Some(result) = callback(&self_ty.value, item) {
@@ -601,11 +602,6 @@ pub fn implements_trait(
601 krate: CrateId, 602 krate: CrateId,
602 trait_: TraitId, 603 trait_: TraitId,
603) -> bool { 604) -> bool {
604 if ty.value.inherent_trait() == Some(trait_) {
605 // FIXME this is a bit of a hack, since Chalk should say the same thing
606 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
607 return true;
608 }
609 let goal = generic_implements_goal(db, env, trait_, ty.clone()); 605 let goal = generic_implements_goal(db, env, trait_, ty.clone());
610 let solution = db.trait_solve(krate, goal); 606 let solution = db.trait_solve(krate, goal);
611 607
diff --git a/crates/ra_hir_ty/src/op.rs b/crates/ra_hir_ty/src/op.rs
index 54e2bd05a..0870874fc 100644
--- a/crates/ra_hir_ty/src/op.rs
+++ b/crates/ra_hir_ty/src/op.rs
@@ -30,7 +30,8 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
30pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { 30pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
31 match op { 31 match op {
32 BinaryOp::LogicOp(..) => Ty::simple(TypeCtor::Bool), 32 BinaryOp::LogicOp(..) => Ty::simple(TypeCtor::Bool),
33 BinaryOp::Assignment { op: None } | BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty { 33 BinaryOp::Assignment { op: None } => lhs_ty,
34 BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty {
34 Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { 35 Ty::Apply(ApplicationTy { ctor, .. }) => match ctor {
35 TypeCtor::Int(..) 36 TypeCtor::Int(..)
36 | TypeCtor::Float(..) 37 | TypeCtor::Float(..)
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 588d81282..1fe05c70c 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -6,6 +6,7 @@ mod patterns;
6mod traits; 6mod traits;
7mod method_resolution; 7mod method_resolution;
8mod macros; 8mod macros;
9mod display_source_code;
9 10
10use std::sync::Arc; 11use std::sync::Arc;
11 12
@@ -16,7 +17,7 @@ use hir_def::{
16 item_scope::ItemScope, 17 item_scope::ItemScope,
17 keys, 18 keys,
18 nameres::CrateDefMap, 19 nameres::CrateDefMap,
19 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, 20 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, ModuleId,
20}; 21};
21use hir_expand::{db::AstDatabase, InFile}; 22use hir_expand::{db::AstDatabase, InFile};
22use insta::assert_snapshot; 23use insta::assert_snapshot;
@@ -37,6 +38,18 @@ use crate::{
37// update the snapshots. 38// update the snapshots.
38 39
39fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { 40fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
41 type_at_pos_displayed(db, pos, |ty, _| ty.display(db).to_string())
42}
43
44fn displayed_source_at_pos(db: &TestDB, pos: FilePosition) -> String {
45 type_at_pos_displayed(db, pos, |ty, module_id| ty.display_source_code(db, module_id).unwrap())
46}
47
48fn type_at_pos_displayed(
49 db: &TestDB,
50 pos: FilePosition,
51 display_fn: impl FnOnce(&Ty, ModuleId) -> String,
52) -> String {
40 let file = db.parse(pos.file_id).ok().unwrap(); 53 let file = db.parse(pos.file_id).ok().unwrap();
41 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 54 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
42 let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); 55 let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
@@ -49,7 +62,7 @@ fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
49 if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { 62 if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) {
50 let infer = db.infer(func.into()); 63 let infer = db.infer(func.into());
51 let ty = &infer[expr_id]; 64 let ty = &infer[expr_id];
52 return ty.display(db).to_string(); 65 return display_fn(ty, module);
53 } 66 }
54 panic!("Can't find expression") 67 panic!("Can't find expression")
55} 68}
@@ -361,6 +374,33 @@ fn no_such_field_with_feature_flag_diagnostics() {
361} 374}
362 375
363#[test] 376#[test]
377fn no_such_field_enum_with_feature_flag_diagnostics() {
378 let diagnostics = TestDB::with_files(
379 r#"
380 //- /lib.rs crate:foo cfg:feature=foo
381 enum Foo {
382 #[cfg(not(feature = "foo"))]
383 Buz,
384 #[cfg(feature = "foo")]
385 Bar,
386 Baz
387 }
388
389 fn test_fn(f: Foo) {
390 match f {
391 Foo::Bar => {},
392 Foo::Baz => {},
393 }
394 }
395 "#,
396 )
397 .diagnostics()
398 .0;
399
400 assert_snapshot!(diagnostics, @r###""###);
401}
402
403#[test]
364fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() { 404fn no_such_field_with_feature_flag_diagnostics_on_struct_lit() {
365 let diagnostics = TestDB::with_files( 405 let diagnostics = TestDB::with_files(
366 r#" 406 r#"
@@ -491,3 +531,21 @@ fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
491 531
492 assert_snapshot!(diagnostics, @""); 532 assert_snapshot!(diagnostics, @"");
493} 533}
534
535#[test]
536fn break_outside_of_loop() {
537 let diagnostics = TestDB::with_files(
538 r"
539 //- /lib.rs
540 fn foo() {
541 break;
542 }
543 ",
544 )
545 .diagnostics()
546 .0;
547
548 assert_snapshot!(diagnostics, @r###""break": break outside of loop
549 "###
550 );
551}
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index e6fb3e123..2cc4f4bf9 100644
--- a/crates/ra_hir_ty/src/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
@@ -1,6 +1,6 @@
1use super::infer_with_mismatches; 1use super::infer_with_mismatches;
2use insta::assert_snapshot; 2use insta::assert_snapshot;
3use test_utils::covers; 3use test_utils::mark;
4 4
5// Infer with some common definitions and impls. 5// Infer with some common definitions and impls.
6fn infer(source: &str) -> String { 6fn infer(source: &str) -> String {
@@ -339,7 +339,7 @@ fn test(i: i32) {
339 339
340#[test] 340#[test]
341fn coerce_merge_one_by_one1() { 341fn coerce_merge_one_by_one1() {
342 covers!(coerce_merge_fail_fallback); 342 mark::check!(coerce_merge_fail_fallback);
343 343
344 assert_snapshot!( 344 assert_snapshot!(
345 infer(r#" 345 infer(r#"
@@ -384,7 +384,7 @@ fn foo() -> u32 {
384} 384}
385"#, true), 385"#, true),
386 @r###" 386 @r###"
387 17..40 '{ ...own; }': ! 387 17..40 '{ ...own; }': u32
388 23..37 'return unknown': ! 388 23..37 'return unknown': !
389 30..37 'unknown': u32 389 30..37 'unknown': u32
390 "### 390 "###
@@ -514,7 +514,7 @@ fn foo() {
514 27..103 '{ ... }': &u32 514 27..103 '{ ... }': &u32
515 37..82 'if tru... }': () 515 37..82 'if tru... }': ()
516 40..44 'true': bool 516 40..44 'true': bool
517 45..82 '{ ... }': ! 517 45..82 '{ ... }': ()
518 59..71 'return &1u32': ! 518 59..71 'return &1u32': !
519 66..71 '&1u32': &u32 519 66..71 '&1u32': &u32
520 67..71 '1u32': u32 520 67..71 '1u32': u32
@@ -546,6 +546,48 @@ fn test() {
546} 546}
547 547
548#[test] 548#[test]
549fn coerce_fn_items_in_match_arms() {
550 mark::check!(coerce_fn_reification);
551 assert_snapshot!(
552 infer_with_mismatches(r#"
553fn foo1(x: u32) -> isize { 1 }
554fn foo2(x: u32) -> isize { 2 }
555fn foo3(x: u32) -> isize { 3 }
556fn test() {
557 let x = match 1 {
558 1 => foo1,
559 2 => foo2,
560 _ => foo3,
561 };
562}
563"#, true),
564 @r###"
565 9..10 'x': u32
566 26..31 '{ 1 }': isize
567 28..29 '1': isize
568 40..41 'x': u32
569 57..62 '{ 2 }': isize
570 59..60 '2': isize
571 71..72 'x': u32
572 88..93 '{ 3 }': isize
573 90..91 '3': isize
574 104..193 '{ ... }; }': ()
575 114..115 'x': fn(u32) -> isize
576 118..190 'match ... }': fn(u32) -> isize
577 124..125 '1': i32
578 136..137 '1': i32
579 136..137 '1': i32
580 141..145 'foo1': fn foo1(u32) -> isize
581 155..156 '2': i32
582 155..156 '2': i32
583 160..164 'foo2': fn foo2(u32) -> isize
584 174..175 '_': i32
585 179..183 'foo3': fn foo3(u32) -> isize
586 "###
587 );
588}
589
590#[test]
549fn coerce_closure_to_fn_ptr() { 591fn coerce_closure_to_fn_ptr() {
550 assert_snapshot!( 592 assert_snapshot!(
551 infer_with_mismatches(r#" 593 infer_with_mismatches(r#"
diff --git a/crates/ra_hir_ty/src/tests/display_source_code.rs b/crates/ra_hir_ty/src/tests/display_source_code.rs
new file mode 100644
index 000000000..4088b1d22
--- /dev/null
+++ b/crates/ra_hir_ty/src/tests/display_source_code.rs
@@ -0,0 +1,50 @@
1use super::displayed_source_at_pos;
2use crate::test_db::TestDB;
3use ra_db::fixture::WithFixture;
4
5#[test]
6fn qualify_path_to_submodule() {
7 let (db, pos) = TestDB::with_position(
8 r#"
9//- /main.rs
10
11mod foo {
12 pub struct Foo;
13}
14
15fn bar() {
16 let foo: foo::Foo = foo::Foo;
17 foo<|>
18}
19
20"#,
21 );
22 assert_eq!("foo::Foo", displayed_source_at_pos(&db, pos));
23}
24
25#[test]
26fn omit_default_type_parameters() {
27 let (db, pos) = TestDB::with_position(
28 r"
29 //- /main.rs
30 struct Foo<T = u8> { t: T }
31 fn main() {
32 let foo = Foo { t: 5 };
33 foo<|>;
34 }
35 ",
36 );
37 assert_eq!("Foo", displayed_source_at_pos(&db, pos));
38
39 let (db, pos) = TestDB::with_position(
40 r"
41 //- /main.rs
42 struct Foo<K, T = u8> { k: K, t: T }
43 fn main() {
44 let foo = Foo { k: 400, t: 5 };
45 foo<|>;
46 }
47 ",
48 );
49 assert_eq!("Foo<i32>", displayed_source_at_pos(&db, pos));
50}
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index 1f796876d..4c6099aa2 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -197,7 +197,7 @@ fn spam() {
197 !0..6 '1isize': isize 197 !0..6 '1isize': isize
198 !0..6 '1isize': isize 198 !0..6 '1isize': isize
199 !0..6 '1isize': isize 199 !0..6 '1isize': isize
200 54..457 '{ ...!(); }': ! 200 54..457 '{ ...!(); }': ()
201 88..109 'spam!(...am!())': {unknown} 201 88..109 'spam!(...am!())': {unknown}
202 115..134 'for _ ...!() {}': () 202 115..134 'for _ ...!() {}': ()
203 119..120 '_': {unknown} 203 119..120 '_': {unknown}
@@ -269,7 +269,7 @@ fn test() { S.foo()<|>; }
269} 269}
270 270
271#[test] 271#[test]
272fn infer_impl_items_generated_by_macros() { 272fn infer_assoc_items_generated_by_macros() {
273 let t = type_at( 273 let t = type_at(
274 r#" 274 r#"
275//- /main.rs 275//- /main.rs
@@ -288,7 +288,7 @@ fn test() { S.foo()<|>; }
288} 288}
289 289
290#[test] 290#[test]
291fn infer_impl_items_generated_by_macros_chain() { 291fn infer_assoc_items_generated_by_macros_chain() {
292 let t = type_at( 292 let t = type_at(
293 r#" 293 r#"
294//- /main.rs 294//- /main.rs
@@ -428,6 +428,32 @@ fn main() {
428} 428}
429 429
430#[test] 430#[test]
431fn infer_local_inner_macros() {
432 let (db, pos) = TestDB::with_position(
433 r#"
434//- /main.rs crate:main deps:foo
435fn test() {
436 let x = foo::foo!(1);
437 x<|>;
438}
439
440//- /lib.rs crate:foo
441#[macro_export(local_inner_macros)]
442macro_rules! foo {
443 (1) => { bar!() };
444}
445
446#[macro_export]
447macro_rules! bar {
448 () => { 42 }
449}
450
451"#,
452 );
453 assert_eq!("i32", type_at_pos(&db, pos));
454}
455
456#[test]
431fn infer_builtin_macros_line() { 457fn infer_builtin_macros_line() {
432 assert_snapshot!( 458 assert_snapshot!(
433 infer(r#" 459 infer(r#"
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index ab87f598a..558a70022 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -17,8 +17,8 @@ impl<T> [T] {
17#[lang = "slice_alloc"] 17#[lang = "slice_alloc"]
18impl<T> [T] {} 18impl<T> [T] {}
19 19
20fn test() { 20fn test(x: &[u8]) {
21 <[_]>::foo(b"foo"); 21 <[_]>::foo(x);
22} 22}
23"#), 23"#),
24 @r###" 24 @r###"
@@ -26,10 +26,11 @@ fn test() {
26 56..79 '{ ... }': T 26 56..79 '{ ... }': T
27 66..73 'loop {}': ! 27 66..73 'loop {}': !
28 71..73 '{}': () 28 71..73 '{}': ()
29 133..160 '{ ...o"); }': () 29 131..132 'x': &[u8]
30 139..149 '<[_]>::foo': fn foo<u8>(&[u8]) -> u8 30 141..163 '{ ...(x); }': ()
31 139..157 '<[_]>:..."foo")': u8 31 147..157 '<[_]>::foo': fn foo<u8>(&[u8]) -> u8
32 150..156 'b"foo"': &[u8] 32 147..160 '<[_]>::foo(x)': u8
33 158..159 'x': &[u8]
33 "### 34 "###
34 ); 35 );
35} 36}
@@ -983,7 +984,7 @@ fn test() { S2.into()<|>; }
983 984
984#[test] 985#[test]
985fn method_resolution_overloaded_method() { 986fn method_resolution_overloaded_method() {
986 test_utils::covers!(impl_self_type_match_without_receiver); 987 test_utils::mark::check!(impl_self_type_match_without_receiver);
987 let t = type_at( 988 let t = type_at(
988 r#" 989 r#"
989//- main.rs 990//- main.rs
@@ -1095,3 +1096,34 @@ fn test() { (S {}).method()<|>; }
1095 ); 1096 );
1096 assert_eq!(t, "()"); 1097 assert_eq!(t, "()");
1097} 1098}
1099
1100#[test]
1101fn dyn_trait_super_trait_not_in_scope() {
1102 assert_snapshot!(
1103 infer(r#"
1104mod m {
1105 pub trait SuperTrait {
1106 fn foo(&self) -> u32 { 0 }
1107 }
1108}
1109trait Trait: m::SuperTrait {}
1110
1111struct S;
1112impl m::SuperTrait for S {}
1113impl Trait for S {}
1114
1115fn test(d: &dyn Trait) {
1116 d.foo();
1117}
1118"#),
1119 @r###"
1120 52..56 'self': &Self
1121 65..70 '{ 0 }': u32
1122 67..68 '0': u32
1123 177..178 'd': &dyn Trait
1124 192..208 '{ ...o(); }': ()
1125 198..199 'd': &dyn Trait
1126 198..205 'd.foo()': u32
1127 "###
1128 );
1129}
diff --git a/crates/ra_hir_ty/src/tests/never_type.rs b/crates/ra_hir_ty/src/tests/never_type.rs
index a77209480..082c47208 100644
--- a/crates/ra_hir_ty/src/tests/never_type.rs
+++ b/crates/ra_hir_ty/src/tests/never_type.rs
@@ -1,4 +1,6 @@
1use super::type_at; 1use insta::assert_snapshot;
2
3use super::{infer_with_mismatches, type_at};
2 4
3#[test] 5#[test]
4fn infer_never1() { 6fn infer_never1() {
@@ -261,3 +263,176 @@ fn test(a: i32) {
261 ); 263 );
262 assert_eq!(t, "f64"); 264 assert_eq!(t, "f64");
263} 265}
266
267#[test]
268fn diverging_expression_1() {
269 let t = infer_with_mismatches(
270 r#"
271//- /main.rs
272fn test1() {
273 let x: u32 = return;
274}
275fn test2() {
276 let x: u32 = { return; };
277}
278fn test3() {
279 let x: u32 = loop {};
280}
281fn test4() {
282 let x: u32 = { loop {} };
283}
284fn test5() {
285 let x: u32 = { if true { loop {}; } else { loop {}; } };
286}
287fn test6() {
288 let x: u32 = { let y: u32 = { loop {}; }; };
289}
290"#,
291 true,
292 );
293 assert_snapshot!(t, @r###"
294 25..53 '{ ...urn; }': ()
295 35..36 'x': u32
296 44..50 'return': !
297 65..98 '{ ...; }; }': ()
298 75..76 'x': u32
299 84..95 '{ return; }': u32
300 86..92 'return': !
301 110..139 '{ ... {}; }': ()
302 120..121 'x': u32
303 129..136 'loop {}': !
304 134..136 '{}': ()
305 151..184 '{ ...} }; }': ()
306 161..162 'x': u32
307 170..181 '{ loop {} }': u32
308 172..179 'loop {}': !
309 177..179 '{}': ()
310 196..260 '{ ...} }; }': ()
311 206..207 'x': u32
312 215..257 '{ if t...}; } }': u32
313 217..255 'if tru... {}; }': u32
314 220..224 'true': bool
315 225..237 '{ loop {}; }': u32
316 227..234 'loop {}': !
317 232..234 '{}': ()
318 243..255 '{ loop {}; }': u32
319 245..252 'loop {}': !
320 250..252 '{}': ()
321 272..324 '{ ...; }; }': ()
322 282..283 'x': u32
323 291..321 '{ let ...; }; }': u32
324 297..298 'y': u32
325 306..318 '{ loop {}; }': u32
326 308..315 'loop {}': !
327 313..315 '{}': ()
328 "###);
329}
330
331#[test]
332fn diverging_expression_2() {
333 let t = infer_with_mismatches(
334 r#"
335//- /main.rs
336fn test1() {
337 // should give type mismatch
338 let x: u32 = { loop {}; "foo" };
339}
340"#,
341 true,
342 );
343 assert_snapshot!(t, @r###"
344 25..98 '{ ..." }; }': ()
345 68..69 'x': u32
346 77..95 '{ loop...foo" }': &str
347 79..86 'loop {}': !
348 84..86 '{}': ()
349 88..93 '"foo"': &str
350 77..95: expected u32, got &str
351 88..93: expected u32, got &str
352 "###);
353}
354
355#[test]
356fn diverging_expression_3_break() {
357 let t = infer_with_mismatches(
358 r#"
359//- /main.rs
360fn test1() {
361 // should give type mismatch
362 let x: u32 = { loop { break; } };
363}
364fn test2() {
365 // should give type mismatch
366 let x: u32 = { for a in b { break; }; };
367 // should give type mismatch as well
368 let x: u32 = { for a in b {}; };
369 // should give type mismatch as well
370 let x: u32 = { for a in b { return; }; };
371}
372fn test3() {
373 // should give type mismatch
374 let x: u32 = { while true { break; }; };
375 // should give type mismatch as well -- there's an implicit break, even if it's never hit
376 let x: u32 = { while true {}; };
377 // should give type mismatch as well
378 let x: u32 = { while true { return; }; };
379}
380"#,
381 true,
382 );
383 assert_snapshot!(t, @r###"
384 25..99 '{ ...} }; }': ()
385 68..69 'x': u32
386 77..96 '{ loop...k; } }': ()
387 79..94 'loop { break; }': ()
388 84..94 '{ break; }': ()
389 86..91 'break': !
390 77..96: expected u32, got ()
391 79..94: expected u32, got ()
392 111..357 '{ ...; }; }': ()
393 154..155 'x': u32
394 163..189 '{ for ...; }; }': ()
395 165..186 'for a ...eak; }': ()
396 169..170 'a': {unknown}
397 174..175 'b': {unknown}
398 176..186 '{ break; }': ()
399 178..183 'break': !
400 240..241 'x': u32
401 249..267 '{ for ... {}; }': ()
402 251..264 'for a in b {}': ()
403 255..256 'a': {unknown}
404 260..261 'b': {unknown}
405 262..264 '{}': ()
406 318..319 'x': u32
407 327..354 '{ for ...; }; }': ()
408 329..351 'for a ...urn; }': ()
409 333..334 'a': {unknown}
410 338..339 'b': {unknown}
411 340..351 '{ return; }': ()
412 342..348 'return': !
413 163..189: expected u32, got ()
414 249..267: expected u32, got ()
415 327..354: expected u32, got ()
416 369..668 '{ ...; }; }': ()
417 412..413 'x': u32
418 421..447 '{ whil...; }; }': ()
419 423..444 'while ...eak; }': ()
420 429..433 'true': bool
421 434..444 '{ break; }': ()
422 436..441 'break': !
423 551..552 'x': u32
424 560..578 '{ whil... {}; }': ()
425 562..575 'while true {}': ()
426 568..572 'true': bool
427 573..575 '{}': ()
428 629..630 'x': u32
429 638..665 '{ whil...; }; }': ()
430 640..662 'while ...urn; }': ()
431 646..650 'true': bool
432 651..662 '{ return; }': ()
433 653..659 'return': !
434 421..447: expected u32, got ()
435 560..578: expected u32, got ()
436 638..665: expected u32, got ()
437 "###);
438}
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index af291092d..0c5f972a2 100644
--- a/crates/ra_hir_ty/src/tests/patterns.rs
+++ b/crates/ra_hir_ty/src/tests/patterns.rs
@@ -1,5 +1,5 @@
1use insta::assert_snapshot; 1use insta::assert_snapshot;
2use test_utils::covers; 2use test_utils::mark;
3 3
4use super::{infer, infer_with_mismatches}; 4use super::{infer, infer_with_mismatches};
5 5
@@ -197,7 +197,7 @@ fn test() {
197 197
198#[test] 198#[test]
199fn infer_pattern_match_ergonomics_ref() { 199fn infer_pattern_match_ergonomics_ref() {
200 covers!(match_ergonomics_ref); 200 mark::check!(match_ergonomics_ref);
201 assert_snapshot!( 201 assert_snapshot!(
202 infer(r#" 202 infer(r#"
203fn test() { 203fn test() {
@@ -369,6 +369,45 @@ fn test() {
369} 369}
370 370
371#[test] 371#[test]
372fn enum_variant_through_self_in_pattern() {
373 assert_snapshot!(
374 infer(r#"
375enum E {
376 A { x: usize },
377 B(usize),
378 C
379}
380
381impl E {
382 fn test() {
383 match (loop {}) {
384 Self::A { x } => { x; },
385 Self::B(x) => { x; },
386 Self::C => {},
387 };
388 }
389}
390"#),
391 @r###"
392 76..218 '{ ... }': ()
393 86..211 'match ... }': ()
394 93..100 'loop {}': !
395 98..100 '{}': ()
396 116..129 'Self::A { x }': E
397 126..127 'x': usize
398 133..139 '{ x; }': ()
399 135..136 'x': usize
400 153..163 'Self::B(x)': E
401 161..162 'x': usize
402 167..173 '{ x; }': ()
403 169..170 'x': usize
404 187..194 'Self::C': E
405 198..200 '{}': ()
406 "###
407 );
408}
409
410#[test]
372fn infer_generics_in_patterns() { 411fn infer_generics_in_patterns() {
373 assert_snapshot!( 412 assert_snapshot!(
374 infer(r#" 413 infer(r#"
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 8a1292c7a..1f004bd63 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -1,9 +1,10 @@
1use insta::assert_snapshot; 1use insta::assert_snapshot;
2use test_utils::covers; 2use ra_db::fixture::WithFixture;
3use test_utils::mark;
3 4
4use super::infer;
5use crate::test_db::TestDB; 5use crate::test_db::TestDB;
6use ra_db::fixture::WithFixture; 6
7use super::infer;
7 8
8#[test] 9#[test]
9fn bug_484() { 10fn bug_484() {
@@ -89,8 +90,8 @@ fn quux() {
89 90
90#[test] 91#[test]
91fn recursive_vars() { 92fn recursive_vars() {
92 covers!(type_var_cycles_resolve_completely); 93 mark::check!(type_var_cycles_resolve_completely);
93 covers!(type_var_cycles_resolve_as_possible); 94 mark::check!(type_var_cycles_resolve_as_possible);
94 assert_snapshot!( 95 assert_snapshot!(
95 infer(r#" 96 infer(r#"
96fn test() { 97fn test() {
@@ -112,8 +113,6 @@ fn test() {
112 113
113#[test] 114#[test]
114fn recursive_vars_2() { 115fn recursive_vars_2() {
115 covers!(type_var_cycles_resolve_completely);
116 covers!(type_var_cycles_resolve_as_possible);
117 assert_snapshot!( 116 assert_snapshot!(
118 infer(r#" 117 infer(r#"
119fn test() { 118fn test() {
@@ -170,7 +169,7 @@ fn write() {
170 169
171#[test] 170#[test]
172fn infer_std_crash_2() { 171fn infer_std_crash_2() {
173 covers!(type_var_resolves_to_int_var); 172 mark::check!(type_var_resolves_to_int_var);
174 // caused "equating two type variables, ...", taken from std 173 // caused "equating two type variables, ...", taken from std
175 assert_snapshot!( 174 assert_snapshot!(
176 infer(r#" 175 infer(r#"
@@ -535,6 +534,66 @@ fn foo(b: Bar) {
535} 534}
536 535
537#[test] 536#[test]
537fn issue_4235_name_conflicts() {
538 assert_snapshot!(
539 infer(r#"
540struct FOO {}
541static FOO:FOO = FOO {};
542
543impl FOO {
544 fn foo(&self) {}
545}
546
547fn main() {
548 let a = &FOO;
549 a.foo();
550}
551"#), @r###"
552 32..38 'FOO {}': FOO
553 64..68 'self': &FOO
554 70..72 '{}': ()
555 86..120 '{ ...o(); }': ()
556 96..97 'a': &FOO
557 100..104 '&FOO': &FOO
558 101..104 'FOO': FOO
559 110..111 'a': &FOO
560 110..117 'a.foo()': ()
561"###
562 );
563}
564
565#[test]
566fn issue_4465_dollar_crate_at_type() {
567 assert_snapshot!(
568 infer(r#"
569pub struct Foo {}
570pub fn anything<T>() -> T {
571 loop {}
572}
573macro_rules! foo {
574 () => {{
575 let r: $crate::Foo = anything();
576 r
577 }};
578}
579fn main() {
580 let _a = foo!();
581}
582"#), @r###"
583 45..60 '{ loop {} }': T
584 51..58 'loop {}': !
585 56..58 '{}': ()
586 !0..31 '{letr:...g();r}': Foo
587 !4..5 'r': Foo
588 !18..26 'anything': fn anything<Foo>() -> Foo
589 !18..28 'anything()': Foo
590 !29..30 'r': Foo
591 164..188 '{ ...!(); }': ()
592 174..176 '_a': Foo
593"###);
594}
595
596#[test]
538fn issue_4053_diesel_where_clauses() { 597fn issue_4053_diesel_where_clauses() {
539 assert_snapshot!( 598 assert_snapshot!(
540 infer(r#" 599 infer(r#"
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index 56abc65b8..fd2208af2 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -179,7 +179,7 @@ fn test(a: u32, b: isize, c: !, d: &str) {
179 17..18 'b': isize 179 17..18 'b': isize
180 27..28 'c': ! 180 27..28 'c': !
181 33..34 'd': &str 181 33..34 'd': &str
182 42..121 '{ ...f32; }': ! 182 42..121 '{ ...f32; }': ()
183 48..49 'a': u32 183 48..49 'a': u32
184 55..56 'b': isize 184 55..56 'b': isize
185 62..63 'c': ! 185 62..63 'c': !
@@ -414,7 +414,7 @@ fn test() {
414 27..31 '5f32': f32 414 27..31 '5f32': f32
415 37..41 '5f64': f64 415 37..41 '5f64': f64
416 47..54 '"hello"': &str 416 47..54 '"hello"': &str
417 60..68 'b"bytes"': &[u8] 417 60..68 'b"bytes"': &[u8; _]
418 74..77 ''c'': char 418 74..77 ''c'': char
419 83..87 'b'b'': u8 419 83..87 'b'b'': u8
420 93..97 '3.14': f64 420 93..97 '3.14': f64
@@ -422,7 +422,7 @@ fn test() {
422 113..118 'false': bool 422 113..118 'false': bool
423 124..128 'true': bool 423 124..128 'true': bool
424 134..202 'r#" ... "#': &str 424 134..202 'r#" ... "#': &str
425 208..218 'br#"yolo"#': &[u8] 425 208..218 'br#"yolo"#': &[u8; _]
426 "### 426 "###
427 ); 427 );
428} 428}
@@ -576,6 +576,50 @@ impl S {
576} 576}
577 577
578#[test] 578#[test]
579fn infer_self_as_path() {
580 assert_snapshot!(
581 infer(r#"
582struct S1;
583struct S2(isize);
584enum E {
585 V1,
586 V2(u32),
587}
588
589impl S1 {
590 fn test() {
591 Self;
592 }
593}
594impl S2 {
595 fn test() {
596 Self(1);
597 }
598}
599impl E {
600 fn test() {
601 Self::V1;
602 Self::V2(1);
603 }
604}
605"#),
606 @r###"
607 87..108 '{ ... }': ()
608 97..101 'Self': S1
609 135..159 '{ ... }': ()
610 145..149 'Self': S2(isize) -> S2
611 145..152 'Self(1)': S2
612 150..151 '1': isize
613 185..231 '{ ... }': ()
614 195..203 'Self::V1': E
615 213..221 'Self::V2': V2(u32) -> E
616 213..224 'Self::V2(1)': E
617 222..223 '1': u32
618 "###
619 );
620}
621
622#[test]
579fn infer_binary_op() { 623fn infer_binary_op() {
580 assert_snapshot!( 624 assert_snapshot!(
581 infer(r#" 625 infer(r#"
@@ -935,7 +979,7 @@ fn foo() {
935 29..33 'true': bool 979 29..33 'true': bool
936 34..51 '{ ... }': i32 980 34..51 '{ ... }': i32
937 44..45 '1': i32 981 44..45 '1': i32
938 57..80 '{ ... }': ! 982 57..80 '{ ... }': i32
939 67..73 'return': ! 983 67..73 'return': !
940 90..93 '_x2': i32 984 90..93 '_x2': i32
941 96..149 'if tru... }': i32 985 96..149 'if tru... }': i32
@@ -951,7 +995,7 @@ fn foo() {
951 186..190 'true': bool 995 186..190 'true': bool
952 194..195 '3': i32 996 194..195 '3': i32
953 205..206 '_': bool 997 205..206 '_': bool
954 210..241 '{ ... }': ! 998 210..241 '{ ... }': i32
955 224..230 'return': ! 999 224..230 'return': !
956 257..260 '_x4': i32 1000 257..260 '_x4': i32
957 263..320 'match ... }': i32 1001 263..320 'match ... }': i32
@@ -1687,7 +1731,7 @@ fn foo() -> u32 {
1687 17..59 '{ ...; }; }': () 1731 17..59 '{ ...; }; }': ()
1688 27..28 'x': || -> usize 1732 27..28 'x': || -> usize
1689 31..56 '|| -> ...n 1; }': || -> usize 1733 31..56 '|| -> ...n 1; }': || -> usize
1690 43..56 '{ return 1; }': ! 1734 43..56 '{ return 1; }': usize
1691 45..53 'return 1': ! 1735 45..53 'return 1': !
1692 52..53 '1': usize 1736 52..53 '1': usize
1693 "### 1737 "###
@@ -1706,7 +1750,7 @@ fn foo() -> u32 {
1706 17..48 '{ ...; }; }': () 1750 17..48 '{ ...; }; }': ()
1707 27..28 'x': || -> () 1751 27..28 'x': || -> ()
1708 31..45 '|| { return; }': || -> () 1752 31..45 '|| { return; }': || -> ()
1709 34..45 '{ return; }': ! 1753 34..45 '{ return; }': ()
1710 36..42 'return': ! 1754 36..42 'return': !
1711 "### 1755 "###
1712 ); 1756 );
@@ -1755,3 +1799,127 @@ fn main() {
1755 "### 1799 "###
1756 ); 1800 );
1757} 1801}
1802
1803#[test]
1804fn effects_smoke_test() {
1805 assert_snapshot!(
1806 infer(r#"
1807fn main() {
1808 let x = unsafe { 92 };
1809 let y = async { async { () }.await };
1810 let z = try { () };
1811 let t = 'a: { 92 };
1812}
1813"#),
1814 @r###"
1815 11..131 '{ ...2 }; }': ()
1816 21..22 'x': i32
1817 32..38 '{ 92 }': i32
1818 34..36 '92': i32
1819 48..49 'y': {unknown}
1820 58..80 '{ asyn...wait }': {unknown}
1821 60..78 'async ....await': {unknown}
1822 66..72 '{ () }': ()
1823 68..70 '()': ()
1824 90..91 'z': {unknown}
1825 94..104 'try { () }': {unknown}
1826 98..104 '{ () }': ()
1827 100..102 '()': ()
1828 114..115 't': i32
1829 122..128 '{ 92 }': i32
1830 124..126 '92': i32
1831 "###
1832 )
1833}
1834
1835#[test]
1836fn infer_generic_from_later_assignment() {
1837 assert_snapshot!(
1838 infer(r#"
1839enum Option<T> { Some(T), None }
1840use Option::*;
1841
1842fn test() {
1843 let mut end = None;
1844 loop {
1845 end = Some(true);
1846 }
1847}
1848"#),
1849 @r###"
1850 60..130 '{ ... } }': ()
1851 70..77 'mut end': Option<bool>
1852 80..84 'None': Option<bool>
1853 90..128 'loop {... }': !
1854 95..128 '{ ... }': ()
1855 105..108 'end': Option<bool>
1856 105..121 'end = ...(true)': ()
1857 111..115 'Some': Some<bool>(bool) -> Option<bool>
1858 111..121 'Some(true)': Option<bool>
1859 116..120 'true': bool
1860 "###
1861 );
1862}
1863
1864#[test]
1865fn infer_loop_break_with_val() {
1866 assert_snapshot!(
1867 infer(r#"
1868enum Option<T> { Some(T), None }
1869use Option::*;
1870
1871fn test() {
1872 let x = loop {
1873 if false {
1874 break None;
1875 }
1876
1877 break Some(true);
1878 };
1879}
1880"#),
1881 @r###"
1882 60..169 '{ ... }; }': ()
1883 70..71 'x': Option<bool>
1884 74..166 'loop {... }': Option<bool>
1885 79..166 '{ ... }': ()
1886 89..133 'if fal... }': ()
1887 92..97 'false': bool
1888 98..133 '{ ... }': ()
1889 112..122 'break None': !
1890 118..122 'None': Option<bool>
1891 143..159 'break ...(true)': !
1892 149..153 'Some': Some<bool>(bool) -> Option<bool>
1893 149..159 'Some(true)': Option<bool>
1894 154..158 'true': bool
1895 "###
1896 );
1897}
1898
1899#[test]
1900fn infer_loop_break_without_val() {
1901 assert_snapshot!(
1902 infer(r#"
1903enum Option<T> { Some(T), None }
1904use Option::*;
1905
1906fn test() {
1907 let x = loop {
1908 if false {
1909 break;
1910 }
1911 };
1912}
1913"#),
1914 @r###"
1915 60..137 '{ ... }; }': ()
1916 70..71 'x': ()
1917 74..134 'loop {... }': ()
1918 79..134 '{ ... }': ()
1919 89..128 'if fal... }': ()
1920 92..97 'false': bool
1921 98..128 '{ ... }': ()
1922 112..117 'break': !
1923 "###
1924 );
1925}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index e555c879a..34f4b9039 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1,10 +1,11 @@
1use insta::assert_snapshot; 1use insta::assert_snapshot;
2
3use ra_db::fixture::WithFixture; 2use ra_db::fixture::WithFixture;
3use test_utils::mark;
4 4
5use super::{infer, infer_with_mismatches, type_at, type_at_pos};
6use crate::test_db::TestDB; 5use crate::test_db::TestDB;
7 6
7use super::{infer, infer_with_mismatches, type_at, type_at_pos};
8
8#[test] 9#[test]
9fn infer_await() { 10fn infer_await() {
10 let (db, pos) = TestDB::with_position( 11 let (db, pos) = TestDB::with_position(
@@ -301,7 +302,7 @@ fn test() {
301 302
302#[test] 303#[test]
303fn trait_default_method_self_bound_implements_trait() { 304fn trait_default_method_self_bound_implements_trait() {
304 test_utils::covers!(trait_self_implements_self); 305 mark::check!(trait_self_implements_self);
305 assert_snapshot!( 306 assert_snapshot!(
306 infer(r#" 307 infer(r#"
307trait Trait { 308trait Trait {
@@ -324,7 +325,6 @@ trait Trait {
324 325
325#[test] 326#[test]
326fn trait_default_method_self_bound_implements_super_trait() { 327fn trait_default_method_self_bound_implements_super_trait() {
327 test_utils::covers!(trait_self_implements_self);
328 assert_snapshot!( 328 assert_snapshot!(
329 infer(r#" 329 infer(r#"
330trait SuperTrait { 330trait SuperTrait {
@@ -1617,6 +1617,138 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
1617} 1617}
1618 1618
1619#[test] 1619#[test]
1620fn fn_ptr_and_item() {
1621 assert_snapshot!(
1622 infer(r#"
1623#[lang="fn_once"]
1624trait FnOnce<Args> {
1625 type Output;
1626
1627 fn call_once(self, args: Args) -> Self::Output;
1628}
1629
1630trait Foo<T> {
1631 fn foo(&self) -> T;
1632}
1633
1634struct Bar<T>(T);
1635
1636impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
1637 fn foo(&self) -> (A1, R) {}
1638}
1639
1640enum Opt<T> { None, Some(T) }
1641impl<T> Opt<T> {
1642 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {}
1643}
1644
1645fn test() {
1646 let bar: Bar<fn(u8) -> u32>;
1647 bar.foo();
1648
1649 let opt: Opt<u8>;
1650 let f: fn(u8) -> u32;
1651 opt.map(f);
1652}
1653"#),
1654 @r###"
165575..79 'self': Self
165681..85 'args': Args
1657140..144 'self': &Self
1658244..248 'self': &Bar<F>
1659261..263 '{}': ()
1660347..351 'self': Opt<T>
1661353..354 'f': F
1662369..371 '{}': ()
1663385..501 '{ ...(f); }': ()
1664395..398 'bar': Bar<fn(u8) -> u32>
1665424..427 'bar': Bar<fn(u8) -> u32>
1666424..433 'bar.foo()': {unknown}
1667444..447 'opt': Opt<u8>
1668466..467 'f': fn(u8) -> u32
1669488..491 'opt': Opt<u8>
1670488..498 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>>
1671496..497 'f': fn(u8) -> u32
1672"###
1673 );
1674}
1675
1676#[test]
1677fn fn_trait_deref_with_ty_default() {
1678 assert_snapshot!(
1679 infer(r#"
1680#[lang = "deref"]
1681trait Deref {
1682 type Target;
1683
1684 fn deref(&self) -> &Self::Target;
1685}
1686
1687#[lang="fn_once"]
1688trait FnOnce<Args> {
1689 type Output;
1690
1691 fn call_once(self, args: Args) -> Self::Output;
1692}
1693
1694struct Foo;
1695
1696impl Foo {
1697 fn foo(&self) -> usize {}
1698}
1699
1700struct Lazy<T, F = fn() -> T>(F);
1701
1702impl<T, F> Lazy<T, F> {
1703 pub fn new(f: F) -> Lazy<T, F> {}
1704}
1705
1706impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
1707 type Target = T;
1708}
1709
1710fn test() {
1711 let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
1712 let r1 = lazy1.foo();
1713
1714 fn make_foo_fn() -> Foo {}
1715 let make_foo_fn_ptr: fn() -> Foo = make_foo_fn;
1716 let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr);
1717 let r2 = lazy2.foo();
1718}
1719"#),
1720 @r###"
172165..69 'self': &Self
1722166..170 'self': Self
1723172..176 'args': Args
1724240..244 'self': &Foo
1725255..257 '{}': ()
1726335..336 'f': F
1727355..357 '{}': ()
1728444..690 '{ ...o(); }': ()
1729454..459 'lazy1': Lazy<Foo, fn() -> T>
1730476..485 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
1731476..493 'Lazy::...| Foo)': Lazy<Foo, fn() -> T>
1732486..492 '|| Foo': || -> T
1733489..492 'Foo': Foo
1734503..505 'r1': {unknown}
1735508..513 'lazy1': Lazy<Foo, fn() -> T>
1736508..519 'lazy1.foo()': {unknown}
1737561..576 'make_foo_fn_ptr': fn() -> Foo
1738592..603 'make_foo_fn': fn make_foo_fn() -> Foo
1739613..618 'lazy2': Lazy<Foo, fn() -> T>
1740635..644 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
1741635..661 'Lazy::...n_ptr)': Lazy<Foo, fn() -> T>
1742645..660 'make_foo_fn_ptr': fn() -> Foo
1743671..673 'r2': {unknown}
1744676..681 'lazy2': Lazy<Foo, fn() -> T>
1745676..687 'lazy2.foo()': {unknown}
1746550..552 '{}': ()
1747"###
1748 );
1749}
1750
1751#[test]
1620fn closure_1() { 1752fn closure_1() {
1621 assert_snapshot!( 1753 assert_snapshot!(
1622 infer(r#" 1754 infer(r#"
@@ -2055,7 +2187,7 @@ fn test<I: Iterator<Item: Iterator<Item = u32>>>() {
2055#[test] 2187#[test]
2056fn proc_macro_server_types() { 2188fn proc_macro_server_types() {
2057 assert_snapshot!( 2189 assert_snapshot!(
2058 infer_with_mismatches(r#" 2190 infer(r#"
2059macro_rules! with_api { 2191macro_rules! with_api {
2060 ($S:ident, $self:ident, $m:ident) => { 2192 ($S:ident, $self:ident, $m:ident) => {
2061 $m! { 2193 $m! {
@@ -2069,9 +2201,9 @@ macro_rules! with_api {
2069} 2201}
2070macro_rules! associated_item { 2202macro_rules! associated_item {
2071 (type TokenStream) => 2203 (type TokenStream) =>
2072 (type TokenStream: 'static + Clone;); 2204 (type TokenStream: 'static;);
2073 (type Group) => 2205 (type Group) =>
2074 (type Group: 'static + Clone;); 2206 (type Group: 'static;);
2075 ($($item:tt)*) => ($($item)*;) 2207 ($($item:tt)*) => ($($item)*;)
2076} 2208}
2077macro_rules! declare_server_traits { 2209macro_rules! declare_server_traits {
@@ -2083,21 +2215,23 @@ macro_rules! declare_server_traits {
2083 } 2215 }
2084 2216
2085 $(pub trait $name: Types { 2217 $(pub trait $name: Types {
2086 $(associated_item!(fn $method(&mut self, $($arg: $arg_ty),*) $(-> $ret_ty)?);)* 2218 $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
2087 })* 2219 })*
2088 2220
2089 pub trait Server: Types $(+ $name)* {} 2221 pub trait Server: Types $(+ $name)* {}
2090 impl<S: Types $(+ $name)*> Server for S {} 2222 impl<S: Types $(+ $name)*> Server for S {}
2091 } 2223 }
2092} 2224}
2225
2093with_api!(Self, self_, declare_server_traits); 2226with_api!(Self, self_, declare_server_traits);
2094struct Group {} 2227struct G {}
2095struct TokenStream {} 2228struct T {}
2096struct Rustc; 2229struct Rustc;
2097impl Types for Rustc { 2230impl Types for Rustc {
2098 type TokenStream = TokenStream; 2231 type TokenStream = T;
2099 type Group = Group; 2232 type Group = G;
2100} 2233}
2234
2101fn make<T>() -> T { loop {} } 2235fn make<T>() -> T { loop {} }
2102impl TokenStream for Rustc { 2236impl TokenStream for Rustc {
2103 fn new() -> Self::TokenStream { 2237 fn new() -> Self::TokenStream {
@@ -2105,17 +2239,17 @@ impl TokenStream for Rustc {
2105 make() 2239 make()
2106 } 2240 }
2107} 2241}
2108"#, true), 2242"#),
2109 @r###" 2243 @r###"
2110 1115..1126 '{ loop {} }': T 2244 1062..1073 '{ loop {} }': T
2111 1117..1124 'loop {}': ! 2245 1064..1071 'loop {}': !
2112 1122..1124 '{}': () 2246 1069..1071 '{}': ()
2113 1190..1253 '{ ... }': {unknown} 2247 1137..1200 '{ ... }': T
2114 1204..1209 'group': {unknown} 2248 1151..1156 'group': G
2115 1225..1229 'make': fn make<{unknown}>() -> {unknown} 2249 1172..1176 'make': fn make<G>() -> G
2116 1225..1231 'make()': {unknown} 2250 1172..1178 'make()': G
2117 1241..1245 'make': fn make<{unknown}>() -> {unknown} 2251 1188..1192 'make': fn make<T>() -> T
2118 1241..1247 'make()': {unknown} 2252 1188..1194 'make()': T
2119 "### 2253 "###
2120 ); 2254 );
2121} 2255}
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 1ccb7c3b4..5870618a0 100644
--- a/crates/ra_hir_ty/src/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -182,7 +182,10 @@ impl chalk_ir::interner::Interner for Interner {
182 Arc::new(goal) 182 Arc::new(goal)
183 } 183 }
184 184
185 fn intern_goals(&self, data: impl IntoIterator<Item = Goal<Self>>) -> Self::InternedGoals { 185 fn intern_goals<E>(
186 &self,
187 data: impl IntoIterator<Item = Result<Goal<Self>, E>>,
188 ) -> Result<Self::InternedGoals, E> {
186 data.into_iter().collect() 189 data.into_iter().collect()
187 } 190 }
188 191
@@ -222,10 +225,10 @@ impl chalk_ir::interner::Interner for Interner {
222 clause 225 clause
223 } 226 }
224 227
225 fn intern_program_clauses( 228 fn intern_program_clauses<E>(
226 &self, 229 &self,
227 data: impl IntoIterator<Item = chalk_ir::ProgramClause<Self>>, 230 data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
228 ) -> Arc<[chalk_ir::ProgramClause<Self>]> { 231 ) -> Result<Arc<[chalk_ir::ProgramClause<Self>]>, E> {
229 data.into_iter().collect() 232 data.into_iter().collect()
230 } 233 }
231 234
@@ -236,10 +239,10 @@ impl chalk_ir::interner::Interner for Interner {
236 &clauses 239 &clauses
237 } 240 }
238 241
239 fn intern_quantified_where_clauses( 242 fn intern_quantified_where_clauses<E>(
240 &self, 243 &self,
241 data: impl IntoIterator<Item = chalk_ir::QuantifiedWhereClause<Self>>, 244 data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
242 ) -> Self::InternedQuantifiedWhereClauses { 245 ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
243 data.into_iter().collect() 246 data.into_iter().collect()
244 } 247 }
245 248
@@ -250,10 +253,10 @@ impl chalk_ir::interner::Interner for Interner {
250 clauses 253 clauses
251 } 254 }
252 255
253 fn intern_parameter_kinds( 256 fn intern_parameter_kinds<E>(
254 &self, 257 &self,
255 data: impl IntoIterator<Item = chalk_ir::ParameterKind<()>>, 258 data: impl IntoIterator<Item = Result<chalk_ir::ParameterKind<()>, E>>,
256 ) -> Self::InternedParameterKinds { 259 ) -> Result<Self::InternedParameterKinds, E> {
257 data.into_iter().collect() 260 data.into_iter().collect()
258 } 261 }
259 262
@@ -264,10 +267,10 @@ impl chalk_ir::interner::Interner for Interner {
264 &parameter_kinds 267 &parameter_kinds
265 } 268 }
266 269
267 fn intern_canonical_var_kinds( 270 fn intern_canonical_var_kinds<E>(
268 &self, 271 &self,
269 data: impl IntoIterator<Item = chalk_ir::ParameterKind<UniverseIndex>>, 272 data: impl IntoIterator<Item = Result<chalk_ir::ParameterKind<UniverseIndex>, E>>,
270 ) -> Self::InternedCanonicalVarKinds { 273 ) -> Result<Self::InternedCanonicalVarKinds, E> {
271 data.into_iter().collect() 274 data.into_iter().collect()
272 } 275 }
273 276
@@ -460,6 +463,14 @@ impl ToChalk for TypeCtor {
460 TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), 463 TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()),
461 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), 464 TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)),
462 TypeName::OpaqueType(_) => unreachable!(), 465 TypeName::OpaqueType(_) => unreachable!(),
466
467 TypeName::Scalar(_) => unreachable!(),
468 TypeName::Tuple(_) => unreachable!(),
469 TypeName::Raw(_) => unreachable!(),
470 TypeName::Slice => unreachable!(),
471 TypeName::Ref(_) => unreachable!(),
472 TypeName::Str => unreachable!(),
473
463 TypeName::Error => { 474 TypeName::Error => {
464 // this should not be reached, since we don't represent TypeName::Error with TypeCtor 475 // this should not be reached, since we don't represent TypeName::Error with TypeCtor
465 unreachable!() 476 unreachable!()
@@ -862,12 +873,6 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
862 // We don't do coherence checking (yet) 873 // We don't do coherence checking (yet)
863 unimplemented!() 874 unimplemented!()
864 } 875 }
865 fn as_struct_id(&self, id: &TypeName<Interner>) -> Option<StructId> {
866 match id {
867 TypeName::Struct(struct_id) => Some(*struct_id),
868 _ => None,
869 }
870 }
871 fn interner(&self) -> &Interner { 876 fn interner(&self) -> &Interner {
872 &Interner 877 &Interner
873 } 878 }
@@ -892,6 +897,20 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
892 ) -> Arc<chalk_rust_ir::OpaqueTyDatum<Interner>> { 897 ) -> Arc<chalk_rust_ir::OpaqueTyDatum<Interner>> {
893 unimplemented!() 898 unimplemented!()
894 } 899 }
900
901 fn force_impl_for(
902 &self,
903 _well_known: chalk_rust_ir::WellKnownTrait,
904 _ty: &chalk_ir::TyData<Interner>,
905 ) -> Option<bool> {
906 // this method is mostly for rustc
907 None
908 }
909
910 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
911 // FIXME: implement actual object safety
912 true
913 }
895} 914}
896 915
897pub(crate) fn program_clauses_for_chalk_env_query( 916pub(crate) fn program_clauses_for_chalk_env_query(
diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs
deleted file mode 100644
index 2b5d11681..000000000
--- a/crates/ra_ide/src/assists.rs
+++ /dev/null
@@ -1,47 +0,0 @@
1//! FIXME: write short doc here
2
3use ra_assists::{resolved_assists, AssistAction, AssistLabel};
4use ra_db::{FilePosition, FileRange};
5use ra_ide_db::RootDatabase;
6
7use crate::{FileId, SourceChange, SourceFileEdit};
8
9pub use ra_assists::AssistId;
10
11#[derive(Debug)]
12pub struct Assist {
13 pub id: AssistId,
14 pub label: String,
15 pub group_label: Option<String>,
16 pub source_change: SourceChange,
17}
18
19pub(crate) fn assists(db: &RootDatabase, frange: FileRange) -> Vec<Assist> {
20 resolved_assists(db, frange)
21 .into_iter()
22 .map(|assist| {
23 let file_id = frange.file_id;
24 let assist_label = &assist.label;
25 Assist {
26 id: assist_label.id,
27 label: assist_label.label.clone(),
28 group_label: assist.group_label.map(|it| it.0),
29 source_change: action_to_edit(assist.action, file_id, assist_label),
30 }
31 })
32 .collect()
33}
34
35fn action_to_edit(
36 action: AssistAction,
37 file_id: FileId,
38 assist_label: &AssistLabel,
39) -> SourceChange {
40 let file_id = match action.file {
41 ra_assists::AssistFile::TargetFile(it) => it,
42 _ => file_id,
43 };
44 let file_edit = SourceFileEdit { file_id, edit: action.edit };
45 SourceChange::source_file_edit(assist_label.label.clone(), file_edit)
46 .with_cursor_opt(action.cursor_position.map(|offset| FilePosition { offset, file_id }))
47}
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs
index 780a03c13..aa039e6fc 100644
--- a/crates/ra_ide/src/call_info.rs
+++ b/crates/ra_ide/src/call_info.rs
@@ -5,7 +5,7 @@ use ra_syntax::{
5 ast::{self, ArgListOwner}, 5 ast::{self, ArgListOwner},
6 match_ast, AstNode, SyntaxNode, SyntaxToken, 6 match_ast, AstNode, SyntaxNode, SyntaxToken,
7}; 7};
8use test_utils::tested_by; 8use test_utils::mark;
9 9
10use crate::{CallInfo, FilePosition, FunctionSignature}; 10use crate::{CallInfo, FilePosition, FunctionSignature};
11 11
@@ -84,7 +84,7 @@ fn call_info_for_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Op
84 84
85 let arg_list_range = arg_list.syntax().text_range(); 85 let arg_list_range = arg_list.syntax().text_range();
86 if !arg_list_range.contains_inclusive(token.text_range().start()) { 86 if !arg_list_range.contains_inclusive(token.text_range().start()) {
87 tested_by!(call_info_bad_offset); 87 mark::hit!(call_info_bad_offset);
88 return None; 88 return None;
89 } 89 }
90 90
@@ -213,7 +213,7 @@ impl CallInfo {
213 213
214#[cfg(test)] 214#[cfg(test)]
215mod tests { 215mod tests {
216 use test_utils::covers; 216 use test_utils::mark;
217 217
218 use crate::mock_analysis::single_file_with_position; 218 use crate::mock_analysis::single_file_with_position;
219 219
@@ -529,7 +529,7 @@ By default this method stops actor's `Context`."#
529 529
530 #[test] 530 #[test]
531 fn call_info_bad_offset() { 531 fn call_info_bad_offset() {
532 covers!(call_info_bad_offset); 532 mark::check!(call_info_bad_offset);
533 let (analysis, position) = single_file_with_position( 533 let (analysis, position) = single_file_with_position(
534 r#"fn foo(x: u32, y: u32) -> u32 {x + y} 534 r#"fn foo(x: u32, y: u32) -> u32 {x + y}
535 fn bar() { foo <|> (3, ); }"#, 535 fn bar() { foo <|> (3, ); }"#,
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs
index 4ca0fdf4f..191300704 100644
--- a/crates/ra_ide/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
@@ -59,13 +59,13 @@ pub use crate::completion::{
59/// with ordering of completions (currently this is done by the client). 59/// with ordering of completions (currently this is done by the client).
60pub(crate) fn completions( 60pub(crate) fn completions(
61 db: &RootDatabase, 61 db: &RootDatabase,
62 position: FilePosition,
63 config: &CompletionConfig, 62 config: &CompletionConfig,
63 position: FilePosition,
64) -> Option<Completions> { 64) -> Option<Completions> {
65 let ctx = CompletionContext::new(db, position, config)?; 65 let ctx = CompletionContext::new(db, position, config)?;
66 66
67 let mut acc = Completions::default(); 67 let mut acc = Completions::default();
68 68 complete_attribute::complete_attribute(&mut acc, &ctx);
69 complete_fn_param::complete_fn_param(&mut acc, &ctx); 69 complete_fn_param::complete_fn_param(&mut acc, &ctx);
70 complete_keyword::complete_expr_keyword(&mut acc, &ctx); 70 complete_keyword::complete_expr_keyword(&mut acc, &ctx);
71 complete_keyword::complete_use_tree_keyword(&mut acc, &ctx); 71 complete_keyword::complete_use_tree_keyword(&mut acc, &ctx);
@@ -79,7 +79,6 @@ pub(crate) fn completions(
79 complete_postfix::complete_postfix(&mut acc, &ctx); 79 complete_postfix::complete_postfix(&mut acc, &ctx);
80 complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); 80 complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx);
81 complete_trait_impl::complete_trait_impl(&mut acc, &ctx); 81 complete_trait_impl::complete_trait_impl(&mut acc, &ctx);
82 complete_attribute::complete_attribute(&mut acc, &ctx);
83 82
84 Some(acc) 83 Some(acc)
85} 84}
diff --git a/crates/ra_ide/src/completion/complete_attribute.rs b/crates/ra_ide/src/completion/complete_attribute.rs
index 8bf952798..f17266221 100644
--- a/crates/ra_ide/src/completion/complete_attribute.rs
+++ b/crates/ra_ide/src/completion/complete_attribute.rs
@@ -3,25 +3,29 @@
3//! This module uses a bit of static metadata to provide completions 3//! This module uses a bit of static metadata to provide completions
4//! for built-in attributes. 4//! for built-in attributes.
5 5
6use super::completion_context::CompletionContext; 6use ra_syntax::{ast, AstNode, SyntaxKind};
7use super::completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions}; 7use rustc_hash::FxHashSet;
8use ra_syntax::{ 8
9 ast::{Attr, AttrKind}, 9use crate::completion::{
10 AstNode, 10 completion_context::CompletionContext,
11 completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions},
11}; 12};
12 13
13pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) { 14pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
14 if !ctx.is_attribute { 15 let attribute = ctx.attribute_under_caret.as_ref()?;
15 return;
16 }
17 16
18 let is_inner = ctx 17 match (attribute.path(), attribute.input()) {
19 .original_token 18 (Some(path), Some(ast::AttrInput::TokenTree(token_tree)))
20 .ancestors() 19 if path.to_string() == "derive" =>
21 .find_map(Attr::cast) 20 {
22 .map(|attr| attr.kind() == AttrKind::Inner) 21 complete_derive(acc, ctx, token_tree)
23 .unwrap_or(false); 22 }
23 _ => complete_attribute_start(acc, ctx, attribute),
24 }
25 Some(())
26}
24 27
28fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attribute: &ast::Attr) {
25 for attr_completion in ATTRIBUTES { 29 for attr_completion in ATTRIBUTES {
26 let mut item = CompletionItem::new( 30 let mut item = CompletionItem::new(
27 CompletionKind::Attribute, 31 CompletionKind::Attribute,
@@ -37,7 +41,7 @@ pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
37 _ => {} 41 _ => {}
38 } 42 }
39 43
40 if is_inner || !attr_completion.should_be_inner { 44 if attribute.kind() == ast::AttrKind::Inner || !attr_completion.should_be_inner {
41 acc.add(item); 45 acc.add(item);
42 } 46 }
43 } 47 }
@@ -126,6 +130,106 @@ const ATTRIBUTES: &[AttrCompletion] = &[
126 }, 130 },
127]; 131];
128 132
133fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) {
134 if let Ok(existing_derives) = parse_derive_input(derive_input) {
135 for derive_completion in DEFAULT_DERIVE_COMPLETIONS
136 .into_iter()
137 .filter(|completion| !existing_derives.contains(completion.label))
138 {
139 let mut label = derive_completion.label.to_owned();
140 for dependency in derive_completion
141 .dependencies
142 .into_iter()
143 .filter(|&&dependency| !existing_derives.contains(dependency))
144 {
145 label.push_str(", ");
146 label.push_str(dependency);
147 }
148 acc.add(
149 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label)
150 .kind(CompletionItemKind::Attribute),
151 );
152 }
153
154 for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) {
155 acc.add(
156 CompletionItem::new(
157 CompletionKind::Attribute,
158 ctx.source_range(),
159 custom_derive_name,
160 )
161 .kind(CompletionItemKind::Attribute),
162 );
163 }
164 }
165}
166
167fn parse_derive_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> {
168 match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) {
169 (Some(left_paren), Some(right_paren))
170 if left_paren.kind() == SyntaxKind::L_PAREN
171 && right_paren.kind() == SyntaxKind::R_PAREN =>
172 {
173 let mut input_derives = FxHashSet::default();
174 let mut current_derive = String::new();
175 for token in derive_input
176 .syntax()
177 .children_with_tokens()
178 .filter_map(|token| token.into_token())
179 .skip_while(|token| token != &left_paren)
180 .skip(1)
181 .take_while(|token| token != &right_paren)
182 {
183 if SyntaxKind::COMMA == token.kind() {
184 if !current_derive.is_empty() {
185 input_derives.insert(current_derive);
186 current_derive = String::new();
187 }
188 } else {
189 current_derive.push_str(token.to_string().trim());
190 }
191 }
192
193 if !current_derive.is_empty() {
194 input_derives.insert(current_derive);
195 }
196 Ok(input_derives)
197 }
198 _ => Err(()),
199 }
200}
201
202fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet<String> {
203 let mut result = FxHashSet::default();
204 ctx.scope().process_all_names(&mut |name, scope_def| {
205 if let hir::ScopeDef::MacroDef(mac) = scope_def {
206 if mac.is_derive_macro() {
207 result.insert(name.to_string());
208 }
209 }
210 });
211 result
212}
213
214struct DeriveCompletion {
215 label: &'static str,
216 dependencies: &'static [&'static str],
217}
218
219/// Standard Rust derives and the information about their dependencies
220/// (the dependencies are needed so that the main derive don't break the compilation when added)
221const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[
222 DeriveCompletion { label: "Clone", dependencies: &[] },
223 DeriveCompletion { label: "Copy", dependencies: &["Clone"] },
224 DeriveCompletion { label: "Debug", dependencies: &[] },
225 DeriveCompletion { label: "Default", dependencies: &[] },
226 DeriveCompletion { label: "Hash", dependencies: &[] },
227 DeriveCompletion { label: "PartialEq", dependencies: &[] },
228 DeriveCompletion { label: "Eq", dependencies: &["PartialEq"] },
229 DeriveCompletion { label: "PartialOrd", dependencies: &["PartialEq"] },
230 DeriveCompletion { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] },
231];
232
129#[cfg(test)] 233#[cfg(test)]
130mod tests { 234mod tests {
131 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; 235 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
@@ -136,6 +240,170 @@ mod tests {
136 } 240 }
137 241
138 #[test] 242 #[test]
243 fn empty_derive_completion() {
244 assert_debug_snapshot!(
245 do_attr_completion(
246 r"
247 #[derive(<|>)]
248 struct Test {}
249 ",
250 ),
251 @r###"
252 [
253 CompletionItem {
254 label: "Clone",
255 source_range: 30..30,
256 delete: 30..30,
257 insert: "Clone",
258 kind: Attribute,
259 },
260 CompletionItem {
261 label: "Copy, Clone",
262 source_range: 30..30,
263 delete: 30..30,
264 insert: "Copy, Clone",
265 kind: Attribute,
266 },
267 CompletionItem {
268 label: "Debug",
269 source_range: 30..30,
270 delete: 30..30,
271 insert: "Debug",
272 kind: Attribute,
273 },
274 CompletionItem {
275 label: "Default",
276 source_range: 30..30,
277 delete: 30..30,
278 insert: "Default",
279 kind: Attribute,
280 },
281 CompletionItem {
282 label: "Eq, PartialEq",
283 source_range: 30..30,
284 delete: 30..30,
285 insert: "Eq, PartialEq",
286 kind: Attribute,
287 },
288 CompletionItem {
289 label: "Hash",
290 source_range: 30..30,
291 delete: 30..30,
292 insert: "Hash",
293 kind: Attribute,
294 },
295 CompletionItem {
296 label: "Ord, PartialOrd, Eq, PartialEq",
297 source_range: 30..30,
298 delete: 30..30,
299 insert: "Ord, PartialOrd, Eq, PartialEq",
300 kind: Attribute,
301 },
302 CompletionItem {
303 label: "PartialEq",
304 source_range: 30..30,
305 delete: 30..30,
306 insert: "PartialEq",
307 kind: Attribute,
308 },
309 CompletionItem {
310 label: "PartialOrd, PartialEq",
311 source_range: 30..30,
312 delete: 30..30,
313 insert: "PartialOrd, PartialEq",
314 kind: Attribute,
315 },
316 ]
317 "###
318 );
319 }
320
321 #[test]
322 fn no_completion_for_incorrect_derive() {
323 assert_debug_snapshot!(
324 do_attr_completion(
325 r"
326 #[derive{<|>)]
327 struct Test {}
328 ",
329 ),
330 @"[]"
331 );
332 }
333
334 #[test]
335 fn derive_with_input_completion() {
336 assert_debug_snapshot!(
337 do_attr_completion(
338 r"
339 #[derive(serde::Serialize, PartialEq, <|>)]
340 struct Test {}
341 ",
342 ),
343 @r###"
344 [
345 CompletionItem {
346 label: "Clone",
347 source_range: 59..59,
348 delete: 59..59,
349 insert: "Clone",
350 kind: Attribute,
351 },
352 CompletionItem {
353 label: "Copy, Clone",
354 source_range: 59..59,
355 delete: 59..59,
356 insert: "Copy, Clone",
357 kind: Attribute,
358 },
359 CompletionItem {
360 label: "Debug",
361 source_range: 59..59,
362 delete: 59..59,
363 insert: "Debug",
364 kind: Attribute,
365 },
366 CompletionItem {
367 label: "Default",
368 source_range: 59..59,
369 delete: 59..59,
370 insert: "Default",
371 kind: Attribute,
372 },
373 CompletionItem {
374 label: "Eq",
375 source_range: 59..59,
376 delete: 59..59,
377 insert: "Eq",
378 kind: Attribute,
379 },
380 CompletionItem {
381 label: "Hash",
382 source_range: 59..59,
383 delete: 59..59,
384 insert: "Hash",
385 kind: Attribute,
386 },
387 CompletionItem {
388 label: "Ord, PartialOrd, Eq",
389 source_range: 59..59,
390 delete: 59..59,
391 insert: "Ord, PartialOrd, Eq",
392 kind: Attribute,
393 },
394 CompletionItem {
395 label: "PartialOrd",
396 source_range: 59..59,
397 delete: 59..59,
398 insert: "PartialOrd",
399 kind: Attribute,
400 },
401 ]
402 "###
403 );
404 }
405
406 #[test]
139 fn test_attribute_completion() { 407 fn test_attribute_completion() {
140 assert_debug_snapshot!( 408 assert_debug_snapshot!(
141 do_attr_completion( 409 do_attr_completion(
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs
index 6a0f0c72e..f2a52a407 100644
--- a/crates/ra_ide/src/completion/complete_postfix.rs
+++ b/crates/ra_ide/src/completion/complete_postfix.rs
@@ -14,6 +14,7 @@ use crate::{
14 }, 14 },
15 CompletionItem, 15 CompletionItem,
16}; 16};
17use ra_assists::utils::TryEnum;
17 18
18pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { 19pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
19 if !ctx.config.enable_postfix_completions { 20 if !ctx.config.enable_postfix_completions {
@@ -37,8 +38,53 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
37 Some(it) => it, 38 Some(it) => it,
38 None => return, 39 None => return,
39 }; 40 };
41 let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty);
42 if let Some(try_enum) = &try_enum {
43 match try_enum {
44 TryEnum::Result => {
45 postfix_snippet(
46 ctx,
47 cap,
48 &dot_receiver,
49 "ifl",
50 "if let Ok {}",
51 &format!("if let Ok($1) = {} {{\n $0\n}}", receiver_text),
52 )
53 .add_to(acc);
40 54
41 if receiver_ty.is_bool() || receiver_ty.is_unknown() { 55 postfix_snippet(
56 ctx,
57 cap,
58 &dot_receiver,
59 "while",
60 "while let Ok {}",
61 &format!("while let Ok($1) = {} {{\n $0\n}}", receiver_text),
62 )
63 .add_to(acc);
64 }
65 TryEnum::Option => {
66 postfix_snippet(
67 ctx,
68 cap,
69 &dot_receiver,
70 "ifl",
71 "if let Some {}",
72 &format!("if let Some($1) = {} {{\n $0\n}}", receiver_text),
73 )
74 .add_to(acc);
75
76 postfix_snippet(
77 ctx,
78 cap,
79 &dot_receiver,
80 "while",
81 "while let Some {}",
82 &format!("while let Some($1) = {} {{\n $0\n}}", receiver_text),
83 )
84 .add_to(acc);
85 }
86 }
87 } else if receiver_ty.is_bool() || receiver_ty.is_unknown() {
42 postfix_snippet( 88 postfix_snippet(
43 ctx, 89 ctx,
44 cap, 90 cap,
@@ -58,7 +104,6 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
58 ) 104 )
59 .add_to(acc); 105 .add_to(acc);
60 } 106 }
61
62 // !&&&42 is a compiler error, ergo process it before considering the references 107 // !&&&42 is a compiler error, ergo process it before considering the references
63 postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text)) 108 postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text))
64 .add_to(acc); 109 .add_to(acc);
@@ -80,16 +125,45 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
80 let dot_receiver = include_references(dot_receiver); 125 let dot_receiver = include_references(dot_receiver);
81 let receiver_text = 126 let receiver_text =
82 get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal); 127 get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);
83 128 match try_enum {
84 postfix_snippet( 129 Some(try_enum) => {
85 ctx, 130 match try_enum {
86 cap, 131 TryEnum::Result => {
87 &dot_receiver, 132 postfix_snippet(
88 "match", 133 ctx,
89 "match expr {}", 134 cap,
90 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text), 135 &dot_receiver,
91 ) 136 "match",
92 .add_to(acc); 137 "match expr {}",
138 &format!("match {} {{\n Ok(${{1:_}}) => {{$2\\}},\n Err(${{3:_}}) => {{$0\\}},\n}}", receiver_text),
139 )
140 .add_to(acc);
141 }
142 TryEnum::Option => {
143 postfix_snippet(
144 ctx,
145 cap,
146 &dot_receiver,
147 "match",
148 "match expr {}",
149 &format!("match {} {{\n Some(${{1:_}}) => {{$2\\}},\n None => {{$0\\}},\n}}", receiver_text),
150 )
151 .add_to(acc);
152 }
153 }
154 }
155 None => {
156 postfix_snippet(
157 ctx,
158 cap,
159 &dot_receiver,
160 "match",
161 "match expr {}",
162 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text),
163 )
164 .add_to(acc);
165 }
166 }
93 167
94 postfix_snippet( 168 postfix_snippet(
95 ctx, 169 ctx,
@@ -236,6 +310,164 @@ mod tests {
236 } 310 }
237 311
238 #[test] 312 #[test]
313 fn postfix_completion_works_for_option() {
314 assert_debug_snapshot!(
315 do_postfix_completion(
316 r#"
317 enum Option<T> {
318 Some(T),
319 None,
320 }
321
322 fn main() {
323 let bar = Option::Some(true);
324 bar.<|>
325 }
326 "#,
327 ),
328 @r###"
329 [
330 CompletionItem {
331 label: "box",
332 source_range: 210..210,
333 delete: 206..210,
334 insert: "Box::new(bar)",
335 detail: "Box::new(expr)",
336 },
337 CompletionItem {
338 label: "dbg",
339 source_range: 210..210,
340 delete: 206..210,
341 insert: "dbg!(bar)",
342 detail: "dbg!(expr)",
343 },
344 CompletionItem {
345 label: "ifl",
346 source_range: 210..210,
347 delete: 206..210,
348 insert: "if let Some($1) = bar {\n $0\n}",
349 detail: "if let Some {}",
350 },
351 CompletionItem {
352 label: "match",
353 source_range: 210..210,
354 delete: 206..210,
355 insert: "match bar {\n Some(${1:_}) => {$2\\},\n None => {$0\\},\n}",
356 detail: "match expr {}",
357 },
358 CompletionItem {
359 label: "not",
360 source_range: 210..210,
361 delete: 206..210,
362 insert: "!bar",
363 detail: "!expr",
364 },
365 CompletionItem {
366 label: "ref",
367 source_range: 210..210,
368 delete: 206..210,
369 insert: "&bar",
370 detail: "&expr",
371 },
372 CompletionItem {
373 label: "refm",
374 source_range: 210..210,
375 delete: 206..210,
376 insert: "&mut bar",
377 detail: "&mut expr",
378 },
379 CompletionItem {
380 label: "while",
381 source_range: 210..210,
382 delete: 206..210,
383 insert: "while let Some($1) = bar {\n $0\n}",
384 detail: "while let Some {}",
385 },
386 ]
387 "###
388 );
389 }
390
391 #[test]
392 fn postfix_completion_works_for_result() {
393 assert_debug_snapshot!(
394 do_postfix_completion(
395 r#"
396 enum Result<T, E> {
397 Ok(T),
398 Err(E),
399 }
400
401 fn main() {
402 let bar = Result::Ok(true);
403 bar.<|>
404 }
405 "#,
406 ),
407 @r###"
408 [
409 CompletionItem {
410 label: "box",
411 source_range: 211..211,
412 delete: 207..211,
413 insert: "Box::new(bar)",
414 detail: "Box::new(expr)",
415 },
416 CompletionItem {
417 label: "dbg",
418 source_range: 211..211,
419 delete: 207..211,
420 insert: "dbg!(bar)",
421 detail: "dbg!(expr)",
422 },
423 CompletionItem {
424 label: "ifl",
425 source_range: 211..211,
426 delete: 207..211,
427 insert: "if let Ok($1) = bar {\n $0\n}",
428 detail: "if let Ok {}",
429 },
430 CompletionItem {
431 label: "match",
432 source_range: 211..211,
433 delete: 207..211,
434 insert: "match bar {\n Ok(${1:_}) => {$2\\},\n Err(${3:_}) => {$0\\},\n}",
435 detail: "match expr {}",
436 },
437 CompletionItem {
438 label: "not",
439 source_range: 211..211,
440 delete: 207..211,
441 insert: "!bar",
442 detail: "!expr",
443 },
444 CompletionItem {
445 label: "ref",
446 source_range: 211..211,
447 delete: 207..211,
448 insert: "&bar",
449 detail: "&expr",
450 },
451 CompletionItem {
452 label: "refm",
453 source_range: 211..211,
454 delete: 207..211,
455 insert: "&mut bar",
456 detail: "&mut expr",
457 },
458 CompletionItem {
459 label: "while",
460 source_range: 211..211,
461 delete: 207..211,
462 insert: "while let Ok($1) = bar {\n $0\n}",
463 detail: "while let Ok {}",
464 },
465 ]
466 "###
467 );
468 }
469
470 #[test]
239 fn some_postfix_completions_ignored() { 471 fn some_postfix_completions_ignored() {
240 assert_debug_snapshot!( 472 assert_debug_snapshot!(
241 do_postfix_completion( 473 do_postfix_completion(
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs
index aa56a5cd8..02ac0166b 100644
--- a/crates/ra_ide/src/completion/complete_qualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_qualified_path.rs
@@ -2,20 +2,25 @@
2 2
3use hir::{Adt, HasVisibility, PathResolution, ScopeDef}; 3use hir::{Adt, HasVisibility, PathResolution, ScopeDef};
4use ra_syntax::AstNode; 4use ra_syntax::AstNode;
5use test_utils::tested_by; 5use rustc_hash::FxHashSet;
6use test_utils::mark;
6 7
7use crate::completion::{CompletionContext, Completions}; 8use crate::completion::{CompletionContext, Completions};
8use rustc_hash::FxHashSet;
9 9
10pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) { 10pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
11 let path = match &ctx.path_prefix { 11 let path = match &ctx.path_prefix {
12 Some(path) => path.clone(), 12 Some(path) => path.clone(),
13 _ => return, 13 None => return,
14 }; 14 };
15
16 if ctx.attribute_under_caret.is_some() {
17 return;
18 }
19
15 let scope = ctx.scope(); 20 let scope = ctx.scope();
16 let context_module = scope.module(); 21 let context_module = scope.module();
17 22
18 let res = match scope.resolve_hir_path(&path) { 23 let res = match scope.resolve_hir_path_qualifier(&path) {
19 Some(res) => res, 24 Some(res) => res,
20 None => return, 25 None => return,
21 }; 26 };
@@ -35,7 +40,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
35 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { 40 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
36 if name_ref.syntax().text() == name.to_string().as_str() { 41 if name_ref.syntax().text() == name.to_string().as_str() {
37 // for `use self::foo<|>`, don't suggest `foo` as a completion 42 // for `use self::foo<|>`, don't suggest `foo` as a completion
38 tested_by!(dont_complete_current_use); 43 mark::hit!(dont_complete_current_use);
39 continue; 44 continue;
40 } 45 }
41 } 46 }
@@ -79,7 +84,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
79 }); 84 });
80 85
81 // Iterate assoc types separately 86 // Iterate assoc types separately
82 ty.iterate_impl_items(ctx.db, krate, |item| { 87 ty.iterate_assoc_items(ctx.db, krate, |item| {
83 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { 88 if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
84 return None; 89 return None;
85 } 90 }
@@ -142,7 +147,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
142 147
143#[cfg(test)] 148#[cfg(test)]
144mod tests { 149mod tests {
145 use test_utils::covers; 150 use test_utils::mark;
146 151
147 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; 152 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
148 use insta::assert_debug_snapshot; 153 use insta::assert_debug_snapshot;
@@ -153,7 +158,7 @@ mod tests {
153 158
154 #[test] 159 #[test]
155 fn dont_complete_current_use() { 160 fn dont_complete_current_use() {
156 covers!(dont_complete_current_use); 161 mark::check!(dont_complete_current_use);
157 let completions = do_completion(r"use self::foo<|>;", CompletionKind::Reference); 162 let completions = do_completion(r"use self::foo<|>;", CompletionKind::Reference);
158 assert!(completions.is_empty()); 163 assert!(completions.is_empty());
159 } 164 }
@@ -221,6 +226,34 @@ mod tests {
221 } 226 }
222 227
223 #[test] 228 #[test]
229 fn completes_mod_with_same_name_as_function() {
230 assert_debug_snapshot!(
231 do_reference_completion(
232 r"
233 use self::my::<|>;
234
235 mod my {
236 pub struct Bar;
237 }
238
239 fn my() {}
240 "
241 ),
242 @r###"
243 [
244 CompletionItem {
245 label: "Bar",
246 source_range: 31..31,
247 delete: 31..31,
248 insert: "Bar",
249 kind: Struct,
250 },
251 ]
252 "###
253 );
254 }
255
256 #[test]
224 fn path_visibility() { 257 fn path_visibility() {
225 assert_debug_snapshot!( 258 assert_debug_snapshot!(
226 do_reference_completion( 259 do_reference_completion(
@@ -1325,4 +1358,18 @@ mod tests {
1325 "### 1358 "###
1326 ); 1359 );
1327 } 1360 }
1361
1362 #[test]
1363 fn dont_complete_attr() {
1364 assert_debug_snapshot!(
1365 do_reference_completion(
1366 r"
1367 mod foo { pub struct Foo; }
1368 #[foo::<|>]
1369 fn f() {}
1370 "
1371 ),
1372 @r###"[]"###
1373 )
1374 }
1328} 1375}
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs
index a3f5d1b6a..0568d9ccf 100644
--- a/crates/ra_ide/src/completion/complete_snippet.rs
+++ b/crates/ra_ide/src/completion/complete_snippet.rs
@@ -36,6 +36,24 @@ pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
36 snippet( 36 snippet(
37 ctx, 37 ctx,
38 cap, 38 cap,
39 "Test module",
40 "\
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn ${1:test_name}() {
47 $0
48 }
49}",
50 )
51 .lookup_by("tmod")
52 .add_to(acc);
53
54 snippet(
55 ctx,
56 cap,
39 "Test function", 57 "Test function",
40 "\ 58 "\
41#[test] 59#[test]
@@ -118,6 +136,14 @@ mod tests {
118 lookup: "tfn", 136 lookup: "tfn",
119 }, 137 },
120 CompletionItem { 138 CompletionItem {
139 label: "Test module",
140 source_range: 78..78,
141 delete: 78..78,
142 insert: "#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn ${1:test_name}() {\n $0\n }\n}",
143 kind: Snippet,
144 lookup: "tmod",
145 },
146 CompletionItem {
121 label: "macro_rules", 147 label: "macro_rules",
122 source_range: 78..78, 148 source_range: 78..78,
123 delete: 78..78, 149 delete: 78..78,
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs
index ee32d1ff6..039df03e0 100644
--- a/crates/ra_ide/src/completion/complete_trait_impl.rs
+++ b/crates/ra_ide/src/completion/complete_trait_impl.rs
@@ -32,7 +32,7 @@
32//! ``` 32//! ```
33 33
34use hir::{self, Docs, HasSource}; 34use hir::{self, Docs, HasSource};
35use ra_assists::utils::get_missing_impl_items; 35use ra_assists::utils::get_missing_assoc_items;
36use ra_syntax::{ 36use ra_syntax::{
37 ast::{self, edit, ImplDef}, 37 ast::{self, edit, ImplDef},
38 AstNode, SyntaxKind, SyntaxNode, TextRange, T, 38 AstNode, SyntaxKind, SyntaxNode, TextRange, T,
@@ -50,7 +50,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
50 if let Some((trigger, impl_def)) = completion_match(ctx) { 50 if let Some((trigger, impl_def)) = completion_match(ctx) {
51 match trigger.kind() { 51 match trigger.kind() {
52 SyntaxKind::NAME_REF => { 52 SyntaxKind::NAME_REF => {
53 get_missing_impl_items(&ctx.sema, &impl_def).iter().for_each(|item| match item { 53 get_missing_assoc_items(&ctx.sema, &impl_def).iter().for_each(|item| match item {
54 hir::AssocItem::Function(fn_item) => { 54 hir::AssocItem::Function(fn_item) => {
55 add_function_impl(&trigger, acc, ctx, &fn_item) 55 add_function_impl(&trigger, acc, ctx, &fn_item)
56 } 56 }
@@ -64,34 +64,40 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
64 } 64 }
65 65
66 SyntaxKind::FN_DEF => { 66 SyntaxKind::FN_DEF => {
67 for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( 67 for missing_fn in
68 |item| match item { 68 get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| {
69 hir::AssocItem::Function(fn_item) => Some(fn_item), 69 match item {
70 _ => None, 70 hir::AssocItem::Function(fn_item) => Some(fn_item),
71 }, 71 _ => None,
72 ) { 72 }
73 })
74 {
73 add_function_impl(&trigger, acc, ctx, &missing_fn); 75 add_function_impl(&trigger, acc, ctx, &missing_fn);
74 } 76 }
75 } 77 }
76 78
77 SyntaxKind::TYPE_ALIAS_DEF => { 79 SyntaxKind::TYPE_ALIAS_DEF => {
78 for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( 80 for missing_fn in
79 |item| match item { 81 get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| {
80 hir::AssocItem::TypeAlias(type_item) => Some(type_item), 82 match item {
81 _ => None, 83 hir::AssocItem::TypeAlias(type_item) => Some(type_item),
82 }, 84 _ => None,
83 ) { 85 }
86 })
87 {
84 add_type_alias_impl(&trigger, acc, ctx, &missing_fn); 88 add_type_alias_impl(&trigger, acc, ctx, &missing_fn);
85 } 89 }
86 } 90 }
87 91
88 SyntaxKind::CONST_DEF => { 92 SyntaxKind::CONST_DEF => {
89 for missing_fn in get_missing_impl_items(&ctx.sema, &impl_def).iter().filter_map( 93 for missing_fn in
90 |item| match item { 94 get_missing_assoc_items(&ctx.sema, &impl_def).iter().filter_map(|item| {
91 hir::AssocItem::Const(const_item) => Some(const_item), 95 match item {
92 _ => None, 96 hir::AssocItem::Const(const_item) => Some(const_item),
93 }, 97 _ => None,
94 ) { 98 }
99 })
100 {
95 add_const_impl(&trigger, acc, ctx, &missing_fn); 101 add_const_impl(&trigger, acc, ctx, &missing_fn);
96 } 102 }
97 } 103 }
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs
index a6a5568de..db791660a 100644
--- a/crates/ra_ide/src/completion/complete_unqualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs
@@ -1,16 +1,19 @@
1//! Completion of names from the current scope, e.g. locals and imported items. 1//! Completion of names from the current scope, e.g. locals and imported items.
2 2
3use hir::ScopeDef; 3use hir::ScopeDef;
4use test_utils::tested_by; 4use test_utils::mark;
5 5
6use crate::completion::{CompletionContext, Completions}; 6use crate::completion::{CompletionContext, Completions};
7use hir::{Adt, ModuleDef, Type}; 7use hir::{Adt, ModuleDef, Type};
8use ra_syntax::AstNode; 8use ra_syntax::AstNode;
9 9
10pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { 10pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
11 if (!ctx.is_trivial_path && !ctx.is_pat_binding_or_const) 11 if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) {
12 || ctx.record_lit_syntax.is_some() 12 return;
13 }
14 if ctx.record_lit_syntax.is_some()
13 || ctx.record_pat_syntax.is_some() 15 || ctx.record_pat_syntax.is_some()
16 || ctx.attribute_under_caret.is_some()
14 { 17 {
15 return; 18 return;
16 } 19 }
@@ -27,7 +30,7 @@ pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
27 if ctx.use_item_syntax.is_some() { 30 if ctx.use_item_syntax.is_some() {
28 if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) { 31 if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) {
29 if name_ref.syntax().text() == name.to_string().as_str() { 32 if name_ref.syntax().text() == name.to_string().as_str() {
30 tested_by!(self_fulfilling_completion); 33 mark::hit!(self_fulfilling_completion);
31 return; 34 return;
32 } 35 }
33 } 36 }
@@ -63,7 +66,7 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
63#[cfg(test)] 66#[cfg(test)]
64mod tests { 67mod tests {
65 use insta::assert_debug_snapshot; 68 use insta::assert_debug_snapshot;
66 use test_utils::covers; 69 use test_utils::mark;
67 70
68 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; 71 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
69 72
@@ -73,7 +76,7 @@ mod tests {
73 76
74 #[test] 77 #[test]
75 fn self_fulfilling_completion() { 78 fn self_fulfilling_completion() {
76 covers!(self_fulfilling_completion); 79 mark::check!(self_fulfilling_completion);
77 assert_debug_snapshot!( 80 assert_debug_snapshot!(
78 do_reference_completion( 81 do_reference_completion(
79 r#" 82 r#"
@@ -1369,4 +1372,18 @@ mod tests {
1369 "### 1372 "###
1370 ) 1373 )
1371 } 1374 }
1375
1376 #[test]
1377 fn dont_complete_attr() {
1378 assert_debug_snapshot!(
1379 do_reference_completion(
1380 r"
1381 struct Foo;
1382 #[<|>]
1383 fn f() {}
1384 "
1385 ),
1386 @r###"[]"###
1387 )
1388 }
1372} 1389}
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 118fceb2e..da336973c 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -9,7 +9,7 @@ use ra_syntax::{
9 SyntaxKind::*, 9 SyntaxKind::*,
10 SyntaxNode, SyntaxToken, TextRange, TextSize, 10 SyntaxNode, SyntaxToken, TextRange, TextSize,
11}; 11};
12use ra_text_edit::AtomTextEdit; 12use ra_text_edit::Indel;
13 13
14use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; 14use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition};
15 15
@@ -34,7 +34,7 @@ pub(crate) struct CompletionContext<'a> {
34 pub(super) record_pat_syntax: Option<ast::RecordPat>, 34 pub(super) record_pat_syntax: Option<ast::RecordPat>,
35 pub(super) record_field_syntax: Option<ast::RecordField>, 35 pub(super) record_field_syntax: Option<ast::RecordField>,
36 pub(super) impl_def: Option<ast::ImplDef>, 36 pub(super) impl_def: Option<ast::ImplDef>,
37 /// FIXME: `ActiveParameter` is string-based, which is very wrong 37 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
38 pub(super) active_parameter: Option<ActiveParameter>, 38 pub(super) active_parameter: Option<ActiveParameter>,
39 pub(super) is_param: bool, 39 pub(super) is_param: bool,
40 /// If a name-binding or reference to a const in a pattern. 40 /// If a name-binding or reference to a const in a pattern.
@@ -58,7 +58,7 @@ pub(crate) struct CompletionContext<'a> {
58 pub(super) is_macro_call: bool, 58 pub(super) is_macro_call: bool,
59 pub(super) is_path_type: bool, 59 pub(super) is_path_type: bool,
60 pub(super) has_type_args: bool, 60 pub(super) has_type_args: bool,
61 pub(super) is_attribute: bool, 61 pub(super) attribute_under_caret: Option<ast::Attr>,
62} 62}
63 63
64impl<'a> CompletionContext<'a> { 64impl<'a> CompletionContext<'a> {
@@ -76,7 +76,7 @@ impl<'a> CompletionContext<'a> {
76 // actual completion. 76 // actual completion.
77 let file_with_fake_ident = { 77 let file_with_fake_ident = {
78 let parse = db.parse(position.file_id); 78 let parse = db.parse(position.file_id);
79 let edit = AtomTextEdit::insert(position.offset, "intellijRulezz".to_string()); 79 let edit = Indel::insert(position.offset, "intellijRulezz".to_string());
80 parse.reparse(&edit).tree() 80 parse.reparse(&edit).tree()
81 }; 81 };
82 let fake_ident_token = 82 let fake_ident_token =
@@ -116,7 +116,7 @@ impl<'a> CompletionContext<'a> {
116 is_path_type: false, 116 is_path_type: false,
117 has_type_args: false, 117 has_type_args: false,
118 dot_receiver_is_ambiguous_float_literal: false, 118 dot_receiver_is_ambiguous_float_literal: false,
119 is_attribute: false, 119 attribute_under_caret: None,
120 }; 120 };
121 121
122 let mut original_file = original_file.syntax().clone(); 122 let mut original_file = original_file.syntax().clone();
@@ -200,6 +200,7 @@ impl<'a> CompletionContext<'a> {
200 Some(ty) 200 Some(ty)
201 }) 201 })
202 .flatten(); 202 .flatten();
203 self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset);
203 204
204 // First, let's try to complete a reference to some declaration. 205 // First, let's try to complete a reference to some declaration.
205 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&file_with_fake_ident, offset) { 206 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(&file_with_fake_ident, offset) {
@@ -318,7 +319,6 @@ impl<'a> CompletionContext<'a> {
318 .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) 319 .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast))
319 .is_some(); 320 .is_some();
320 self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some(); 321 self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some();
321 self.is_attribute = path.syntax().parent().and_then(ast::Attr::cast).is_some();
322 322
323 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); 323 self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some();
324 self.has_type_args = segment.type_arg_list().is_some(); 324 self.has_type_args = segment.type_arg_list().is_some();
@@ -344,7 +344,7 @@ impl<'a> CompletionContext<'a> {
344 stmt.syntax().text_range() == name_ref.syntax().text_range(), 344 stmt.syntax().text_range() == name_ref.syntax().text_range(),
345 ); 345 );
346 } 346 }
347 if let Some(block) = ast::Block::cast(node) { 347 if let Some(block) = ast::BlockExpr::cast(node) {
348 return Some( 348 return Some(
349 block.expr().map(|e| e.syntax().text_range()) 349 block.expr().map(|e| e.syntax().text_range())
350 == Some(name_ref.syntax().text_range()), 350 == Some(name_ref.syntax().text_range()),
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index 5936fb8f7..cfb7c1e38 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -2,11 +2,12 @@
2 2
3use std::fmt; 3use std::fmt;
4 4
5use super::completion_config::SnippetCap;
6use hir::Documentation; 5use hir::Documentation;
7use ra_syntax::TextRange; 6use ra_syntax::TextRange;
8use ra_text_edit::TextEdit; 7use ra_text_edit::TextEdit;
9 8
9use crate::completion::completion_config::SnippetCap;
10
10/// `CompletionItem` describes a single completion variant in the editor pop-up. 11/// `CompletionItem` describes a single completion variant in the editor pop-up.
11/// It is basically a POD with various properties. To construct a 12/// It is basically a POD with various properties. To construct a
12/// `CompletionItem`, use `new` method and the `Builder` struct. 13/// `CompletionItem`, use `new` method and the `Builder` struct.
@@ -62,8 +63,8 @@ impl fmt::Debug for CompletionItem {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 let mut s = f.debug_struct("CompletionItem"); 64 let mut s = f.debug_struct("CompletionItem");
64 s.field("label", &self.label()).field("source_range", &self.source_range()); 65 s.field("label", &self.label()).field("source_range", &self.source_range());
65 if self.text_edit().as_atoms().len() == 1 { 66 if self.text_edit().len() == 1 {
66 let atom = &self.text_edit().as_atoms()[0]; 67 let atom = &self.text_edit().iter().next().unwrap();
67 s.field("delete", &atom.delete); 68 s.field("delete", &atom.delete);
68 s.field("insert", &atom.insert); 69 s.field("insert", &atom.insert);
69 } else { 70 } else {
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 2edb130cf..440ffa31d 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -3,7 +3,7 @@
3use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type}; 3use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type};
4use ra_syntax::ast::NameOwner; 4use ra_syntax::ast::NameOwner;
5use stdx::SepBy; 5use stdx::SepBy;
6use test_utils::tested_by; 6use test_utils::mark;
7 7
8use crate::{ 8use crate::{
9 completion::{ 9 completion::{
@@ -17,12 +17,11 @@ use crate::{
17impl Completions { 17impl Completions {
18 pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) { 18 pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) {
19 let is_deprecated = is_deprecated(field, ctx.db); 19 let is_deprecated = is_deprecated(field, ctx.db);
20 let ty = ty.display(ctx.db).to_string();
21 let name = field.name(ctx.db); 20 let name = field.name(ctx.db);
22 let mut completion_item = 21 let mut completion_item =
23 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) 22 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
24 .kind(CompletionItemKind::Field) 23 .kind(CompletionItemKind::Field)
25 .detail(ty.clone()) 24 .detail(ty.display(ctx.db).to_string())
26 .set_documentation(field.docs(ctx.db)) 25 .set_documentation(field.docs(ctx.db))
27 .set_deprecated(is_deprecated); 26 .set_deprecated(is_deprecated);
28 27
@@ -107,6 +106,12 @@ impl Completions {
107 } 106 }
108 }; 107 };
109 108
109 if let ScopeDef::Local(local) = resolution {
110 if let Some(score) = compute_score(ctx, &local.ty(ctx.db), &local_name) {
111 completion_item = completion_item.set_score(score);
112 }
113 }
114
110 // Add `<>` for generic types 115 // Add `<>` for generic types
111 if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis { 116 if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis {
112 if let Some(cap) = ctx.config.snippet_cap { 117 if let Some(cap) = ctx.config.snippet_cap {
@@ -116,7 +121,7 @@ impl Completions {
116 _ => false, 121 _ => false,
117 }; 122 };
118 if has_non_default_type_params { 123 if has_non_default_type_params {
119 tested_by!(inserts_angle_brackets_for_generics); 124 mark::hit!(inserts_angle_brackets_for_generics);
120 completion_item = completion_item 125 completion_item = completion_item
121 .lookup_by(local_name.clone()) 126 .lookup_by(local_name.clone())
122 .label(format!("{}<…>", local_name)) 127 .label(format!("{}<…>", local_name))
@@ -171,7 +176,7 @@ impl Completions {
171 } 176 }
172 None if needs_bang => builder.insert_text(format!("{}!", name)), 177 None if needs_bang => builder.insert_text(format!("{}!", name)),
173 _ => { 178 _ => {
174 tested_by!(dont_insert_macro_call_parens_unncessary); 179 mark::hit!(dont_insert_macro_call_parens_unncessary);
175 builder.insert_text(name) 180 builder.insert_text(name)
176 } 181 }
177 }; 182 };
@@ -319,19 +324,20 @@ impl Completions {
319 324
320pub(crate) fn compute_score( 325pub(crate) fn compute_score(
321 ctx: &CompletionContext, 326 ctx: &CompletionContext,
322 // FIXME: this definitely should be a `Type` 327 ty: &Type,
323 ty: &str,
324 name: &str, 328 name: &str,
325) -> Option<CompletionScore> { 329) -> Option<CompletionScore> {
330 // FIXME: this should not fall back to string equality.
331 let ty = &ty.display(ctx.db).to_string();
326 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { 332 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
327 tested_by!(test_struct_field_completion_in_record_lit); 333 mark::hit!(test_struct_field_completion_in_record_lit);
328 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; 334 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?;
329 ( 335 (
330 struct_field.name(ctx.db).to_string(), 336 struct_field.name(ctx.db).to_string(),
331 struct_field.signature_ty(ctx.db).display(ctx.db).to_string(), 337 struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
332 ) 338 )
333 } else if let Some(active_parameter) = &ctx.active_parameter { 339 } else if let Some(active_parameter) = &ctx.active_parameter {
334 tested_by!(test_struct_field_completion_in_func_call); 340 mark::hit!(test_struct_field_completion_in_func_call);
335 (active_parameter.name.clone(), active_parameter.ty.clone()) 341 (active_parameter.name.clone(), active_parameter.ty.clone())
336 } else { 342 } else {
337 return None; 343 return None;
@@ -392,7 +398,7 @@ impl Builder {
392 None => return self, 398 None => return self,
393 }; 399 };
394 // If not an import, add parenthesis automatically. 400 // If not an import, add parenthesis automatically.
395 tested_by!(inserts_parens_for_function_calls); 401 mark::hit!(inserts_parens_for_function_calls);
396 402
397 let (snippet, label) = if params.is_empty() { 403 let (snippet, label) = if params.is_empty() {
398 (format!("{}()$0", name), format!("{}()", name)) 404 (format!("{}()$0", name), format!("{}()", name))
@@ -451,7 +457,7 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s
451#[cfg(test)] 457#[cfg(test)]
452mod tests { 458mod tests {
453 use insta::assert_debug_snapshot; 459 use insta::assert_debug_snapshot;
454 use test_utils::covers; 460 use test_utils::mark;
455 461
456 use crate::completion::{ 462 use crate::completion::{
457 test_utils::{do_completion, do_completion_with_options}, 463 test_utils::{do_completion, do_completion_with_options},
@@ -601,7 +607,7 @@ mod tests {
601 607
602 #[test] 608 #[test]
603 fn inserts_parens_for_function_calls() { 609 fn inserts_parens_for_function_calls() {
604 covers!(inserts_parens_for_function_calls); 610 mark::check!(inserts_parens_for_function_calls);
605 assert_debug_snapshot!( 611 assert_debug_snapshot!(
606 do_reference_completion( 612 do_reference_completion(
607 r" 613 r"
@@ -986,7 +992,7 @@ mod tests {
986 992
987 #[test] 993 #[test]
988 fn inserts_angle_brackets_for_generics() { 994 fn inserts_angle_brackets_for_generics() {
989 covers!(inserts_angle_brackets_for_generics); 995 mark::check!(inserts_angle_brackets_for_generics);
990 assert_debug_snapshot!( 996 assert_debug_snapshot!(
991 do_reference_completion( 997 do_reference_completion(
992 r" 998 r"
@@ -1109,7 +1115,7 @@ mod tests {
1109 1115
1110 #[test] 1116 #[test]
1111 fn dont_insert_macro_call_parens_unncessary() { 1117 fn dont_insert_macro_call_parens_unncessary() {
1112 covers!(dont_insert_macro_call_parens_unncessary); 1118 mark::check!(dont_insert_macro_call_parens_unncessary);
1113 assert_debug_snapshot!( 1119 assert_debug_snapshot!(
1114 do_reference_completion( 1120 do_reference_completion(
1115 r" 1121 r"
@@ -1175,7 +1181,7 @@ mod tests {
1175 1181
1176 #[test] 1182 #[test]
1177 fn test_struct_field_completion_in_func_call() { 1183 fn test_struct_field_completion_in_func_call() {
1178 covers!(test_struct_field_completion_in_func_call); 1184 mark::check!(test_struct_field_completion_in_func_call);
1179 assert_debug_snapshot!( 1185 assert_debug_snapshot!(
1180 do_reference_completion( 1186 do_reference_completion(
1181 r" 1187 r"
@@ -1265,7 +1271,7 @@ mod tests {
1265 1271
1266 #[test] 1272 #[test]
1267 fn test_struct_field_completion_in_record_lit() { 1273 fn test_struct_field_completion_in_record_lit() {
1268 covers!(test_struct_field_completion_in_record_lit); 1274 mark::check!(test_struct_field_completion_in_record_lit);
1269 assert_debug_snapshot!( 1275 assert_debug_snapshot!(
1270 do_reference_completion( 1276 do_reference_completion(
1271 r" 1277 r"
@@ -1405,4 +1411,48 @@ mod tests {
1405 "### 1411 "###
1406 ); 1412 );
1407 } 1413 }
1414
1415 #[test]
1416 fn prioritize_exact_ref_match() {
1417 assert_debug_snapshot!(
1418 do_reference_completion(
1419 r"
1420 struct WorldSnapshot { _f: () };
1421 fn go(world: &WorldSnapshot) {
1422 go(w<|>)
1423 }
1424 ",
1425 ),
1426 @r###"
1427 [
1428 CompletionItem {
1429 label: "WorldSnapshot",
1430 source_range: 132..133,
1431 delete: 132..133,
1432 insert: "WorldSnapshot",
1433 kind: Struct,
1434 },
1435 CompletionItem {
1436 label: "go(…)",
1437 source_range: 132..133,
1438 delete: 132..133,
1439 insert: "go(${1:world})$0",
1440 kind: Function,
1441 lookup: "go",
1442 detail: "fn go(world: &WorldSnapshot)",
1443 trigger_call_info: true,
1444 },
1445 CompletionItem {
1446 label: "world",
1447 source_range: 132..133,
1448 delete: 132..133,
1449 insert: "world",
1450 kind: Binding,
1451 detail: "&WorldSnapshot",
1452 score: TypeAndNameMatch,
1453 },
1454 ]
1455 "###
1456 );
1457 }
1408} 1458}
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index eb90b5279..bf22452a2 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -20,7 +20,7 @@ pub(crate) fn do_completion_with_options(
20 } else { 20 } else {
21 single_file_with_position(code) 21 single_file_with_position(code)
22 }; 22 };
23 let completions = analysis.completions(position, options).unwrap().unwrap(); 23 let completions = analysis.completions(options, position).unwrap().unwrap();
24 let completion_items: Vec<CompletionItem> = completions.into(); 24 let completion_items: Vec<CompletionItem> = completions.into();
25 let mut kind_completions: Vec<CompletionItem> = 25 let mut kind_completions: Vec<CompletionItem> =
26 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); 26 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index a6b4c2c28..c2819bbf7 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -64,7 +64,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
64 .unwrap_or_else(|| RelativePath::new("")) 64 .unwrap_or_else(|| RelativePath::new(""))
65 .join(&d.candidate); 65 .join(&d.candidate);
66 let create_file = FileSystemEdit::CreateFile { source_root, path }; 66 let create_file = FileSystemEdit::CreateFile { source_root, path };
67 let fix = SourceChange::file_system_edit("create module", create_file); 67 let fix = SourceChange::file_system_edit("Create module", create_file);
68 res.borrow_mut().push(Diagnostic { 68 res.borrow_mut().push(Diagnostic {
69 range: sema.diagnostics_range(d).range, 69 range: sema.diagnostics_range(d).range,
70 message: d.message(), 70 message: d.message(),
@@ -92,7 +92,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
92 algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder); 92 algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder);
93 93
94 Some(SourceChange::source_file_edit_from( 94 Some(SourceChange::source_file_edit_from(
95 "fill struct fields", 95 "Fill struct fields",
96 file_id, 96 file_id,
97 builder.finish(), 97 builder.finish(),
98 )) 98 ))
@@ -117,7 +117,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
117 let node = d.ast(db); 117 let node = d.ast(db);
118 let replacement = format!("Ok({})", node.syntax()); 118 let replacement = format!("Ok({})", node.syntax());
119 let edit = TextEdit::replace(node.syntax().text_range(), replacement); 119 let edit = TextEdit::replace(node.syntax().text_range(), replacement);
120 let fix = SourceChange::source_file_edit_from("wrap with ok", file_id, edit); 120 let fix = SourceChange::source_file_edit_from("Wrap with ok", file_id, edit);
121 res.borrow_mut().push(Diagnostic { 121 res.borrow_mut().push(Diagnostic {
122 range: sema.diagnostics_range(d).range, 122 range: sema.diagnostics_range(d).range,
123 message: d.message(), 123 message: d.message(),
@@ -199,7 +199,7 @@ fn check_struct_shorthand_initialization(
199 message: "Shorthand struct initialization".to_string(), 199 message: "Shorthand struct initialization".to_string(),
200 severity: Severity::WeakWarning, 200 severity: Severity::WeakWarning,
201 fix: Some(SourceChange::source_file_edit( 201 fix: Some(SourceChange::source_file_edit(
202 "use struct shorthand initialization", 202 "Use struct shorthand initialization",
203 SourceFileEdit { file_id, edit }, 203 SourceFileEdit { file_id, edit },
204 )), 204 )),
205 }); 205 });
@@ -241,7 +241,11 @@ mod tests {
241 diagnostics.pop().unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before)); 241 diagnostics.pop().unwrap_or_else(|| panic!("no diagnostics for:\n{}\n", before));
242 let mut fix = diagnostic.fix.unwrap(); 242 let mut fix = diagnostic.fix.unwrap();
243 let edit = fix.source_file_edits.pop().unwrap().edit; 243 let edit = fix.source_file_edits.pop().unwrap().edit;
244 let actual = edit.apply(&before); 244 let actual = {
245 let mut actual = before.to_string();
246 edit.apply(&mut actual);
247 actual
248 };
245 assert_eq_text!(after, &actual); 249 assert_eq_text!(after, &actual);
246 } 250 }
247 251
@@ -256,7 +260,11 @@ mod tests {
256 let mut fix = diagnostic.fix.unwrap(); 260 let mut fix = diagnostic.fix.unwrap();
257 let edit = fix.source_file_edits.pop().unwrap().edit; 261 let edit = fix.source_file_edits.pop().unwrap().edit;
258 let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); 262 let target_file_contents = analysis.file_text(file_position.file_id).unwrap();
259 let actual = edit.apply(&target_file_contents); 263 let actual = {
264 let mut actual = target_file_contents.to_string();
265 edit.apply(&mut actual);
266 actual
267 };
260 268
261 // Strip indent and empty lines from `after`, to match the behaviour of 269 // Strip indent and empty lines from `after`, to match the behaviour of
262 // `parse_fixture` called from `analysis_and_position`. 270 // `parse_fixture` called from `analysis_and_position`.
@@ -288,7 +296,11 @@ mod tests {
288 let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap(); 296 let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap();
289 let mut fix = diagnostic.fix.unwrap(); 297 let mut fix = diagnostic.fix.unwrap();
290 let edit = fix.source_file_edits.pop().unwrap().edit; 298 let edit = fix.source_file_edits.pop().unwrap().edit;
291 let actual = edit.apply(&before); 299 let actual = {
300 let mut actual = before.to_string();
301 edit.apply(&mut actual);
302 actual
303 };
292 assert_eq_text!(after, &actual); 304 assert_eq_text!(after, &actual);
293 } 305 }
294 306
@@ -606,7 +618,7 @@ mod tests {
606 range: 0..8, 618 range: 0..8,
607 fix: Some( 619 fix: Some(
608 SourceChange { 620 SourceChange {
609 label: "create module", 621 label: "Create module",
610 source_file_edits: [], 622 source_file_edits: [],
611 file_system_edits: [ 623 file_system_edits: [
612 CreateFile { 624 CreateFile {
@@ -616,7 +628,7 @@ mod tests {
616 path: "foo.rs", 628 path: "foo.rs",
617 }, 629 },
618 ], 630 ],
619 cursor_position: None, 631 is_snippet: false,
620 }, 632 },
621 ), 633 ),
622 severity: Error, 634 severity: Error,
@@ -655,24 +667,24 @@ mod tests {
655 range: 224..233, 667 range: 224..233,
656 fix: Some( 668 fix: Some(
657 SourceChange { 669 SourceChange {
658 label: "fill struct fields", 670 label: "Fill struct fields",
659 source_file_edits: [ 671 source_file_edits: [
660 SourceFileEdit { 672 SourceFileEdit {
661 file_id: FileId( 673 file_id: FileId(
662 1, 674 1,
663 ), 675 ),
664 edit: TextEdit { 676 edit: TextEdit {
665 atoms: [ 677 indels: [
666 AtomTextEdit { 678 Indel {
667 delete: 3..9,
668 insert: "{a:42, b: ()}", 679 insert: "{a:42, b: ()}",
680 delete: 3..9,
669 }, 681 },
670 ], 682 ],
671 }, 683 },
672 }, 684 },
673 ], 685 ],
674 file_system_edits: [], 686 file_system_edits: [],
675 cursor_position: None, 687 is_snippet: false,
676 }, 688 },
677 ), 689 ),
678 severity: Error, 690 severity: Error,
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs
index db3907fe6..9572debd8 100644
--- a/crates/ra_ide/src/display/function_signature.rs
+++ b/crates/ra_ide/src/display/function_signature.rs
@@ -1,5 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3// FIXME: this modules relies on strings and AST way too much, and it should be
4// rewritten (matklad 2020-05-07)
3use std::{ 5use std::{
4 convert::From, 6 convert::From,
5 fmt::{self, Display}, 7 fmt::{self, Display},
@@ -82,8 +84,8 @@ impl FunctionSignature {
82 let ty = field.signature_ty(db); 84 let ty = field.signature_ty(db);
83 let raw_param = format!("{}", ty.display(db)); 85 let raw_param = format!("{}", ty.display(db));
84 86
85 if let Some(param_type) = raw_param.split(':').nth(1) { 87 if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) {
86 parameter_types.push(param_type[1..].to_string()); 88 parameter_types.push(param_type.to_string());
87 } else { 89 } else {
88 // useful when you have tuple struct 90 // useful when you have tuple struct
89 parameter_types.push(raw_param.clone()); 91 parameter_types.push(raw_param.clone());
@@ -127,8 +129,8 @@ impl FunctionSignature {
127 for field in variant.fields(db).into_iter() { 129 for field in variant.fields(db).into_iter() {
128 let ty = field.signature_ty(db); 130 let ty = field.signature_ty(db);
129 let raw_param = format!("{}", ty.display(db)); 131 let raw_param = format!("{}", ty.display(db));
130 if let Some(param_type) = raw_param.split(':').nth(1) { 132 if let Some(param_type) = raw_param.split(':').nth(1).and_then(|it| it.get(1..)) {
131 parameter_types.push(param_type[1..].to_string()); 133 parameter_types.push(param_type.to_string());
132 } else { 134 } else {
133 // The unwrap_or_else is useful when you have tuple 135 // The unwrap_or_else is useful when you have tuple
134 parameter_types.push(raw_param); 136 parameter_types.push(raw_param);
@@ -195,14 +197,23 @@ impl From<&'_ ast::FnDef> for FunctionSignature {
195 let raw_param = self_param.syntax().text().to_string(); 197 let raw_param = self_param.syntax().text().to_string();
196 198
197 res_types.push( 199 res_types.push(
198 raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(), 200 raw_param
201 .split(':')
202 .nth(1)
203 .and_then(|it| it.get(1..))
204 .unwrap_or_else(|| "Self")
205 .to_string(),
199 ); 206 );
200 res.push(raw_param); 207 res.push(raw_param);
201 } 208 }
202 209
203 res.extend(param_list.params().map(|param| param.syntax().text().to_string())); 210 res.extend(param_list.params().map(|param| param.syntax().text().to_string()));
204 res_types.extend(param_list.params().map(|param| { 211 res_types.extend(param_list.params().map(|param| {
205 param.syntax().text().to_string().split(':').nth(1).unwrap()[1..].to_string() 212 let param_text = param.syntax().text().to_string();
213 match param_text.split(':').nth(1).and_then(|it| it.get(1..)) {
214 Some(it) => it.to_string(),
215 None => param_text,
216 }
206 })); 217 }));
207 } 218 }
208 (has_self_param, res, res_types) 219 (has_self_param, res, res_types)
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index 914a8b471..5da28edd2 100644
--- a/crates/ra_ide/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11 TextRange, 11 TextRange,
12}; 12};
13 13
14use crate::FileSymbol; 14use crate::{FileRange, FileSymbol};
15 15
16use super::short_label::ShortLabel; 16use super::short_label::ShortLabel;
17 17
@@ -22,10 +22,11 @@ use super::short_label::ShortLabel;
22/// code, like a function or a struct, but this is not strictly required. 22/// code, like a function or a struct, but this is not strictly required.
23#[derive(Debug, Clone, PartialEq, Eq, Hash)] 23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct NavigationTarget { 24pub struct NavigationTarget {
25 // FIXME: use FileRange?
25 file_id: FileId, 26 file_id: FileId,
27 full_range: TextRange,
26 name: SmolStr, 28 name: SmolStr,
27 kind: SyntaxKind, 29 kind: SyntaxKind,
28 full_range: TextRange,
29 focus_range: Option<TextRange>, 30 focus_range: Option<TextRange>,
30 container_name: Option<SmolStr>, 31 container_name: Option<SmolStr>,
31 description: Option<String>, 32 description: Option<String>,
@@ -63,6 +64,10 @@ impl NavigationTarget {
63 self.file_id 64 self.file_id
64 } 65 }
65 66
67 pub fn file_range(&self) -> FileRange {
68 FileRange { file_id: self.file_id, range: self.full_range }
69 }
70
66 pub fn full_range(&self) -> TextRange { 71 pub fn full_range(&self) -> TextRange {
67 self.full_range 72 self.full_range
68 } 73 }
@@ -376,16 +381,20 @@ impl ToNav for hir::Local {
376impl ToNav for hir::TypeParam { 381impl ToNav for hir::TypeParam {
377 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 382 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
378 let src = self.source(db); 383 let src = self.source(db);
379 let range = match src.value { 384 let full_range = match &src.value {
380 Either::Left(it) => it.syntax().text_range(), 385 Either::Left(it) => it.syntax().text_range(),
381 Either::Right(it) => it.syntax().text_range(), 386 Either::Right(it) => it.syntax().text_range(),
382 }; 387 };
388 let focus_range = match &src.value {
389 Either::Left(_) => None,
390 Either::Right(it) => it.name().map(|it| it.syntax().text_range()),
391 };
383 NavigationTarget { 392 NavigationTarget {
384 file_id: src.file_id.original_file(db), 393 file_id: src.file_id.original_file(db),
385 name: self.name(db).to_string().into(), 394 name: self.name(db).to_string().into(),
386 kind: TYPE_PARAM, 395 kind: TYPE_PARAM,
387 full_range: range, 396 full_range,
388 focus_range: None, 397 focus_range,
389 container_name: None, 398 container_name: None,
390 description: None, 399 description: None,
391 docs: None, 400 docs: None,
diff --git a/crates/ra_ide/src/folding_ranges.rs b/crates/ra_ide/src/folding_ranges.rs
index 4379005aa..8657377de 100644
--- a/crates/ra_ide/src/folding_ranges.rs
+++ b/crates/ra_ide/src/folding_ranges.rs
@@ -88,7 +88,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
88 | ITEM_LIST 88 | ITEM_LIST
89 | EXTERN_ITEM_LIST 89 | EXTERN_ITEM_LIST
90 | USE_TREE_LIST 90 | USE_TREE_LIST
91 | BLOCK 91 | BLOCK_EXPR
92 | MATCH_ARM_LIST 92 | MATCH_ARM_LIST
93 | ENUM_VARIANT_LIST 93 | ENUM_VARIANT_LIST
94 | TOKEN_TREE => Some(FoldKind::Block), 94 | TOKEN_TREE => Some(FoldKind::Block),
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index 1dfca819d..90e85d419 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -93,7 +93,7 @@ pub(crate) fn reference_definition(
93 93
94#[cfg(test)] 94#[cfg(test)]
95mod tests { 95mod tests {
96 use test_utils::{assert_eq_text, covers}; 96 use test_utils::assert_eq_text;
97 97
98 use crate::mock_analysis::analysis_and_position; 98 use crate::mock_analysis::analysis_and_position;
99 99
@@ -208,7 +208,6 @@ mod tests {
208 208
209 #[test] 209 #[test]
210 fn goto_def_for_macros() { 210 fn goto_def_for_macros() {
211 covers!(ra_ide_db::goto_def_for_macros);
212 check_goto( 211 check_goto(
213 " 212 "
214 //- /lib.rs 213 //- /lib.rs
@@ -225,7 +224,6 @@ mod tests {
225 224
226 #[test] 225 #[test]
227 fn goto_def_for_macros_from_other_crates() { 226 fn goto_def_for_macros_from_other_crates() {
228 covers!(ra_ide_db::goto_def_for_macros);
229 check_goto( 227 check_goto(
230 " 228 "
231 //- /lib.rs 229 //- /lib.rs
@@ -244,6 +242,38 @@ mod tests {
244 } 242 }
245 243
246 #[test] 244 #[test]
245 fn goto_def_for_use_alias() {
246 check_goto(
247 "
248 //- /lib.rs
249 use foo as bar<|>;
250
251
252 //- /foo/lib.rs
253 #[macro_export]
254 macro_rules! foo { () => { () } }",
255 "SOURCE_FILE FileId(2) 0..50",
256 "#[macro_export]\nmacro_rules! foo { () => { () } }\n",
257 );
258 }
259
260 #[test]
261 fn goto_def_for_use_alias_foo_macro() {
262 check_goto(
263 "
264 //- /lib.rs
265 use foo::foo as bar<|>;
266
267 //- /foo/lib.rs
268 #[macro_export]
269 macro_rules! foo { () => { () } }
270 ",
271 "foo MACRO_CALL FileId(2) 0..49 29..32",
272 "#[macro_export]\nmacro_rules! foo { () => { () } }|foo",
273 );
274 }
275
276 #[test]
247 fn goto_def_for_macros_in_use_tree() { 277 fn goto_def_for_macros_in_use_tree() {
248 check_goto( 278 check_goto(
249 " 279 "
@@ -337,7 +367,6 @@ mod tests {
337 367
338 #[test] 368 #[test]
339 fn goto_def_for_methods() { 369 fn goto_def_for_methods() {
340 covers!(ra_ide_db::goto_def_for_methods);
341 check_goto( 370 check_goto(
342 " 371 "
343 //- /lib.rs 372 //- /lib.rs
@@ -357,7 +386,6 @@ mod tests {
357 386
358 #[test] 387 #[test]
359 fn goto_def_for_fields() { 388 fn goto_def_for_fields() {
360 covers!(ra_ide_db::goto_def_for_fields);
361 check_goto( 389 check_goto(
362 r" 390 r"
363 //- /lib.rs 391 //- /lib.rs
@@ -376,7 +404,6 @@ mod tests {
376 404
377 #[test] 405 #[test]
378 fn goto_def_for_record_fields() { 406 fn goto_def_for_record_fields() {
379 covers!(ra_ide_db::goto_def_for_record_fields);
380 check_goto( 407 check_goto(
381 r" 408 r"
382 //- /lib.rs 409 //- /lib.rs
@@ -397,7 +424,6 @@ mod tests {
397 424
398 #[test] 425 #[test]
399 fn goto_def_for_record_pat_fields() { 426 fn goto_def_for_record_pat_fields() {
400 covers!(ra_ide_db::goto_def_for_record_field_pats);
401 check_goto( 427 check_goto(
402 r" 428 r"
403 //- /lib.rs 429 //- /lib.rs
@@ -754,14 +780,14 @@ mod tests {
754 #[test] 780 #[test]
755 fn goto_for_type_param() { 781 fn goto_for_type_param() {
756 check_goto( 782 check_goto(
757 " 783 r#"
758 //- /lib.rs 784 //- /lib.rs
759 struct Foo<T> { 785 struct Foo<T: Clone> {
760 t: <|>T, 786 t: <|>T,
761 } 787 }
762 ", 788 "#,
763 "T TYPE_PARAM FileId(1) 11..12", 789 "T TYPE_PARAM FileId(1) 11..19 11..12",
764 "T", 790 "T: Clone|T",
765 ); 791 );
766 } 792 }
767 793
@@ -840,7 +866,6 @@ mod tests {
840 866
841 #[test] 867 #[test]
842 fn goto_def_for_field_init_shorthand() { 868 fn goto_def_for_field_init_shorthand() {
843 covers!(ra_ide_db::goto_def_for_field_init_shorthand);
844 check_goto( 869 check_goto(
845 " 870 "
846 //- /lib.rs 871 //- /lib.rs
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 54d318858..befa977c7 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -143,7 +143,7 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin
143 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), 143 ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path),
144 ModuleDef::BuiltinType(it) => Some(it.to_string()), 144 ModuleDef::BuiltinType(it) => Some(it.to_string()),
145 }, 145 },
146 Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display_truncated(db, None))), 146 Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display(db))),
147 Definition::TypeParam(_) | Definition::SelfType(_) => { 147 Definition::TypeParam(_) | Definition::SelfType(_) => {
148 // FIXME: Hover for generic param 148 // FIXME: Hover for generic param
149 None 149 None
@@ -208,7 +208,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
208 } 208 }
209 }?; 209 }?;
210 210
211 res.extend(Some(rust_code_markup(&ty.display_truncated(db, None)))); 211 res.extend(Some(rust_code_markup(&ty.display(db))));
212 let range = sema.original_range(&node).range; 212 let range = sema.original_range(&node).range;
213 Some(RangeInfo::new(range, res)) 213 Some(RangeInfo::new(range, res))
214} 214}
@@ -280,6 +280,47 @@ mod tests {
280 } 280 }
281 281
282 #[test] 282 #[test]
283 fn hover_shows_long_type_of_an_expression() {
284 check_hover_result(
285 r#"
286 //- /main.rs
287 struct Scan<A, B, C> {
288 a: A,
289 b: B,
290 c: C,
291 }
292
293 struct FakeIter<I> {
294 inner: I,
295 }
296
297 struct OtherStruct<T> {
298 i: T,
299 }
300
301 enum FakeOption<T> {
302 Some(T),
303 None,
304 }
305
306 fn scan<A, B, C>(a: A, b: B, c: C) -> FakeIter<Scan<OtherStruct<A>, B, C>> {
307 FakeIter { inner: Scan { a, b, c } }
308 }
309
310 fn main() {
311 let num: i32 = 55;
312 let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> FakeOption<u32> {
313 FakeOption::Some(*memo + value)
314 };
315 let number = 5u32;
316 let mut iter<|> = scan(OtherStruct { i: num }, closure, number);
317 }
318 "#,
319 &["FakeIter<Scan<OtherStruct<OtherStruct<i32>>, |&mut u32, &u32, &mut u32| -> FakeOption<u32>, u32>>"],
320 );
321 }
322
323 #[test]
283 fn hover_shows_fn_signature() { 324 fn hover_shows_fn_signature() {
284 // Single file with result 325 // Single file with result
285 check_hover_result( 326 check_hover_result(
@@ -405,7 +446,7 @@ mod tests {
405 } 446 }
406 447
407 #[test] 448 #[test]
408 fn hover_omits_default_generic_types() { 449 fn hover_default_generic_types() {
409 check_hover_result( 450 check_hover_result(
410 r#" 451 r#"
411//- /main.rs 452//- /main.rs
@@ -417,7 +458,7 @@ struct Test<K, T = u8> {
417fn main() { 458fn main() {
418 let zz<|> = Test { t: 23, k: 33 }; 459 let zz<|> = Test { t: 23, k: 33 };
419}"#, 460}"#,
420 &["Test<i32>"], 461 &["Test<i32, u8>"],
421 ); 462 );
422 } 463 }
423 464
@@ -880,4 +921,21 @@ fn func(foo: i32) { if true { <|>foo; }; }
880 &["unsafe trait foo"], 921 &["unsafe trait foo"],
881 ); 922 );
882 } 923 }
924
925 #[test]
926 fn test_hover_mod_with_same_name_as_function() {
927 check_hover_result(
928 "
929 //- /lib.rs
930 use self::m<|>y::Bar;
931
932 mod my {
933 pub struct Bar;
934 }
935
936 fn my() {}
937 ",
938 &["mod my"],
939 );
940 }
883} 941}
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 98483df32..b391f903a 100644
--- a/crates/ra_ide/src/inlay_hints.rs
+++ b/crates/ra_ide/src/inlay_hints.rs
@@ -9,6 +9,7 @@ use ra_syntax::{
9}; 9};
10 10
11use crate::{FileId, FunctionSignature}; 11use crate::{FileId, FunctionSignature};
12use stdx::to_lower_snake_case;
12 13
13#[derive(Clone, Debug, PartialEq, Eq)] 14#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct InlayHintsConfig { 15pub struct InlayHintsConfig {
@@ -144,7 +145,7 @@ fn get_param_name_hints(
144 .iter() 145 .iter()
145 .skip(n_params_to_skip) 146 .skip(n_params_to_skip)
146 .zip(args) 147 .zip(args)
147 .filter(|(param, arg)| should_show_param_hint(&fn_signature, param, &arg)) 148 .filter(|(param, arg)| should_show_param_name_hint(sema, &fn_signature, param, &arg))
148 .map(|(param_name, arg)| InlayHint { 149 .map(|(param_name, arg)| InlayHint {
149 range: arg.syntax().text_range(), 150 range: arg.syntax().text_range(),
150 kind: InlayKind::ParameterHint, 151 kind: InlayKind::ParameterHint,
@@ -181,7 +182,7 @@ fn get_bind_pat_hints(
181 182
182fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ty: &Type) -> bool { 183fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ty: &Type) -> bool {
183 if let Some(Adt::Enum(enum_data)) = pat_ty.as_adt() { 184 if let Some(Adt::Enum(enum_data)) = pat_ty.as_adt() {
184 let pat_text = bind_pat.syntax().to_string(); 185 let pat_text = bind_pat.to_string();
185 enum_data 186 enum_data
186 .variants(db) 187 .variants(db)
187 .into_iter() 188 .into_iter()
@@ -198,7 +199,7 @@ fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_
198 } 199 }
199 200
200 if let Some(Adt::Struct(s)) = pat_ty.as_adt() { 201 if let Some(Adt::Struct(s)) = pat_ty.as_adt() {
201 if s.fields(db).is_empty() && s.name(db).to_string() == bind_pat.syntax().to_string() { 202 if s.fields(db).is_empty() && s.name(db).to_string() == bind_pat.to_string() {
202 return true; 203 return true;
203 } 204 }
204 } 205 }
@@ -230,15 +231,16 @@ fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_
230 false 231 false
231} 232}
232 233
233fn should_show_param_hint( 234fn should_show_param_name_hint(
235 sema: &Semantics<RootDatabase>,
234 fn_signature: &FunctionSignature, 236 fn_signature: &FunctionSignature,
235 param_name: &str, 237 param_name: &str,
236 argument: &ast::Expr, 238 argument: &ast::Expr,
237) -> bool { 239) -> bool {
240 let param_name = param_name.trim_start_matches('_');
238 if param_name.is_empty() 241 if param_name.is_empty()
239 || is_argument_similar_to_param(argument, param_name) 242 || Some(param_name) == fn_signature.name.as_ref().map(|s| s.trim_start_matches('_'))
240 || Some(param_name.trim_start_matches('_')) 243 || is_argument_similar_to_param_name(sema, argument, param_name)
241 == fn_signature.name.as_ref().map(|s| s.trim_start_matches('_'))
242 { 244 {
243 return false; 245 return false;
244 } 246 }
@@ -254,20 +256,42 @@ fn should_show_param_hint(
254 parameters_len != 1 || !is_obvious_param(param_name) 256 parameters_len != 1 || !is_obvious_param(param_name)
255} 257}
256 258
257fn is_argument_similar_to_param(argument: &ast::Expr, param_name: &str) -> bool { 259fn is_argument_similar_to_param_name(
258 let argument_string = remove_ref(argument.clone()).syntax().to_string(); 260 sema: &Semantics<RootDatabase>,
259 let param_name = param_name.trim_start_matches('_'); 261 argument: &ast::Expr,
260 let argument_string = argument_string.trim_start_matches('_'); 262 param_name: &str,
261 argument_string.starts_with(&param_name) || argument_string.ends_with(&param_name) 263) -> bool {
264 if is_enum_name_similar_to_param_name(sema, argument, param_name) {
265 return true;
266 }
267 match get_string_representation(argument) {
268 None => false,
269 Some(repr) => {
270 let argument_string = repr.trim_start_matches('_');
271 argument_string.starts_with(param_name) || argument_string.ends_with(param_name)
272 }
273 }
274}
275
276fn is_enum_name_similar_to_param_name(
277 sema: &Semantics<RootDatabase>,
278 argument: &ast::Expr,
279 param_name: &str,
280) -> bool {
281 match sema.type_of_expr(argument).and_then(|t| t.as_adt()) {
282 Some(Adt::Enum(e)) => to_lower_snake_case(&e.name(sema.db).to_string()) == param_name,
283 _ => false,
284 }
262} 285}
263 286
264fn remove_ref(expr: ast::Expr) -> ast::Expr { 287fn get_string_representation(expr: &ast::Expr) -> Option<String> {
265 if let ast::Expr::RefExpr(ref_expr) = &expr { 288 match expr {
266 if let Some(inner) = ref_expr.expr() { 289 ast::Expr::MethodCallExpr(method_call_expr) => {
267 return inner; 290 Some(method_call_expr.name_ref()?.to_string())
268 } 291 }
292 ast::Expr::RefExpr(ref_expr) => get_string_representation(&ref_expr.expr()?),
293 _ => Some(expr.to_string()),
269 } 294 }
270 expr
271} 295}
272 296
273fn is_obvious_param(param_name: &str) -> bool { 297fn is_obvious_param(param_name: &str) -> bool {
@@ -1073,6 +1097,12 @@ struct TestVarContainer {
1073 test_var: i32, 1097 test_var: i32,
1074} 1098}
1075 1099
1100impl TestVarContainer {
1101 fn test_var(&self) -> i32 {
1102 self.test_var
1103 }
1104}
1105
1076struct Test {} 1106struct Test {}
1077 1107
1078impl Test { 1108impl Test {
@@ -1098,10 +1128,15 @@ struct Param {}
1098fn different_order(param: &Param) {} 1128fn different_order(param: &Param) {}
1099fn different_order_mut(param: &mut Param) {} 1129fn different_order_mut(param: &mut Param) {}
1100fn has_underscore(_param: bool) {} 1130fn has_underscore(_param: bool) {}
1131fn enum_matches_param_name(completion_kind: CompletionKind) {}
1101 1132
1102fn twiddle(twiddle: bool) {} 1133fn twiddle(twiddle: bool) {}
1103fn doo(_doo: bool) {} 1134fn doo(_doo: bool) {}
1104 1135
1136enum CompletionKind {
1137 Keyword,
1138}
1139
1105fn main() { 1140fn main() {
1106 let container: TestVarContainer = TestVarContainer { test_var: 42 }; 1141 let container: TestVarContainer = TestVarContainer { test_var: 42 };
1107 let test: Test = Test {}; 1142 let test: Test = Test {};
@@ -1114,18 +1149,21 @@ fn main() {
1114 let test_var: i32 = 55; 1149 let test_var: i32 = 55;
1115 test_processed.no_hints_expected(22, test_var); 1150 test_processed.no_hints_expected(22, test_var);
1116 test_processed.no_hints_expected(33, container.test_var); 1151 test_processed.no_hints_expected(33, container.test_var);
1152 test_processed.no_hints_expected(44, container.test_var());
1117 test_processed.frob(false); 1153 test_processed.frob(false);
1118 1154
1119 twiddle(true); 1155 twiddle(true);
1120 doo(true); 1156 doo(true);
1121 1157
1122 let param_begin: Param = Param {}; 1158 let mut param_begin: Param = Param {};
1123 different_order(&param_begin); 1159 different_order(&param_begin);
1124 different_order(&mut param_begin); 1160 different_order(&mut param_begin);
1125 1161
1126 let param: bool = true; 1162 let param: bool = true;
1127 has_underscore(param); 1163 has_underscore(param);
1128 1164
1165 enum_matches_param_name(CompletionKind::Keyword);
1166
1129 let a: f64 = 7.0; 1167 let a: f64 = 7.0;
1130 let b: f64 = 4.0; 1168 let b: f64 = 4.0;
1131 let _: f64 = a.div_euclid(b); 1169 let _: f64 = a.div_euclid(b);
diff --git a/crates/ra_ide/src/join_lines.rs b/crates/ra_ide/src/join_lines.rs
index d0def7eaa..af1ade8a1 100644
--- a/crates/ra_ide/src/join_lines.rs
+++ b/crates/ra_ide/src/join_lines.rs
@@ -129,8 +129,7 @@ fn has_comma_after(node: &SyntaxNode) -> bool {
129} 129}
130 130
131fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> { 131fn join_single_expr_block(edit: &mut TextEditBuilder, token: &SyntaxToken) -> Option<()> {
132 let block = ast::Block::cast(token.parent())?; 132 let block_expr = ast::BlockExpr::cast(token.parent())?;
133 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
134 if !block_expr.is_standalone() { 133 if !block_expr.is_standalone() {
135 return None; 134 return None;
136 } 135 }
@@ -167,16 +166,28 @@ fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool {
167 166
168#[cfg(test)] 167#[cfg(test)]
169mod tests { 168mod tests {
170 use crate::test_utils::{assert_eq_text, check_action, extract_range}; 169 use ra_syntax::SourceFile;
170 use test_utils::{add_cursor, assert_eq_text, extract_offset, extract_range};
171 171
172 use super::*; 172 use super::*;
173 173
174 fn check_join_lines(before: &str, after: &str) { 174 fn check_join_lines(before: &str, after: &str) {
175 check_action(before, after, |file, offset| { 175 let (before_cursor_pos, before) = extract_offset(before);
176 let range = TextRange::empty(offset); 176 let file = SourceFile::parse(&before).ok().unwrap();
177 let res = join_lines(file, range); 177
178 Some(res) 178 let range = TextRange::empty(before_cursor_pos);
179 }) 179 let result = join_lines(&file, range);
180
181 let actual = {
182 let mut actual = before.to_string();
183 result.apply(&mut actual);
184 actual
185 };
186 let actual_cursor_pos = result
187 .apply_to_offset(before_cursor_pos)
188 .expect("cursor position is affected by the edit");
189 let actual = add_cursor(&actual, actual_cursor_pos);
190 assert_eq_text!(after, &actual);
180 } 191 }
181 192
182 #[test] 193 #[test]
@@ -570,7 +581,11 @@ fn foo() {
570 let (sel, before) = extract_range(before); 581 let (sel, before) = extract_range(before);
571 let parse = SourceFile::parse(&before); 582 let parse = SourceFile::parse(&before);
572 let result = join_lines(&parse.tree(), sel); 583 let result = join_lines(&parse.tree(), sel);
573 let actual = result.apply(&before); 584 let actual = {
585 let mut actual = before.to_string();
586 result.apply(&mut actual);
587 actual
588 };
574 assert_eq_text!(after, &actual); 589 assert_eq_text!(after, &actual);
575 } 590 }
576 591
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 09f602fe1..97ff67ee8 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -16,7 +16,6 @@ macro_rules! eprintln {
16} 16}
17 17
18pub mod mock_analysis; 18pub mod mock_analysis;
19mod source_change;
20 19
21mod prime_caches; 20mod prime_caches;
22mod status; 21mod status;
@@ -32,7 +31,6 @@ mod syntax_highlighting;
32mod parent_module; 31mod parent_module;
33mod references; 32mod references;
34mod impls; 33mod impls;
35mod assists;
36mod diagnostics; 34mod diagnostics;
37mod syntax_tree; 35mod syntax_tree;
38mod folding_ranges; 36mod folding_ranges;
@@ -44,11 +42,6 @@ mod inlay_hints;
44mod expand_macro; 42mod expand_macro;
45mod ssr; 43mod ssr;
46 44
47#[cfg(test)]
48mod marks;
49#[cfg(test)]
50mod test_utils;
51
52use std::sync::Arc; 45use std::sync::Arc;
53 46
54use ra_cfg::CfgOptions; 47use ra_cfg::CfgOptions;
@@ -65,7 +58,6 @@ use ra_syntax::{SourceFile, TextRange, TextSize};
65use crate::display::ToNav; 58use crate::display::ToNav;
66 59
67pub use crate::{ 60pub use crate::{
68 assists::{Assist, AssistId},
69 call_hierarchy::CallItem, 61 call_hierarchy::CallItem,
70 completion::{ 62 completion::{
71 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, 63 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat,
@@ -78,7 +70,6 @@ pub use crate::{
78 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, 70 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
79 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, 71 references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
80 runnables::{Runnable, RunnableKind, TestId}, 72 runnables::{Runnable, RunnableKind, TestId},
81 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
82 ssr::SsrError, 73 ssr::SsrError,
83 syntax_highlighting::{ 74 syntax_highlighting::{
84 Highlight, HighlightModifier, HighlightModifiers, HighlightTag, HighlightedRange, 75 Highlight, HighlightModifier, HighlightModifiers, HighlightTag, HighlightedRange,
@@ -86,17 +77,19 @@ pub use crate::{
86}; 77};
87 78
88pub use hir::Documentation; 79pub use hir::Documentation;
80pub use ra_assists::{AssistConfig, AssistId};
89pub use ra_db::{ 81pub use ra_db::{
90 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId, 82 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId,
91}; 83};
92pub use ra_ide_db::{ 84pub use ra_ide_db::{
93 change::{AnalysisChange, LibraryData}, 85 change::{AnalysisChange, LibraryData},
94 line_index::{LineCol, LineIndex}, 86 line_index::{LineCol, LineIndex},
95 line_index_utils::translate_offset_with_edit,
96 search::SearchScope, 87 search::SearchScope,
88 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
97 symbol_index::Query, 89 symbol_index::Query,
98 RootDatabase, 90 RootDatabase,
99}; 91};
92pub use ra_text_edit::{Indel, TextEdit};
100 93
101pub type Cancelable<T> = Result<T, Canceled>; 94pub type Cancelable<T> = Result<T, Canceled>;
102 95
@@ -135,10 +128,12 @@ pub struct AnalysisHost {
135 db: RootDatabase, 128 db: RootDatabase,
136} 129}
137 130
138impl Default for AnalysisHost { 131#[derive(Debug)]
139 fn default() -> AnalysisHost { 132pub struct Assist {
140 AnalysisHost::new(None) 133 pub id: AssistId,
141 } 134 pub label: String,
135 pub group_label: Option<String>,
136 pub source_change: SourceChange,
142} 137}
143 138
144impl AnalysisHost { 139impl AnalysisHost {
@@ -176,18 +171,20 @@ impl AnalysisHost {
176 pub fn request_cancellation(&mut self) { 171 pub fn request_cancellation(&mut self) {
177 self.db.request_cancellation(); 172 self.db.request_cancellation();
178 } 173 }
179 pub fn raw_database( 174 pub fn raw_database(&self) -> &RootDatabase {
180 &self,
181 ) -> &(impl hir::db::HirDatabase + salsa::Database + ra_db::SourceDatabaseExt) {
182 &self.db 175 &self.db
183 } 176 }
184 pub fn raw_database_mut( 177 pub fn raw_database_mut(&mut self) -> &mut RootDatabase {
185 &mut self,
186 ) -> &mut (impl hir::db::HirDatabase + salsa::Database + ra_db::SourceDatabaseExt) {
187 &mut self.db 178 &mut self.db
188 } 179 }
189} 180}
190 181
182impl Default for AnalysisHost {
183 fn default() -> AnalysisHost {
184 AnalysisHost::new(None)
185 }
186}
187
191/// Analysis is a snapshot of a world state at a moment in time. It is the main 188/// Analysis is a snapshot of a world state at a moment in time. It is the main
192/// entry point for asking semantic information about the world. When the world 189/// entry point for asking semantic information about the world. When the world
193/// state is advanced using `AnalysisHost::apply_change` method, all existing 190/// state is advanced using `AnalysisHost::apply_change` method, all existing
@@ -289,14 +286,10 @@ impl Analysis {
289 286
290 /// Returns an edit to remove all newlines in the range, cleaning up minor 287 /// Returns an edit to remove all newlines in the range, cleaning up minor
291 /// stuff like trailing commas. 288 /// stuff like trailing commas.
292 pub fn join_lines(&self, frange: FileRange) -> Cancelable<SourceChange> { 289 pub fn join_lines(&self, frange: FileRange) -> Cancelable<TextEdit> {
293 self.with_db(|db| { 290 self.with_db(|db| {
294 let parse = db.parse(frange.file_id); 291 let parse = db.parse(frange.file_id);
295 let file_edit = SourceFileEdit { 292 join_lines::join_lines(&parse.tree(), frange.range)
296 file_id: frange.file_id,
297 edit: join_lines::join_lines(&parse.tree(), frange.range),
298 };
299 SourceChange::source_file_edit("join lines", file_edit)
300 }) 293 })
301 } 294 }
302 295
@@ -456,16 +449,26 @@ impl Analysis {
456 /// Computes completions at the given position. 449 /// Computes completions at the given position.
457 pub fn completions( 450 pub fn completions(
458 &self, 451 &self,
459 position: FilePosition,
460 config: &CompletionConfig, 452 config: &CompletionConfig,
453 position: FilePosition,
461 ) -> Cancelable<Option<Vec<CompletionItem>>> { 454 ) -> Cancelable<Option<Vec<CompletionItem>>> {
462 self.with_db(|db| completion::completions(db, position, config).map(Into::into)) 455 self.with_db(|db| completion::completions(db, config, position).map(Into::into))
463 } 456 }
464 457
465 /// Computes assists (aka code actions aka intentions) for the given 458 /// Computes assists (aka code actions aka intentions) for the given
466 /// position. 459 /// position.
467 pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<Assist>> { 460 pub fn assists(&self, config: &AssistConfig, frange: FileRange) -> Cancelable<Vec<Assist>> {
468 self.with_db(|db| assists::assists(db, frange)) 461 self.with_db(|db| {
462 ra_assists::Assist::resolved(db, config, frange)
463 .into_iter()
464 .map(|assist| Assist {
465 id: assist.assist.id,
466 label: assist.assist.label,
467 group_label: assist.assist.group.map(|it| it.0),
468 source_change: assist.source_change,
469 })
470 .collect()
471 })
469 } 472 }
470 473
471 /// Computes the set of diagnostics for the given file. 474 /// Computes the set of diagnostics for the given file.
@@ -490,7 +493,7 @@ impl Analysis {
490 ) -> Cancelable<Result<SourceChange, SsrError>> { 493 ) -> Cancelable<Result<SourceChange, SsrError>> {
491 self.with_db(|db| { 494 self.with_db(|db| {
492 let edits = ssr::parse_search_replace(query, parse_only, db)?; 495 let edits = ssr::parse_search_replace(query, parse_only, db)?;
493 Ok(SourceChange::source_file_edits("ssr", edits)) 496 Ok(SourceChange::source_file_edits("Structural Search Replace", edits))
494 }) 497 })
495 } 498 }
496 499
diff --git a/crates/ra_ide/src/marks.rs b/crates/ra_ide/src/marks.rs
deleted file mode 100644
index bea30fe2a..000000000
--- a/crates/ra_ide/src/marks.rs
+++ /dev/null
@@ -1,14 +0,0 @@
1//! See test_utils/src/marks.rs
2
3test_utils::marks!(
4 inserts_angle_brackets_for_generics
5 inserts_parens_for_function_calls
6 call_info_bad_offset
7 dont_complete_current_use
8 test_resolve_parent_module_on_module_decl
9 search_filters_by_range
10 dont_insert_macro_call_parens_unncessary
11 self_fulfilling_completion
12 test_struct_field_completion_in_func_call
13 test_struct_field_completion_in_record_lit
14);
diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs
index aaf4460df..a083fb1eb 100644
--- a/crates/ra_ide/src/parent_module.rs
+++ b/crates/ra_ide/src/parent_module.rs
@@ -7,7 +7,7 @@ use ra_syntax::{
7 algo::find_node_at_offset, 7 algo::find_node_at_offset,
8 ast::{self, AstNode}, 8 ast::{self, AstNode},
9}; 9};
10use test_utils::tested_by; 10use test_utils::mark;
11 11
12use crate::NavigationTarget; 12use crate::NavigationTarget;
13 13
@@ -25,7 +25,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
25 .item_list() 25 .item_list()
26 .map_or(false, |it| it.syntax().text_range().contains_inclusive(position.offset)) 26 .map_or(false, |it| it.syntax().text_range().contains_inclusive(position.offset))
27 { 27 {
28 tested_by!(test_resolve_parent_module_on_module_decl); 28 mark::hit!(test_resolve_parent_module_on_module_decl);
29 module = m.syntax().ancestors().skip(1).find_map(ast::Module::cast); 29 module = m.syntax().ancestors().skip(1).find_map(ast::Module::cast);
30 } 30 }
31 } 31 }
@@ -57,7 +57,7 @@ pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
57mod tests { 57mod tests {
58 use ra_cfg::CfgOptions; 58 use ra_cfg::CfgOptions;
59 use ra_db::Env; 59 use ra_db::Env;
60 use test_utils::covers; 60 use test_utils::mark;
61 61
62 use crate::{ 62 use crate::{
63 mock_analysis::{analysis_and_position, MockAnalysis}, 63 mock_analysis::{analysis_and_position, MockAnalysis},
@@ -81,7 +81,7 @@ mod tests {
81 81
82 #[test] 82 #[test]
83 fn test_resolve_parent_module_on_module_decl() { 83 fn test_resolve_parent_module_on_module_decl() {
84 covers!(test_resolve_parent_module_on_module_decl); 84 mark::check!(test_resolve_parent_module_on_module_decl);
85 let (analysis, pos) = analysis_and_position( 85 let (analysis, pos) = analysis_and_position(
86 " 86 "
87 //- /lib.rs 87 //- /lib.rs
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index 555ccf295..96444bf6a 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -190,8 +190,6 @@ fn get_struct_def_name_for_struct_literal_search(
190 190
191#[cfg(test)] 191#[cfg(test)]
192mod tests { 192mod tests {
193 use test_utils::covers;
194
195 use crate::{ 193 use crate::{
196 mock_analysis::{analysis_and_position, single_file_with_position, MockAnalysis}, 194 mock_analysis::{analysis_and_position, single_file_with_position, MockAnalysis},
197 Declaration, Reference, ReferenceSearchResult, SearchScope, 195 Declaration, Reference, ReferenceSearchResult, SearchScope,
@@ -301,7 +299,6 @@ mod tests {
301 299
302 #[test] 300 #[test]
303 fn search_filters_by_range() { 301 fn search_filters_by_range() {
304 covers!(ra_ide_db::search_filters_by_range);
305 let code = r#" 302 let code = r#"
306 fn foo() { 303 fn foo() {
307 let spam<|> = 92; 304 let spam<|> = 92;
@@ -593,6 +590,31 @@ mod tests {
593 check_result(refs, "i BIND_PAT FileId(1) 36..37 Other", &["FileId(1) 51..52 Other Write"]); 590 check_result(refs, "i BIND_PAT FileId(1) 36..37 Other", &["FileId(1) 51..52 Other Write"]);
594 } 591 }
595 592
593 #[test]
594 fn test_find_struct_function_refs_outside_module() {
595 let code = r#"
596 mod foo {
597 pub struct Foo;
598
599 impl Foo {
600 pub fn new<|>() -> Foo {
601 Foo
602 }
603 }
604 }
605
606 fn main() {
607 let _f = foo::Foo::new();
608 }"#;
609
610 let refs = get_all_refs(code);
611 check_result(
612 refs,
613 "new FN_DEF FileId(1) 87..150 94..97 Other",
614 &["FileId(1) 227..230 StructLiteral"],
615 );
616 }
617
596 fn get_all_refs(text: &str) -> ReferenceSearchResult { 618 fn get_all_refs(text: &str) -> ReferenceSearchResult {
597 let (analysis, position) = single_file_with_position(text); 619 let (analysis, position) = single_file_with_position(text);
598 analysis.find_all_refs(position, None).unwrap().unwrap() 620 analysis.find_all_refs(position, None).unwrap().unwrap()
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs
index fd17bc9f2..fd2163dad 100644
--- a/crates/ra_ide/src/references/rename.rs
+++ b/crates/ra_ide/src/references/rename.rs
@@ -4,17 +4,18 @@ use hir::{ModuleSource, Semantics};
4use ra_db::{RelativePath, RelativePathBuf, SourceDatabaseExt}; 4use ra_db::{RelativePath, RelativePathBuf, SourceDatabaseExt};
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{ 6use ra_syntax::{
7 algo::find_node_at_offset, ast, lex_single_valid_syntax_kind, AstNode, SyntaxKind, SyntaxNode, 7 algo::find_node_at_offset, ast, ast::TypeAscriptionOwner, lex_single_valid_syntax_kind,
8 AstNode, SyntaxKind, SyntaxNode, SyntaxToken,
8}; 9};
9use ra_text_edit::TextEdit; 10use ra_text_edit::TextEdit;
11use std::convert::TryInto;
12use test_utils::mark;
10 13
11use crate::{ 14use crate::{
12 FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind, SourceChange, 15 references::find_all_refs, FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind,
13 SourceFileEdit, TextRange, 16 SourceChange, SourceFileEdit, TextRange, TextSize,
14}; 17};
15 18
16use super::find_all_refs;
17
18pub(crate) fn rename( 19pub(crate) fn rename(
19 db: &RootDatabase, 20 db: &RootDatabase,
20 position: FilePosition, 21 position: FilePosition,
@@ -22,17 +23,21 @@ pub(crate) fn rename(
22) -> Option<RangeInfo<SourceChange>> { 23) -> Option<RangeInfo<SourceChange>> {
23 match lex_single_valid_syntax_kind(new_name)? { 24 match lex_single_valid_syntax_kind(new_name)? {
24 SyntaxKind::IDENT | SyntaxKind::UNDERSCORE => (), 25 SyntaxKind::IDENT | SyntaxKind::UNDERSCORE => (),
26 SyntaxKind::SELF_KW => return rename_to_self(db, position),
25 _ => return None, 27 _ => return None,
26 } 28 }
27 29
28 let sema = Semantics::new(db); 30 let sema = Semantics::new(db);
29 let source_file = sema.parse(position.file_id); 31 let source_file = sema.parse(position.file_id);
30 if let Some((ast_name, ast_module)) = 32 let syntax = source_file.syntax();
31 find_name_and_module_at_offset(source_file.syntax(), position) 33 if let Some((ast_name, ast_module)) = find_name_and_module_at_offset(syntax, position) {
32 {
33 let range = ast_name.syntax().text_range(); 34 let range = ast_name.syntax().text_range();
34 rename_mod(&sema, &ast_name, &ast_module, position, new_name) 35 rename_mod(&sema, &ast_name, &ast_module, position, new_name)
35 .map(|info| RangeInfo::new(range, info)) 36 .map(|info| RangeInfo::new(range, info))
37 } else if let Some(self_token) =
38 syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW)
39 {
40 rename_self_to_param(db, position, self_token, new_name)
36 } else { 41 } else {
37 rename_reference(sema.db, position, new_name) 42 rename_reference(sema.db, position, new_name)
38 } 43 }
@@ -52,11 +57,13 @@ fn source_edit_from_reference(reference: Reference, new_name: &str) -> SourceFil
52 let file_id = reference.file_range.file_id; 57 let file_id = reference.file_range.file_id;
53 let range = match reference.kind { 58 let range = match reference.kind {
54 ReferenceKind::FieldShorthandForField => { 59 ReferenceKind::FieldShorthandForField => {
60 mark::hit!(test_rename_struct_field_for_shorthand);
55 replacement_text.push_str(new_name); 61 replacement_text.push_str(new_name);
56 replacement_text.push_str(": "); 62 replacement_text.push_str(": ");
57 TextRange::new(reference.file_range.range.start(), reference.file_range.range.start()) 63 TextRange::new(reference.file_range.range.start(), reference.file_range.range.start())
58 } 64 }
59 ReferenceKind::FieldShorthandForLocal => { 65 ReferenceKind::FieldShorthandForLocal => {
66 mark::hit!(test_rename_local_for_field_shorthand);
60 replacement_text.push_str(": "); 67 replacement_text.push_str(": ");
61 replacement_text.push_str(new_name); 68 replacement_text.push_str(new_name);
62 TextRange::new(reference.file_range.range.end(), reference.file_range.range.end()) 69 TextRange::new(reference.file_range.range.end(), reference.file_range.range.end())
@@ -121,7 +128,113 @@ fn rename_mod(
121 source_file_edits.extend(ref_edits); 128 source_file_edits.extend(ref_edits);
122 } 129 }
123 130
124 Some(SourceChange::from_edits("rename", source_file_edits, file_system_edits)) 131 Some(SourceChange::from_edits("Rename", source_file_edits, file_system_edits))
132}
133
134fn rename_to_self(db: &RootDatabase, position: FilePosition) -> Option<RangeInfo<SourceChange>> {
135 let sema = Semantics::new(db);
136 let source_file = sema.parse(position.file_id);
137 let syn = source_file.syntax();
138
139 let fn_def = find_node_at_offset::<ast::FnDef>(syn, position.offset)?;
140 let params = fn_def.param_list()?;
141 if params.self_param().is_some() {
142 return None; // method already has self param
143 }
144 let first_param = params.params().next()?;
145 let mutable = match first_param.ascribed_type() {
146 Some(ast::TypeRef::ReferenceType(rt)) => rt.mut_token().is_some(),
147 _ => return None, // not renaming other types
148 };
149
150 let RangeInfo { range, info: refs } = find_all_refs(db, position, None)?;
151
152 let param_range = first_param.syntax().text_range();
153 let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs
154 .into_iter()
155 .partition(|reference| param_range.intersect(reference.file_range.range).is_some());
156
157 if param_ref.is_empty() {
158 return None;
159 }
160
161 let mut edits = usages
162 .into_iter()
163 .map(|reference| source_edit_from_reference(reference, "self"))
164 .collect::<Vec<_>>();
165
166 edits.push(SourceFileEdit {
167 file_id: position.file_id,
168 edit: TextEdit::replace(
169 param_range,
170 String::from(if mutable { "&mut self" } else { "&self" }),
171 ),
172 });
173
174 Some(RangeInfo::new(range, SourceChange::source_file_edits("Rename", edits)))
175}
176
177fn text_edit_from_self_param(
178 syn: &SyntaxNode,
179 self_param: &ast::SelfParam,
180 new_name: &str,
181) -> Option<TextEdit> {
182 fn target_type_name(impl_def: &ast::ImplDef) -> Option<String> {
183 if let Some(ast::TypeRef::PathType(p)) = impl_def.target_type() {
184 return Some(p.path()?.segment()?.name_ref()?.text().to_string());
185 }
186 None
187 }
188
189 let impl_def =
190 find_node_at_offset::<ast::ImplDef>(syn, self_param.syntax().text_range().start())?;
191 let type_name = target_type_name(&impl_def)?;
192
193 let mut replacement_text = String::from(new_name);
194 replacement_text.push_str(": ");
195 replacement_text.push_str(self_param.mut_token().map_or("&", |_| "&mut "));
196 replacement_text.push_str(type_name.as_str());
197
198 Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text))
199}
200
201fn rename_self_to_param(
202 db: &RootDatabase,
203 position: FilePosition,
204 self_token: SyntaxToken,
205 new_name: &str,
206) -> Option<RangeInfo<SourceChange>> {
207 let sema = Semantics::new(db);
208 let source_file = sema.parse(position.file_id);
209 let syn = source_file.syntax();
210
211 let text = db.file_text(position.file_id);
212 let fn_def = find_node_at_offset::<ast::FnDef>(syn, position.offset)?;
213 let search_range = fn_def.syntax().text_range();
214
215 let mut edits: Vec<SourceFileEdit> = vec![];
216
217 for (idx, _) in text.match_indices("self") {
218 let offset: TextSize = idx.try_into().unwrap();
219 if !search_range.contains_inclusive(offset) {
220 continue;
221 }
222 if let Some(ref usage) =
223 syn.token_at_offset(offset).find(|t| t.kind() == SyntaxKind::SELF_KW)
224 {
225 let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) {
226 text_edit_from_self_param(syn, self_param, new_name)?
227 } else {
228 TextEdit::replace(usage.text_range(), String::from(new_name))
229 };
230 edits.push(SourceFileEdit { file_id: position.file_id, edit });
231 }
232 }
233
234 let range = ast::SelfParam::cast(self_token.parent())
235 .map_or(self_token.text_range(), |p| p.syntax().text_range());
236
237 Some(RangeInfo::new(range, SourceChange::source_file_edits("Rename", edits)))
125} 238}
126 239
127fn rename_reference( 240fn rename_reference(
@@ -140,14 +253,14 @@ fn rename_reference(
140 return None; 253 return None;
141 } 254 }
142 255
143 Some(RangeInfo::new(range, SourceChange::source_file_edits("rename", edit))) 256 Some(RangeInfo::new(range, SourceChange::source_file_edits("Rename", edit)))
144} 257}
145 258
146#[cfg(test)] 259#[cfg(test)]
147mod tests { 260mod tests {
148 use insta::assert_debug_snapshot; 261 use insta::assert_debug_snapshot;
149 use ra_text_edit::TextEditBuilder; 262 use ra_text_edit::TextEditBuilder;
150 use test_utils::assert_eq_text; 263 use test_utils::{assert_eq_text, mark};
151 264
152 use crate::{ 265 use crate::{
153 mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId, 266 mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId,
@@ -379,6 +492,7 @@ mod tests {
379 492
380 #[test] 493 #[test]
381 fn test_rename_struct_field_for_shorthand() { 494 fn test_rename_struct_field_for_shorthand() {
495 mark::check!(test_rename_struct_field_for_shorthand);
382 test_rename( 496 test_rename(
383 r#" 497 r#"
384 struct Foo { 498 struct Foo {
@@ -408,6 +522,7 @@ mod tests {
408 522
409 #[test] 523 #[test]
410 fn test_rename_local_for_field_shorthand() { 524 fn test_rename_local_for_field_shorthand() {
525 mark::check!(test_rename_local_for_field_shorthand);
411 test_rename( 526 test_rename(
412 r#" 527 r#"
413 struct Foo { 528 struct Foo {
@@ -527,17 +642,17 @@ mod tests {
527 RangeInfo { 642 RangeInfo {
528 range: 4..7, 643 range: 4..7,
529 info: SourceChange { 644 info: SourceChange {
530 label: "rename", 645 label: "Rename",
531 source_file_edits: [ 646 source_file_edits: [
532 SourceFileEdit { 647 SourceFileEdit {
533 file_id: FileId( 648 file_id: FileId(
534 2, 649 2,
535 ), 650 ),
536 edit: TextEdit { 651 edit: TextEdit {
537 atoms: [ 652 indels: [
538 AtomTextEdit { 653 Indel {
539 delete: 4..7,
540 insert: "foo2", 654 insert: "foo2",
655 delete: 4..7,
541 }, 656 },
542 ], 657 ],
543 }, 658 },
@@ -554,7 +669,7 @@ mod tests {
554 dst_path: "bar/foo2.rs", 669 dst_path: "bar/foo2.rs",
555 }, 670 },
556 ], 671 ],
557 cursor_position: None, 672 is_snippet: false,
558 }, 673 },
559 }, 674 },
560 ) 675 )
@@ -579,17 +694,17 @@ mod tests {
579 RangeInfo { 694 RangeInfo {
580 range: 4..7, 695 range: 4..7,
581 info: SourceChange { 696 info: SourceChange {
582 label: "rename", 697 label: "Rename",
583 source_file_edits: [ 698 source_file_edits: [
584 SourceFileEdit { 699 SourceFileEdit {
585 file_id: FileId( 700 file_id: FileId(
586 1, 701 1,
587 ), 702 ),
588 edit: TextEdit { 703 edit: TextEdit {
589 atoms: [ 704 indels: [
590 AtomTextEdit { 705 Indel {
591 delete: 4..7,
592 insert: "foo2", 706 insert: "foo2",
707 delete: 4..7,
593 }, 708 },
594 ], 709 ],
595 }, 710 },
@@ -606,7 +721,7 @@ mod tests {
606 dst_path: "foo2/mod.rs", 721 dst_path: "foo2/mod.rs",
607 }, 722 },
608 ], 723 ],
609 cursor_position: None, 724 is_snippet: false,
610 }, 725 },
611 }, 726 },
612 ) 727 )
@@ -662,17 +777,17 @@ mod tests {
662 RangeInfo { 777 RangeInfo {
663 range: 8..11, 778 range: 8..11,
664 info: SourceChange { 779 info: SourceChange {
665 label: "rename", 780 label: "Rename",
666 source_file_edits: [ 781 source_file_edits: [
667 SourceFileEdit { 782 SourceFileEdit {
668 file_id: FileId( 783 file_id: FileId(
669 2, 784 2,
670 ), 785 ),
671 edit: TextEdit { 786 edit: TextEdit {
672 atoms: [ 787 indels: [
673 AtomTextEdit { 788 Indel {
674 delete: 8..11,
675 insert: "foo2", 789 insert: "foo2",
790 delete: 8..11,
676 }, 791 },
677 ], 792 ],
678 }, 793 },
@@ -682,10 +797,10 @@ mod tests {
682 1, 797 1,
683 ), 798 ),
684 edit: TextEdit { 799 edit: TextEdit {
685 atoms: [ 800 indels: [
686 AtomTextEdit { 801 Indel {
687 delete: 27..30,
688 insert: "foo2", 802 insert: "foo2",
803 delete: 27..30,
689 }, 804 },
690 ], 805 ],
691 }, 806 },
@@ -702,13 +817,164 @@ mod tests {
702 dst_path: "bar/foo2.rs", 817 dst_path: "bar/foo2.rs",
703 }, 818 },
704 ], 819 ],
705 cursor_position: None, 820 is_snippet: false,
706 }, 821 },
707 }, 822 },
708 ) 823 )
709 "###); 824 "###);
710 } 825 }
711 826
827 #[test]
828 fn test_enum_variant_from_module_1() {
829 test_rename(
830 r#"
831 mod foo {
832 pub enum Foo {
833 Bar<|>,
834 }
835 }
836
837 fn func(f: foo::Foo) {
838 match f {
839 foo::Foo::Bar => {}
840 }
841 }
842 "#,
843 "Baz",
844 r#"
845 mod foo {
846 pub enum Foo {
847 Baz,
848 }
849 }
850
851 fn func(f: foo::Foo) {
852 match f {
853 foo::Foo::Baz => {}
854 }
855 }
856 "#,
857 );
858 }
859
860 #[test]
861 fn test_enum_variant_from_module_2() {
862 test_rename(
863 r#"
864 mod foo {
865 pub struct Foo {
866 pub bar<|>: uint,
867 }
868 }
869
870 fn foo(f: foo::Foo) {
871 let _ = f.bar;
872 }
873 "#,
874 "baz",
875 r#"
876 mod foo {
877 pub struct Foo {
878 pub baz: uint,
879 }
880 }
881
882 fn foo(f: foo::Foo) {
883 let _ = f.baz;
884 }
885 "#,
886 );
887 }
888
889 #[test]
890 fn test_parameter_to_self() {
891 test_rename(
892 r#"
893 struct Foo {
894 i: i32,
895 }
896
897 impl Foo {
898 fn f(foo<|>: &mut Foo) -> i32 {
899 foo.i
900 }
901 }
902 "#,
903 "self",
904 r#"
905 struct Foo {
906 i: i32,
907 }
908
909 impl Foo {
910 fn f(&mut self) -> i32 {
911 self.i
912 }
913 }
914 "#,
915 );
916 }
917
918 #[test]
919 fn test_self_to_parameter() {
920 test_rename(
921 r#"
922 struct Foo {
923 i: i32,
924 }
925
926 impl Foo {
927 fn f(&mut <|>self) -> i32 {
928 self.i
929 }
930 }
931 "#,
932 "foo",
933 r#"
934 struct Foo {
935 i: i32,
936 }
937
938 impl Foo {
939 fn f(foo: &mut Foo) -> i32 {
940 foo.i
941 }
942 }
943 "#,
944 );
945 }
946
947 #[test]
948 fn test_self_in_path_to_parameter() {
949 test_rename(
950 r#"
951 struct Foo {
952 i: i32,
953 }
954
955 impl Foo {
956 fn f(&self) -> i32 {
957 let self_var = 1;
958 self<|>.i
959 }
960 }
961 "#,
962 "foo",
963 r#"
964 struct Foo {
965 i: i32,
966 }
967
968 impl Foo {
969 fn f(foo: &Foo) -> i32 {
970 let self_var = 1;
971 foo.i
972 }
973 }
974 "#,
975 );
976 }
977
712 fn test_rename(text: &str, new_name: &str, expected: &str) { 978 fn test_rename(text: &str, new_name: &str, expected: &str) {
713 let (analysis, position) = single_file_with_position(text); 979 let (analysis, position) = single_file_with_position(text);
714 let source_change = analysis.rename(position, new_name).unwrap(); 980 let source_change = analysis.rename(position, new_name).unwrap();
@@ -717,13 +983,13 @@ mod tests {
717 if let Some(change) = source_change { 983 if let Some(change) = source_change {
718 for edit in change.info.source_file_edits { 984 for edit in change.info.source_file_edits {
719 file_id = Some(edit.file_id); 985 file_id = Some(edit.file_id);
720 for atom in edit.edit.as_atoms() { 986 for indel in edit.edit.into_iter() {
721 text_edit_builder.replace(atom.delete, atom.insert.clone()); 987 text_edit_builder.replace(indel.delete, indel.insert);
722 } 988 }
723 } 989 }
724 } 990 }
725 let result = 991 let mut result = analysis.file_text(file_id.unwrap()).unwrap().to_string();
726 text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap()).unwrap()); 992 text_edit_builder.finish().apply(&mut result);
727 assert_eq_text!(expected, &*result); 993 assert_eq_text!(expected, &*result);
728 } 994 }
729} 995}
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs
index 38637c19c..131b8f307 100644
--- a/crates/ra_ide/src/runnables.rs
+++ b/crates/ra_ide/src/runnables.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::Semantics; 3use hir::{AsAssocItem, Semantics};
4use itertools::Itertools; 4use itertools::Itertools;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{ 6use ra_syntax::{
@@ -9,6 +9,7 @@ use ra_syntax::{
9}; 9};
10 10
11use crate::FileId; 11use crate::FileId;
12use ast::DocCommentsOwner;
12use std::fmt::Display; 13use std::fmt::Display;
13 14
14#[derive(Debug)] 15#[derive(Debug)]
@@ -37,6 +38,7 @@ pub enum RunnableKind {
37 Test { test_id: TestId, attr: TestAttr }, 38 Test { test_id: TestId, attr: TestAttr },
38 TestMod { path: String }, 39 TestMod { path: String },
39 Bench { test_id: TestId }, 40 Bench { test_id: TestId },
41 DocTest { test_id: TestId },
40 Bin, 42 Bin,
41} 43}
42 44
@@ -63,14 +65,36 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run
63 RunnableKind::Bin 65 RunnableKind::Bin
64 } else { 66 } else {
65 let test_id = if let Some(module) = sema.to_def(&fn_def).map(|def| def.module(sema.db)) { 67 let test_id = if let Some(module) = sema.to_def(&fn_def).map(|def| def.module(sema.db)) {
66 let path = module 68 let def = sema.to_def(&fn_def)?;
69 let impl_trait_name =
70 def.as_assoc_item(sema.db).and_then(|assoc_item| {
71 match assoc_item.container(sema.db) {
72 hir::AssocItemContainer::Trait(trait_item) => {
73 Some(trait_item.name(sema.db).to_string())
74 }
75 hir::AssocItemContainer::ImplDef(impl_def) => impl_def
76 .target_ty(sema.db)
77 .as_adt()
78 .map(|adt| adt.name(sema.db).to_string()),
79 }
80 });
81
82 let path_iter = module
67 .path_to_root(sema.db) 83 .path_to_root(sema.db)
68 .into_iter() 84 .into_iter()
69 .rev() 85 .rev()
70 .filter_map(|it| it.name(sema.db)) 86 .filter_map(|it| it.name(sema.db))
71 .map(|name| name.to_string()) 87 .map(|name| name.to_string());
72 .chain(std::iter::once(name_string)) 88
73 .join("::"); 89 let path = if let Some(impl_trait_name) = impl_trait_name {
90 path_iter
91 .chain(std::iter::once(impl_trait_name))
92 .chain(std::iter::once(name_string))
93 .join("::")
94 } else {
95 path_iter.chain(std::iter::once(name_string)).join("::")
96 };
97
74 TestId::Path(path) 98 TestId::Path(path)
75 } else { 99 } else {
76 TestId::Name(name_string) 100 TestId::Name(name_string)
@@ -81,6 +105,8 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run
81 RunnableKind::Test { test_id, attr } 105 RunnableKind::Test { test_id, attr }
82 } else if fn_def.has_atom_attr("bench") { 106 } else if fn_def.has_atom_attr("bench") {
83 RunnableKind::Bench { test_id } 107 RunnableKind::Bench { test_id }
108 } else if has_doc_test(&fn_def) {
109 RunnableKind::DocTest { test_id }
84 } else { 110 } else {
85 return None; 111 return None;
86 } 112 }
@@ -117,6 +143,10 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
117 .any(|attribute_text| attribute_text.contains("test")) 143 .any(|attribute_text| attribute_text.contains("test"))
118} 144}
119 145
146fn has_doc_test(fn_def: &ast::FnDef) -> bool {
147 fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```"))
148}
149
120fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> { 150fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> {
121 let has_test_function = module 151 let has_test_function = module
122 .item_list()? 152 .item_list()?
@@ -195,6 +225,79 @@ mod tests {
195 } 225 }
196 226
197 #[test] 227 #[test]
228 fn test_runnables_doc_test() {
229 let (analysis, pos) = analysis_and_position(
230 r#"
231 //- /lib.rs
232 <|> //empty
233 fn main() {}
234
235 /// ```
236 /// let x = 5;
237 /// ```
238 fn foo() {}
239 "#,
240 );
241 let runnables = analysis.runnables(pos.file_id).unwrap();
242 assert_debug_snapshot!(&runnables,
243 @r###"
244 [
245 Runnable {
246 range: 1..21,
247 kind: Bin,
248 },
249 Runnable {
250 range: 22..64,
251 kind: DocTest {
252 test_id: Path(
253 "foo",
254 ),
255 },
256 },
257 ]
258 "###
259 );
260 }
261
262 #[test]
263 fn test_runnables_doc_test_in_impl() {
264 let (analysis, pos) = analysis_and_position(
265 r#"
266 //- /lib.rs
267 <|> //empty
268 fn main() {}
269
270 struct Data;
271 impl Data {
272 /// ```
273 /// let x = 5;
274 /// ```
275 fn foo() {}
276 }
277 "#,
278 );
279 let runnables = analysis.runnables(pos.file_id).unwrap();
280 assert_debug_snapshot!(&runnables,
281 @r###"
282 [
283 Runnable {
284 range: 1..21,
285 kind: Bin,
286 },
287 Runnable {
288 range: 51..105,
289 kind: DocTest {
290 test_id: Path(
291 "Data::foo",
292 ),
293 },
294 },
295 ]
296 "###
297 );
298 }
299
300 #[test]
198 fn test_runnables_module() { 301 fn test_runnables_module() {
199 let (analysis, pos) = analysis_and_position( 302 let (analysis, pos) = analysis_and_position(
200 r#" 303 r#"
diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/src/snapshots/highlight_strings.html
index de06daf72..752b487e8 100644
--- a/crates/ra_ide/src/snapshots/highlight_strings.html
+++ b/crates/ra_ide/src/snapshots/highlight_strings.html
@@ -27,13 +27,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
27.keyword.unsafe { color: #BC8383; font-weight: bold; } 27.keyword.unsafe { color: #BC8383; font-weight: bold; }
28.control { font-style: italic; } 28.control { font-style: italic; }
29</style> 29</style>
30<pre><code><span class="macro">macro_rules!</span> println { 30<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> {
31 ($($arg:tt)*) =&gt; ({ 31 ($($arg:tt)*) =&gt; ({
32 $<span class="keyword">crate</span>::io::_print($<span class="keyword">crate</span>::format_args_nl!($($arg)*)); 32 $<span class="keyword">crate</span>::io::_print($<span class="keyword">crate</span>::format_args_nl!($($arg)*));
33 }) 33 })
34} 34}
35#[rustc_builtin_macro] 35#[rustc_builtin_macro]
36<span class="macro">macro_rules!</span> format_args_nl { 36<span class="macro">macro_rules!</span> <span class="macro declaration">format_args_nl</span> {
37 ($fmt:expr) =&gt; {{ <span class="comment">/* compiler built-in */</span> }}; 37 ($fmt:expr) =&gt; {{ <span class="comment">/* compiler built-in */</span> }};
38 ($fmt:expr, $($args:tt)*) =&gt; {{ <span class="comment">/* compiler built-in */</span> }}; 38 ($fmt:expr, $($args:tt)*) =&gt; {{ <span class="comment">/* compiler built-in */</span> }};
39} 39}
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html
index 4b12fe823..635fe5cf9 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/src/snapshots/highlighting.html
@@ -33,11 +33,23 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
33 <span class="keyword">pub</span> <span class="field declaration">y</span>: <span class="builtin_type">i32</span>, 33 <span class="keyword">pub</span> <span class="field declaration">y</span>: <span class="builtin_type">i32</span>,
34} 34}
35 35
36<span class="keyword">trait</span> <span class="trait declaration">Bar</span> {
37 <span class="keyword">fn</span> <span class="function declaration">bar</span>(&<span class="keyword">self</span>) -&gt; <span class="builtin_type">i32</span>;
38}
39
40<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> {
41 <span class="keyword">fn</span> <span class="function declaration">bar</span>(&<span class="keyword">self</span>) -&gt; <span class="builtin_type">i32</span> {
42 <span class="keyword">self</span>.<span class="field">x</span>
43 }
44}
45
46<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable">STATIC_MUT</span>: <span class="builtin_type">i32</span> = <span class="numeric_literal">0</span>;
47
36<span class="keyword">fn</span> <span class="function declaration">foo</span>&lt;<span class="lifetime declaration">'a</span>, <span class="type_param declaration">T</span>&gt;() -&gt; <span class="type_param">T</span> { 48<span class="keyword">fn</span> <span class="function declaration">foo</span>&lt;<span class="lifetime declaration">'a</span>, <span class="type_param declaration">T</span>&gt;() -&gt; <span class="type_param">T</span> {
37 <span class="function">foo</span>::&lt;<span class="lifetime">'a</span>, <span class="builtin_type">i32</span>&gt;() 49 <span class="function">foo</span>::&lt;<span class="lifetime">'a</span>, <span class="builtin_type">i32</span>&gt;()
38} 50}
39 51
40<span class="macro">macro_rules!</span> def_fn { 52<span class="macro">macro_rules!</span> <span class="macro declaration">def_fn</span> {
41 ($($tt:tt)*) =&gt; {$($tt)*} 53 ($($tt:tt)*) =&gt; {$($tt)*}
42} 54}
43 55
@@ -56,7 +68,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
56 <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>; 68 <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>;
57 <span class="variable mutable">vec</span>.<span class="unresolved_reference">push</span>(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> }); 69 <span class="variable mutable">vec</span>.<span class="unresolved_reference">push</span>(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> });
58 } 70 }
59 <span class="keyword unsafe">unsafe</span> { <span class="variable mutable">vec</span>.<span class="unresolved_reference">set_len</span>(<span class="numeric_literal">0</span>); } 71 <span class="keyword unsafe">unsafe</span> {
72 <span class="variable mutable">vec</span>.<span class="unresolved_reference">set_len</span>(<span class="numeric_literal">0</span>);
73 <span class="static mutable">STATIC_MUT</span> = <span class="numeric_literal">1</span>;
74 }
75
76 <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> {
77 <span class="comment">// Do nothing</span>
78 }
60 79
61 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; 80 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>;
62 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; 81 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>;
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs
index 7b93ff2d2..1873d1d0d 100644
--- a/crates/ra_ide/src/ssr.rs
+++ b/crates/ra_ide/src/ssr.rs
@@ -1,18 +1,18 @@
1//! structural search replace 1//! structural search replace
2 2
3use crate::source_change::SourceFileEdit; 3use std::{collections::HashMap, iter::once, str::FromStr};
4
4use ra_db::{SourceDatabase, SourceDatabaseExt}; 5use ra_db::{SourceDatabase, SourceDatabaseExt};
5use ra_ide_db::symbol_index::SymbolsDatabase; 6use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase};
6use ra_ide_db::RootDatabase;
7use ra_syntax::ast::make::try_expr_from_text;
8use ra_syntax::ast::{ 7use ra_syntax::ast::{
9 ArgList, AstToken, CallExpr, Comment, Expr, MethodCallExpr, RecordField, RecordLit, 8 make::try_expr_from_text, ArgList, AstToken, CallExpr, Comment, Expr, MethodCallExpr,
9 RecordField, RecordLit,
10}; 10};
11use ra_syntax::{AstNode, SyntaxElement, SyntaxKind, SyntaxNode}; 11use ra_syntax::{AstNode, SyntaxElement, SyntaxKind, SyntaxNode};
12use ra_text_edit::{TextEdit, TextEditBuilder}; 12use ra_text_edit::{TextEdit, TextEditBuilder};
13use rustc_hash::FxHashMap; 13use rustc_hash::FxHashMap;
14use std::collections::HashMap; 14
15use std::{iter::once, str::FromStr}; 15use crate::SourceFileEdit;
16 16
17#[derive(Debug, PartialEq)] 17#[derive(Debug, PartialEq)]
18pub struct SsrError(String); 18pub struct SsrError(String);
@@ -401,16 +401,22 @@ fn render_replace(
401 ignored_comments: &Vec<Comment>, 401 ignored_comments: &Vec<Comment>,
402 template: &SsrTemplate, 402 template: &SsrTemplate,
403) -> String { 403) -> String {
404 let mut builder = TextEditBuilder::default(); 404 let edit = {
405 for element in template.template.descendants() { 405 let mut builder = TextEditBuilder::default();
406 if let Some(var) = template.placeholders.get(&element) { 406 for element in template.template.descendants() {
407 builder.replace(element.text_range(), binding[var].to_string()) 407 if let Some(var) = template.placeholders.get(&element) {
408 builder.replace(element.text_range(), binding[var].to_string())
409 }
408 } 410 }
409 } 411 for comment in ignored_comments {
410 for comment in ignored_comments { 412 builder.insert(template.template.text_range().end(), comment.syntax().to_string())
411 builder.insert(template.template.text_range().end(), comment.syntax().to_string()) 413 }
412 } 414 builder.finish()
413 builder.finish().apply(&template.template.text().to_string()) 415 };
416
417 let mut text = template.template.text().to_string();
418 edit.apply(&mut text);
419 text
414} 420}
415 421
416#[cfg(test)] 422#[cfg(test)]
@@ -505,7 +511,9 @@ mod tests {
505 ); 511 );
506 512
507 let edit = replace(&matches, &query.template); 513 let edit = replace(&matches, &query.template);
508 assert_eq!(edit.apply(input), "fn main() { bar(1+2); }"); 514 let mut after = input.to_string();
515 edit.apply(&mut after);
516 assert_eq!(after, "fn main() { bar(1+2); }");
509 } 517 }
510 518
511 fn assert_ssr_transform(query: &str, input: &str, result: &str) { 519 fn assert_ssr_transform(query: &str, input: &str, result: &str) {
@@ -513,7 +521,9 @@ mod tests {
513 let code = SourceFile::parse(input).tree(); 521 let code = SourceFile::parse(input).tree();
514 let matches = find(&query.pattern, code.syntax()); 522 let matches = find(&query.pattern, code.syntax());
515 let edit = replace(&matches, &query.template); 523 let edit = replace(&matches, &query.template);
516 assert_eq!(edit.apply(input), result); 524 let mut after = input.to_string();
525 edit.apply(&mut after);
526 assert_eq!(after, result);
517 } 527 }
518 528
519 #[test] 529 #[test]
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 6658c7bb2..be57eeb0a 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -167,6 +167,19 @@ pub(crate) fn highlight(
167 binding_hash: None, 167 binding_hash: None,
168 }); 168 });
169 } 169 }
170 if let Some(name) = mc.is_macro_rules() {
171 if let Some((highlight, binding_hash)) = highlight_element(
172 &sema,
173 &mut bindings_shadow_count,
174 name.syntax().clone().into(),
175 ) {
176 stack.add(HighlightedRange {
177 range: name.syntax().text_range(),
178 highlight,
179 binding_hash,
180 });
181 }
182 }
170 continue; 183 continue;
171 } 184 }
172 WalkEvent::Leave(Some(mc)) => { 185 WalkEvent::Leave(Some(mc)) => {
@@ -390,12 +403,13 @@ fn highlight_element(
390 T![break] 403 T![break]
391 | T![continue] 404 | T![continue]
392 | T![else] 405 | T![else]
393 | T![for]
394 | T![if] 406 | T![if]
395 | T![loop] 407 | T![loop]
396 | T![match] 408 | T![match]
397 | T![return] 409 | T![return]
398 | T![while] => h | HighlightModifier::ControlFlow, 410 | T![while]
411 | T![in] => h | HighlightModifier::ControlFlow,
412 T![for] if !is_child_of_impl(element) => h | HighlightModifier::ControlFlow,
399 T![unsafe] => h | HighlightModifier::Unsafe, 413 T![unsafe] => h | HighlightModifier::Unsafe,
400 _ => h, 414 _ => h,
401 } 415 }
@@ -419,6 +433,13 @@ fn highlight_element(
419 } 433 }
420} 434}
421 435
436fn is_child_of_impl(element: SyntaxElement) -> bool {
437 match element.parent() {
438 Some(e) => e.kind() == IMPL_DEF,
439 _ => false,
440 }
441}
442
422fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { 443fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
423 match def { 444 match def {
424 Definition::Macro(_) => HighlightTag::Macro, 445 Definition::Macro(_) => HighlightTag::Macro,
@@ -431,10 +452,16 @@ fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
431 hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union, 452 hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union,
432 hir::ModuleDef::EnumVariant(_) => HighlightTag::EnumVariant, 453 hir::ModuleDef::EnumVariant(_) => HighlightTag::EnumVariant,
433 hir::ModuleDef::Const(_) => HighlightTag::Constant, 454 hir::ModuleDef::Const(_) => HighlightTag::Constant,
434 hir::ModuleDef::Static(_) => HighlightTag::Static,
435 hir::ModuleDef::Trait(_) => HighlightTag::Trait, 455 hir::ModuleDef::Trait(_) => HighlightTag::Trait,
436 hir::ModuleDef::TypeAlias(_) => HighlightTag::TypeAlias, 456 hir::ModuleDef::TypeAlias(_) => HighlightTag::TypeAlias,
437 hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType, 457 hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType,
458 hir::ModuleDef::Static(s) => {
459 let mut h = Highlight::new(HighlightTag::Static);
460 if s.is_mut(db) {
461 h |= HighlightModifier::Mutable;
462 }
463 return h;
464 }
438 }, 465 },
439 Definition::SelfType(_) => HighlightTag::SelfType, 466 Definition::SelfType(_) => HighlightTag::SelfType,
440 Definition::TypeParam(_) => HighlightTag::TypeParam, 467 Definition::TypeParam(_) => HighlightTag::TypeParam,
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index d2926ba78..eb43a23da 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -17,6 +17,18 @@ struct Foo {
17 pub y: i32, 17 pub y: i32,
18} 18}
19 19
20trait Bar {
21 fn bar(&self) -> i32;
22}
23
24impl Bar for Foo {
25 fn bar(&self) -> i32 {
26 self.x
27 }
28}
29
30static mut STATIC_MUT: i32 = 0;
31
20fn foo<'a, T>() -> T { 32fn foo<'a, T>() -> T {
21 foo::<'a, i32>() 33 foo::<'a, i32>()
22} 34}
@@ -40,7 +52,14 @@ fn main() {
40 let x = 92; 52 let x = 92;
41 vec.push(Foo { x, y: 1 }); 53 vec.push(Foo { x, y: 1 });
42 } 54 }
43 unsafe { vec.set_len(0); } 55 unsafe {
56 vec.set_len(0);
57 STATIC_MUT = 1;
58 }
59
60 for e in vec {
61 // Do nothing
62 }
44 63
45 let mut x = 42; 64 let mut x = 42;
46 let y = &mut x; 65 let y = &mut x;
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs
index bf97f8c56..86c70ff83 100644
--- a/crates/ra_ide/src/syntax_tree.rs
+++ b/crates/ra_ide/src/syntax_tree.rs
@@ -120,9 +120,8 @@ [email protected]
120 [email protected] ")" 120 [email protected] ")"
121 [email protected] " " 121 [email protected] " "
122 [email protected] 122 [email protected]
123 [email protected] 123 [email protected] "{"
124 [email protected] "{" 124 [email protected] "}"
125 [email protected] "}"
126"# 125"#
127 .trim() 126 .trim()
128 ); 127 );
@@ -153,26 +152,25 @@ [email protected]
153 [email protected] ")" 152 [email protected] ")"
154 [email protected] " " 153 [email protected] " "
155 [email protected] 154 [email protected]
156 [email protected] 155 [email protected] "{"
157 [email protected] "{" 156 [email protected] "\n "
158 [email protected] "\n " 157 [email protected]
159 [email protected] 158 [email protected]
160 [email protected] 159 [email protected]
161 [email protected] 160 [email protected]
162 [email protected] 161 [email protected]
163 [email protected] 162 [email protected] "assert"
164 [email protected] "assert" 163 [email protected] "!"
165 [email protected] "!" 164 [email protected]
166 [email protected] 165 [email protected] "("
167 [email protected] "(" 166 [email protected] "\"\n fn foo() {\n ..."
168 [email protected] "\"\n fn foo() {\n ..." 167 [email protected] ","
169 [email protected] "," 168 [email protected] " "
170 [email protected] " " 169 [email protected] "\"\""
171 [email protected] "\"\"" 170 [email protected] ")"
172 [email protected] ")" 171 [email protected] ";"
173 [email protected] ";" 172 [email protected] "\n"
174 [email protected] "\n" 173 [email protected] "}"
175 [email protected] "}"
176"# 174"#
177 .trim() 175 .trim()
178 ); 176 );
@@ -196,9 +194,8 @@ [email protected]
196 [email protected] ")" 194 [email protected] ")"
197 [email protected] " " 195 [email protected] " "
198 [email protected] 196 [email protected]
199 [email protected] 197 [email protected] "{"
200 [email protected] "{" 198 [email protected] "}"
201 [email protected] "}"
202"# 199"#
203 .trim() 200 .trim()
204 ); 201 );
@@ -265,10 +262,9 @@ [email protected]
265 [email protected] ")" 262 [email protected] ")"
266 [email protected] " " 263 [email protected] " "
267 [email protected] 264 [email protected]
268 [email protected] 265 [email protected] "{"
269 [email protected] "{" 266 [email protected] "\n"
270 [email protected] "\n" 267 [email protected] "}"
271 [email protected] "}"
272"# 268"#
273 .trim() 269 .trim()
274 ); 270 );
@@ -300,10 +296,9 @@ [email protected]
300 [email protected] ")" 296 [email protected] ")"
301 [email protected] " " 297 [email protected] " "
302 [email protected] 298 [email protected]
303 [email protected] 299 [email protected] "{"
304 [email protected] "{" 300 [email protected] "\n"
305 [email protected] "\n" 301 [email protected] "}"
306 [email protected] "}"
307"# 302"#
308 .trim() 303 .trim()
309 ); 304 );
@@ -334,10 +329,9 @@ [email protected]
334 [email protected] ")" 329 [email protected] ")"
335 [email protected] " " 330 [email protected] " "
336 [email protected] 331 [email protected]
337 [email protected] 332 [email protected] "{"
338 [email protected] "{" 333 [email protected] "\n"
339 [email protected] "\n" 334 [email protected] "}"
340 [email protected] "}"
341 [email protected] "\n" 335 [email protected] "\n"
342 [email protected] 336 [email protected]
343 [email protected] "fn" 337 [email protected] "fn"
@@ -349,10 +343,9 @@ [email protected]
349 [email protected] ")" 343 [email protected] ")"
350 [email protected] " " 344 [email protected] " "
351 [email protected] 345 [email protected]
352 [email protected] 346 [email protected] "{"
353 [email protected] "{" 347 [email protected] "\n"
354 [email protected] "\n" 348 [email protected] "}"
355 [email protected] "}"
356"# 349"#
357 .trim() 350 .trim()
358 ); 351 );
diff --git a/crates/ra_ide/src/test_utils.rs b/crates/ra_ide/src/test_utils.rs
deleted file mode 100644
index f14533e14..000000000
--- a/crates/ra_ide/src/test_utils.rs
+++ /dev/null
@@ -1,21 +0,0 @@
1//! FIXME: write short doc here
2
3use ra_syntax::{SourceFile, TextSize};
4use ra_text_edit::TextEdit;
5
6pub use test_utils::*;
7
8pub fn check_action<F: Fn(&SourceFile, TextSize) -> Option<TextEdit>>(
9 before: &str,
10 after: &str,
11 f: F,
12) {
13 let (before_cursor_pos, before) = extract_offset(before);
14 let file = SourceFile::parse(&before).ok().unwrap();
15 let result = f(&file, before_cursor_pos).expect("code action is not applicable");
16 let actual = result.apply(&before);
17 let actual_cursor_pos =
18 result.apply_to_offset(before_cursor_pos).expect("cursor position is affected by the edit");
19 let actual = add_cursor(&actual, actual_cursor_pos);
20 assert_eq_text!(after, &actual);
21}
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs
index 2a8b4327f..cd48cad93 100644
--- a/crates/ra_ide/src/typing.rs
+++ b/crates/ra_ide/src/typing.rs
@@ -17,15 +17,16 @@ mod on_enter;
17 17
18use ra_db::{FilePosition, SourceDatabase}; 18use ra_db::{FilePosition, SourceDatabase};
19use ra_fmt::leading_indent; 19use ra_fmt::leading_indent;
20use ra_ide_db::RootDatabase; 20use ra_ide_db::{source_change::SingleFileChange, RootDatabase};
21use ra_syntax::{ 21use ra_syntax::{
22 algo::find_node_at_offset, 22 algo::find_node_at_offset,
23 ast::{self, AstToken}, 23 ast::{self, AstToken},
24 AstNode, SourceFile, TextRange, TextSize, 24 AstNode, SourceFile, TextRange, TextSize,
25}; 25};
26
26use ra_text_edit::TextEdit; 27use ra_text_edit::TextEdit;
27 28
28use crate::{source_change::SingleFileChange, SourceChange}; 29use crate::SourceChange;
29 30
30pub(crate) use on_enter::on_enter; 31pub(crate) use on_enter::on_enter;
31 32
@@ -81,7 +82,6 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<SingleFileChange>
81 Some(SingleFileChange { 82 Some(SingleFileChange {
82 label: "add semicolon".to_string(), 83 label: "add semicolon".to_string(),
83 edit: TextEdit::insert(offset, ";".to_string()), 84 edit: TextEdit::insert(offset, ";".to_string()),
84 cursor_position: None,
85 }) 85 })
86} 86}
87 87
@@ -110,7 +110,6 @@ fn on_dot_typed(file: &SourceFile, offset: TextSize) -> Option<SingleFileChange>
110 Some(SingleFileChange { 110 Some(SingleFileChange {
111 label: "reindent dot".to_string(), 111 label: "reindent dot".to_string(),
112 edit: TextEdit::replace(TextRange::new(offset - current_indent_len, offset), target_indent), 112 edit: TextEdit::replace(TextRange::new(offset - current_indent_len, offset), target_indent),
113 cursor_position: Some(offset + target_indent_len - current_indent_len + TextSize::of('.')),
114 }) 113 })
115} 114}
116 115
@@ -129,7 +128,6 @@ fn on_arrow_typed(file: &SourceFile, offset: TextSize) -> Option<SingleFileChang
129 Some(SingleFileChange { 128 Some(SingleFileChange {
130 label: "add space after return type".to_string(), 129 label: "add space after return type".to_string(),
131 edit: TextEdit::insert(after_arrow, " ".to_string()), 130 edit: TextEdit::insert(after_arrow, " ".to_string()),
132 cursor_position: Some(after_arrow),
133 }) 131 })
134} 132}
135 133
@@ -139,26 +137,23 @@ mod tests {
139 137
140 use super::*; 138 use super::*;
141 139
142 fn do_type_char(char_typed: char, before: &str) -> Option<(String, SingleFileChange)> { 140 fn do_type_char(char_typed: char, before: &str) -> Option<String> {
143 let (offset, before) = extract_offset(before); 141 let (offset, before) = extract_offset(before);
144 let edit = TextEdit::insert(offset, char_typed.to_string()); 142 let edit = TextEdit::insert(offset, char_typed.to_string());
145 let before = edit.apply(&before); 143 let mut before = before.to_string();
144 edit.apply(&mut before);
146 let parse = SourceFile::parse(&before); 145 let parse = SourceFile::parse(&before);
147 on_char_typed_inner(&parse.tree(), offset, char_typed) 146 on_char_typed_inner(&parse.tree(), offset, char_typed).map(|it| {
148 .map(|it| (it.edit.apply(&before), it)) 147 it.edit.apply(&mut before);
148 before.to_string()
149 })
149 } 150 }
150 151
151 fn type_char(char_typed: char, before: &str, after: &str) { 152 fn type_char(char_typed: char, before: &str, after: &str) {
152 let (actual, file_change) = do_type_char(char_typed, before) 153 let actual = do_type_char(char_typed, before)
153 .unwrap_or_else(|| panic!("typing `{}` did nothing", char_typed)); 154 .unwrap_or_else(|| panic!("typing `{}` did nothing", char_typed));
154 155
155 if after.contains("<|>") { 156 assert_eq_text!(after, &actual);
156 let (offset, after) = extract_offset(after);
157 assert_eq_text!(&after, &actual);
158 assert_eq!(file_change.cursor_position, Some(offset))
159 } else {
160 assert_eq_text!(after, &actual);
161 }
162 } 157 }
163 158
164 fn type_char_noop(char_typed: char, before: &str) { 159 fn type_char_noop(char_typed: char, before: &str) {
@@ -346,6 +341,6 @@ fn foo() {
346 341
347 #[test] 342 #[test]
348 fn adds_space_after_return_type() { 343 fn adds_space_after_return_type() {
349 type_char('>', "fn foo() -<|>{ 92 }", "fn foo() -><|> { 92 }") 344 type_char('>', "fn foo() -<|>{ 92 }", "fn foo() -> { 92 }")
350 } 345 }
351} 346}
diff --git a/crates/ra_ide/src/typing/on_enter.rs b/crates/ra_ide/src/typing/on_enter.rs
index 30c8c5572..85be14ad3 100644
--- a/crates/ra_ide/src/typing/on_enter.rs
+++ b/crates/ra_ide/src/typing/on_enter.rs
@@ -38,17 +38,15 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour
38 } 38 }
39 39
40 let indent = node_indent(&file, comment.syntax())?; 40 let indent = node_indent(&file, comment.syntax())?;
41 let inserted = format!("\n{}{} ", indent, prefix); 41 let inserted = format!("\n{}{} $0", indent, prefix);
42 let cursor_position = position.offset + TextSize::of(&inserted);
43 let edit = TextEdit::insert(position.offset, inserted); 42 let edit = TextEdit::insert(position.offset, inserted);
44 43
45 Some( 44 let mut res = SourceChange::source_file_edit(
46 SourceChange::source_file_edit( 45 "On enter",
47 "on enter", 46 SourceFileEdit { edit, file_id: position.file_id },
48 SourceFileEdit { edit, file_id: position.file_id }, 47 );
49 ) 48 res.is_snippet = true;
50 .with_cursor(FilePosition { offset: cursor_position, file_id: position.file_id }), 49 Some(res)
51 )
52} 50}
53 51
54fn followed_by_comment(comment: &ast::Comment) -> bool { 52fn followed_by_comment(comment: &ast::Comment) -> bool {
@@ -84,7 +82,7 @@ fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
84 82
85#[cfg(test)] 83#[cfg(test)]
86mod tests { 84mod tests {
87 use test_utils::{add_cursor, assert_eq_text, extract_offset}; 85 use test_utils::{assert_eq_text, extract_offset};
88 86
89 use crate::mock_analysis::single_file; 87 use crate::mock_analysis::single_file;
90 88
@@ -96,8 +94,8 @@ mod tests {
96 let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?; 94 let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?;
97 95
98 assert_eq!(result.source_file_edits.len(), 1); 96 assert_eq!(result.source_file_edits.len(), 1);
99 let actual = result.source_file_edits[0].edit.apply(&before); 97 let mut actual = before.to_string();
100 let actual = add_cursor(&actual, result.cursor_position.unwrap().offset); 98 result.source_file_edits[0].edit.apply(&mut actual);
101 Some(actual) 99 Some(actual)
102 } 100 }
103 101
@@ -120,7 +118,7 @@ fn foo() {
120", 118",
121 r" 119 r"
122/// Some docs 120/// Some docs
123/// <|> 121/// $0
124fn foo() { 122fn foo() {
125} 123}
126", 124",
@@ -136,7 +134,7 @@ impl S {
136 r" 134 r"
137impl S { 135impl S {
138 /// Some 136 /// Some
139 /// <|> docs. 137 /// $0 docs.
140 fn foo() {} 138 fn foo() {}
141} 139}
142", 140",
@@ -150,7 +148,7 @@ fn foo() {
150", 148",
151 r" 149 r"
152/// 150///
153/// <|> Some docs 151/// $0 Some docs
154fn foo() { 152fn foo() {
155} 153}
156", 154",
@@ -174,7 +172,7 @@ fn main() {
174 r" 172 r"
175fn main() { 173fn main() {
176 // Fix 174 // Fix
177 // <|> me 175 // $0 me
178 let x = 1 + 1; 176 let x = 1 + 1;
179} 177}
180", 178",
@@ -194,7 +192,7 @@ fn main() {
194 r" 192 r"
195fn main() { 193fn main() {
196 // Fix 194 // Fix
197 // <|> 195 // $0
198 // me 196 // me
199 let x = 1 + 1; 197 let x = 1 + 1;
200} 198}
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index 7cd2384e9..8b06cbfc5 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -14,7 +14,6 @@ use ra_syntax::{
14 ast::{self, AstNode}, 14 ast::{self, AstNode},
15 match_ast, 15 match_ast,
16}; 16};
17use test_utils::tested_by;
18 17
19use crate::RootDatabase; 18use crate::RootDatabase;
20 19
@@ -42,12 +41,10 @@ impl Definition {
42 } 41 }
43 42
44 pub fn visibility(&self, db: &RootDatabase) -> Option<Visibility> { 43 pub fn visibility(&self, db: &RootDatabase) -> Option<Visibility> {
45 let module = self.module(db);
46
47 match self { 44 match self {
48 Definition::Macro(_) => None, 45 Definition::Macro(_) => None,
49 Definition::Field(sf) => Some(sf.visibility(db)), 46 Definition::Field(sf) => Some(sf.visibility(db)),
50 Definition::ModuleDef(def) => module?.visibility_of(db, def), 47 Definition::ModuleDef(def) => def.definition_visibility(db),
51 Definition::SelfType(_) => None, 48 Definition::SelfType(_) => None,
52 Definition::Local(_) => None, 49 Definition::Local(_) => None,
53 Definition::TypeParam(_) => None, 50 Definition::TypeParam(_) => None,
@@ -119,6 +116,15 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti
119 116
120 match_ast! { 117 match_ast! {
121 match parent { 118 match parent {
119 ast::Alias(it) => {
120 let use_tree = it.syntax().parent().and_then(ast::UseTree::cast)?;
121 let path = use_tree.path()?;
122 let path_segment = path.segment()?;
123 let name_ref = path_segment.name_ref()?;
124 let name_ref_class = classify_name_ref(sema, &name_ref)?;
125
126 Some(name_ref_class.definition())
127 },
122 ast::BindPat(it) => { 128 ast::BindPat(it) => {
123 let local = sema.to_def(&it)?; 129 let local = sema.to_def(&it)?;
124 Some(Definition::Local(local)) 130 Some(Definition::Local(local))
@@ -195,6 +201,8 @@ impl NameRefClass {
195 } 201 }
196} 202}
197 203
204// Note: we don't have unit-tests for this rather important function.
205// It is primarily exercised via goto definition tests in `ra_ide`.
198pub fn classify_name_ref( 206pub fn classify_name_ref(
199 sema: &Semantics<RootDatabase>, 207 sema: &Semantics<RootDatabase>,
200 name_ref: &ast::NameRef, 208 name_ref: &ast::NameRef,
@@ -204,22 +212,18 @@ pub fn classify_name_ref(
204 let parent = name_ref.syntax().parent()?; 212 let parent = name_ref.syntax().parent()?;
205 213
206 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { 214 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
207 tested_by!(goto_def_for_methods; force);
208 if let Some(func) = sema.resolve_method_call(&method_call) { 215 if let Some(func) = sema.resolve_method_call(&method_call) {
209 return Some(NameRefClass::Definition(Definition::ModuleDef(func.into()))); 216 return Some(NameRefClass::Definition(Definition::ModuleDef(func.into())));
210 } 217 }
211 } 218 }
212 219
213 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { 220 if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) {
214 tested_by!(goto_def_for_fields; force);
215 if let Some(field) = sema.resolve_field(&field_expr) { 221 if let Some(field) = sema.resolve_field(&field_expr) {
216 return Some(NameRefClass::Definition(Definition::Field(field))); 222 return Some(NameRefClass::Definition(Definition::Field(field)));
217 } 223 }
218 } 224 }
219 225
220 if let Some(record_field) = ast::RecordField::for_field_name(name_ref) { 226 if let Some(record_field) = ast::RecordField::for_field_name(name_ref) {
221 tested_by!(goto_def_for_record_fields; force);
222 tested_by!(goto_def_for_field_init_shorthand; force);
223 if let Some((field, local)) = sema.resolve_record_field(&record_field) { 227 if let Some((field, local)) = sema.resolve_record_field(&record_field) {
224 let field = Definition::Field(field); 228 let field = Definition::Field(field);
225 let res = match local { 229 let res = match local {
@@ -231,7 +235,6 @@ pub fn classify_name_ref(
231 } 235 }
232 236
233 if let Some(record_field_pat) = ast::RecordFieldPat::cast(parent.clone()) { 237 if let Some(record_field_pat) = ast::RecordFieldPat::cast(parent.clone()) {
234 tested_by!(goto_def_for_record_field_pats; force);
235 if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) { 238 if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) {
236 let field = Definition::Field(field); 239 let field = Definition::Field(field);
237 return Some(NameRefClass::Definition(field)); 240 return Some(NameRefClass::Definition(field));
@@ -239,7 +242,6 @@ pub fn classify_name_ref(
239 } 242 }
240 243
241 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 244 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
242 tested_by!(goto_def_for_macros; force);
243 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) { 245 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
244 return Some(NameRefClass::Definition(Definition::Macro(macro_def))); 246 return Some(NameRefClass::Definition(Definition::Macro(macro_def)));
245 } 247 }
diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs
index e6f2d36e9..1b74e6558 100644
--- a/crates/ra_ide_db/src/lib.rs
+++ b/crates/ra_ide_db/src/lib.rs
@@ -2,14 +2,13 @@
2//! 2//!
3//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search. 3//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search.
4 4
5pub mod marks;
6pub mod line_index; 5pub mod line_index;
7pub mod line_index_utils;
8pub mod symbol_index; 6pub mod symbol_index;
9pub mod change; 7pub mod change;
10pub mod defs; 8pub mod defs;
11pub mod search; 9pub mod search;
12pub mod imports_locator; 10pub mod imports_locator;
11pub mod source_change;
13mod wasm_shims; 12mod wasm_shims;
14 13
15use std::sync::Arc; 14use std::sync::Arc;
diff --git a/crates/ra_ide_db/src/line_index.rs b/crates/ra_ide_db/src/line_index.rs
index 00ba95913..c7c744fce 100644
--- a/crates/ra_ide_db/src/line_index.rs
+++ b/crates/ra_ide_db/src/line_index.rs
@@ -8,7 +8,9 @@ use superslice::Ext;
8 8
9#[derive(Clone, Debug, PartialEq, Eq)] 9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct LineIndex { 10pub struct LineIndex {
11 /// Offset the the beginning of each line, zero-based
11 pub(crate) newlines: Vec<TextSize>, 12 pub(crate) newlines: Vec<TextSize>,
13 /// List of non-ASCII characters on each line
12 pub(crate) utf16_lines: FxHashMap<u32, Vec<Utf16Char>>, 14 pub(crate) utf16_lines: FxHashMap<u32, Vec<Utf16Char>>,
13} 15}
14 16
@@ -22,14 +24,26 @@ pub struct LineCol {
22 24
23#[derive(Clone, Debug, Hash, PartialEq, Eq)] 25#[derive(Clone, Debug, Hash, PartialEq, Eq)]
24pub(crate) struct Utf16Char { 26pub(crate) struct Utf16Char {
27 /// Start offset of a character inside a line, zero-based
25 pub(crate) start: TextSize, 28 pub(crate) start: TextSize,
29 /// End offset of a character inside a line, zero-based
26 pub(crate) end: TextSize, 30 pub(crate) end: TextSize,
27} 31}
28 32
29impl Utf16Char { 33impl Utf16Char {
34 /// Returns the length in 8-bit UTF-8 code units.
30 fn len(&self) -> TextSize { 35 fn len(&self) -> TextSize {
31 self.end - self.start 36 self.end - self.start
32 } 37 }
38
39 /// Returns the length in 16-bit UTF-16 code units.
40 fn len_utf16(&self) -> usize {
41 if self.len() == TextSize::from(4) {
42 2
43 } else {
44 1
45 }
46 }
33} 47}
34 48
35impl LineIndex { 49impl LineIndex {
@@ -106,7 +120,7 @@ impl LineIndex {
106 if let Some(utf16_chars) = self.utf16_lines.get(&line) { 120 if let Some(utf16_chars) = self.utf16_lines.get(&line) {
107 for c in utf16_chars { 121 for c in utf16_chars {
108 if c.end <= col { 122 if c.end <= col {
109 res -= usize::from(c.len()) - 1; 123 res -= usize::from(c.len()) - c.len_utf16();
110 } else { 124 } else {
111 // From here on, all utf16 characters come *after* the character we are mapping, 125 // From here on, all utf16 characters come *after* the character we are mapping,
112 // so we don't need to take them into account 126 // so we don't need to take them into account
@@ -120,8 +134,8 @@ impl LineIndex {
120 fn utf16_to_utf8_col(&self, line: u32, mut col: u32) -> TextSize { 134 fn utf16_to_utf8_col(&self, line: u32, mut col: u32) -> TextSize {
121 if let Some(utf16_chars) = self.utf16_lines.get(&line) { 135 if let Some(utf16_chars) = self.utf16_lines.get(&line) {
122 for c in utf16_chars { 136 for c in utf16_chars {
123 if col >= u32::from(c.start) { 137 if col > u32::from(c.start) {
124 col += u32::from(c.len()) - 1; 138 col += u32::from(c.len()) - c.len_utf16() as u32;
125 } else { 139 } else {
126 // From here on, all utf16 characters come *after* the character we are mapping, 140 // From here on, all utf16 characters come *after* the character we are mapping,
127 // so we don't need to take them into account 141 // so we don't need to take them into account
@@ -200,6 +214,9 @@ const C: char = 'メ';
200 214
201 // UTF-16 to UTF-8 215 // UTF-16 to UTF-8
202 assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); 216 assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21));
217
218 let col_index = LineIndex::new("a𐐏b");
219 assert_eq!(col_index.utf16_to_utf8_col(0, 3), TextSize::from(5));
203 } 220 }
204 221
205 #[test] 222 #[test]
@@ -226,8 +243,10 @@ const C: char = \"メ メ\";
226 // UTF-16 to UTF-8 243 // UTF-16 to UTF-8
227 assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextSize::from(15)); 244 assert_eq!(col_index.utf16_to_utf8_col(1, 15), TextSize::from(15));
228 245
229 assert_eq!(col_index.utf16_to_utf8_col(1, 18), TextSize::from(20)); 246 // メ UTF-8: 0xE3 0x83 0xA1, UTF-16: 0x30E1
230 assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(23)); 247 assert_eq!(col_index.utf16_to_utf8_col(1, 17), TextSize::from(17)); // first メ at 17..20
248 assert_eq!(col_index.utf16_to_utf8_col(1, 18), TextSize::from(20)); // space
249 assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); // second メ at 21..24
231 250
232 assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextSize::from(15)); 251 assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextSize::from(15));
233 } 252 }
diff --git a/crates/ra_ide_db/src/line_index_utils.rs b/crates/ra_ide_db/src/line_index_utils.rs
deleted file mode 100644
index 039a12c0d..000000000
--- a/crates/ra_ide_db/src/line_index_utils.rs
+++ /dev/null
@@ -1,302 +0,0 @@
1//! Code actions can specify desirable final position of the cursor.
2//!
3//! The position is specified as a `TextSize` in the final file. We need to send
4//! it in `(Line, Column)` coordinate though. However, we only have a LineIndex
5//! for a file pre-edit!
6//!
7//! Code in this module applies this "to (Line, Column) after edit"
8//! transformation.
9
10use std::convert::TryInto;
11
12use ra_syntax::{TextRange, TextSize};
13use ra_text_edit::{AtomTextEdit, TextEdit};
14
15use crate::line_index::{LineCol, LineIndex, Utf16Char};
16
17pub fn translate_offset_with_edit(
18 line_index: &LineIndex,
19 offset: TextSize,
20 text_edit: &TextEdit,
21) -> LineCol {
22 let mut state = Edits::from_text_edit(&text_edit);
23
24 let mut res = RunningLineCol::new();
25
26 macro_rules! test_step {
27 ($x:ident) => {
28 match &$x {
29 Step::Newline(n) => {
30 if offset < *n {
31 return res.to_line_col(offset);
32 } else {
33 res.add_line(*n);
34 }
35 }
36 Step::Utf16Char(x) => {
37 if offset < x.end() {
38 // if the offset is inside a multibyte char it's invalid
39 // clamp it to the start of the char
40 let clamp = offset.min(x.start());
41 return res.to_line_col(clamp);
42 } else {
43 res.adjust_col(*x);
44 }
45 }
46 }
47 };
48 }
49
50 for orig_step in LineIndexStepIter::from(line_index) {
51 loop {
52 let translated_step = state.translate_step(&orig_step);
53 match state.next_steps(&translated_step) {
54 NextSteps::Use => {
55 test_step!(translated_step);
56 break;
57 }
58 NextSteps::ReplaceMany(ns) => {
59 for n in ns {
60 test_step!(n);
61 }
62 break;
63 }
64 NextSteps::AddMany(ns) => {
65 for n in ns {
66 test_step!(n);
67 }
68 }
69 }
70 }
71 }
72
73 loop {
74 match state.next_inserted_steps() {
75 None => break,
76 Some(ns) => {
77 for n in ns {
78 test_step!(n);
79 }
80 }
81 }
82 }
83
84 res.to_line_col(offset)
85}
86
87#[derive(Debug, Clone)]
88enum Step {
89 Newline(TextSize),
90 Utf16Char(TextRange),
91}
92
93#[derive(Debug)]
94struct LineIndexStepIter<'a> {
95 line_index: &'a LineIndex,
96 next_newline_idx: usize,
97 utf16_chars: Option<(TextSize, std::slice::Iter<'a, Utf16Char>)>,
98}
99
100impl LineIndexStepIter<'_> {
101 fn from(line_index: &LineIndex) -> LineIndexStepIter {
102 let mut x = LineIndexStepIter { line_index, next_newline_idx: 0, utf16_chars: None };
103 // skip first newline since it's not real
104 x.next();
105 x
106 }
107}
108
109impl Iterator for LineIndexStepIter<'_> {
110 type Item = Step;
111 fn next(&mut self) -> Option<Step> {
112 self.utf16_chars
113 .as_mut()
114 .and_then(|(newline, x)| {
115 let x = x.next()?;
116 Some(Step::Utf16Char(TextRange::new(*newline + x.start, *newline + x.end)))
117 })
118 .or_else(|| {
119 let next_newline = *self.line_index.newlines.get(self.next_newline_idx)?;
120 self.utf16_chars = self
121 .line_index
122 .utf16_lines
123 .get(&(self.next_newline_idx as u32))
124 .map(|x| (next_newline, x.iter()));
125 self.next_newline_idx += 1;
126 Some(Step::Newline(next_newline))
127 })
128 }
129}
130
131#[derive(Debug)]
132struct OffsetStepIter<'a> {
133 text: &'a str,
134 offset: TextSize,
135}
136
137impl Iterator for OffsetStepIter<'_> {
138 type Item = Step;
139 fn next(&mut self) -> Option<Step> {
140 let (next, next_offset) = self
141 .text
142 .char_indices()
143 .filter_map(|(i, c)| {
144 let i: TextSize = i.try_into().unwrap();
145 let char_len = TextSize::of(c);
146 if c == '\n' {
147 let next_offset = self.offset + i + char_len;
148 let next = Step::Newline(next_offset);
149 Some((next, next_offset))
150 } else {
151 if !c.is_ascii() {
152 let start = self.offset + i;
153 let end = start + char_len;
154 let next = Step::Utf16Char(TextRange::new(start, end));
155 let next_offset = end;
156 Some((next, next_offset))
157 } else {
158 None
159 }
160 }
161 })
162 .next()?;
163 let next_idx: usize = (next_offset - self.offset).into();
164 self.text = &self.text[next_idx..];
165 self.offset = next_offset;
166 Some(next)
167 }
168}
169
170#[derive(Debug)]
171enum NextSteps<'a> {
172 Use,
173 ReplaceMany(OffsetStepIter<'a>),
174 AddMany(OffsetStepIter<'a>),
175}
176
177#[derive(Debug)]
178struct TranslatedEdit<'a> {
179 delete: TextRange,
180 insert: &'a str,
181 diff: i64,
182}
183
184struct Edits<'a> {
185 edits: &'a [AtomTextEdit],
186 current: Option<TranslatedEdit<'a>>,
187 acc_diff: i64,
188}
189
190impl<'a> Edits<'a> {
191 fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> {
192 let mut x = Edits { edits: text_edit.as_atoms(), current: None, acc_diff: 0 };
193 x.advance_edit();
194 x
195 }
196 fn advance_edit(&mut self) {
197 self.acc_diff += self.current.as_ref().map_or(0, |x| x.diff);
198 match self.edits.split_first() {
199 Some((next, rest)) => {
200 let delete = self.translate_range(next.delete);
201 let diff = next.insert.len() as i64 - usize::from(next.delete.len()) as i64;
202 self.current = Some(TranslatedEdit { delete, insert: &next.insert, diff });
203 self.edits = rest;
204 }
205 None => {
206 self.current = None;
207 }
208 }
209 }
210
211 fn next_inserted_steps(&mut self) -> Option<OffsetStepIter<'a>> {
212 let cur = self.current.as_ref()?;
213 let res = Some(OffsetStepIter { offset: cur.delete.start(), text: &cur.insert });
214 self.advance_edit();
215 res
216 }
217
218 fn next_steps(&mut self, step: &Step) -> NextSteps {
219 let step_pos = match *step {
220 Step::Newline(n) => n,
221 Step::Utf16Char(r) => r.end(),
222 };
223 match &mut self.current {
224 Some(edit) => {
225 if step_pos <= edit.delete.start() {
226 NextSteps::Use
227 } else if step_pos <= edit.delete.end() {
228 let iter = OffsetStepIter { offset: edit.delete.start(), text: &edit.insert };
229 // empty slice to avoid returning steps again
230 edit.insert = &edit.insert[edit.insert.len()..];
231 NextSteps::ReplaceMany(iter)
232 } else {
233 let iter = OffsetStepIter { offset: edit.delete.start(), text: &edit.insert };
234 // empty slice to avoid returning steps again
235 edit.insert = &edit.insert[edit.insert.len()..];
236 self.advance_edit();
237 NextSteps::AddMany(iter)
238 }
239 }
240 None => NextSteps::Use,
241 }
242 }
243
244 fn translate_range(&self, range: TextRange) -> TextRange {
245 if self.acc_diff == 0 {
246 range
247 } else {
248 let start = self.translate(range.start());
249 let end = self.translate(range.end());
250 TextRange::new(start, end)
251 }
252 }
253
254 fn translate(&self, x: TextSize) -> TextSize {
255 if self.acc_diff == 0 {
256 x
257 } else {
258 TextSize::from((usize::from(x) as i64 + self.acc_diff) as u32)
259 }
260 }
261
262 fn translate_step(&self, x: &Step) -> Step {
263 if self.acc_diff == 0 {
264 x.clone()
265 } else {
266 match *x {
267 Step::Newline(n) => Step::Newline(self.translate(n)),
268 Step::Utf16Char(r) => Step::Utf16Char(self.translate_range(r)),
269 }
270 }
271 }
272}
273
274#[derive(Debug)]
275struct RunningLineCol {
276 line: u32,
277 last_newline: TextSize,
278 col_adjust: TextSize,
279}
280
281impl RunningLineCol {
282 fn new() -> RunningLineCol {
283 RunningLineCol { line: 0, last_newline: TextSize::from(0), col_adjust: TextSize::from(0) }
284 }
285
286 fn to_line_col(&self, offset: TextSize) -> LineCol {
287 LineCol {
288 line: self.line,
289 col_utf16: ((offset - self.last_newline) - self.col_adjust).into(),
290 }
291 }
292
293 fn add_line(&mut self, newline: TextSize) {
294 self.line += 1;
295 self.last_newline = newline;
296 self.col_adjust = TextSize::from(0);
297 }
298
299 fn adjust_col(&mut self, range: TextRange) {
300 self.col_adjust += range.len() - TextSize::from(1);
301 }
302}
diff --git a/crates/ra_ide_db/src/marks.rs b/crates/ra_ide_db/src/marks.rs
deleted file mode 100644
index 03b4be21c..000000000
--- a/crates/ra_ide_db/src/marks.rs
+++ /dev/null
@@ -1,11 +0,0 @@
1//! See test_utils/src/marks.rs
2
3test_utils::marks![
4 goto_def_for_macros
5 goto_def_for_methods
6 goto_def_for_fields
7 goto_def_for_record_fields
8 goto_def_for_field_init_shorthand
9 goto_def_for_record_field_pats
10 search_filters_by_range
11];
diff --git a/crates/ra_ide_db/src/search.rs b/crates/ra_ide_db/src/search.rs
index b464959fc..589f44771 100644
--- a/crates/ra_ide_db/src/search.rs
+++ b/crates/ra_ide_db/src/search.rs
@@ -12,7 +12,6 @@ use ra_db::{FileId, FileRange, SourceDatabaseExt};
12use ra_prof::profile; 12use ra_prof::profile;
13use ra_syntax::{ast, match_ast, AstNode, TextRange, TextSize}; 13use ra_syntax::{ast, match_ast, AstNode, TextRange, TextSize};
14use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
15use test_utils::tested_by;
16 15
17use crate::{ 16use crate::{
18 defs::{classify_name_ref, Definition, NameRefClass}, 17 defs::{classify_name_ref, Definition, NameRefClass},
@@ -209,7 +208,6 @@ impl Definition {
209 for (idx, _) in text.match_indices(pat) { 208 for (idx, _) in text.match_indices(pat) {
210 let offset: TextSize = idx.try_into().unwrap(); 209 let offset: TextSize = idx.try_into().unwrap();
211 if !search_range.contains_inclusive(offset) { 210 if !search_range.contains_inclusive(offset) {
212 tested_by!(search_filters_by_range; force);
213 continue; 211 continue;
214 } 212 }
215 213
diff --git a/crates/ra_ide/src/source_change.rs b/crates/ra_ide_db/src/source_change.rs
index 71b0e8f75..3484f5588 100644
--- a/crates/ra_ide/src/source_change.rs
+++ b/crates/ra_ide_db/src/source_change.rs
@@ -3,23 +3,22 @@
3//! 3//!
4//! It can be viewed as a dual for `AnalysisChange`. 4//! It can be viewed as a dual for `AnalysisChange`.
5 5
6use ra_db::RelativePathBuf; 6use ra_db::{FileId, RelativePathBuf, SourceRootId};
7use ra_text_edit::TextEdit; 7use ra_text_edit::TextEdit;
8 8
9use crate::{FileId, FilePosition, SourceRootId, TextSize}; 9#[derive(Debug, Clone)]
10
11#[derive(Debug)]
12pub struct SourceChange { 10pub struct SourceChange {
11 /// For display in the undo log in the editor
13 pub label: String, 12 pub label: String,
14 pub source_file_edits: Vec<SourceFileEdit>, 13 pub source_file_edits: Vec<SourceFileEdit>,
15 pub file_system_edits: Vec<FileSystemEdit>, 14 pub file_system_edits: Vec<FileSystemEdit>,
16 pub cursor_position: Option<FilePosition>, 15 pub is_snippet: bool,
17} 16}
18 17
19impl SourceChange { 18impl SourceChange {
20 /// Creates a new SourceChange with the given label 19 /// Creates a new SourceChange with the given label
21 /// from the edits. 20 /// from the edits.
22 pub(crate) fn from_edits<L: Into<String>>( 21 pub fn from_edits<L: Into<String>>(
23 label: L, 22 label: L,
24 source_file_edits: Vec<SourceFileEdit>, 23 source_file_edits: Vec<SourceFileEdit>,
25 file_system_edits: Vec<FileSystemEdit>, 24 file_system_edits: Vec<FileSystemEdit>,
@@ -28,18 +27,20 @@ impl SourceChange {
28 label: label.into(), 27 label: label.into(),
29 source_file_edits, 28 source_file_edits,
30 file_system_edits, 29 file_system_edits,
31 cursor_position: None, 30 is_snippet: false,
32 } 31 }
33 } 32 }
34 33
35 /// Creates a new SourceChange with the given label, 34 /// Creates a new SourceChange with the given label,
36 /// containing only the given `SourceFileEdits`. 35 /// containing only the given `SourceFileEdits`.
37 pub(crate) fn source_file_edits<L: Into<String>>(label: L, edits: Vec<SourceFileEdit>) -> Self { 36 pub fn source_file_edits<L: Into<String>>(label: L, edits: Vec<SourceFileEdit>) -> Self {
37 let label = label.into();
38 assert!(label.starts_with(char::is_uppercase));
38 SourceChange { 39 SourceChange {
39 label: label.into(), 40 label: label,
40 source_file_edits: edits, 41 source_file_edits: edits,
41 file_system_edits: vec![], 42 file_system_edits: vec![],
42 cursor_position: None, 43 is_snippet: false,
43 } 44 }
44 } 45 }
45 46
@@ -50,19 +51,19 @@ impl SourceChange {
50 label: label.into(), 51 label: label.into(),
51 source_file_edits: vec![], 52 source_file_edits: vec![],
52 file_system_edits: edits, 53 file_system_edits: edits,
53 cursor_position: None, 54 is_snippet: false,
54 } 55 }
55 } 56 }
56 57
57 /// Creates a new SourceChange with the given label, 58 /// Creates a new SourceChange with the given label,
58 /// containing only a single `SourceFileEdit`. 59 /// containing only a single `SourceFileEdit`.
59 pub(crate) fn source_file_edit<L: Into<String>>(label: L, edit: SourceFileEdit) -> Self { 60 pub fn source_file_edit<L: Into<String>>(label: L, edit: SourceFileEdit) -> Self {
60 SourceChange::source_file_edits(label, vec![edit]) 61 SourceChange::source_file_edits(label, vec![edit])
61 } 62 }
62 63
63 /// Creates a new SourceChange with the given label 64 /// Creates a new SourceChange with the given label
64 /// from the given `FileId` and `TextEdit` 65 /// from the given `FileId` and `TextEdit`
65 pub(crate) fn source_file_edit_from<L: Into<String>>( 66 pub fn source_file_edit_from<L: Into<String>>(
66 label: L, 67 label: L,
67 file_id: FileId, 68 file_id: FileId,
68 edit: TextEdit, 69 edit: TextEdit,
@@ -72,48 +73,35 @@ impl SourceChange {
72 73
73 /// Creates a new SourceChange with the given label 74 /// Creates a new SourceChange with the given label
74 /// from the given `FileId` and `TextEdit` 75 /// from the given `FileId` and `TextEdit`
75 pub(crate) fn file_system_edit<L: Into<String>>(label: L, edit: FileSystemEdit) -> Self { 76 pub fn file_system_edit<L: Into<String>>(label: L, edit: FileSystemEdit) -> Self {
76 SourceChange::file_system_edits(label, vec![edit]) 77 SourceChange::file_system_edits(label, vec![edit])
77 } 78 }
78
79 /// Sets the cursor position to the given `FilePosition`
80 pub(crate) fn with_cursor(mut self, cursor_position: FilePosition) -> Self {
81 self.cursor_position = Some(cursor_position);
82 self
83 }
84
85 /// Sets the cursor position to the given `FilePosition`
86 pub(crate) fn with_cursor_opt(mut self, cursor_position: Option<FilePosition>) -> Self {
87 self.cursor_position = cursor_position;
88 self
89 }
90} 79}
91 80
92#[derive(Debug)] 81#[derive(Debug, Clone)]
93pub struct SourceFileEdit { 82pub struct SourceFileEdit {
94 pub file_id: FileId, 83 pub file_id: FileId,
95 pub edit: TextEdit, 84 pub edit: TextEdit,
96} 85}
97 86
98#[derive(Debug)] 87#[derive(Debug, Clone)]
99pub enum FileSystemEdit { 88pub enum FileSystemEdit {
100 CreateFile { source_root: SourceRootId, path: RelativePathBuf }, 89 CreateFile { source_root: SourceRootId, path: RelativePathBuf },
101 MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf }, 90 MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf },
102} 91}
103 92
104pub(crate) struct SingleFileChange { 93pub struct SingleFileChange {
105 pub label: String, 94 pub label: String,
106 pub edit: TextEdit, 95 pub edit: TextEdit,
107 pub cursor_position: Option<TextSize>,
108} 96}
109 97
110impl SingleFileChange { 98impl SingleFileChange {
111 pub(crate) fn into_source_change(self, file_id: FileId) -> SourceChange { 99 pub fn into_source_change(self, file_id: FileId) -> SourceChange {
112 SourceChange { 100 SourceChange {
113 label: self.label, 101 label: self.label,
114 source_file_edits: vec![SourceFileEdit { file_id, edit: self.edit }], 102 source_file_edits: vec![SourceFileEdit { file_id, edit: self.edit }],
115 file_system_edits: Vec::new(), 103 file_system_edits: Vec::new(),
116 cursor_position: self.cursor_position.map(|offset| FilePosition { file_id, offset }), 104 is_snippet: false,
117 } 105 }
118 } 106 }
119} 107}
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index 1a020398e..9c450eaba 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -22,7 +22,7 @@ pub enum ParseError {
22 RepetitionEmtpyTokenTree, 22 RepetitionEmtpyTokenTree,
23} 23}
24 24
25#[derive(Debug, PartialEq, Eq)] 25#[derive(Debug, PartialEq, Eq, Clone)]
26pub enum ExpandError { 26pub enum ExpandError {
27 NoMatchingRule, 27 NoMatchingRule,
28 UnexpectedToken, 28 UnexpectedToken,
diff --git a/crates/ra_mbe/src/mbe_expander/transcriber.rs b/crates/ra_mbe/src/mbe_expander/transcriber.rs
index 4b173edd3..7c9bb4d00 100644
--- a/crates/ra_mbe/src/mbe_expander/transcriber.rs
+++ b/crates/ra_mbe/src/mbe_expander/transcriber.rs
@@ -1,4 +1,4 @@
1//! Transcraber takes a template, like `fn $ident() {}`, a set of bindings like 1//! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like
2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` 2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
3 3
4use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
@@ -53,7 +53,8 @@ impl Bindings {
53pub(super) fn transcribe(template: &tt::Subtree, bindings: &Bindings) -> ExpandResult<tt::Subtree> { 53pub(super) fn transcribe(template: &tt::Subtree, bindings: &Bindings) -> ExpandResult<tt::Subtree> {
54 assert!(template.delimiter == None); 54 assert!(template.delimiter == None);
55 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() }; 55 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() };
56 expand_subtree(&mut ctx, template) 56 let mut arena: Vec<tt::TokenTree> = Vec::new();
57 expand_subtree(&mut ctx, template, &mut arena)
57} 58}
58 59
59#[derive(Debug)] 60#[derive(Debug)]
@@ -73,8 +74,13 @@ struct ExpandCtx<'a> {
73 nesting: Vec<NestingState>, 74 nesting: Vec<NestingState>,
74} 75}
75 76
76fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<tt::Subtree> { 77fn expand_subtree(
77 let mut buf: Vec<tt::TokenTree> = Vec::new(); 78 ctx: &mut ExpandCtx,
79 template: &tt::Subtree,
80 arena: &mut Vec<tt::TokenTree>,
81) -> ExpandResult<tt::Subtree> {
82 // remember how many elements are in the arena now - when returning, we want to drain exactly how many elements we added. This way, the recursive uses of the arena get their own "view" of the arena, but will reuse the allocation
83 let start_elements = arena.len();
78 let mut err = None; 84 let mut err = None;
79 for op in parse_template(template) { 85 for op in parse_template(template) {
80 let op = match op { 86 let op = match op {
@@ -85,25 +91,27 @@ fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<t
85 } 91 }
86 }; 92 };
87 match op { 93 match op {
88 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()), 94 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => arena.push(tt.clone()),
89 Op::TokenTree(tt::TokenTree::Subtree(tt)) => { 95 Op::TokenTree(tt::TokenTree::Subtree(tt)) => {
90 let ExpandResult(tt, e) = expand_subtree(ctx, tt); 96 let ExpandResult(tt, e) = expand_subtree(ctx, tt, arena);
91 err = err.or(e); 97 err = err.or(e);
92 buf.push(tt.into()); 98 arena.push(tt.into());
93 } 99 }
94 Op::Var { name, kind: _ } => { 100 Op::Var { name, kind: _ } => {
95 let ExpandResult(fragment, e) = expand_var(ctx, name); 101 let ExpandResult(fragment, e) = expand_var(ctx, name);
96 err = err.or(e); 102 err = err.or(e);
97 push_fragment(&mut buf, fragment); 103 push_fragment(arena, fragment);
98 } 104 }
99 Op::Repeat { subtree, kind, separator } => { 105 Op::Repeat { subtree, kind, separator } => {
100 let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator); 106 let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator, arena);
101 err = err.or(e); 107 err = err.or(e);
102 push_fragment(&mut buf, fragment) 108 push_fragment(arena, fragment)
103 } 109 }
104 } 110 }
105 } 111 }
106 ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err) 112 // drain the elements added in this instance of expand_subtree
113 let tts = arena.drain(start_elements..arena.len()).collect();
114 ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err)
107} 115}
108 116
109fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { 117fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
@@ -155,6 +163,7 @@ fn expand_repeat(
155 template: &tt::Subtree, 163 template: &tt::Subtree,
156 kind: RepeatKind, 164 kind: RepeatKind,
157 separator: Option<Separator>, 165 separator: Option<Separator>,
166 arena: &mut Vec<tt::TokenTree>,
158) -> ExpandResult<Fragment> { 167) -> ExpandResult<Fragment> {
159 let mut buf: Vec<tt::TokenTree> = Vec::new(); 168 let mut buf: Vec<tt::TokenTree> = Vec::new();
160 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false }); 169 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false });
@@ -165,7 +174,7 @@ fn expand_repeat(
165 let mut counter = 0; 174 let mut counter = 0;
166 175
167 loop { 176 loop {
168 let ExpandResult(mut t, e) = expand_subtree(ctx, template); 177 let ExpandResult(mut t, e) = expand_subtree(ctx, template, arena);
169 let nesting_state = ctx.nesting.last_mut().unwrap(); 178 let nesting_state = ctx.nesting.last_mut().unwrap();
170 if nesting_state.at_end || !nesting_state.hit { 179 if nesting_state.at_end || !nesting_state.hit {
171 break; 180 break;
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index bb28acfd9..fc4133a67 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -63,7 +63,7 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke
63// * Items(SmallVec<[P<ast::Item>; 1]>) -> token_tree_to_items 63// * Items(SmallVec<[P<ast::Item>; 1]>) -> token_tree_to_items
64// 64//
65// * TraitItems(SmallVec<[ast::TraitItem; 1]>) 65// * TraitItems(SmallVec<[ast::TraitItem; 1]>)
66// * ImplItems(SmallVec<[ast::ImplItem; 1]>) 66// * AssocItems(SmallVec<[ast::AssocItem; 1]>)
67// * ForeignItems(SmallVec<[ast::ForeignItem; 1]> 67// * ForeignItems(SmallVec<[ast::ForeignItem; 1]>
68 68
69pub fn token_tree_to_syntax_node( 69pub fn token_tree_to_syntax_node(
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 0d924ce58..c43003fd6 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -266,21 +266,20 @@ fn test_expr_order() {
266 [email protected] "(" 266 [email protected] "("
267 [email protected] ")" 267 [email protected] ")"
268 [email protected] 268 [email protected]
269 [email protected] 269 [email protected] "{"
270 [email protected] "{" 270 [email protected]
271 [email protected] 271 [email protected]
272 [email protected] 272 [email protected]
273 [email protected] 273 [email protected]
274 [email protected] 274 [email protected] "1"
275 [email protected] "1" 275 [email protected] "+"
276 [email protected] "+" 276 [email protected]
277 [email protected] 277 [email protected] "1"
278 [email protected] "1" 278 [email protected] "*"
279 [email protected] "*" 279 [email protected]
280 [email protected] 280 [email protected] "2"
281 [email protected] "2" 281 [email protected] ";"
282 [email protected] ";" 282 [email protected] "}""#,
283 [email protected] "}""#,
284 ); 283 );
285} 284}
286 285
@@ -1114,68 +1113,67 @@ fn test_vec() {
1114 assert_eq!( 1113 assert_eq!(
1115 format!("{:#?}", tree).trim(), 1114 format!("{:#?}", tree).trim(),
1116 r#"[email protected] 1115 r#"[email protected]
1117 [email protected] 1116 [email protected] "{"
1118 [email protected] "{" 1117 [email protected]
1119 [email protected] 1118 [email protected] "let"
1120 [email protected] "let" 1119 [email protected]
1121 [email protected] 1120 [email protected] "mut"
1122 [email protected] "mut" 1121 [email protected]
1123 [email protected] 1122 [email protected] "v"
1124 [email protected] "v" 1123 [email protected] "="
1125 [email protected] "=" 1124 [email protected]
1126 [email protected] 1125 [email protected]
1127 [email protected] 1126 [email protected]
1128 [email protected] 1127 [email protected]
1129 [email protected] 1128 [email protected]
1130 [email protected] 1129 [email protected]
1131 [email protected] 1130 [email protected] "Vec"
1132 [email protected] "Vec" 1131 [email protected] "::"
1133 [email protected] "::" 1132 [email protected]
1134 [email protected] 1133 [email protected]
1135 [email protected] 1134 [email protected] "new"
1136 [email protected] "new" 1135 [email protected]
1137 [email protected] 1136 [email protected] "("
1138 [email protected] "(" 1137 [email protected] ")"
1139 [email protected] ")" 1138 [email protected] ";"
1140 [email protected] ";" 1139 [email protected]
1141 [email protected] 1140 [email protected]
1142 [email protected] 1141 [email protected]
1143 [email protected] 1142 [email protected]
1144 [email protected] 1143 [email protected]
1145 [email protected] 1144 [email protected]
1146 [email protected] 1145 [email protected] "v"
1147 [email protected] "v" 1146 [email protected] "."
1148 [email protected] "." 1147 [email protected]
1149 [email protected] 1148 [email protected] "push"
1150 [email protected] "push" 1149 [email protected]
1151 [email protected] 1150 [email protected] "("
1152 [email protected] "(" 1151 [email protected]
1153 [email protected] 1152 [email protected] "1u32"
1154 [email protected] "1u32" 1153 [email protected] ")"
1155 [email protected] ")" 1154 [email protected] ";"
1156 [email protected] ";" 1155 [email protected]
1157 [email protected] 1156 [email protected]
1158 [email protected] 1157 [email protected]
1159 [email protected] 1158 [email protected]
1160 [email protected] 1159 [email protected]
1161 [email protected] 1160 [email protected]
1162 [email protected] 1161 [email protected] "v"
1163 [email protected] "v" 1162 [email protected] "."
1164 [email protected] "." 1163 [email protected]
1165 [email protected] 1164 [email protected] "push"
1166 [email protected] "push" 1165 [email protected]
1167 [email protected] 1166 [email protected] "("
1168 [email protected] "(" 1167 [email protected]
1169 [email protected] 1168 [email protected] "2"
1170 [email protected] "2" 1169 [email protected] ")"
1171 [email protected] ")" 1170 [email protected] ";"
1172 [email protected] ";" 1171 [email protected]
1173 [email protected] 1172 [email protected]
1174 [email protected] 1173 [email protected]
1175 [email protected] 1174 [email protected]
1176 [email protected] 1175 [email protected] "v"
1177 [email protected] "v" 1176 [email protected] "}""#
1178 [email protected] "}""#
1179 ); 1177 );
1180} 1178}
1181 1179
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index c2a6e82e9..be0cd5661 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -54,7 +54,7 @@ pub(crate) mod fragments {
54 use super::*; 54 use super::*;
55 55
56 pub(crate) use super::{ 56 pub(crate) use super::{
57 expressions::block, paths::type_path as path, patterns::pattern, types::type_, 57 expressions::block_expr, paths::type_path as path, patterns::pattern, types::type_,
58 }; 58 };
59 59
60 pub(crate) fn expr(p: &mut Parser) { 60 pub(crate) fn expr(p: &mut Parser) {
@@ -143,7 +143,7 @@ pub(crate) fn reparser(
143 parent: Option<SyntaxKind>, 143 parent: Option<SyntaxKind>,
144) -> Option<fn(&mut Parser)> { 144) -> Option<fn(&mut Parser)> {
145 let res = match node { 145 let res = match node {
146 BLOCK => expressions::naked_block, 146 BLOCK_EXPR => expressions::block_expr,
147 RECORD_FIELD_DEF_LIST => items::record_field_def_list, 147 RECORD_FIELD_DEF_LIST => items::record_field_def_list,
148 RECORD_FIELD_LIST => items::record_field_list, 148 RECORD_FIELD_LIST => items::record_field_list,
149 ENUM_VARIANT_LIST => items::enum_variant_list, 149 ENUM_VARIANT_LIST => items::enum_variant_list,
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index cb30b25a8..34f039768 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -2,7 +2,7 @@
2 2
3mod atom; 3mod atom;
4 4
5pub(crate) use self::atom::match_arm_list; 5pub(crate) use self::atom::{block_expr, match_arm_list};
6pub(super) use self::atom::{literal, LITERAL_FIRST}; 6pub(super) use self::atom::{literal, LITERAL_FIRST};
7use super::*; 7use super::*;
8 8
@@ -49,28 +49,6 @@ fn expr_no_struct(p: &mut Parser) {
49 expr_bp(p, r, 1); 49 expr_bp(p, r, 1);
50} 50}
51 51
52// test block
53// fn a() {}
54// fn b() { let _ = 1; }
55// fn c() { 1; 2; }
56// fn d() { 1; 2 }
57pub(crate) fn block(p: &mut Parser) {
58 if !p.at(T!['{']) {
59 p.error("expected a block");
60 return;
61 }
62 atom::block_expr(p, None);
63}
64
65pub(crate) fn naked_block(p: &mut Parser) {
66 assert!(p.at(T!['{']));
67 let m = p.start();
68 p.bump(T!['{']);
69 expr_block_contents(p);
70 p.expect(T!['}']);
71 m.complete(p, BLOCK);
72}
73
74fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool { 52fn is_expr_stmt_attr_allowed(kind: SyntaxKind) -> bool {
75 match kind { 53 match kind {
76 BIN_EXPR | RANGE_EXPR | IF_EXPR => false, 54 BIN_EXPR | RANGE_EXPR | IF_EXPR => false,
@@ -197,7 +175,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
197 } 175 }
198} 176}
199 177
200pub(crate) fn expr_block_contents(p: &mut Parser) { 178pub(super) fn expr_block_contents(p: &mut Parser) {
201 // This is checked by a validator 179 // This is checked by a validator
202 attributes::inner_attributes(p); 180 attributes::inner_attributes(p);
203 181
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 76aa601cb..706a2f796 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -84,7 +84,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
84 T![box] => box_expr(p, None), 84 T![box] => box_expr(p, None),
85 T![for] => for_expr(p, None), 85 T![for] => for_expr(p, None),
86 T![while] => while_expr(p, None), 86 T![while] => while_expr(p, None),
87 T![try] => try_expr(p, None), 87 T![try] => try_block_expr(p, None),
88 LIFETIME if la == T![:] => { 88 LIFETIME if la == T![:] => {
89 let m = p.start(); 89 let m = p.start();
90 label(p); 90 label(p);
@@ -92,7 +92,12 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
92 T![loop] => loop_expr(p, Some(m)), 92 T![loop] => loop_expr(p, Some(m)),
93 T![for] => for_expr(p, Some(m)), 93 T![for] => for_expr(p, Some(m)),
94 T![while] => while_expr(p, Some(m)), 94 T![while] => while_expr(p, Some(m)),
95 T!['{'] => block_expr(p, Some(m)), 95 // test labeled_block
96 // fn f() { 'label: {}; }
97 T!['{'] => {
98 block_expr(p);
99 m.complete(p, EFFECT_EXPR)
100 }
96 _ => { 101 _ => {
97 // test_err misplaced_label_err 102 // test_err misplaced_label_err
98 // fn main() { 103 // fn main() {
@@ -108,13 +113,17 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
108 let m = p.start(); 113 let m = p.start();
109 p.bump(T![async]); 114 p.bump(T![async]);
110 p.eat(T![move]); 115 p.eat(T![move]);
111 block_expr(p, Some(m)) 116 block_expr(p);
117 m.complete(p, EFFECT_EXPR)
112 } 118 }
113 T![match] => match_expr(p), 119 T![match] => match_expr(p),
120 // test unsafe_block
121 // fn f() { unsafe { } }
114 T![unsafe] if la == T!['{'] => { 122 T![unsafe] if la == T!['{'] => {
115 let m = p.start(); 123 let m = p.start();
116 p.bump(T![unsafe]); 124 p.bump(T![unsafe]);
117 block_expr(p, Some(m)) 125 block_expr(p);
126 m.complete(p, EFFECT_EXPR)
118 } 127 }
119 T!['{'] => { 128 T!['{'] => {
120 // test for_range_from 129 // test for_range_from
@@ -123,7 +132,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
123 // break; 132 // break;
124 // } 133 // }
125 // } 134 // }
126 block_expr(p, None) 135 block_expr_unchecked(p)
127 } 136 }
128 T![return] => return_expr(p), 137 T![return] => return_expr(p),
129 T![continue] => continue_expr(p), 138 T![continue] => continue_expr(p),
@@ -134,7 +143,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
134 } 143 }
135 }; 144 };
136 let blocklike = match done.kind() { 145 let blocklike = match done.kind() {
137 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | TRY_EXPR => { 146 IF_EXPR | WHILE_EXPR | FOR_EXPR | LOOP_EXPR | MATCH_EXPR | BLOCK_EXPR | EFFECT_EXPR => {
138 BlockLike::Block 147 BlockLike::Block
139 } 148 }
140 _ => BlockLike::NotBlock, 149 _ => BlockLike::NotBlock,
@@ -231,13 +240,9 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
231 p.eat(T![move]); 240 p.eat(T![move]);
232 params::param_list_closure(p); 241 params::param_list_closure(p);
233 if opt_fn_ret_type(p) { 242 if opt_fn_ret_type(p) {
234 if p.at(T!['{']) { 243 // test lambda_ret_block
235 // test lambda_ret_block 244 // fn main() { || -> i32 { 92 }(); }
236 // fn main() { || -> i32 { 92 }(); } 245 block_expr(p);
237 block_expr(p, None);
238 } else {
239 p.error("expected `{`");
240 }
241 } else { 246 } else {
242 if p.at_ts(EXPR_FIRST) { 247 if p.at_ts(EXPR_FIRST) {
243 expr(p); 248 expr(p);
@@ -261,13 +266,13 @@ fn if_expr(p: &mut Parser) -> CompletedMarker {
261 let m = p.start(); 266 let m = p.start();
262 p.bump(T![if]); 267 p.bump(T![if]);
263 cond(p); 268 cond(p);
264 block(p); 269 block_expr(p);
265 if p.at(T![else]) { 270 if p.at(T![else]) {
266 p.bump(T![else]); 271 p.bump(T![else]);
267 if p.at(T![if]) { 272 if p.at(T![if]) {
268 if_expr(p); 273 if_expr(p);
269 } else { 274 } else {
270 block(p); 275 block_expr(p);
271 } 276 }
272 } 277 }
273 m.complete(p, IF_EXPR) 278 m.complete(p, IF_EXPR)
@@ -295,7 +300,7 @@ fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
295 assert!(p.at(T![loop])); 300 assert!(p.at(T![loop]));
296 let m = m.unwrap_or_else(|| p.start()); 301 let m = m.unwrap_or_else(|| p.start());
297 p.bump(T![loop]); 302 p.bump(T![loop]);
298 block(p); 303 block_expr(p);
299 m.complete(p, LOOP_EXPR) 304 m.complete(p, LOOP_EXPR)
300} 305}
301 306
@@ -310,7 +315,7 @@ fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
310 let m = m.unwrap_or_else(|| p.start()); 315 let m = m.unwrap_or_else(|| p.start());
311 p.bump(T![while]); 316 p.bump(T![while]);
312 cond(p); 317 cond(p);
313 block(p); 318 block_expr(p);
314 m.complete(p, WHILE_EXPR) 319 m.complete(p, WHILE_EXPR)
315} 320}
316 321
@@ -325,7 +330,7 @@ fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
325 patterns::pattern(p); 330 patterns::pattern(p);
326 p.expect(T![in]); 331 p.expect(T![in]);
327 expr_no_struct(p); 332 expr_no_struct(p);
328 block(p); 333 block_expr(p);
329 m.complete(p, FOR_EXPR) 334 m.complete(p, FOR_EXPR)
330} 335}
331 336
@@ -458,16 +463,25 @@ fn match_guard(p: &mut Parser) -> CompletedMarker {
458 m.complete(p, MATCH_GUARD) 463 m.complete(p, MATCH_GUARD)
459} 464}
460 465
461// test block_expr 466// test block
462// fn foo() { 467// fn a() {}
463// {}; 468// fn b() { let _ = 1; }
464// unsafe {}; 469// fn c() { 1; 2; }
465// 'label: {}; 470// fn d() { 1; 2 }
466// } 471pub(crate) fn block_expr(p: &mut Parser) {
467pub(super) fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 472 if !p.at(T!['{']) {
473 p.error("expected a block");
474 return;
475 }
476 block_expr_unchecked(p);
477}
478
479fn block_expr_unchecked(p: &mut Parser) -> CompletedMarker {
468 assert!(p.at(T!['{'])); 480 assert!(p.at(T!['{']));
469 let m = m.unwrap_or_else(|| p.start()); 481 let m = p.start();
470 naked_block(p); 482 p.bump(T!['{']);
483 expr_block_contents(p);
484 p.expect(T!['}']);
471 m.complete(p, BLOCK_EXPR) 485 m.complete(p, BLOCK_EXPR)
472} 486}
473 487
@@ -532,7 +546,7 @@ fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
532// fn foo() { 546// fn foo() {
533// let _ = try {}; 547// let _ = try {};
534// } 548// }
535fn try_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 549fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
536 assert!(p.at(T![try])); 550 assert!(p.at(T![try]));
537 let m = m.unwrap_or_else(|| p.start()); 551 let m = m.unwrap_or_else(|| p.start());
538 // Special-case `try!` as macro. 552 // Special-case `try!` as macro.
@@ -552,8 +566,8 @@ fn try_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
552 } 566 }
553 567
554 p.bump(T![try]); 568 p.bump(T![try]);
555 block(p); 569 block_expr(p);
556 m.complete(p, TRY_EXPR) 570 m.complete(p, EFFECT_EXPR)
557} 571}
558 572
559// test box_expr 573// test box_expr
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 1503a8730..67a924de5 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -329,7 +329,7 @@ fn fn_def(p: &mut Parser) {
329 if p.at(T![;]) { 329 if p.at(T![;]) {
330 p.bump(T![;]); 330 p.bump(T![;]);
331 } else { 331 } else {
332 expressions::block(p) 332 expressions::block_expr(p)
333 } 333 }
334} 334}
335 335
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs
index 33d9973e9..2d61f9d80 100644
--- a/crates/ra_parser/src/grammar/type_args.rs
+++ b/crates/ra_parser/src/grammar/type_args.rs
@@ -48,7 +48,7 @@ fn type_arg(p: &mut Parser) {
48 m.complete(p, ASSOC_TYPE_ARG); 48 m.complete(p, ASSOC_TYPE_ARG);
49 } 49 }
50 T!['{'] => { 50 T!['{'] => {
51 expressions::block(p); 51 expressions::block_expr(p);
52 m.complete(p, CONST_ARG); 52 m.complete(p, CONST_ARG);
53 } 53 }
54 k if k.is_literal() => { 54 k if k.is_literal() => {
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs
index 652492c1e..eeb8ad66b 100644
--- a/crates/ra_parser/src/lib.rs
+++ b/crates/ra_parser/src/lib.rs
@@ -25,7 +25,7 @@ pub(crate) use token_set::TokenSet;
25pub use syntax_kind::SyntaxKind; 25pub use syntax_kind::SyntaxKind;
26 26
27#[derive(Debug, Clone, PartialEq, Eq, Hash)] 27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28pub struct ParseError(pub String); 28pub struct ParseError(pub Box<String>);
29 29
30/// `TokenSource` abstracts the source of the tokens parser operates on. 30/// `TokenSource` abstracts the source of the tokens parser operates on.
31/// 31///
@@ -112,7 +112,7 @@ pub fn parse_fragment(
112 FragmentKind::Type => grammar::fragments::type_, 112 FragmentKind::Type => grammar::fragments::type_,
113 FragmentKind::Pattern => grammar::fragments::pattern, 113 FragmentKind::Pattern => grammar::fragments::pattern,
114 FragmentKind::Item => grammar::fragments::item, 114 FragmentKind::Item => grammar::fragments::item,
115 FragmentKind::Block => grammar::fragments::block, 115 FragmentKind::Block => grammar::fragments::block_expr,
116 FragmentKind::Visibility => grammar::fragments::opt_visibility, 116 FragmentKind::Visibility => grammar::fragments::opt_visibility,
117 FragmentKind::MetaItem => grammar::fragments::meta_item, 117 FragmentKind::MetaItem => grammar::fragments::meta_item,
118 FragmentKind::Statement => grammar::fragments::stmt, 118 FragmentKind::Statement => grammar::fragments::stmt,
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
index faa63d53f..4f59b0a23 100644
--- a/crates/ra_parser/src/parser.rs
+++ b/crates/ra_parser/src/parser.rs
@@ -192,7 +192,7 @@ impl<'t> Parser<'t> {
192 /// structured errors with spans and notes, like rustc 192 /// structured errors with spans and notes, like rustc
193 /// does. 193 /// does.
194 pub(crate) fn error<T: Into<String>>(&mut self, message: T) { 194 pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
195 let msg = ParseError(message.into()); 195 let msg = ParseError(Box::new(message.into()));
196 self.push_event(Event::Error { msg }) 196 self.push_event(Event::Error { msg })
197 } 197 }
198 198
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index ab727ed7e..e7404492a 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -191,6 +191,7 @@ pub enum SyntaxKind {
191 RECORD_LIT, 191 RECORD_LIT,
192 RECORD_FIELD_LIST, 192 RECORD_FIELD_LIST,
193 RECORD_FIELD, 193 RECORD_FIELD,
194 EFFECT_EXPR,
194 BOX_EXPR, 195 BOX_EXPR,
195 CALL_EXPR, 196 CALL_EXPR,
196 INDEX_EXPR, 197 INDEX_EXPR,
@@ -203,7 +204,6 @@ pub enum SyntaxKind {
203 PREFIX_EXPR, 204 PREFIX_EXPR,
204 RANGE_EXPR, 205 RANGE_EXPR,
205 BIN_EXPR, 206 BIN_EXPR,
206 BLOCK,
207 EXTERN_BLOCK, 207 EXTERN_BLOCK,
208 EXTERN_ITEM_LIST, 208 EXTERN_ITEM_LIST,
209 ENUM_VARIANT, 209 ENUM_VARIANT,
diff --git a/crates/ra_proc_macro_srv/Cargo.toml b/crates/ra_proc_macro_srv/Cargo.toml
index 886e14870..bb3003278 100644
--- a/crates/ra_proc_macro_srv/Cargo.toml
+++ b/crates/ra_proc_macro_srv/Cargo.toml
@@ -18,7 +18,7 @@ memmap = "0.7"
18test_utils = { path = "../test_utils" } 18test_utils = { path = "../test_utils" }
19 19
20[dev-dependencies] 20[dev-dependencies]
21cargo_metadata = "0.9.1" 21cargo_metadata = "0.10.0"
22difference = "2.0.0" 22difference = "2.0.0"
23# used as proc macro test target 23# used as proc macro test target
24serde_derive = "=1.0.106" 24serde_derive = "1.0.106"
diff --git a/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt b/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
index 6776f5231..bc010cfe9 100644
--- a/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
+++ b/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
@@ -23,23 +23,12 @@ SUBTREE $
23 SUBTREE [] 4294967295 23 SUBTREE [] 4294967295
24 IDENT allow 4294967295 24 IDENT allow 4294967295
25 SUBTREE () 4294967295 25 SUBTREE () 4294967295
26 IDENT unknown_lints 4294967295
27 PUNCH # [alone] 4294967295
28 SUBTREE [] 4294967295
29 IDENT cfg_attr 4294967295
30 SUBTREE () 4294967295
31 IDENT feature 4294967295
32 PUNCH = [alone] 4294967295
33 LITERAL "cargo-clippy" 0
34 PUNCH , [alone] 4294967295
35 IDENT allow 4294967295
36 SUBTREE () 4294967295
37 IDENT useless_attribute 4294967295
38 PUNCH # [alone] 4294967295
39 SUBTREE [] 4294967295
40 IDENT allow 4294967295
41 SUBTREE () 4294967295
42 IDENT rust_2018_idioms 4294967295 26 IDENT rust_2018_idioms 4294967295
27 PUNCH , [alone] 4294967295
28 IDENT clippy 4294967295
29 PUNCH : [joint] 4294967295
30 PUNCH : [alone] 4294967295
31 IDENT useless_attribute 4294967295
43 IDENT extern 4294967295 32 IDENT extern 4294967295
44 IDENT crate 4294967295 33 IDENT crate 4294967295
45 IDENT serde 4294967295 34 IDENT serde 4294967295
diff --git a/crates/ra_proc_macro_srv/src/tests/mod.rs b/crates/ra_proc_macro_srv/src/tests/mod.rs
index 9cf58511c..82cefbb29 100644
--- a/crates/ra_proc_macro_srv/src/tests/mod.rs
+++ b/crates/ra_proc_macro_srv/src/tests/mod.rs
@@ -10,7 +10,7 @@ fn test_derive_serialize_proc_macro() {
10 assert_expand( 10 assert_expand(
11 "serde_derive", 11 "serde_derive",
12 "Serialize", 12 "Serialize",
13 "1.0.106", 13 "1.0",
14 r##"struct Foo {}"##, 14 r##"struct Foo {}"##,
15 include_str!("fixtures/test_serialize_proc_macro.txt"), 15 include_str!("fixtures/test_serialize_proc_macro.txt"),
16 ); 16 );
@@ -21,7 +21,7 @@ fn test_derive_serialize_proc_macro_failed() {
21 assert_expand( 21 assert_expand(
22 "serde_derive", 22 "serde_derive",
23 "Serialize", 23 "Serialize",
24 "1.0.106", 24 "1.0",
25 r##" 25 r##"
26 struct {} 26 struct {}
27"##, 27"##,
@@ -37,7 +37,7 @@ SUBTREE $
37 37
38#[test] 38#[test]
39fn test_derive_proc_macro_list() { 39fn test_derive_proc_macro_list() {
40 let res = list("serde_derive", "1.0.106").join("\n"); 40 let res = list("serde_derive", "1.0").join("\n");
41 41
42 assert_eq_text!( 42 assert_eq_text!(
43 &res, 43 &res,
diff --git a/crates/ra_proc_macro_srv/src/tests/utils.rs b/crates/ra_proc_macro_srv/src/tests/utils.rs
index 646a427c5..84348b5de 100644
--- a/crates/ra_proc_macro_srv/src/tests/utils.rs
+++ b/crates/ra_proc_macro_srv/src/tests/utils.rs
@@ -8,7 +8,7 @@ use std::str::FromStr;
8use test_utils::assert_eq_text; 8use test_utils::assert_eq_text;
9 9
10mod fixtures { 10mod fixtures {
11 use cargo_metadata::{parse_messages, Message}; 11 use cargo_metadata::Message;
12 use std::process::Command; 12 use std::process::Command;
13 13
14 // Use current project metadata to get the proc-macro dylib path 14 // Use current project metadata to get the proc-macro dylib path
@@ -19,7 +19,7 @@ mod fixtures {
19 .unwrap() 19 .unwrap()
20 .stdout; 20 .stdout;
21 21
22 for message in parse_messages(command.as_slice()) { 22 for message in Message::parse_stream(command.as_slice()) {
23 match message.unwrap() { 23 match message.unwrap() {
24 Message::CompilerArtifact(artifact) => { 24 Message::CompilerArtifact(artifact) => {
25 if artifact.target.kind.contains(&"proc-macro".to_string()) { 25 if artifact.target.kind.contains(&"proc-macro".to_string()) {
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml
index 5e651fe70..e4a60f4c0 100644
--- a/crates/ra_project_model/Cargo.toml
+++ b/crates/ra_project_model/Cargo.toml
@@ -11,11 +11,12 @@ doctest = false
11log = "0.4.8" 11log = "0.4.8"
12rustc-hash = "1.1.0" 12rustc-hash = "1.1.0"
13 13
14cargo_metadata = "0.9.1" 14cargo_metadata = "0.10.0"
15 15
16ra_arena = { path = "../ra_arena" } 16ra_arena = { path = "../ra_arena" }
17ra_db = { path = "../ra_db" }
18ra_cfg = { path = "../ra_cfg" } 17ra_cfg = { path = "../ra_cfg" }
18ra_db = { path = "../ra_db" }
19ra_toolchain = { path = "../ra_toolchain" }
19ra_proc_macro = { path = "../ra_proc_macro" } 20ra_proc_macro = { path = "../ra_proc_macro" }
20 21
21serde = { version = "1.0.106", features = ["derive"] } 22serde = { version = "1.0.106", features = ["derive"] }
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 362ee30fe..a306ce95f 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -1,7 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::{ 3use std::{
4 env,
5 ffi::OsStr, 4 ffi::OsStr,
6 ops, 5 ops,
7 path::{Path, PathBuf}, 6 path::{Path, PathBuf},
@@ -56,6 +55,9 @@ pub struct CargoConfig {
56 55
57 /// Runs cargo check on launch to figure out the correct values of OUT_DIR 56 /// Runs cargo check on launch to figure out the correct values of OUT_DIR
58 pub load_out_dirs_from_check: bool, 57 pub load_out_dirs_from_check: bool,
58
59 /// rustc target
60 pub target: Option<String>,
59} 61}
60 62
61impl Default for CargoConfig { 63impl Default for CargoConfig {
@@ -65,6 +67,7 @@ impl Default for CargoConfig {
65 all_features: true, 67 all_features: true,
66 features: Vec::new(), 68 features: Vec::new(),
67 load_out_dirs_from_check: false, 69 load_out_dirs_from_check: false,
70 target: None,
68 } 71 }
69 } 72 }
70} 73}
@@ -83,6 +86,7 @@ pub struct PackageData {
83 pub dependencies: Vec<PackageDependency>, 86 pub dependencies: Vec<PackageDependency>,
84 pub edition: Edition, 87 pub edition: Edition,
85 pub features: Vec<String>, 88 pub features: Vec<String>,
89 pub cfgs: Vec<String>,
86 pub out_dir: Option<PathBuf>, 90 pub out_dir: Option<PathBuf>,
87 pub proc_macro_dylib_path: Option<PathBuf>, 91 pub proc_macro_dylib_path: Option<PathBuf>,
88} 92}
@@ -141,12 +145,8 @@ impl CargoWorkspace {
141 cargo_toml: &Path, 145 cargo_toml: &Path,
142 cargo_features: &CargoConfig, 146 cargo_features: &CargoConfig,
143 ) -> Result<CargoWorkspace> { 147 ) -> Result<CargoWorkspace> {
144 let _ = Command::new(cargo_binary())
145 .arg("--version")
146 .output()
147 .context("failed to run `cargo --version`, is `cargo` in PATH?")?;
148
149 let mut meta = MetadataCommand::new(); 148 let mut meta = MetadataCommand::new();
149 meta.cargo_path(ra_toolchain::cargo());
150 meta.manifest_path(cargo_toml); 150 meta.manifest_path(cargo_toml);
151 if cargo_features.all_features { 151 if cargo_features.all_features {
152 meta.features(CargoOpt::AllFeatures); 152 meta.features(CargoOpt::AllFeatures);
@@ -160,15 +160,20 @@ impl CargoWorkspace {
160 if let Some(parent) = cargo_toml.parent() { 160 if let Some(parent) = cargo_toml.parent() {
161 meta.current_dir(parent); 161 meta.current_dir(parent);
162 } 162 }
163 if let Some(target) = cargo_features.target.as_ref() {
164 meta.other_options(vec![String::from("--filter-platform"), target.clone()]);
165 }
163 let meta = meta.exec().with_context(|| { 166 let meta = meta.exec().with_context(|| {
164 format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) 167 format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display())
165 })?; 168 })?;
166 169
167 let mut out_dir_by_id = FxHashMap::default(); 170 let mut out_dir_by_id = FxHashMap::default();
171 let mut cfgs = FxHashMap::default();
168 let mut proc_macro_dylib_paths = FxHashMap::default(); 172 let mut proc_macro_dylib_paths = FxHashMap::default();
169 if cargo_features.load_out_dirs_from_check { 173 if cargo_features.load_out_dirs_from_check {
170 let resources = load_extern_resources(cargo_toml, cargo_features)?; 174 let resources = load_extern_resources(cargo_toml, cargo_features)?;
171 out_dir_by_id = resources.out_dirs; 175 out_dir_by_id = resources.out_dirs;
176 cfgs = resources.cfgs;
172 proc_macro_dylib_paths = resources.proc_dylib_paths; 177 proc_macro_dylib_paths = resources.proc_dylib_paths;
173 } 178 }
174 179
@@ -194,6 +199,7 @@ impl CargoWorkspace {
194 edition, 199 edition,
195 dependencies: Vec::new(), 200 dependencies: Vec::new(),
196 features: Vec::new(), 201 features: Vec::new(),
202 cfgs: cfgs.get(&id).cloned().unwrap_or_default(),
197 out_dir: out_dir_by_id.get(&id).cloned(), 203 out_dir: out_dir_by_id.get(&id).cloned(),
198 proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(), 204 proc_macro_dylib_path: proc_macro_dylib_paths.get(&id).cloned(),
199 }); 205 });
@@ -275,13 +281,14 @@ impl CargoWorkspace {
275pub struct ExternResources { 281pub struct ExternResources {
276 out_dirs: FxHashMap<PackageId, PathBuf>, 282 out_dirs: FxHashMap<PackageId, PathBuf>,
277 proc_dylib_paths: FxHashMap<PackageId, PathBuf>, 283 proc_dylib_paths: FxHashMap<PackageId, PathBuf>,
284 cfgs: FxHashMap<PackageId, Vec<String>>,
278} 285}
279 286
280pub fn load_extern_resources( 287pub fn load_extern_resources(
281 cargo_toml: &Path, 288 cargo_toml: &Path,
282 cargo_features: &CargoConfig, 289 cargo_features: &CargoConfig,
283) -> Result<ExternResources> { 290) -> Result<ExternResources> {
284 let mut cmd = Command::new(cargo_binary()); 291 let mut cmd = Command::new(ra_toolchain::cargo());
285 cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); 292 cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml);
286 if cargo_features.all_features { 293 if cargo_features.all_features {
287 cmd.arg("--all-features"); 294 cmd.arg("--all-features");
@@ -297,13 +304,13 @@ pub fn load_extern_resources(
297 304
298 let mut res = ExternResources::default(); 305 let mut res = ExternResources::default();
299 306
300 for message in cargo_metadata::parse_messages(output.stdout.as_slice()) { 307 for message in cargo_metadata::Message::parse_stream(output.stdout.as_slice()) {
301 if let Ok(message) = message { 308 if let Ok(message) = message {
302 match message { 309 match message {
303 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, .. }) => { 310 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => {
304 res.out_dirs.insert(package_id, out_dir); 311 res.out_dirs.insert(package_id.clone(), out_dir);
312 res.cfgs.insert(package_id, cfgs);
305 } 313 }
306
307 Message::CompilerArtifact(message) => { 314 Message::CompilerArtifact(message) => {
308 if message.target.kind.contains(&"proc-macro".to_string()) { 315 if message.target.kind.contains(&"proc-macro".to_string()) {
309 let package_id = message.package_id; 316 let package_id = message.package_id;
@@ -316,6 +323,8 @@ pub fn load_extern_resources(
316 } 323 }
317 Message::CompilerMessage(_) => (), 324 Message::CompilerMessage(_) => (),
318 Message::Unknown => (), 325 Message::Unknown => (),
326 Message::BuildFinished(_) => {}
327 Message::TextLine(_) => {}
319 } 328 }
320 } 329 }
321 } 330 }
@@ -329,7 +338,3 @@ fn is_dylib(path: &Path) -> bool {
329 Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"), 338 Some(ext) => matches!(ext.as_str(), "dll" | "dylib" | "so"),
330 } 339 }
331} 340}
332
333fn cargo_binary() -> String {
334 env::var("CARGO").unwrap_or_else(|_| "cargo".to_string())
335}
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 731cbd291..a2e9f65ef 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -8,7 +8,7 @@ use std::{
8 fs::{read_dir, File, ReadDir}, 8 fs::{read_dir, File, ReadDir},
9 io::{self, BufReader}, 9 io::{self, BufReader},
10 path::{Path, PathBuf}, 10 path::{Path, PathBuf},
11 process::Command, 11 process::{Command, Output},
12}; 12};
13 13
14use anyhow::{bail, Context, Result}; 14use anyhow::{bail, Context, Result};
@@ -35,7 +35,7 @@ pub enum ProjectWorkspace {
35/// `PackageRoot` describes a package root folder. 35/// `PackageRoot` describes a package root folder.
36/// Which may be an external dependency, or a member of 36/// Which may be an external dependency, or a member of
37/// the current workspace. 37/// the current workspace.
38#[derive(Clone)] 38#[derive(Debug, Clone)]
39pub struct PackageRoot { 39pub struct PackageRoot {
40 /// Path to the root folder 40 /// Path to the root folder
41 path: PathBuf, 41 path: PathBuf,
@@ -88,46 +88,28 @@ impl ProjectRoot {
88 } 88 }
89 89
90 pub fn discover(path: &Path) -> io::Result<Vec<ProjectRoot>> { 90 pub fn discover(path: &Path) -> io::Result<Vec<ProjectRoot>> {
91 if let Some(project_json) = find_rust_project_json(path) { 91 if let Some(project_json) = find_in_parent_dirs(path, "rust-project.json") {
92 return Ok(vec![ProjectRoot::ProjectJson(project_json)]); 92 return Ok(vec![ProjectRoot::ProjectJson(project_json)]);
93 } 93 }
94 return find_cargo_toml(path) 94 return find_cargo_toml(path)
95 .map(|paths| paths.into_iter().map(ProjectRoot::CargoToml).collect()); 95 .map(|paths| paths.into_iter().map(ProjectRoot::CargoToml).collect());
96 96
97 fn find_rust_project_json(path: &Path) -> Option<PathBuf> {
98 if path.ends_with("rust-project.json") {
99 return Some(path.to_path_buf());
100 }
101
102 let mut curr = Some(path);
103 while let Some(path) = curr {
104 let candidate = path.join("rust-project.json");
105 if candidate.exists() {
106 return Some(candidate);
107 }
108 curr = path.parent();
109 }
110
111 None
112 }
113
114 fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> { 97 fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> {
115 if path.ends_with("Cargo.toml") { 98 match find_in_parent_dirs(path, "Cargo.toml") {
116 return Ok(vec![path.to_path_buf()]); 99 Some(it) => Ok(vec![it]),
100 None => Ok(find_cargo_toml_in_child_dir(read_dir(path)?)),
117 } 101 }
102 }
118 103
119 if let Some(p) = find_cargo_toml_in_parent_dir(path) { 104 fn find_in_parent_dirs(path: &Path, target_file_name: &str) -> Option<PathBuf> {
120 return Ok(vec![p]); 105 if path.ends_with(target_file_name) {
106 return Some(path.to_owned());
121 } 107 }
122 108
123 let entities = read_dir(path)?;
124 Ok(find_cargo_toml_in_child_dir(entities))
125 }
126
127 fn find_cargo_toml_in_parent_dir(path: &Path) -> Option<PathBuf> {
128 let mut curr = Some(path); 109 let mut curr = Some(path);
110
129 while let Some(path) = curr { 111 while let Some(path) = curr {
130 let candidate = path.join("Cargo.toml"); 112 let candidate = path.join(target_file_name);
131 if candidate.exists() { 113 if candidate.exists() {
132 return Some(candidate); 114 return Some(candidate);
133 } 115 }
@@ -139,14 +121,11 @@ impl ProjectRoot {
139 121
140 fn find_cargo_toml_in_child_dir(entities: ReadDir) -> Vec<PathBuf> { 122 fn find_cargo_toml_in_child_dir(entities: ReadDir) -> Vec<PathBuf> {
141 // Only one level down to avoid cycles the easy way and stop a runaway scan with large projects 123 // Only one level down to avoid cycles the easy way and stop a runaway scan with large projects
142 let mut valid_canditates = vec![]; 124 entities
143 for entity in entities.filter_map(Result::ok) { 125 .filter_map(Result::ok)
144 let candidate = entity.path().join("Cargo.toml"); 126 .map(|it| it.path().join("Cargo.toml"))
145 if candidate.exists() { 127 .filter(|it| it.exists())
146 valid_canditates.push(candidate) 128 .collect()
147 }
148 }
149 valid_canditates
150 } 129 }
151 } 130 }
152} 131}
@@ -398,7 +377,18 @@ impl ProjectWorkspace {
398 let edition = cargo[pkg].edition; 377 let edition = cargo[pkg].edition;
399 let cfg_options = { 378 let cfg_options = {
400 let mut opts = default_cfg_options.clone(); 379 let mut opts = default_cfg_options.clone();
401 opts.insert_features(cargo[pkg].features.iter().map(Into::into)); 380 for feature in cargo[pkg].features.iter() {
381 opts.insert_key_value("feature".into(), feature.into());
382 }
383 for cfg in cargo[pkg].cfgs.iter() {
384 match cfg.find('=') {
385 Some(split) => opts.insert_key_value(
386 cfg[..split].into(),
387 cfg[split + 1..].trim_matches('"').into(),
388 ),
389 None => opts.insert_atom(cfg.into()),
390 };
391 }
402 opts 392 opts
403 }; 393 };
404 let mut env = Env::default(); 394 let mut env = Env::default();
@@ -543,7 +533,7 @@ impl ProjectWorkspace {
543 } 533 }
544} 534}
545 535
546pub fn get_rustc_cfg_options() -> CfgOptions { 536pub fn get_rustc_cfg_options(target: Option<&String>) -> CfgOptions {
547 let mut cfg_options = CfgOptions::default(); 537 let mut cfg_options = CfgOptions::default();
548 538
549 // Some nightly-only cfgs, which are required for stdlib 539 // Some nightly-only cfgs, which are required for stdlib
@@ -556,23 +546,18 @@ pub fn get_rustc_cfg_options() -> CfgOptions {
556 } 546 }
557 } 547 }
558 548
559 match (|| -> Result<String> { 549 let rustc_cfgs = || -> Result<String> {
560 // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. 550 // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here.
561 let output = Command::new("rustc") 551 let mut cmd = Command::new(ra_toolchain::rustc());
562 .args(&["--print", "cfg", "-O"]) 552 cmd.args(&["--print", "cfg", "-O"]);
563 .output() 553 if let Some(target) = target {
564 .context("Failed to get output from rustc --print cfg -O")?; 554 cmd.args(&["--target", target.as_str()]);
565 if !output.status.success() {
566 bail!(
567 "rustc --print cfg -O exited with exit code ({})",
568 output
569 .status
570 .code()
571 .map_or(String::from("no exit code"), |code| format!("{}", code))
572 );
573 } 555 }
556 let output = output(cmd)?;
574 Ok(String::from_utf8(output.stdout)?) 557 Ok(String::from_utf8(output.stdout)?)
575 })() { 558 }();
559
560 match rustc_cfgs {
576 Ok(rustc_cfgs) => { 561 Ok(rustc_cfgs) => {
577 for line in rustc_cfgs.lines() { 562 for line in rustc_cfgs.lines() {
578 match line.find('=') { 563 match line.find('=') {
@@ -585,8 +570,21 @@ pub fn get_rustc_cfg_options() -> CfgOptions {
585 } 570 }
586 } 571 }
587 } 572 }
588 Err(e) => log::error!("failed to get rustc cfgs: {}", e), 573 Err(e) => log::error!("failed to get rustc cfgs: {:#}", e),
589 } 574 }
590 575
591 cfg_options 576 cfg_options
592} 577}
578
579fn output(mut cmd: Command) -> Result<Output> {
580 let output = cmd.output().with_context(|| format!("{:?} failed", cmd))?;
581 if !output.status.success() {
582 match String::from_utf8(output.stderr) {
583 Ok(stderr) if !stderr.is_empty() => {
584 bail!("{:?} failed, {}\nstderr:\n{}", cmd, output.status, stderr)
585 }
586 _ => bail!("{:?} failed, {}", cmd, output.status),
587 }
588 }
589 Ok(output)
590}
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index 55ff5ad80..a8a196e64 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -1,14 +1,16 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use anyhow::{bail, Context, Result};
4use std::{ 3use std::{
5 env, ops, 4 env, ops,
6 path::{Path, PathBuf}, 5 path::{Path, PathBuf},
7 process::{Command, Output}, 6 process::Command,
8}; 7};
9 8
9use anyhow::{bail, Result};
10use ra_arena::{Arena, Idx}; 10use ra_arena::{Arena, Idx};
11 11
12use crate::output;
13
12#[derive(Default, Debug, Clone)] 14#[derive(Default, Debug, Clone)]
13pub struct Sysroot { 15pub struct Sysroot {
14 crates: Arena<SysrootCrateData>, 16 crates: Arena<SysrootCrateData>,
@@ -84,43 +86,22 @@ impl Sysroot {
84 } 86 }
85} 87}
86 88
87fn create_command_text(program: &str, args: &[&str]) -> String {
88 format!("{} {}", program, args.join(" "))
89}
90
91fn run_command_in_cargo_dir(cargo_toml: &Path, program: &str, args: &[&str]) -> Result<Output> {
92 let output = Command::new(program)
93 .current_dir(cargo_toml.parent().unwrap())
94 .args(args)
95 .output()
96 .context(format!("{} failed", create_command_text(program, args)))?;
97 if !output.status.success() {
98 match output.status.code() {
99 Some(code) => bail!(
100 "failed to run the command: '{}' exited with code {}",
101 create_command_text(program, args),
102 code
103 ),
104 None => bail!(
105 "failed to run the command: '{}' terminated by signal",
106 create_command_text(program, args)
107 ),
108 };
109 }
110 Ok(output)
111}
112
113fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> { 89fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
114 if let Ok(path) = env::var("RUST_SRC_PATH") { 90 if let Ok(path) = env::var("RUST_SRC_PATH") {
115 return Ok(path.into()); 91 return Ok(path.into());
116 } 92 }
117 let rustc_output = run_command_in_cargo_dir(cargo_toml, "rustc", &["--print", "sysroot"])?; 93 let current_dir = cargo_toml.parent().unwrap();
94 let mut rustc = Command::new(ra_toolchain::rustc());
95 rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
96 let rustc_output = output(rustc)?;
118 let stdout = String::from_utf8(rustc_output.stdout)?; 97 let stdout = String::from_utf8(rustc_output.stdout)?;
119 let sysroot_path = Path::new(stdout.trim()); 98 let sysroot_path = Path::new(stdout.trim());
120 let src_path = sysroot_path.join("lib/rustlib/src/rust/src"); 99 let src_path = sysroot_path.join("lib/rustlib/src/rust/src");
121 100
122 if !src_path.exists() { 101 if !src_path.exists() {
123 run_command_in_cargo_dir(cargo_toml, "rustup", &["component", "add", "rust-src"])?; 102 let mut rustup = Command::new(ra_toolchain::rustup());
103 rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]);
104 let _output = output(rustup)?;
124 } 105 }
125 if !src_path.exists() { 106 if !src_path.exists() {
126 bail!( 107 bail!(
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index 2a8dac757..664894d1f 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -266,6 +266,15 @@ impl<'a> SyntaxRewriter<'a> {
266 let replacement = Replacement::Single(with.clone().into()); 266 let replacement = Replacement::Single(with.clone().into());
267 self.replacements.insert(what, replacement); 267 self.replacements.insert(what, replacement);
268 } 268 }
269 pub fn replace_with_many<T: Clone + Into<SyntaxElement>>(
270 &mut self,
271 what: &T,
272 with: Vec<SyntaxElement>,
273 ) {
274 let what = what.clone().into();
275 let replacement = Replacement::Many(with);
276 self.replacements.insert(what, replacement);
277 }
269 pub fn replace_ast<T: AstNode>(&mut self, what: &T, with: &T) { 278 pub fn replace_ast<T: AstNode>(&mut self, what: &T, with: &T) {
270 self.replace(what.syntax(), with.syntax()) 279 self.replace(what.syntax(), with.syntax())
271 } 280 }
@@ -302,31 +311,41 @@ impl<'a> SyntaxRewriter<'a> {
302 311
303 fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode { 312 fn rewrite_children(&self, node: &SyntaxNode) -> SyntaxNode {
304 // FIXME: this could be made much faster. 313 // FIXME: this could be made much faster.
305 let new_children = 314 let mut new_children = Vec::new();
306 node.children_with_tokens().flat_map(|it| self.rewrite_self(&it)).collect::<Vec<_>>(); 315 for child in node.children_with_tokens() {
316 self.rewrite_self(&mut new_children, &child);
317 }
307 with_children(node, new_children) 318 with_children(node, new_children)
308 } 319 }
309 320
310 fn rewrite_self( 321 fn rewrite_self(
311 &self, 322 &self,
323 acc: &mut Vec<NodeOrToken<rowan::GreenNode, rowan::GreenToken>>,
312 element: &SyntaxElement, 324 element: &SyntaxElement,
313 ) -> Option<NodeOrToken<rowan::GreenNode, rowan::GreenToken>> { 325 ) {
314 if let Some(replacement) = self.replacement(&element) { 326 if let Some(replacement) = self.replacement(&element) {
315 return match replacement { 327 match replacement {
316 Replacement::Single(NodeOrToken::Node(it)) => { 328 Replacement::Single(NodeOrToken::Node(it)) => {
317 Some(NodeOrToken::Node(it.green().clone())) 329 acc.push(NodeOrToken::Node(it.green().clone()))
318 } 330 }
319 Replacement::Single(NodeOrToken::Token(it)) => { 331 Replacement::Single(NodeOrToken::Token(it)) => {
320 Some(NodeOrToken::Token(it.green().clone())) 332 acc.push(NodeOrToken::Token(it.green().clone()))
321 } 333 }
322 Replacement::Delete => None, 334 Replacement::Many(replacements) => {
335 acc.extend(replacements.iter().map(|it| match it {
336 NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()),
337 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
338 }))
339 }
340 Replacement::Delete => (),
323 }; 341 };
342 return;
324 } 343 }
325 let res = match element { 344 let res = match element {
326 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()), 345 NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()),
327 NodeOrToken::Node(it) => NodeOrToken::Node(self.rewrite_children(it).green().clone()), 346 NodeOrToken::Node(it) => NodeOrToken::Node(self.rewrite_children(it).green().clone()),
328 }; 347 };
329 Some(res) 348 acc.push(res)
330 } 349 }
331} 350}
332 351
@@ -341,6 +360,7 @@ impl ops::AddAssign for SyntaxRewriter<'_> {
341enum Replacement { 360enum Replacement {
342 Delete, 361 Delete,
343 Single(SyntaxElement), 362 Single(SyntaxElement),
363 Many(Vec<SyntaxElement>),
344} 364}
345 365
346fn with_children( 366fn with_children(
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 521ca8ab8..1876afe95 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -16,9 +16,7 @@ use crate::{
16}; 16};
17 17
18pub use self::{ 18pub use self::{
19 expr_extensions::{ 19 expr_extensions::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp},
20 ArrayExprKind, BinOp, BlockModifier, ElseBranch, LiteralKind, PrefixOp, RangeOp,
21 },
22 extensions::{ 20 extensions::{
23 AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents, 21 AttrKind, FieldKind, NameOrNameRef, PathSegmentKind, SelfParamKind, SlicePatComponents,
24 StructKind, TypeBoundKind, VisibilityKind, 22 StructKind, TypeBoundKind, VisibilityKind,
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs
index 26e4576ff..29eb3fcb9 100644
--- a/crates/ra_syntax/src/ast/edit.rs
+++ b/crates/ra_syntax/src/ast/edit.rs
@@ -1,7 +1,10 @@
1//! This module contains functions for editing syntax trees. As the trees are 1//! This module contains functions for editing syntax trees. As the trees are
2//! immutable, all function here return a fresh copy of the tree, instead of 2//! immutable, all function here return a fresh copy of the tree, instead of
3//! doing an in-place modification. 3//! doing an in-place modification.
4use std::{iter, ops::RangeInclusive}; 4use std::{
5 fmt, iter,
6 ops::{self, RangeInclusive},
7};
5 8
6use arrayvec::ArrayVec; 9use arrayvec::ArrayVec;
7 10
@@ -28,7 +31,7 @@ impl ast::BinExpr {
28 31
29impl ast::FnDef { 32impl ast::FnDef {
30 #[must_use] 33 #[must_use]
31 pub fn with_body(&self, body: ast::Block) -> ast::FnDef { 34 pub fn with_body(&self, body: ast::BlockExpr) -> ast::FnDef {
32 let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); 35 let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
33 let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { 36 let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
34 old_body.syntax().clone().into() 37 old_body.syntax().clone().into()
@@ -79,7 +82,7 @@ where
79 82
80impl ast::ItemList { 83impl ast::ItemList {
81 #[must_use] 84 #[must_use]
82 pub fn append_items(&self, items: impl IntoIterator<Item = ast::ImplItem>) -> ast::ItemList { 85 pub fn append_items(&self, items: impl IntoIterator<Item = ast::AssocItem>) -> ast::ItemList {
83 let mut res = self.clone(); 86 let mut res = self.clone();
84 if !self.syntax().text().contains_char('\n') { 87 if !self.syntax().text().contains_char('\n') {
85 res = make_multiline(res); 88 res = make_multiline(res);
@@ -89,8 +92,8 @@ impl ast::ItemList {
89 } 92 }
90 93
91 #[must_use] 94 #[must_use]
92 pub fn append_item(&self, item: ast::ImplItem) -> ast::ItemList { 95 pub fn append_item(&self, item: ast::AssocItem) -> ast::ItemList {
93 let (indent, position) = match self.impl_items().last() { 96 let (indent, position) = match self.assoc_items().last() {
94 Some(it) => ( 97 Some(it) => (
95 leading_indent(it.syntax()).unwrap_or_default().to_string(), 98 leading_indent(it.syntax()).unwrap_or_default().to_string(),
96 InsertPosition::After(it.syntax().clone().into()), 99 InsertPosition::After(it.syntax().clone().into()),
@@ -437,6 +440,28 @@ impl From<u8> for IndentLevel {
437 } 440 }
438} 441}
439 442
443impl fmt::Display for IndentLevel {
444 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
445 let spaces = " ";
446 let buf;
447 let len = self.0 as usize * 4;
448 let indent = if len <= spaces.len() {
449 &spaces[..len]
450 } else {
451 buf = iter::repeat(' ').take(len).collect::<String>();
452 &buf
453 };
454 fmt::Display::fmt(indent, f)
455 }
456}
457
458impl ops::Add<u8> for IndentLevel {
459 type Output = IndentLevel;
460 fn add(self, rhs: u8) -> IndentLevel {
461 IndentLevel(self.0 + rhs)
462 }
463}
464
440impl IndentLevel { 465impl IndentLevel {
441 pub fn from_node(node: &SyntaxNode) -> IndentLevel { 466 pub fn from_node(node: &SyntaxNode) -> IndentLevel {
442 let first_token = match node.first_token() { 467 let first_token = match node.first_token() {
@@ -453,11 +478,15 @@ impl IndentLevel {
453 IndentLevel(0) 478 IndentLevel(0)
454 } 479 }
455 480
456 pub fn increase_indent<N: AstNode>(self, node: N) -> N { 481 /// XXX: this intentionally doesn't change the indent of the very first token.
457 N::cast(self._increase_indent(node.syntax().clone())).unwrap() 482 /// Ie, in something like
458 } 483 /// ```
459 484 /// fn foo() {
460 fn _increase_indent(self, node: SyntaxNode) -> SyntaxNode { 485 /// 92
486 /// }
487 /// ```
488 /// if you indent the block, the `{` token would stay put.
489 fn increase_indent(self, node: SyntaxNode) -> SyntaxNode {
461 let mut rewriter = SyntaxRewriter::default(); 490 let mut rewriter = SyntaxRewriter::default();
462 node.descendants_with_tokens() 491 node.descendants_with_tokens()
463 .filter_map(|el| el.into_token()) 492 .filter_map(|el| el.into_token())
@@ -467,22 +496,13 @@ impl IndentLevel {
467 text.contains('\n') 496 text.contains('\n')
468 }) 497 })
469 .for_each(|ws| { 498 .for_each(|ws| {
470 let new_ws = make::tokens::whitespace(&format!( 499 let new_ws = make::tokens::whitespace(&format!("{}{}", ws.syntax(), self,));
471 "{}{:width$}",
472 ws.syntax().text(),
473 "",
474 width = self.0 as usize * 4
475 ));
476 rewriter.replace(ws.syntax(), &new_ws) 500 rewriter.replace(ws.syntax(), &new_ws)
477 }); 501 });
478 rewriter.rewrite(&node) 502 rewriter.rewrite(&node)
479 } 503 }
480 504
481 pub fn decrease_indent<N: AstNode>(self, node: N) -> N { 505 fn decrease_indent(self, node: SyntaxNode) -> SyntaxNode {
482 N::cast(self._decrease_indent(node.syntax().clone())).unwrap()
483 }
484
485 fn _decrease_indent(self, node: SyntaxNode) -> SyntaxNode {
486 let mut rewriter = SyntaxRewriter::default(); 506 let mut rewriter = SyntaxRewriter::default();
487 node.descendants_with_tokens() 507 node.descendants_with_tokens()
488 .filter_map(|el| el.into_token()) 508 .filter_map(|el| el.into_token())
@@ -493,7 +513,7 @@ impl IndentLevel {
493 }) 513 })
494 .for_each(|ws| { 514 .for_each(|ws| {
495 let new_ws = make::tokens::whitespace( 515 let new_ws = make::tokens::whitespace(
496 &ws.syntax().text().replace(&format!("\n{:1$}", "", self.0 as usize * 4), "\n"), 516 &ws.syntax().text().replace(&format!("\n{}", self), "\n"),
497 ); 517 );
498 rewriter.replace(ws.syntax(), &new_ws) 518 rewriter.replace(ws.syntax(), &new_ws)
499 }); 519 });
@@ -521,7 +541,7 @@ fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
521 iter::successors(Some(token), |token| token.prev_token()) 541 iter::successors(Some(token), |token| token.prev_token())
522} 542}
523 543
524pub trait AstNodeEdit: AstNode + Sized { 544pub trait AstNodeEdit: AstNode + Clone + Sized {
525 #[must_use] 545 #[must_use]
526 fn insert_children( 546 fn insert_children(
527 &self, 547 &self,
@@ -558,9 +578,17 @@ pub trait AstNodeEdit: AstNode + Sized {
558 } 578 }
559 rewriter.rewrite_ast(self) 579 rewriter.rewrite_ast(self)
560 } 580 }
581 #[must_use]
582 fn indent(&self, indent: IndentLevel) -> Self {
583 Self::cast(indent.increase_indent(self.syntax().clone())).unwrap()
584 }
585 #[must_use]
586 fn dedent(&self, indent: IndentLevel) -> Self {
587 Self::cast(indent.decrease_indent(self.syntax().clone())).unwrap()
588 }
561} 589}
562 590
563impl<N: AstNode> AstNodeEdit for N {} 591impl<N: AstNode + Clone> AstNodeEdit for N {}
564 592
565fn single_node(element: impl Into<SyntaxElement>) -> RangeInclusive<SyntaxElement> { 593fn single_node(element: impl Into<SyntaxElement>) -> RangeInclusive<SyntaxElement> {
566 let element = element.into(); 594 let element = element.into();
@@ -580,7 +608,7 @@ fn test_increase_indent() {
580 _ => (), 608 _ => (),
581}" 609}"
582 ); 610 );
583 let indented = IndentLevel(2).increase_indent(arm_list); 611 let indented = arm_list.indent(IndentLevel(2));
584 assert_eq!( 612 assert_eq!(
585 indented.syntax().to_string(), 613 indented.syntax().to_string(),
586 "{ 614 "{
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 352c0d2c5..7771d6759 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -16,7 +16,7 @@ impl ast::Expr {
16 | ast::Expr::WhileExpr(_) 16 | ast::Expr::WhileExpr(_)
17 | ast::Expr::BlockExpr(_) 17 | ast::Expr::BlockExpr(_)
18 | ast::Expr::MatchExpr(_) 18 | ast::Expr::MatchExpr(_)
19 | ast::Expr::TryExpr(_) => true, 19 | ast::Expr::EffectExpr(_) => true,
20 _ => false, 20 _ => false,
21 } 21 }
22 } 22 }
@@ -43,7 +43,7 @@ impl ast::IfExpr {
43 Some(res) 43 Some(res)
44 } 44 }
45 45
46 fn blocks(&self) -> AstChildren<ast::BlockExpr> { 46 pub fn blocks(&self) -> AstChildren<ast::BlockExpr> {
47 support::children(self.syntax()) 47 support::children(self.syntax())
48 } 48 }
49} 49}
@@ -359,22 +359,34 @@ impl ast::Literal {
359 } 359 }
360} 360}
361 361
362pub enum BlockModifier { 362#[derive(Debug, Clone, PartialEq, Eq)]
363pub enum Effect {
363 Async(SyntaxToken), 364 Async(SyntaxToken),
364 Unsafe(SyntaxToken), 365 Unsafe(SyntaxToken),
366 Try(SyntaxToken),
367 // Very much not an effect, but we stuff it into this node anyway
368 Label(ast::Label),
365} 369}
366 370
367impl ast::BlockExpr { 371impl ast::EffectExpr {
368 pub fn modifier(&self) -> Option<BlockModifier> { 372 pub fn effect(&self) -> Effect {
369 if let Some(token) = self.async_token() { 373 if let Some(token) = self.async_token() {
370 return Some(BlockModifier::Async(token)); 374 return Effect::Async(token);
371 } 375 }
372 if let Some(token) = self.unsafe_token() { 376 if let Some(token) = self.unsafe_token() {
373 return Some(BlockModifier::Unsafe(token)); 377 return Effect::Unsafe(token);
378 }
379 if let Some(token) = self.try_token() {
380 return Effect::Try(token);
381 }
382 if let Some(label) = self.label() {
383 return Effect::Label(label);
374 } 384 }
375 None 385 unreachable!("ast::EffectExpr without Effect")
376 } 386 }
387}
377 388
389impl ast::BlockExpr {
378 /// false if the block is an intrinsic part of the syntax and can't be 390 /// false if the block is an intrinsic part of the syntax and can't be
379 /// replaced with arbitrary expression. 391 /// replaced with arbitrary expression.
380 /// 392 ///
@@ -383,15 +395,12 @@ impl ast::BlockExpr {
383 /// const FOO: () = { stand_alone }; 395 /// const FOO: () = { stand_alone };
384 /// ``` 396 /// ```
385 pub fn is_standalone(&self) -> bool { 397 pub fn is_standalone(&self) -> bool {
386 if self.modifier().is_some() {
387 return false;
388 }
389 let parent = match self.syntax().parent() { 398 let parent = match self.syntax().parent() {
390 Some(it) => it, 399 Some(it) => it,
391 None => return true, 400 None => return true,
392 }; 401 };
393 match parent.kind() { 402 match parent.kind() {
394 FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR => false, 403 FN_DEF | IF_EXPR | WHILE_EXPR | LOOP_EXPR | EFFECT_EXPR => false,
395 _ => true, 404 _ => true,
396 } 405 }
397 } 406 }
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 45e3dd2d3..98c38d009 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -423,6 +423,10 @@ impl ast::MacroCall {
423 None 423 None
424 } 424 }
425 } 425 }
426
427 pub fn is_bang(&self) -> bool {
428 self.is_macro_rules().is_none()
429 }
426} 430}
427 431
428impl ast::LifetimeParam { 432impl ast::LifetimeParam {
@@ -463,7 +467,7 @@ impl ast::TokenTree {
463 467
464 pub fn right_delimiter_token(&self) -> Option<SyntaxToken> { 468 pub fn right_delimiter_token(&self) -> Option<SyntaxToken> {
465 self.syntax().last_child_or_token()?.into_token().filter(|it| match it.kind() { 469 self.syntax().last_child_or_token()?.into_token().filter(|it| match it.kind() {
466 T!['{'] | T!['('] | T!['['] => true, 470 T!['}'] | T![')'] | T![']'] => true,
467 _ => false, 471 _ => false,
468 }) 472 })
469 } 473 }
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs
index 3f16592b6..cf6067e57 100644
--- a/crates/ra_syntax/src/ast/generated/nodes.rs
+++ b/crates/ra_syntax/src/ast/generated/nodes.rs
@@ -5,17 +5,41 @@ use crate::{
5 SyntaxKind::{self, *}, 5 SyntaxKind::{self, *},
6 SyntaxNode, SyntaxToken, T, 6 SyntaxNode, SyntaxToken, T,
7}; 7};
8 8/// The entire Rust source file. Includes all top-level inner attributes and module items.
9///
10/// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html)
9#[derive(Debug, Clone, PartialEq, Eq, Hash)] 11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct SourceFile { 12pub struct SourceFile {
11 pub(crate) syntax: SyntaxNode, 13 pub(crate) syntax: SyntaxNode,
12} 14}
13impl ast::ModuleItemOwner for SourceFile {} 15impl ast::ModuleItemOwner for SourceFile {}
14impl ast::AttrsOwner for SourceFile {} 16impl ast::AttrsOwner for SourceFile {}
17impl ast::DocCommentsOwner for SourceFile {}
15impl SourceFile { 18impl SourceFile {
16 pub fn modules(&self) -> AstChildren<Module> { support::children(&self.syntax) } 19 pub fn modules(&self) -> AstChildren<Module> { support::children(&self.syntax) }
17} 20}
18 21/// Function definition either with body or not.
22/// Includes all of its attributes and doc comments.
23///
24/// ```
25/// ❰
26/// /// Docs
27/// #[attr]
28/// pub extern "C" fn foo<T>(#[attr] Patern {p}: Pattern) -> u32
29/// where
30/// T: Debug
31/// {
32/// 42
33/// }
34/// ❱
35///
36/// extern "C" {
37/// ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱
38/// }
39/// ```
40///
41/// - [Reference](https://doc.rust-lang.org/reference/items/functions.html)
42/// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions)
19#[derive(Debug, Clone, PartialEq, Eq, Hash)] 43#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub struct FnDef { 44pub struct FnDef {
21 pub(crate) syntax: SyntaxNode, 45 pub(crate) syntax: SyntaxNode,
@@ -37,7 +61,13 @@ impl FnDef {
37 pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) } 61 pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
38 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 62 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
39} 63}
40 64/// Return type annotation.
65///
66/// ```
67/// fn foo(a: u32) ❰ -> Option<u32> ❱ { Some(a) }
68/// ```
69///
70/// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
41#[derive(Debug, Clone, PartialEq, Eq, Hash)] 71#[derive(Debug, Clone, PartialEq, Eq, Hash)]
42pub struct RetType { 72pub struct RetType {
43 pub(crate) syntax: SyntaxNode, 73 pub(crate) syntax: SyntaxNode,
@@ -46,7 +76,26 @@ impl RetType {
46 pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) } 76 pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) }
47 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 77 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
48} 78}
49 79/// Struct definition.
80/// Includes all of its attributes and doc comments.
81///
82/// ```
83/// ❰
84/// /// Docs
85/// #[attr]
86/// struct Foo<T> where T: Debug {
87/// /// Docs
88/// #[attr]
89/// pub a: u32,
90/// b: T,
91/// }
92/// ❱
93///
94/// ❰ struct Foo; ❱
95/// ❰ struct Foo<T>(#[attr] T) where T: Debug; ❱
96/// ```
97///
98/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
50#[derive(Debug, Clone, PartialEq, Eq, Hash)] 99#[derive(Debug, Clone, PartialEq, Eq, Hash)]
51pub struct StructDef { 100pub struct StructDef {
52 pub(crate) syntax: SyntaxNode, 101 pub(crate) syntax: SyntaxNode,
@@ -61,7 +110,23 @@ impl StructDef {
61 pub fn field_def_list(&self) -> Option<FieldDefList> { support::child(&self.syntax) } 110 pub fn field_def_list(&self) -> Option<FieldDefList> { support::child(&self.syntax) }
62 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 111 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
63} 112}
64 113/// Union definition.
114/// Includes all of its attributes and doc comments.
115///
116/// ```
117/// ❰
118/// /// Docs
119/// #[attr]
120/// pub union Foo<T> where T: Debug {
121/// /// Docs
122/// #[attr]
123/// a: T,
124/// b: u32,
125/// }
126/// ❱
127/// ```
128///
129/// [Reference](https://doc.rust-lang.org/reference/items/unions.html)
65#[derive(Debug, Clone, PartialEq, Eq, Hash)] 130#[derive(Debug, Clone, PartialEq, Eq, Hash)]
66pub struct UnionDef { 131pub struct UnionDef {
67 pub(crate) syntax: SyntaxNode, 132 pub(crate) syntax: SyntaxNode,
@@ -77,7 +142,19 @@ impl UnionDef {
77 support::child(&self.syntax) 142 support::child(&self.syntax)
78 } 143 }
79} 144}
80 145/// Record field definition list including enclosing curly braces.
146///
147/// ```
148/// struct Foo // same for union
149/// ❰
150/// {
151/// a: u32,
152/// b: bool,
153/// }
154/// ❱
155/// ```
156///
157/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
81#[derive(Debug, Clone, PartialEq, Eq, Hash)] 158#[derive(Debug, Clone, PartialEq, Eq, Hash)]
82pub struct RecordFieldDefList { 159pub struct RecordFieldDefList {
83 pub(crate) syntax: SyntaxNode, 160 pub(crate) syntax: SyntaxNode,
@@ -87,7 +164,22 @@ impl RecordFieldDefList {
87 pub fn fields(&self) -> AstChildren<RecordFieldDef> { support::children(&self.syntax) } 164 pub fn fields(&self) -> AstChildren<RecordFieldDef> { support::children(&self.syntax) }
88 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 165 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
89} 166}
90 167/// Record field definition including its attributes and doc comments.
168///
169/// ` ``
170/// same for union
171/// struct Foo {
172/// ❰
173/// /// Docs
174/// #[attr]
175/// pub a: u32
176/// ❱
177///
178/// ❰ b: bool ❱
179/// }
180/// ```
181///
182/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
91#[derive(Debug, Clone, PartialEq, Eq, Hash)] 183#[derive(Debug, Clone, PartialEq, Eq, Hash)]
92pub struct RecordFieldDef { 184pub struct RecordFieldDef {
93 pub(crate) syntax: SyntaxNode, 185 pub(crate) syntax: SyntaxNode,
@@ -98,7 +190,13 @@ impl ast::AttrsOwner for RecordFieldDef {}
98impl ast::DocCommentsOwner for RecordFieldDef {} 190impl ast::DocCommentsOwner for RecordFieldDef {}
99impl ast::TypeAscriptionOwner for RecordFieldDef {} 191impl ast::TypeAscriptionOwner for RecordFieldDef {}
100impl RecordFieldDef {} 192impl RecordFieldDef {}
101 193/// Tuple field definition list including enclosing parens.
194///
195/// ```
196/// struct Foo ❰ (u32, String, Vec<u32>) ❱;
197/// ```
198///
199/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
102#[derive(Debug, Clone, PartialEq, Eq, Hash)] 200#[derive(Debug, Clone, PartialEq, Eq, Hash)]
103pub struct TupleFieldDefList { 201pub struct TupleFieldDefList {
104 pub(crate) syntax: SyntaxNode, 202 pub(crate) syntax: SyntaxNode,
@@ -108,7 +206,13 @@ impl TupleFieldDefList {
108 pub fn fields(&self) -> AstChildren<TupleFieldDef> { support::children(&self.syntax) } 206 pub fn fields(&self) -> AstChildren<TupleFieldDef> { support::children(&self.syntax) }
109 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 207 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
110} 208}
111 209/// Tuple field definition including its attributes.
210///
211/// ```
212/// struct Foo(❰ #[attr] u32 ❱);
213/// ```
214///
215/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
112#[derive(Debug, Clone, PartialEq, Eq, Hash)] 216#[derive(Debug, Clone, PartialEq, Eq, Hash)]
113pub struct TupleFieldDef { 217pub struct TupleFieldDef {
114 pub(crate) syntax: SyntaxNode, 218 pub(crate) syntax: SyntaxNode,
@@ -118,7 +222,29 @@ impl ast::AttrsOwner for TupleFieldDef {}
118impl TupleFieldDef { 222impl TupleFieldDef {
119 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 223 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
120} 224}
121 225/// Enum definition.
226/// Includes all of its attributes and doc comments.
227///
228/// ```
229/// ❰
230/// /// Docs
231/// #[attr]
232/// pub enum Foo<T> where T: Debug {
233/// /// Docs
234/// #[attr]
235/// Bar,
236/// Baz(#[attr] u32),
237/// Bruh {
238/// a: u32,
239/// /// Docs
240/// #[attr]
241/// b: T,
242/// }
243/// }
244/// ❱
245/// ```
246///
247/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
122#[derive(Debug, Clone, PartialEq, Eq, Hash)] 248#[derive(Debug, Clone, PartialEq, Eq, Hash)]
123pub struct EnumDef { 249pub struct EnumDef {
124 pub(crate) syntax: SyntaxNode, 250 pub(crate) syntax: SyntaxNode,
@@ -132,7 +258,22 @@ impl EnumDef {
132 pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) } 258 pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
133 pub fn variant_list(&self) -> Option<EnumVariantList> { support::child(&self.syntax) } 259 pub fn variant_list(&self) -> Option<EnumVariantList> { support::child(&self.syntax) }
134} 260}
135 261/// Enum variant definition list including enclosing curly braces.
262///
263/// ```
264/// enum Foo
265/// ❰
266/// {
267/// Bar,
268/// Baz(u32),
269/// Bruh {
270/// a: u32
271/// }
272/// }
273/// ❱
274/// ```
275///
276/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
136#[derive(Debug, Clone, PartialEq, Eq, Hash)] 277#[derive(Debug, Clone, PartialEq, Eq, Hash)]
137pub struct EnumVariantList { 278pub struct EnumVariantList {
138 pub(crate) syntax: SyntaxNode, 279 pub(crate) syntax: SyntaxNode,
@@ -142,7 +283,21 @@ impl EnumVariantList {
142 pub fn variants(&self) -> AstChildren<EnumVariant> { support::children(&self.syntax) } 283 pub fn variants(&self) -> AstChildren<EnumVariant> { support::children(&self.syntax) }
143 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 284 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
144} 285}
145 286/// Enum variant definition including its attributes and discriminant value definition.
287///
288/// ```
289/// enum Foo {
290/// ❰
291/// /// Docs
292/// #[attr]
293/// Bar
294/// ❱
295///
296/// // same for tuple and record variants
297/// }
298/// ```
299///
300/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
146#[derive(Debug, Clone, PartialEq, Eq, Hash)] 301#[derive(Debug, Clone, PartialEq, Eq, Hash)]
147pub struct EnumVariant { 302pub struct EnumVariant {
148 pub(crate) syntax: SyntaxNode, 303 pub(crate) syntax: SyntaxNode,
@@ -156,7 +311,20 @@ impl EnumVariant {
156 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } 311 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
157 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 312 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
158} 313}
159 314/// Trait definition.
315/// Includes all of its attributes and doc comments.
316///
317/// ```
318/// ❰
319/// /// Docs
320/// #[attr]
321/// pub unsafe trait Foo<T>: Debug where T: Debug {
322/// // ...
323/// }
324/// ❱
325/// ```
326///
327/// [Reference](https://doc.rust-lang.org/reference/items/traits.html)
160#[derive(Debug, Clone, PartialEq, Eq, Hash)] 328#[derive(Debug, Clone, PartialEq, Eq, Hash)]
161pub struct TraitDef { 329pub struct TraitDef {
162 pub(crate) syntax: SyntaxNode, 330 pub(crate) syntax: SyntaxNode,
@@ -173,7 +341,27 @@ impl TraitDef {
173 pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) } 341 pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
174 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) } 342 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
175} 343}
176 344/// Module definition either with body or not.
345/// Includes all of its inner and outer attributes, module items, doc comments.
346///
347/// ```
348/// ❰
349/// /// Docs
350/// #[attr]
351/// pub mod foo;
352/// ❱
353///
354/// ❰
355/// /// Docs
356/// #[attr]
357/// pub mod bar {
358/// //! Inner docs
359/// #![inner_attr]
360/// }
361/// ❱
362/// ```
363///
364/// [Reference](https://doc.rust-lang.org/reference/items/modules.html)
177#[derive(Debug, Clone, PartialEq, Eq, Hash)] 365#[derive(Debug, Clone, PartialEq, Eq, Hash)]
178pub struct Module { 366pub struct Module {
179 pub(crate) syntax: SyntaxNode, 367 pub(crate) syntax: SyntaxNode,
@@ -187,7 +375,28 @@ impl Module {
187 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) } 375 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
188 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 376 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
189} 377}
190 378/// Item defintion list.
379/// This is used for both top-level items and impl block items.
380///
381/// ```
382/// ❰
383/// fn foo {}
384/// struct Bar;
385/// enum Baz;
386/// trait Bruh;
387/// const BRUUH: u32 = 42;
388/// ❱
389///
390/// impl Foo
391/// ❰
392/// {
393/// fn bar() {}
394/// const BAZ: u32 = 42;
395/// }
396/// ❱
397/// ```
398///
399/// [Reference](https://doc.rust-lang.org/reference/items.html)
191#[derive(Debug, Clone, PartialEq, Eq, Hash)] 400#[derive(Debug, Clone, PartialEq, Eq, Hash)]
192pub struct ItemList { 401pub struct ItemList {
193 pub(crate) syntax: SyntaxNode, 402 pub(crate) syntax: SyntaxNode,
@@ -195,10 +404,21 @@ pub struct ItemList {
195impl ast::ModuleItemOwner for ItemList {} 404impl ast::ModuleItemOwner for ItemList {}
196impl ItemList { 405impl ItemList {
197 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } 406 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
198 pub fn impl_items(&self) -> AstChildren<ImplItem> { support::children(&self.syntax) } 407 pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) }
199 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 408 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
200} 409}
201 410/// Constant variable definition.
411/// Includes all of its attributes and doc comments.
412///
413/// ```
414/// ❰
415/// /// Docs
416/// #[attr]
417/// pub const FOO: u32 = 42;
418/// ❱
419/// ```
420///
421/// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html)
202#[derive(Debug, Clone, PartialEq, Eq, Hash)] 422#[derive(Debug, Clone, PartialEq, Eq, Hash)]
203pub struct ConstDef { 423pub struct ConstDef {
204 pub(crate) syntax: SyntaxNode, 424 pub(crate) syntax: SyntaxNode,
@@ -216,7 +436,18 @@ impl ConstDef {
216 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } 436 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
217 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 437 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
218} 438}
219 439/// Static variable definition.
440/// Includes all of its attributes and doc comments.
441///
442/// ```
443/// ❰
444/// /// Docs
445/// #[attr]
446/// pub static mut FOO: u32 = 42;
447/// ❱
448/// ```
449///
450/// [Reference](https://doc.rust-lang.org/reference/items/static-items.html)
220#[derive(Debug, Clone, PartialEq, Eq, Hash)] 451#[derive(Debug, Clone, PartialEq, Eq, Hash)]
221pub struct StaticDef { 452pub struct StaticDef {
222 pub(crate) syntax: SyntaxNode, 453 pub(crate) syntax: SyntaxNode,
@@ -234,7 +465,24 @@ impl StaticDef {
234 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } 465 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
235 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 466 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
236} 467}
237 468/// Type alias definition.
469/// Includes associated type clauses with type bounds.
470///
471/// ```
472/// ❰
473/// /// Docs
474/// #[attr]
475/// pub type Foo<T> where T: Debug = T;
476/// ❱
477///
478/// trait Bar {
479/// ❰ type Baz: Debug; ❱
480/// ❰ type Bruh = String; ❱
481/// ❰ type Bruuh: Debug = u32; ❱
482/// }
483/// ```
484///
485/// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html)
238#[derive(Debug, Clone, PartialEq, Eq, Hash)] 486#[derive(Debug, Clone, PartialEq, Eq, Hash)]
239pub struct TypeAliasDef { 487pub struct TypeAliasDef {
240 pub(crate) syntax: SyntaxNode, 488 pub(crate) syntax: SyntaxNode,
@@ -252,13 +500,27 @@ impl TypeAliasDef {
252 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 500 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
253 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 501 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
254} 502}
255 503/// Inherent and trait impl definition.
504/// Includes all of its inner and outer attributes.
505///
506/// ```
507/// ❰
508/// #[attr]
509/// unsafe impl<T> const !Foo for Bar where T: Debug {
510/// #![inner_attr]
511/// // ...
512/// }
513/// ❱
514/// ```
515///
516/// [Reference](https://doc.rust-lang.org/reference/items/implementations.html)
256#[derive(Debug, Clone, PartialEq, Eq, Hash)] 517#[derive(Debug, Clone, PartialEq, Eq, Hash)]
257pub struct ImplDef { 518pub struct ImplDef {
258 pub(crate) syntax: SyntaxNode, 519 pub(crate) syntax: SyntaxNode,
259} 520}
260impl ast::TypeParamsOwner for ImplDef {} 521impl ast::TypeParamsOwner for ImplDef {}
261impl ast::AttrsOwner for ImplDef {} 522impl ast::AttrsOwner for ImplDef {}
523impl ast::DocCommentsOwner for ImplDef {}
262impl ImplDef { 524impl ImplDef {
263 pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) } 525 pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
264 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } 526 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
@@ -268,7 +530,16 @@ impl ImplDef {
268 pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } 530 pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
269 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) } 531 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
270} 532}
271 533/// Parenthesized type reference.
534/// Note: parens are only used for grouping, this is not a tuple type.
535///
536/// ```
537/// // This is effectively just `u32`.
538/// // Single-item tuple must be defined with a trailing comma: `(u32,)`
539/// type Foo = ❰ (u32) ❱;
540///
541/// let bar: &'static ❰ (dyn Debug) ❱ = "bruh";
542/// ```
272#[derive(Debug, Clone, PartialEq, Eq, Hash)] 543#[derive(Debug, Clone, PartialEq, Eq, Hash)]
273pub struct ParenType { 544pub struct ParenType {
274 pub(crate) syntax: SyntaxNode, 545 pub(crate) syntax: SyntaxNode,
@@ -278,7 +549,13 @@ impl ParenType {
278 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 549 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
279 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 550 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
280} 551}
281 552/// Unnamed tuple type.
553///
554/// ```
555/// let foo: ❰ (u32, bool) ❱ = (42, true);
556/// ```
557///
558/// [Reference](https://doc.rust-lang.org/reference/types/tuple.html)
282#[derive(Debug, Clone, PartialEq, Eq, Hash)] 559#[derive(Debug, Clone, PartialEq, Eq, Hash)]
283pub struct TupleType { 560pub struct TupleType {
284 pub(crate) syntax: SyntaxNode, 561 pub(crate) syntax: SyntaxNode,
@@ -288,7 +565,17 @@ impl TupleType {
288 pub fn fields(&self) -> AstChildren<TypeRef> { support::children(&self.syntax) } 565 pub fn fields(&self) -> AstChildren<TypeRef> { support::children(&self.syntax) }
289 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 566 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
290} 567}
291 568/// The never type (i.e. the exclamation point).
569///
570/// ```
571/// type T = ❰ ! ❱;
572///
573/// fn no_return() -> ❰ ! ❱ {
574/// loop {}
575/// }
576/// ```
577///
578/// [Reference](https://doc.rust-lang.org/reference/types/never.html)
292#[derive(Debug, Clone, PartialEq, Eq, Hash)] 579#[derive(Debug, Clone, PartialEq, Eq, Hash)]
293pub struct NeverType { 580pub struct NeverType {
294 pub(crate) syntax: SyntaxNode, 581 pub(crate) syntax: SyntaxNode,
@@ -296,7 +583,17 @@ pub struct NeverType {
296impl NeverType { 583impl NeverType {
297 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } 584 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
298} 585}
299 586/// Path to a type.
587/// Includes single identifier type names and elaborate paths with
588/// generic parameters.
589///
590/// ```
591/// type Foo = ❰ String ❱;
592/// type Bar = ❰ std::vec::Vec<T> ❱;
593/// type Baz = ❰ ::bruh::<Bruuh as Iterator>::Item ❱;
594/// ```
595///
596/// [Reference](https://doc.rust-lang.org/reference/paths.html)
300#[derive(Debug, Clone, PartialEq, Eq, Hash)] 597#[derive(Debug, Clone, PartialEq, Eq, Hash)]
301pub struct PathType { 598pub struct PathType {
302 pub(crate) syntax: SyntaxNode, 599 pub(crate) syntax: SyntaxNode,
@@ -304,7 +601,14 @@ pub struct PathType {
304impl PathType { 601impl PathType {
305 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 602 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
306} 603}
307 604/// Raw pointer type.
605///
606/// ```
607/// type Foo = ❰ *const u32 ❱;
608/// type Bar = ❰ *mut u32 ❱;
609/// ```
610///
611/// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut)
308#[derive(Debug, Clone, PartialEq, Eq, Hash)] 612#[derive(Debug, Clone, PartialEq, Eq, Hash)]
309pub struct PointerType { 613pub struct PointerType {
310 pub(crate) syntax: SyntaxNode, 614 pub(crate) syntax: SyntaxNode,
@@ -315,7 +619,13 @@ impl PointerType {
315 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } 619 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
316 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 620 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
317} 621}
318 622/// Array type.
623///
624/// ```
625/// type Foo = ❰ [u32; 24 - 3] ❱;
626/// ```
627///
628/// [Reference](https://doc.rust-lang.org/reference/types/array.html)
319#[derive(Debug, Clone, PartialEq, Eq, Hash)] 629#[derive(Debug, Clone, PartialEq, Eq, Hash)]
320pub struct ArrayType { 630pub struct ArrayType {
321 pub(crate) syntax: SyntaxNode, 631 pub(crate) syntax: SyntaxNode,
@@ -327,7 +637,13 @@ impl ArrayType {
327 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 637 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
328 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 638 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
329} 639}
330 640/// Slice type.
641///
642/// ```
643/// type Foo = ❰ [u8] ❱;
644/// ```
645///
646/// [Reference](https://doc.rust-lang.org/reference/types/slice.html)
331#[derive(Debug, Clone, PartialEq, Eq, Hash)] 647#[derive(Debug, Clone, PartialEq, Eq, Hash)]
332pub struct SliceType { 648pub struct SliceType {
333 pub(crate) syntax: SyntaxNode, 649 pub(crate) syntax: SyntaxNode,
@@ -337,7 +653,13 @@ impl SliceType {
337 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 653 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
338 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 654 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
339} 655}
340 656/// Reference type.
657///
658/// ```
659/// type Foo = ❰ &'static str ❱;
660/// ```
661///
662/// [Reference](https://doc.rust-lang.org/reference/types/pointer.html)
341#[derive(Debug, Clone, PartialEq, Eq, Hash)] 663#[derive(Debug, Clone, PartialEq, Eq, Hash)]
342pub struct ReferenceType { 664pub struct ReferenceType {
343 pub(crate) syntax: SyntaxNode, 665 pub(crate) syntax: SyntaxNode,
@@ -350,7 +672,13 @@ impl ReferenceType {
350 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } 672 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
351 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 673 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
352} 674}
353 675/// Placeholder type (i.e. the underscore).
676///
677/// ```
678/// let foo: ❰ _ ❱ = 42_u32;
679/// ```
680///
681/// [Reference](https://doc.rust-lang.org/reference/types/inferred.html)
354#[derive(Debug, Clone, PartialEq, Eq, Hash)] 682#[derive(Debug, Clone, PartialEq, Eq, Hash)]
355pub struct PlaceholderType { 683pub struct PlaceholderType {
356 pub(crate) syntax: SyntaxNode, 684 pub(crate) syntax: SyntaxNode,
@@ -358,7 +686,15 @@ pub struct PlaceholderType {
358impl PlaceholderType { 686impl PlaceholderType {
359 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } 687 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
360} 688}
361 689/// Function pointer type (not to be confused with `Fn*` family of traits).
690///
691/// ```
692/// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱;
693///
694/// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱;
695/// ```
696///
697/// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html)
362#[derive(Debug, Clone, PartialEq, Eq, Hash)] 698#[derive(Debug, Clone, PartialEq, Eq, Hash)]
363pub struct FnPointerType { 699pub struct FnPointerType {
364 pub(crate) syntax: SyntaxNode, 700 pub(crate) syntax: SyntaxNode,
@@ -370,7 +706,13 @@ impl FnPointerType {
370 pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } 706 pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
371 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } 707 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
372} 708}
373 709/// Higher order type.
710///
711/// ```
712/// type Foo = ❰ for<'a> fn(&'a str) ❱;
713/// ```
714///
715/// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html)
374#[derive(Debug, Clone, PartialEq, Eq, Hash)] 716#[derive(Debug, Clone, PartialEq, Eq, Hash)]
375pub struct ForType { 717pub struct ForType {
376 pub(crate) syntax: SyntaxNode, 718 pub(crate) syntax: SyntaxNode,
@@ -380,7 +722,13 @@ impl ForType {
380 pub fn type_param_list(&self) -> Option<TypeParamList> { support::child(&self.syntax) } 722 pub fn type_param_list(&self) -> Option<TypeParamList> { support::child(&self.syntax) }
381 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 723 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
382} 724}
383 725/// Opaque `impl Trait` type.
726///
727/// ```
728/// fn foo(bar: ❰ impl Debug + Eq ❱) {}
729/// ```
730///
731/// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html)
384#[derive(Debug, Clone, PartialEq, Eq, Hash)] 732#[derive(Debug, Clone, PartialEq, Eq, Hash)]
385pub struct ImplTraitType { 733pub struct ImplTraitType {
386 pub(crate) syntax: SyntaxNode, 734 pub(crate) syntax: SyntaxNode,
@@ -389,7 +737,13 @@ impl ast::TypeBoundsOwner for ImplTraitType {}
389impl ImplTraitType { 737impl ImplTraitType {
390 pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) } 738 pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
391} 739}
392 740/// Trait object type.
741///
742/// ```
743/// type Foo = ❰ dyn Debug ❱;
744/// ```
745///
746/// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html)
393#[derive(Debug, Clone, PartialEq, Eq, Hash)] 747#[derive(Debug, Clone, PartialEq, Eq, Hash)]
394pub struct DynTraitType { 748pub struct DynTraitType {
395 pub(crate) syntax: SyntaxNode, 749 pub(crate) syntax: SyntaxNode,
@@ -398,7 +752,13 @@ impl ast::TypeBoundsOwner for DynTraitType {}
398impl DynTraitType { 752impl DynTraitType {
399 pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) } 753 pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
400} 754}
401 755/// Tuple literal.
756///
757/// ```
758/// ❰ (42, true) ❱;
759/// ```
760///
761/// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html)
402#[derive(Debug, Clone, PartialEq, Eq, Hash)] 762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
403pub struct TupleExpr { 763pub struct TupleExpr {
404 pub(crate) syntax: SyntaxNode, 764 pub(crate) syntax: SyntaxNode,
@@ -409,7 +769,15 @@ impl TupleExpr {
409 pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) } 769 pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
410 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 770 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
411} 771}
412 772/// Array literal.
773///
774/// ```
775/// ❰ [#![inner_attr] true, false, true] ❱;
776///
777/// ❰ ["baz"; 24] ❱;
778/// ```
779///
780/// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
413#[derive(Debug, Clone, PartialEq, Eq, Hash)] 781#[derive(Debug, Clone, PartialEq, Eq, Hash)]
414pub struct ArrayExpr { 782pub struct ArrayExpr {
415 pub(crate) syntax: SyntaxNode, 783 pub(crate) syntax: SyntaxNode,
@@ -421,7 +789,14 @@ impl ArrayExpr {
421 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 789 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
422 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 790 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
423} 791}
424 792/// Parenthesized expression.
793/// Note: parens are only used for grouping, this is not a tuple literal.
794///
795/// ```
796/// ❰ (#![inner_attr] 2 + 2) ❱ * 2;
797/// ```
798///
799/// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html)
425#[derive(Debug, Clone, PartialEq, Eq, Hash)] 800#[derive(Debug, Clone, PartialEq, Eq, Hash)]
426pub struct ParenExpr { 801pub struct ParenExpr {
427 pub(crate) syntax: SyntaxNode, 802 pub(crate) syntax: SyntaxNode,
@@ -432,7 +807,19 @@ impl ParenExpr {
432 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 807 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
433 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 808 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
434} 809}
435 810/// Path to a symbol in expression context.
811/// Includes single identifier variable names and elaborate paths with
812/// generic parameters.
813///
814/// ```
815/// ❰ Some::<i32> ❱;
816/// ❰ foo ❱ + 42;
817/// ❰ Vec::<i32>::push ❱;
818/// ❰ <[i32]>::reverse ❱;
819/// ❰ <String as std::borrow::Borrow<str>>::borrow ❱;
820/// ```
821///
822/// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html)
436#[derive(Debug, Clone, PartialEq, Eq, Hash)] 823#[derive(Debug, Clone, PartialEq, Eq, Hash)]
437pub struct PathExpr { 824pub struct PathExpr {
438 pub(crate) syntax: SyntaxNode, 825 pub(crate) syntax: SyntaxNode,
@@ -440,7 +827,17 @@ pub struct PathExpr {
440impl PathExpr { 827impl PathExpr {
441 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 828 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
442} 829}
443 830/// Anonymous callable object literal a.k.a. closure, lambda or functor.
831///
832/// ```
833/// ❰ || 42 ❱;
834/// ❰ |a: u32| val + 1 ❱;
835/// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱;
836/// ❰ move || baz ❱;
837/// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱
838/// ```
839///
840/// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html)
444#[derive(Debug, Clone, PartialEq, Eq, Hash)] 841#[derive(Debug, Clone, PartialEq, Eq, Hash)]
445pub struct LambdaExpr { 842pub struct LambdaExpr {
446 pub(crate) syntax: SyntaxNode, 843 pub(crate) syntax: SyntaxNode,
@@ -454,7 +851,25 @@ impl LambdaExpr {
454 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } 851 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
455 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } 852 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
456} 853}
457 854/// If expression. Includes both regular `if` and `if let` forms.
855/// Beware that `else if` is a special case syntax sugar, because in general
856/// there has to be block expression after `else`.
857///
858/// ```
859/// ❰ if bool_cond { 42 } ❱
860/// ❰ if bool_cond { 42 } else { 24 } ❱
861/// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱
862///
863/// ❰
864/// if let Pattern(foo) = bar {
865/// foo
866/// } else {
867/// panic!();
868/// }
869/// ❱
870/// ```
871///
872/// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
458#[derive(Debug, Clone, PartialEq, Eq, Hash)] 873#[derive(Debug, Clone, PartialEq, Eq, Hash)]
459pub struct IfExpr { 874pub struct IfExpr {
460 pub(crate) syntax: SyntaxNode, 875 pub(crate) syntax: SyntaxNode,
@@ -464,7 +879,17 @@ impl IfExpr {
464 pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) } 879 pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
465 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } 880 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
466} 881}
467 882/// Unconditional loop expression.
883///
884/// ```
885/// ❰
886/// loop {
887/// // yeah, it's that simple...
888/// }
889/// ❱
890/// ```
891///
892/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html)
468#[derive(Debug, Clone, PartialEq, Eq, Hash)] 893#[derive(Debug, Clone, PartialEq, Eq, Hash)]
469pub struct LoopExpr { 894pub struct LoopExpr {
470 pub(crate) syntax: SyntaxNode, 895 pub(crate) syntax: SyntaxNode,
@@ -474,7 +899,45 @@ impl ast::LoopBodyOwner for LoopExpr {}
474impl LoopExpr { 899impl LoopExpr {
475 pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) } 900 pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
476} 901}
477 902/// Block expression with an optional prefix (label, try ketword,
903/// unsafe keyword, async keyword...).
904///
905/// ```
906/// ❰
907/// 'label: try {
908/// None?
909/// }
910/// ❱
911/// ```
912///
913/// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html)
914/// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks)
915/// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks)
916#[derive(Debug, Clone, PartialEq, Eq, Hash)]
917pub struct EffectExpr {
918 pub(crate) syntax: SyntaxNode,
919}
920impl ast::AttrsOwner for EffectExpr {}
921impl EffectExpr {
922 pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
923 pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
924 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
925 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
926 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
927}
928/// For loop expression.
929/// Note: record struct literals are not valid as iterable expression
930/// due to ambiguity.
931///
932/// ```
933/// ❰
934/// for i in (0..4) {
935/// dbg!(i);
936/// }
937/// ❱
938/// ```
939///
940/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops)
478#[derive(Debug, Clone, PartialEq, Eq, Hash)] 941#[derive(Debug, Clone, PartialEq, Eq, Hash)]
479pub struct ForExpr { 942pub struct ForExpr {
480 pub(crate) syntax: SyntaxNode, 943 pub(crate) syntax: SyntaxNode,
@@ -487,7 +950,22 @@ impl ForExpr {
487 pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) } 950 pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
488 pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) } 951 pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) }
489} 952}
490 953/// While loop expression. Includes both regular `while` and `while let` forms.
954///
955/// ```
956/// ❰
957/// while bool_cond {
958/// 42;
959/// }
960/// ❱
961/// ❰
962/// while let Pattern(foo) = bar {
963/// bar += 1;
964/// }
965/// ❱
966/// ```
967///
968/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
491#[derive(Debug, Clone, PartialEq, Eq, Hash)] 969#[derive(Debug, Clone, PartialEq, Eq, Hash)]
492pub struct WhileExpr { 970pub struct WhileExpr {
493 pub(crate) syntax: SyntaxNode, 971 pub(crate) syntax: SyntaxNode,
@@ -498,7 +976,22 @@ impl WhileExpr {
498 pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) } 976 pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) }
499 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } 977 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
500} 978}
501 979/// Continue expression.
980///
981/// ```
982/// while bool_cond {
983/// ❰ continue ❱;
984/// }
985///
986/// 'outer: loop {
987/// loop {
988/// ❰ continue 'outer ❱;
989/// }
990/// }
991///
992/// ```
993///
994/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)
502#[derive(Debug, Clone, PartialEq, Eq, Hash)] 995#[derive(Debug, Clone, PartialEq, Eq, Hash)]
503pub struct ContinueExpr { 996pub struct ContinueExpr {
504 pub(crate) syntax: SyntaxNode, 997 pub(crate) syntax: SyntaxNode,
@@ -512,7 +1005,25 @@ impl ContinueExpr {
512 support::token(&self.syntax, T![lifetime]) 1005 support::token(&self.syntax, T![lifetime])
513 } 1006 }
514} 1007}
515 1008/// Break expression.
1009///
1010/// ```
1011/// while bool_cond {
1012/// ❰ break ❱;
1013/// }
1014/// 'outer: loop {
1015/// for foo in bar {
1016/// ❰ break 'outer ❱;
1017/// }
1018/// }
1019/// 'outer: loop {
1020/// loop {
1021/// ❰ break 'outer 42 ❱;
1022/// }
1023/// }
1024/// ```
1025///
1026/// [Refernce](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions)
516#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1027#[derive(Debug, Clone, PartialEq, Eq, Hash)]
517pub struct BreakExpr { 1028pub struct BreakExpr {
518 pub(crate) syntax: SyntaxNode, 1029 pub(crate) syntax: SyntaxNode,
@@ -525,7 +1036,20 @@ impl BreakExpr {
525 } 1036 }
526 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1037 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
527} 1038}
528 1039/// Label.
1040///
1041/// ```
1042/// ❰ 'outer: ❱ loop {}
1043///
1044/// let foo = ❰ 'bar: ❱ loop {}
1045///
1046/// ❰ 'baz: ❱ {
1047/// break 'baz;
1048/// }
1049/// ```
1050///
1051/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html?highlight=label#loop-labels)
1052/// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
529#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1053#[derive(Debug, Clone, PartialEq, Eq, Hash)]
530pub struct Label { 1054pub struct Label {
531 pub(crate) syntax: SyntaxNode, 1055 pub(crate) syntax: SyntaxNode,
@@ -535,19 +1059,44 @@ impl Label {
535 support::token(&self.syntax, T![lifetime]) 1059 support::token(&self.syntax, T![lifetime])
536 } 1060 }
537} 1061}
538 1062/// Block expression. Includes unsafe blocks and block labels.
1063///
1064/// ```
1065/// let foo = ❰
1066/// {
1067/// #![inner_attr]
1068/// ❰ { } ❱
1069///
1070/// ❰ 'label: { break 'label } ❱
1071/// }
1072/// ❱;
1073/// ```
1074///
1075/// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html)
1076/// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
539#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1077#[derive(Debug, Clone, PartialEq, Eq, Hash)]
540pub struct BlockExpr { 1078pub struct BlockExpr {
541 pub(crate) syntax: SyntaxNode, 1079 pub(crate) syntax: SyntaxNode,
542} 1080}
543impl ast::AttrsOwner for BlockExpr {} 1081impl ast::AttrsOwner for BlockExpr {}
1082impl ast::ModuleItemOwner for BlockExpr {}
544impl BlockExpr { 1083impl BlockExpr {
545 pub fn label(&self) -> Option<Label> { support::child(&self.syntax) } 1084 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
546 pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } 1085 pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
547 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } 1086 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
548 pub fn block(&self) -> Option<Block> { support::child(&self.syntax) } 1087 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
549} 1088}
550 1089/// Return expression.
1090///
1091/// ```
1092/// || ❰ return 42 ❱;
1093///
1094/// fn bar() {
1095/// ❰ return ❱;
1096/// }
1097/// ```
1098///
1099/// [Reference](https://doc.rust-lang.org/reference/expressions/return-expr.html)
551#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1100#[derive(Debug, Clone, PartialEq, Eq, Hash)]
552pub struct ReturnExpr { 1101pub struct ReturnExpr {
553 pub(crate) syntax: SyntaxNode, 1102 pub(crate) syntax: SyntaxNode,
@@ -556,7 +1105,16 @@ impl ast::AttrsOwner for ReturnExpr {}
556impl ReturnExpr { 1105impl ReturnExpr {
557 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1106 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
558} 1107}
559 1108/// Call expression (not to be confused with method call expression, it is
1109/// a separate ast node).
1110///
1111/// ```
1112/// ❰ foo() ❱;
1113/// ❰ &str::len("bar") ❱;
1114/// ❰ <&str as PartialEq<&str>>::eq(&"", &"") ❱;
1115/// ```
1116///
1117/// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
560#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1118#[derive(Debug, Clone, PartialEq, Eq, Hash)]
561pub struct CallExpr { 1119pub struct CallExpr {
562 pub(crate) syntax: SyntaxNode, 1120 pub(crate) syntax: SyntaxNode,
@@ -565,7 +1123,16 @@ impl ast::ArgListOwner for CallExpr {}
565impl CallExpr { 1123impl CallExpr {
566 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1124 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
567} 1125}
568 1126/// Method call expression.
1127///
1128/// ```
1129/// ❰ receiver_expr.method() ❱;
1130/// ❰ receiver_expr.method::<T>(42, true) ❱;
1131///
1132/// ❰ ❰ ❰ foo.bar() ❱ .baz() ❱ .bruh() ❱;
1133/// ```
1134///
1135/// [Reference](https://doc.rust-lang.org/reference/expressions/method-call-expr.html)
569#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1136#[derive(Debug, Clone, PartialEq, Eq, Hash)]
570pub struct MethodCallExpr { 1137pub struct MethodCallExpr {
571 pub(crate) syntax: SyntaxNode, 1138 pub(crate) syntax: SyntaxNode,
@@ -578,7 +1145,13 @@ impl MethodCallExpr {
578 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } 1145 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
579 pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } 1146 pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) }
580} 1147}
581 1148/// Index expression a.k.a. subscript operator call.
1149///
1150/// ```
1151/// ❰ foo[42] ❱;
1152/// ```
1153///
1154/// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
582#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1155#[derive(Debug, Clone, PartialEq, Eq, Hash)]
583pub struct IndexExpr { 1156pub struct IndexExpr {
584 pub(crate) syntax: SyntaxNode, 1157 pub(crate) syntax: SyntaxNode,
@@ -588,7 +1161,15 @@ impl IndexExpr {
588 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } 1161 pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
589 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 1162 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
590} 1163}
591 1164/// Field access expression.
1165///
1166/// ```
1167/// ❰ expr.bar ❱;
1168///
1169/// ❰ ❰ ❰ foo.bar ❱ .baz ❱ .bruh ❱;
1170/// ```
1171///
1172/// [Reference](https://doc.rust-lang.org/reference/expressions/field-expr.html)
592#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1173#[derive(Debug, Clone, PartialEq, Eq, Hash)]
593pub struct FieldExpr { 1174pub struct FieldExpr {
594 pub(crate) syntax: SyntaxNode, 1175 pub(crate) syntax: SyntaxNode,
@@ -599,7 +1180,13 @@ impl FieldExpr {
599 pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } 1180 pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
600 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } 1181 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
601} 1182}
602 1183/// Await operator call expression.
1184///
1185/// ```
1186/// ❰ expr.await ❱;
1187/// ```
1188///
1189/// [Reference](https://doc.rust-lang.org/reference/expressions/await-expr.html)
603#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1190#[derive(Debug, Clone, PartialEq, Eq, Hash)]
604pub struct AwaitExpr { 1191pub struct AwaitExpr {
605 pub(crate) syntax: SyntaxNode, 1192 pub(crate) syntax: SyntaxNode,
@@ -610,17 +1197,29 @@ impl AwaitExpr {
610 pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } 1197 pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
611 pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) } 1198 pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) }
612} 1199}
613 1200/// The question mark operator call.
1201///
1202/// ```
1203/// ❰ expr? ❱;
1204/// ```
1205///
1206/// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator)
614#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1207#[derive(Debug, Clone, PartialEq, Eq, Hash)]
615pub struct TryExpr { 1208pub struct TryExpr {
616 pub(crate) syntax: SyntaxNode, 1209 pub(crate) syntax: SyntaxNode,
617} 1210}
618impl ast::AttrsOwner for TryExpr {} 1211impl ast::AttrsOwner for TryExpr {}
619impl TryExpr { 1212impl TryExpr {
620 pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
621 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1213 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
1214 pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
622} 1215}
623 1216/// Type cast expression.
1217///
1218/// ```
1219/// ❰ expr as T ❱;
1220/// ```
1221///
1222/// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions)
624#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1223#[derive(Debug, Clone, PartialEq, Eq, Hash)]
625pub struct CastExpr { 1224pub struct CastExpr {
626 pub(crate) syntax: SyntaxNode, 1225 pub(crate) syntax: SyntaxNode,
@@ -631,7 +1230,14 @@ impl CastExpr {
631 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } 1230 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
632 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 1231 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
633} 1232}
634 1233/// Borrow operator call.
1234///
1235/// ```
1236/// ❰ &foo ❱;
1237/// ❰ &mut bar ❱;
1238/// ```
1239///
1240/// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators)
635#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1241#[derive(Debug, Clone, PartialEq, Eq, Hash)]
636pub struct RefExpr { 1242pub struct RefExpr {
637 pub(crate) syntax: SyntaxNode, 1243 pub(crate) syntax: SyntaxNode,
@@ -643,7 +1249,15 @@ impl RefExpr {
643 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } 1249 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
644 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1250 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
645} 1251}
646 1252/// Prefix operator call. This is either `!` or `*` or `-`.
1253///
1254/// ```
1255/// ❰ !foo ❱;
1256/// ❰ *bar ❱;
1257/// ❰ -42 ❱;
1258/// ```
1259///
1260/// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html)
647#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1261#[derive(Debug, Clone, PartialEq, Eq, Hash)]
648pub struct PrefixExpr { 1262pub struct PrefixExpr {
649 pub(crate) syntax: SyntaxNode, 1263 pub(crate) syntax: SyntaxNode,
@@ -652,7 +1266,13 @@ impl ast::AttrsOwner for PrefixExpr {}
652impl PrefixExpr { 1266impl PrefixExpr {
653 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1267 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
654} 1268}
655 1269/// Box operator call.
1270///
1271/// ```
1272/// ❰ box 42 ❱;
1273/// ```
1274///
1275/// [RFC](https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b1d20284b43f87cbe1c6/text/0809-box-and-in-for-stdlib.md)
656#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1276#[derive(Debug, Clone, PartialEq, Eq, Hash)]
657pub struct BoxExpr { 1277pub struct BoxExpr {
658 pub(crate) syntax: SyntaxNode, 1278 pub(crate) syntax: SyntaxNode,
@@ -662,27 +1282,69 @@ impl BoxExpr {
662 pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) } 1282 pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
663 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1283 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
664} 1284}
665 1285/// Range operator call.
1286///
1287/// ```
1288/// ❰ 0..42 ❱;
1289/// ❰ ..42 ❱;
1290/// ❰ 0.. ❱;
1291/// ❰ .. ❱;
1292/// ❰ 0..=42 ❱;
1293/// ❰ ..=42 ❱;
1294/// ```
1295///
1296/// [Reference](https://doc.rust-lang.org/reference/expressions/range-expr.html)
666#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1297#[derive(Debug, Clone, PartialEq, Eq, Hash)]
667pub struct RangeExpr { 1298pub struct RangeExpr {
668 pub(crate) syntax: SyntaxNode, 1299 pub(crate) syntax: SyntaxNode,
669} 1300}
670impl ast::AttrsOwner for RangeExpr {} 1301impl ast::AttrsOwner for RangeExpr {}
671impl RangeExpr {} 1302impl RangeExpr {}
672 1303/// Binary operator call.
1304/// Includes all arithmetic, logic, bitwise and assignment operators.
1305///
1306/// ```
1307/// ❰ 2 + ❰ 2 * 2 ❱ ❱;
1308/// ❰ ❰ true && false ❱ || true ❱;
1309/// ```
1310///
1311/// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators)
673#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1312#[derive(Debug, Clone, PartialEq, Eq, Hash)]
674pub struct BinExpr { 1313pub struct BinExpr {
675 pub(crate) syntax: SyntaxNode, 1314 pub(crate) syntax: SyntaxNode,
676} 1315}
677impl ast::AttrsOwner for BinExpr {} 1316impl ast::AttrsOwner for BinExpr {}
678impl BinExpr {} 1317impl BinExpr {}
679 1318/// [Raw] string, [raw] byte string, char, byte, integer, float or bool literal.
1319///
1320/// ```
1321/// ❰ "str" ❱;
1322/// ❰ br##"raw byte str"## ❱;
1323/// ❰ 'c' ❱;
1324/// ❰ b'c' ❱;
1325/// ❰ 42 ❱;
1326/// ❰ 1e9 ❱;
1327/// ❰ true ❱;
1328/// ```
1329///
1330/// [Reference](https://doc.rust-lang.org/reference/expressions/literal-expr.html)
680#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1331#[derive(Debug, Clone, PartialEq, Eq, Hash)]
681pub struct Literal { 1332pub struct Literal {
682 pub(crate) syntax: SyntaxNode, 1333 pub(crate) syntax: SyntaxNode,
683} 1334}
684impl Literal {} 1335impl Literal {}
685 1336/// Match expression.
1337///
1338/// ```
1339/// ❰
1340/// match expr {
1341/// Pat1 => {}
1342/// Pat2(_) => 42,
1343/// }
1344/// ❱
1345/// ```
1346///
1347/// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
686#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1348#[derive(Debug, Clone, PartialEq, Eq, Hash)]
687pub struct MatchExpr { 1349pub struct MatchExpr {
688 pub(crate) syntax: SyntaxNode, 1350 pub(crate) syntax: SyntaxNode,
@@ -693,7 +1355,20 @@ impl MatchExpr {
693 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1355 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
694 pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) } 1356 pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) }
695} 1357}
696 1358/// Match arm list part of match expression. Includes its inner attributes.
1359///
1360/// ```
1361/// match expr
1362/// ❰
1363/// {
1364/// #![inner_attr]
1365/// Pat1 => {}
1366/// Pat2(_) => 42,
1367/// }
1368/// ❱
1369/// ```
1370///
1371/// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
697#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1372#[derive(Debug, Clone, PartialEq, Eq, Hash)]
698pub struct MatchArmList { 1373pub struct MatchArmList {
699 pub(crate) syntax: SyntaxNode, 1374 pub(crate) syntax: SyntaxNode,
@@ -704,7 +1379,16 @@ impl MatchArmList {
704 pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) } 1379 pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) }
705 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 1380 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
706} 1381}
707 1382/// Match arm.
1383/// Note: record struct literals are not valid as target match expression
1384/// due to ambiguity.
1385/// ```
1386/// match expr {
1387/// ❰ #[attr] Pattern(it) if bool_cond => it ❱,
1388/// }
1389/// ```
1390///
1391/// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
708#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1392#[derive(Debug, Clone, PartialEq, Eq, Hash)]
709pub struct MatchArm { 1393pub struct MatchArm {
710 pub(crate) syntax: SyntaxNode, 1394 pub(crate) syntax: SyntaxNode,
@@ -716,7 +1400,15 @@ impl MatchArm {
716 pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) } 1400 pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
717 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1401 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
718} 1402}
719 1403/// Match guard.
1404///
1405/// ```
1406/// match expr {
1407/// Pattern(it) ❰ if bool_cond ❱ => it,
1408/// }
1409/// ```
1410///
1411/// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards)
720#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1412#[derive(Debug, Clone, PartialEq, Eq, Hash)]
721pub struct MatchGuard { 1413pub struct MatchGuard {
722 pub(crate) syntax: SyntaxNode, 1414 pub(crate) syntax: SyntaxNode,
@@ -725,7 +1417,21 @@ impl MatchGuard {
725 pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) } 1417 pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
726 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1418 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
727} 1419}
728 1420/// Record literal expression. The same syntax is used for structs,
1421/// unions and record enum variants.
1422///
1423/// ```
1424/// ❰
1425/// foo::Bar {
1426/// #![inner_attr]
1427/// baz: 42,
1428/// bruh: true,
1429/// ..spread
1430/// }
1431/// ❱
1432/// ```
1433///
1434/// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
729#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1435#[derive(Debug, Clone, PartialEq, Eq, Hash)]
730pub struct RecordLit { 1436pub struct RecordLit {
731 pub(crate) syntax: SyntaxNode, 1437 pub(crate) syntax: SyntaxNode,
@@ -734,7 +1440,16 @@ impl RecordLit {
734 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 1440 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
735 pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) } 1441 pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) }
736} 1442}
737 1443/// Record field list including enclosing curly braces.
1444///
1445/// foo::Bar ❰
1446/// {
1447/// baz: 42,
1448/// ..spread
1449/// }
1450/// ❱
1451///
1452/// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
738#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1453#[derive(Debug, Clone, PartialEq, Eq, Hash)]
739pub struct RecordFieldList { 1454pub struct RecordFieldList {
740 pub(crate) syntax: SyntaxNode, 1455 pub(crate) syntax: SyntaxNode,
@@ -746,7 +1461,15 @@ impl RecordFieldList {
746 pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) } 1461 pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) }
747 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 1462 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
748} 1463}
749 1464/// Record field.
1465///
1466/// ```
1467/// foo::Bar {
1468/// ❰ #[attr] baz: 42 ❱
1469/// }
1470/// ```
1471///
1472/// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
750#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1473#[derive(Debug, Clone, PartialEq, Eq, Hash)]
751pub struct RecordField { 1474pub struct RecordField {
752 pub(crate) syntax: SyntaxNode, 1475 pub(crate) syntax: SyntaxNode,
@@ -757,7 +1480,13 @@ impl RecordField {
757 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } 1480 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
758 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1481 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
759} 1482}
760 1483/// Disjunction of patterns.
1484///
1485/// ```
1486/// let ❰ Foo(it) | Bar(it) | Baz(it) ❱ = bruh;
1487/// ```
1488///
1489/// [Reference](https://doc.rust-lang.org/reference/patterns.html)
761#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1490#[derive(Debug, Clone, PartialEq, Eq, Hash)]
762pub struct OrPat { 1491pub struct OrPat {
763 pub(crate) syntax: SyntaxNode, 1492 pub(crate) syntax: SyntaxNode,
@@ -765,7 +1494,14 @@ pub struct OrPat {
765impl OrPat { 1494impl OrPat {
766 pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) } 1495 pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
767} 1496}
768 1497/// Parenthesized pattern.
1498/// Note: parens are only used for grouping, this is not a tuple pattern.
1499///
1500/// ```
1501/// if let ❰ &(0..=42) ❱ = foo {}
1502/// ```
1503///
1504/// https://doc.rust-lang.org/reference/patterns.html#grouped-patterns
769#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1505#[derive(Debug, Clone, PartialEq, Eq, Hash)]
770pub struct ParenPat { 1506pub struct ParenPat {
771 pub(crate) syntax: SyntaxNode, 1507 pub(crate) syntax: SyntaxNode,
@@ -775,7 +1511,16 @@ impl ParenPat {
775 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } 1511 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
776 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 1512 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
777} 1513}
778 1514/// Reference pattern.
1515/// Note: this has nothing to do with `ref` keyword, the latter is used in bind patterns.
1516///
1517/// ```
1518/// let ❰ &mut foo ❱ = bar;
1519///
1520/// let ❰ & ❰ &mut ❰ &_ ❱ ❱ ❱ = baz;
1521/// ```
1522///
1523/// [Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns)
779#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1524#[derive(Debug, Clone, PartialEq, Eq, Hash)]
780pub struct RefPat { 1525pub struct RefPat {
781 pub(crate) syntax: SyntaxNode, 1526 pub(crate) syntax: SyntaxNode,
@@ -785,7 +1530,13 @@ impl RefPat {
785 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } 1530 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
786 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } 1531 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
787} 1532}
788 1533/// Box pattern.
1534///
1535/// ```
1536/// let ❰ box foo ❱ = box 42;
1537/// ```
1538///
1539/// [Unstable book](https://doc.rust-lang.org/unstable-book/language-features/box-patterns.html)
789#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1540#[derive(Debug, Clone, PartialEq, Eq, Hash)]
790pub struct BoxPat { 1541pub struct BoxPat {
791 pub(crate) syntax: SyntaxNode, 1542 pub(crate) syntax: SyntaxNode,
@@ -794,7 +1545,16 @@ impl BoxPat {
794 pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) } 1545 pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
795 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } 1546 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
796} 1547}
797 1548/// Bind pattern.
1549///
1550/// ```
1551/// match foo {
1552/// Some(❰ ref mut bar ❱) => {}
1553/// ❰ baz @ None ❱ => {}
1554/// }
1555/// ```
1556///
1557/// [Reference](https://doc.rust-lang.org/reference/patterns.html#identifier-patterns)
798#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1558#[derive(Debug, Clone, PartialEq, Eq, Hash)]
799pub struct BindPat { 1559pub struct BindPat {
800 pub(crate) syntax: SyntaxNode, 1560 pub(crate) syntax: SyntaxNode,
@@ -807,7 +1567,13 @@ impl BindPat {
807 pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) } 1567 pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) }
808 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } 1568 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
809} 1569}
810 1570/// Placeholder pattern a.k.a. the wildcard pattern or the underscore.
1571///
1572/// ```
1573/// let ❰ _ ❱ = foo;
1574/// ```
1575///
1576/// [Reference](https://doc.rust-lang.org/reference/patterns.html#wildcard-pattern)
811#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1577#[derive(Debug, Clone, PartialEq, Eq, Hash)]
812pub struct PlaceholderPat { 1578pub struct PlaceholderPat {
813 pub(crate) syntax: SyntaxNode, 1579 pub(crate) syntax: SyntaxNode,
@@ -815,7 +1581,16 @@ pub struct PlaceholderPat {
815impl PlaceholderPat { 1581impl PlaceholderPat {
816 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } 1582 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
817} 1583}
818 1584/// Rest-of-the record/tuple pattern.
1585/// Note: this is not the unbonded range pattern (even more: it doesn't exist).
1586///
1587/// ```
1588/// let Foo { bar, ❰ .. ❱ } = baz;
1589/// let (❰ .. ❱, bruh) = (42, 24, 42);
1590/// let Bruuh(❰ .. ❱) = bruuuh;
1591/// ```
1592///
1593/// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
819#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1594#[derive(Debug, Clone, PartialEq, Eq, Hash)]
820pub struct DotDotPat { 1595pub struct DotDotPat {
821 pub(crate) syntax: SyntaxNode, 1596 pub(crate) syntax: SyntaxNode,
@@ -823,7 +1598,15 @@ pub struct DotDotPat {
823impl DotDotPat { 1598impl DotDotPat {
824 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } 1599 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
825} 1600}
826 1601/// Path pattern.
1602/// Doesn't include the underscore pattern (it is a special case, namely `PlaceholderPat`).
1603///
1604/// ```
1605/// let ❰ foo::bar::Baz ❱ { .. } = bruh;
1606/// if let ❰ CONST ❱ = 42 {}
1607/// ```
1608///
1609/// [Reference](https://doc.rust-lang.org/reference/patterns.html#path-patterns)
827#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1610#[derive(Debug, Clone, PartialEq, Eq, Hash)]
828pub struct PathPat { 1611pub struct PathPat {
829 pub(crate) syntax: SyntaxNode, 1612 pub(crate) syntax: SyntaxNode,
@@ -831,7 +1614,13 @@ pub struct PathPat {
831impl PathPat { 1614impl PathPat {
832 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 1615 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
833} 1616}
834 1617/// Slice pattern.
1618///
1619/// ```
1620/// let ❰ [foo, bar, baz] ❱ = [1, 2, 3];
1621/// ```
1622///
1623/// [Reference](https://doc.rust-lang.org/reference/patterns.html#slice-patterns)
835#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1624#[derive(Debug, Clone, PartialEq, Eq, Hash)]
836pub struct SlicePat { 1625pub struct SlicePat {
837 pub(crate) syntax: SyntaxNode, 1626 pub(crate) syntax: SyntaxNode,
@@ -841,13 +1630,33 @@ impl SlicePat {
841 pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } 1630 pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
842 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 1631 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
843} 1632}
844 1633/// Range pattern.
1634///
1635/// ```
1636/// match foo {
1637/// ❰ 0..42 ❱ => {}
1638/// ❰ 0..=42 ❱ => {}
1639/// }
1640/// ```
1641///
1642/// [Reference](https://doc.rust-lang.org/reference/patterns.html#range-patterns)
845#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1643#[derive(Debug, Clone, PartialEq, Eq, Hash)]
846pub struct RangePat { 1644pub struct RangePat {
847 pub(crate) syntax: SyntaxNode, 1645 pub(crate) syntax: SyntaxNode,
848} 1646}
849impl RangePat {} 1647impl RangePat {}
850 1648/// Literal pattern.
1649/// Includes only bool, number, char, and string literals.
1650///
1651/// ```
1652/// match foo {
1653/// Number(❰ 42 ❱) => {}
1654/// String(❰ "42" ❱) => {}
1655/// Bool(❰ true ❱) => {}
1656/// }
1657/// ```
1658///
1659/// [Reference](https://doc.rust-lang.org/reference/patterns.html#literal-patterns)
851#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1660#[derive(Debug, Clone, PartialEq, Eq, Hash)]
852pub struct LiteralPat { 1661pub struct LiteralPat {
853 pub(crate) syntax: SyntaxNode, 1662 pub(crate) syntax: SyntaxNode,
@@ -855,7 +1664,13 @@ pub struct LiteralPat {
855impl LiteralPat { 1664impl LiteralPat {
856 pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) } 1665 pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
857} 1666}
858 1667/// Macro invocation in pattern position.
1668///
1669/// ```
1670/// let ❰ foo!(my custom syntax) ❱ = baz;
1671///
1672/// ```
1673/// [Reference](https://doc.rust-lang.org/reference/macros.html#macro-invocation)
859#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1674#[derive(Debug, Clone, PartialEq, Eq, Hash)]
860pub struct MacroPat { 1675pub struct MacroPat {
861 pub(crate) syntax: SyntaxNode, 1676 pub(crate) syntax: SyntaxNode,
@@ -863,7 +1678,13 @@ pub struct MacroPat {
863impl MacroPat { 1678impl MacroPat {
864 pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) } 1679 pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
865} 1680}
866 1681/// Record literal pattern.
1682///
1683/// ```
1684/// let ❰ foo::Bar { baz, .. } ❱ = bruh;
1685/// ```
1686///
1687/// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
867#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1688#[derive(Debug, Clone, PartialEq, Eq, Hash)]
868pub struct RecordPat { 1689pub struct RecordPat {
869 pub(crate) syntax: SyntaxNode, 1690 pub(crate) syntax: SyntaxNode,
@@ -874,7 +1695,13 @@ impl RecordPat {
874 } 1695 }
875 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 1696 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
876} 1697}
877 1698/// Record literal's field patterns list including enclosing curly braces.
1699///
1700/// ```
1701/// let foo::Bar ❰ { baz, bind @ bruh, .. } ❱ = bruuh;
1702/// ``
1703///
1704/// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
878#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1705#[derive(Debug, Clone, PartialEq, Eq, Hash)]
879pub struct RecordFieldPatList { 1706pub struct RecordFieldPatList {
880 pub(crate) syntax: SyntaxNode, 1707 pub(crate) syntax: SyntaxNode,
@@ -889,7 +1716,15 @@ impl RecordFieldPatList {
889 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } 1716 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
890 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 1717 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
891} 1718}
892 1719/// Record literal's field pattern.
1720/// Note: record literal can also match tuple structs.
1721///
1722/// ```
1723/// let Foo { ❰ bar: _ ❱ } = baz;
1724/// let TupleStruct { ❰ 0: _ ❱ } = bruh;
1725/// ```
1726///
1727/// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
893#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1728#[derive(Debug, Clone, PartialEq, Eq, Hash)]
894pub struct RecordFieldPat { 1729pub struct RecordFieldPat {
895 pub(crate) syntax: SyntaxNode, 1730 pub(crate) syntax: SyntaxNode,
@@ -900,7 +1735,13 @@ impl RecordFieldPat {
900 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } 1735 pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
901 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } 1736 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
902} 1737}
903 1738/// Tuple struct literal pattern.
1739///
1740/// ```
1741/// let ❰ foo::Bar(baz, bruh) ❱ = bruuh;
1742/// ```
1743///
1744/// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns)
904#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1745#[derive(Debug, Clone, PartialEq, Eq, Hash)]
905pub struct TupleStructPat { 1746pub struct TupleStructPat {
906 pub(crate) syntax: SyntaxNode, 1747 pub(crate) syntax: SyntaxNode,
@@ -911,7 +1752,14 @@ impl TupleStructPat {
911 pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } 1752 pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
912 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 1753 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
913} 1754}
914 1755/// Tuple pattern.
1756/// Note: this doesn't include tuple structs (see `TupleStructPat`)
1757///
1758/// ```
1759/// let ❰ (foo, bar, .., baz) ❱ = bruh;
1760/// ```
1761///
1762/// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-patterns)
915#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1763#[derive(Debug, Clone, PartialEq, Eq, Hash)]
916pub struct TuplePat { 1764pub struct TuplePat {
917 pub(crate) syntax: SyntaxNode, 1765 pub(crate) syntax: SyntaxNode,
@@ -921,7 +1769,17 @@ impl TuplePat {
921 pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } 1769 pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
922 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 1770 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
923} 1771}
924 1772/// Visibility.
1773///
1774/// ```
1775/// ❰ pub mod ❱ foo;
1776/// ❰ pub(crate) ❱ struct Bar;
1777/// ❰ pub(self) ❱ enum Baz {}
1778/// ❰ pub(super) ❱ fn bruh() {}
1779/// ❰ pub(in bruuh::bruuuh) ❱ type T = u64;
1780/// ```
1781///
1782/// [Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html)
925#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1783#[derive(Debug, Clone, PartialEq, Eq, Hash)]
926pub struct Visibility { 1784pub struct Visibility {
927 pub(crate) syntax: SyntaxNode, 1785 pub(crate) syntax: SyntaxNode,
@@ -932,7 +1790,29 @@ impl Visibility {
932 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } 1790 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
933 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } 1791 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
934} 1792}
935 1793/// Single identifier.
1794/// Note(@matklad): `Name` is for things that install a new name into the scope,
1795/// `NameRef` is a usage of a name. Most of the time, this definition/reference
1796/// distinction can be determined purely syntactically, ie in
1797/// ```
1798/// fn foo() { foo() }
1799/// ```
1800/// the first foo is `Name`, the second one is `NameRef`.
1801/// The notable exception are patterns, where in
1802/// ``
1803/// let x = 92
1804/// ```
1805/// `x` can be semantically either a name or a name ref, depeding on
1806/// wether there's an `x` constant in scope.
1807/// We use `Name` for patterns, and disambiguate semantically (see `NameClass` in ide_db).
1808///
1809/// ```
1810/// let ❰ foo ❱ = bar;
1811/// struct ❰ Baz ❱;
1812/// fn ❰ bruh ❱() {}
1813/// ```
1814///
1815/// [Reference](https://doc.rust-lang.org/reference/identifiers.html)
936#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1816#[derive(Debug, Clone, PartialEq, Eq, Hash)]
937pub struct Name { 1817pub struct Name {
938 pub(crate) syntax: SyntaxNode, 1818 pub(crate) syntax: SyntaxNode,
@@ -940,13 +1820,41 @@ pub struct Name {
940impl Name { 1820impl Name {
941 pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) } 1821 pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
942} 1822}
943 1823/// Reference to a name.
1824/// See the explanation on the difference between `Name` and `NameRef`
1825/// in `Name` ast node docs.
1826///
1827/// ```
1828/// let foo = ❰ bar ❱(❰ Baz(❰ bruh ❱) ❱;
1829/// ```
1830///
1831/// [Reference](https://doc.rust-lang.org/reference/identifiers.html)
944#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1832#[derive(Debug, Clone, PartialEq, Eq, Hash)]
945pub struct NameRef { 1833pub struct NameRef {
946 pub(crate) syntax: SyntaxNode, 1834 pub(crate) syntax: SyntaxNode,
947} 1835}
948impl NameRef {} 1836impl NameRef {}
949 1837/// Macro call.
1838/// Includes all of its attributes and doc comments.
1839///
1840/// ```
1841/// ❰
1842/// /// Docs
1843/// #[attr]
1844/// macro_rules! foo { // macro rules is also a macro call
1845/// ($bar: tt) => {}
1846/// }
1847/// ❱
1848///
1849/// // semicolon is a part of `MacroCall` when it is used in item positions
1850/// ❰ foo!(); ❱
1851///
1852/// fn main() {
1853/// ❰ foo!() ❱; // macro call in expression positions doesn't include the semi
1854/// }
1855/// ```
1856///
1857/// [Reference](https://doc.rust-lang.org/reference/macros.html)
950#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1858#[derive(Debug, Clone, PartialEq, Eq, Hash)]
951pub struct MacroCall { 1859pub struct MacroCall {
952 pub(crate) syntax: SyntaxNode, 1860 pub(crate) syntax: SyntaxNode,
@@ -960,7 +1868,18 @@ impl MacroCall {
960 pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } 1868 pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
961 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 1869 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
962} 1870}
963 1871/// Attribute.
1872///
1873/// ```
1874/// ❰ #![inner_attr] ❱
1875///
1876/// ❰ #[attr] ❱
1877/// ❰ #[foo = "bar"] ❱
1878/// ❰ #[baz(bruh::bruuh = "42")] ❱
1879/// struct Foo;
1880/// ```
1881///
1882/// [Reference](https://doc.rust-lang.org/reference/attributes.html)
964#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1883#[derive(Debug, Clone, PartialEq, Eq, Hash)]
965pub struct Attr { 1884pub struct Attr {
966 pub(crate) syntax: SyntaxNode, 1885 pub(crate) syntax: SyntaxNode,
@@ -974,13 +1893,32 @@ impl Attr {
974 pub fn input(&self) -> Option<AttrInput> { support::child(&self.syntax) } 1893 pub fn input(&self) -> Option<AttrInput> { support::child(&self.syntax) }
975 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 1894 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
976} 1895}
977 1896/// Stores a list of lexer tokens and other `TokenTree`s.
1897/// It appears in attributes, macro_rules and macro call (foo!)
1898///
1899/// ```
1900/// macro_call! ❰ { my syntax here } ❱;
1901/// ```
1902///
1903/// [Reference](https://doc.rust-lang.org/reference/macros.html)
978#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1904#[derive(Debug, Clone, PartialEq, Eq, Hash)]
979pub struct TokenTree { 1905pub struct TokenTree {
980 pub(crate) syntax: SyntaxNode, 1906 pub(crate) syntax: SyntaxNode,
981} 1907}
982impl TokenTree {} 1908impl TokenTree {}
983 1909/// Generic lifetime, type and constants parameters list **declaration**.
1910///
1911/// ```
1912/// fn foo❰ <'a, 'b, T, U, const BAR: u64> ❱() {}
1913///
1914/// struct Baz❰ <T> ❱(T);
1915///
1916/// impl❰ <T> ❱ Bruh<T> {}
1917///
1918/// type Bruuh = for❰ <'a> ❱ fn(&'a str) -> &'a str;
1919/// ```
1920///
1921/// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
984#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1922#[derive(Debug, Clone, PartialEq, Eq, Hash)]
985pub struct TypeParamList { 1923pub struct TypeParamList {
986 pub(crate) syntax: SyntaxNode, 1924 pub(crate) syntax: SyntaxNode,
@@ -993,7 +1931,13 @@ impl TypeParamList {
993 pub fn const_params(&self) -> AstChildren<ConstParam> { support::children(&self.syntax) } 1931 pub fn const_params(&self) -> AstChildren<ConstParam> { support::children(&self.syntax) }
994 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } 1932 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
995} 1933}
996 1934/// Single type parameter **declaration**.
1935///
1936/// ```
1937/// fn foo<❰ K ❱, ❰ I ❱, ❰ E: Debug ❱, ❰ V = DefaultType ❱>() {}
1938/// ```
1939///
1940/// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
997#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1941#[derive(Debug, Clone, PartialEq, Eq, Hash)]
998pub struct TypeParam { 1942pub struct TypeParam {
999 pub(crate) syntax: SyntaxNode, 1943 pub(crate) syntax: SyntaxNode,
@@ -1005,7 +1949,12 @@ impl TypeParam {
1005 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } 1949 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
1006 pub fn default_type(&self) -> Option<TypeRef> { support::child(&self.syntax) } 1950 pub fn default_type(&self) -> Option<TypeRef> { support::child(&self.syntax) }
1007} 1951}
1008 1952/// Const generic parameter **declaration**.
1953/// ```
1954/// fn foo<T, U, ❰ const BAR: usize ❱, ❰ const BAZ: bool ❱>() {}
1955/// ```
1956///
1957/// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter)
1009#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1958#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1010pub struct ConstParam { 1959pub struct ConstParam {
1011 pub(crate) syntax: SyntaxNode, 1960 pub(crate) syntax: SyntaxNode,
@@ -1017,7 +1966,13 @@ impl ConstParam {
1017 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } 1966 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
1018 pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) } 1967 pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) }
1019} 1968}
1020 1969/// Lifetime parameter **declaration**.
1970///
1971/// ```
1972/// fn foo<❰ 'a ❱, ❰ 'b ❱, V, G, D>(bar: &'a str, baz: &'b mut str) {}
1973/// ```
1974///
1975/// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
1021#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1976#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1022pub struct LifetimeParam { 1977pub struct LifetimeParam {
1023 pub(crate) syntax: SyntaxNode, 1978 pub(crate) syntax: SyntaxNode,
@@ -1028,7 +1983,20 @@ impl LifetimeParam {
1028 support::token(&self.syntax, T![lifetime]) 1983 support::token(&self.syntax, T![lifetime])
1029 } 1984 }
1030} 1985}
1031 1986/// Type bound declaration clause.
1987///
1988/// ```
1989/// fn foo<T: ❰ ?Sized ❱ + ❰ Debug ❱>() {}
1990///
1991/// trait Bar<T>
1992/// where
1993/// T: ❰ Send ❱ + ❰ Sync ❱
1994/// {
1995/// type Baz: ❰ !Sync ❱ + ❰ Debug ❱ + ❰ ?const Add ❱;
1996/// }
1997/// ```
1998///
1999/// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html)
1032#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2000#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1033pub struct TypeBound { 2001pub struct TypeBound {
1034 pub(crate) syntax: SyntaxNode, 2002 pub(crate) syntax: SyntaxNode,
@@ -1040,7 +2008,21 @@ impl TypeBound {
1040 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } 2008 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
1041 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 2009 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
1042} 2010}
1043 2011/// Type bounds list.
2012///
2013/// ```
2014///
2015/// fn foo<T: ❰ ?Sized + Debug ❱>() {}
2016///
2017/// trait Bar<T>
2018/// where
2019/// T: ❰ Send + Sync ❱
2020/// {
2021/// type Baz: ❰ !Sync + Debug ❱;
2022/// }
2023/// ```
2024///
2025/// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html)
1044#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2026#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1045pub struct TypeBoundList { 2027pub struct TypeBoundList {
1046 pub(crate) syntax: SyntaxNode, 2028 pub(crate) syntax: SyntaxNode,
@@ -1048,7 +2030,18 @@ pub struct TypeBoundList {
1048impl TypeBoundList { 2030impl TypeBoundList {
1049 pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) } 2031 pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) }
1050} 2032}
1051 2033/// Single where predicate.
2034///
2035/// ```
2036/// trait Foo<'a, 'b, T>
2037/// where
2038/// ❰ 'a: 'b ❱,
2039/// ❰ T: IntoIterator ❱,
2040/// ❰ for<'c> <T as IntoIterator>::Item: Bar<'c> ❱
2041/// {}
2042/// ```
2043///
2044/// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses)
1052#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2045#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1053pub struct WherePred { 2046pub struct WherePred {
1054 pub(crate) syntax: SyntaxNode, 2047 pub(crate) syntax: SyntaxNode,
@@ -1060,7 +2053,14 @@ impl WherePred {
1060 } 2053 }
1061 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 2054 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
1062} 2055}
1063 2056/// Where clause.
2057///
2058/// ```
2059/// trait Foo<'a, T> ❰ where 'a: 'static, T: Debug ❱ {}
2060///
2061/// ```
2062///
2063/// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses)
1064#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2064#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1065pub struct WhereClause { 2065pub struct WhereClause {
1066 pub(crate) syntax: SyntaxNode, 2066 pub(crate) syntax: SyntaxNode,
@@ -1069,13 +2069,42 @@ impl WhereClause {
1069 pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) } 2069 pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) }
1070 pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) } 2070 pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) }
1071} 2071}
1072 2072/// Abi declaration.
2073/// Note: the abi string is optional.
2074///
2075/// ```
2076/// ❰ extern "C" ❱ {
2077/// fn foo() {}
2078/// }
2079///
2080/// type Bar = ❰ extern ❱ fn() -> u32;
2081///
2082/// type Baz = ❰ extern r#"stdcall"# ❱ fn() -> bool;
2083/// ```
2084///
2085/// - [Extern blocks reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
2086/// - [FFI function pointers reference](https://doc.rust-lang.org/reference/items/functions.html#functions)
1073#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2087#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1074pub struct Abi { 2088pub struct Abi {
1075 pub(crate) syntax: SyntaxNode, 2089 pub(crate) syntax: SyntaxNode,
1076} 2090}
1077impl Abi {} 2091impl Abi {}
1078 2092/// Expression statement.
2093///
2094/// ```
2095/// ❰ 42; ❱
2096/// ❰ foo(); ❱
2097/// ❰ (); ❱
2098/// ❰ {}; ❱
2099///
2100/// // constructions with trailing curly brace can omit the semicolon
2101/// // but only when there are satements immediately after them (this is important!)
2102/// ❰ if bool_cond { } ❱
2103/// ❰ loop {} ❱
2104/// ❰ somestatment; ❱
2105/// ```
2106///
2107/// [Reference](https://doc.rust-lang.org/reference/statements.html)
1079#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2108#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1080pub struct ExprStmt { 2109pub struct ExprStmt {
1081 pub(crate) syntax: SyntaxNode, 2110 pub(crate) syntax: SyntaxNode,
@@ -1085,7 +2114,16 @@ impl ExprStmt {
1085 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 2114 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
1086 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 2115 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
1087} 2116}
1088 2117/// Let statement.
2118///
2119/// ```
2120/// ❰ #[attr] let foo; ❱
2121/// ❰ let bar: u64; ❱
2122/// ❰ let baz = 42; ❱
2123/// ❰ let bruh: bool = true; ❱
2124/// ```
2125///
2126/// [Reference](https://doc.rust-lang.org/reference/statements.html#let-statements)
1089#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2127#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1090pub struct LetStmt { 2128pub struct LetStmt {
1091 pub(crate) syntax: SyntaxNode, 2129 pub(crate) syntax: SyntaxNode,
@@ -1099,7 +2137,18 @@ impl LetStmt {
1099 pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) } 2137 pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) }
1100 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 2138 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
1101} 2139}
1102 2140/// Condition of `if` or `while` expression.
2141///
2142/// ```
2143/// if ❰ true ❱ {}
2144/// if ❰ let Pat(foo) = bar ❱ {}
2145///
2146/// while ❰ true ❱ {}
2147/// while ❰ let Pat(baz) = bruh ❱ {}
2148/// ```
2149///
2150/// [If expression reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
2151/// [While expression reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
1103#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2152#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1104pub struct Condition { 2153pub struct Condition {
1105 pub(crate) syntax: SyntaxNode, 2154 pub(crate) syntax: SyntaxNode,
@@ -1110,20 +2159,18 @@ impl Condition {
1110 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } 2159 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
1111 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 2160 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
1112} 2161}
1113 2162/// Parameter list **declaration**.
1114#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2163///
1115pub struct Block { 2164/// ```
1116 pub(crate) syntax: SyntaxNode, 2165/// fn foo❰ (a: u32, b: bool) ❱ -> u32 {}
1117} 2166/// let bar = ❰ |a, b| ❱ {};
1118impl ast::AttrsOwner for Block {} 2167///
1119impl ast::ModuleItemOwner for Block {} 2168/// impl Baz {
1120impl Block { 2169/// fn bruh❰ (&self, a: u32) ❱ {}
1121 pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } 2170/// }
1122 pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } 2171/// ```
1123 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 2172///
1124 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 2173/// [Reference](https://doc.rust-lang.org/reference/items/functions.html)ocs to codegen script
1125}
1126
1127#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2174#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1128pub struct ParamList { 2175pub struct ParamList {
1129 pub(crate) syntax: SyntaxNode, 2176 pub(crate) syntax: SyntaxNode,
@@ -1134,7 +2181,19 @@ impl ParamList {
1134 pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) } 2181 pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
1135 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 2182 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
1136} 2183}
1137 2184/// Self parameter **declaration**.
2185///
2186/// ```
2187/// impl Bruh {
2188/// fn foo(❰ self ❱) {}
2189/// fn bar(❰ &self ❱) {}
2190/// fn baz(❰ &mut self ❱) {}
2191/// fn blah<'a>(❰ &'a self ❱) {}
2192/// fn blin(❰ self: Box<Self> ❱) {}
2193/// }
2194/// ```
2195///
2196/// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
1138#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2197#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1139pub struct SelfParam { 2198pub struct SelfParam {
1140 pub(crate) syntax: SyntaxNode, 2199 pub(crate) syntax: SyntaxNode,
@@ -1149,7 +2208,17 @@ impl SelfParam {
1149 } 2208 }
1150 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } 2209 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
1151} 2210}
1152 2211/// Parameter **declaration**.
2212///
2213/// ```
2214/// fn foo(❰ #[attr] Pat(bar): Pat(u32) ❱, ❰ #[attr] _: bool ❱) {}
2215///
2216/// extern "C" {
2217/// fn bar(❰ baz: u32 ❱, ❰ ... ❱) -> u32;
2218/// }
2219/// ```
2220///
2221/// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
1153#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2222#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1154pub struct Param { 2223pub struct Param {
1155 pub(crate) syntax: SyntaxNode, 2224 pub(crate) syntax: SyntaxNode,
@@ -1160,7 +2229,16 @@ impl Param {
1160 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } 2229 pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
1161 pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) } 2230 pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
1162} 2231}
1163 2232/// Use declaration.
2233///
2234/// ```
2235/// ❰ #[attr] pub use foo; ❱
2236/// ❰ use bar as baz; ❱
2237/// ❰ use bruh::{self, bruuh}; ❱
2238/// ❰ use { blin::blen, blah::* };
2239/// ```
2240///
2241/// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
1164#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2242#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1165pub struct UseItem { 2243pub struct UseItem {
1166 pub(crate) syntax: SyntaxNode, 2244 pub(crate) syntax: SyntaxNode,
@@ -1171,7 +2249,16 @@ impl UseItem {
1171 pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) } 2249 pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
1172 pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) } 2250 pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
1173} 2251}
1174 2252/// Use tree.
2253///
2254/// ```
2255/// pub use ❰ foo::❰ * ❱ ❱;
2256/// use ❰ bar as baz ❱;
2257/// use ❰ bruh::bruuh::{ ❰ self ❱, ❰ blin ❱ } ❱;
2258/// use ❰ { ❰ blin::blen ❱ } ❱
2259/// ```
2260///
2261/// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
1175#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2262#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1176pub struct UseTree { 2263pub struct UseTree {
1177 pub(crate) syntax: SyntaxNode, 2264 pub(crate) syntax: SyntaxNode,
@@ -1182,7 +2269,16 @@ impl UseTree {
1182 pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) } 2269 pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
1183 pub fn alias(&self) -> Option<Alias> { support::child(&self.syntax) } 2270 pub fn alias(&self) -> Option<Alias> { support::child(&self.syntax) }
1184} 2271}
1185 2272/// Item alias.
2273/// Note: this is not the type alias.
2274///
2275/// ```
2276/// use foo ❰ as bar ❱;
2277/// use baz::{bruh ❰ as _ ❱};
2278/// extern crate bruuh ❰ as blin ❱;
2279/// ```
2280///
2281/// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
1186#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2282#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1187pub struct Alias { 2283pub struct Alias {
1188 pub(crate) syntax: SyntaxNode, 2284 pub(crate) syntax: SyntaxNode,
@@ -1191,7 +2287,14 @@ impl ast::NameOwner for Alias {}
1191impl Alias { 2287impl Alias {
1192 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } 2288 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
1193} 2289}
1194 2290/// Sublist of use trees.
2291///
2292/// ```
2293/// use bruh::bruuh::❰ { ❰ self ❱, ❰ blin ❱ } ❱;
2294/// use ❰ { blin::blen::❰ {} ❱ } ❱
2295/// ```
2296///
2297/// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
1195#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2298#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1196pub struct UseTreeList { 2299pub struct UseTreeList {
1197 pub(crate) syntax: SyntaxNode, 2300 pub(crate) syntax: SyntaxNode,
@@ -1201,7 +2304,14 @@ impl UseTreeList {
1201 pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) } 2304 pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
1202 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 2305 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
1203} 2306}
1204 2307/// Extern crate item.
2308///
2309/// ```
2310/// ❰ #[attr] pub extern crate foo; ❱
2311/// ❰ extern crate self as bar; ❱
2312/// ```
2313///
2314/// [Reference](https://doc.rust-lang.org/reference/items/extern-crates.html)
1205#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2315#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1206pub struct ExternCrateItem { 2316pub struct ExternCrateItem {
1207 pub(crate) syntax: SyntaxNode, 2317 pub(crate) syntax: SyntaxNode,
@@ -1214,7 +2324,13 @@ impl ExternCrateItem {
1214 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } 2324 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
1215 pub fn alias(&self) -> Option<Alias> { support::child(&self.syntax) } 2325 pub fn alias(&self) -> Option<Alias> { support::child(&self.syntax) }
1216} 2326}
1217 2327/// Call site arguments list.
2328///
2329/// ```
2330/// foo::<T, U>❰ (42, true) ❱;
2331/// ```
2332///
2333/// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
1218#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2334#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1219pub struct ArgList { 2335pub struct ArgList {
1220 pub(crate) syntax: SyntaxNode, 2336 pub(crate) syntax: SyntaxNode,
@@ -1224,16 +2340,41 @@ impl ArgList {
1224 pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) } 2340 pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
1225 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 2341 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
1226} 2342}
1227 2343/// Path to a symbol. Includes single identifier names and elaborate paths with
2344/// generic parameters.
2345///
2346/// ```
2347/// (0..10).❰ ❰ collect ❱ ::<Vec<_>> ❱();
2348/// ❰ ❰ ❰ Vec ❱ ::<u8> ❱ ::with_capacity ❱(1024);
2349/// ❰ ❰ <❰ Foo ❱ as ❰ ❰ bar ❱ ::Bar ❱> ❱ ::baz ❱();
2350/// ❰ ❰ <❰ bruh ❱> ❱ ::bruuh ❱();
2351/// ```
2352///
2353/// [Reference](https://doc.rust-lang.org/reference/paths.html)
1228#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2354#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1229pub struct Path { 2355pub struct Path {
1230 pub(crate) syntax: SyntaxNode, 2356 pub(crate) syntax: SyntaxNode,
1231} 2357}
1232impl Path { 2358impl Path {
1233 pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) } 2359 pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
2360 pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
1234 pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) } 2361 pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
1235} 2362}
1236 2363/// Segment of the path to a symbol.
2364/// Only path segment of an absolute path holds the `::` token,
2365/// all other `::` tokens that connect path segments reside under `Path` itself.`
2366///
2367/// ```
2368/// (0..10).❰ collect ❱ :: ❰ <Vec<_>> ❱();
2369/// ❰ Vec ❱ :: ❰ <u8> ❱ :: ❰ with_capacity ❱(1024);
2370/// ❰ <❰ Foo ❱ as ❰ bar ❱ :: ❰ Bar ❱> ❱ :: ❰ baz ❱();
2371/// ❰ <❰ bruh ❱> ❱ :: ❰ bruuh ❱();
2372///
2373/// // Note that only in this case `::` token is inlcuded:
2374/// ❰ ::foo ❱;
2375/// ```
2376///
2377/// [Reference](https://doc.rust-lang.org/reference/paths.html)
1237#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2378#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1238pub struct PathSegment { 2379pub struct PathSegment {
1239 pub(crate) syntax: SyntaxNode, 2380 pub(crate) syntax: SyntaxNode,
@@ -1251,7 +2392,15 @@ impl PathSegment {
1251 pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) } 2392 pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
1252 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } 2393 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
1253} 2394}
1254 2395/// List of type arguments that are passed at generic instantiation site.
2396///
2397/// ```
2398/// type _ = Foo ❰ ::<'a, u64, Item = Bar, 42, {true}> ❱::Bar;
2399///
2400/// Vec❰ ::<bool> ❱::();
2401/// ```
2402///
2403/// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
1255#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2404#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1256pub struct TypeArgList { 2405pub struct TypeArgList {
1257 pub(crate) syntax: SyntaxNode, 2406 pub(crate) syntax: SyntaxNode,
@@ -1266,7 +2415,13 @@ impl TypeArgList {
1266 pub fn const_args(&self) -> AstChildren<ConstArg> { support::children(&self.syntax) } 2415 pub fn const_args(&self) -> AstChildren<ConstArg> { support::children(&self.syntax) }
1267 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } 2416 pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
1268} 2417}
1269 2418/// Type argument that is passed at generic instantiation site.
2419///
2420/// ```
2421/// type _ = Foo::<'a, ❰ u64 ❱, ❰ bool ❱, Item = Bar, 42>::Baz;
2422/// ```
2423///
2424/// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
1270#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2425#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1271pub struct TypeArg { 2426pub struct TypeArg {
1272 pub(crate) syntax: SyntaxNode, 2427 pub(crate) syntax: SyntaxNode,
@@ -1274,7 +2429,13 @@ pub struct TypeArg {
1274impl TypeArg { 2429impl TypeArg {
1275 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 2430 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
1276} 2431}
1277 2432/// Associated type argument that is passed at generic instantiation site.
2433/// ```
2434/// type Foo = Bar::<'a, u64, bool, ❰ Item = Baz ❱, 42>::Bruh;
2435///
2436/// trait Bruh<T>: Iterator<❰ Item: Debug ❱> {}
2437/// ```
2438///
1278#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2439#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1279pub struct AssocTypeArg { 2440pub struct AssocTypeArg {
1280 pub(crate) syntax: SyntaxNode, 2441 pub(crate) syntax: SyntaxNode,
@@ -1285,7 +2446,15 @@ impl AssocTypeArg {
1285 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } 2446 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
1286 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 2447 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
1287} 2448}
1288 2449/// Lifetime argument that is passed at generic instantiation site.
2450///
2451/// ```
2452/// fn foo<'a>(s: &'a str) {
2453/// bar::<❰ 'a ❱>(s);
2454/// }
2455/// ```
2456///
2457/// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
1289#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2458#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1290pub struct LifetimeArg { 2459pub struct LifetimeArg {
1291 pub(crate) syntax: SyntaxNode, 2460 pub(crate) syntax: SyntaxNode,
@@ -1295,24 +2464,41 @@ impl LifetimeArg {
1295 support::token(&self.syntax, T![lifetime]) 2464 support::token(&self.syntax, T![lifetime])
1296 } 2465 }
1297} 2466}
1298 2467/// Constant value argument that is passed at generic instantiation site.
2468///
2469/// ```
2470/// foo::<u32, ❰ { true } ❱>();
2471///
2472/// bar::<❰ { 2 + 2} ❱>();
2473/// ```
2474///
2475/// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter)
1299#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2476#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1300pub struct ConstArg { 2477pub struct ConstArg {
1301 pub(crate) syntax: SyntaxNode, 2478 pub(crate) syntax: SyntaxNode,
1302} 2479}
1303impl ConstArg { 2480impl ConstArg {
1304 pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) } 2481 pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
1305 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
1306 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } 2482 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
1307} 2483}
1308 2484/// FIXME: (@edwin0cheng) Remove it to use ItemList instead
2485/// https://github.com/rust-analyzer/rust-analyzer/pull/4083#discussion_r422666243
2486///
2487/// [Reference](https://doc.rust-lang.org/reference/macros.html)
1309#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2488#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1310pub struct MacroItems { 2489pub struct MacroItems {
1311 pub(crate) syntax: SyntaxNode, 2490 pub(crate) syntax: SyntaxNode,
1312} 2491}
1313impl ast::ModuleItemOwner for MacroItems {} 2492impl ast::ModuleItemOwner for MacroItems {}
1314impl MacroItems {} 2493impl MacroItems {}
1315 2494/// FIXME: (@edwin0cheng) add some documentation here. As per the writing
2495/// of this comment this ast node is not used.
2496///
2497/// ```
2498/// // FIXME: example here
2499/// ```
2500///
2501/// [Reference](https://doc.rust-lang.org/reference/macros.html)
1316#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2502#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1317pub struct MacroStmts { 2503pub struct MacroStmts {
1318 pub(crate) syntax: SyntaxNode, 2504 pub(crate) syntax: SyntaxNode,
@@ -1321,7 +2507,18 @@ impl MacroStmts {
1321 pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } 2507 pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
1322 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 2508 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
1323} 2509}
1324 2510/// List of items in an extern block.
2511///
2512/// ```
2513/// extern "C" ❰
2514/// {
2515/// fn foo();
2516/// static var: u32;
2517/// }
2518/// ❱
2519/// ```
2520///
2521/// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
1325#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2522#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1326pub struct ExternItemList { 2523pub struct ExternItemList {
1327 pub(crate) syntax: SyntaxNode, 2524 pub(crate) syntax: SyntaxNode,
@@ -1332,7 +2529,18 @@ impl ExternItemList {
1332 pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) } 2529 pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) }
1333 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 2530 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
1334} 2531}
1335 2532/// Extern block.
2533///
2534/// ```
2535/// ❰
2536/// extern "C" {
2537/// fn foo();
2538/// }
2539/// ❱
2540///
2541/// ```
2542///
2543/// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
1336#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2544#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1337pub struct ExternBlock { 2545pub struct ExternBlock {
1338 pub(crate) syntax: SyntaxNode, 2546 pub(crate) syntax: SyntaxNode,
@@ -1341,7 +2549,15 @@ impl ExternBlock {
1341 pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) } 2549 pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
1342 pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) } 2550 pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) }
1343} 2551}
1344 2552/// Meta item in an attribute.
2553///
2554/// ```
2555/// #[❰ bar::baz = "42" ❱]
2556/// #[❰ bruh(bruuh("true")) ❱]
2557/// struct Foo;
2558/// ```
2559///
2560/// [Reference](https://doc.rust-lang.org/reference/attributes.html?highlight=meta,item#meta-item-attribute-syntax)
1345#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2561#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1346pub struct MetaItem { 2562pub struct MetaItem {
1347 pub(crate) syntax: SyntaxNode, 2563 pub(crate) syntax: SyntaxNode,
@@ -1352,7 +2568,15 @@ impl MetaItem {
1352 pub fn attr_input(&self) -> Option<AttrInput> { support::child(&self.syntax) } 2568 pub fn attr_input(&self) -> Option<AttrInput> { support::child(&self.syntax) }
1353 pub fn nested_meta_items(&self) -> AstChildren<MetaItem> { support::children(&self.syntax) } 2569 pub fn nested_meta_items(&self) -> AstChildren<MetaItem> { support::children(&self.syntax) }
1354} 2570}
1355 2571/// Macro 2.0 definition.
2572/// Their syntax is still WIP by rustc team...
2573/// ```
2574/// ❰
2575/// macro foo { }
2576/// ❱
2577/// ```
2578///
2579/// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/1584-macros.md)
1356#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2580#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1357pub struct MacroDef { 2581pub struct MacroDef {
1358 pub(crate) syntax: SyntaxNode, 2582 pub(crate) syntax: SyntaxNode,
@@ -1361,7 +2585,7 @@ impl MacroDef {
1361 pub fn name(&self) -> Option<Name> { support::child(&self.syntax) } 2585 pub fn name(&self) -> Option<Name> { support::child(&self.syntax) }
1362 pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } 2586 pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
1363} 2587}
1364 2588/// Any kind of nominal type definition.
1365#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2589#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1366pub enum NominalDef { 2590pub enum NominalDef {
1367 StructDef(StructDef), 2591 StructDef(StructDef),
@@ -1371,14 +2595,14 @@ pub enum NominalDef {
1371impl ast::NameOwner for NominalDef {} 2595impl ast::NameOwner for NominalDef {}
1372impl ast::TypeParamsOwner for NominalDef {} 2596impl ast::TypeParamsOwner for NominalDef {}
1373impl ast::AttrsOwner for NominalDef {} 2597impl ast::AttrsOwner for NominalDef {}
1374 2598/// Any kind of **declared** generic parameter
1375#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2599#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1376pub enum GenericParam { 2600pub enum GenericParam {
1377 LifetimeParam(LifetimeParam), 2601 LifetimeParam(LifetimeParam),
1378 TypeParam(TypeParam), 2602 TypeParam(TypeParam),
1379 ConstParam(ConstParam), 2603 ConstParam(ConstParam),
1380} 2604}
1381 2605/// Any kind of generic argument passed at instantiation site
1382#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2606#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1383pub enum GenericArg { 2607pub enum GenericArg {
1384 LifetimeArg(LifetimeArg), 2608 LifetimeArg(LifetimeArg),
@@ -1386,7 +2610,7 @@ pub enum GenericArg {
1386 ConstArg(ConstArg), 2610 ConstArg(ConstArg),
1387 AssocTypeArg(AssocTypeArg), 2611 AssocTypeArg(AssocTypeArg),
1388} 2612}
1389 2613/// Any kind of construct valid in type context
1390#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2614#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1391pub enum TypeRef { 2615pub enum TypeRef {
1392 ParenType(ParenType), 2616 ParenType(ParenType),
@@ -1403,7 +2627,7 @@ pub enum TypeRef {
1403 ImplTraitType(ImplTraitType), 2627 ImplTraitType(ImplTraitType),
1404 DynTraitType(DynTraitType), 2628 DynTraitType(DynTraitType),
1405} 2629}
1406 2630/// Any kind of top-level item that may appear in a module
1407#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2631#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1408pub enum ModuleItem { 2632pub enum ModuleItem {
1409 StructDef(StructDef), 2633 StructDef(StructDef),
@@ -1424,16 +2648,20 @@ pub enum ModuleItem {
1424impl ast::NameOwner for ModuleItem {} 2648impl ast::NameOwner for ModuleItem {}
1425impl ast::AttrsOwner for ModuleItem {} 2649impl ast::AttrsOwner for ModuleItem {}
1426impl ast::VisibilityOwner for ModuleItem {} 2650impl ast::VisibilityOwner for ModuleItem {}
1427 2651/// Any kind of item that may appear in an impl block
2652///
2653/// // FIXME: impl blocks can also contain MacroCall
1428#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2654#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1429pub enum ImplItem { 2655pub enum AssocItem {
1430 FnDef(FnDef), 2656 FnDef(FnDef),
1431 TypeAliasDef(TypeAliasDef), 2657 TypeAliasDef(TypeAliasDef),
1432 ConstDef(ConstDef), 2658 ConstDef(ConstDef),
1433} 2659}
1434impl ast::NameOwner for ImplItem {} 2660impl ast::NameOwner for AssocItem {}
1435impl ast::AttrsOwner for ImplItem {} 2661impl ast::AttrsOwner for AssocItem {}
1436 2662/// Any kind of item that may appear in an extern block
2663///
2664/// // FIXME: extern blocks can also contain MacroCall
1437#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2665#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1438pub enum ExternItem { 2666pub enum ExternItem {
1439 FnDef(FnDef), 2667 FnDef(FnDef),
@@ -1442,7 +2670,7 @@ pub enum ExternItem {
1442impl ast::NameOwner for ExternItem {} 2670impl ast::NameOwner for ExternItem {}
1443impl ast::AttrsOwner for ExternItem {} 2671impl ast::AttrsOwner for ExternItem {}
1444impl ast::VisibilityOwner for ExternItem {} 2672impl ast::VisibilityOwner for ExternItem {}
1445 2673/// Any kind of expression
1446#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2674#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1447pub enum Expr { 2675pub enum Expr {
1448 TupleExpr(TupleExpr), 2676 TupleExpr(TupleExpr),
@@ -1467,6 +2695,7 @@ pub enum Expr {
1467 FieldExpr(FieldExpr), 2695 FieldExpr(FieldExpr),
1468 AwaitExpr(AwaitExpr), 2696 AwaitExpr(AwaitExpr),
1469 TryExpr(TryExpr), 2697 TryExpr(TryExpr),
2698 EffectExpr(EffectExpr),
1470 CastExpr(CastExpr), 2699 CastExpr(CastExpr),
1471 RefExpr(RefExpr), 2700 RefExpr(RefExpr),
1472 PrefixExpr(PrefixExpr), 2701 PrefixExpr(PrefixExpr),
@@ -1477,7 +2706,7 @@ pub enum Expr {
1477 BoxExpr(BoxExpr), 2706 BoxExpr(BoxExpr),
1478} 2707}
1479impl ast::AttrsOwner for Expr {} 2708impl ast::AttrsOwner for Expr {}
1480 2709/// Any kind of pattern
1481#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2710#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1482pub enum Pat { 2711pub enum Pat {
1483 OrPat(OrPat), 2712 OrPat(OrPat),
@@ -1496,25 +2725,28 @@ pub enum Pat {
1496 LiteralPat(LiteralPat), 2725 LiteralPat(LiteralPat),
1497 MacroPat(MacroPat), 2726 MacroPat(MacroPat),
1498} 2727}
1499 2728/// Any kind of pattern that appears directly inside of the curly
2729/// braces of a record pattern
1500#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2730#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1501pub enum RecordInnerPat { 2731pub enum RecordInnerPat {
1502 RecordFieldPat(RecordFieldPat), 2732 RecordFieldPat(RecordFieldPat),
1503 BindPat(BindPat), 2733 BindPat(BindPat),
1504} 2734}
1505 2735/// Any kind of input to an attribute
1506#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2736#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1507pub enum AttrInput { 2737pub enum AttrInput {
1508 Literal(Literal), 2738 Literal(Literal),
1509 TokenTree(TokenTree), 2739 TokenTree(TokenTree),
1510} 2740}
1511 2741/// Any kind of statement
2742/// Note: there are no empty statements, these are just represented as
2743/// bare semicolons without a dedicated statement ast node.
1512#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2744#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1513pub enum Stmt { 2745pub enum Stmt {
1514 LetStmt(LetStmt), 2746 LetStmt(LetStmt),
1515 ExprStmt(ExprStmt), 2747 ExprStmt(ExprStmt),
1516} 2748}
1517 2749/// Any kind of fields list (record or tuple field lists)
1518#[derive(Debug, Clone, PartialEq, Eq, Hash)] 2750#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1519pub enum FieldDefList { 2751pub enum FieldDefList {
1520 RecordFieldDefList(RecordFieldDefList), 2752 RecordFieldDefList(RecordFieldDefList),
@@ -1949,6 +3181,17 @@ impl AstNode for LoopExpr {
1949 } 3181 }
1950 fn syntax(&self) -> &SyntaxNode { &self.syntax } 3182 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1951} 3183}
3184impl AstNode for EffectExpr {
3185 fn can_cast(kind: SyntaxKind) -> bool { kind == EFFECT_EXPR }
3186 fn cast(syntax: SyntaxNode) -> Option<Self> {
3187 if Self::can_cast(syntax.kind()) {
3188 Some(Self { syntax })
3189 } else {
3190 None
3191 }
3192 }
3193 fn syntax(&self) -> &SyntaxNode { &self.syntax }
3194}
1952impl AstNode for ForExpr { 3195impl AstNode for ForExpr {
1953 fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR } 3196 fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR }
1954 fn cast(syntax: SyntaxNode) -> Option<Self> { 3197 fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2631,17 +3874,6 @@ impl AstNode for Condition {
2631 } 3874 }
2632 fn syntax(&self) -> &SyntaxNode { &self.syntax } 3875 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2633} 3876}
2634impl AstNode for Block {
2635 fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK }
2636 fn cast(syntax: SyntaxNode) -> Option<Self> {
2637 if Self::can_cast(syntax.kind()) {
2638 Some(Self { syntax })
2639 } else {
2640 None
2641 }
2642 }
2643 fn syntax(&self) -> &SyntaxNode { &self.syntax }
2644}
2645impl AstNode for ParamList { 3877impl AstNode for ParamList {
2646 fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST } 3878 fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
2647 fn cast(syntax: SyntaxNode) -> Option<Self> { 3879 fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3163,16 +4395,16 @@ impl AstNode for ModuleItem {
3163 } 4395 }
3164 } 4396 }
3165} 4397}
3166impl From<FnDef> for ImplItem { 4398impl From<FnDef> for AssocItem {
3167 fn from(node: FnDef) -> ImplItem { ImplItem::FnDef(node) } 4399 fn from(node: FnDef) -> AssocItem { AssocItem::FnDef(node) }
3168} 4400}
3169impl From<TypeAliasDef> for ImplItem { 4401impl From<TypeAliasDef> for AssocItem {
3170 fn from(node: TypeAliasDef) -> ImplItem { ImplItem::TypeAliasDef(node) } 4402 fn from(node: TypeAliasDef) -> AssocItem { AssocItem::TypeAliasDef(node) }
3171} 4403}
3172impl From<ConstDef> for ImplItem { 4404impl From<ConstDef> for AssocItem {
3173 fn from(node: ConstDef) -> ImplItem { ImplItem::ConstDef(node) } 4405 fn from(node: ConstDef) -> AssocItem { AssocItem::ConstDef(node) }
3174} 4406}
3175impl AstNode for ImplItem { 4407impl AstNode for AssocItem {
3176 fn can_cast(kind: SyntaxKind) -> bool { 4408 fn can_cast(kind: SyntaxKind) -> bool {
3177 match kind { 4409 match kind {
3178 FN_DEF | TYPE_ALIAS_DEF | CONST_DEF => true, 4410 FN_DEF | TYPE_ALIAS_DEF | CONST_DEF => true,
@@ -3181,18 +4413,18 @@ impl AstNode for ImplItem {
3181 } 4413 }
3182 fn cast(syntax: SyntaxNode) -> Option<Self> { 4414 fn cast(syntax: SyntaxNode) -> Option<Self> {
3183 let res = match syntax.kind() { 4415 let res = match syntax.kind() {
3184 FN_DEF => ImplItem::FnDef(FnDef { syntax }), 4416 FN_DEF => AssocItem::FnDef(FnDef { syntax }),
3185 TYPE_ALIAS_DEF => ImplItem::TypeAliasDef(TypeAliasDef { syntax }), 4417 TYPE_ALIAS_DEF => AssocItem::TypeAliasDef(TypeAliasDef { syntax }),
3186 CONST_DEF => ImplItem::ConstDef(ConstDef { syntax }), 4418 CONST_DEF => AssocItem::ConstDef(ConstDef { syntax }),
3187 _ => return None, 4419 _ => return None,
3188 }; 4420 };
3189 Some(res) 4421 Some(res)
3190 } 4422 }
3191 fn syntax(&self) -> &SyntaxNode { 4423 fn syntax(&self) -> &SyntaxNode {
3192 match self { 4424 match self {
3193 ImplItem::FnDef(it) => &it.syntax, 4425 AssocItem::FnDef(it) => &it.syntax,
3194 ImplItem::TypeAliasDef(it) => &it.syntax, 4426 AssocItem::TypeAliasDef(it) => &it.syntax,
3195 ImplItem::ConstDef(it) => &it.syntax, 4427 AssocItem::ConstDef(it) => &it.syntax,
3196 } 4428 }
3197 } 4429 }
3198} 4430}
@@ -3290,6 +4522,9 @@ impl From<AwaitExpr> for Expr {
3290impl From<TryExpr> for Expr { 4522impl From<TryExpr> for Expr {
3291 fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) } 4523 fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
3292} 4524}
4525impl From<EffectExpr> for Expr {
4526 fn from(node: EffectExpr) -> Expr { Expr::EffectExpr(node) }
4527}
3293impl From<CastExpr> for Expr { 4528impl From<CastExpr> for Expr {
3294 fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) } 4529 fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) }
3295} 4530}
@@ -3320,8 +4555,10 @@ impl AstNode for Expr {
3320 TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR 4555 TUPLE_EXPR | ARRAY_EXPR | PAREN_EXPR | PATH_EXPR | LAMBDA_EXPR | IF_EXPR
3321 | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL 4556 | LOOP_EXPR | FOR_EXPR | WHILE_EXPR | CONTINUE_EXPR | BREAK_EXPR | LABEL
3322 | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR 4557 | BLOCK_EXPR | RETURN_EXPR | MATCH_EXPR | RECORD_LIT | CALL_EXPR | INDEX_EXPR
3323 | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | CAST_EXPR | REF_EXPR 4558 | METHOD_CALL_EXPR | FIELD_EXPR | AWAIT_EXPR | TRY_EXPR | EFFECT_EXPR | CAST_EXPR
3324 | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL | BOX_EXPR => true, 4559 | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR | LITERAL | MACRO_CALL | BOX_EXPR => {
4560 true
4561 }
3325 _ => false, 4562 _ => false,
3326 } 4563 }
3327 } 4564 }
@@ -3349,6 +4586,7 @@ impl AstNode for Expr {
3349 FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }), 4586 FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
3350 AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }), 4587 AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
3351 TRY_EXPR => Expr::TryExpr(TryExpr { syntax }), 4588 TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
4589 EFFECT_EXPR => Expr::EffectExpr(EffectExpr { syntax }),
3352 CAST_EXPR => Expr::CastExpr(CastExpr { syntax }), 4590 CAST_EXPR => Expr::CastExpr(CastExpr { syntax }),
3353 REF_EXPR => Expr::RefExpr(RefExpr { syntax }), 4591 REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
3354 PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }), 4592 PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
@@ -3385,6 +4623,7 @@ impl AstNode for Expr {
3385 Expr::FieldExpr(it) => &it.syntax, 4623 Expr::FieldExpr(it) => &it.syntax,
3386 Expr::AwaitExpr(it) => &it.syntax, 4624 Expr::AwaitExpr(it) => &it.syntax,
3387 Expr::TryExpr(it) => &it.syntax, 4625 Expr::TryExpr(it) => &it.syntax,
4626 Expr::EffectExpr(it) => &it.syntax,
3388 Expr::CastExpr(it) => &it.syntax, 4627 Expr::CastExpr(it) => &it.syntax,
3389 Expr::RefExpr(it) => &it.syntax, 4628 Expr::RefExpr(it) => &it.syntax,
3390 Expr::PrefixExpr(it) => &it.syntax, 4629 Expr::PrefixExpr(it) => &it.syntax,
@@ -3630,7 +4869,7 @@ impl std::fmt::Display for ModuleItem {
3630 std::fmt::Display::fmt(self.syntax(), f) 4869 std::fmt::Display::fmt(self.syntax(), f)
3631 } 4870 }
3632} 4871}
3633impl std::fmt::Display for ImplItem { 4872impl std::fmt::Display for AssocItem {
3634 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 4873 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3635 std::fmt::Display::fmt(self.syntax(), f) 4874 std::fmt::Display::fmt(self.syntax(), f)
3636 } 4875 }
@@ -3865,6 +5104,11 @@ impl std::fmt::Display for LoopExpr {
3865 std::fmt::Display::fmt(self.syntax(), f) 5104 std::fmt::Display::fmt(self.syntax(), f)
3866 } 5105 }
3867} 5106}
5107impl std::fmt::Display for EffectExpr {
5108 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
5109 std::fmt::Display::fmt(self.syntax(), f)
5110 }
5111}
3868impl std::fmt::Display for ForExpr { 5112impl std::fmt::Display for ForExpr {
3869 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 5113 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3870 std::fmt::Display::fmt(self.syntax(), f) 5114 std::fmt::Display::fmt(self.syntax(), f)
@@ -4175,11 +5419,6 @@ impl std::fmt::Display for Condition {
4175 std::fmt::Display::fmt(self.syntax(), f) 5419 std::fmt::Display::fmt(self.syntax(), f)
4176 } 5420 }
4177} 5421}
4178impl std::fmt::Display for Block {
4179 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4180 std::fmt::Display::fmt(self.syntax(), f)
4181 }
4182}
4183impl std::fmt::Display for ParamList { 5422impl std::fmt::Display for ParamList {
4184 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 5423 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4185 std::fmt::Display::fmt(self.syntax(), f) 5424 std::fmt::Display::fmt(self.syntax(), f)
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index 492088353..da0eb0926 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -1,5 +1,9 @@
1//! This module contains free-standing functions for creating AST fragments out 1//! This module contains free-standing functions for creating AST fragments out
2//! of smaller pieces. 2//! of smaller pieces.
3//!
4//! Note that all functions here intended to be stupid constructors, which just
5//! assemble a finish node from immediate children. If you want to do something
6//! smarter than that, it probably doesn't belong in this module.
3use itertools::Itertools; 7use itertools::Itertools;
4use stdx::format_to; 8use stdx::format_to;
5 9
@@ -13,6 +17,10 @@ pub fn name_ref(text: &str) -> ast::NameRef {
13 ast_from_text(&format!("fn f() {{ {}; }}", text)) 17 ast_from_text(&format!("fn f() {{ {}; }}", text))
14} 18}
15 19
20pub fn type_ref(text: &str) -> ast::TypeRef {
21 ast_from_text(&format!("impl {} for D {{}};", text))
22}
23
16pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment { 24pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment {
17 ast_from_text(&format!("use {};", name_ref)) 25 ast_from_text(&format!("use {};", name_ref))
18} 26}
@@ -82,14 +90,6 @@ pub fn block_expr(
82 ast_from_text(&format!("fn f() {}", buf)) 90 ast_from_text(&format!("fn f() {}", buf))
83} 91}
84 92
85pub fn block_from_expr(e: ast::Expr) -> ast::Block {
86 return from_text(&format!("{{ {} }}", e));
87
88 fn from_text(text: &str) -> ast::Block {
89 ast_from_text(&format!("fn f() {}", text))
90 }
91}
92
93pub fn expr_unit() -> ast::Expr { 93pub fn expr_unit() -> ast::Expr {
94 expr_from_text("()") 94 expr_from_text("()")
95} 95}
@@ -99,6 +99,9 @@ pub fn expr_empty_block() -> ast::Expr {
99pub fn expr_unimplemented() -> ast::Expr { 99pub fn expr_unimplemented() -> ast::Expr {
100 expr_from_text("unimplemented!()") 100 expr_from_text("unimplemented!()")
101} 101}
102pub fn expr_unreachable() -> ast::Expr {
103 expr_from_text("unreachable!()")
104}
102pub fn expr_todo() -> ast::Expr { 105pub fn expr_todo() -> ast::Expr {
103 expr_from_text("todo!()") 106 expr_from_text("todo!()")
104} 107}
@@ -268,10 +271,6 @@ pub fn token(kind: SyntaxKind) -> SyntaxToken {
268 .unwrap_or_else(|| panic!("unhandled token: {:?}", kind)) 271 .unwrap_or_else(|| panic!("unhandled token: {:?}", kind))
269} 272}
270 273
271pub fn unreachable_macro_call() -> ast::MacroCall {
272 ast_from_text(&format!("unreachable!()"))
273}
274
275pub fn param(name: String, ty: String) -> ast::Param { 274pub fn param(name: String, ty: String) -> ast::Param {
276 ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty)) 275 ast_from_text(&format!("fn f({}: {}) {{ }}", name, ty))
277} 276}
@@ -281,7 +280,12 @@ pub fn param_list(pats: impl IntoIterator<Item = ast::Param>) -> ast::ParamList
281 ast_from_text(&format!("fn f({}) {{ }}", args)) 280 ast_from_text(&format!("fn f({}) {{ }}", args))
282} 281}
283 282
283pub fn visibility_pub_crate() -> ast::Visibility {
284 ast_from_text("pub(crate) struct S")
285}
286
284pub fn fn_def( 287pub fn fn_def(
288 visibility: Option<ast::Visibility>,
285 fn_name: ast::Name, 289 fn_name: ast::Name,
286 type_params: Option<ast::TypeParamList>, 290 type_params: Option<ast::TypeParamList>,
287 params: ast::ParamList, 291 params: ast::ParamList,
@@ -289,26 +293,21 @@ pub fn fn_def(
289) -> ast::FnDef { 293) -> ast::FnDef {
290 let type_params = 294 let type_params =
291 if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() }; 295 if let Some(type_params) = type_params { format!("<{}>", type_params) } else { "".into() };
292 ast_from_text(&format!("fn {}{}{} {}", fn_name, type_params, params, body)) 296 let visibility = match visibility {
293} 297 None => String::new(),
294 298 Some(it) => format!("{} ", it),
295pub fn add_leading_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile { 299 };
296 let newlines = "\n".repeat(amount_of_newlines); 300 ast_from_text(&format!("{}fn {}{}{} {}", visibility, fn_name, type_params, params, body))
297 ast_from_text(&format!("{}{}", newlines, t.syntax()))
298}
299
300pub fn add_trailing_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile {
301 let newlines = "\n".repeat(amount_of_newlines);
302 ast_from_text(&format!("{}{}", t.syntax(), newlines))
303}
304
305pub fn add_pub_crate_modifier(fn_def: ast::FnDef) -> ast::FnDef {
306 ast_from_text(&format!("pub(crate) {}", fn_def))
307} 301}
308 302
309fn ast_from_text<N: AstNode>(text: &str) -> N { 303fn ast_from_text<N: AstNode>(text: &str) -> N {
310 let parse = SourceFile::parse(text); 304 let parse = SourceFile::parse(text);
311 let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); 305 let node = match parse.tree().syntax().descendants().find_map(N::cast) {
306 Some(it) => it,
307 None => {
308 panic!("Failed to make ast node `{}` from text {}", std::any::type_name::<N>(), text)
309 }
310 };
312 let node = node.syntax().clone(); 311 let node = node.syntax().clone();
313 let node = unroot(node); 312 let node = unroot(node);
314 let node = N::cast(node).unwrap(); 313 let node = N::cast(node).unwrap();
diff --git a/crates/ra_syntax/src/fuzz.rs b/crates/ra_syntax/src/fuzz.rs
index 10fbe3176..39f9b12ab 100644
--- a/crates/ra_syntax/src/fuzz.rs
+++ b/crates/ra_syntax/src/fuzz.rs
@@ -5,7 +5,7 @@ use std::{
5 str::{self, FromStr}, 5 str::{self, FromStr},
6}; 6};
7 7
8use ra_text_edit::AtomTextEdit; 8use ra_text_edit::Indel;
9 9
10use crate::{validation, AstNode, SourceFile, TextRange}; 10use crate::{validation, AstNode, SourceFile, TextRange};
11 11
@@ -22,7 +22,7 @@ pub fn check_parser(text: &str) {
22#[derive(Debug, Clone)] 22#[derive(Debug, Clone)]
23pub struct CheckReparse { 23pub struct CheckReparse {
24 text: String, 24 text: String,
25 edit: AtomTextEdit, 25 edit: Indel,
26 edited_text: String, 26 edited_text: String,
27} 27}
28 28
@@ -43,7 +43,7 @@ impl CheckReparse {
43 TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap()); 43 TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap());
44 let edited_text = 44 let edited_text =
45 format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]); 45 format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]);
46 let edit = AtomTextEdit { delete, insert }; 46 let edit = Indel { delete, insert };
47 Some(CheckReparse { text, edit, edited_text }) 47 Some(CheckReparse { text, edit, edited_text })
48 } 48 }
49 49
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index ceeb2bde9..61e686da5 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -39,7 +39,7 @@ pub mod fuzz;
39 39
40use std::{marker::PhantomData, sync::Arc}; 40use std::{marker::PhantomData, sync::Arc};
41 41
42use ra_text_edit::AtomTextEdit; 42use ra_text_edit::Indel;
43use stdx::format_to; 43use stdx::format_to;
44 44
45use crate::syntax_node::GreenNode; 45use crate::syntax_node::GreenNode;
@@ -126,13 +126,13 @@ impl Parse<SourceFile> {
126 buf 126 buf
127 } 127 }
128 128
129 pub fn reparse(&self, edit: &AtomTextEdit) -> Parse<SourceFile> { 129 pub fn reparse(&self, indel: &Indel) -> Parse<SourceFile> {
130 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) 130 self.incremental_reparse(indel).unwrap_or_else(|| self.full_reparse(indel))
131 } 131 }
132 132
133 fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<Parse<SourceFile>> { 133 fn incremental_reparse(&self, indel: &Indel) -> Option<Parse<SourceFile>> {
134 // FIXME: validation errors are not handled here 134 // FIXME: validation errors are not handled here
135 parsing::incremental_reparse(self.tree().syntax(), edit, self.errors.to_vec()).map( 135 parsing::incremental_reparse(self.tree().syntax(), indel, self.errors.to_vec()).map(
136 |(green_node, errors, _reparsed_range)| Parse { 136 |(green_node, errors, _reparsed_range)| Parse {
137 green: green_node, 137 green: green_node,
138 errors: Arc::new(errors), 138 errors: Arc::new(errors),
@@ -141,8 +141,9 @@ impl Parse<SourceFile> {
141 ) 141 )
142 } 142 }
143 143
144 fn full_reparse(&self, edit: &AtomTextEdit) -> Parse<SourceFile> { 144 fn full_reparse(&self, indel: &Indel) -> Parse<SourceFile> {
145 let text = edit.apply(self.tree().syntax().text().to_string()); 145 let mut text = self.tree().syntax().text().to_string();
146 indel.apply(&mut text);
146 SourceFile::parse(&text) 147 SourceFile::parse(&text)
147 } 148 }
148} 149}
@@ -237,8 +238,7 @@ fn api_walkthrough() {
237 238
238 // Let's get the `1 + 1` expression! 239 // Let's get the `1 + 1` expression!
239 let body: ast::BlockExpr = func.body().unwrap(); 240 let body: ast::BlockExpr = func.body().unwrap();
240 let block = body.block().unwrap(); 241 let expr: ast::Expr = body.expr().unwrap();
241 let expr: ast::Expr = block.expr().unwrap();
242 242
243 // Enums are used to group related ast nodes together, and can be used for 243 // Enums are used to group related ast nodes together, and can be used for
244 // matching. However, because there are no public fields, it's possible to 244 // matching. However, because there are no public fields, it's possible to
@@ -274,8 +274,8 @@ fn api_walkthrough() {
274 assert_eq!(text.to_string(), "1 + 1"); 274 assert_eq!(text.to_string(), "1 + 1");
275 275
276 // There's a bunch of traversal methods on `SyntaxNode`: 276 // There's a bunch of traversal methods on `SyntaxNode`:
277 assert_eq!(expr_syntax.parent().as_ref(), Some(block.syntax())); 277 assert_eq!(expr_syntax.parent().as_ref(), Some(body.syntax()));
278 assert_eq!(block.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{'])); 278 assert_eq!(body.syntax().first_child_or_token().map(|it| it.kind()), Some(T!['{']));
279 assert_eq!( 279 assert_eq!(
280 expr_syntax.next_sibling_or_token().map(|it| it.kind()), 280 expr_syntax.next_sibling_or_token().map(|it| it.kind()),
281 Some(SyntaxKind::WHITESPACE) 281 Some(SyntaxKind::WHITESPACE)
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs
index ffff0a7b2..edbc190f8 100644
--- a/crates/ra_syntax/src/parsing/reparsing.rs
+++ b/crates/ra_syntax/src/parsing/reparsing.rs
@@ -7,7 +7,7 @@
7//! and try to parse only this block. 7//! and try to parse only this block.
8 8
9use ra_parser::Reparser; 9use ra_parser::Reparser;
10use ra_text_edit::AtomTextEdit; 10use ra_text_edit::Indel;
11 11
12use crate::{ 12use crate::{
13 algo, 13 algo,
@@ -24,7 +24,7 @@ use crate::{
24 24
25pub(crate) fn incremental_reparse( 25pub(crate) fn incremental_reparse(
26 node: &SyntaxNode, 26 node: &SyntaxNode,
27 edit: &AtomTextEdit, 27 edit: &Indel,
28 errors: Vec<SyntaxError>, 28 errors: Vec<SyntaxError>,
29) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> { 29) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
30 if let Some((green, new_errors, old_range)) = reparse_token(node, &edit) { 30 if let Some((green, new_errors, old_range)) = reparse_token(node, &edit) {
@@ -39,7 +39,7 @@ pub(crate) fn incremental_reparse(
39 39
40fn reparse_token<'node>( 40fn reparse_token<'node>(
41 root: &'node SyntaxNode, 41 root: &'node SyntaxNode,
42 edit: &AtomTextEdit, 42 edit: &Indel,
43) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> { 43) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
44 let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone(); 44 let prev_token = algo::find_covering_element(root, edit.delete).as_token()?.clone();
45 let prev_token_kind = prev_token.kind(); 45 let prev_token_kind = prev_token.kind();
@@ -88,7 +88,7 @@ fn reparse_token<'node>(
88 88
89fn reparse_block<'node>( 89fn reparse_block<'node>(
90 root: &'node SyntaxNode, 90 root: &'node SyntaxNode,
91 edit: &AtomTextEdit, 91 edit: &Indel,
92) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> { 92) -> Option<(GreenNode, Vec<SyntaxError>, TextRange)> {
93 let (node, reparser) = find_reparsable_node(root, edit.delete)?; 93 let (node, reparser) = find_reparsable_node(root, edit.delete)?;
94 let text = get_text_after_edit(node.clone().into(), edit); 94 let text = get_text_after_edit(node.clone().into(), edit);
@@ -108,15 +108,15 @@ fn reparse_block<'node>(
108 Some((node.replace_with(green), new_parser_errors, node.text_range())) 108 Some((node.replace_with(green), new_parser_errors, node.text_range()))
109} 109}
110 110
111fn get_text_after_edit(element: SyntaxElement, edit: &AtomTextEdit) -> String { 111fn get_text_after_edit(element: SyntaxElement, edit: &Indel) -> String {
112 let edit = 112 let edit = Indel::replace(edit.delete - element.text_range().start(), edit.insert.clone());
113 AtomTextEdit::replace(edit.delete - element.text_range().start(), edit.insert.clone());
114 113
115 let text = match element { 114 let mut text = match element {
116 NodeOrToken::Token(token) => token.text().to_string(), 115 NodeOrToken::Token(token) => token.text().to_string(),
117 NodeOrToken::Node(node) => node.text().to_string(), 116 NodeOrToken::Node(node) => node.text().to_string(),
118 }; 117 };
119 edit.apply(text) 118 edit.apply(&mut text);
119 text
120} 120}
121 121
122fn is_contextual_kw(text: &str) -> bool { 122fn is_contextual_kw(text: &str) -> bool {
@@ -167,7 +167,7 @@ fn merge_errors(
167 old_errors: Vec<SyntaxError>, 167 old_errors: Vec<SyntaxError>,
168 new_errors: Vec<SyntaxError>, 168 new_errors: Vec<SyntaxError>,
169 range_before_reparse: TextRange, 169 range_before_reparse: TextRange,
170 edit: &AtomTextEdit, 170 edit: &Indel,
171) -> Vec<SyntaxError> { 171) -> Vec<SyntaxError> {
172 let mut res = Vec::new(); 172 let mut res = Vec::new();
173 173
@@ -198,8 +198,12 @@ mod tests {
198 198
199 fn do_check(before: &str, replace_with: &str, reparsed_len: u32) { 199 fn do_check(before: &str, replace_with: &str, reparsed_len: u32) {
200 let (range, before) = extract_range(before); 200 let (range, before) = extract_range(before);
201 let edit = AtomTextEdit::replace(range, replace_with.to_owned()); 201 let edit = Indel::replace(range, replace_with.to_owned());
202 let after = edit.apply(before.clone()); 202 let after = {
203 let mut after = before.clone();
204 edit.apply(&mut after);
205 after
206 };
203 207
204 let fully_reparsed = SourceFile::parse(&after); 208 let fully_reparsed = SourceFile::parse(&after);
205 let incrementally_reparsed: Parse<SourceFile> = { 209 let incrementally_reparsed: Parse<SourceFile> = {
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs
index f9d379abf..e566af7e8 100644
--- a/crates/ra_syntax/src/syntax_node.rs
+++ b/crates/ra_syntax/src/syntax_node.rs
@@ -70,6 +70,6 @@ impl SyntaxTreeBuilder {
70 } 70 }
71 71
72 pub fn error(&mut self, error: ra_parser::ParseError, text_pos: TextSize) { 72 pub fn error(&mut self, error: ra_parser::ParseError, text_pos: TextSize) {
73 self.errors.push(SyntaxError::new_at_offset(error.0, text_pos)) 73 self.errors.push(SyntaxError::new_at_offset(*error.0, text_pos))
74 } 74 }
75} 75}
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index e075cd801..d68cf0a82 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -54,7 +54,7 @@ fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str {
54 "Unicode escape must not be empty" 54 "Unicode escape must not be empty"
55 } 55 }
56 EE::UnclosedUnicodeEscape => { 56 EE::UnclosedUnicodeEscape => {
57 "Missing '}' to terminate the unicode escape" 57 "Missing `}` to terminate the unicode escape"
58 } 58 }
59 EE::LeadingUnderscoreUnicodeEscape => { 59 EE::LeadingUnderscoreUnicodeEscape => {
60 "Unicode escape code must not begin with an underscore" 60 "Unicode escape code must not begin with an underscore"
diff --git a/crates/ra_syntax/src/validation/block.rs b/crates/ra_syntax/src/validation/block.rs
index 8e962ab5b..2c08f7e6e 100644
--- a/crates/ra_syntax/src/validation/block.rs
+++ b/crates/ra_syntax/src/validation/block.rs
@@ -6,19 +6,17 @@ use crate::{
6 SyntaxKind::*, 6 SyntaxKind::*,
7}; 7};
8 8
9pub(crate) fn validate_block_expr(expr: ast::BlockExpr, errors: &mut Vec<SyntaxError>) { 9pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec<SyntaxError>) {
10 if let Some(parent) = expr.syntax().parent() { 10 if let Some(parent) = block.syntax().parent() {
11 match parent.kind() { 11 match parent.kind() {
12 FN_DEF | EXPR_STMT | BLOCK => return, 12 FN_DEF | EXPR_STMT | BLOCK_EXPR => return,
13 _ => {} 13 _ => {}
14 } 14 }
15 } 15 }
16 if let Some(block) = expr.block() { 16 errors.extend(block.attrs().map(|attr| {
17 errors.extend(block.attrs().map(|attr| { 17 SyntaxError::new(
18 SyntaxError::new( 18 "A block in this position cannot accept inner attributes",
19 "A block in this position cannot accept inner attributes", 19 attr.syntax().text_range(),
20 attr.syntax().text_range(), 20 )
21 ) 21 }))
22 }))
23 }
24} 22}
diff --git a/crates/ra_syntax/test_data/parser/err/0005_attribute_recover.rast b/crates/ra_syntax/test_data/parser/err/0005_attribute_recover.rast
index 95cc83caa..375ed45e0 100644
--- a/crates/ra_syntax/test_data/parser/err/0005_attribute_recover.rast
+++ b/crates/ra_syntax/test_data/parser/err/0005_attribute_recover.rast
@@ -28,10 +28,9 @@ [email protected]
28 [email protected] ")" 28 [email protected] ")"
29 [email protected] " " 29 [email protected] " "
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected] "{"
32 [email protected] "{" 32 [email protected] "\n"
33 [email protected] "\n" 33 [email protected] "}"
34 [email protected] "}"
35 [email protected] "\n\n\n" 34 [email protected] "\n\n\n"
36 [email protected] 35 [email protected]
37 [email protected] "#" 36 [email protected] "#"
diff --git a/crates/ra_syntax/test_data/parser/err/0007_stray_curly_in_file.rast b/crates/ra_syntax/test_data/parser/err/0007_stray_curly_in_file.rast
index dc3e12091..b72c92c33 100644
--- a/crates/ra_syntax/test_data/parser/err/0007_stray_curly_in_file.rast
+++ b/crates/ra_syntax/test_data/parser/err/0007_stray_curly_in_file.rast
@@ -21,9 +21,8 @@ [email protected]
21 [email protected] "(" 21 [email protected] "("
22 [email protected] ")" 22 [email protected] ")"
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected] "{"
25 [email protected] "{" 25 [email protected] "}"
26 [email protected] "}"
27 [email protected] "\n\n" 26 [email protected] "\n\n"
28 [email protected] 27 [email protected]
29 [email protected] "}" 28 [email protected] "}"
diff --git a/crates/ra_syntax/test_data/parser/err/0008_item_block_recovery.rast b/crates/ra_syntax/test_data/parser/err/0008_item_block_recovery.rast
index 97539fcf2..33953d8d7 100644
--- a/crates/ra_syntax/test_data/parser/err/0008_item_block_recovery.rast
+++ b/crates/ra_syntax/test_data/parser/err/0008_item_block_recovery.rast
@@ -9,10 +9,9 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n"
14 [email protected] "\n" 14 [email protected] "}"
15 [email protected] "}"
16 [email protected] "\n\n" 15 [email protected] "\n\n"
17 [email protected] 16 [email protected]
18 [email protected] 17 [email protected]
@@ -34,30 +33,28 @@ [email protected]
34 [email protected] "true" 33 [email protected] "true"
35 [email protected] " " 34 [email protected] " "
36 [email protected] 35 [email protected]
37 [email protected] 36 [email protected] "{"
38 [email protected] "{" 37 [email protected] "\n "
39 [email protected] "\n " 38 [email protected]
40 [email protected] 39 [email protected] "1"
41 [email protected] "1" 40 [email protected] "\n "
42 [email protected] "\n " 41 [email protected] "}"
43 [email protected] "}"
44 [email protected] " " 42 [email protected] " "
45 [email protected] "else" 43 [email protected] "else"
46 [email protected] " " 44 [email protected] " "
47 [email protected] 45 [email protected]
48 [email protected] 46 [email protected] "{"
49 [email protected] "{" 47 [email protected] "\n "
50 [email protected] "\n " 48 [email protected]
51 [email protected] 49 [email protected]
52 [email protected] 50 [email protected] "2"
53 [email protected] "2" 51 [email protected] " "
54 [email protected] " " 52 [email protected] "+"
55 [email protected] "+" 53 [email protected] " "
56 [email protected] " " 54 [email protected]
57 [email protected] 55 [email protected] "3"
58 [email protected] "3" 56 [email protected] "\n "
59 [email protected] "\n " 57 [email protected] "}"
60 [email protected] "}"
61 [email protected] "\n" 58 [email protected] "\n"
62 [email protected] "}" 59 [email protected] "}"
63 [email protected] "\n\n" 60 [email protected] "\n\n"
@@ -71,10 +68,9 @@ [email protected]
71 [email protected] ")" 68 [email protected] ")"
72 [email protected] " " 69 [email protected] " "
73 [email protected] 70 [email protected]
74 [email protected] 71 [email protected] "{"
75 [email protected] "{" 72 [email protected] "\n"
76 [email protected] "\n" 73 [email protected] "}"
77 [email protected] "}"
78 [email protected] "\n" 74 [email protected] "\n"
79error 17..17: expected BANG 75error 17..17: expected BANG
80error 19..19: expected SEMICOLON 76error 19..19: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/err/0010_unsafe_lambda_block.rast b/crates/ra_syntax/test_data/parser/err/0010_unsafe_lambda_block.rast
index e10bb8174..3bf57eacc 100644
--- a/crates/ra_syntax/test_data/parser/err/0010_unsafe_lambda_block.rast
+++ b/crates/ra_syntax/test_data/parser/err/0010_unsafe_lambda_block.rast
@@ -9,37 +9,36 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected] "|"
18 [email protected] "|" 18 [email protected] "|"
19 [email protected] "|" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "->"
22 [email protected] "->" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "("
25 [email protected] "(" 25 [email protected] ")"
26 [email protected] ")" 26 [email protected] " "
27 [email protected] " " 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "unsafe"
30 [email protected] "unsafe" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "{"
33 [email protected] "{" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected] "("
36 [email protected] "(" 36 [email protected] ")"
37 [email protected] ")" 37 [email protected] " "
38 [email protected] " " 38 [email protected] "}"
39 [email protected] "}" 39 [email protected] ";"
40 [email protected] ";" 40 [email protected] "\n"
41 [email protected] "\n" 41 [email protected] "}"
42 [email protected] "}"
43 [email protected] "\n" 42 [email protected] "\n"
44error 24..24: expected `{` 43error 24..24: expected a block
45error 24..24: expected SEMICOLON 44error 24..24: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/err/0014_where_no_bounds.rast b/crates/ra_syntax/test_data/parser/err/0014_where_no_bounds.rast
index 61c361833..9323b7890 100644
--- a/crates/ra_syntax/test_data/parser/err/0014_where_no_bounds.rast
+++ b/crates/ra_syntax/test_data/parser/err/0014_where_no_bounds.rast
@@ -25,8 +25,7 @@ [email protected]
25 [email protected] "T" 25 [email protected] "T"
26 [email protected] " " 26 [email protected] " "
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected] "{"
29 [email protected] "{" 29 [email protected] "}"
30 [email protected] "}"
31 [email protected] "\n" 30 [email protected] "\n"
32error 19..19: expected colon 31error 19..19: expected colon
diff --git a/crates/ra_syntax/test_data/parser/err/0016_missing_semi.rast b/crates/ra_syntax/test_data/parser/err/0016_missing_semi.rast
index 92bb47316..93434f34f 100644
--- a/crates/ra_syntax/test_data/parser/err/0016_missing_semi.rast
+++ b/crates/ra_syntax/test_data/parser/err/0016_missing_semi.rast
@@ -9,36 +9,35 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "foo"
21 [email protected] "foo" 21 [email protected]
22 [email protected] 22 [email protected] "("
23 [email protected] "(" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected] "1"
26 [email protected] "1" 26 [email protected] ","
27 [email protected] "," 27 [email protected] " "
28 [email protected] " " 28 [email protected]
29 [email protected] 29 [email protected] "2"
30 [email protected] "2" 30 [email protected] "\n "
31 [email protected] "\n " 31 [email protected] ")"
32 [email protected] ")" 32 [email protected] "\n "
33 [email protected] "\n " 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "return"
36 [email protected] "return" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected] "92"
39 [email protected] "92" 39 [email protected] ";"
40 [email protected] ";" 40 [email protected] "\n"
41 [email protected] "\n" 41 [email protected] "}"
42 [email protected] "}"
43 [email protected] "\n" 42 [email protected] "\n"
44error 38..38: expected SEMICOLON 43error 38..38: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/err/0017_incomplete_binexpr.rast b/crates/ra_syntax/test_data/parser/err/0017_incomplete_binexpr.rast
index 7bc718302..628315c78 100644
--- a/crates/ra_syntax/test_data/parser/err/0017_incomplete_binexpr.rast
+++ b/crates/ra_syntax/test_data/parser/err/0017_incomplete_binexpr.rast
@@ -20,28 +20,27 @@ [email protected]
20 [email protected] ")" 20 [email protected] ")"
21 [email protected] " " 21 [email protected] " "
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] "{" 24 [email protected] "\n "
25 [email protected] "\n " 25 [email protected]
26 [email protected] 26 [email protected] "let"
27 [email protected] "let" 27 [email protected] " "
28 [email protected] " " 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "bar"
31 [email protected] "bar" 31 [email protected] " "
32 [email protected] " " 32 [email protected] "="
33 [email protected] "=" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected] "92"
36 [email protected] "92" 36 [email protected] ";"
37 [email protected] ";" 37 [email protected] "\n "
38 [email protected] "\n " 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected] "1"
41 [email protected] "1" 41 [email protected] " "
42 [email protected] " " 42 [email protected] "+"
43 [email protected] "+" 43 [email protected] "\n"
44 [email protected] "\n" 44 [email protected] "}"
45 [email protected] "}"
46 [email protected] "\n" 45 [email protected] "\n"
47error 44..44: expected expression 46error 44..44: expected expression
diff --git a/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.rast b/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.rast
index 63194f974..31cc4e551 100644
--- a/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.rast
+++ b/crates/ra_syntax/test_data/parser/err/0018_incomplete_fn.rast
@@ -33,89 +33,88 @@ [email protected]
33 [email protected] "ScopeId" 33 [email protected] "ScopeId"
34 [email protected] " " 34 [email protected] " "
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected] "{"
37 [email protected] "{" 37 [email protected] "\n "
38 [email protected] "\n " 38 [email protected]
39 [email protected] 39 [email protected] "let"
40 [email protected] "let" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected]
43 [email protected] 43 [email protected] "res"
44 [email protected] "res" 44 [email protected] " "
45 [email protected] " " 45 [email protected] "="
46 [email protected] "=" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "self"
53 [email protected] "self" 53 [email protected] "."
54 [email protected] "." 54 [email protected]
55 [email protected] 55 [email protected] "scopes"
56 [email protected] "scopes" 56 [email protected] "."
57 [email protected] "." 57 [email protected]
58 [email protected] 58 [email protected] "len"
59 [email protected] "len" 59 [email protected]
60 [email protected] 60 [email protected] "("
61 [email protected] "(" 61 [email protected] ")"
62 [email protected] ")" 62 [email protected] ";"
63 [email protected] ";" 63 [email protected] "\n "
64 [email protected] "\n " 64 [email protected]
65 [email protected] 65 [email protected]
66 [email protected] 66 [email protected]
67 [email protected] 67 [email protected]
68 [email protected] 68 [email protected]
69 [email protected] 69 [email protected] "self"
70 [email protected] "self" 70 [email protected] "."
71 [email protected] "." 71 [email protected]
72 [email protected] 72 [email protected] "scopes"
73 [email protected] "scopes" 73 [email protected] "."
74 [email protected] "." 74 [email protected]
75 [email protected] 75 [email protected] "push"
76 [email protected] "push" 76 [email protected]
77 [email protected] 77 [email protected] "("
78 [email protected] "(" 78 [email protected]
79 [email protected] 79 [email protected]
80 [email protected] 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "ScopeData"
83 [email protected] "ScopeData" 83 [email protected] " "
84 [email protected] " " 84 [email protected]
85 [email protected] 85 [email protected] "{"
86 [email protected] "{" 86 [email protected] " "
87 [email protected] " " 87 [email protected]
88 [email protected] 88 [email protected]
89 [email protected] 89 [email protected] "parent"
90 [email protected] "parent" 90 [email protected] ":"
91 [email protected] ":" 91 [email protected] " "
92 [email protected] " " 92 [email protected]
93 [email protected] 93 [email protected]
94 [email protected] 94 [email protected]
95 [email protected] 95 [email protected]
96 [email protected] 96 [email protected] "None"
97 [email protected] "None" 97 [email protected] ","
98 [email protected] "," 98 [email protected] " "
99 [email protected] " " 99 [email protected]
100 [email protected] 100 [email protected]
101 [email protected] 101 [email protected] "entries"
102 [email protected] "entries" 102 [email protected] ":"
103 [email protected] ":" 103 [email protected] " "
104 [email protected] " " 104 [email protected]
105 [email protected] 105 [email protected]
106 [email protected] 106 [email protected]
107 [email protected] 107 [email protected]
108 [email protected] 108 [email protected] "vec"
109 [email protected] "vec" 109 [email protected] "!"
110 [email protected] "!" 110 [email protected]
111 [email protected] 111 [email protected] "["
112 [email protected] "[" 112 [email protected] "]"
113 [email protected] "]" 113 [email protected] " "
114 [email protected] " " 114 [email protected] "}"
115 [email protected] "}" 115 [email protected] ")"
116 [email protected] ")" 116 [email protected] "\n "
117 [email protected] "\n " 117 [email protected] "}"
118 [email protected] "}"
119 [email protected] "\n\n " 118 [email protected] "\n\n "
120 [email protected] 119 [email protected]
121 [email protected] "fn" 120 [email protected] "fn"
diff --git a/crates/ra_syntax/test_data/parser/err/0019_let_recover.rast b/crates/ra_syntax/test_data/parser/err/0019_let_recover.rast
index d20bb60f1..4ff27f5c8 100644
--- a/crates/ra_syntax/test_data/parser/err/0019_let_recover.rast
+++ b/crates/ra_syntax/test_data/parser/err/0019_let_recover.rast
@@ -9,91 +9,87 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "foo"
20 [email protected] "foo" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "="
22 [email protected] "=" 22 [email protected] "\n "
23 [email protected] "\n " 23 [email protected]
24 [email protected] 24 [email protected] "let"
25 [email protected] "let" 25 [email protected] " "
26 [email protected] " " 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected] "bar"
29 [email protected] "bar" 29 [email protected] " "
30 [email protected] " " 30 [email protected] "="
31 [email protected] "=" 31 [email protected] " "
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected] "1"
34 [email protected] "1" 34 [email protected] ";"
35 [email protected] ";" 35 [email protected] "\n "
36 [email protected] "\n " 36 [email protected]
37 [email protected] 37 [email protected] "let"
38 [email protected] "let" 38 [email protected] "\n "
39 [email protected] "\n " 39 [email protected]
40 [email protected] 40 [email protected] "let"
41 [email protected] "let" 41 [email protected] " "
42 [email protected] " " 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected] "baz"
45 [email protected] "baz" 45 [email protected] " "
46 [email protected] " " 46 [email protected] "="
47 [email protected] "=" 47 [email protected] " "
48 [email protected] " " 48 [email protected]
49 [email protected] 49 [email protected] "92"
50 [email protected] "92" 50 [email protected] ";"
51 [email protected] ";" 51 [email protected] "\n "
52 [email protected] "\n " 52 [email protected]
53 [email protected] 53 [email protected] "let"
54 [email protected] "let" 54 [email protected] "\n "
55 [email protected] "\n " 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected] "if"
58 [email protected] "if" 58 [email protected] " "
59 [email protected] " " 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected] "true"
62 [email protected] "true" 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected] "{"
65 [email protected] 65 [email protected] "}"
66 [email protected] "{" 66 [email protected] "\n "
67 [email protected] "}" 67 [email protected]
68 [email protected] "\n " 68 [email protected] "let"
69 [email protected] 69 [email protected] "\n "
70 [email protected] "let" 70 [email protected]
71 [email protected] "\n " 71 [email protected]
72 [email protected] 72 [email protected] "while"
73 [email protected] 73 [email protected] " "
74 [email protected] "while" 74 [email protected]
75 [email protected] " " 75 [email protected]
76 [email protected] 76 [email protected] "true"
77 [email protected] 77 [email protected] " "
78 [email protected] "true" 78 [email protected]
79 [email protected] " " 79 [email protected] "{"
80 [email protected] 80 [email protected] "}"
81 [email protected] 81 [email protected] "\n "
82 [email protected] "{" 82 [email protected]
83 [email protected] "}" 83 [email protected] "let"
84 [email protected] "\n " 84 [email protected] "\n "
85 [email protected] 85 [email protected]
86 [email protected] "let" 86 [email protected] "loop"
87 [email protected] "\n " 87 [email protected] " "
88 [email protected] 88 [email protected]
89 [email protected] "loop" 89 [email protected] "{"
90 [email protected] " " 90 [email protected] "}"
91 [email protected] 91 [email protected] "\n"
92 [email protected] 92 [email protected] "}"
93 [email protected] "{"
94 [email protected] "}"
95 [email protected] "\n"
96 [email protected] "}"
97 [email protected] "\n" 93 [email protected] "\n"
98error 24..24: expected expression 94error 24..24: expected expression
99error 24..24: expected SEMICOLON 95error 24..24: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/err/0020_fn_recover.rast b/crates/ra_syntax/test_data/parser/err/0020_fn_recover.rast
index 1185f44f9..5f3a31473 100644
--- a/crates/ra_syntax/test_data/parser/err/0020_fn_recover.rast
+++ b/crates/ra_syntax/test_data/parser/err/0020_fn_recover.rast
@@ -12,9 +12,8 @@ [email protected]
12 [email protected] ")" 12 [email protected] ")"
13 [email protected] " " 13 [email protected] " "
14 [email protected] 14 [email protected]
15 [email protected] 15 [email protected] "{"
16 [email protected] "{" 16 [email protected] "}"
17 [email protected] "}"
18 [email protected] "\n" 17 [email protected] "\n"
19error 2..2: expected a name 18error 2..2: expected a name
20error 2..2: expected function arguments 19error 2..2: expected function arguments
diff --git a/crates/ra_syntax/test_data/parser/err/0021_incomplete_param.rast b/crates/ra_syntax/test_data/parser/err/0021_incomplete_param.rast
index c7bf4caa0..1746bd3c1 100644
--- a/crates/ra_syntax/test_data/parser/err/0021_incomplete_param.rast
+++ b/crates/ra_syntax/test_data/parser/err/0021_incomplete_param.rast
@@ -26,10 +26,9 @@ [email protected]
26 [email protected] ")" 26 [email protected] ")"
27 [email protected] " " 27 [email protected] " "
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "{"
30 [email protected] "{" 30 [email protected] "\n"
31 [email protected] "\n" 31 [email protected] "}"
32 [email protected] "}"
33 [email protected] "\n" 32 [email protected] "\n"
34error 16..16: expected COLON 33error 16..16: expected COLON
35error 16..16: expected type 34error 16..16: expected type
diff --git a/crates/ra_syntax/test_data/parser/err/0022_bad_exprs.rast b/crates/ra_syntax/test_data/parser/err/0022_bad_exprs.rast
index cc0d75cc8..28146f44e 100644
--- a/crates/ra_syntax/test_data/parser/err/0022_bad_exprs.rast
+++ b/crates/ra_syntax/test_data/parser/err/0022_bad_exprs.rast
@@ -9,37 +9,36 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "["
17 [email protected] "[" 17 [email protected]
18 [email protected] 18 [email protected] "1"
19 [email protected] "1" 19 [email protected] ","
20 [email protected] "," 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "2"
23 [email protected] "2" 23 [email protected] ","
24 [email protected] "," 24 [email protected] " "
25 [email protected] " " 25 [email protected]
26 [email protected] 26 [email protected] "@"
27 [email protected] "@" 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] ","
30 [email protected] "," 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "struct"
33 [email protected] "struct" 33 [email protected]
34 [email protected] 34 [email protected] ","
35 [email protected] "," 35 [email protected] " "
36 [email protected] " " 36 [email protected]
37 [email protected] 37 [email protected] "let"
38 [email protected] "let" 38 [email protected]
39 [email protected] 39 [email protected] "]"
40 [email protected] "]" 40 [email protected] " "
41 [email protected] " " 41 [email protected] "}"
42 [email protected] "}"
43 [email protected] "\n" 42 [email protected] "\n"
44 [email protected] 43 [email protected]
45 [email protected] "fn" 44 [email protected] "fn"
@@ -51,44 +50,43 @@ [email protected]
51 [email protected] ")" 50 [email protected] ")"
52 [email protected] " " 51 [email protected] " "
53 [email protected] 52 [email protected]
54 [email protected] 53 [email protected] "{"
55 [email protected] "{" 54 [email protected] " "
56 [email protected] " " 55 [email protected]
57 [email protected] 56 [email protected]
58 [email protected] 57 [email protected]
59 [email protected] 58 [email protected]
60 [email protected] 59 [email protected]
61 [email protected] 60 [email protected]
62 [email protected] 61 [email protected] "foo"
63 [email protected] "foo" 62 [email protected]
64 [email protected] 63 [email protected] "("
65 [email protected] "(" 64 [email protected]
66 [email protected] 65 [email protected] "1"
67 [email protected] "1" 66 [email protected] ","
68 [email protected] "," 67 [email protected] " "
69 [email protected] " " 68 [email protected]
70 [email protected] 69 [email protected] "2"
71 [email protected] "2" 70 [email protected] ","
72 [email protected] "," 71 [email protected] " "
73 [email protected] " " 72 [email protected]
74 [email protected] 73 [email protected] "@"
75 [email protected] "@" 74 [email protected]
76 [email protected] 75 [email protected]
77 [email protected] 76 [email protected] ","
78 [email protected] "," 77 [email protected] " "
79 [email protected] " " 78 [email protected]
80 [email protected] 79 [email protected] "impl"
81 [email protected] "impl" 80 [email protected]
82 [email protected] 81 [email protected]
83 [email protected] 82 [email protected] ","
84 [email protected] "," 83 [email protected] " "
85 [email protected] " " 84 [email protected]
86 [email protected] 85 [email protected] "let"
87 [email protected] "let" 86 [email protected]
88 [email protected] 87 [email protected] ")"
89 [email protected] ")" 88 [email protected] " "
90 [email protected] " " 89 [email protected] "}"
91 [email protected] "}"
92 [email protected] "\n" 90 [email protected] "\n"
93 [email protected] 91 [email protected]
94 [email protected] "fn" 92 [email protected] "fn"
@@ -100,53 +98,52 @@ [email protected]
100 [email protected] ")" 98 [email protected] ")"
101 [email protected] " " 99 [email protected] " "
102 [email protected] 100 [email protected]
103 [email protected] 101 [email protected] "{"
104 [email protected] "{" 102 [email protected] " "
105 [email protected] " " 103 [email protected]
106 [email protected] 104 [email protected]
107 [email protected] 105 [email protected]
108 [email protected] 106 [email protected]
109 [email protected] 107 [email protected]
110 [email protected] 108 [email protected]
111 [email protected] 109 [email protected] "foo"
112 [email protected] "foo" 110 [email protected] "."
113 [email protected] "." 111 [email protected]
114 [email protected] 112 [email protected] "bar"
115 [email protected] "bar" 113 [email protected]
116 [email protected] 114 [email protected] "("
117 [email protected] "(" 115 [email protected]
118 [email protected] 116 [email protected] "1"
119 [email protected] "1" 117 [email protected] ","
120 [email protected] "," 118 [email protected] " "
121 [email protected] " " 119 [email protected]
122 [email protected] 120 [email protected] "2"
123 [email protected] "2" 121 [email protected] ","
124 [email protected] "," 122 [email protected] " "
125 [email protected] " " 123 [email protected]
126 [email protected] 124 [email protected] "@"
127 [email protected] "@" 125 [email protected]
128 [email protected] 126 [email protected]
129 [email protected] 127 [email protected] ","
130 [email protected] "," 128 [email protected] " "
131 [email protected] " " 129 [email protected]
132 [email protected] 130 [email protected]
133 [email protected] 131 [email protected] "]"
134 [email protected] "]" 132 [email protected]
135 [email protected] 133 [email protected]
136 [email protected] 134 [email protected] ","
137 [email protected] "," 135 [email protected] " "
138 [email protected] " " 136 [email protected]
139 [email protected] 137 [email protected] "trait"
140 [email protected] "trait" 138 [email protected]
141 [email protected] 139 [email protected] ","
142 [email protected] "," 140 [email protected] " "
143 [email protected] " " 141 [email protected]
144 [email protected] 142 [email protected] "let"
145 [email protected] "let" 143 [email protected]
146 [email protected] 144 [email protected] ")"
147 [email protected] ")" 145 [email protected] " "
148 [email protected] " " 146 [email protected] "}"
149 [email protected] "}"
150 [email protected] "\n" 147 [email protected] "\n"
151error 16..16: expected expression 148error 16..16: expected expression
152error 17..17: expected R_BRACK 149error 17..17: expected R_BRACK
diff --git a/crates/ra_syntax/test_data/parser/err/0023_mismatched_paren.rast b/crates/ra_syntax/test_data/parser/err/0023_mismatched_paren.rast
index c37594146..9ea9d715e 100644
--- a/crates/ra_syntax/test_data/parser/err/0023_mismatched_paren.rast
+++ b/crates/ra_syntax/test_data/parser/err/0023_mismatched_paren.rast
@@ -9,31 +9,30 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected] "foo"
19 [email protected] "foo" 19 [email protected] "!"
20 [email protected] "!" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "("
23 [email protected] "(" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected] "bar"
25 [email protected] "bar" 25 [email protected] ","
26 [email protected] "," 26 [email protected] " "
27 [email protected] " " 27 [email protected] "\"baz\""
28 [email protected] "\"baz\"" 28 [email protected] ","
29 [email protected] "," 29 [email protected] " "
30 [email protected] " " 30 [email protected] "1"
31 [email protected] "1" 31 [email protected] ","
32 [email protected] "," 32 [email protected] " "
33 [email protected] " " 33 [email protected] "2.0"
34 [email protected] "2.0" 34 [email protected] "\n "
35 [email protected] "\n " 35 [email protected] "}"
36 [email protected] "}"
37 [email protected] " " 36 [email protected] " "
38 [email protected] "//~ ERROR incorrect c ..." 37 [email protected] "//~ ERROR incorrect c ..."
39 [email protected] "\n" 38 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/err/0024_many_type_parens.rast b/crates/ra_syntax/test_data/parser/err/0024_many_type_parens.rast
index 4296355f2..7c957fdde 100644
--- a/crates/ra_syntax/test_data/parser/err/0024_many_type_parens.rast
+++ b/crates/ra_syntax/test_data/parser/err/0024_many_type_parens.rast
@@ -62,9 +62,8 @@ [email protected]
62 [email protected] ")" 62 [email protected] ")"
63 [email protected] " " 63 [email protected] " "
64 [email protected] 64 [email protected]
65 [email protected] 65 [email protected] "{"
66 [email protected] "{" 66 [email protected] "}"
67 [email protected] "}"
68 [email protected] "\n\n" 67 [email protected] "\n\n"
69 [email protected] 68 [email protected]
70 [email protected] "fn" 69 [email protected] "fn"
@@ -76,219 +75,218 @@ [email protected]
76 [email protected] ")" 75 [email protected] ")"
77 [email protected] " " 76 [email protected] " "
78 [email protected] 77 [email protected]
79 [email protected] 78 [email protected] "{"
80 [email protected] "{" 79 [email protected] "\n "
81 [email protected] "\n " 80 [email protected]
82 [email protected] 81 [email protected] "let"
83 [email protected] "let" 82 [email protected] " "
84 [email protected] " " 83 [email protected]
85 [email protected] 84 [email protected] "_"
86 [email protected] "_" 85 [email protected] ":"
87 [email protected] ":" 86 [email protected] " "
88 [email protected] " " 87 [email protected]
89 [email protected] 88 [email protected]
90 [email protected] 89 [email protected]
91 [email protected] 90 [email protected]
92 [email protected] 91 [email protected]
93 [email protected] 92 [email protected]
94 [email protected] 93 [email protected]
95 [email protected] 94 [email protected] "Box"
96 [email protected] "Box" 95 [email protected]
97 [email protected] 96 [email protected] "<"
98 [email protected] "<" 97 [email protected]
99 [email protected] 98 [email protected]
100 [email protected] 99 [email protected] "("
101 [email protected] "(" 100 [email protected]
102 [email protected] 101 [email protected]
103 [email protected] 102 [email protected]
104 [email protected] 103 [email protected]
105 [email protected] 104 [email protected] "Copy"
106 [email protected] "Copy" 105 [email protected] ")"
107 [email protected] ")" 106 [email protected] " "
108 [email protected] " " 107 [email protected] "+"
109 [email protected] "+" 108 [email protected] " "
110 [email protected] " " 109 [email protected]
111 [email protected] 110 [email protected] "("
112 [email protected] "(" 111 [email protected] "?"
113 [email protected] "?" 112 [email protected]
114 [email protected] 113 [email protected]
115 [email protected] 114 [email protected]
116 [email protected] 115 [email protected]
117 [email protected] 116 [email protected] "Sized"
118 [email protected] "Sized" 117 [email protected] ")"
119 [email protected] ")" 118 [email protected] " "
120 [email protected] " " 119 [email protected] "+"
121 [email protected] "+" 120 [email protected] " "
122 [email protected] " " 121 [email protected]
123 [email protected] 122 [email protected] "("
124 [email protected] "(" 123 [email protected]
125 [email protected] 124 [email protected] "for"
126 [email protected] "for" 125 [email protected]
127 [email protected] 126 [email protected] "<"
128 [email protected] "<" 127 [email protected]
129 [email protected] 128 [email protected] "\'a"
130 [email protected] "\'a" 129 [email protected] ">"
131 [email protected] ">" 130 [email protected] " "
132 [email protected] " " 131 [email protected]
133 [email protected] 132 [email protected]
134 [email protected] 133 [email protected]
135 [email protected] 134 [email protected]
136 [email protected] 135 [email protected] "Trait"
137 [email protected] "Trait" 136 [email protected]
138 [email protected] 137 [email protected] "<"
139 [email protected] "<" 138 [email protected]
140 [email protected] 139 [email protected] "\'a"
141 [email protected] "\'a" 140 [email protected] ">"
142 [email protected] ">" 141 [email protected] ")"
143 [email protected] ")" 142 [email protected]
144 [email protected] 143 [email protected]
145 [email protected] 144 [email protected] ">"
146 [email protected] ">" 145 [email protected] ";"
147 [email protected] ";" 146 [email protected] "\n "
148 [email protected] "\n " 147 [email protected]
149 [email protected] 148 [email protected] "let"
150 [email protected] "let" 149 [email protected] " "
151 [email protected] " " 150 [email protected]
152 [email protected] 151 [email protected] "_"
153 [email protected] "_" 152 [email protected] ":"
154 [email protected] ":" 153 [email protected] " "
155 [email protected] " " 154 [email protected]
156 [email protected] 155 [email protected]
157 [email protected] 156 [email protected]
158 [email protected] 157 [email protected]
159 [email protected] 158 [email protected] "Box"
160 [email protected] "Box" 159 [email protected]
161 [email protected] 160 [email protected] "<"
162 [email protected] "<" 161 [email protected]
163 [email protected] 162 [email protected]
164 [email protected] 163 [email protected] "("
165 [email protected] "(" 164 [email protected]
166 [email protected] 165 [email protected] "?"
167 [email protected] "?" 166 [email protected]
168 [email protected] 167 [email protected]
169 [email protected] 168 [email protected]
170 [email protected] 169 [email protected]
171 [email protected] 170 [email protected]
172 [email protected] 171 [email protected] "Sized"
173 [email protected] "Sized" 172 [email protected]
174 [email protected] 173 [email protected]
175 [email protected] 174 [email protected] ")"
176 [email protected] ")" 175 [email protected] " "
177 [email protected] " " 176 [email protected]
178 [email protected] 177 [email protected]
179 [email protected] 178 [email protected] "+"
180 [email protected] "+" 179 [email protected] " "
181 [email protected] " " 180 [email protected]
182 [email protected] 181 [email protected]
183 [email protected] 182 [email protected] "("
184 [email protected] "(" 183 [email protected]
185 [email protected] 184 [email protected]
186 [email protected] 185 [email protected]
187 [email protected] 186 [email protected]
188 [email protected] 187 [email protected]
189 [email protected] 188 [email protected]
190 [email protected] 189 [email protected] "for"
191 [email protected] "for" 190 [email protected]
192 [email protected] 191 [email protected] "<"
193 [email protected] "<" 192 [email protected]
194 [email protected] 193 [email protected] "\'a"
195 [email protected] "\'a" 194 [email protected] ">"
196 [email protected] ">" 195 [email protected] " "
197 [email protected] " " 196 [email protected]
198 [email protected] 197 [email protected]
199 [email protected] 198 [email protected]
200 [email protected] 199 [email protected]
201 [email protected] 200 [email protected] "Trait"
202 [email protected] "Trait" 201 [email protected] "<"
203 [email protected] "<" 202 [email protected]
204 [email protected] 203 [email protected] "\'a"
205 [email protected] "\'a" 204 [email protected] ">"
206 [email protected] ">" 205 [email protected]
207 [email protected] 206 [email protected] ")"
208 [email protected] ")" 207 [email protected] " "
209 [email protected] " " 208 [email protected] "+"
210 [email protected] "+" 209 [email protected] " "
211 [email protected] " " 210 [email protected]
212 [email protected] 211 [email protected] "("
213 [email protected] "(" 212 [email protected]
214 [email protected] 213 [email protected]
215 [email protected] 214 [email protected]
216 [email protected] 215 [email protected]
217 [email protected] 216 [email protected] "Copy"
218 [email protected] "Copy" 217 [email protected] ")"
219 [email protected] ")" 218 [email protected] ">"
220 [email protected] ">" 219 [email protected]
221 [email protected] 220 [email protected] ";"
222 [email protected] ";" 221 [email protected] "\n "
223 [email protected] "\n " 222 [email protected]
224 [email protected] 223 [email protected] "let"
225 [email protected] "let" 224 [email protected] " "
226 [email protected] " " 225 [email protected]
227 [email protected] 226 [email protected] "_"
228 [email protected] "_" 227 [email protected] ":"
229 [email protected] ":" 228 [email protected] " "
230 [email protected] " " 229 [email protected]
231 [email protected] 230 [email protected]
232 [email protected] 231 [email protected]
233 [email protected] 232 [email protected]
234 [email protected] 233 [email protected]
235 [email protected] 234 [email protected]
236 [email protected] 235 [email protected]
237 [email protected] 236 [email protected] "Box"
238 [email protected] "Box" 237 [email protected]
239 [email protected] 238 [email protected] "<"
240 [email protected] "<" 239 [email protected]
241 [email protected] 240 [email protected]
242 [email protected] 241 [email protected] "("
243 [email protected] "(" 242 [email protected]
244 [email protected] 243 [email protected] "for"
245 [email protected] "for" 244 [email protected]
246 [email protected] 245 [email protected] "<"
247 [email protected] "<" 246 [email protected]
248 [email protected] 247 [email protected] "\'a"
249 [email protected] "\'a" 248 [email protected] ">"
250 [email protected] ">" 249 [email protected] " "
251 [email protected] " " 250 [email protected]
252 [email protected] 251 [email protected]
253 [email protected] 252 [email protected]
254 [email protected] 253 [email protected]
255 [email protected] 254 [email protected] "Trait"
256 [email protected] "Trait" 255 [email protected]
257 [email protected] 256 [email protected] "<"
258 [email protected] "<" 257 [email protected]
259 [email protected] 258 [email protected] "\'a"
260 [email protected] "\'a" 259 [email protected] ">"
261 [email protected] ">" 260 [email protected] ")"
262 [email protected] ")" 261 [email protected] " "
263 [email protected] " " 262 [email protected] "+"
264 [email protected] "+" 263 [email protected] " "
265 [email protected] " " 264 [email protected]
266 [email protected] 265 [email protected] "("
267 [email protected] "(" 266 [email protected]
268 [email protected] 267 [email protected]
269 [email protected] 268 [email protected]
270 [email protected] 269 [email protected]
271 [email protected] 270 [email protected] "Copy"
272 [email protected] "Copy" 271 [email protected] ")"
273 [email protected] ")" 272 [email protected] " "
274 [email protected] " " 273 [email protected] "+"
275 [email protected] "+" 274 [email protected] " "
276 [email protected] " " 275 [email protected]
277 [email protected] 276 [email protected] "("
278 [email protected] "(" 277 [email protected] "?"
279 [email protected] "?" 278 [email protected]
280 [email protected] 279 [email protected]
281 [email protected] 280 [email protected]
282 [email protected] 281 [email protected]
283 [email protected] 282 [email protected] "Sized"
284 [email protected] "Sized" 283 [email protected] ")"
285 [email protected] ")" 284 [email protected]
286 [email protected] 285 [email protected]
287 [email protected] 286 [email protected] ">"
288 [email protected] ">" 287 [email protected] ";"
289 [email protected] ";" 288 [email protected] "\n"
290 [email protected] "\n" 289 [email protected] "}"
291 [email protected] "}"
292 [email protected] "\n" 290 [email protected] "\n"
293error 88..88: expected COMMA 291error 88..88: expected COMMA
294error 88..88: expected R_ANGLE 292error 88..88: expected R_ANGLE
diff --git a/crates/ra_syntax/test_data/parser/err/0025_nope.rast b/crates/ra_syntax/test_data/parser/err/0025_nope.rast
index 195c08bd9..88b086daf 100644
--- a/crates/ra_syntax/test_data/parser/err/0025_nope.rast
+++ b/crates/ra_syntax/test_data/parser/err/0025_nope.rast
@@ -9,187 +9,185 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "enum"
16 [email protected] "enum" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "Test"
19 [email protected] "Test" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "{"
22 [email protected] "{" 22 [email protected] "\n "
23 [email protected] "\n " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "Var1"
26 [email protected] "Var1" 26 [email protected] ","
27 [email protected] "," 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "Var2"
31 [email protected] "Var2" 31 [email protected]
32 [email protected] 32 [email protected] "("
33 [email protected] "(" 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "String"
39 [email protected] "String" 39 [email protected] ")"
40 [email protected] ")" 40 [email protected] ","
41 [email protected] "," 41 [email protected] "\n "
42 [email protected] "\n " 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected] "Var3"
45 [email protected] "Var3" 45 [email protected] " "
46 [email protected] " " 46 [email protected]
47 [email protected] 47 [email protected] "{"
48 [email protected] "{" 48 [email protected] "\n "
49 [email protected] "\n " 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected] "abc"
52 [email protected] "abc" 52 [email protected] ":"
53 [email protected] ":" 53 [email protected] " "
54 [email protected] " " 54 [email protected]
55 [email protected] 55 [email protected] "{"
56 [email protected] "{" 56 [email protected] "}"
57 [email protected] "}" 57 [email protected]
58 [email protected] 58 [email protected] ","
59 [email protected] "," 59 [email protected] " "
60 [email protected] " " 60 [email protected] "//~ ERROR: expected t ..."
61 [email protected] "//~ ERROR: expected t ..." 61 [email protected] "\n "
62 [email protected] "\n " 62 [email protected] "}"
63 [email protected] "}" 63 [email protected] ","
64 [email protected] "," 64 [email protected] "\n "
65 [email protected] "\n " 65 [email protected] "}"
66 [email protected] "}" 66 [email protected] "\n\n "
67 [email protected] "\n\n " 67 [email protected] "// recover..."
68 [email protected] "// recover..." 68 [email protected] "\n "
69 [email protected] "\n " 69 [email protected]
70 [email protected] 70 [email protected] "let"
71 [email protected] "let" 71 [email protected] " "
72 [email protected] " " 72 [email protected]
73 [email protected] 73 [email protected]
74 [email protected] 74 [email protected] "a"
75 [email protected] "a" 75 [email protected] " "
76 [email protected] " " 76 [email protected] "="
77 [email protected] "=" 77 [email protected] " "
78 [email protected] " " 78 [email protected]
79 [email protected] 79 [email protected] "1"
80 [email protected] "1" 80 [email protected] ";"
81 [email protected] ";" 81 [email protected] "\n "
82 [email protected] "\n " 82 [email protected]
83 [email protected] 83 [email protected] "enum"
84 [email protected] "enum" 84 [email protected] " "
85 [email protected] " " 85 [email protected]
86 [email protected] 86 [email protected] "Test2"
87 [email protected] "Test2" 87 [email protected] " "
88 [email protected] " " 88 [email protected]
89 [email protected] 89 [email protected] "{"
90 [email protected] "{" 90 [email protected] "\n "
91 [email protected] "\n " 91 [email protected]
92 [email protected] 92 [email protected]
93 [email protected] 93 [email protected] "Fine"
94 [email protected] "Fine" 94 [email protected] ","
95 [email protected] "," 95 [email protected] "\n "
96 [email protected] "\n " 96 [email protected] "}"
97 [email protected] "}" 97 [email protected] "\n\n "
98 [email protected] "\n\n " 98 [email protected]
99 [email protected] 99 [email protected] "enum"
100 [email protected] "enum" 100 [email protected] " "
101 [email protected] " " 101 [email protected]
102 [email protected] 102 [email protected] "Test3"
103 [email protected] "Test3" 103 [email protected] " "
104 [email protected] " " 104 [email protected]
105 [email protected] 105 [email protected] "{"
106 [email protected] "{" 106 [email protected] "\n "
107 [email protected] "\n " 107 [email protected]
108 [email protected] 108 [email protected]
109 [email protected] 109 [email protected] "StillFine"
110 [email protected] "StillFine" 110 [email protected] " "
111 [email protected] " " 111 [email protected]
112 [email protected] 112 [email protected] "{"
113 [email protected] "{" 113 [email protected] "\n "
114 [email protected] "\n " 114 [email protected]
115 [email protected] 115 [email protected]
116 [email protected] 116 [email protected] "def"
117 [email protected] "def" 117 [email protected] ":"
118 [email protected] ":" 118 [email protected] " "
119 [email protected] " " 119 [email protected]
120 [email protected] 120 [email protected]
121 [email protected] 121 [email protected]
122 [email protected] 122 [email protected]
123 [email protected] 123 [email protected] "i32"
124 [email protected] "i32" 124 [email protected] ","
125 [email protected] "," 125 [email protected] "\n "
126 [email protected] "\n " 126 [email protected] "}"
127 [email protected] "}" 127 [email protected] ","
128 [email protected] "," 128 [email protected] "\n "
129 [email protected] "\n " 129 [email protected] "}"
130 [email protected] "}" 130 [email protected] "\n\n "
131 [email protected] "\n\n " 131 [email protected]
132 [email protected] 132 [email protected]
133 [email protected] 133 [email protected] "{"
134 [email protected] 134 [email protected] "\n "
135 [email protected] "{" 135 [email protected]
136 [email protected] "\n " 136 [email protected] "// fail again"
137 [email protected] 137 [email protected] "\n "
138 [email protected] "// fail again" 138 [email protected] "enum"
139 [email protected] "\n " 139 [email protected] " "
140 [email protected] "enum" 140 [email protected]
141 [email protected] " " 141 [email protected] "Test4"
142 [email protected] 142 [email protected] " "
143 [email protected] "Test4" 143 [email protected]
144 [email protected] " " 144 [email protected] "{"
145 [email protected] 145 [email protected] "\n "
146 [email protected] "{" 146 [email protected]
147 [email protected] "\n " 147 [email protected]
148 [email protected] 148 [email protected] "Nope"
149 [email protected] 149 [email protected]
150 [email protected] "Nope" 150 [email protected] "("
151 [email protected] 151 [email protected]
152 [email protected] "(" 152 [email protected]
153 [email protected] 153 [email protected]
154 [email protected] 154 [email protected]
155 [email protected] 155 [email protected]
156 [email protected] 156 [email protected] "i32"
157 [email protected] 157 [email protected] " "
158 [email protected] "i32" 158 [email protected]
159 [email protected] " " 159 [email protected]
160 [email protected] 160 [email protected] "{"
161 [email protected] 161 [email protected] "}"
162 [email protected] "{" 162 [email protected]
163 [email protected] "}" 163 [email protected] ")"
164 [email protected] 164 [email protected] " "
165 [email protected] ")" 165 [email protected] "//~ ERROR: found `{`"
166 [email protected] " " 166 [email protected] "\n ..."
167 [email protected] "//~ ERROR: found `{`" 167 [email protected] "//~^ ERROR: found `{`"
168 [email protected] "\n ..." 168 [email protected] "\n "
169 [email protected] "//~^ ERROR: found `{`" 169 [email protected] "}"
170 [email protected] "\n " 170 [email protected] "\n "
171 [email protected] "}" 171 [email protected] "}"
172 [email protected] "\n " 172 [email protected] "\n "
173 [email protected] "}" 173 [email protected] "// still recover later"
174 [email protected] "\n " 174 [email protected] "\n "
175 [email protected] "// still recover later" 175 [email protected]
176 [email protected] "\n " 176 [email protected] "let"
177 [email protected] 177 [email protected] " "
178 [email protected] "let" 178 [email protected]
179 [email protected] " " 179 [email protected]
180 [email protected] 180 [email protected] "bad_syntax"
181 [email protected] 181 [email protected] " "
182 [email protected] "bad_syntax" 182 [email protected] "="
183 [email protected] " " 183 [email protected] " "
184 [email protected] "=" 184 [email protected]
185 [email protected] " " 185 [email protected] "_"
186 [email protected] 186 [email protected] ";"
187 [email protected] "_" 187 [email protected] " "
188 [email protected] ";" 188 [email protected] "//~ ERROR: expected e ..."
189 [email protected] " " 189 [email protected] "\n"
190 [email protected] "//~ ERROR: expected e ..." 190 [email protected] "}"
191 [email protected] "\n"
192 [email protected] "}"
193 [email protected] "\n" 191 [email protected] "\n"
194error 95..95: expected type 192error 95..95: expected type
195error 95..95: expected COMMA 193error 95..95: expected COMMA
diff --git a/crates/ra_syntax/test_data/parser/err/0027_incomplere_where_for.rast b/crates/ra_syntax/test_data/parser/err/0027_incomplere_where_for.rast
index f2fada510..568a4cc02 100644
--- a/crates/ra_syntax/test_data/parser/err/0027_incomplere_where_for.rast
+++ b/crates/ra_syntax/test_data/parser/err/0027_incomplere_where_for.rast
@@ -21,9 +21,8 @@ [email protected]
21 [email protected] ">" 21 [email protected] ">"
22 [email protected] "\n" 22 [email protected] "\n"
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected] "{"
25 [email protected] "{" 25 [email protected] "}"
26 [email protected] "}"
27 [email protected] "\n" 26 [email protected] "\n"
28error 26..26: expected a path 27error 26..26: expected a path
29error 26..26: expected colon 28error 26..26: expected colon
diff --git a/crates/ra_syntax/test_data/parser/err/0029_field_completion.rast b/crates/ra_syntax/test_data/parser/err/0029_field_completion.rast
index 56682f966..0da8f59f0 100644
--- a/crates/ra_syntax/test_data/parser/err/0029_field_completion.rast
+++ b/crates/ra_syntax/test_data/parser/err/0029_field_completion.rast
@@ -20,17 +20,16 @@ [email protected]
20 [email protected] ")" 20 [email protected] ")"
21 [email protected] " " 21 [email protected] " "
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] "{" 24 [email protected] "\n "
25 [email protected] "\n " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "a"
31 [email protected] "a" 31 [email protected] "."
32 [email protected] "." 32 [email protected] "\n"
33 [email protected] "\n" 33 [email protected] "}"
34 [email protected] "}"
35 [email protected] "\n" 34 [email protected] "\n"
36error 21..21: expected field name or number 35error 21..21: expected field name or number
diff --git a/crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.rast b/crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.rast
index aac476430..515819e42 100644
--- a/crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.rast
+++ b/crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.rast
@@ -9,115 +9,111 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "inner"
20 [email protected] "inner" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "="
22 [email protected] "=" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "{"
25 [email protected] 25 [email protected] "\n "
26 [email protected] "{" 26 [email protected]
27 [email protected] "\n " 27 [email protected] "#"
28 [email protected] 28 [email protected] "!"
29 [email protected] "#" 29 [email protected] "["
30 [email protected] "!" 30 [email protected]
31 [email protected] "[" 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected] "doc"
34 [email protected] 34 [email protected]
35 [email protected] "doc" 35 [email protected] "("
36 [email protected] 36 [email protected] "\"Inner attributes not ..."
37 [email protected] "(" 37 [email protected] ")"
38 [email protected] "\"Inner attributes not ..." 38 [email protected] "]"
39 [email protected] ")" 39 [email protected] "\n "
40 [email protected] "]" 40 [email protected] "//! Nor are ModuleDoc ..."
41 [email protected] "\n " 41 [email protected] "\n "
42 [email protected] "//! Nor are ModuleDoc ..." 42 [email protected] "}"
43 [email protected] "\n " 43 [email protected] ";"
44 [email protected] "}" 44 [email protected] "\n "
45 [email protected] ";" 45 [email protected]
46 [email protected] "\n " 46 [email protected]
47 [email protected] 47 [email protected] "if"
48 [email protected] 48 [email protected] " "
49 [email protected] "if" 49 [email protected]
50 [email protected] " " 50 [email protected]
51 [email protected] 51 [email protected] "true"
52 [email protected] 52 [email protected] " "
53 [email protected] "true" 53 [email protected]
54 [email protected] " " 54 [email protected] "{"
55 [email protected] 55 [email protected] "\n "
56 [email protected] 56 [email protected]
57 [email protected] "{" 57 [email protected] "#"
58 [email protected] "\n " 58 [email protected] "!"
59 [email protected] 59 [email protected] "["
60 [email protected] "#" 60 [email protected]
61 [email protected] "!" 61 [email protected]
62 [email protected] "[" 62 [email protected]
63 [email protected] 63 [email protected] "doc"
64 [email protected] 64 [email protected]
65 [email protected] 65 [email protected] "("
66 [email protected] "doc" 66 [email protected] "\"Nor here\""
67 [email protected] 67 [email protected] ")"
68 [email protected] "(" 68 [email protected] "]"
69 [email protected] "\"Nor here\"" 69 [email protected] "\n "
70 [email protected] ")" 70 [email protected]
71 [email protected] "]" 71 [email protected] "#"
72 [email protected] "\n " 72 [email protected] "!"
73 [email protected] 73 [email protected] "["
74 [email protected] "#" 74 [email protected]
75 [email protected] "!" 75 [email protected]
76 [email protected] "[" 76 [email protected]
77 [email protected] 77 [email protected] "doc"
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected] "("
80 [email protected] "doc" 80 [email protected] "\"We error on each attr\""
81 [email protected] 81 [email protected] ")"
82 [email protected] "(" 82 [email protected] "]"
83 [email protected] "\"We error on each attr\"" 83 [email protected] "\n "
84 [email protected] ")" 84 [email protected] "//! Nor are ModuleDoc ..."
85 [email protected] "]" 85 [email protected] "\n "
86 [email protected] "\n " 86 [email protected] "}"
87 [email protected] "//! Nor are ModuleDoc ..." 87 [email protected] "\n "
88 [email protected] "\n " 88 [email protected]
89 [email protected] "}" 89 [email protected] "while"
90 [email protected] "\n " 90 [email protected] " "
91 [email protected] 91 [email protected]
92 [email protected] "while" 92 [email protected]
93 [email protected] " " 93 [email protected] "true"
94 [email protected] 94 [email protected] " "
95 [email protected] 95 [email protected]
96 [email protected] "true" 96 [email protected] "{"
97 [email protected] " " 97 [email protected] "\n "
98 [email protected] 98 [email protected]
99 [email protected] 99 [email protected] "#"
100 [email protected] "{" 100 [email protected] "!"
101 [email protected] "\n " 101 [email protected] "["
102 [email protected] 102 [email protected]
103 [email protected] "#" 103 [email protected]
104 [email protected] "!" 104 [email protected]
105 [email protected] "[" 105 [email protected] "doc"
106 [email protected] 106 [email protected]
107 [email protected] 107 [email protected] "("
108 [email protected] 108 [email protected] "\"Nor here\""
109 [email protected] "doc" 109 [email protected] ")"
110 [email protected] 110 [email protected] "]"
111 [email protected] "(" 111 [email protected] "\n "
112 [email protected] "\"Nor here\"" 112 [email protected] "//! Nor are ModuleDoc ..."
113 [email protected] ")" 113 [email protected] "\n "
114 [email protected] "]" 114 [email protected] "}"
115 [email protected] "\n " 115 [email protected] "\n"
116 [email protected] "//! Nor are ModuleDoc ..." 116 [email protected] "}"
117 [email protected] "\n "
118 [email protected] "}"
119 [email protected] "\n"
120 [email protected] "}"
121 [email protected] "\n" 117 [email protected] "\n"
122error 39..83: A block in this position cannot accept inner attributes 118error 39..83: A block in this position cannot accept inner attributes
123error 152..171: A block in this position cannot accept inner attributes 119error 152..171: A block in this position cannot accept inner attributes
diff --git a/crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast b/crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast
index f98de7f15..c6859eca8 100644
--- a/crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast
+++ b/crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.rast
@@ -9,187 +9,186 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "match"
17 [email protected] "match" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected] "("
20 [email protected] "(" 20 [email protected] ")"
21 [email protected] ")" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] "{" 24 [email protected] "\n "
25 [email protected] "\n " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected] "_"
28 [email protected] "_" 28 [email protected] " "
29 [email protected] " " 29 [email protected] "=>"
30 [email protected] "=>" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "("
33 [email protected] "(" 33 [email protected] ")"
34 [email protected] ")" 34 [email protected] ","
35 [email protected] "," 35 [email protected] "\n "
36 [email protected] "\n " 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "#"
39 [email protected] "#" 39 [email protected]
40 [email protected] 40 [email protected] "!"
41 [email protected] "!" 41 [email protected]
42 [email protected] 42 [email protected] "["
43 [email protected] "[" 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "doc"
49 [email protected] "doc" 49 [email protected]
50 [email protected] 50 [email protected] "("
51 [email protected] "(" 51 [email protected]
52 [email protected] 52 [email protected] "\"Not allowed here\""
53 [email protected] "\"Not allowed here\"" 53 [email protected] ")"
54 [email protected] ")" 54 [email protected] "]"
55 [email protected] "]" 55 [email protected] "\n "
56 [email protected] "\n " 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected] "_"
59 [email protected] "_" 59 [email protected] " "
60 [email protected] " " 60 [email protected] "=>"
61 [email protected] "=>" 61 [email protected] " "
62 [email protected] " " 62 [email protected]
63 [email protected] 63 [email protected] "("
64 [email protected] "(" 64 [email protected] ")"
65 [email protected] ")" 65 [email protected] ","
66 [email protected] "," 66 [email protected] "\n "
67 [email protected] "\n " 67 [email protected] "}"
68 [email protected] "}" 68 [email protected] "\n\n "
69 [email protected] "\n\n " 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected] "match"
72 [email protected] "match" 72 [email protected] " "
73 [email protected] " " 73 [email protected]
74 [email protected] 74 [email protected] "("
75 [email protected] "(" 75 [email protected] ")"
76 [email protected] ")" 76 [email protected] " "
77 [email protected] " " 77 [email protected]
78 [email protected] 78 [email protected] "{"
79 [email protected] "{" 79 [email protected] "\n "
80 [email protected] "\n " 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "_"
83 [email protected] "_" 83 [email protected] " "
84 [email protected] " " 84 [email protected] "=>"
85 [email protected] "=>" 85 [email protected] " "
86 [email protected] " " 86 [email protected]
87 [email protected] 87 [email protected] "("
88 [email protected] "(" 88 [email protected] ")"
89 [email protected] ")" 89 [email protected] ","
90 [email protected] "," 90 [email protected] "\n "
91 [email protected] "\n " 91 [email protected]
92 [email protected] 92 [email protected]
93 [email protected] 93 [email protected] "_"
94 [email protected] "_" 94 [email protected] " "
95 [email protected] " " 95 [email protected] "=>"
96 [email protected] "=>" 96 [email protected] " "
97 [email protected] " " 97 [email protected]
98 [email protected] 98 [email protected] "("
99 [email protected] "(" 99 [email protected] ")"
100 [email protected] ")" 100 [email protected] ","
101 [email protected] "," 101 [email protected] "\n "
102 [email protected] "\n " 102 [email protected]
103 [email protected] 103 [email protected]
104 [email protected] 104 [email protected] "#"
105 [email protected] "#" 105 [email protected]
106 [email protected] 106 [email protected] "!"
107 [email protected] "!" 107 [email protected]
108 [email protected] 108 [email protected] "["
109 [email protected] "[" 109 [email protected]
110 [email protected] 110 [email protected]
111 [email protected] 111 [email protected]
112 [email protected] 112 [email protected]
113 [email protected] 113 [email protected]
114 [email protected] 114 [email protected] "doc"
115 [email protected] "doc" 115 [email protected]
116 [email protected] 116 [email protected] "("
117 [email protected] "(" 117 [email protected]
118 [email protected] 118 [email protected] "\"Nor here\""
119 [email protected] "\"Nor here\"" 119 [email protected] ")"
120 [email protected] ")" 120 [email protected] "]"
121 [email protected] "]" 121 [email protected] "\n "
122 [email protected] "\n " 122 [email protected] "}"
123 [email protected] "}" 123 [email protected] "\n\n "
124 [email protected] "\n\n " 124 [email protected]
125 [email protected] 125 [email protected] "match"
126 [email protected] "match" 126 [email protected] " "
127 [email protected] " " 127 [email protected]
128 [email protected] 128 [email protected] "("
129 [email protected] "(" 129 [email protected] ")"
130 [email protected] ")" 130 [email protected] " "
131 [email protected] " " 131 [email protected]
132 [email protected] 132 [email protected] "{"
133 [email protected] "{" 133 [email protected] "\n "
134 [email protected] "\n " 134 [email protected]
135 [email protected] 135 [email protected]
136 [email protected] 136 [email protected] "#"
137 [email protected] "#" 137 [email protected] "["
138 [email protected] "[" 138 [email protected]
139 [email protected] 139 [email protected]
140 [email protected] 140 [email protected]
141 [email protected] 141 [email protected] "cfg"
142 [email protected] "cfg" 142 [email protected]
143 [email protected] 143 [email protected] "("
144 [email protected] "(" 144 [email protected] "test"
145 [email protected] "test" 145 [email protected] ")"
146 [email protected] ")" 146 [email protected] "]"
147 [email protected] "]" 147 [email protected] "\n "
148 [email protected] "\n " 148 [email protected]
149 [email protected] 149 [email protected] "#"
150 [email protected] "#" 150 [email protected]
151 [email protected] 151 [email protected] "!"
152 [email protected] "!" 152 [email protected]
153 [email protected] 153 [email protected] "["
154 [email protected] "[" 154 [email protected]
155 [email protected] 155 [email protected]
156 [email protected] 156 [email protected]
157 [email protected] 157 [email protected]
158 [email protected] 158 [email protected]
159 [email protected] 159 [email protected] "doc"
160 [email protected] "doc" 160 [email protected]
161 [email protected] 161 [email protected] "("
162 [email protected] "(" 162 [email protected]
163 [email protected] 163 [email protected] "\"Nor here\""
164 [email protected] "\"Nor here\"" 164 [email protected] ")"
165 [email protected] ")" 165 [email protected] "]"
166 [email protected] "]" 166 [email protected] "\n "
167 [email protected] "\n " 167 [email protected]
168 [email protected] 168 [email protected]
169 [email protected] 169 [email protected] "_"
170 [email protected] "_" 170 [email protected] " "
171 [email protected] " " 171 [email protected] "=>"
172 [email protected] "=>" 172 [email protected] " "
173 [email protected] " " 173 [email protected]
174 [email protected] 174 [email protected] "("
175 [email protected] "(" 175 [email protected] ")"
176 [email protected] ")" 176 [email protected] ","
177 [email protected] "," 177 [email protected] "\n "
178 [email protected] "\n " 178 [email protected]
179 [email protected] 179 [email protected]
180 [email protected] 180 [email protected] "_"
181 [email protected] "_" 181 [email protected] " "
182 [email protected] " " 182 [email protected] "=>"
183 [email protected] "=>" 183 [email protected] " "
184 [email protected] " " 184 [email protected]
185 [email protected] 185 [email protected] "("
186 [email protected] "(" 186 [email protected] ")"
187 [email protected] ")" 187 [email protected] ","
188 [email protected] "," 188 [email protected] "\n "
189 [email protected] "\n " 189 [email protected] "}"
190 [email protected] "}" 190 [email protected] "\n"
191 [email protected] "\n" 191 [email protected] "}"
192 [email protected] "}"
193 [email protected] "\n" 192 [email protected] "\n"
194error 52..52: expected `[` 193error 52..52: expected `[`
195error 52..52: expected pattern 194error 52..52: expected pattern
diff --git a/crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast b/crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast
index d0017c883..53e445459 100644
--- a/crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast
+++ b/crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.rast
@@ -9,58 +9,57 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected] ")"
20 [email protected] ")" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "_"
27 [email protected] "_" 27 [email protected] " "
28 [email protected] " " 28 [email protected] "=>"
29 [email protected] "=>" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "("
32 [email protected] "(" 32 [email protected] ")"
33 [email protected] ")" 33 [email protected] ","
34 [email protected] "," 34 [email protected] "\n "
35 [email protected] "\n " 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected] "_"
38 [email protected] "_" 38 [email protected] " "
39 [email protected] " " 39 [email protected] "=>"
40 [email protected] "=>" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected] "("
43 [email protected] "(" 43 [email protected] ")"
44 [email protected] ")" 44 [email protected] ","
45 [email protected] "," 45 [email protected] "\n "
46 [email protected] "\n " 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "#"
49 [email protected] "#" 49 [email protected] "["
50 [email protected] "[" 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected] "cfg"
54 [email protected] "cfg" 54 [email protected]
55 [email protected] 55 [email protected] "("
56 [email protected] "(" 56 [email protected] "test"
57 [email protected] "test" 57 [email protected] ")"
58 [email protected] ")" 58 [email protected] "]"
59 [email protected] "]" 59 [email protected] "\n "
60 [email protected] "\n " 60 [email protected] "}"
61 [email protected] "}" 61 [email protected] "\n"
62 [email protected] "\n" 62 [email protected] "}"
63 [email protected] "}"
64 [email protected] "\n" 63 [email protected] "\n"
65error 80..80: expected pattern 64error 80..80: expected pattern
66error 80..80: expected FAT_ARROW 65error 80..80: expected FAT_ARROW
diff --git a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rast b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rast
index 2c0bddec8..1b2ac5011 100644
--- a/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rast
+++ b/crates/ra_syntax/test_data/parser/err/0034_bad_box_pattern.rast
@@ -9,84 +9,83 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "ref"
19 [email protected] "ref" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "box"
22 [email protected] "box" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "i"
30 [email protected] "i" 30 [email protected] " "
31 [email protected] " " 31 [email protected] "="
32 [email protected] "=" 32 [email protected] " "
33 [email protected] " " 33 [email protected]
34 [email protected] 34 [email protected] "("
35 [email protected] "(" 35 [email protected] ")"
36 [email protected] ")" 36 [email protected] ";"
37 [email protected] ";" 37 [email protected] "\n "
38 [email protected] "\n " 38 [email protected]
39 [email protected] 39 [email protected] "let"
40 [email protected] "let" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected] "mut"
43 [email protected] "mut" 43 [email protected] " "
44 [email protected] " " 44 [email protected]
45 [email protected] 45 [email protected] "box"
46 [email protected] "box" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected] "i"
54 [email protected] "i" 54 [email protected] " "
55 [email protected] " " 55 [email protected] "="
56 [email protected] "=" 56 [email protected] " "
57 [email protected] " " 57 [email protected]
58 [email protected] 58 [email protected] "("
59 [email protected] "(" 59 [email protected] ")"
60 [email protected] ")" 60 [email protected] ";"
61 [email protected] ";" 61 [email protected] "\n "
62 [email protected] "\n " 62 [email protected]
63 [email protected] 63 [email protected] "let"
64 [email protected] "let" 64 [email protected] " "
65 [email protected] " " 65 [email protected]
66 [email protected] 66 [email protected] "ref"
67 [email protected] "ref" 67 [email protected] " "
68 [email protected] " " 68 [email protected] "mut"
69 [email protected] "mut" 69 [email protected] " "
70 [email protected] " " 70 [email protected]
71 [email protected] 71 [email protected] "box"
72 [email protected] "box" 72 [email protected] " "
73 [email protected] " " 73 [email protected]
74 [email protected] 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected] "i"
80 [email protected] "i" 80 [email protected] " "
81 [email protected] " " 81 [email protected] "="
82 [email protected] "=" 82 [email protected] " "
83 [email protected] " " 83 [email protected]
84 [email protected] 84 [email protected] "("
85 [email protected] "(" 85 [email protected] ")"
86 [email protected] ")" 86 [email protected] ";"
87 [email protected] ";" 87 [email protected] "\n"
88 [email protected] "\n" 88 [email protected] "}"
89 [email protected] "}"
90 [email protected] "\n\n" 89 [email protected] "\n\n"
91error 24..24: expected a name 90error 24..24: expected a name
92error 27..27: expected SEMICOLON 91error 27..27: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/err/0035_use_recover.rast b/crates/ra_syntax/test_data/parser/err/0035_use_recover.rast
index 83851f5d2..9588cf3b3 100644
--- a/crates/ra_syntax/test_data/parser/err/0035_use_recover.rast
+++ b/crates/ra_syntax/test_data/parser/err/0035_use_recover.rast
@@ -44,9 +44,8 @@ [email protected]
44 [email protected] ")" 44 [email protected] ")"
45 [email protected] " " 45 [email protected] " "
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected] "{"
48 [email protected] "{" 48 [email protected] "}"
49 [email protected] "}"
50 [email protected] "\n" 49 [email protected] "\n"
51error 17..17: expected one of `*`, `::`, `{`, `self`, `super` or an identifier 50error 17..17: expected one of `*`, `::`, `{`, `self`, `super` or an identifier
52error 17..17: expected SEMICOLON 51error 17..17: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rast b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rast
index a328222aa..e3cda7c43 100644
--- a/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rast
+++ b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rast
@@ -27,9 +27,8 @@ [email protected]
27 [email protected] ")" 27 [email protected] ")"
28 [email protected] " " 28 [email protected] " "
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "{"
31 [email protected] "{" 31 [email protected] "}"
32 [email protected] "}"
33 [email protected] "\n " 32 [email protected] "\n "
34 [email protected] 33 [email protected]
35 [email protected] 34 [email protected]
@@ -44,9 +43,8 @@ [email protected]
44 [email protected] ")" 43 [email protected] ")"
45 [email protected] " " 44 [email protected] " "
46 [email protected] 45 [email protected]
47 [email protected] 46 [email protected] "{"
48 [email protected] "{" 47 [email protected] "}"
49 [email protected] "}"
50 [email protected] "\n " 48 [email protected] "\n "
51 [email protected] 49 [email protected]
52 [email protected] 50 [email protected]
diff --git a/crates/ra_syntax/test_data/parser/err/0038_endless_inclusive_range.rast b/crates/ra_syntax/test_data/parser/err/0038_endless_inclusive_range.rast
index bcd1fad69..21db9ee85 100644
--- a/crates/ra_syntax/test_data/parser/err/0038_endless_inclusive_range.rast
+++ b/crates/ra_syntax/test_data/parser/err/0038_endless_inclusive_range.rast
@@ -9,22 +9,21 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected] "0"
18 [email protected] "0" 18 [email protected] "..="
19 [email protected] "..=" 19 [email protected] ";"
20 [email protected] ";" 20 [email protected] "\n "
21 [email protected] "\n " 21 [email protected]
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected] "..="
24 [email protected] "..=" 24 [email protected] ";"
25 [email protected] ";" 25 [email protected] "\n"
26 [email protected] "\n" 26 [email protected] "}"
27 [email protected] "}"
28 [email protected] "\n" 27 [email protected] "\n"
29error 16..20: An inclusive range must have an end expression 28error 16..20: An inclusive range must have an end expression
30error 26..29: An inclusive range must have an end expression 29error 26..29: An inclusive range must have an end expression
diff --git a/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rast b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rast
index 433ea7bad..ec950381b 100644
--- a/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rast
+++ b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rast
@@ -18,66 +18,65 @@ [email protected]
18 [email protected] "i32" 18 [email protected] "i32"
19 [email protected] " " 19 [email protected] " "
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "{"
22 [email protected] "{" 22 [email protected] "\n "
23 [email protected] "\n " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected] "["
29 [email protected] "[" 29 [email protected]
30 [email protected] 30 [email protected] "1"
31 [email protected] "1" 31 [email protected] ","
32 [email protected] "," 32 [email protected] " "
33 [email protected] " " 33 [email protected]
34 [email protected] 34 [email protected] "2"
35 [email protected] "2" 35 [email protected] ","
36 [email protected] "," 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected] "3"
39 [email protected] "3" 39 [email protected] "]"
40 [email protected] "]" 40 [email protected] "."
41 [email protected] "." 41 [email protected]
42 [email protected] 42 [email protected] "iter"
43 [email protected] "iter" 43 [email protected]
44 [email protected] 44 [email protected] "("
45 [email protected] "(" 45 [email protected] ")"
46 [email protected] ")" 46 [email protected] "\n "
47 [email protected] "\n " 47 [email protected] "."
48 [email protected] "." 48 [email protected]
49 [email protected] 49 [email protected] "map"
50 [email protected] "map" 50 [email protected]
51 [email protected] 51 [email protected] "("
52 [email protected] "(" 52 [email protected]
53 [email protected] 53 [email protected]
54 [email protected] 54 [email protected] "|"
55 [email protected] "|" 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected] "it"
59 [email protected] "it" 59 [email protected] "|"
60 [email protected] "|" 60 [email protected] ")"
61 [email protected] ")" 61 [email protected] "\n "
62 [email protected] "\n " 62 [email protected] "."
63 [email protected] "." 63 [email protected]
64 [email protected] 64 [email protected] "max"
65 [email protected] "max" 65 [email protected]
66 [email protected] 66 [email protected] "::"
67 [email protected] "::" 67 [email protected] "<"
68 [email protected] "<" 68 [email protected]
69 [email protected] 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected]
72 [email protected] 72 [email protected]
73 [email protected] 73 [email protected] "i32"
74 [email protected] "i32" 74 [email protected] ">"
75 [email protected] ">" 75 [email protected]
76 [email protected] 76 [email protected] "("
77 [email protected] "(" 77 [email protected] ")"
78 [email protected] ")" 78 [email protected] ";"
79 [email protected] ";" 79 [email protected] "\n"
80 [email protected] "\n" 80 [email protected] "}"
81 [email protected] "}"
82 [email protected] "\n" 81 [email protected] "\n"
83error 56..56: expected expression 82error 56..56: expected expression
diff --git a/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rast b/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rast
new file mode 100644
index 000000000..e46456384
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rast
@@ -0,0 +1,71 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "main"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] "\n "
14 [email protected]
15 [email protected]
16 [email protected] "{"
17 [email protected] " "
18 [email protected]
19 [email protected] "unsafe"
20 [email protected] " "
21 [email protected]
22 [email protected] "92"
23 [email protected] " "
24 [email protected] "}"
25 [email protected] "\n "
26 [email protected]
27 [email protected]
28 [email protected] "{"
29 [email protected] " "
30 [email protected]
31 [email protected] "async"
32 [email protected] " "
33 [email protected]
34 [email protected] "92"
35 [email protected] " "
36 [email protected] "}"
37 [email protected] "\n "
38 [email protected]
39 [email protected]
40 [email protected] "{"
41 [email protected] " "
42 [email protected]
43 [email protected]
44 [email protected] "try"
45 [email protected] " "
46 [email protected]
47 [email protected] "92"
48 [email protected] " "
49 [email protected] "}"
50 [email protected] "\n "
51 [email protected]
52 [email protected] "{"
53 [email protected] " "
54 [email protected]
55 [email protected]
56 [email protected]
57 [email protected] "\'label"
58 [email protected] ":"
59 [email protected] " "
60 [email protected]
61 [email protected] "92"
62 [email protected] " "
63 [email protected] "}"
64 [email protected] "\n"
65 [email protected] "}"
66 [email protected] "\n"
67error 24..24: expected existential, fn, trait or impl
68error 41..41: expected existential, fn, trait or impl
69error 56..56: expected a block
70error 75..75: expected a loop
71error 75..75: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rs b/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rs
new file mode 100644
index 000000000..8fa324c1a
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0163_weird_blocks.rs
@@ -0,0 +1,6 @@
1fn main() {
2 { unsafe 92 }
3 { async 92 }
4 { try 92 }
5 { 'label: 92 }
6}
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast b/crates/ra_syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast
index 85bf276a0..75668c818 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0002_misplaced_label_err.rast
@@ -9,19 +9,18 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected] "\'loop"
18 [email protected] "\'loop" 18 [email protected] ":"
19 [email protected] ":" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "impl"
22 [email protected] "impl" 22 [email protected] "\n"
23 [email protected] "\n" 23 [email protected] "}"
24 [email protected] "}"
25 [email protected] "\n" 24 [email protected] "\n"
26error 22..22: expected a loop 25error 22..22: expected a loop
27error 22..22: expected SEMICOLON 26error 22..22: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast b/crates/ra_syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast
index b901c17f7..c789e8d82 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0006_unsafe_block_in_mod.rast
@@ -8,9 +8,8 @@ [email protected]
8 [email protected] "(" 8 [email protected] "("
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] 10 [email protected]
11 [email protected] 11 [email protected] "{"
12 [email protected] "{" 12 [email protected] "}"
13 [email protected] "}"
14 [email protected] " " 13 [email protected] " "
15 [email protected] 14 [email protected]
16 [email protected] "unsafe" 15 [email protected] "unsafe"
@@ -29,9 +28,8 @@ [email protected]
29 [email protected] "(" 28 [email protected] "("
30 [email protected] ")" 29 [email protected] ")"
31 [email protected] 30 [email protected]
32 [email protected] 31 [email protected] "{"
33 [email protected] "{" 32 [email protected] "}"
34 [email protected] "}"
35 [email protected] "\n" 33 [email protected] "\n"
36error 11..11: expected an item 34error 11..11: expected an item
37error 18..18: expected an item 35error 18..18: expected an item
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast b/crates/ra_syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast
index 3f48b86ed..cd24313d4 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0007_async_without_semicolon.rast
@@ -9,24 +9,23 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "async"
24 [email protected] "async" 24 [email protected] " "
25 [email protected] " " 25 [email protected]
26 [email protected] 26 [email protected] "{"
27 [email protected] "{" 27 [email protected] "}"
28 [email protected] "}" 28 [email protected] " "
29 [email protected] " " 29 [email protected] "}"
30 [email protected] "}"
31 [email protected] "\n" 30 [email protected] "\n"
32error 27..27: expected SEMICOLON 31error 27..27: expected SEMICOLON
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0008_pub_expr.rast b/crates/ra_syntax/test_data/parser/inline/err/0008_pub_expr.rast
index be02eaeeb..c5fa7a404 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0008_pub_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0008_pub_expr.rast
@@ -9,18 +9,17 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "pub"
17 [email protected] "pub" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "92"
21 [email protected] "92" 21 [email protected] ";"
22 [email protected] ";" 22 [email protected] " "
23 [email protected] " " 23 [email protected] "}"
24 [email protected] "}"
25 [email protected] "\n" 24 [email protected] "\n"
26error 14..14: expected an item 25error 14..14: expected an item
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast b/crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast
index b344e4f7f..0656fdf73 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.rast
@@ -9,53 +9,51 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "#"
17 [email protected] "#" 17 [email protected] "["
18 [email protected] "[" 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "A"
22 [email protected] "A" 22 [email protected] "]"
23 [email protected] "]" 23 [email protected] " "
24 [email protected] " " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "1"
27 [email protected] "1" 27 [email protected] " "
28 [email protected] " " 28 [email protected] "+"
29 [email protected] "+" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "2"
32 [email protected] "2" 32 [email protected] ";"
33 [email protected] ";" 33 [email protected] "\n "
34 [email protected] "\n " 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected] "#"
37 [email protected] "#" 37 [email protected] "["
38 [email protected] "[" 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "B"
42 [email protected] "B" 42 [email protected] "]"
43 [email protected] "]" 43 [email protected] " "
44 [email protected] " " 44 [email protected]
45 [email protected] 45 [email protected] "if"
46 [email protected] "if" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected] "true"
50 [email protected] "true" 50 [email protected] " "
51 [email protected] " " 51 [email protected]
52 [email protected] 52 [email protected] "{"
53 [email protected] 53 [email protected] "}"
54 [email protected] "{" 54 [email protected] ";"
55 [email protected] "}" 55 [email protected] "\n"
56 [email protected] ";" 56 [email protected] "}"
57 [email protected] "\n"
58 [email protected] "}"
59 [email protected] "\n" 57 [email protected] "\n"
60error 24..24: attributes are not allowed on BIN_EXPR 58error 24..24: attributes are not allowed on BIN_EXPR
61error 44..44: attributes are not allowed on IF_EXPR 59error 44..44: attributes are not allowed on IF_EXPR
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast b/crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast
index 5339a84d7..e1abc5633 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0010_bad_tuple_index_expr.rast
@@ -9,45 +9,44 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "x"
21 [email protected] "x" 21 [email protected] "."
22 [email protected] "." 22 [email protected] "0."
23 [email protected] "0." 23 [email protected] ";"
24 [email protected] ";" 24 [email protected] "\n "
25 [email protected] "\n " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected] "x"
32 [email protected] "x" 32 [email protected] "."
33 [email protected] "." 33 [email protected]
34 [email protected] 34 [email protected] "1i32"
35 [email protected] "1i32" 35 [email protected] ";"
36 [email protected] ";" 36 [email protected] "\n "
37 [email protected] "\n " 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected]
43 [email protected] 43 [email protected] "x"
44 [email protected] "x" 44 [email protected] "."
45 [email protected] "." 45 [email protected]
46 [email protected] 46 [email protected] "0x01"
47 [email protected] "0x01" 47 [email protected] ";"
48 [email protected] ";" 48 [email protected] "\n"
49 [email protected] "\n" 49 [email protected] "}"
50 [email protected] "}"
51 [email protected] "\n" 50 [email protected] "\n"
52error 27..31: Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix 51error 27..31: Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix
53error 39..43: Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix 52error 39..43: Tuple (struct) field access is only allowed through decimal integers with no underscores or suffix
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rast b/crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rast
index 20ed39046..9be441110 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0010_wrong_order_fns.rast
@@ -14,9 +14,8 @@ [email protected]
14 [email protected] ")" 14 [email protected] ")"
15 [email protected] " " 15 [email protected] " "
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected] "{"
18 [email protected] "{" 18 [email protected] "}"
19 [email protected] "}"
20 [email protected] "\n" 19 [email protected] "\n"
21 [email protected] 20 [email protected]
22 [email protected] "unsafe" 21 [email protected] "unsafe"
@@ -33,9 +32,8 @@ [email protected]
33 [email protected] ")" 32 [email protected] ")"
34 [email protected] " " 33 [email protected] " "
35 [email protected] 34 [email protected]
36 [email protected] 35 [email protected] "{"
37 [email protected] "{" 36 [email protected] "}"
38 [email protected] "}"
39 [email protected] "\n" 37 [email protected] "\n"
40error 6..6: expected existential, fn, trait or impl 38error 6..6: expected existential, fn, trait or impl
41error 31..31: expected existential, fn, trait or impl 39error 31..31: expected existential, fn, trait or impl
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast b/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast
index 88567263e..b8cd0587d 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0014_default_fn_type.rast
@@ -45,9 +45,8 @@ [email protected]
45 [email protected] ")" 45 [email protected] ")"
46 [email protected] " " 46 [email protected] " "
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "{"
49 [email protected] "{" 49 [email protected] "}"
50 [email protected] "}"
51 [email protected] "\n" 50 [email protected] "\n"
52 [email protected] "}" 51 [email protected] "}"
53 [email protected] "\n" 52 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast b/crates/ra_syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
index 578befa56..a9de44b57 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
+++ b/crates/ra_syntax/test_data/parser/inline/err/0014_record_literal_before_ellipsis_recovery.rast
@@ -9,41 +9,40 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected] "S"
19 [email protected] "S" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "{"
22 [email protected] "{" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "field"
26 [email protected] "field" 26 [email protected] " "
27 [email protected] " " 27 [email protected]
28 [email protected] 28 [email protected] ".."
29 [email protected] ".." 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "S"
36 [email protected] "S" 36 [email protected] "::"
37 [email protected] "::" 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected] "default"
40 [email protected] "default" 40 [email protected]
41 [email protected] 41 [email protected] "("
42 [email protected] "(" 42 [email protected] ")"
43 [email protected] ")" 43 [email protected] " "
44 [email protected] " " 44 [email protected] "}"
45 [email protected] "}" 45 [email protected] "\n"
46 [email protected] "\n" 46 [email protected] "}"
47 [email protected] "}"
48 [email protected] "\n" 47 [email protected] "\n"
49error 25..25: expected COLON 48error 25..25: expected COLON
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0001_trait_item_list.rast b/crates/ra_syntax/test_data/parser/inline/ok/0001_trait_item_list.rast
index a1fabb557..a38b4f573 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0001_trait_item_list.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0001_trait_item_list.rast
@@ -51,9 +51,8 @@ [email protected]
51 [email protected] ")" 51 [email protected] ")"
52 [email protected] " " 52 [email protected] " "
53 [email protected] 53 [email protected]
54 [email protected] 54 [email protected] "{"
55 [email protected] "{" 55 [email protected] "}"
56 [email protected] "}"
57 [email protected] "\n " 56 [email protected] "\n "
58 [email protected] 57 [email protected]
59 [email protected] "fn" 58 [email protected] "fn"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast b/crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast
index a46d76fde..9dc473e43 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0003_where_pred_for.rast
@@ -55,8 +55,7 @@ [email protected]
55 [email protected] ")" 55 [email protected] ")"
56 [email protected] "\n" 56 [email protected] "\n"
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected] "{"
59 [email protected] "{" 59 [email protected] " "
60 [email protected] " " 60 [email protected] "}"
61 [email protected] "}"
62 [email protected] "\n" 61 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0005_function_type_params.rast b/crates/ra_syntax/test_data/parser/inline/ok/0005_function_type_params.rast
index 5181fcd2b..6c8c1e24b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0005_function_type_params.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0005_function_type_params.rast
@@ -32,7 +32,6 @@ [email protected]
32 [email protected] "(" 32 [email protected] "("
33 [email protected] ")" 33 [email protected] ")"
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "{"
36 [email protected] "{" 36 [email protected] "}"
37 [email protected] "}"
38 [email protected] "\n" 37 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0006_self_param.rast b/crates/ra_syntax/test_data/parser/inline/ok/0006_self_param.rast
index dd41b44e1..9f4a9e69b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0006_self_param.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0006_self_param.rast
@@ -23,9 +23,8 @@ [email protected]
23 [email protected] ")" 23 [email protected] ")"
24 [email protected] " " 24 [email protected] " "
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "{"
27 [email protected] "{" 27 [email protected] "}"
28 [email protected] "}"
29 [email protected] "\n " 28 [email protected] "\n "
30 [email protected] 29 [email protected]
31 [email protected] "fn" 30 [email protected] "fn"
@@ -41,9 +40,8 @@ [email protected]
41 [email protected] ")" 40 [email protected] ")"
42 [email protected] " " 41 [email protected] " "
43 [email protected] 42 [email protected]
44 [email protected] 43 [email protected] "{"
45 [email protected] "{" 44 [email protected] "}"
46 [email protected] "}"
47 [email protected] "\n " 45 [email protected] "\n "
48 [email protected] 46 [email protected]
49 [email protected] "fn" 47 [email protected] "fn"
@@ -61,9 +59,8 @@ [email protected]
61 [email protected] ")" 59 [email protected] ")"
62 [email protected] " " 60 [email protected] " "
63 [email protected] 61 [email protected]
64 [email protected] 62 [email protected] "{"
65 [email protected] "{" 63 [email protected] "}"
66 [email protected] "}"
67 [email protected] "\n " 64 [email protected] "\n "
68 [email protected] 65 [email protected]
69 [email protected] "fn" 66 [email protected] "fn"
@@ -95,9 +92,8 @@ [email protected]
95 [email protected] ")" 92 [email protected] ")"
96 [email protected] " " 93 [email protected] " "
97 [email protected] 94 [email protected]
98 [email protected] 95 [email protected] "{"
99 [email protected] "{" 96 [email protected] "}"
100 [email protected] "}"
101 [email protected] "\n " 97 [email protected] "\n "
102 [email protected] 98 [email protected]
103 [email protected] "fn" 99 [email protected] "fn"
@@ -113,9 +109,8 @@ [email protected]
113 [email protected] ")" 109 [email protected] ")"
114 [email protected] " " 110 [email protected] " "
115 [email protected] 111 [email protected]
116 [email protected] 112 [email protected] "{"
117 [email protected] "{" 113 [email protected] "}"
118 [email protected] "}"
119 [email protected] "\n" 114 [email protected] "\n"
120 [email protected] "}" 115 [email protected] "}"
121 [email protected] "\n" 116 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.rast b/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.rast
index a8ddd20c9..10eb31d68 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0008_path_part.rast
@@ -9,89 +9,88 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected] "foo"
23 [email protected] "foo" 23 [email protected] "::"
24 [email protected] "::" 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "Bar"
27 [email protected] "Bar" 27 [email protected] " "
28 [email protected] " " 28 [email protected] "="
29 [email protected] "=" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "("
32 [email protected] "(" 32 [email protected] ")"
33 [email protected] ")" 33 [email protected] ";"
34 [email protected] ";" 34 [email protected] "\n "
35 [email protected] "\n " 35 [email protected]
36 [email protected] 36 [email protected] "let"
37 [email protected] "let" 37 [email protected] " "
38 [email protected] " " 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "::"
42 [email protected] "::" 42 [email protected]
43 [email protected] 43 [email protected] "Bar"
44 [email protected] "Bar" 44 [email protected] " "
45 [email protected] " " 45 [email protected] "="
46 [email protected] "=" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected] "("
49 [email protected] "(" 49 [email protected] ")"
50 [email protected] ")" 50 [email protected] ";"
51 [email protected] ";" 51 [email protected] "\n "
52 [email protected] "\n " 52 [email protected]
53 [email protected] 53 [email protected] "let"
54 [email protected] "let" 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected] "Bar"
60 [email protected] "Bar" 60 [email protected] " "
61 [email protected] " " 61 [email protected]
62 [email protected] 62 [email protected] "{"
63 [email protected] "{" 63 [email protected] " "
64 [email protected] " " 64 [email protected] ".."
65 [email protected] ".." 65 [email protected] " "
66 [email protected] " " 66 [email protected] "}"
67 [email protected] "}" 67 [email protected] " "
68 [email protected] " " 68 [email protected] "="
69 [email protected] "=" 69 [email protected] " "
70 [email protected] " " 70 [email protected]
71 [email protected] 71 [email protected] "("
72 [email protected] "(" 72 [email protected] ")"
73 [email protected] ")" 73 [email protected] ";"
74 [email protected] ";" 74 [email protected] "\n "
75 [email protected] "\n " 75 [email protected]
76 [email protected] 76 [email protected] "let"
77 [email protected] "let" 77 [email protected] " "
78 [email protected] " " 78 [email protected]
79 [email protected] 79 [email protected]
80 [email protected] 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "Bar"
83 [email protected] "Bar" 83 [email protected] "("
84 [email protected] "(" 84 [email protected]
85 [email protected] 85 [email protected] ".."
86 [email protected] ".." 86 [email protected] ")"
87 [email protected] ")" 87 [email protected] " "
88 [email protected] " " 88 [email protected] "="
89 [email protected] "=" 89 [email protected] " "
90 [email protected] " " 90 [email protected]
91 [email protected] 91 [email protected] "("
92 [email protected] "(" 92 [email protected] ")"
93 [email protected] ")" 93 [email protected] ";"
94 [email protected] ";" 94 [email protected] "\n"
95 [email protected] "\n" 95 [email protected] "}"
96 [email protected] "}"
97 [email protected] "\n" 96 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0009_loop_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0009_loop_expr.rast
index df8ada62a..425e5196c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0009_loop_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0009_loop_expr.rast
@@ -9,18 +9,16 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "loop"
17 [email protected] "loop" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected] "{"
20 [email protected] 20 [email protected] "}"
21 [email protected] "{" 21 [email protected] ";"
22 [email protected] "}" 22 [email protected] "\n"
23 [email protected] ";" 23 [email protected] "}"
24 [email protected] "\n"
25 [email protected] "}"
26 [email protected] "\n" 24 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.rast
index de01cc79e..d823c08fc 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0011_field_expr.rast
@@ -9,52 +9,51 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "x"
21 [email protected] "x" 21 [email protected] "."
22 [email protected] "." 22 [email protected]
23 [email protected] 23 [email protected] "foo"
24 [email protected] "foo" 24 [email protected] ";"
25 [email protected] ";" 25 [email protected] "\n "
26 [email protected] "\n " 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected] "x"
34 [email protected] "x" 34 [email protected] "."
35 [email protected] "." 35 [email protected]
36 [email protected] 36 [email protected] "0"
37 [email protected] "0" 37 [email protected] "."
38 [email protected] "." 38 [email protected]
39 [email protected] 39 [email protected] "bar"
40 [email protected] "bar" 40 [email protected] ";"
41 [email protected] ";" 41 [email protected] "\n "
42 [email protected] "\n " 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected] "x"
50 [email protected] "x" 50 [email protected] "."
51 [email protected] "." 51 [email protected]
52 [email protected] 52 [email protected] "0"
53 [email protected] "0" 53 [email protected]
54 [email protected] 54 [email protected] "("
55 [email protected] "(" 55 [email protected] ")"
56 [email protected] ")" 56 [email protected] ";"
57 [email protected] ";" 57 [email protected] "\n"
58 [email protected] "\n" 58 [email protected] "}"
59 [email protected] "}"
60 [email protected] "\n" 59 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0015_continue_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0015_continue_expr.rast
index 8ac307cb3..422912e3c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0015_continue_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0015_continue_expr.rast
@@ -9,29 +9,27 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "loop"
16 [email protected] "loop" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "{"
19 [email protected] 19 [email protected] "\n "
20 [email protected] "{" 20 [email protected]
21 [email protected] "\n " 21 [email protected]
22 [email protected] 22 [email protected] "continue"
23 [email protected] 23 [email protected] ";"
24 [email protected] "continue" 24 [email protected] "\n "
25 [email protected] ";" 25 [email protected]
26 [email protected] "\n " 26 [email protected]
27 [email protected] 27 [email protected] "continue"
28 [email protected] 28 [email protected] " "
29 [email protected] "continue" 29 [email protected] "\'l"
30 [email protected] " " 30 [email protected] ";"
31 [email protected] "\'l" 31 [email protected] "\n "
32 [email protected] ";" 32 [email protected] "}"
33 [email protected] "\n " 33 [email protected] "\n"
34 [email protected] "}" 34 [email protected] "}"
35 [email protected] "\n"
36 [email protected] "}"
37 [email protected] "\n" 35 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast b/crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast
index 6f6400d00..15da6fdd6 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0018_arb_self_types.rast
@@ -32,9 +32,8 @@ [email protected]
32 [email protected] ")" 32 [email protected] ")"
33 [email protected] " " 33 [email protected] " "
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "{"
36 [email protected] "{" 36 [email protected] "}"
37 [email protected] "}"
38 [email protected] "\n " 37 [email protected] "\n "
39 [email protected] 38 [email protected]
40 [email protected] "fn" 39 [email protected] "fn"
@@ -66,9 +65,8 @@ [email protected]
66 [email protected] ")" 65 [email protected] ")"
67 [email protected] " " 66 [email protected] " "
68 [email protected] 67 [email protected]
69 [email protected] 68 [email protected] "{"
70 [email protected] "{" 69 [email protected] "}"
71 [email protected] "}"
72 [email protected] "\n" 70 [email protected] "\n"
73 [email protected] "}" 71 [email protected] "}"
74 [email protected] "\n" 72 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0019_unary_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0019_unary_expr.rast
index ba422f1ae..10d6b2fde 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0019_unary_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0019_unary_expr.rast
@@ -9,37 +9,36 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "*"
17 [email protected] "*" 17 [email protected]
18 [email protected] 18 [email protected] "*"
19 [email protected] "*" 19 [email protected]
20 [email protected] 20 [email protected] "&"
21 [email protected] "&" 21 [email protected]
22 [email protected] 22 [email protected] "1"
23 [email protected] "1" 23 [email protected] ";"
24 [email protected] ";" 24 [email protected] "\n "
25 [email protected] "\n " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected] "!"
28 [email protected] "!" 28 [email protected]
29 [email protected] 29 [email protected] "!"
30 [email protected] "!" 30 [email protected]
31 [email protected] 31 [email protected] "true"
32 [email protected] "true" 32 [email protected] ";"
33 [email protected] ";" 33 [email protected] "\n "
34 [email protected] "\n " 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected] "-"
37 [email protected] "-" 37 [email protected]
38 [email protected] 38 [email protected] "-"
39 [email protected] "-" 39 [email protected]
40 [email protected] 40 [email protected] "1"
41 [email protected] "1" 41 [email protected] ";"
42 [email protected] ";" 42 [email protected] "\n"
43 [email protected] "\n" 43 [email protected] "}"
44 [email protected] "}"
45 [email protected] "\n" 44 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0021_impl_item_list.rast b/crates/ra_syntax/test_data/parser/inline/ok/0021_impl_item_list.rast
index de22b22dd..c204aeb63 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0021_impl_item_list.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0021_impl_item_list.rast
@@ -55,9 +55,8 @@ [email protected]
55 [email protected] ")" 55 [email protected] ")"
56 [email protected] " " 56 [email protected] " "
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected] "{"
59 [email protected] "{" 59 [email protected] "}"
60 [email protected] "}"
61 [email protected] "\n " 60 [email protected] "\n "
62 [email protected] 61 [email protected]
63 [email protected] "fn" 62 [email protected] "fn"
@@ -72,9 +71,8 @@ [email protected]
72 [email protected] ")" 71 [email protected] ")"
73 [email protected] " " 72 [email protected] " "
74 [email protected] 73 [email protected]
75 [email protected] 74 [email protected] "{"
76 [email protected] "{" 75 [email protected] "}"
77 [email protected] "}"
78 [email protected] "\n" 76 [email protected] "\n"
79 [email protected] "}" 77 [email protected] "}"
80 [email protected] "\n" 78 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0024_slice_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0024_slice_pat.rast
index 7da292a2d..7eb27d5e1 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0024_slice_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0024_slice_pat.rast
@@ -9,34 +9,33 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "["
19 [email protected] "[" 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "a"
22 [email protected] "a" 22 [email protected] ","
23 [email protected] "," 23 [email protected] " "
24 [email protected] " " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "b"
27 [email protected] "b" 27 [email protected] ","
28 [email protected] "," 28 [email protected] " "
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected] ".."
31 [email protected] ".." 31 [email protected] "]"
32 [email protected] "]" 32 [email protected] " "
33 [email protected] " " 33 [email protected] "="
34 [email protected] "=" 34 [email protected] " "
35 [email protected] " " 35 [email protected]
36 [email protected] 36 [email protected] "["
37 [email protected] "[" 37 [email protected] "]"
38 [email protected] "]" 38 [email protected] ";"
39 [email protected] ";" 39 [email protected] "\n"
40 [email protected] "\n" 40 [email protected] "}"
41 [email protected] "}"
42 [email protected] "\n" 41 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast b/crates/ra_syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
index 574942f06..b4598768e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0026_tuple_pat_fields.rast
@@ -9,97 +9,96 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "S"
22 [email protected] "S" 22 [email protected] "("
23 [email protected] "(" 23 [email protected] ")"
24 [email protected] ")" 24 [email protected] " "
25 [email protected] " " 25 [email protected] "="
26 [email protected] "=" 26 [email protected] " "
27 [email protected] " " 27 [email protected]
28 [email protected] 28 [email protected] "("
29 [email protected] "(" 29 [email protected] ")"
30 [email protected] ")" 30 [email protected] ";"
31 [email protected] ";" 31 [email protected] "\n "
32 [email protected] "\n " 32 [email protected]
33 [email protected] 33 [email protected] "let"
34 [email protected] "let" 34 [email protected] " "
35 [email protected] " " 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected] "S"
40 [email protected] "S" 40 [email protected] "("
41 [email protected] "(" 41 [email protected]
42 [email protected] 42 [email protected] "_"
43 [email protected] "_" 43 [email protected] ")"
44 [email protected] ")" 44 [email protected] " "
45 [email protected] " " 45 [email protected] "="
46 [email protected] "=" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected] "("
49 [email protected] "(" 49 [email protected] ")"
50 [email protected] ")" 50 [email protected] ";"
51 [email protected] ";" 51 [email protected] "\n "
52 [email protected] "\n " 52 [email protected]
53 [email protected] 53 [email protected] "let"
54 [email protected] "let" 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected] "S"
60 [email protected] "S" 60 [email protected] "("
61 [email protected] "(" 61 [email protected]
62 [email protected] 62 [email protected] "_"
63 [email protected] "_" 63 [email protected] ","
64 [email protected] "," 64 [email protected] ")"
65 [email protected] ")" 65 [email protected] " "
66 [email protected] " " 66 [email protected] "="
67 [email protected] "=" 67 [email protected] " "
68 [email protected] " " 68 [email protected]
69 [email protected] 69 [email protected] "("
70 [email protected] "(" 70 [email protected] ")"
71 [email protected] ")" 71 [email protected] ";"
72 [email protected] ";" 72 [email protected] "\n "
73 [email protected] "\n " 73 [email protected]
74 [email protected] 74 [email protected] "let"
75 [email protected] "let" 75 [email protected] " "
76 [email protected] " " 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected]
80 [email protected] 80 [email protected] "S"
81 [email protected] "S" 81 [email protected] "("
82 [email protected] "(" 82 [email protected]
83 [email protected] 83 [email protected] "_"
84 [email protected] "_" 84 [email protected] ","
85 [email protected] "," 85 [email protected] " "
86 [email protected] " " 86 [email protected]
87 [email protected] 87 [email protected] ".."
88 [email protected] ".." 88 [email protected] " "
89 [email protected] " " 89 [email protected] ","
90 [email protected] "," 90 [email protected] " "
91 [email protected] " " 91 [email protected]
92 [email protected] 92 [email protected]
93 [email protected] 93 [email protected] "x"
94 [email protected] "x" 94 [email protected] ")"
95 [email protected] ")" 95 [email protected] " "
96 [email protected] " " 96 [email protected] "="
97 [email protected] "=" 97 [email protected] " "
98 [email protected] " " 98 [email protected]
99 [email protected] 99 [email protected] "("
100 [email protected] "(" 100 [email protected] ")"
101 [email protected] ")" 101 [email protected] ";"
102 [email protected] ";" 102 [email protected] "\n"
103 [email protected] "\n" 103 [email protected] "}"
104 [email protected] "}"
105 [email protected] "\n" 104 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0027_ref_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0027_ref_pat.rast
index 1927438bb..b824c10a8 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0027_ref_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0027_ref_pat.rast
@@ -9,42 +9,41 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "&"
19 [email protected] "&" 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "a"
22 [email protected] "a" 22 [email protected] " "
23 [email protected] " " 23 [email protected] "="
24 [email protected] "=" 24 [email protected] " "
25 [email protected] " " 25 [email protected]
26 [email protected] 26 [email protected] "("
27 [email protected] "(" 27 [email protected] ")"
28 [email protected] ")" 28 [email protected] ";"
29 [email protected] ";" 29 [email protected] "\n "
30 [email protected] "\n " 30 [email protected]
31 [email protected] 31 [email protected] "let"
32 [email protected] "let" 32 [email protected] " "
33 [email protected] " " 33 [email protected]
34 [email protected] 34 [email protected] "&"
35 [email protected] "&" 35 [email protected] "mut"
36 [email protected] "mut" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected] "b"
40 [email protected] "b" 40 [email protected] " "
41 [email protected] " " 41 [email protected] "="
42 [email protected] "=" 42 [email protected] " "
43 [email protected] " " 43 [email protected]
44 [email protected] 44 [email protected] "("
45 [email protected] "(" 45 [email protected] ")"
46 [email protected] ")" 46 [email protected] ";"
47 [email protected] ";" 47 [email protected] "\n"
48 [email protected] "\n" 48 [email protected] "}"
49 [email protected] "}"
50 [email protected] "\n" 49 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0029_cast_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0029_cast_expr.rast
index 9effb345f..fabb09937 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0029_cast_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0029_cast_expr.rast
@@ -9,82 +9,81 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected] "82"
18 [email protected] "82" 18 [email protected] " "
19 [email protected] " " 19 [email protected] "as"
20 [email protected] "as" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "i32"
26 [email protected] "i32" 26 [email protected] ";"
27 [email protected] ";" 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected] "81"
33 [email protected] "81" 33 [email protected] " "
34 [email protected] " " 34 [email protected] "as"
35 [email protected] "as" 35 [email protected] " "
36 [email protected] " " 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected] "i8"
41 [email protected] "i8" 41 [email protected] " "
42 [email protected] " " 42 [email protected] "+"
43 [email protected] "+" 43 [email protected] " "
44 [email protected] " " 44 [email protected]
45 [email protected] 45 [email protected] "1"
46 [email protected] "1" 46 [email protected] ";"
47 [email protected] ";" 47 [email protected] "\n "
48 [email protected] "\n " 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "79"
53 [email protected] "79" 53 [email protected] " "
54 [email protected] " " 54 [email protected] "as"
55 [email protected] "as" 55 [email protected] " "
56 [email protected] " " 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected] "i16"
61 [email protected] "i16" 61 [email protected] " "
62 [email protected] " " 62 [email protected] "-"
63 [email protected] "-" 63 [email protected] " "
64 [email protected] " " 64 [email protected]
65 [email protected] 65 [email protected] "1"
66 [email protected] "1" 66 [email protected] ";"
67 [email protected] ";" 67 [email protected] "\n "
68 [email protected] "\n " 68 [email protected]
69 [email protected] 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected]
72 [email protected] 72 [email protected] "0x36"
73 [email protected] "0x36" 73 [email protected] " "
74 [email protected] " " 74 [email protected] "as"
75 [email protected] "as" 75 [email protected] " "
76 [email protected] " " 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected]
80 [email protected] 80 [email protected] "u8"
81 [email protected] "u8" 81 [email protected] " "
82 [email protected] " " 82 [email protected] "<="
83 [email protected] "<=" 83 [email protected] " "
84 [email protected] " " 84 [email protected]
85 [email protected] 85 [email protected] "0x37"
86 [email protected] "0x37" 86 [email protected] ";"
87 [email protected] ";" 87 [email protected] "\n"
88 [email protected] "\n" 88 [email protected] "}"
89 [email protected] "}"
90 [email protected] "\n" 89 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.rast b/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.rast
index b6759541e..3aed26732 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0030_cond.rast
@@ -9,39 +9,37 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected] "if"
16 [email protected] "if" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "let"
19 [email protected] "let" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected] "Some"
25 [email protected] "Some" 25 [email protected] "("
26 [email protected] "(" 26 [email protected]
27 [email protected] 27 [email protected] "_"
28 [email protected] "_" 28 [email protected] ")"
29 [email protected] ")" 29 [email protected] " "
30 [email protected] " " 30 [email protected] "="
31 [email protected] "=" 31 [email protected] " "
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected] "None"
37 [email protected] "None" 37 [email protected] " "
38 [email protected] " " 38 [email protected]
39 [email protected] 39 [email protected] "{"
40 [email protected] 40 [email protected] "}"
41 [email protected] "{" 41 [email protected] " "
42 [email protected] "}" 42 [email protected] "}"
43 [email protected] " "
44 [email protected] "}"
45 [email protected] "\n" 43 [email protected] "\n"
46 [email protected] 44 [email protected]
47 [email protected] "fn" 45 [email protected] "fn"
@@ -53,157 +51,152 @@ [email protected]
53 [email protected] ")" 51 [email protected] ")"
54 [email protected] " " 52 [email protected] " "
55 [email protected] 53 [email protected]
56 [email protected] 54 [email protected] "{"
57 [email protected] "{" 55 [email protected] "\n "
58 [email protected] "\n " 56 [email protected]
59 [email protected] 57 [email protected]
60 [email protected] 58 [email protected] "if"
61 [email protected] "if" 59 [email protected] " "
62 [email protected] " " 60 [email protected]
63 [email protected] 61 [email protected] "let"
64 [email protected] "let" 62 [email protected] " "
65 [email protected] " " 63 [email protected]
66 [email protected] 64 [email protected]
67 [email protected] 65 [email protected]
68 [email protected] 66 [email protected]
69 [email protected] 67 [email protected]
70 [email protected] 68 [email protected] "Some"
71 [email protected] "Some" 69 [email protected] "("
72 [email protected] "(" 70 [email protected]
73 [email protected] 71 [email protected] "_"
74 [email protected] "_" 72 [email protected] ")"
75 [email protected] ")" 73 [email protected] " "
76 [email protected] " " 74 [email protected] "|"
77 [email protected] "|" 75 [email protected] " "
78 [email protected] " " 76 [email protected]
79 [email protected] 77 [email protected]
80 [email protected] 78 [email protected]
81 [email protected] 79 [email protected]
82 [email protected] 80 [email protected] "Some"
83 [email protected] "Some" 81 [email protected] "("
84 [email protected] "(" 82 [email protected]
85 [email protected] 83 [email protected] "_"
86 [email protected] "_" 84 [email protected] ")"
87 [email protected] ")" 85 [email protected] " "
88 [email protected] " " 86 [email protected] "="
89 [email protected] "=" 87 [email protected] " "
90 [email protected] " " 88 [email protected]
91 [email protected] 89 [email protected]
92 [email protected] 90 [email protected]
93 [email protected] 91 [email protected]
94 [email protected] 92 [email protected] "None"
95 [email protected] "None" 93 [email protected] " "
96 [email protected] " " 94 [email protected]
97 [email protected] 95 [email protected] "{"
98 [email protected] 96 [email protected] "}"
99 [email protected] "{" 97 [email protected] "\n "
100 [email protected] "}" 98 [email protected]
101 [email protected] "\n " 99 [email protected]
102 [email protected] 100 [email protected] "if"
103 [email protected] 101 [email protected] " "
104 [email protected] "if" 102 [email protected]
105 [email protected] " " 103 [email protected] "let"
106 [email protected] 104 [email protected] " "
107 [email protected] "let" 105 [email protected] "|"
108 [email protected] " " 106 [email protected] " "
109 [email protected] "|" 107 [email protected]
110 [email protected] " " 108 [email protected]
111 [email protected] 109 [email protected]
112 [email protected] 110 [email protected]
113 [email protected] 111 [email protected] "Some"
114 [email protected] 112 [email protected] "("
115 [email protected] "Some" 113 [email protected]
116 [email protected] "(" 114 [email protected] "_"
117 [email protected] 115 [email protected] ")"
118 [email protected] "_" 116 [email protected] " "
119 [email protected] ")" 117 [email protected] "="
120 [email protected] " " 118 [email protected] " "
121 [email protected] "=" 119 [email protected]
122 [email protected] " " 120 [email protected]
123 [email protected] 121 [email protected]
124 [email protected] 122 [email protected]
125 [email protected] 123 [email protected] "None"
126 [email protected] 124 [email protected] " "
127 [email protected] "None" 125 [email protected]
128 [email protected] " " 126 [email protected] "{"
129 [email protected] 127 [email protected] "}"
130 [email protected] 128 [email protected] "\n "
131 [email protected] "{" 129 [email protected]
132 [email protected] "}" 130 [email protected]
133 [email protected] "\n " 131 [email protected] "while"
134 [email protected] 132 [email protected] " "
135 [email protected] 133 [email protected]
136 [email protected] "while" 134 [email protected] "let"
137 [email protected] " " 135 [email protected] " "
138 [email protected] 136 [email protected]
139 [email protected] "let" 137 [email protected]
140 [email protected] " " 138 [email protected]
141 [email protected] 139 [email protected]
142 [email protected] 140 [email protected]
143 [email protected] 141 [email protected] "Some"
144 [email protected] 142 [email protected] "("
145 [email protected] 143 [email protected]
146 [email protected] "Some" 144 [email protected] "_"
147 [email protected] "(" 145 [email protected] ")"
148 [email protected] 146 [email protected] " "
149 [email protected] "_" 147 [email protected] "|"
150 [email protected] ")" 148 [email protected] " "
151 [email protected] " " 149 [email protected]
152 [email protected] "|" 150 [email protected]
153 [email protected] " " 151 [email protected]
154 [email protected] 152 [email protected]
155 [email protected] 153 [email protected] "Some"
156 [email protected] 154 [email protected] "("
157 [email protected] 155 [email protected]
158 [email protected] "Some" 156 [email protected] "_"
159 [email protected] "(" 157 [email protected] ")"
160 [email protected] 158 [email protected] " "
161 [email protected] "_" 159 [email protected] "="
162 [email protected] ")" 160 [email protected] " "
163 [email protected] " " 161 [email protected]
164 [email protected] "=" 162 [email protected]
165 [email protected] " " 163 [email protected]
166 [email protected] 164 [email protected]
167 [email protected] 165 [email protected] "None"
168 [email protected] 166 [email protected] " "
169 [email protected] 167 [email protected]
170 [email protected] "None" 168 [email protected] "{"
171 [email protected] " " 169 [email protected] "}"
172 [email protected] 170 [email protected] "\n "
173 [email protected] 171 [email protected]
174 [email protected] "{" 172 [email protected] "while"
175 [email protected] "}" 173 [email protected] " "
176 [email protected] "\n " 174 [email protected]
177 [email protected] 175 [email protected] "let"
178 [email protected] "while" 176 [email protected] " "
179 [email protected] " " 177 [email protected] "|"
180 [email protected] 178 [email protected] " "
181 [email protected] "let" 179 [email protected]
182 [email protected] " " 180 [email protected]
183 [email protected] "|" 181 [email protected]
184 [email protected] " " 182 [email protected]
185 [email protected] 183 [email protected] "Some"
186 [email protected] 184 [email protected] "("
187 [email protected] 185 [email protected]
188 [email protected] 186 [email protected] "_"
189 [email protected] "Some" 187 [email protected] ")"
190 [email protected] "(" 188 [email protected] " "
191 [email protected] 189 [email protected] "="
192 [email protected] "_" 190 [email protected] " "
193 [email protected] ")" 191 [email protected]
194 [email protected] " " 192 [email protected]
195 [email protected] "=" 193 [email protected]
196 [email protected] " " 194 [email protected]
197 [email protected] 195 [email protected] "None"
198 [email protected] 196 [email protected] " "
199 [email protected] 197 [email protected]
200 [email protected] 198 [email protected] "{"
201 [email protected] "None" 199 [email protected] "}"
202 [email protected] " " 200 [email protected] "\n"
203 [email protected] 201 [email protected] "}"
204 [email protected]
205 [email protected] "{"
206 [email protected] "}"
207 [email protected] "\n"
208 [email protected] "}"
209 [email protected] "\n" 202 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rast
index e5138a599..899b63aac 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rast
@@ -9,81 +9,76 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "while"
17 [email protected] "while" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "true"
21 [email protected] "true" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] 24 [email protected] "}"
25 [email protected] "{" 25 [email protected] ";"
26 [email protected] "}" 26 [email protected] "\n "
27 [email protected] ";" 27 [email protected]
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected] "while"
30 [email protected] 30 [email protected] " "
31 [email protected] "while" 31 [email protected]
32 [email protected] " " 32 [email protected] "let"
33 [email protected] 33 [email protected] " "
34 [email protected] "let" 34 [email protected]
35 [email protected] " " 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "Some"
39 [email protected] 39 [email protected] "("
40 [email protected] "Some" 40 [email protected]
41 [email protected] "(" 41 [email protected]
42 [email protected] 42 [email protected] "x"
43 [email protected] 43 [email protected] ")"
44 [email protected] "x" 44 [email protected] " "
45 [email protected] ")" 45 [email protected] "="
46 [email protected] " " 46 [email protected] " "
47 [email protected] "=" 47 [email protected]
48 [email protected] " " 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "it"
53 [email protected] 53 [email protected] "."
54 [email protected] "it" 54 [email protected]
55 [email protected] "." 55 [email protected] "next"
56 [email protected] 56 [email protected]
57 [email protected] "next" 57 [email protected] "("
58 [email protected] 58 [email protected] ")"
59 [email protected] "(" 59 [email protected] " "
60 [email protected] ")" 60 [email protected]
61 [email protected] " " 61 [email protected] "{"
62 [email protected] 62 [email protected] "}"
63 [email protected] 63 [email protected] ";"
64 [email protected] "{" 64 [email protected] "\n "
65 [email protected] "}" 65 [email protected]
66 [email protected] ";" 66 [email protected]
67 [email protected] "\n " 67 [email protected] "while"
68 [email protected] 68 [email protected] " "
69 [email protected] 69 [email protected]
70 [email protected] "while" 70 [email protected]
71 [email protected] " " 71 [email protected] "{"
72 [email protected] 72 [email protected] " "
73 [email protected] 73 [email protected]
74 [email protected] 74 [email protected] "true"
75 [email protected] "{" 75 [email protected] " "
76 [email protected] " " 76 [email protected] "}"
77 [email protected] 77 [email protected] " "
78 [email protected] "true" 78 [email protected]
79 [email protected] " " 79 [email protected] "{"
80 [email protected] "}" 80 [email protected] "}"
81 [email protected] " " 81 [email protected] ";"
82 [email protected] 82 [email protected] "\n"
83 [email protected] 83 [email protected] "}"
84 [email protected] "{"
85 [email protected] "}"
86 [email protected] ";"
87 [email protected] "\n"
88 [email protected] "}"
89 [email protected] "\n" 84 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0034_break_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0034_break_expr.rast
index 52644da8f..e064aafaf 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0034_break_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0034_break_expr.rast
@@ -9,47 +9,45 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "loop"
16 [email protected] "loop" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "{"
19 [email protected] 19 [email protected] "\n "
20 [email protected] "{" 20 [email protected]
21 [email protected] "\n " 21 [email protected]
22 [email protected] 22 [email protected] "break"
23 [email protected] 23 [email protected] ";"
24 [email protected] "break" 24 [email protected] "\n "
25 [email protected] ";" 25 [email protected]
26 [email protected] "\n " 26 [email protected]
27 [email protected] 27 [email protected] "break"
28 [email protected] 28 [email protected] " "
29 [email protected] "break" 29 [email protected] "\'l"
30 [email protected] " " 30 [email protected] ";"
31 [email protected] "\'l" 31 [email protected] "\n "
32 [email protected] ";" 32 [email protected]
33 [email protected] "\n " 33 [email protected]
34 [email protected] 34 [email protected] "break"
35 [email protected] 35 [email protected] " "
36 [email protected] "break" 36 [email protected]
37 [email protected] " " 37 [email protected] "92"
38 [email protected] 38 [email protected] ";"
39 [email protected] "92" 39 [email protected] "\n "
40 [email protected] ";" 40 [email protected]
41 [email protected] "\n " 41 [email protected]
42 [email protected] 42 [email protected] "break"
43 [email protected] 43 [email protected] " "
44 [email protected] "break" 44 [email protected] "\'l"
45 [email protected] " " 45 [email protected] " "
46 [email protected] "\'l" 46 [email protected]
47 [email protected] " " 47 [email protected] "92"
48 [email protected] 48 [email protected] ";"
49 [email protected] "92" 49 [email protected] "\n "
50 [email protected] ";" 50 [email protected] "}"
51 [email protected] "\n " 51 [email protected] "\n"
52 [email protected] "}" 52 [email protected] "}"
53 [email protected] "\n"
54 [email protected] "}"
55 [email protected] "\n" 53 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rast
index f061c0cac..cf5825593 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0036_unsafe_extern_fn.rast
@@ -16,7 +16,6 @@ [email protected]
16 [email protected] ")" 16 [email protected] ")"
17 [email protected] " " 17 [email protected] " "
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "{"
20 [email protected] "{" 20 [email protected] "}"
21 [email protected] "}"
22 [email protected] "\n" 21 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0037_qual_paths.rast b/crates/ra_syntax/test_data/parser/inline/ok/0037_qual_paths.rast
index e25fc8c3e..fbd90bc0f 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0037_qual_paths.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0037_qual_paths.rast
@@ -42,38 +42,37 @@ [email protected]
42 [email protected] ")" 42 [email protected] ")"
43 [email protected] " " 43 [email protected] " "
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected] "{"
46 [email protected] "{" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected] "<"
54 [email protected] "<" 54 [email protected]
55 [email protected] 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected] "usize"
59 [email protected] "usize" 59 [email protected] " "
60 [email protected] " " 60 [email protected] "as"
61 [email protected] "as" 61 [email protected] " "
62 [email protected] " " 62 [email protected]
63 [email protected] 63 [email protected]
64 [email protected] 64 [email protected]
65 [email protected] 65 [email protected]
66 [email protected] 66 [email protected] "Default"
67 [email protected] "Default" 67 [email protected] ">"
68 [email protected] ">" 68 [email protected] "::"
69 [email protected] "::" 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected] "default"
72 [email protected] "default" 72 [email protected]
73 [email protected] 73 [email protected] "("
74 [email protected] "(" 74 [email protected] ")"
75 [email protected] ")" 75 [email protected] ";"
76 [email protected] ";" 76 [email protected] " "
77 [email protected] " " 77 [email protected] "}"
78 [email protected] "}"
79 [email protected] "\n" 78 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0038_full_range_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0038_full_range_expr.rast
index a1238d610..a767f145d 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0038_full_range_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0038_full_range_expr.rast
@@ -9,21 +9,20 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "xs"
21 [email protected] "xs" 21 [email protected] "["
22 [email protected] "[" 22 [email protected]
23 [email protected] 23 [email protected] ".."
24 [email protected] ".." 24 [email protected] "]"
25 [email protected] "]" 25 [email protected] ";"
26 [email protected] ";" 26 [email protected] " "
27 [email protected] " " 27 [email protected] "}"
28 [email protected] "}"
29 [email protected] "\n" 28 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rast b/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rast
index 69e5fe4bc..e92ea2bf2 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0039_type_arg.rast
@@ -32,13 +32,12 @@ [email protected]
32 [email protected] " " 32 [email protected] " "
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "{"
36 [email protected] "{" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected] "2"
39 [email protected] "2" 39 [email protected] " "
40 [email protected] " " 40 [email protected] "}"
41 [email protected] "}"
42 [email protected] "," 41 [email protected] ","
43 [email protected] " " 42 [email protected] " "
44 [email protected] 43 [email protected]
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast b/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
index 1a98e2610..aa582516a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0040_crate_keyword_vis.rast
@@ -12,10 +12,9 @@ [email protected]
12 [email protected] ")" 12 [email protected] ")"
13 [email protected] " " 13 [email protected] " "
14 [email protected] 14 [email protected]
15 [email protected] 15 [email protected] "{"
16 [email protected] "{" 16 [email protected] " "
17 [email protected] " " 17 [email protected] "}"
18 [email protected] "}"
19 [email protected] "\n" 18 [email protected] "\n"
20 [email protected] 19 [email protected]
21 [email protected] "struct" 20 [email protected] "struct"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0042_call_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0042_call_expr.rast
index bbf6dc494..0c1c6e877 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0042_call_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0042_call_expr.rast
@@ -9,140 +9,139 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected] "f"
28 [email protected] "f" 28 [email protected]
29 [email protected] 29 [email protected] "("
30 [email protected] "(" 30 [email protected] ")"
31 [email protected] ")" 31 [email protected] ";"
32 [email protected] ";" 32 [email protected] "\n "
33 [email protected] "\n " 33 [email protected]
34 [email protected] 34 [email protected] "let"
35 [email protected] "let" 35 [email protected] " "
36 [email protected] " " 36 [email protected]
37 [email protected] 37 [email protected] "_"
38 [email protected] "_" 38 [email protected] " "
39 [email protected] " " 39 [email protected] "="
40 [email protected] "=" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "f"
49 [email protected] "f" 49 [email protected]
50 [email protected] 50 [email protected] "("
51 [email protected] "(" 51 [email protected] ")"
52 [email protected] ")" 52 [email protected]
53 [email protected] 53 [email protected] "("
54 [email protected] "(" 54 [email protected]
55 [email protected] 55 [email protected] "1"
56 [email protected] "1" 56 [email protected] ")"
57 [email protected] ")" 57 [email protected]
58 [email protected] 58 [email protected] "("
59 [email protected] "(" 59 [email protected]
60 [email protected] 60 [email protected] "1"
61 [email protected] "1" 61 [email protected] ","
62 [email protected] "," 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected] "2"
65 [email protected] "2" 65 [email protected] ","
66 [email protected] "," 66 [email protected] ")"
67 [email protected] ")" 67 [email protected] ";"
68 [email protected] ";" 68 [email protected] "\n "
69 [email protected] "\n " 69 [email protected]
70 [email protected] 70 [email protected] "let"
71 [email protected] "let" 71 [email protected] " "
72 [email protected] " " 72 [email protected]
73 [email protected] 73 [email protected] "_"
74 [email protected] "_" 74 [email protected] " "
75 [email protected] " " 75 [email protected] "="
76 [email protected] "=" 76 [email protected] " "
77 [email protected] " " 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected]
80 [email protected] 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "f"
83 [email protected] "f" 83 [email protected]
84 [email protected] 84 [email protected] "("
85 [email protected] "(" 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected]
88 [email protected] 88 [email protected]
89 [email protected] 89 [email protected]
90 [email protected] 90 [email protected] "<"
91 [email protected] "<" 91 [email protected]
92 [email protected] 92 [email protected]
93 [email protected] 93 [email protected]
94 [email protected] 94 [email protected]
95 [email protected] 95 [email protected] "Foo"
96 [email protected] "Foo" 96 [email protected] ">"
97 [email protected] ">" 97 [email protected] "::"
98 [email protected] "::" 98 [email protected]
99 [email protected] 99 [email protected]
100 [email protected] 100 [email protected] "func"
101 [email protected] "func" 101 [email protected]
102 [email protected] 102 [email protected] "("
103 [email protected] "(" 103 [email protected] ")"
104 [email protected] ")" 104 [email protected] ")"
105 [email protected] ")" 105 [email protected] ";"
106 [email protected] ";" 106 [email protected] "\n "
107 [email protected] "\n " 107 [email protected]
108 [email protected] 108 [email protected]
109 [email protected] 109 [email protected]
110 [email protected] 110 [email protected]
111 [email protected] 111 [email protected]
112 [email protected] 112 [email protected]
113 [email protected] 113 [email protected] "f"
114 [email protected] "f" 114 [email protected]
115 [email protected] 115 [email protected] "("
116 [email protected] "(" 116 [email protected]
117 [email protected] 117 [email protected]
118 [email protected] 118 [email protected]
119 [email protected] 119 [email protected]
120 [email protected] 120 [email protected]
121 [email protected] 121 [email protected] "<"
122 [email protected] "<" 122 [email protected]
123 [email protected] 123 [email protected]
124 [email protected] 124 [email protected]
125 [email protected] 125 [email protected]
126 [email protected] 126 [email protected] "Foo"
127 [email protected] "Foo" 127 [email protected] " "
128 [email protected] " " 128 [email protected] "as"
129 [email protected] "as" 129 [email protected] " "
130 [email protected] " " 130 [email protected]
131 [email protected] 131 [email protected]
132 [email protected] 132 [email protected]
133 [email protected] 133 [email protected]
134 [email protected] 134 [email protected] "Trait"
135 [email protected] "Trait" 135 [email protected] ">"
136 [email protected] ">" 136 [email protected] "::"
137 [email protected] "::" 137 [email protected]
138 [email protected] 138 [email protected]
139 [email protected] 139 [email protected] "func"
140 [email protected] "func" 140 [email protected]
141 [email protected] 141 [email protected] "("
142 [email protected] "(" 142 [email protected] ")"
143 [email protected] ")" 143 [email protected] ")"
144 [email protected] ")" 144 [email protected] ";"
145 [email protected] ";" 145 [email protected] "\n"
146 [email protected] "\n" 146 [email protected] "}"
147 [email protected] "}"
148 [email protected] "\n" 147 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0044_block_items.rast b/crates/ra_syntax/test_data/parser/inline/ok/0044_block_items.rast
index a454dfc3a..c23b3b67c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0044_block_items.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0044_block_items.rast
@@ -9,22 +9,20 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected] "fn"
16 [email protected] "fn" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "b"
19 [email protected] "b" 19 [email protected]
20 [email protected] 20 [email protected] "("
21 [email protected] "(" 21 [email protected] ")"
22 [email protected] ")" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "{"
25 [email protected] 25 [email protected] "}"
26 [email protected] "{" 26 [email protected] " "
27 [email protected] "}" 27 [email protected] "}"
28 [email protected] " "
29 [email protected] "}"
30 [email protected] "\n" 28 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast b/crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast
index 2a50f796c..9ca2165ba 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0045_param_list_opt_patterns.rast
@@ -41,7 +41,6 @@ [email protected]
41 [email protected] "(" 41 [email protected] "("
42 [email protected] ")" 42 [email protected] ")"
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected] "{"
45 [email protected] "{" 45 [email protected] "}"
46 [email protected] "}"
47 [email protected] "\n" 46 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast b/crates/ra_syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast
index 7f87e05ec..b209f67f8 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0048_path_type_with_bounds.rast
@@ -35,9 +35,8 @@ [email protected]
35 [email protected] ">" 35 [email protected] ">"
36 [email protected] " " 36 [email protected] " "
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "{"
39 [email protected] "{" 39 [email protected] "}"
40 [email protected] "}"
41 [email protected] "\n" 40 [email protected] "\n"
42 [email protected] 41 [email protected]
43 [email protected] "fn" 42 [email protected] "fn"
@@ -77,7 +76,6 @@ [email protected]
77 [email protected] ">" 76 [email protected] ">"
78 [email protected] " " 77 [email protected] " "
79 [email protected] 78 [email protected]
80 [email protected] 79 [email protected] "{"
81 [email protected] "{" 80 [email protected] "}"
82 [email protected] "}"
83 [email protected] "\n" 81 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0053_path_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0053_path_expr.rast
index 5f846177e..70232a3b2 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0053_path_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0053_path_expr.rast
@@ -9,88 +9,87 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "a"
27 [email protected] "a" 27 [email protected] ";"
28 [email protected] ";" 28 [email protected] "\n "
29 [email protected] "\n " 29 [email protected]
30 [email protected] 30 [email protected] "let"
31 [email protected] "let" 31 [email protected] " "
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected] "_"
34 [email protected] "_" 34 [email protected] " "
35 [email protected] " " 35 [email protected] "="
36 [email protected] "=" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected] "a"
43 [email protected] "a" 43 [email protected] "::"
44 [email protected] "::" 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected] "b"
47 [email protected] "b" 47 [email protected] ";"
48 [email protected] ";" 48 [email protected] "\n "
49 [email protected] "\n " 49 [email protected]
50 [email protected] 50 [email protected] "let"
51 [email protected] "let" 51 [email protected] " "
52 [email protected] " " 52 [email protected]
53 [email protected] 53 [email protected] "_"
54 [email protected] "_" 54 [email protected] " "
55 [email protected] " " 55 [email protected] "="
56 [email protected] "=" 56 [email protected] " "
57 [email protected] " " 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected] "::"
61 [email protected] "::" 61 [email protected]
62 [email protected] 62 [email protected] "a"
63 [email protected] "a" 63 [email protected]
64 [email protected] 64 [email protected] "::"
65 [email protected] "::" 65 [email protected] "<"
66 [email protected] "<" 66 [email protected]
67 [email protected] 67 [email protected]
68 [email protected] 68 [email protected]
69 [email protected] 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected] "b"
72 [email protected] "b" 72 [email protected] ">"
73 [email protected] ">" 73 [email protected] ";"
74 [email protected] ";" 74 [email protected] "\n "
75 [email protected] "\n " 75 [email protected]
76 [email protected] 76 [email protected] "let"
77 [email protected] "let" 77 [email protected] " "
78 [email protected] " " 78 [email protected]
79 [email protected] 79 [email protected] "_"
80 [email protected] "_" 80 [email protected] " "
81 [email protected] " " 81 [email protected] "="
82 [email protected] "=" 82 [email protected] " "
83 [email protected] " " 83 [email protected]
84 [email protected] 84 [email protected]
85 [email protected] 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected] "format"
88 [email protected] "format" 88 [email protected] "!"
89 [email protected] "!" 89 [email protected]
90 [email protected] 90 [email protected] "("
91 [email protected] "(" 91 [email protected] ")"
92 [email protected] ")" 92 [email protected] ";"
93 [email protected] ";" 93 [email protected] "\n"
94 [email protected] "\n" 94 [email protected] "}"
95 [email protected] "}"
96 [email protected] "\n" 95 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0055_literal_pattern.rast b/crates/ra_syntax/test_data/parser/inline/ok/0055_literal_pattern.rast
index d9310e82e..03c52525e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0055_literal_pattern.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0055_literal_pattern.rast
@@ -9,69 +9,68 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected] ")"
20 [email protected] ")" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "-"
27 [email protected] "-" 27 [email protected]
28 [email protected] 28 [email protected] "1"
29 [email protected] "1" 29 [email protected] " "
30 [email protected] " " 30 [email protected] "=>"
31 [email protected] "=>" 31 [email protected] " "
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected] "("
34 [email protected] "(" 34 [email protected] ")"
35 [email protected] ")" 35 [email protected] ","
36 [email protected] "," 36 [email protected] "\n "
37 [email protected] "\n " 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected] "92"
41 [email protected] "92" 41 [email protected] " "
42 [email protected] " " 42 [email protected] "=>"
43 [email protected] "=>" 43 [email protected] " "
44 [email protected] " " 44 [email protected]
45 [email protected] 45 [email protected] "("
46 [email protected] "(" 46 [email protected] ")"
47 [email protected] ")" 47 [email protected] ","
48 [email protected] "," 48 [email protected] "\n "
49 [email protected] "\n " 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "\'c\'"
53 [email protected] "\'c\'" 53 [email protected] " "
54 [email protected] " " 54 [email protected] "=>"
55 [email protected] "=>" 55 [email protected] " "
56 [email protected] " " 56 [email protected]
57 [email protected] 57 [email protected] "("
58 [email protected] "(" 58 [email protected] ")"
59 [email protected] ")" 59 [email protected] ","
60 [email protected] "," 60 [email protected] "\n "
61 [email protected] "\n " 61 [email protected]
62 [email protected] 62 [email protected]
63 [email protected] 63 [email protected]
64 [email protected] 64 [email protected] "\"hello\""
65 [email protected] "\"hello\"" 65 [email protected] " "
66 [email protected] " " 66 [email protected] "=>"
67 [email protected] "=>" 67 [email protected] " "
68 [email protected] " " 68 [email protected]
69 [email protected] 69 [email protected] "("
70 [email protected] "(" 70 [email protected] ")"
71 [email protected] ")" 71 [email protected] ","
72 [email protected] "," 72 [email protected] "\n "
73 [email protected] "\n " 73 [email protected] "}"
74 [email protected] "}" 74 [email protected] "\n"
75 [email protected] "\n" 75 [email protected] "}"
76 [email protected] "}"
77 [email protected] "\n" 76 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0056_where_clause.rast b/crates/ra_syntax/test_data/parser/inline/ok/0056_where_clause.rast
index 2e727c1ef..24f89b83f 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0056_where_clause.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0056_where_clause.rast
@@ -105,7 +105,6 @@ [email protected]
105 [email protected] "\'a" 105 [email protected] "\'a"
106 [email protected] "\n" 106 [email protected] "\n"
107 [email protected] 107 [email protected]
108 [email protected] 108 [email protected] "{"
109 [email protected] "{" 109 [email protected] "}"
110 [email protected] "}"
111 [email protected] "\n" 110 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rast
index c1e58f9bf..bb43d1eaf 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0057_const_fn.rast
@@ -11,7 +11,6 @@ [email protected]
11 [email protected] ")" 11 [email protected] ")"
12 [email protected] " " 12 [email protected] " "
13 [email protected] 13 [email protected]
14 [email protected] 14 [email protected] "{"
15 [email protected] "{" 15 [email protected] "}"
16 [email protected] "}"
17 [email protected] "\n" 16 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0058_range_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0058_range_pat.rast
index 9bdf2379f..8bd94a868 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0058_range_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0058_range_pat.rast
@@ -9,75 +9,74 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "92"
19 [email protected] "92" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "{"
22 [email protected] "{" 22 [email protected] "\n "
23 [email protected] "\n " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected] "0"
28 [email protected] "0" 28 [email protected] " "
29 [email protected] " " 29 [email protected] "..."
30 [email protected] "..." 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected] "100"
34 [email protected] "100" 34 [email protected] " "
35 [email protected] " " 35 [email protected] "=>"
36 [email protected] "=>" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected] "("
39 [email protected] "(" 39 [email protected] ")"
40 [email protected] ")" 40 [email protected] ","
41 [email protected] "," 41 [email protected] "\n "
42 [email protected] "\n " 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected] "101"
47 [email protected] "101" 47 [email protected] " "
48 [email protected] " " 48 [email protected] "..="
49 [email protected] "..=" 49 [email protected] " "
50 [email protected] " " 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "200"
53 [email protected] "200" 53 [email protected] " "
54 [email protected] " " 54 [email protected] "=>"
55 [email protected] "=>" 55 [email protected] " "
56 [email protected] " " 56 [email protected]
57 [email protected] 57 [email protected] "("
58 [email protected] "(" 58 [email protected] ")"
59 [email protected] ")" 59 [email protected] ","
60 [email protected] "," 60 [email protected] "\n "
61 [email protected] "\n " 61 [email protected]
62 [email protected] 62 [email protected]
63 [email protected] 63 [email protected]
64 [email protected] 64 [email protected]
65 [email protected] 65 [email protected] "200"
66 [email protected] "200" 66 [email protected] " "
67 [email protected] " " 67 [email protected] ".."
68 [email protected] ".." 68 [email protected] " "
69 [email protected] " " 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected] "301"
72 [email protected] "301" 72 [email protected] "=>"
73 [email protected] "=>" 73 [email protected] " "
74 [email protected] " " 74 [email protected]
75 [email protected] 75 [email protected] "("
76 [email protected] "(" 76 [email protected] ")"
77 [email protected] ")" 77 [email protected] ","
78 [email protected] "," 78 [email protected] "\n "
79 [email protected] "\n " 79 [email protected] "}"
80 [email protected] "}" 80 [email protected] "\n"
81 [email protected] "\n" 81 [email protected] "}"
82 [email protected] "}"
83 [email protected] "\n" 82 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast b/crates/ra_syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast
index e9ca92364..9210f155c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0059_match_arms_commas.rast
@@ -9,52 +9,50 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected] ")"
20 [email protected] ")" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "_"
27 [email protected] "_" 27 [email protected] " "
28 [email protected] " " 28 [email protected] "=>"
29 [email protected] "=>" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "("
32 [email protected] "(" 32 [email protected] ")"
33 [email protected] ")" 33 [email protected] ","
34 [email protected] "," 34 [email protected] "\n "
35 [email protected] "\n " 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected] "_"
38 [email protected] "_" 38 [email protected] " "
39 [email protected] " " 39 [email protected] "=>"
40 [email protected] "=>" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected] "{"
43 [email protected] 43 [email protected] "}"
44 [email protected] "{" 44 [email protected] "\n "
45 [email protected] "}" 45 [email protected]
46 [email protected] "\n " 46 [email protected]
47 [email protected] 47 [email protected] "_"
48 [email protected] 48 [email protected] " "
49 [email protected] "_" 49 [email protected] "=>"
50 [email protected] " " 50 [email protected] " "
51 [email protected] "=>" 51 [email protected]
52 [email protected] " " 52 [email protected] "("
53 [email protected] 53 [email protected] ")"
54 [email protected] "(" 54 [email protected] "\n "
55 [email protected] ")" 55 [email protected] "}"
56 [email protected] "\n " 56 [email protected] "\n"
57 [email protected] "}" 57 [email protected] "}"
58 [email protected] "\n"
59 [email protected] "}"
60 [email protected] "\n" 58 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rast b/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rast
index 15d332938..850465d82 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0061_record_lit.rast
@@ -9,117 +9,116 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "S"
20 [email protected] "S" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "}"
24 [email protected] "}" 24 [email protected] ";"
25 [email protected] ";" 25 [email protected] "\n "
26 [email protected] "\n " 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected] "S"
32 [email protected] "S" 32 [email protected] " "
33 [email protected] " " 33 [email protected]
34 [email protected] 34 [email protected] "{"
35 [email protected] "{" 35 [email protected] " "
36 [email protected] " " 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "x"
42 [email protected] "x" 42 [email protected] ","
43 [email protected] "," 43 [email protected] " "
44 [email protected] " " 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected] "y"
47 [email protected] "y" 47 [email protected] ":"
48 [email protected] ":" 48 [email protected] " "
49 [email protected] " " 49 [email protected]
50 [email protected] 50 [email protected] "32"
51 [email protected] "32" 51 [email protected] ","
52 [email protected] "," 52 [email protected] " "
53 [email protected] " " 53 [email protected] "}"
54 [email protected] "}" 54 [email protected] ";"
55 [email protected] ";" 55 [email protected] "\n "
56 [email protected] "\n " 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected] "S"
62 [email protected] "S" 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected] "{"
65 [email protected] "{" 65 [email protected] " "
66 [email protected] " " 66 [email protected]
67 [email protected] 67 [email protected]
68 [email protected] 68 [email protected]
69 [email protected] 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected] "x"
72 [email protected] "x" 72 [email protected] ","
73 [email protected] "," 73 [email protected] " "
74 [email protected] " " 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected] "y"
77 [email protected] "y" 77 [email protected] ":"
78 [email protected] ":" 78 [email protected] " "
79 [email protected] " " 79 [email protected]
80 [email protected] 80 [email protected] "32"
81 [email protected] "32" 81 [email protected] ","
82 [email protected] "," 82 [email protected] " "
83 [email protected] " " 83 [email protected] ".."
84 [email protected] ".." 84 [email protected]
85 [email protected] 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected]
88 [email protected] 88 [email protected]
89 [email protected] 89 [email protected]
90 [email protected] 90 [email protected] "Default"
91 [email protected] "Default" 91 [email protected] "::"
92 [email protected] "::" 92 [email protected]
93 [email protected] 93 [email protected]
94 [email protected] 94 [email protected] "default"
95 [email protected] "default" 95 [email protected]
96 [email protected] 96 [email protected] "("
97 [email protected] "(" 97 [email protected] ")"
98 [email protected] ")" 98 [email protected] " "
99 [email protected] " " 99 [email protected] "}"
100 [email protected] "}" 100 [email protected] ";"
101 [email protected] ";" 101 [email protected] "\n "
102 [email protected] "\n " 102 [email protected]
103 [email protected] 103 [email protected]
104 [email protected] 104 [email protected]
105 [email protected] 105 [email protected]
106 [email protected] 106 [email protected]
107 [email protected] 107 [email protected] "TupleStruct"
108 [email protected] "TupleStruct" 108 [email protected] " "
109 [email protected] " " 109 [email protected]
110 [email protected] 110 [email protected] "{"
111 [email protected] "{" 111 [email protected] " "
112 [email protected] " " 112 [email protected]
113 [email protected] 113 [email protected]
114 [email protected] 114 [email protected] "0"
115 [email protected] "0" 115 [email protected] ":"
116 [email protected] ":" 116 [email protected] " "
117 [email protected] " " 117 [email protected]
118 [email protected] 118 [email protected] "1"
119 [email protected] "1" 119 [email protected] " "
120 [email protected] " " 120 [email protected] "}"
121 [email protected] "}" 121 [email protected] ";"
122 [email protected] ";" 122 [email protected] "\n"
123 [email protected] "\n" 123 [email protected] "}"
124 [email protected] "}"
125 [email protected] "\n" 124 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0062_mod_contents.rast b/crates/ra_syntax/test_data/parser/inline/ok/0062_mod_contents.rast
index 3cce106e4..02656df31 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0062_mod_contents.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0062_mod_contents.rast
@@ -9,9 +9,8 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "}"
14 [email protected] "}"
15 [email protected] "\n" 14 [email protected] "\n"
16 [email protected] 15 [email protected]
17 [email protected] 16 [email protected]
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rast
index 5e1b4cc68..445d8d309 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rast
@@ -9,124 +9,113 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "if"
17 [email protected] "if" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "true"
21 [email protected] "true" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] 24 [email protected] "}"
25 [email protected] "{" 25 [email protected] ";"
26 [email protected] "}" 26 [email protected] "\n "
27 [email protected] ";" 27 [email protected]
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected] "if"
30 [email protected] 30 [email protected] " "
31 [email protected] "if" 31 [email protected]
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected] "true"
34 [email protected] 34 [email protected] " "
35 [email protected] "true" 35 [email protected]
36 [email protected] " " 36 [email protected] "{"
37 [email protected] 37 [email protected] "}"
38 [email protected] 38 [email protected] " "
39 [email protected] "{" 39 [email protected] "else"
40 [email protected] "}" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] "else" 42 [email protected] "{"
43 [email protected] " " 43 [email protected] "}"
44 [email protected] 44 [email protected] ";"
45 [email protected] 45 [email protected] "\n "
46 [email protected] "{" 46 [email protected]
47 [email protected] "}" 47 [email protected]
48 [email protected] ";" 48 [email protected] "if"
49 [email protected] "\n " 49 [email protected] " "
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] "if" 52 [email protected] "true"
53 [email protected] " " 53 [email protected] " "
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected] "{"
56 [email protected] "true" 56 [email protected] "}"
57 [email protected] " " 57 [email protected] " "
58 [email protected] 58 [email protected] "else"
59 [email protected] 59 [email protected] " "
60 [email protected] "{" 60 [email protected]
61 [email protected] "}" 61 [email protected] "if"
62 [email protected] " " 62 [email protected] " "
63 [email protected] "else" 63 [email protected]
64 [email protected] " " 64 [email protected]
65 [email protected] 65 [email protected] "false"
66 [email protected] "if" 66 [email protected] " "
67 [email protected] " " 67 [email protected]
68 [email protected] 68 [email protected] "{"
69 [email protected] 69 [email protected] "}"
70 [email protected] "false" 70 [email protected] " "
71 [email protected] " " 71 [email protected] "else"
72 [email protected] 72 [email protected] " "
73 [email protected] 73 [email protected]
74 [email protected] "{" 74 [email protected] "{"
75 [email protected] "}" 75 [email protected] "}"
76 [email protected] " " 76 [email protected] ";"
77 [email protected] "else" 77 [email protected] "\n "
78 [email protected] " " 78 [email protected]
79 [email protected] 79 [email protected]
80 [email protected] 80 [email protected] "if"
81 [email protected] "{" 81 [email protected] " "
82 [email protected] "}" 82 [email protected]
83 [email protected] ";" 83 [email protected]
84 [email protected] "\n " 84 [email protected]
85 [email protected] 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] "if" 87 [email protected] "S"
88 [email protected] " " 88 [email protected] " "
89 [email protected] 89 [email protected]
90 [email protected] 90 [email protected] "{"
91 [email protected] 91 [email protected] "}"
92 [email protected] 92 [email protected] ";"
93 [email protected] 93 [email protected] "\n "
94 [email protected] "S" 94 [email protected]
95 [email protected] " " 95 [email protected]
96 [email protected] 96 [email protected] "if"
97 [email protected] 97 [email protected] " "
98 [email protected] "{" 98 [email protected]
99 [email protected] "}" 99 [email protected]
100 [email protected] ";" 100 [email protected] "{"
101 [email protected] "\n " 101 [email protected] " "
102 [email protected] 102 [email protected]
103 [email protected] 103 [email protected] "true"
104 [email protected] "if" 104 [email protected] " "
105 [email protected] " " 105 [email protected] "}"
106 [email protected] 106 [email protected] " "
107 [email protected] 107 [email protected]
108 [email protected] 108 [email protected] "{"
109 [email protected] "{" 109 [email protected] " "
110 [email protected] " " 110 [email protected] "}"
111 [email protected] 111 [email protected] " "
112 [email protected] "true" 112 [email protected] "else"
113 [email protected] " " 113 [email protected] " "
114 [email protected] "}" 114 [email protected]
115 [email protected] " " 115 [email protected] "{"
116 [email protected] 116 [email protected] " "
117 [email protected] 117 [email protected] "}"
118 [email protected] "{" 118 [email protected] ";"
119 [email protected] " " 119 [email protected] "\n"
120 [email protected] "}" 120 [email protected] "}"
121 [email protected] " "
122 [email protected] "else"
123 [email protected] " "
124 [email protected]
125 [email protected]
126 [email protected] "{"
127 [email protected] " "
128 [email protected] "}"
129 [email protected] ";"
130 [email protected] "\n"
131 [email protected] "}"
132 [email protected] "\n" 121 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rast b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rast
index 108e5c5cc..177bb5514 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0066_match_arm.rast
@@ -9,144 +9,143 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "match"
17 [email protected] "match" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected] "("
20 [email protected] "(" 20 [email protected] ")"
21 [email protected] ")" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] "{" 24 [email protected] "\n "
25 [email protected] "\n " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected] "_"
28 [email protected] "_" 28 [email protected] " "
29 [email protected] " " 29 [email protected] "=>"
30 [email protected] "=>" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "("
33 [email protected] "(" 33 [email protected] ")"
34 [email protected] ")" 34 [email protected] ","
35 [email protected] "," 35 [email protected] "\n "
36 [email protected] "\n " 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "_"
39 [email protected] "_" 39 [email protected] " "
40 [email protected] " " 40 [email protected]
41 [email protected] 41 [email protected] "if"
42 [email protected] "if" 42 [email protected] " "
43 [email protected] " " 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "Test"
49 [email protected] "Test" 49 [email protected] " "
50 [email protected] " " 50 [email protected] ">"
51 [email protected] ">" 51 [email protected] " "
52 [email protected] " " 52 [email protected]
53 [email protected] 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected]
56 [email protected] 56 [email protected] "Test"
57 [email protected] "Test" 57 [email protected]
58 [email protected] 58 [email protected] "{"
59 [email protected] "{" 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected] "field"
62 [email protected] "field" 62 [email protected] ":"
63 [email protected] ":" 63 [email protected] " "
64 [email protected] " " 64 [email protected]
65 [email protected] 65 [email protected] "0"
66 [email protected] "0" 66 [email protected] "}"
67 [email protected] "}" 67 [email protected] " "
68 [email protected] " " 68 [email protected] "=>"
69 [email protected] "=>" 69 [email protected] " "
70 [email protected] " " 70 [email protected]
71 [email protected] 71 [email protected] "("
72 [email protected] "(" 72 [email protected] ")"
73 [email protected] ")" 73 [email protected] ","
74 [email protected] "," 74 [email protected] "\n "
75 [email protected] "\n " 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected] "X"
80 [email protected] "X" 80 [email protected] " "
81 [email protected] " " 81 [email protected] "|"
82 [email protected] "|" 82 [email protected] " "
83 [email protected] " " 83 [email protected]
84 [email protected] 84 [email protected]
85 [email protected] 85 [email protected] "Y"
86 [email protected] "Y" 86 [email protected] " "
87 [email protected] " " 87 [email protected]
88 [email protected] 88 [email protected] "if"
89 [email protected] "if" 89 [email protected] " "
90 [email protected] " " 90 [email protected]
91 [email protected] 91 [email protected]
92 [email protected] 92 [email protected]
93 [email protected] 93 [email protected]
94 [email protected] 94 [email protected] "Z"
95 [email protected] "Z" 95 [email protected] " "
96 [email protected] " " 96 [email protected] "=>"
97 [email protected] "=>" 97 [email protected] " "
98 [email protected] " " 98 [email protected]
99 [email protected] 99 [email protected] "("
100 [email protected] "(" 100 [email protected] ")"
101 [email protected] ")" 101 [email protected] ","
102 [email protected] "," 102 [email protected] "\n "
103 [email protected] "\n " 103 [email protected]
104 [email protected] 104 [email protected] "|"
105 [email protected] "|" 105 [email protected] " "
106 [email protected] " " 106 [email protected]
107 [email protected] 107 [email protected]
108 [email protected] 108 [email protected]
109 [email protected] 109 [email protected] "X"
110 [email protected] "X" 110 [email protected] " "
111 [email protected] " " 111 [email protected] "|"
112 [email protected] "|" 112 [email protected] " "
113 [email protected] " " 113 [email protected]
114 [email protected] 114 [email protected]
115 [email protected] 115 [email protected] "Y"
116 [email protected] "Y" 116 [email protected] " "
117 [email protected] " " 117 [email protected]
118 [email protected] 118 [email protected] "if"
119 [email protected] "if" 119 [email protected] " "
120 [email protected] " " 120 [email protected]
121 [email protected] 121 [email protected]
122 [email protected] 122 [email protected]
123 [email protected] 123 [email protected]
124 [email protected] 124 [email protected] "Z"
125 [email protected] "Z" 125 [email protected] " "
126 [email protected] " " 126 [email protected] "=>"
127 [email protected] "=>" 127 [email protected] " "
128 [email protected] " " 128 [email protected]
129 [email protected] 129 [email protected] "("
130 [email protected] "(" 130 [email protected] ")"
131 [email protected] ")" 131 [email protected] ","
132 [email protected] "," 132 [email protected] "\n "
133 [email protected] "\n " 133 [email protected]
134 [email protected] 134 [email protected] "|"
135 [email protected] "|" 135 [email protected] " "
136 [email protected] " " 136 [email protected]
137 [email protected] 137 [email protected]
138 [email protected] 138 [email protected] "X"
139 [email protected] "X" 139 [email protected] " "
140 [email protected] " " 140 [email protected] "=>"
141 [email protected] "=>" 141 [email protected] " "
142 [email protected] " " 142 [email protected]
143 [email protected] 143 [email protected] "("
144 [email protected] "(" 144 [email protected] ")"
145 [email protected] ")" 145 [email protected] ","
146 [email protected] "," 146 [email protected] "\n "
147 [email protected] "\n " 147 [email protected] "}"
148 [email protected] "}" 148 [email protected] ";"
149 [email protected] ";" 149 [email protected] "\n"
150 [email protected] "\n" 150 [email protected] "}"
151 [email protected] "}"
152 [email protected] "\n" 151 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast b/crates/ra_syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast
index 1e888063e..f8ff7079b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rast
@@ -9,45 +9,42 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected] "{"
25 [email protected] 25 [email protected]
26 [email protected] "{" 26 [email protected] "1"
27 [email protected] 27 [email protected] "}"
28 [email protected] "1" 28 [email protected] " "
29 [email protected] "}" 29 [email protected] "&"
30 [email protected] " " 30 [email protected] " "
31 [email protected] "&" 31 [email protected]
32 [email protected] " " 32 [email protected] "2"
33 [email protected] 33 [email protected] ";"
34 [email protected] "2" 34 [email protected] "\n "
35 [email protected] ";" 35 [email protected]
36 [email protected] "\n " 36 [email protected]
37 [email protected] 37 [email protected] "{"
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected] "1"
40 [email protected] "{" 40 [email protected] "}"
41 [email protected] 41 [email protected] " "
42 [email protected] "1" 42 [email protected]
43 [email protected] "}" 43 [email protected]
44 [email protected] " " 44 [email protected] "&"
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected] "2"
47 [email protected] "&" 47 [email protected] ";"
48 [email protected] 48 [email protected] "\n"
49 [email protected] "2" 49 [email protected] "}"
50 [email protected] ";"
51 [email protected] "\n"
52 [email protected] "}"
53 [email protected] "\n" 50 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rast
index 218b3ec9e..07b3d1435 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rast
@@ -9,88 +9,85 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "match"
17 [email protected] "match" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected] "("
20 [email protected] "(" 20 [email protected] ")"
21 [email protected] ")" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] "{" 24 [email protected] " "
25 [email protected] " " 25 [email protected] "}"
26 [email protected] "}" 26 [email protected] ";"
27 [email protected] ";" 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "match"
31 [email protected] "match" 31 [email protected] " "
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected] "S"
37 [email protected] "S" 37 [email protected] " "
38 [email protected] " " 38 [email protected]
39 [email protected] 39 [email protected] "{"
40 [email protected] "{" 40 [email protected] "}"
41 [email protected] "}" 41 [email protected] ";"
42 [email protected] ";" 42 [email protected] "\n "
43 [email protected] "\n " 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected] "match"
46 [email protected] "match" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected] "{"
49 [email protected] 49 [email protected] " "
50 [email protected] "{" 50 [email protected] "}"
51 [email protected] " " 51 [email protected] " "
52 [email protected] "}" 52 [email protected]
53 [email protected] " " 53 [email protected] "{"
54 [email protected] 54 [email protected] " "
55 [email protected] "{" 55 [email protected]
56 [email protected] " " 56 [email protected]
57 [email protected] 57 [email protected] "_"
58 [email protected] 58 [email protected] " "
59 [email protected] "_" 59 [email protected] "=>"
60 [email protected] " " 60 [email protected] " "
61 [email protected] "=>" 61 [email protected]
62 [email protected] " " 62 [email protected] "("
63 [email protected] 63 [email protected] ")"
64 [email protected] "(" 64 [email protected] " "
65 [email protected] ")" 65 [email protected] "}"
66 [email protected] " " 66 [email protected] ";"
67 [email protected] "}" 67 [email protected] "\n "
68 [email protected] ";" 68 [email protected]
69 [email protected] "\n " 69 [email protected]
70 [email protected] 70 [email protected] "match"
71 [email protected] 71 [email protected] " "
72 [email protected] "match" 72 [email protected]
73 [email protected] " " 73 [email protected] "{"
74 [email protected] 74 [email protected] " "
75 [email protected] 75 [email protected]
76 [email protected] "{" 76 [email protected]
77 [email protected] " " 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected] "S"
80 [email protected] 80 [email protected] " "
81 [email protected] 81 [email protected]
82 [email protected] "S" 82 [email protected] "{"
83 [email protected] " " 83 [email protected] "}"
84 [email protected] 84 [email protected] " "
85 [email protected] "{" 85 [email protected] "}"
86 [email protected] "}" 86 [email protected] " "
87 [email protected] " " 87 [email protected]
88 [email protected] "}" 88 [email protected] "{"
89 [email protected] " " 89 [email protected] "}"
90 [email protected] 90 [email protected] ";"
91 [email protected] "{" 91 [email protected] "\n"
92 [email protected] "}" 92 [email protected] "}"
93 [email protected] ";"
94 [email protected] "\n"
95 [email protected] "}"
96 [email protected] "\n" 93 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0072_return_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0072_return_expr.rast
index b8171dc9c..665f716a8 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0072_return_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0072_return_expr.rast
@@ -9,21 +9,20 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "return"
17 [email protected] "return" 17 [email protected] ";"
18 [email protected] ";" 18 [email protected] "\n "
19 [email protected] "\n " 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "return"
22 [email protected] "return" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "92"
25 [email protected] "92" 25 [email protected] ";"
26 [email protected] ";" 26 [email protected] "\n"
27 [email protected] "\n" 27 [email protected] "}"
28 [email protected] "}"
29 [email protected] "\n" 28 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast b/crates/ra_syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast
index c2a73ef25..3fd3a4391 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rast
@@ -9,55 +9,51 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected] ")"
20 [email protected] ")" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "_"
27 [email protected] "_" 27 [email protected] " "
28 [email protected] " " 28 [email protected] "=>"
29 [email protected] "=>" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "{"
32 [email protected] 32 [email protected] "}"
33 [email protected] "{" 33 [email protected] "\n "
34 [email protected] "}" 34 [email protected]
35 [email protected] "\n " 35 [email protected]
36 [email protected] 36 [email protected] "("
37 [email protected] 37 [email protected] ")"
38 [email protected] "(" 38 [email protected] " "
39 [email protected] ")" 39 [email protected] "=>"
40 [email protected] " " 40 [email protected] " "
41 [email protected] "=>" 41 [email protected]
42 [email protected] " " 42 [email protected] "{"
43 [email protected] 43 [email protected] "}"
44 [email protected] 44 [email protected] "\n "
45 [email protected] "{" 45 [email protected]
46 [email protected] "}" 46 [email protected]
47 [email protected] "\n " 47 [email protected] "["
48 [email protected] 48 [email protected] "]"
49 [email protected] 49 [email protected] " "
50 [email protected] "[" 50 [email protected] "=>"
51 [email protected] "]" 51 [email protected] " "
52 [email protected] " " 52 [email protected]
53 [email protected] "=>" 53 [email protected] "{"
54 [email protected] " " 54 [email protected] "}"
55 [email protected] 55 [email protected] "\n "
56 [email protected] 56 [email protected] "}"
57 [email protected] "{" 57 [email protected] "\n"
58 [email protected] "}" 58 [email protected] "}"
59 [email protected] "\n "
60 [email protected] "}"
61 [email protected] "\n"
62 [email protected] "}"
63 [email protected] "\n" 59 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0075_block.rast b/crates/ra_syntax/test_data/parser/inline/ok/0075_block.rast
index 39a86d002..97c6e6a9d 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0075_block.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0075_block.rast
@@ -9,9 +9,8 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "}"
14 [email protected] "}"
15 [email protected] "\n" 14 [email protected] "\n"
16 [email protected] 15 [email protected]
17 [email protected] "fn" 16 [email protected] "fn"
@@ -23,22 +22,21 @@ [email protected]
23 [email protected] ")" 22 [email protected] ")"
24 [email protected] " " 23 [email protected] " "
25 [email protected] 24 [email protected]
26 [email protected] 25 [email protected] "{"
27 [email protected] "{" 26 [email protected] " "
28 [email protected] " " 27 [email protected]
29 [email protected] 28 [email protected] "let"
30 [email protected] "let" 29 [email protected] " "
31 [email protected] " " 30 [email protected]
32 [email protected] 31 [email protected] "_"
33 [email protected] "_" 32 [email protected] " "
34 [email protected] " " 33 [email protected] "="
35 [email protected] "=" 34 [email protected] " "
36 [email protected] " " 35 [email protected]
37 [email protected] 36 [email protected] "1"
38 [email protected] "1" 37 [email protected] ";"
39 [email protected] ";" 38 [email protected] " "
40 [email protected] " " 39 [email protected] "}"
41 [email protected] "}"
42 [email protected] "\n" 40 [email protected] "\n"
43 [email protected] 41 [email protected]
44 [email protected] "fn" 42 [email protected] "fn"
@@ -50,20 +48,19 @@ [email protected]
50 [email protected] ")" 48 [email protected] ")"
51 [email protected] " " 49 [email protected] " "
52 [email protected] 50 [email protected]
53 [email protected] 51 [email protected] "{"
54 [email protected] "{" 52 [email protected] " "
55 [email protected] " " 53 [email protected]
56 [email protected] 54 [email protected]
57 [email protected] 55 [email protected] "1"
58 [email protected] "1" 56 [email protected] ";"
59 [email protected] ";" 57 [email protected] " "
60 [email protected] " " 58 [email protected]
61 [email protected] 59 [email protected]
62 [email protected] 60 [email protected] "2"
63 [email protected] "2" 61 [email protected] ";"
64 [email protected] ";" 62 [email protected] " "
65 [email protected] " " 63 [email protected] "}"
66 [email protected] "}"
67 [email protected] "\n" 64 [email protected] "\n"
68 [email protected] 65 [email protected]
69 [email protected] "fn" 66 [email protected] "fn"
@@ -75,16 +72,15 @@ [email protected]
75 [email protected] ")" 72 [email protected] ")"
76 [email protected] " " 73 [email protected] " "
77 [email protected] 74 [email protected]
78 [email protected] 75 [email protected] "{"
79 [email protected] "{" 76 [email protected] " "
80 [email protected] " " 77 [email protected]
81 [email protected] 78 [email protected]
82 [email protected] 79 [email protected] "1"
83 [email protected] "1" 80 [email protected] ";"
84 [email protected] ";" 81 [email protected] " "
85 [email protected] " " 82 [email protected]
86 [email protected] 83 [email protected] "2"
87 [email protected] "2" 84 [email protected] " "
88 [email protected] " " 85 [email protected] "}"
89 [email protected] "}"
90 [email protected] "\n" 86 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0076_function_where_clause.rast b/crates/ra_syntax/test_data/parser/inline/ok/0076_function_where_clause.rast
index 9621ba59e..e2c1a507d 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0076_function_where_clause.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0076_function_where_clause.rast
@@ -34,7 +34,6 @@ [email protected]
34 [email protected] "Copy" 34 [email protected] "Copy"
35 [email protected] " " 35 [email protected] " "
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected] "{"
38 [email protected] "{" 38 [email protected] "}"
39 [email protected] "}"
40 [email protected] "\n" 39 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0077_try_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0077_try_expr.rast
index ed9d62c5f..4f3a8ed24 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0077_try_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0077_try_expr.rast
@@ -9,18 +9,17 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "x"
21 [email protected] "x" 21 [email protected] "?"
22 [email protected] "?" 22 [email protected] ";"
23 [email protected] ";" 23 [email protected] "\n"
24 [email protected] "\n" 24 [email protected] "}"
25 [email protected] "}"
26 [email protected] "\n" 25 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rast b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rast
index 5141ce70d..462d1a8bb 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rast
@@ -9,88 +9,87 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "x"
20 [email protected] "x" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "="
22 [email protected] "=" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "1"
26 [email protected] "1" 26 [email protected] ".."
27 [email protected] ".." 27 [email protected] ";"
28 [email protected] ";" 28 [email protected] "\n "
29 [email protected] "\n " 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected] "match"
32 [email protected] "match" 32 [email protected] " "
33 [email protected] " " 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "1"
36 [email protected] "1" 36 [email protected] ".."
37 [email protected] ".." 37 [email protected] " "
38 [email protected] " " 38 [email protected]
39 [email protected] 39 [email protected] "{"
40 [email protected] "{" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected]
43 [email protected] 43 [email protected] "_"
44 [email protected] "_" 44 [email protected] " "
45 [email protected] " " 45 [email protected] "=>"
46 [email protected] "=>" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected] "("
49 [email protected] "(" 49 [email protected] ")"
50 [email protected] ")" 50 [email protected] " "
51 [email protected] " " 51 [email protected] "}"
52 [email protected] "}" 52 [email protected] ";"
53 [email protected] ";" 53 [email protected] "\n "
54 [email protected] "\n " 54 [email protected]
55 [email protected] 55 [email protected]
56 [email protected] 56 [email protected] "match"
57 [email protected] "match" 57 [email protected] " "
58 [email protected] " " 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected]
62 [email protected] 62 [email protected]
63 [email protected] 63 [email protected]
64 [email protected] 64 [email protected] "a"
65 [email protected] "a" 65 [email protected] "."
66 [email protected] "." 66 [email protected]
67 [email protected] 67 [email protected] "b"
68 [email protected] "b" 68 [email protected]
69 [email protected] 69 [email protected] "("
70 [email protected] "(" 70 [email protected] ")"
71 [email protected] ")" 71 [email protected] ".."
72 [email protected] ".." 72 [email protected]
73 [email protected] 73 [email protected]
74 [email protected] 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected] "S"
77 [email protected] "S" 77 [email protected] " "
78 [email protected] " " 78 [email protected]
79 [email protected] 79 [email protected] "{"
80 [email protected] "{" 80 [email protected] " "
81 [email protected] " " 81 [email protected]
82 [email protected] 82 [email protected]
83 [email protected] 83 [email protected] "_"
84 [email protected] "_" 84 [email protected] " "
85 [email protected] " " 85 [email protected] "=>"
86 [email protected] "=>" 86 [email protected] " "
87 [email protected] " " 87 [email protected]
88 [email protected] 88 [email protected] "("
89 [email protected] "(" 89 [email protected] ")"
90 [email protected] ")" 90 [email protected] " "
91 [email protected] " " 91 [email protected] "}"
92 [email protected] "}" 92 [email protected] ";"
93 [email protected] ";" 93 [email protected] "\n"
94 [email protected] "\n" 94 [email protected] "}"
95 [email protected] "}"
96 [email protected] "\n" 95 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast b/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast
index cdbe64180..dfb8d57ad 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0081_for_type.rast
@@ -89,9 +89,8 @@ [email protected]
89 [email protected] "Iterator" 89 [email protected] "Iterator"
90 [email protected] " " 90 [email protected] " "
91 [email protected] 91 [email protected]
92 [email protected] 92 [email protected] "{"
93 [email protected] "{" 93 [email protected] "}"
94 [email protected] "}"
95 [email protected] "\n" 94 [email protected] "\n"
96 [email protected] 95 [email protected]
97 [email protected] "fn" 96 [email protected] "fn"
@@ -155,9 +154,8 @@ [email protected]
155 [email protected] "Iterator" 154 [email protected] "Iterator"
156 [email protected] " " 155 [email protected] " "
157 [email protected] 156 [email protected]
158 [email protected] 157 [email protected] "{"
159 [email protected] "{" 158 [email protected] "}"
160 [email protected] "}"
161 [email protected] "\n" 159 [email protected] "\n"
162 [email protected] 160 [email protected]
163 [email protected] "fn" 161 [email protected] "fn"
@@ -237,7 +235,6 @@ [email protected]
237 [email protected] "Iterator" 235 [email protected] "Iterator"
238 [email protected] " " 236 [email protected] " "
239 [email protected] 237 [email protected]
240 [email protected] 238 [email protected] "{"
241 [email protected] "{" 239 [email protected] "}"
242 [email protected] "}"
243 [email protected] "\n" 240 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rast
index fbad33389..7fe96e17d 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0082_ref_expr.rast
@@ -9,47 +9,46 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "&"
24 [email protected] "&" 24 [email protected]
25 [email protected] 25 [email protected] "1"
26 [email protected] "1" 26 [email protected] ";"
27 [email protected] ";" 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected] "let"
30 [email protected] "let" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "_"
33 [email protected] "_" 33 [email protected] " "
34 [email protected] " " 34 [email protected] "="
35 [email protected] "=" 35 [email protected] " "
36 [email protected] " " 36 [email protected]
37 [email protected] 37 [email protected] "&"
38 [email protected] "&" 38 [email protected] "mut"
39 [email protected] "mut" 39 [email protected] " "
40 [email protected] " " 40 [email protected]
41 [email protected] 41 [email protected] "&"
42 [email protected] "&" 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected] "f"
48 [email protected] "f" 48 [email protected]
49 [email protected] 49 [email protected] "("
50 [email protected] "(" 50 [email protected] ")"
51 [email protected] ")" 51 [email protected] ";"
52 [email protected] ";" 52 [email protected] "\n"
53 [email protected] "\n" 53 [email protected] "}"
54 [email protected] "}"
55 [email protected] "\n" 54 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0085_expr_literals.rast b/crates/ra_syntax/test_data/parser/inline/ok/0085_expr_literals.rast
index b165789fd..9fcb7899e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0085_expr_literals.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0085_expr_literals.rast
@@ -9,128 +9,127 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "true"
24 [email protected] "true" 24 [email protected] ";"
25 [email protected] ";" 25 [email protected] "\n "
26 [email protected] "\n " 26 [email protected]
27 [email protected] 27 [email protected] "let"
28 [email protected] "let" 28 [email protected] " "
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected] "_"
31 [email protected] "_" 31 [email protected] " "
32 [email protected] " " 32 [email protected] "="
33 [email protected] "=" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected] "false"
36 [email protected] "false" 36 [email protected] ";"
37 [email protected] ";" 37 [email protected] "\n "
38 [email protected] "\n " 38 [email protected]
39 [email protected] 39 [email protected] "let"
40 [email protected] "let" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected] "_"
43 [email protected] "_" 43 [email protected] " "
44 [email protected] " " 44 [email protected] "="
45 [email protected] "=" 45 [email protected] " "
46 [email protected] " " 46 [email protected]
47 [email protected] 47 [email protected] "1"
48 [email protected] "1" 48 [email protected] ";"
49 [email protected] ";" 49 [email protected] "\n "
50 [email protected] "\n " 50 [email protected]
51 [email protected] 51 [email protected] "let"
52 [email protected] "let" 52 [email protected] " "
53 [email protected] " " 53 [email protected]
54 [email protected] 54 [email protected] "_"
55 [email protected] "_" 55 [email protected] " "
56 [email protected] " " 56 [email protected] "="
57 [email protected] "=" 57 [email protected] " "
58 [email protected] " " 58 [email protected]
59 [email protected] 59 [email protected] "2.0"
60 [email protected] "2.0" 60 [email protected] ";"
61 [email protected] ";" 61 [email protected] "\n "
62 [email protected] "\n " 62 [email protected]
63 [email protected] 63 [email protected] "let"
64 [email protected] "let" 64 [email protected] " "
65 [email protected] " " 65 [email protected]
66 [email protected] 66 [email protected] "_"
67 [email protected] "_" 67 [email protected] " "
68 [email protected] " " 68 [email protected] "="
69 [email protected] "=" 69 [email protected] " "
70 [email protected] " " 70 [email protected]
71 [email protected] 71 [email protected] "b\'a\'"
72 [email protected] "b\'a\'" 72 [email protected] ";"
73 [email protected] ";" 73 [email protected] "\n "
74 [email protected] "\n " 74 [email protected]
75 [email protected] 75 [email protected] "let"
76 [email protected] "let" 76 [email protected] " "
77 [email protected] " " 77 [email protected]
78 [email protected] 78 [email protected] "_"
79 [email protected] "_" 79 [email protected] " "
80 [email protected] " " 80 [email protected] "="
81 [email protected] "=" 81 [email protected] " "
82 [email protected] " " 82 [email protected]
83 [email protected] 83 [email protected] "\'b\'"
84 [email protected] "\'b\'" 84 [email protected] ";"
85 [email protected] ";" 85 [email protected] "\n "
86 [email protected] "\n " 86 [email protected]
87 [email protected] 87 [email protected] "let"
88 [email protected] "let" 88 [email protected] " "
89 [email protected] " " 89 [email protected]
90 [email protected] 90 [email protected] "_"
91 [email protected] "_" 91 [email protected] " "
92 [email protected] " " 92 [email protected] "="
93 [email protected] "=" 93 [email protected] " "
94 [email protected] " " 94 [email protected]
95 [email protected] 95 [email protected] "\"c\""
96 [email protected] "\"c\"" 96 [email protected] ";"
97 [email protected] ";" 97 [email protected] "\n "
98 [email protected] "\n " 98 [email protected]
99 [email protected] 99 [email protected] "let"
100 [email protected] "let" 100 [email protected] " "
101 [email protected] " " 101 [email protected]
102 [email protected] 102 [email protected] "_"
103 [email protected] "_" 103 [email protected] " "
104 [email protected] " " 104 [email protected] "="
105 [email protected] "=" 105 [email protected] " "
106 [email protected] " " 106 [email protected]
107 [email protected] 107 [email protected] "r\"d\""
108 [email protected] "r\"d\"" 108 [email protected] ";"
109 [email protected] ";" 109 [email protected] "\n "
110 [email protected] "\n " 110 [email protected]
111 [email protected] 111 [email protected] "let"
112 [email protected] "let" 112 [email protected] " "
113 [email protected] " " 113 [email protected]
114 [email protected] 114 [email protected] "_"
115 [email protected] "_" 115 [email protected] " "
116 [email protected] " " 116 [email protected] "="
117 [email protected] "=" 117 [email protected] " "
118 [email protected] " " 118 [email protected]
119 [email protected] 119 [email protected] "b\"e\""
120 [email protected] "b\"e\"" 120 [email protected] ";"
121 [email protected] ";" 121 [email protected] "\n "
122 [email protected] "\n " 122 [email protected]
123 [email protected] 123 [email protected] "let"
124 [email protected] "let" 124 [email protected] " "
125 [email protected] " " 125 [email protected]
126 [email protected] 126 [email protected] "_"
127 [email protected] "_" 127 [email protected] " "
128 [email protected] " " 128 [email protected] "="
129 [email protected] "=" 129 [email protected] " "
130 [email protected] " " 130 [email protected]
131 [email protected] 131 [email protected] "br\"f\""
132 [email protected] "br\"f\"" 132 [email protected] ";"
133 [email protected] ";" 133 [email protected] "\n"
134 [email protected] "\n" 134 [email protected] "}"
135 [email protected] "}"
136 [email protected] "\n" 135 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0086_function_ret_type.rast b/crates/ra_syntax/test_data/parser/inline/ok/0086_function_ret_type.rast
index 36f17133d..a42abc189 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0086_function_ret_type.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0086_function_ret_type.rast
@@ -9,9 +9,8 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "}"
14 [email protected] "}"
15 [email protected] "\n" 14 [email protected] "\n"
16 [email protected] 15 [email protected]
17 [email protected] "fn" 16 [email protected] "fn"
@@ -30,7 +29,6 @@ [email protected]
30 [email protected] ")" 29 [email protected] ")"
31 [email protected] " " 30 [email protected] " "
32 [email protected] 31 [email protected]
33 [email protected] 32 [email protected] "{"
34 [email protected] "{" 33 [email protected] "}"
35 [email protected] "}"
36 [email protected] "\n" 34 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast b/crates/ra_syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast
index ca5aa007e..7e71d7373 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0088_break_ambiguity.rast
@@ -8,62 +8,58 @@ [email protected]
8 [email protected] "(" 8 [email protected] "("
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] 10 [email protected]
11 [email protected] 11 [email protected] "{"
12 [email protected] "{" 12 [email protected] "\n "
13 [email protected] "\n " 13 [email protected]
14 [email protected] 14 [email protected]
15 [email protected] 15 [email protected] "if"
16 [email protected] "if" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "break"
20 [email protected] "break" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] 23 [email protected] "}"
24 [email protected] "{" 24 [email protected] "\n "
25 [email protected] "}" 25 [email protected]
26 [email protected] "\n " 26 [email protected]
27 [email protected] 27 [email protected] "while"
28 [email protected] 28 [email protected] " "
29 [email protected] "while" 29 [email protected]
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "break"
32 [email protected] 32 [email protected] " "
33 [email protected] "break" 33 [email protected]
34 [email protected] " " 34 [email protected] "{"
35 [email protected] 35 [email protected] "}"
36 [email protected] 36 [email protected] "\n "
37 [email protected] "{" 37 [email protected]
38 [email protected] "}" 38 [email protected]
39 [email protected] "\n " 39 [email protected] "for"
40 [email protected] 40 [email protected] " "
41 [email protected] 41 [email protected]
42 [email protected] "for" 42 [email protected]
43 [email protected] " " 43 [email protected] "i"
44 [email protected] 44 [email protected] " "
45 [email protected] 45 [email protected] "in"
46 [email protected] "i" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] "in" 48 [email protected] "break"
49 [email protected] " " 49 [email protected] " "
50 [email protected] 50 [email protected]
51 [email protected] "break" 51 [email protected] "{"
52 [email protected] " " 52 [email protected] "}"
53 [email protected] 53 [email protected] "\n "
54 [email protected] 54 [email protected]
55 [email protected] "{" 55 [email protected] "match"
56 [email protected] "}" 56 [email protected] " "
57 [email protected] "\n " 57 [email protected]
58 [email protected] 58 [email protected] "break"
59 [email protected] "match" 59 [email protected] " "
60 [email protected] " " 60 [email protected]
61 [email protected] 61 [email protected] "{"
62 [email protected] "break" 62 [email protected] "}"
63 [email protected] " " 63 [email protected] "\n"
64 [email protected] 64 [email protected] "}"
65 [email protected] "{"
66 [email protected] "}"
67 [email protected] "\n"
68 [email protected] "}"
69 [email protected] "\n" 65 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rast
index 1c1e349e1..48aaf1004 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0089_extern_fn.rast
@@ -12,7 +12,6 @@ [email protected]
12 [email protected] ")" 12 [email protected] ")"
13 [email protected] " " 13 [email protected] " "
14 [email protected] 14 [email protected]
15 [email protected] 15 [email protected] "{"
16 [email protected] "{" 16 [email protected] "}"
17 [email protected] "}"
18 [email protected] "\n" 17 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0093_index_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0093_index_expr.rast
index c264dae5e..aed81f9b0 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0093_index_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0093_index_expr.rast
@@ -9,26 +9,25 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "x"
22 [email protected] "x" 22 [email protected] "["
23 [email protected] "[" 23 [email protected]
24 [email protected] 24 [email protected] "1"
25 [email protected] "1" 25 [email protected] "]"
26 [email protected] "]" 26 [email protected] "["
27 [email protected] "[" 27 [email protected]
28 [email protected] 28 [email protected] "2"
29 [email protected] "2" 29 [email protected] "]"
30 [email protected] "]" 30 [email protected] ";"
31 [email protected] ";" 31 [email protected] "\n"
32 [email protected] "\n" 32 [email protected] "}"
33 [email protected] "}"
34 [email protected] "\n" 33 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast
index 24e1ba8a0..67d9595d3 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0095_placeholder_pat.rast
@@ -9,21 +9,20 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "("
24 [email protected] "(" 24 [email protected] ")"
25 [email protected] ")" 25 [email protected] ";"
26 [email protected] ";" 26 [email protected] " "
27 [email protected] " " 27 [email protected] "}"
28 [email protected] "}"
29 [email protected] "\n" 28 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast b/crates/ra_syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
index 47462d44e..031e74652 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0096_no_semi_after_block.rast
@@ -9,122 +9,115 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "if"
17 [email protected] "if" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "true"
21 [email protected] "true" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] 24 [email protected] "}"
25 [email protected] "{" 25 [email protected] "\n "
26 [email protected] "}" 26 [email protected]
27 [email protected] "\n " 27 [email protected]
28 [email protected] 28 [email protected] "loop"
29 [email protected] 29 [email protected] " "
30 [email protected] "loop" 30 [email protected]
31 [email protected] " " 31 [email protected] "{"
32 [email protected] 32 [email protected] "}"
33 [email protected] 33 [email protected] "\n "
34 [email protected] "{" 34 [email protected]
35 [email protected] "}" 35 [email protected]
36 [email protected] "\n " 36 [email protected] "match"
37 [email protected] 37 [email protected] " "
38 [email protected] 38 [email protected]
39 [email protected] "match" 39 [email protected] "("
40 [email protected] " " 40 [email protected] ")"
41 [email protected] 41 [email protected] " "
42 [email protected] "(" 42 [email protected]
43 [email protected] ")" 43 [email protected] "{"
44 [email protected] " " 44 [email protected] "}"
45 [email protected] 45 [email protected] "\n "
46 [email protected] "{" 46 [email protected]
47 [email protected] "}" 47 [email protected]
48 [email protected] "\n " 48 [email protected] "while"
49 [email protected] 49 [email protected] " "
50 [email protected] 50 [email protected]
51 [email protected] "while" 51 [email protected]
52 [email protected] " " 52 [email protected] "true"
53 [email protected] 53 [email protected] " "
54 [email protected] 54 [email protected]
55 [email protected] "true" 55 [email protected] "{"
56 [email protected] " " 56 [email protected] "}"
57 [email protected] 57 [email protected] "\n "
58 [email protected] 58 [email protected]
59 [email protected] "{" 59 [email protected]
60 [email protected] "}" 60 [email protected] "for"
61 [email protected] "\n " 61 [email protected] " "
62 [email protected] 62 [email protected]
63 [email protected] 63 [email protected] "_"
64 [email protected] "for" 64 [email protected] " "
65 [email protected] " " 65 [email protected] "in"
66 [email protected] 66 [email protected] " "
67 [email protected] "_" 67 [email protected]
68 [email protected] " " 68 [email protected] "("
69 [email protected] "in" 69 [email protected] ")"
70 [email protected] " " 70 [email protected] " "
71 [email protected] 71 [email protected]
72 [email protected] "(" 72 [email protected] "{"
73 [email protected] ")" 73 [email protected] "}"
74 [email protected] " " 74 [email protected] "\n "
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] "{" 77 [email protected] "{"
78 [email protected] "}" 78 [email protected] "}"
79 [email protected] "\n " 79 [email protected] "\n "
80 [email protected] 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "{"
83 [email protected] "{" 83 [email protected] "}"
84 [email protected] "}" 84 [email protected] "\n "
85 [email protected] "\n " 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected]
88 [email protected] 88 [email protected]
89 [email protected] "{" 89 [email protected]
90 [email protected] "}" 90 [email protected] "macro_rules"
91 [email protected] "\n " 91 [email protected] "!"
92 [email protected] 92 [email protected] " "
93 [email protected] 93 [email protected]
94 [email protected] 94 [email protected] "test"
95 [email protected] 95 [email protected] " "
96 [email protected] 96 [email protected]
97 [email protected] "macro_rules" 97 [email protected] "{"
98 [email protected] "!" 98 [email protected] "\n "
99 [email protected] " " 99 [email protected]
100 [email protected] 100 [email protected] "("
101 [email protected] "test" 101 [email protected] ")"
102 [email protected] " " 102 [email protected] " "
103 [email protected] 103 [email protected] "="
104 [email protected] "{" 104 [email protected] ">"
105 [email protected] "\n " 105 [email protected] " "
106 [email protected] 106 [email protected]
107 [email protected] "(" 107 [email protected] "{"
108 [email protected] ")" 108 [email protected] "}"
109 [email protected] " " 109 [email protected] "\n "
110 [email protected] "=" 110 [email protected] "}"
111 [email protected] ">" 111 [email protected] "\n "
112 [email protected] " " 112 [email protected]
113 [email protected] 113 [email protected]
114 [email protected] "{" 114 [email protected]
115 [email protected] "}" 115 [email protected]
116 [email protected] "\n " 116 [email protected] "test"
117 [email protected] "}" 117 [email protected] "!"
118 [email protected] "\n " 118 [email protected]
119 [email protected] 119 [email protected] "{"
120 [email protected] 120 [email protected] "}"
121 [email protected] 121 [email protected] "\n"
122 [email protected] 122 [email protected] "}"
123 [email protected] "test"
124 [email protected] "!"
125 [email protected]
126 [email protected] "{"
127 [email protected] "}"
128 [email protected] "\n"
129 [email protected] "}"
130 [email protected] "\n" 123 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rast
index a51fb5511..816e49310 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0098_const_unsafe_fn.rast
@@ -13,7 +13,6 @@ [email protected]
13 [email protected] ")" 13 [email protected] ")"
14 [email protected] " " 14 [email protected] " "
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "{"
17 [email protected] "{" 17 [email protected] "}"
18 [email protected] "}"
19 [email protected] "\n" 18 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0099_param_list.rast b/crates/ra_syntax/test_data/parser/inline/ok/0099_param_list.rast
index 61b47bf35..d48ef865c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0099_param_list.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0099_param_list.rast
@@ -9,9 +9,8 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "}"
14 [email protected] "}"
15 [email protected] "\n" 14 [email protected] "\n"
16 [email protected] 15 [email protected]
17 [email protected] "fn" 16 [email protected] "fn"
@@ -34,9 +33,8 @@ [email protected]
34 [email protected] ")" 33 [email protected] ")"
35 [email protected] " " 34 [email protected] " "
36 [email protected] 35 [email protected]
37 [email protected] 36 [email protected] "{"
38 [email protected] "{" 37 [email protected] "}"
39 [email protected] "}"
40 [email protected] "\n" 38 [email protected] "\n"
41 [email protected] 39 [email protected]
42 [email protected] "fn" 40 [email protected] "fn"
@@ -61,9 +59,8 @@ [email protected]
61 [email protected] ")" 59 [email protected] ")"
62 [email protected] " " 60 [email protected] " "
63 [email protected] 61 [email protected]
64 [email protected] 62 [email protected] "{"
65 [email protected] "{" 63 [email protected] "}"
66 [email protected] "}"
67 [email protected] "\n" 64 [email protected] "\n"
68 [email protected] 65 [email protected]
69 [email protected] "fn" 66 [email protected] "fn"
@@ -97,7 +94,6 @@ [email protected]
97 [email protected] ")" 94 [email protected] ")"
98 [email protected] " " 95 [email protected] " "
99 [email protected] 96 [email protected]
100 [email protected] 97 [email protected] "{"
101 [email protected] "{" 98 [email protected] "}"
102 [email protected] "}"
103 [email protected] "\n" 99 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0100_for_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0100_for_expr.rast
index 89d435d1f..e4455cd3e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0100_for_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0100_for_expr.rast
@@ -9,28 +9,26 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "for"
17 [email protected] "for" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "x"
21 [email protected] "x" 21 [email protected] " "
22 [email protected] " " 22 [email protected] "in"
23 [email protected] "in" 23 [email protected] " "
24 [email protected] " " 24 [email protected]
25 [email protected] 25 [email protected] "["
26 [email protected] "[" 26 [email protected] "]"
27 [email protected] "]" 27 [email protected] " "
28 [email protected] " " 28 [email protected]
29 [email protected] 29 [email protected] "{"
30 [email protected] 30 [email protected] "}"
31 [email protected] "{" 31 [email protected] ";"
32 [email protected] "}" 32 [email protected] "\n"
33 [email protected] ";" 33 [email protected] "}"
34 [email protected] "\n"
35 [email protected] "}"
36 [email protected] "\n" 34 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rast
index 57b4d0c4f..8a8743060 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0101_unsafe_fn.rast
@@ -11,7 +11,6 @@ [email protected]
11 [email protected] ")" 11 [email protected] ")"
12 [email protected] " " 12 [email protected] " "
13 [email protected] 13 [email protected]
14 [email protected] 14 [email protected] "{"
15 [email protected] "{" 15 [email protected] "}"
16 [email protected] "}"
17 [email protected] "\n" 16 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast b/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast
index ed6f6f326..9f966ff8a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0102_record_field_pat_list.rast
@@ -9,125 +9,124 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "S"
22 [email protected] "S" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "{"
25 [email protected] "{" 25 [email protected] "}"
26 [email protected] "}" 26 [email protected] " "
27 [email protected] " " 27 [email protected] "="
28 [email protected] "=" 28 [email protected] " "
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected] "("
31 [email protected] "(" 31 [email protected] ")"
32 [email protected] ")" 32 [email protected] ";"
33 [email protected] ";" 33 [email protected] "\n "
34 [email protected] "\n " 34 [email protected]
35 [email protected] 35 [email protected] "let"
36 [email protected] "let" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "S"
42 [email protected] "S" 42 [email protected] " "
43 [email protected] " " 43 [email protected]
44 [email protected] 44 [email protected] "{"
45 [email protected] "{" 45 [email protected] " "
46 [email protected] " " 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected] "f"
50 [email protected] "f" 50 [email protected] ","
51 [email protected] "," 51 [email protected] " "
52 [email protected] " " 52 [email protected]
53 [email protected] 53 [email protected]
54 [email protected] 54 [email protected] "ref"
55 [email protected] "ref" 55 [email protected] " "
56 [email protected] " " 56 [email protected] "mut"
57 [email protected] "mut" 57 [email protected] " "
58 [email protected] " " 58 [email protected]
59 [email protected] 59 [email protected] "g"
60 [email protected] "g" 60 [email protected] " "
61 [email protected] " " 61 [email protected] "}"
62 [email protected] "}" 62 [email protected] " "
63 [email protected] " " 63 [email protected] "="
64 [email protected] "=" 64 [email protected] " "
65 [email protected] " " 65 [email protected]
66 [email protected] 66 [email protected] "("
67 [email protected] "(" 67 [email protected] ")"
68 [email protected] ")" 68 [email protected] ";"
69 [email protected] ";" 69 [email protected] "\n "
70 [email protected] "\n " 70 [email protected]
71 [email protected] 71 [email protected] "let"
72 [email protected] "let" 72 [email protected] " "
73 [email protected] " " 73 [email protected]
74 [email protected] 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] 77 [email protected] "S"
78 [email protected] "S" 78 [email protected] " "
79 [email protected] " " 79 [email protected]
80 [email protected] 80 [email protected] "{"
81 [email protected] "{" 81 [email protected] " "
82 [email protected] " " 82 [email protected]
83 [email protected] 83 [email protected]
84 [email protected] 84 [email protected] "h"
85 [email protected] "h" 85 [email protected] ":"
86 [email protected] ":" 86 [email protected] " "
87 [email protected] " " 87 [email protected]
88 [email protected] 88 [email protected] "_"
89 [email protected] "_" 89 [email protected] ","
90 [email protected] "," 90 [email protected] " "
91 [email protected] " " 91 [email protected] ".."
92 [email protected] ".." 92 [email protected] "}"
93 [email protected] "}" 93 [email protected] " "
94 [email protected] " " 94 [email protected] "="
95 [email protected] "=" 95 [email protected] " "
96 [email protected] " " 96 [email protected]
97 [email protected] 97 [email protected] "("
98 [email protected] "(" 98 [email protected] ")"
99 [email protected] ")" 99 [email protected] ";"
100 [email protected] ";" 100 [email protected] "\n "
101 [email protected] "\n " 101 [email protected]
102 [email protected] 102 [email protected] "let"
103 [email protected] "let" 103 [email protected] " "
104 [email protected] " " 104 [email protected]
105 [email protected] 105 [email protected]
106 [email protected] 106 [email protected]
107 [email protected] 107 [email protected]
108 [email protected] 108 [email protected] "S"
109 [email protected] "S" 109 [email protected] " "
110 [email protected] " " 110 [email protected]
111 [email protected] 111 [email protected] "{"
112 [email protected] "{" 112 [email protected] " "
113 [email protected] " " 113 [email protected]
114 [email protected] 114 [email protected]
115 [email protected] 115 [email protected] "h"
116 [email protected] "h" 116 [email protected] ":"
117 [email protected] ":" 117 [email protected] " "
118 [email protected] " " 118 [email protected]
119 [email protected] 119 [email protected] "_"
120 [email protected] "_" 120 [email protected] ","
121 [email protected] "," 121 [email protected] " "
122 [email protected] " " 122 [email protected] "}"
123 [email protected] "}" 123 [email protected] " "
124 [email protected] " " 124 [email protected] "="
125 [email protected] "=" 125 [email protected] " "
126 [email protected] " " 126 [email protected]
127 [email protected] 127 [email protected] "("
128 [email protected] "(" 128 [email protected] ")"
129 [email protected] ")" 129 [email protected] ";"
130 [email protected] ";" 130 [email protected] "\n"
131 [email protected] "\n" 131 [email protected] "}"
132 [email protected] "}"
133 [email protected] "\n" 132 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0103_array_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0103_array_expr.rast
index 461c61914..9b3bef04e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0103_array_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0103_array_expr.rast
@@ -9,47 +9,46 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "["
17 [email protected] "[" 17 [email protected] "]"
18 [email protected] "]" 18 [email protected] ";"
19 [email protected] ";" 19 [email protected] "\n "
20 [email protected] "\n " 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected] "["
23 [email protected] "[" 23 [email protected]
24 [email protected] 24 [email protected] "1"
25 [email protected] "1" 25 [email protected] "]"
26 [email protected] "]" 26 [email protected] ";"
27 [email protected] ";" 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "["
31 [email protected] "[" 31 [email protected]
32 [email protected] 32 [email protected] "1"
33 [email protected] "1" 33 [email protected] ","
34 [email protected] "," 34 [email protected] " "
35 [email protected] " " 35 [email protected]
36 [email protected] 36 [email protected] "2"
37 [email protected] "2" 37 [email protected] ","
38 [email protected] "," 38 [email protected] "]"
39 [email protected] "]" 39 [email protected] ";"
40 [email protected] ";" 40 [email protected] "\n "
41 [email protected] "\n " 41 [email protected]
42 [email protected] 42 [email protected]
43 [email protected] 43 [email protected] "["
44 [email protected] "[" 44 [email protected]
45 [email protected] 45 [email protected] "1"
46 [email protected] "1" 46 [email protected] ";"
47 [email protected] ";" 47 [email protected] " "
48 [email protected] " " 48 [email protected]
49 [email protected] 49 [email protected] "2"
50 [email protected] "2" 50 [email protected] "]"
51 [email protected] "]" 51 [email protected] ";"
52 [email protected] ";" 52 [email protected] "\n"
53 [email protected] "\n" 53 [email protected] "}"
54 [email protected] "}"
55 [email protected] "\n" 54 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rast
deleted file mode 100644
index 8b2323cf2..000000000
--- a/crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rast
+++ /dev/null
@@ -1,43 +0,0 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "foo"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected]
13 [email protected] "{"
14 [email protected] "\n "
15 [email protected]
16 [email protected]
17 [email protected]
18 [email protected] "{"
19 [email protected] "}"
20 [email protected] ";"
21 [email protected] "\n "
22 [email protected]
23 [email protected]
24 [email protected] "unsafe"
25 [email protected] " "
26 [email protected]
27 [email protected] "{"
28 [email protected] "}"
29 [email protected] ";"
30 [email protected] "\n "
31 [email protected]
32 [email protected]
33 [email protected]
34 [email protected] "\'label"
35 [email protected] ":"
36 [email protected] " "
37 [email protected]
38 [email protected] "{"
39 [email protected] "}"
40 [email protected] ";"
41 [email protected] "\n"
42 [email protected] "}"
43 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rs
deleted file mode 100644
index 2fed74c5e..000000000
--- a/crates/ra_syntax/test_data/parser/inline/ok/0105_block_expr.rs
+++ /dev/null
@@ -1,5 +0,0 @@
1fn foo() {
2 {};
3 unsafe {};
4 'label: {};
5}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0106_lambda_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0106_lambda_expr.rast
index 73c314e07..e64717152 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0106_lambda_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0106_lambda_expr.rast
@@ -9,132 +9,127 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected] "|"
18 [email protected] "|" 18 [email protected] "|"
19 [email protected] "|" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "("
22 [email protected] "(" 22 [email protected] ")"
23 [email protected] ")" 23 [email protected] ";"
24 [email protected] ";" 24 [email protected] "\n "
25 [email protected] "\n " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected] "|"
29 [email protected] "|" 29 [email protected] "|"
30 [email protected] "|" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "->"
33 [email protected] "->" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "i32"
39 [email protected] "i32" 39 [email protected] " "
40 [email protected] " " 40 [email protected]
41 [email protected] 41 [email protected] "{"
42 [email protected] 42 [email protected] " "
43 [email protected] "{" 43 [email protected]
44 [email protected] " " 44 [email protected] "92"
45 [email protected] 45 [email protected] " "
46 [email protected] "92" 46 [email protected] "}"
47 [email protected] " " 47 [email protected] ";"
48 [email protected] "}" 48 [email protected] "\n "
49 [email protected] ";" 49 [email protected]
50 [email protected] "\n " 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "|"
53 [email protected] 53 [email protected]
54 [email protected] "|" 54 [email protected]
55 [email protected] 55 [email protected]
56 [email protected] 56 [email protected] "x"
57 [email protected] 57 [email protected] "|"
58 [email protected] "x" 58 [email protected] " "
59 [email protected] "|" 59 [email protected]
60 [email protected] " " 60 [email protected]
61 [email protected] 61 [email protected]
62 [email protected] 62 [email protected]
63 [email protected] 63 [email protected] "x"
64 [email protected] 64 [email protected] ";"
65 [email protected] "x" 65 [email protected] "\n "
66 [email protected] ";" 66 [email protected]
67 [email protected] "\n " 67 [email protected]
68 [email protected] 68 [email protected] "move"
69 [email protected] 69 [email protected] " "
70 [email protected] "move" 70 [email protected]
71 [email protected] " " 71 [email protected] "|"
72 [email protected] 72 [email protected]
73 [email protected] "|" 73 [email protected]
74 [email protected] 74 [email protected]
75 [email protected] 75 [email protected] "x"
76 [email protected] 76 [email protected] ":"
77 [email protected] "x" 77 [email protected] " "
78 [email protected] ":" 78 [email protected]
79 [email protected] " " 79 [email protected]
80 [email protected] 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "i32"
83 [email protected] 83 [email protected] ","
84 [email protected] "i32" 84 [email protected] "|"
85 [email protected] "," 85 [email protected] " "
86 [email protected] "|" 86 [email protected]
87 [email protected] " " 87 [email protected]
88 [email protected] 88 [email protected]
89 [email protected] 89 [email protected]
90 [email protected] 90 [email protected] "x"
91 [email protected] 91 [email protected] ";"
92 [email protected] "x" 92 [email protected] "\n "
93 [email protected] ";" 93 [email protected]
94 [email protected] "\n " 94 [email protected]
95 [email protected] 95 [email protected] "async"
96 [email protected] 96 [email protected] " "
97 [email protected] "async" 97 [email protected]
98 [email protected] " " 98 [email protected] "|"
99 [email protected] 99 [email protected] "|"
100 [email protected] "|" 100 [email protected] " "
101 [email protected] "|" 101 [email protected]
102 [email protected] " " 102 [email protected] "{"
103 [email protected] 103 [email protected] "}"
104 [email protected] 104 [email protected] ";"
105 [email protected] "{" 105 [email protected] "\n "
106 [email protected] "}" 106 [email protected]
107 [email protected] ";" 107 [email protected]
108 [email protected] "\n " 108 [email protected] "move"
109 [email protected] 109 [email protected] " "
110 [email protected] 110 [email protected]
111 [email protected] "move" 111 [email protected] "|"
112 [email protected] " " 112 [email protected] "|"
113 [email protected] 113 [email protected] " "
114 [email protected] "|" 114 [email protected]
115 [email protected] "|" 115 [email protected] "{"
116 [email protected] " " 116 [email protected] "}"
117 [email protected] 117 [email protected] ";"
118 [email protected] 118 [email protected] "\n "
119 [email protected] "{" 119 [email protected]
120 [email protected] "}" 120 [email protected]
121 [email protected] ";" 121 [email protected] "async"
122 [email protected] "\n " 122 [email protected] " "
123 [email protected] 123 [email protected] "move"
124 [email protected] 124 [email protected] " "
125 [email protected] "async" 125 [email protected]
126 [email protected] " " 126 [email protected] "|"
127 [email protected] "move" 127 [email protected] "|"
128 [email protected] " " 128 [email protected] " "
129 [email protected] 129 [email protected]
130 [email protected] "|" 130 [email protected] "{"
131 [email protected] "|" 131 [email protected] "}"
132 [email protected] " " 132 [email protected] ";"
133 [email protected] 133 [email protected] "\n"
134 [email protected] 134 [email protected] "}"
135 [email protected] "{"
136 [email protected] "}"
137 [email protected] ";"
138 [email protected] "\n"
139 [email protected] "}"
140 [email protected] "\n" 135 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0107_method_call_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0107_method_call_expr.rast
index 5392b1a74..98963dc62 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0107_method_call_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0107_method_call_expr.rast
@@ -9,55 +9,54 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "x"
21 [email protected] "x" 21 [email protected] "."
22 [email protected] "." 22 [email protected]
23 [email protected] 23 [email protected] "foo"
24 [email protected] "foo" 24 [email protected]
25 [email protected] 25 [email protected] "("
26 [email protected] "(" 26 [email protected] ")"
27 [email protected] ")" 27 [email protected] ";"
28 [email protected] ";" 28 [email protected] "\n "
29 [email protected] "\n " 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "y"
36 [email protected] "y" 36 [email protected] "."
37 [email protected] "." 37 [email protected]
38 [email protected] 38 [email protected] "bar"
39 [email protected] "bar" 39 [email protected]
40 [email protected] 40 [email protected] "::"
41 [email protected] "::" 41 [email protected] "<"
42 [email protected] "<" 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected] "T"
48 [email protected] "T" 48 [email protected] ">"
49 [email protected] ">" 49 [email protected]
50 [email protected] 50 [email protected] "("
51 [email protected] "(" 51 [email protected]
52 [email protected] 52 [email protected] "1"
53 [email protected] "1" 53 [email protected] ","
54 [email protected] "," 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] 56 [email protected] "2"
57 [email protected] "2" 57 [email protected] ","
58 [email protected] "," 58 [email protected] ")"
59 [email protected] ")" 59 [email protected] ";"
60 [email protected] ";" 60 [email protected] "\n"
61 [email protected] "\n" 61 [email protected] "}"
62 [email protected] "}"
63 [email protected] "\n" 62 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0108_tuple_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0108_tuple_expr.rast
index 54f18adac..ea603e2c9 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0108_tuple_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0108_tuple_expr.rast
@@ -9,31 +9,30 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "("
17 [email protected] "(" 17 [email protected] ")"
18 [email protected] ")" 18 [email protected] ";"
19 [email protected] ";" 19 [email protected] "\n "
20 [email protected] "\n " 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected] "("
23 [email protected] "(" 23 [email protected]
24 [email protected] 24 [email protected] "1"
25 [email protected] "1" 25 [email protected] ")"
26 [email protected] ")" 26 [email protected] ";"
27 [email protected] ";" 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "("
31 [email protected] "(" 31 [email protected]
32 [email protected] 32 [email protected] "1"
33 [email protected] "1" 33 [email protected] ","
34 [email protected] "," 34 [email protected] ")"
35 [email protected] ")" 35 [email protected] ";"
36 [email protected] ";" 36 [email protected] "\n"
37 [email protected] "\n" 37 [email protected] "}"
38 [email protected] "}"
39 [email protected] "\n" 38 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0109_label.rast b/crates/ra_syntax/test_data/parser/inline/ok/0109_label.rast
index 6c9e45684..30ff96a7c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0109_label.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0109_label.rast
@@ -9,60 +9,56 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected] "\'a"
18 [email protected] "\'a" 18 [email protected] ":"
19 [email protected] ":" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "loop"
21 [email protected] "loop" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] 24 [email protected] "}"
25 [email protected] "{" 25 [email protected] "\n "
26 [email protected] "}" 26 [email protected]
27 [email protected] "\n " 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "\'b"
30 [email protected] 30 [email protected] ":"
31 [email protected] "\'b" 31 [email protected] " "
32 [email protected] ":" 32 [email protected] "while"
33 [email protected] " " 33 [email protected] " "
34 [email protected] "while" 34 [email protected]
35 [email protected] " " 35 [email protected]
36 [email protected] 36 [email protected] "true"
37 [email protected] 37 [email protected] " "
38 [email protected] "true" 38 [email protected]
39 [email protected] " " 39 [email protected] "{"
40 [email protected] 40 [email protected] "}"
41 [email protected] 41 [email protected] "\n "
42 [email protected] "{" 42 [email protected]
43 [email protected] "}" 43 [email protected]
44 [email protected] "\n " 44 [email protected] "\'c"
45 [email protected] 45 [email protected] ":"
46 [email protected] 46 [email protected] " "
47 [email protected] "\'c" 47 [email protected] "for"
48 [email protected] ":" 48 [email protected] " "
49 [email protected] " " 49 [email protected]
50 [email protected] "for" 50 [email protected]
51 [email protected] " " 51 [email protected] "x"
52 [email protected] 52 [email protected] " "
53 [email protected] 53 [email protected] "in"
54 [email protected] "x" 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] "in" 56 [email protected] "("
57 [email protected] " " 57 [email protected] ")"
58 [email protected] 58 [email protected] " "
59 [email protected] "(" 59 [email protected]
60 [email protected] ")" 60 [email protected] "{"
61 [email protected] " " 61 [email protected] "}"
62 [email protected] 62 [email protected] "\n"
63 [email protected] 63 [email protected] "}"
64 [email protected] "{"
65 [email protected] "}"
66 [email protected] "\n"
67 [email protected] "}"
68 [email protected] "\n" 64 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rast
index a1c5475e7..b58f40ac1 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0111_tuple_pat.rast
@@ -9,82 +9,81 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "a"
22 [email protected] "a" 22 [email protected] ","
23 [email protected] "," 23 [email protected] " "
24 [email protected] " " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "b"
27 [email protected] "b" 27 [email protected] ","
28 [email protected] "," 28 [email protected] " "
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected] ".."
31 [email protected] ".." 31 [email protected] ")"
32 [email protected] ")" 32 [email protected] " "
33 [email protected] " " 33 [email protected] "="
34 [email protected] "=" 34 [email protected] " "
35 [email protected] " " 35 [email protected]
36 [email protected] 36 [email protected] "("
37 [email protected] "(" 37 [email protected] ")"
38 [email protected] ")" 38 [email protected] ";"
39 [email protected] ";" 39 [email protected] "\n "
40 [email protected] "\n " 40 [email protected]
41 [email protected] 41 [email protected] "let"
42 [email protected] "let" 42 [email protected] " "
43 [email protected] " " 43 [email protected]
44 [email protected] 44 [email protected] "("
45 [email protected] "(" 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected] "a"
48 [email protected] "a" 48 [email protected] ","
49 [email protected] "," 49 [email protected] ")"
50 [email protected] ")" 50 [email protected] " "
51 [email protected] " " 51 [email protected] "="
52 [email protected] "=" 52 [email protected] " "
53 [email protected] " " 53 [email protected]
54 [email protected] 54 [email protected] "("
55 [email protected] "(" 55 [email protected] ")"
56 [email protected] ")" 56 [email protected] ";"
57 [email protected] ";" 57 [email protected] "\n "
58 [email protected] "\n " 58 [email protected]
59 [email protected] 59 [email protected] "let"
60 [email protected] "let" 60 [email protected] " "
61 [email protected] " " 61 [email protected]
62 [email protected] 62 [email protected] "("
63 [email protected] "(" 63 [email protected]
64 [email protected] 64 [email protected] ".."
65 [email protected] ".." 65 [email protected] ")"
66 [email protected] ")" 66 [email protected] " "
67 [email protected] " " 67 [email protected] "="
68 [email protected] "=" 68 [email protected] " "
69 [email protected] " " 69 [email protected]
70 [email protected] 70 [email protected] "("
71 [email protected] "(" 71 [email protected] ")"
72 [email protected] ")" 72 [email protected] ";"
73 [email protected] ";" 73 [email protected] "\n "
74 [email protected] "\n " 74 [email protected]
75 [email protected] 75 [email protected] "let"
76 [email protected] "let" 76 [email protected] " "
77 [email protected] " " 77 [email protected]
78 [email protected] 78 [email protected] "("
79 [email protected] "(" 79 [email protected] ")"
80 [email protected] ")" 80 [email protected] " "
81 [email protected] " " 81 [email protected] "="
82 [email protected] "=" 82 [email protected] " "
83 [email protected] " " 83 [email protected]
84 [email protected] 84 [email protected] "("
85 [email protected] "(" 85 [email protected] ")"
86 [email protected] ")" 86 [email protected] ";"
87 [email protected] ";" 87 [email protected] "\n"
88 [email protected] "\n" 88 [email protected] "}"
89 [email protected] "}"
90 [email protected] "\n" 89 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rast
index 42a770a83..b67714c17 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0112_bind_pat.rast
@@ -9,120 +9,119 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "a"
20 [email protected] "a" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "="
22 [email protected] "=" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "("
25 [email protected] "(" 25 [email protected] ")"
26 [email protected] ")" 26 [email protected] ";"
27 [email protected] ";" 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected] "let"
30 [email protected] "let" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "mut"
33 [email protected] "mut" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected] "b"
36 [email protected] "b" 36 [email protected] " "
37 [email protected] " " 37 [email protected] "="
38 [email protected] "=" 38 [email protected] " "
39 [email protected] " " 39 [email protected]
40 [email protected] 40 [email protected] "("
41 [email protected] "(" 41 [email protected] ")"
42 [email protected] ")" 42 [email protected] ";"
43 [email protected] ";" 43 [email protected] "\n "
44 [email protected] "\n " 44 [email protected]
45 [email protected] 45 [email protected] "let"
46 [email protected] "let" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected] "ref"
49 [email protected] "ref" 49 [email protected] " "
50 [email protected] " " 50 [email protected]
51 [email protected] 51 [email protected] "c"
52 [email protected] "c" 52 [email protected] " "
53 [email protected] " " 53 [email protected] "="
54 [email protected] "=" 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] 56 [email protected] "("
57 [email protected] "(" 57 [email protected] ")"
58 [email protected] ")" 58 [email protected] ";"
59 [email protected] ";" 59 [email protected] "\n "
60 [email protected] "\n " 60 [email protected]
61 [email protected] 61 [email protected] "let"
62 [email protected] "let" 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected] "ref"
65 [email protected] "ref" 65 [email protected] " "
66 [email protected] " " 66 [email protected] "mut"
67 [email protected] "mut" 67 [email protected] " "
68 [email protected] " " 68 [email protected]
69 [email protected] 69 [email protected] "d"
70 [email protected] "d" 70 [email protected] " "
71 [email protected] " " 71 [email protected] "="
72 [email protected] "=" 72 [email protected] " "
73 [email protected] " " 73 [email protected]
74 [email protected] 74 [email protected] "("
75 [email protected] "(" 75 [email protected] ")"
76 [email protected] ")" 76 [email protected] ";"
77 [email protected] ";" 77 [email protected] "\n "
78 [email protected] "\n " 78 [email protected]
79 [email protected] 79 [email protected] "let"
80 [email protected] "let" 80 [email protected] " "
81 [email protected] " " 81 [email protected]
82 [email protected] 82 [email protected]
83 [email protected] 83 [email protected] "e"
84 [email protected] "e" 84 [email protected] " "
85 [email protected] " " 85 [email protected] "@"
86 [email protected] "@" 86 [email protected] " "
87 [email protected] " " 87 [email protected]
88 [email protected] 88 [email protected] "_"
89 [email protected] "_" 89 [email protected] " "
90 [email protected] " " 90 [email protected] "="
91 [email protected] "=" 91 [email protected] " "
92 [email protected] " " 92 [email protected]
93 [email protected] 93 [email protected] "("
94 [email protected] "(" 94 [email protected] ")"
95 [email protected] ")" 95 [email protected] ";"
96 [email protected] ";" 96 [email protected] "\n "
97 [email protected] "\n " 97 [email protected]
98 [email protected] 98 [email protected] "let"
99 [email protected] "let" 99 [email protected] " "
100 [email protected] " " 100 [email protected]
101 [email protected] 101 [email protected] "ref"
102 [email protected] "ref" 102 [email protected] " "
103 [email protected] " " 103 [email protected] "mut"
104 [email protected] "mut" 104 [email protected] " "
105 [email protected] " " 105 [email protected]
106 [email protected] 106 [email protected] "f"
107 [email protected] "f" 107 [email protected] " "
108 [email protected] " " 108 [email protected] "@"
109 [email protected] "@" 109 [email protected] " "
110 [email protected] " " 110 [email protected]
111 [email protected] 111 [email protected]
112 [email protected] 112 [email protected] "g"
113 [email protected] "g" 113 [email protected] " "
114 [email protected] " " 114 [email protected] "@"
115 [email protected] "@" 115 [email protected] " "
116 [email protected] " " 116 [email protected]
117 [email protected] 117 [email protected] "_"
118 [email protected] "_" 118 [email protected] " "
119 [email protected] " " 119 [email protected] "="
120 [email protected] "=" 120 [email protected] " "
121 [email protected] " " 121 [email protected]
122 [email protected] 122 [email protected] "("
123 [email protected] "(" 123 [email protected] ")"
124 [email protected] ")" 124 [email protected] ";"
125 [email protected] ";" 125 [email protected] "\n"
126 [email protected] "\n" 126 [email protected] "}"
127 [email protected] "}"
128 [email protected] "\n" 127 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast
index 5414c90b8..5de480da9 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0113_nocontentexpr.rast
@@ -8,50 +8,48 @@ [email protected]
8 [email protected] "(" 8 [email protected] "("
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] 10 [email protected]
11 [email protected] 11 [email protected] "{"
12 [email protected] "{" 12 [email protected] "\n "
13 [email protected] "\n " 13 [email protected] ";"
14 [email protected] ";" 14 [email protected] ";"
15 [email protected] ";" 15 [email protected] ";"
16 [email protected] ";" 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected] "some_expr"
23 [email protected] "some_expr" 23 [email protected]
24 [email protected] 24 [email protected] "("
25 [email protected] "(" 25 [email protected] ")"
26 [email protected] ")" 26 [email protected] ";"
27 [email protected] ";" 27 [email protected] ";"
28 [email protected] ";" 28 [email protected] ";"
29 [email protected] ";" 29 [email protected] ";"
30 [email protected] ";" 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected] "{"
33 [email protected] 33 [email protected] ";"
34 [email protected] "{" 34 [email protected] ";"
35 [email protected] ";" 35 [email protected] ";"
36 [email protected] ";" 36 [email protected] "}"
37 [email protected] ";" 37 [email protected] ";"
38 [email protected] "}" 38 [email protected] ";"
39 [email protected] ";" 39 [email protected] ";"
40 [email protected] ";" 40 [email protected] ";"
41 [email protected] ";" 41 [email protected]
42 [email protected] ";" 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected] "Ok"
47 [email protected] 47 [email protected]
48 [email protected] "Ok" 48 [email protected] "("
49 [email protected] 49 [email protected]
50 [email protected] "(" 50 [email protected] "("
51 [email protected] 51 [email protected] ")"
52 [email protected] "(" 52 [email protected] ")"
53 [email protected] ")" 53 [email protected] "\n"
54 [email protected] ")" 54 [email protected] "}"
55 [email protected] "\n"
56 [email protected] "}"
57 [email protected] "\n" 55 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0118_match_guard.rast b/crates/ra_syntax/test_data/parser/inline/ok/0118_match_guard.rast
index 8e080fb60..e152c6b6c 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0118_match_guard.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0118_match_guard.rast
@@ -9,40 +9,39 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected] ")"
20 [email protected] ")" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "_"
27 [email protected] "_" 27 [email protected] " "
28 [email protected] " " 28 [email protected]
29 [email protected] 29 [email protected] "if"
30 [email protected] "if" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "foo"
36 [email protected] "foo" 36 [email protected] " "
37 [email protected] " " 37 [email protected] "=>"
38 [email protected] "=>" 38 [email protected] " "
39 [email protected] " " 39 [email protected]
40 [email protected] 40 [email protected] "("
41 [email protected] "(" 41 [email protected] ")"
42 [email protected] ")" 42 [email protected] ","
43 [email protected] "," 43 [email protected] "\n "
44 [email protected] "\n " 44 [email protected] "}"
45 [email protected] "}" 45 [email protected] "\n"
46 [email protected] "\n" 46 [email protected] "}"
47 [email protected] "}"
48 [email protected] "\n" 47 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast b/crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast
index 728164f8e..b283ab804 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.rast
@@ -9,73 +9,72 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected] ")"
20 [email protected] ")" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected] "#"
26 [email protected] "#" 26 [email protected] "!"
27 [email protected] "!" 27 [email protected] "["
28 [email protected] "[" 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected] "doc"
32 [email protected] "doc" 32 [email protected]
33 [email protected] 33 [email protected] "("
34 [email protected] "(" 34 [email protected] "\"Inner attribute\""
35 [email protected] "\"Inner attribute\"" 35 [email protected] ")"
36 [email protected] ")" 36 [email protected] "]"
37 [email protected] "]" 37 [email protected] "\n "
38 [email protected] "\n " 38 [email protected]
39 [email protected] 39 [email protected] "#"
40 [email protected] "#" 40 [email protected] "!"
41 [email protected] "!" 41 [email protected] "["
42 [email protected] "[" 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected] "doc"
46 [email protected] "doc" 46 [email protected]
47 [email protected] 47 [email protected] "("
48 [email protected] "(" 48 [email protected] "\"Can be\""
49 [email protected] "\"Can be\"" 49 [email protected] ")"
50 [email protected] ")" 50 [email protected] "]"
51 [email protected] "]" 51 [email protected] "\n "
52 [email protected] "\n " 52 [email protected]
53 [email protected] 53 [email protected] "#"
54 [email protected] "#" 54 [email protected] "!"
55 [email protected] "!" 55 [email protected] "["
56 [email protected] "[" 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected] "doc"
60 [email protected] "doc" 60 [email protected]
61 [email protected] 61 [email protected] "("
62 [email protected] "(" 62 [email protected] "\"Stacked\""
63 [email protected] "\"Stacked\"" 63 [email protected] ")"
64 [email protected] ")" 64 [email protected] "]"
65 [email protected] "]" 65 [email protected] "\n "
66 [email protected] "\n " 66 [email protected]
67 [email protected] 67 [email protected]
68 [email protected] 68 [email protected] "_"
69 [email protected] "_" 69 [email protected] " "
70 [email protected] " " 70 [email protected] "=>"
71 [email protected] "=>" 71 [email protected] " "
72 [email protected] " " 72 [email protected]
73 [email protected] 73 [email protected] "("
74 [email protected] "(" 74 [email protected] ")"
75 [email protected] ")" 75 [email protected] ","
76 [email protected] "," 76 [email protected] "\n "
77 [email protected] "\n " 77 [email protected] "}"
78 [email protected] "}" 78 [email protected] "\n"
79 [email protected] "\n" 79 [email protected] "}"
80 [email protected] "}"
81 [email protected] "\n" 80 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast b/crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast
index 6123885e3..9d5470914 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.rast
@@ -9,138 +9,137 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected] ")"
20 [email protected] ")" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "#"
27 [email protected] "#" 27 [email protected] "["
28 [email protected] "[" 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected] "cfg"
32 [email protected] "cfg" 32 [email protected]
33 [email protected] 33 [email protected] "("
34 [email protected] "(" 34 [email protected] "feature"
35 [email protected] "feature" 35 [email protected] " "
36 [email protected] " " 36 [email protected] "="
37 [email protected] "=" 37 [email protected] " "
38 [email protected] " " 38 [email protected] "\"some\""
39 [email protected] "\"some\"" 39 [email protected] ")"
40 [email protected] ")" 40 [email protected] "]"
41 [email protected] "]" 41 [email protected] "\n "
42 [email protected] "\n " 42 [email protected]
43 [email protected] 43 [email protected] "_"
44 [email protected] "_" 44 [email protected] " "
45 [email protected] " " 45 [email protected] "=>"
46 [email protected] "=>" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected] "("
49 [email protected] "(" 49 [email protected] ")"
50 [email protected] ")" 50 [email protected] ","
51 [email protected] "," 51 [email protected] "\n "
52 [email protected] "\n " 52 [email protected]
53 [email protected] 53 [email protected]
54 [email protected] 54 [email protected] "#"
55 [email protected] "#" 55 [email protected] "["
56 [email protected] "[" 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected] "cfg"
60 [email protected] "cfg" 60 [email protected]
61 [email protected] 61 [email protected] "("
62 [email protected] "(" 62 [email protected] "feature"
63 [email protected] "feature" 63 [email protected] " "
64 [email protected] " " 64 [email protected] "="
65 [email protected] "=" 65 [email protected] " "
66 [email protected] " " 66 [email protected] "\"other\""
67 [email protected] "\"other\"" 67 [email protected] ")"
68 [email protected] ")" 68 [email protected] "]"
69 [email protected] "]" 69 [email protected] "\n "
70 [email protected] "\n " 70 [email protected]
71 [email protected] 71 [email protected] "_"
72 [email protected] "_" 72 [email protected] " "
73 [email protected] " " 73 [email protected] "=>"
74 [email protected] "=>" 74 [email protected] " "
75 [email protected] " " 75 [email protected]
76 [email protected] 76 [email protected] "("
77 [email protected] "(" 77 [email protected] ")"
78 [email protected] ")" 78 [email protected] ","
79 [email protected] "," 79 [email protected] "\n "
80 [email protected] "\n " 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "#"
83 [email protected] "#" 83 [email protected] "["
84 [email protected] "[" 84 [email protected]
85 [email protected] 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected] "cfg"
88 [email protected] "cfg" 88 [email protected]
89 [email protected] 89 [email protected] "("
90 [email protected] "(" 90 [email protected] "feature"
91 [email protected] "feature" 91 [email protected] " "
92 [email protected] " " 92 [email protected] "="
93 [email protected] "=" 93 [email protected] " "
94 [email protected] " " 94 [email protected] "\"many\""
95 [email protected] "\"many\"" 95 [email protected] ")"
96 [email protected] ")" 96 [email protected] "]"
97 [email protected] "]" 97 [email protected] "\n "
98 [email protected] "\n " 98 [email protected]
99 [email protected] 99 [email protected] "#"
100 [email protected] "#" 100 [email protected] "["
101 [email protected] "[" 101 [email protected]
102 [email protected] 102 [email protected]
103 [email protected] 103 [email protected]
104 [email protected] 104 [email protected] "cfg"
105 [email protected] "cfg" 105 [email protected]
106 [email protected] 106 [email protected] "("
107 [email protected] "(" 107 [email protected] "feature"
108 [email protected] "feature" 108 [email protected] " "
109 [email protected] " " 109 [email protected] "="
110 [email protected] "=" 110 [email protected] " "
111 [email protected] " " 111 [email protected] "\"attributes\""
112 [email protected] "\"attributes\"" 112 [email protected] ")"
113 [email protected] ")" 113 [email protected] "]"
114 [email protected] "]" 114 [email protected] "\n "
115 [email protected] "\n " 115 [email protected]
116 [email protected] 116 [email protected] "#"
117 [email protected] "#" 117 [email protected] "["
118 [email protected] "[" 118 [email protected]
119 [email protected] 119 [email protected]
120 [email protected] 120 [email protected]
121 [email protected] 121 [email protected] "cfg"
122 [email protected] "cfg" 122 [email protected]
123 [email protected] 123 [email protected] "("
124 [email protected] "(" 124 [email protected] "feature"
125 [email protected] "feature" 125 [email protected] " "
126 [email protected] " " 126 [email protected] "="
127 [email protected] "=" 127 [email protected] " "
128 [email protected] " " 128 [email protected] "\"before\""
129 [email protected] "\"before\"" 129 [email protected] ")"
130 [email protected] ")" 130 [email protected] "]"
131 [email protected] "]" 131 [email protected] "\n "
132 [email protected] "\n " 132 [email protected]
133 [email protected] 133 [email protected] "_"
134 [email protected] "_" 134 [email protected] " "
135 [email protected] " " 135 [email protected] "=>"
136 [email protected] "=>" 136 [email protected] " "
137 [email protected] " " 137 [email protected]
138 [email protected] 138 [email protected] "("
139 [email protected] "(" 139 [email protected] ")"
140 [email protected] ")" 140 [email protected] ","
141 [email protected] "," 141 [email protected] "\n "
142 [email protected] "\n " 142 [email protected] "}"
143 [email protected] "}" 143 [email protected] "\n"
144 [email protected] "\n" 144 [email protected] "}"
145 [email protected] "}"
146 [email protected] "\n" 145 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast b/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast
index 67b9c10d5..ada2fc54e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.rast
@@ -59,8 +59,7 @@ [email protected]
59 [email protected] ")" 59 [email protected] ")"
60 [email protected] " " 60 [email protected] " "
61 [email protected] 61 [email protected]
62 [email protected] 62 [email protected] "{"
63 [email protected] "{" 63 [email protected] "\n"
64 [email protected] "\n" 64 [email protected] "}"
65 [email protected] "}"
66 [email protected] "\n" 65 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rast b/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rast
index baf22a8d7..6178dfe59 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0124_async_fn.rast
@@ -11,7 +11,6 @@ [email protected]
11 [email protected] ")" 11 [email protected] ")"
12 [email protected] " " 12 [email protected] " "
13 [email protected] 13 [email protected]
14 [email protected] 14 [email protected] "{"
15 [email protected] "{" 15 [email protected] "}"
16 [email protected] "}"
17 [email protected] "\n" 16 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast b/crates/ra_syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast
index 16f5b90b6..ced59b7c1 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0125_crate_keyword_path.rast
@@ -9,24 +9,23 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "crate"
21 [email protected] "crate" 21 [email protected] "::"
22 [email protected] "::" 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected] "foo"
25 [email protected] "foo" 25 [email protected]
26 [email protected] 26 [email protected] "("
27 [email protected] "(" 27 [email protected] ")"
28 [email protected] ")" 28 [email protected] ";"
29 [email protected] ";" 29 [email protected] " "
30 [email protected] " " 30 [email protected] "}"
31 [email protected] "}"
32 [email protected] "\n" 31 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast
index 07ed14773..97611f7f3 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.rast
@@ -9,40 +9,39 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected] "S"
19 [email protected] "S" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "{"
22 [email protected] "{" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "#"
26 [email protected] "#" 26 [email protected] "["
27 [email protected] "[" 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "cfg"
31 [email protected] "cfg" 31 [email protected]
32 [email protected] 32 [email protected] "("
33 [email protected] "(" 33 [email protected] "test"
34 [email protected] "test" 34 [email protected] ")"
35 [email protected] ")" 35 [email protected] "]"
36 [email protected] "]" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected] "field"
39 [email protected] "field" 39 [email protected] ":"
40 [email protected] ":" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected] "1"
43 [email protected] "1" 43 [email protected] " "
44 [email protected] " " 44 [email protected] "}"
45 [email protected] "}" 45 [email protected] "\n"
46 [email protected] "\n" 46 [email protected] "}"
47 [email protected] "}"
48 [email protected] "\n" 47 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast b/crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast
index 8307d4c15..09221fc54 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.rast
@@ -9,91 +9,89 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "#"
17 [email protected] "#" 17 [email protected] "["
18 [email protected] "[" 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "A"
22 [email protected] "A" 22 [email protected] "]"
23 [email protected] "]" 23 [email protected] " "
24 [email protected] " " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "foo"
30 [email protected] "foo" 30 [email protected]
31 [email protected] 31 [email protected] "("
32 [email protected] "(" 32 [email protected] ")"
33 [email protected] ")" 33 [email protected] ";"
34 [email protected] ";" 34 [email protected] "\n "
35 [email protected] "\n " 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected] "#"
38 [email protected] "#" 38 [email protected] "["
39 [email protected] "[" 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected] "B"
43 [email protected] "B" 43 [email protected] "]"
44 [email protected] "]" 44 [email protected] " "
45 [email protected] " " 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected] "bar"
50 [email protected] "bar" 50 [email protected] "!"
51 [email protected] "!" 51 [email protected]
52 [email protected] 52 [email protected] "{"
53 [email protected] "{" 53 [email protected] "}"
54 [email protected] "}" 54 [email protected] "\n "
55 [email protected] "\n " 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected] "#"
58 [email protected] "#" 58 [email protected] "["
59 [email protected] "[" 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected]
62 [email protected] 62 [email protected] "C"
63 [email protected] "C" 63 [email protected] "]"
64 [email protected] "]" 64 [email protected] " "
65 [email protected] " " 65 [email protected]
66 [email protected] 66 [email protected] "#"
67 [email protected] "#" 67 [email protected] "["
68 [email protected] "[" 68 [email protected]
69 [email protected] 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected] "D"
72 [email protected] "D" 72 [email protected] "]"
73 [email protected] "]" 73 [email protected] " "
74 [email protected] " " 74 [email protected]
75 [email protected] 75 [email protected] "{"
76 [email protected] 76 [email protected] "}"
77 [email protected] "{" 77 [email protected] "\n "
78 [email protected] "}" 78 [email protected]
79 [email protected] "\n " 79 [email protected]
80 [email protected] 80 [email protected] "#"
81 [email protected] 81 [email protected] "["
82 [email protected] "#" 82 [email protected]
83 [email protected] "[" 83 [email protected]
84 [email protected] 84 [email protected]
85 [email protected] 85 [email protected] "D"
86 [email protected] 86 [email protected] "]"
87 [email protected] "D" 87 [email protected] " "
88 [email protected] "]" 88 [email protected]
89 [email protected] " " 89 [email protected] "return"
90 [email protected] 90 [email protected] " "
91 [email protected] "return" 91 [email protected]
92 [email protected] " " 92 [email protected] "("
93 [email protected] 93 [email protected] ")"
94 [email protected] "(" 94 [email protected] ";"
95 [email protected] ")" 95 [email protected] "\n"
96 [email protected] ";" 96 [email protected] "}"
97 [email protected] "\n"
98 [email protected] "}"
99 [email protected] "\n" 97 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast b/crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast
index 19c47ea25..93cc41533 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.rast
@@ -9,51 +9,49 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "{"
17 [email protected] 17 [email protected] " "
18 [email protected] "{" 18 [email protected]
19 [email protected] " " 19 [email protected]
20 [email protected] 20 [email protected] "#"
21 [email protected] 21 [email protected] "["
22 [email protected] "#" 22 [email protected]
23 [email protected] "[" 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "A"
26 [email protected] 26 [email protected] "]"
27 [email protected] "A" 27 [email protected] " "
28 [email protected] "]" 28 [email protected]
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected] "bar"
33 [email protected] 33 [email protected] "!"
34 [email protected] "bar" 34 [email protected]
35 [email protected] "!" 35 [email protected] "("
36 [email protected] 36 [email protected] ")"
37 [email protected] "(" 37 [email protected] "?"
38 [email protected] ")" 38 [email protected] " "
39 [email protected] "?" 39 [email protected] "}"
40 [email protected] " " 40 [email protected] "\n "
41 [email protected] "}" 41 [email protected]
42 [email protected] "\n " 42 [email protected]
43 [email protected] 43 [email protected] "#"
44 [email protected] 44 [email protected] "["
45 [email protected] "#" 45 [email protected]
46 [email protected] "[" 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "B"
49 [email protected] 49 [email protected] "]"
50 [email protected] "B" 50 [email protected] " "
51 [email protected] "]" 51 [email protected] "&"
52 [email protected] " " 52 [email protected]
53 [email protected] "&" 53 [email protected] "("
54 [email protected] 54 [email protected] ")"
55 [email protected] "(" 55 [email protected] "\n"
56 [email protected] ")" 56 [email protected] "}"
57 [email protected] "\n"
58 [email protected] "}"
59 [email protected] "\n" 57 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rast b/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rast
index 5630b20af..0901f2348 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0128_combined_fns.rast
@@ -13,9 +13,8 @@ [email protected]
13 [email protected] ")" 13 [email protected] ")"
14 [email protected] " " 14 [email protected] " "
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "{"
17 [email protected] "{" 17 [email protected] "}"
18 [email protected] "}"
19 [email protected] "\n" 18 [email protected] "\n"
20 [email protected] 19 [email protected]
21 [email protected] "const" 20 [email protected] "const"
@@ -31,7 +30,6 @@ [email protected]
31 [email protected] ")" 30 [email protected] ")"
32 [email protected] " " 31 [email protected] " "
33 [email protected] 32 [email protected]
34 [email protected] 33 [email protected] "{"
35 [email protected] "{" 34 [email protected] "}"
36 [email protected] "}"
37 [email protected] "\n" 35 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.rast
index 4946ee050..28291afc2 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.rast
@@ -9,29 +9,28 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected] "m"
23 [email protected] "m" 23 [email protected] "!"
24 [email protected] "!" 24 [email protected]
25 [email protected] 25 [email protected] "("
26 [email protected] "(" 26 [email protected] "x"
27 [email protected] "x" 27 [email protected] ")"
28 [email protected] ")" 28 [email protected] " "
29 [email protected] " " 29 [email protected] "="
30 [email protected] "=" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "0"
33 [email protected] "0" 33 [email protected] ";"
34 [email protected] ";" 34 [email protected] "\n"
35 [email protected] "\n" 35 [email protected] "}"
36 [email protected] "}"
37 [email protected] "\n" 36 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rast b/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rast
index 18fdd9dc9..bb94a05c6 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0130_let_stmt.rast
@@ -9,121 +9,118 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "a"
20 [email protected] "a" 20 [email protected] ";"
21 [email protected] ";" 21 [email protected] "\n "
22 [email protected] "\n " 22 [email protected]
23 [email protected] 23 [email protected] "let"
24 [email protected] "let" 24 [email protected] " "
25 [email protected] " " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected] "b"
28 [email protected] "b" 28 [email protected] ":"
29 [email protected] ":" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected] "i32"
35 [email protected] "i32" 35 [email protected] ";"
36 [email protected] ";" 36 [email protected] "\n "
37 [email protected] "\n " 37 [email protected]
38 [email protected] 38 [email protected] "let"
39 [email protected] "let" 39 [email protected] " "
40 [email protected] " " 40 [email protected]
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected] "c"
43 [email protected] "c" 43 [email protected] " "
44 [email protected] " " 44 [email protected] "="
45 [email protected] "=" 45 [email protected] " "
46 [email protected] " " 46 [email protected]
47 [email protected] 47 [email protected] "92"
48 [email protected] "92" 48 [email protected] ";"
49 [email protected] ";" 49 [email protected] "\n "
50 [email protected] "\n " 50 [email protected]
51 [email protected] 51 [email protected] "let"
52 [email protected] "let" 52 [email protected] " "
53 [email protected] " " 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected] "d"
56 [email protected] "d" 56 [email protected] ":"
57 [email protected] ":" 57 [email protected] " "
58 [email protected] " " 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected]
62 [email protected] 62 [email protected] "i32"
63 [email protected] "i32" 63 [email protected] " "
64 [email protected] " " 64 [email protected] "="
65 [email protected] "=" 65 [email protected] " "
66 [email protected] " " 66 [email protected]
67 [email protected] 67 [email protected] "92"
68 [email protected] "92" 68 [email protected] ";"
69 [email protected] ";" 69 [email protected] "\n "
70 [email protected] "\n " 70 [email protected]
71 [email protected] 71 [email protected] "let"
72 [email protected] "let" 72 [email protected] " "
73 [email protected] " " 73 [email protected]
74 [email protected] 74 [email protected]
75 [email protected] 75 [email protected] "e"
76 [email protected] "e" 76 [email protected] ":"
77 [email protected] ":" 77 [email protected] " "
78 [email protected] " " 78 [email protected]
79 [email protected] 79 [email protected] "!"
80 [email protected] "!" 80 [email protected] ";"
81 [email protected] ";" 81 [email protected] "\n "
82 [email protected] "\n " 82 [email protected]
83 [email protected] 83 [email protected] "let"
84 [email protected] "let" 84 [email protected] " "
85 [email protected] " " 85 [email protected]
86 [email protected] 86 [email protected] "_"
87 [email protected] "_" 87 [email protected] ":"
88 [email protected] ":" 88 [email protected] " "
89 [email protected] " " 89 [email protected]
90 [email protected] 90 [email protected] "!"
91 [email protected] "!" 91 [email protected] " "
92 [email protected] " " 92 [email protected] "="
93 [email protected] "=" 93 [email protected] " "
94 [email protected] " " 94 [email protected]
95 [email protected] 95 [email protected] "{"
96 [email protected] 96 [email protected] "}"
97 [email protected] "{" 97 [email protected] ";"
98 [email protected] "}" 98 [email protected] "\n "
99 [email protected] ";" 99 [email protected]
100 [email protected] "\n " 100 [email protected] "let"
101 [email protected] 101 [email protected] " "
102 [email protected] "let" 102 [email protected]
103 [email protected] " " 103 [email protected]
104 [email protected] 104 [email protected] "f"
105 [email protected] 105 [email protected] " "
106 [email protected] "f" 106 [email protected] "="
107 [email protected] " " 107 [email protected] " "
108 [email protected] "=" 108 [email protected]
109 [email protected] " " 109 [email protected]
110 [email protected] 110 [email protected] "#"
111 [email protected] 111 [email protected] "["
112 [email protected] "#" 112 [email protected]
113 [email protected] "[" 113 [email protected]
114 [email protected] 114 [email protected]
115 [email protected] 115 [email protected] "attr"
116 [email protected] 116 [email protected] "]"
117 [email protected] "attr" 117 [email protected]
118 [email protected] "]" 118 [email protected] "|"
119 [email protected] 119 [email protected] "|"
120 [email protected] "|" 120 [email protected]
121 [email protected] "|" 121 [email protected] "{"
122 [email protected] 122 [email protected] "}"
123 [email protected] 123 [email protected] ";"
124 [email protected] "{" 124 [email protected] "\n"
125 [email protected] "}" 125 [email protected] "}"
126 [email protected] ";"
127 [email protected] "\n"
128 [email protected] "}"
129 [email protected] "\n" 126 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0130_try_block_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0130_try_block_expr.rast
index 01fffd7b0..8f2f144c7 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0130_try_block_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0130_try_block_expr.rast
@@ -9,25 +9,23 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "try"
24 [email protected] "try" 24 [email protected] " "
25 [email protected] " " 25 [email protected]
26 [email protected] 26 [email protected] "{"
27 [email protected] 27 [email protected] "}"
28 [email protected] "{" 28 [email protected] ";"
29 [email protected] "}" 29 [email protected] "\n"
30 [email protected] ";" 30 [email protected] "}"
31 [email protected] "\n"
32 [email protected] "}"
33 [email protected] "\n" 31 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0132_box_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0132_box_expr.rast
index 498b3121e..87ac42748 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0132_box_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0132_box_expr.rast
@@ -9,82 +9,81 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "x"
20 [email protected] "x" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "="
22 [email protected] "=" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "box"
25 [email protected] "box" 25 [email protected] " "
26 [email protected] " " 26 [email protected]
27 [email protected] 27 [email protected] "1i32"
28 [email protected] "1i32" 28 [email protected] ";"
29 [email protected] ";" 29 [email protected] "\n "
30 [email protected] "\n " 30 [email protected]
31 [email protected] 31 [email protected] "let"
32 [email protected] "let" 32 [email protected] " "
33 [email protected] " " 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "y"
36 [email protected] "y" 36 [email protected] " "
37 [email protected] " " 37 [email protected] "="
38 [email protected] "=" 38 [email protected] " "
39 [email protected] " " 39 [email protected]
40 [email protected] 40 [email protected] "("
41 [email protected] "(" 41 [email protected]
42 [email protected] 42 [email protected] "box"
43 [email protected] "box" 43 [email protected] " "
44 [email protected] " " 44 [email protected]
45 [email protected] 45 [email protected] "1i32"
46 [email protected] "1i32" 46 [email protected] ","
47 [email protected] "," 47 [email protected] " "
48 [email protected] " " 48 [email protected]
49 [email protected] 49 [email protected] "box"
50 [email protected] "box" 50 [email protected] " "
51 [email protected] " " 51 [email protected]
52 [email protected] 52 [email protected] "2i32"
53 [email protected] "2i32" 53 [email protected] ")"
54 [email protected] ")" 54 [email protected] ";"
55 [email protected] ";" 55 [email protected] "\n "
56 [email protected] "\n " 56 [email protected]
57 [email protected] 57 [email protected] "let"
58 [email protected] "let" 58 [email protected] " "
59 [email protected] " " 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected] "z"
62 [email protected] "z" 62 [email protected] " "
63 [email protected] " " 63 [email protected] "="
64 [email protected] "=" 64 [email protected] " "
65 [email protected] " " 65 [email protected]
66 [email protected] 66 [email protected]
67 [email protected] 67 [email protected]
68 [email protected] 68 [email protected]
69 [email protected] 69 [email protected]
70 [email protected] 70 [email protected] "Foo"
71 [email protected] "Foo" 71 [email protected]
72 [email protected] 72 [email protected] "("
73 [email protected] "(" 73 [email protected]
74 [email protected] 74 [email protected] "box"
75 [email protected] "box" 75 [email protected] " "
76 [email protected] " " 76 [email protected]
77 [email protected] 77 [email protected] "1i32"
78 [email protected] "1i32" 78 [email protected] ","
79 [email protected] "," 79 [email protected] " "
80 [email protected] " " 80 [email protected]
81 [email protected] 81 [email protected] "box"
82 [email protected] "box" 82 [email protected] " "
83 [email protected] " " 83 [email protected]
84 [email protected] 84 [email protected] "2i32"
85 [email protected] "2i32" 85 [email protected] ")"
86 [email protected] ")" 86 [email protected] ";"
87 [email protected] ";" 87 [email protected] "\n"
88 [email protected] "\n" 88 [email protected] "}"
89 [email protected] "}"
90 [email protected] "\n" 89 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast b/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast
index db58a928e..00ce5ecf0 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0132_default_fn_type.rast
@@ -48,9 +48,8 @@ [email protected]
48 [email protected] ")" 48 [email protected] ")"
49 [email protected] " " 49 [email protected] " "
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected] "{"
52 [email protected] "{" 52 [email protected] "}"
53 [email protected] "}"
54 [email protected] "\n" 53 [email protected] "\n"
55 [email protected] "}" 54 [email protected] "}"
56 [email protected] "\n" 55 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast b/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast
index 4ca554ef8..b330a0932 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0134_nocontentexpr_after_item.rast
@@ -9,56 +9,54 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "enum"
16 [email protected] "enum" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "LocalEnum"
19 [email protected] "LocalEnum" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "{"
22 [email protected] "{" 22 [email protected] "\n "
23 [email protected] "\n " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "One"
26 [email protected] "One" 26 [email protected] ","
27 [email protected] "," 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] "Two"
31 [email protected] "Two" 31 [email protected] ","
32 [email protected] "," 32 [email protected] "\n "
33 [email protected] "\n " 33 [email protected] "}"
34 [email protected] "}" 34 [email protected] ";"
35 [email protected] ";" 35 [email protected] "\n "
36 [email protected] "\n " 36 [email protected]
37 [email protected] 37 [email protected] "fn"
38 [email protected] "fn" 38 [email protected] " "
39 [email protected] " " 39 [email protected]
40 [email protected] 40 [email protected] "f"
41 [email protected] "f" 41 [email protected]
42 [email protected] 42 [email protected] "("
43 [email protected] "(" 43 [email protected] ")"
44 [email protected] ")" 44 [email protected] " "
45 [email protected] " " 45 [email protected]
46 [email protected] 46 [email protected] "{"
47 [email protected] 47 [email protected] "}"
48 [email protected] "{" 48 [email protected] ";"
49 [email protected] "}" 49 [email protected] "\n "
50 [email protected] ";" 50 [email protected]
51 [email protected] "\n " 51 [email protected] "struct"
52 [email protected] 52 [email protected] " "
53 [email protected] "struct" 53 [email protected]
54 [email protected] " " 54 [email protected] "S"
55 [email protected] 55 [email protected] " "
56 [email protected] "S" 56 [email protected]
57 [email protected] " " 57 [email protected] "{"
58 [email protected] 58 [email protected] "}"
59 [email protected] "{" 59 [email protected] ";"
60 [email protected] "}" 60 [email protected] "\n"
61 [email protected] ";" 61 [email protected] "}"
62 [email protected] "\n"
63 [email protected] "}"
64 [email protected] "\n" 62 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.rast
index 7fa3b9f32..8e8d9e992 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0137_await_expr.rast
@@ -9,62 +9,61 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "x"
21 [email protected] "x" 21 [email protected] "."
22 [email protected] "." 22 [email protected] "await"
23 [email protected] "await" 23 [email protected] ";"
24 [email protected] ";" 24 [email protected] "\n "
25 [email protected] "\n " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected] "x"
33 [email protected] "x" 33 [email protected] "."
34 [email protected] "." 34 [email protected]
35 [email protected] 35 [email protected] "0"
36 [email protected] "0" 36 [email protected] "."
37 [email protected] "." 37 [email protected] "await"
38 [email protected] "await" 38 [email protected] ";"
39 [email protected] ";" 39 [email protected] "\n "
40 [email protected] "\n " 40 [email protected]
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected] "x"
51 [email protected] "x" 51 [email protected] "."
52 [email protected] "." 52 [email protected]
53 [email protected] 53 [email protected] "0"
54 [email protected] "0" 54 [email protected]
55 [email protected] 55 [email protected] "("
56 [email protected] "(" 56 [email protected] ")"
57 [email protected] ")" 57 [email protected] "."
58 [email protected] "." 58 [email protected] "await"
59 [email protected] "await" 59 [email protected] "?"
60 [email protected] "?" 60 [email protected] "."
61 [email protected] "." 61 [email protected]
62 [email protected] 62 [email protected] "hello"
63 [email protected] "hello" 63 [email protected]
64 [email protected] 64 [email protected] "("
65 [email protected] "(" 65 [email protected] ")"
66 [email protected] ")" 66 [email protected] ";"
67 [email protected] ";" 67 [email protected] "\n"
68 [email protected] "\n" 68 [email protected] "}"
69 [email protected] "}"
70 [email protected] "\n" 69 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast b/crates/ra_syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast
index a32484f2c..c457851c9 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0138_associated_type_bounds.rast
@@ -50,7 +50,6 @@ [email protected]
50 [email protected] ")" 50 [email protected] ")"
51 [email protected] " " 51 [email protected] " "
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected] "{"
54 [email protected] "{" 54 [email protected] "}"
55 [email protected] "}"
56 [email protected] "\n" 55 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.rast b/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.rast
index 9017236cc..ea325831e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0138_expression_after_block.rast
@@ -9,58 +9,56 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "mut"
19 [email protected] "mut" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "p"
22 [email protected] "p" 22 [email protected] " "
23 [email protected] " " 23 [email protected] "="
24 [email protected] "=" 24 [email protected] " "
25 [email protected] " " 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "F"
30 [email protected] "F" 30 [email protected]
31 [email protected] 31 [email protected] "{"
32 [email protected] "{" 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected] "x"
35 [email protected] "x" 35 [email protected] ":"
36 [email protected] ":" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected] "5"
39 [email protected] "5" 39 [email protected] "}"
40 [email protected] "}" 40 [email protected] ";"
41 [email protected] ";" 41 [email protected] "\n "
42 [email protected] "\n " 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected] "{"
47 [email protected] 47 [email protected]
48 [email protected] "{" 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected] "p"
52 [email protected] 52 [email protected] "}"
53 [email protected] "p" 53 [email protected] "."
54 [email protected] "}" 54 [email protected]
55 [email protected] "." 55 [email protected] "x"
56 [email protected] 56 [email protected] " "
57 [email protected] "x" 57 [email protected] "="
58 [email protected] " " 58 [email protected] " "
59 [email protected] "=" 59 [email protected]
60 [email protected] " " 60 [email protected] "10"
61 [email protected] 61 [email protected] ";"
62 [email protected] "10" 62 [email protected] "\n"
63 [email protected] ";" 63 [email protected] "}"
64 [email protected] "\n"
65 [email protected] "}"
66 [email protected] "\n" 64 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
index 2cb5b52f4..9135de9df 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
@@ -20,7 +20,6 @@ [email protected]
20 [email protected] ")" 20 [email protected] ")"
21 [email protected] " " 21 [email protected] " "
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] "{" 24 [email protected] "}"
25 [email protected] "}"
26 [email protected] "\n" 25 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast b/crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast
index ac3f4de26..14610a0a2 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.rast
@@ -29,7 +29,6 @@ [email protected]
29 [email protected] ")" 29 [email protected] ")"
30 [email protected] " " 30 [email protected] " "
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected] "{"
33 [email protected] "{" 33 [email protected] "}"
34 [email protected] "}"
35 [email protected] "\n" 34 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0142_for_range_from.rast b/crates/ra_syntax/test_data/parser/inline/ok/0142_for_range_from.rast
index 8d4919cbd..e6be8b7e4 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0142_for_range_from.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0142_for_range_from.rast
@@ -9,34 +9,32 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "for"
16 [email protected] "for" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "x"
20 [email protected] "x" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "in"
22 [email protected] "in" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "0"
26 [email protected] "0" 26 [email protected] " "
27 [email protected] " " 27 [email protected] ".."
28 [email protected] ".." 28 [email protected] " "
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected] "{"
31 [email protected] 31 [email protected] "\n "
32 [email protected] "{" 32 [email protected]
33 [email protected] "\n " 33 [email protected]
34 [email protected] 34 [email protected] "break"
35 [email protected] 35 [email protected] ";"
36 [email protected] "break" 36 [email protected] "\n "
37 [email protected] ";" 37 [email protected] "}"
38 [email protected] "\n " 38 [email protected] "\n"
39 [email protected] "}" 39 [email protected] "}"
40 [email protected] "\n"
41 [email protected] "}"
42 [email protected] "\n" 40 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast
index 2c933fa76..57fba5fd5 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0143_box_pat.rast
@@ -9,103 +9,102 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "box"
19 [email protected] "box" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected] "i"
23 [email protected] "i" 23 [email protected] " "
24 [email protected] " " 24 [email protected] "="
25 [email protected] "=" 25 [email protected] " "
26 [email protected] " " 26 [email protected]
27 [email protected] 27 [email protected] "("
28 [email protected] "(" 28 [email protected] ")"
29 [email protected] ")" 29 [email protected] ";"
30 [email protected] ";" 30 [email protected] "\n "
31 [email protected] "\n " 31 [email protected]
32 [email protected] 32 [email protected] "let"
33 [email protected] "let" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected] "box"
36 [email protected] "box" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "Outer"
42 [email protected] "Outer" 42 [email protected] " "
43 [email protected] " " 43 [email protected]
44 [email protected] 44 [email protected] "{"
45 [email protected] "{" 45 [email protected] " "
46 [email protected] " " 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "box"
49 [email protected] "box" 49 [email protected] " "
50 [email protected] " " 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "i"
53 [email protected] "i" 53 [email protected] ","
54 [email protected] "," 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected] "j"
58 [email protected] "j" 58 [email protected] ":"
59 [email protected] ":" 59 [email protected] " "
60 [email protected] " " 60 [email protected]
61 [email protected] 61 [email protected] "box"
62 [email protected] "box" 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected]
65 [email protected] 65 [email protected]
66 [email protected] 66 [email protected]
67 [email protected] 67 [email protected] "Inner"
68 [email protected] "Inner" 68 [email protected] "("
69 [email protected] "(" 69 [email protected]
70 [email protected] 70 [email protected] "box"
71 [email protected] "box" 71 [email protected] " "
72 [email protected] " " 72 [email protected]
73 [email protected] 73 [email protected] "&"
74 [email protected] "&" 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected] "x"
77 [email protected] "x" 77 [email protected] ")"
78 [email protected] ")" 78 [email protected] " "
79 [email protected] " " 79 [email protected] "}"
80 [email protected] "}" 80 [email protected] " "
81 [email protected] " " 81 [email protected] "="
82 [email protected] "=" 82 [email protected] " "
83 [email protected] " " 83 [email protected]
84 [email protected] 84 [email protected] "("
85 [email protected] "(" 85 [email protected] ")"
86 [email protected] ")" 86 [email protected] ";"
87 [email protected] ";" 87 [email protected] "\n "
88 [email protected] "\n " 88 [email protected]
89 [email protected] 89 [email protected] "let"
90 [email protected] "let" 90 [email protected] " "
91 [email protected] " " 91 [email protected]
92 [email protected] 92 [email protected] "box"
93 [email protected] "box" 93 [email protected] " "
94 [email protected] " " 94 [email protected]
95 [email protected] 95 [email protected] "ref"
96 [email protected] "ref" 96 [email protected] " "
97 [email protected] " " 97 [email protected] "mut"
98 [email protected] "mut" 98 [email protected] " "
99 [email protected] " " 99 [email protected]
100 [email protected] 100 [email protected] "i"
101 [email protected] "i" 101 [email protected] " "
102 [email protected] " " 102 [email protected] "="
103 [email protected] "=" 103 [email protected] " "
104 [email protected] " " 104 [email protected]
105 [email protected] 105 [email protected] "("
106 [email protected] "(" 106 [email protected] ")"
107 [email protected] ")" 107 [email protected] ";"
108 [email protected] ";" 108 [email protected] "\n"
109 [email protected] "\n" 109 [email protected] "}"
110 [email protected] "}"
111 [email protected] "\n" 110 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast
index e0b50d8be..8d8b9597b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0144_dot_dot_pat.rast
@@ -9,448 +9,447 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] ".."
19 [email protected] ".." 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "("
24 [email protected] "(" 24 [email protected] ")"
25 [email protected] ")" 25 [email protected] ";"
26 [email protected] ";" 26 [email protected] "\n "
27 [email protected] "\n " 27 [email protected] "//"
28 [email protected] "//" 28 [email protected] "\n "
29 [email protected] "\n " 29 [email protected] "// Tuples"
30 [email protected] "// Tuples" 30 [email protected] "\n "
31 [email protected] "\n " 31 [email protected] "//"
32 [email protected] "//" 32 [email protected] "\n "
33 [email protected] "\n " 33 [email protected]
34 [email protected] 34 [email protected] "let"
35 [email protected] "let" 35 [email protected] " "
36 [email protected] " " 36 [email protected]
37 [email protected] 37 [email protected] "("
38 [email protected] "(" 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected] "a"
41 [email protected] "a" 41 [email protected] ","
42 [email protected] "," 42 [email protected] " "
43 [email protected] " " 43 [email protected]
44 [email protected] 44 [email protected] ".."
45 [email protected] ".." 45 [email protected] ")"
46 [email protected] ")" 46 [email protected] " "
47 [email protected] " " 47 [email protected] "="
48 [email protected] "=" 48 [email protected] " "
49 [email protected] " " 49 [email protected]
50 [email protected] 50 [email protected] "("
51 [email protected] "(" 51 [email protected] ")"
52 [email protected] ")" 52 [email protected] ";"
53 [email protected] ";" 53 [email protected] "\n "
54 [email protected] "\n " 54 [email protected]
55 [email protected] 55 [email protected] "let"
56 [email protected] "let" 56 [email protected] " "
57 [email protected] " " 57 [email protected]
58 [email protected] 58 [email protected] "("
59 [email protected] "(" 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected] "a"
62 [email protected] "a" 62 [email protected] ","
63 [email protected] "," 63 [email protected] " "
64 [email protected] " " 64 [email protected]
65 [email protected] 65 [email protected] ".."
66 [email protected] ".." 66 [email protected] ","
67 [email protected] "," 67 [email protected] ")"
68 [email protected] ")" 68 [email protected] " "
69 [email protected] " " 69 [email protected] "="
70 [email protected] "=" 70 [email protected] " "
71 [email protected] " " 71 [email protected]
72 [email protected] 72 [email protected] "("
73 [email protected] "(" 73 [email protected] ")"
74 [email protected] ")" 74 [email protected] ";"
75 [email protected] ";" 75 [email protected] "\n "
76 [email protected] "\n " 76 [email protected]
77 [email protected] 77 [email protected] "let"
78 [email protected] "let" 78 [email protected] " "
79 [email protected] " " 79 [email protected]
80 [email protected] 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected]
83 [email protected] 83 [email protected] "Tuple"
84 [email protected] "Tuple" 84 [email protected] "("
85 [email protected] "(" 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected] "a"
88 [email protected] "a" 88 [email protected] ","
89 [email protected] "," 89 [email protected] " "
90 [email protected] " " 90 [email protected]
91 [email protected] 91 [email protected] ".."
92 [email protected] ".." 92 [email protected] ")"
93 [email protected] ")" 93 [email protected] " "
94 [email protected] " " 94 [email protected] "="
95 [email protected] "=" 95 [email protected] " "
96 [email protected] " " 96 [email protected]
97 [email protected] 97 [email protected] "("
98 [email protected] "(" 98 [email protected] ")"
99 [email protected] ")" 99 [email protected] ";"
100 [email protected] ";" 100 [email protected] "\n "
101 [email protected] "\n " 101 [email protected]
102 [email protected] 102 [email protected] "let"
103 [email protected] "let" 103 [email protected] " "
104 [email protected] " " 104 [email protected]
105 [email protected] 105 [email protected]
106 [email protected] 106 [email protected]
107 [email protected] 107 [email protected]
108 [email protected] 108 [email protected] "Tuple"
109 [email protected] "Tuple" 109 [email protected] "("
110 [email protected] "(" 110 [email protected]
111 [email protected] 111 [email protected]
112 [email protected] 112 [email protected] "a"
113 [email protected] "a" 113 [email protected] ","
114 [email protected] "," 114 [email protected] " "
115 [email protected] " " 115 [email protected]
116 [email protected] 116 [email protected] ".."
117 [email protected] ".." 117 [email protected] ","
118 [email protected] "," 118 [email protected] ")"
119 [email protected] ")" 119 [email protected] " "
120 [email protected] " " 120 [email protected] "="
121 [email protected] "=" 121 [email protected] " "
122 [email protected] " " 122 [email protected]
123 [email protected] 123 [email protected] "("
124 [email protected] "(" 124 [email protected] ")"
125 [email protected] ")" 125 [email protected] ";"
126 [email protected] ";" 126 [email protected] "\n "
127 [email protected] "\n " 127 [email protected]
128 [email protected] 128 [email protected] "let"
129 [email protected] "let" 129 [email protected] " "
130 [email protected] " " 130 [email protected]
131 [email protected] 131 [email protected] "("
132 [email protected] "(" 132 [email protected]
133 [email protected] 133 [email protected] ".."
134 [email protected] ".." 134 [email protected] ","
135 [email protected] "," 135 [email protected] " "
136 [email protected] " " 136 [email protected]
137 [email protected] 137 [email protected] ".."
138 [email protected] ".." 138 [email protected] ")"
139 [email protected] ")" 139 [email protected] " "
140 [email protected] " " 140 [email protected] "="
141 [email protected] "=" 141 [email protected] " "
142 [email protected] " " 142 [email protected]
143 [email protected] 143 [email protected] "("
144 [email protected] "(" 144 [email protected] ")"
145 [email protected] ")" 145 [email protected] ";"
146 [email protected] ";" 146 [email protected] "\n "
147 [email protected] "\n " 147 [email protected]
148 [email protected] 148 [email protected] "let"
149 [email protected] "let" 149 [email protected] " "
150 [email protected] " " 150 [email protected]
151 [email protected] 151 [email protected]
152 [email protected] 152 [email protected]
153 [email protected] 153 [email protected]
154 [email protected] 154 [email protected] "Tuple"
155 [email protected] "Tuple" 155 [email protected] "("
156 [email protected] "(" 156 [email protected]
157 [email protected] 157 [email protected] ".."
158 [email protected] ".." 158 [email protected] ","
159 [email protected] "," 159 [email protected] " "
160 [email protected] " " 160 [email protected]
161 [email protected] 161 [email protected] ".."
162 [email protected] ".." 162 [email protected] ")"
163 [email protected] ")" 163 [email protected] " "
164 [email protected] " " 164 [email protected] "="
165 [email protected] "=" 165 [email protected] " "
166 [email protected] " " 166 [email protected]
167 [email protected] 167 [email protected] "("
168 [email protected] "(" 168 [email protected] ")"
169 [email protected] ")" 169 [email protected] ";"
170 [email protected] ";" 170 [email protected] "\n "
171 [email protected] "\n " 171 [email protected]
172 [email protected] 172 [email protected] "let"
173 [email protected] "let" 173 [email protected] " "
174 [email protected] " " 174 [email protected]
175 [email protected] 175 [email protected] "("
176 [email protected] "(" 176 [email protected]
177 [email protected] 177 [email protected] ".."
178 [email protected] ".." 178 [email protected] ","
179 [email protected] "," 179 [email protected] " "
180 [email protected] " " 180 [email protected]
181 [email protected] 181 [email protected]
182 [email protected] 182 [email protected] "a"
183 [email protected] "a" 183 [email protected] ","
184 [email protected] "," 184 [email protected] " "
185 [email protected] " " 185 [email protected]
186 [email protected] 186 [email protected] ".."
187 [email protected] ".." 187 [email protected] ")"
188 [email protected] ")" 188 [email protected] " "
189 [email protected] " " 189 [email protected] "="
190 [email protected] "=" 190 [email protected] " "
191 [email protected] " " 191 [email protected]
192 [email protected] 192 [email protected] "("
193 [email protected] "(" 193 [email protected] ")"
194 [email protected] ")" 194 [email protected] ";"
195 [email protected] ";" 195 [email protected] "\n "
196 [email protected] "\n " 196 [email protected]
197 [email protected] 197 [email protected] "let"
198 [email protected] "let" 198 [email protected] " "
199 [email protected] " " 199 [email protected]
200 [email protected] 200 [email protected]
201 [email protected] 201 [email protected]
202 [email protected] 202 [email protected]
203 [email protected] 203 [email protected] "Tuple"
204 [email protected] "Tuple" 204 [email protected] "("
205 [email protected] "(" 205 [email protected]
206 [email protected] 206 [email protected] ".."
207 [email protected] ".." 207 [email protected] ","
208 [email protected] "," 208 [email protected] " "
209 [email protected] " " 209 [email protected]
210 [email protected] 210 [email protected]
211 [email protected] 211 [email protected] "a"
212 [email protected] "a" 212 [email protected] ","
213 [email protected] "," 213 [email protected] " "
214 [email protected] " " 214 [email protected]
215 [email protected] 215 [email protected] ".."
216 [email protected] ".." 216 [email protected] ")"
217 [email protected] ")" 217 [email protected] " "
218 [email protected] " " 218 [email protected] "="
219 [email protected] "=" 219 [email protected] " "
220 [email protected] " " 220 [email protected]
221 [email protected] 221 [email protected] "("
222 [email protected] "(" 222 [email protected] ")"
223 [email protected] ")" 223 [email protected] ";"
224 [email protected] ";" 224 [email protected] "\n "
225 [email protected] "\n " 225 [email protected] "//"
226 [email protected] "//" 226 [email protected] "\n "
227 [email protected] "\n " 227 [email protected] "// Slices"
228 [email protected] "// Slices" 228 [email protected] "\n "
229 [email protected] "\n " 229 [email protected] "//"
230 [email protected] "//" 230 [email protected] "\n "
231 [email protected] "\n " 231 [email protected]
232 [email protected] 232 [email protected] "let"
233 [email protected] "let" 233 [email protected] " "
234 [email protected] " " 234 [email protected]
235 [email protected] 235 [email protected] "["
236 [email protected] "[" 236 [email protected]
237 [email protected] 237 [email protected] ".."
238 [email protected] ".." 238 [email protected] "]"
239 [email protected] "]" 239 [email protected] " "
240 [email protected] " " 240 [email protected] "="
241 [email protected] "=" 241 [email protected] " "
242 [email protected] " " 242 [email protected]
243 [email protected] 243 [email protected] "("
244 [email protected] "(" 244 [email protected] ")"
245 [email protected] ")" 245 [email protected] ";"
246 [email protected] ";" 246 [email protected] "\n "
247 [email protected] "\n " 247 [email protected]
248 [email protected] 248 [email protected] "let"
249 [email protected] "let" 249 [email protected] " "
250 [email protected] " " 250 [email protected]
251 [email protected] 251 [email protected] "["
252 [email protected] "[" 252 [email protected]
253 [email protected] 253 [email protected]
254 [email protected] 254 [email protected] "head"
255 [email protected] "head" 255 [email protected] ","
256 [email protected] "," 256 [email protected] " "
257 [email protected] " " 257 [email protected]
258 [email protected] 258 [email protected] ".."
259 [email protected] ".." 259 [email protected] "]"
260 [email protected] "]" 260 [email protected] " "
261 [email protected] " " 261 [email protected] "="
262 [email protected] "=" 262 [email protected] " "
263 [email protected] " " 263 [email protected]
264 [email protected] 264 [email protected] "("
265 [email protected] "(" 265 [email protected] ")"
266 [email protected] ")" 266 [email protected] ";"
267 [email protected] ";" 267 [email protected] "\n "
268 [email protected] "\n " 268 [email protected]
269 [email protected] 269 [email protected] "let"
270 [email protected] "let" 270 [email protected] " "
271 [email protected] " " 271 [email protected]
272 [email protected] 272 [email protected] "["
273 [email protected] "[" 273 [email protected]
274 [email protected] 274 [email protected]
275 [email protected] 275 [email protected] "head"
276 [email protected] "head" 276 [email protected] ","
277 [email protected] "," 277 [email protected] " "
278 [email protected] " " 278 [email protected]
279 [email protected] 279 [email protected]
280 [email protected] 280 [email protected] "tail"
281 [email protected] "tail" 281 [email protected] " "
282 [email protected] " " 282 [email protected] "@"
283 [email protected] "@" 283 [email protected] " "
284 [email protected] " " 284 [email protected]
285 [email protected] 285 [email protected] ".."
286 [email protected] ".." 286 [email protected] "]"
287 [email protected] "]" 287 [email protected] " "
288 [email protected] " " 288 [email protected] "="
289 [email protected] "=" 289 [email protected] " "
290 [email protected] " " 290 [email protected]
291 [email protected] 291 [email protected] "("
292 [email protected] "(" 292 [email protected] ")"
293 [email protected] ")" 293 [email protected] ";"
294 [email protected] ";" 294 [email protected] "\n "
295 [email protected] "\n " 295 [email protected]
296 [email protected] 296 [email protected] "let"
297 [email protected] "let" 297 [email protected] " "
298 [email protected] " " 298 [email protected]
299 [email protected] 299 [email protected] "["
300 [email protected] "[" 300 [email protected]
301 [email protected] 301 [email protected]
302 [email protected] 302 [email protected] "head"
303 [email protected] "head" 303 [email protected] ","
304 [email protected] "," 304 [email protected] " "
305 [email protected] " " 305 [email protected]
306 [email protected] 306 [email protected] ".."
307 [email protected] ".." 307 [email protected] ","
308 [email protected] "," 308 [email protected] " "
309 [email protected] " " 309 [email protected]
310 [email protected] 310 [email protected]
311 [email protected] 311 [email protected] "cons"
312 [email protected] "cons" 312 [email protected] "]"
313 [email protected] "]" 313 [email protected] " "
314 [email protected] " " 314 [email protected] "="
315 [email protected] "=" 315 [email protected] " "
316 [email protected] " " 316 [email protected]
317 [email protected] 317 [email protected] "("
318 [email protected] "(" 318 [email protected] ")"
319 [email protected] ")" 319 [email protected] ";"
320 [email protected] ";" 320 [email protected] "\n "
321 [email protected] "\n " 321 [email protected]
322 [email protected] 322 [email protected] "let"
323 [email protected] "let" 323 [email protected] " "
324 [email protected] " " 324 [email protected]
325 [email protected] 325 [email protected] "["
326 [email protected] "[" 326 [email protected]
327 [email protected] 327 [email protected]
328 [email protected] 328 [email protected] "head"
329 [email protected] "head" 329 [email protected] ","
330 [email protected] "," 330 [email protected] " "
331 [email protected] " " 331 [email protected]
332 [email protected] 332 [email protected]
333 [email protected] 333 [email protected] "mid"
334 [email protected] "mid" 334 [email protected] " "
335 [email protected] " " 335 [email protected] "@"
336 [email protected] "@" 336 [email protected] " "
337 [email protected] " " 337 [email protected]
338 [email protected] 338 [email protected] ".."
339 [email protected] ".." 339 [email protected] ","
340 [email protected] "," 340 [email protected] " "
341 [email protected] " " 341 [email protected]
342 [email protected] 342 [email protected]
343 [email protected] 343 [email protected] "cons"
344 [email protected] "cons" 344 [email protected] "]"
345 [email protected] "]" 345 [email protected] " "
346 [email protected] " " 346 [email protected] "="
347 [email protected] "=" 347 [email protected] " "
348 [email protected] " " 348 [email protected]
349 [email protected] 349 [email protected] "("
350 [email protected] "(" 350 [email protected] ")"
351 [email protected] ")" 351 [email protected] ";"
352 [email protected] ";" 352 [email protected] "\n "
353 [email protected] "\n " 353 [email protected]
354 [email protected] 354 [email protected] "let"
355 [email protected] "let" 355 [email protected] " "
356 [email protected] " " 356 [email protected]
357 [email protected] 357 [email protected] "["
358 [email protected] "[" 358 [email protected]
359 [email protected] 359 [email protected]
360 [email protected] 360 [email protected] "head"
361 [email protected] "head" 361 [email protected] ","
362 [email protected] "," 362 [email protected] " "
363 [email protected] " " 363 [email protected]
364 [email protected] 364 [email protected] ".."
365 [email protected] ".." 365 [email protected] ","
366 [email protected] "," 366 [email protected] " "
367 [email protected] " " 367 [email protected]
368 [email protected] 368 [email protected] ".."
369 [email protected] ".." 369 [email protected] ","
370 [email protected] "," 370 [email protected] " "
371 [email protected] " " 371 [email protected]
372 [email protected] 372 [email protected]
373 [email protected] 373 [email protected] "cons"
374 [email protected] "cons" 374 [email protected] "]"
375 [email protected] "]" 375 [email protected] " "
376 [email protected] " " 376 [email protected] "="
377 [email protected] "=" 377 [email protected] " "
378 [email protected] " " 378 [email protected]
379 [email protected] 379 [email protected] "("
380 [email protected] "(" 380 [email protected] ")"
381 [email protected] ")" 381 [email protected] ";"
382 [email protected] ";" 382 [email protected] "\n "
383 [email protected] "\n " 383 [email protected]
384 [email protected] 384 [email protected] "let"
385 [email protected] "let" 385 [email protected] " "
386 [email protected] " " 386 [email protected]
387 [email protected] 387 [email protected] "["
388 [email protected] "[" 388 [email protected]
389 [email protected] 389 [email protected]
390 [email protected] 390 [email protected] "head"
391 [email protected] "head" 391 [email protected] ","
392 [email protected] "," 392 [email protected] " "
393 [email protected] " " 393 [email protected]
394 [email protected] 394 [email protected] ".."
395 [email protected] ".." 395 [email protected] ","
396 [email protected] "," 396 [email protected] " "
397 [email protected] " " 397 [email protected]
398 [email protected] 398 [email protected]
399 [email protected] 399 [email protected] "mid"
400 [email protected] "mid" 400 [email protected] ","
401 [email protected] "," 401 [email protected] " "
402 [email protected] " " 402 [email protected]
403 [email protected] 403 [email protected]
404 [email protected] 404 [email protected] "tail"
405 [email protected] "tail" 405 [email protected] " "
406 [email protected] " " 406 [email protected] "@"
407 [email protected] "@" 407 [email protected] " "
408 [email protected] " " 408 [email protected]
409 [email protected] 409 [email protected] ".."
410 [email protected] ".." 410 [email protected] "]"
411 [email protected] "]" 411 [email protected] " "
412 [email protected] " " 412 [email protected] "="
413 [email protected] "=" 413 [email protected] " "
414 [email protected] " " 414 [email protected]
415 [email protected] 415 [email protected] "("
416 [email protected] "(" 416 [email protected] ")"
417 [email protected] ")" 417 [email protected] ";"
418 [email protected] ";" 418 [email protected] "\n "
419 [email protected] "\n " 419 [email protected]
420 [email protected] 420 [email protected] "let"
421 [email protected] "let" 421 [email protected] " "
422 [email protected] " " 422 [email protected]
423 [email protected] 423 [email protected] "["
424 [email protected] "[" 424 [email protected]
425 [email protected] 425 [email protected]
426 [email protected] 426 [email protected] "head"
427 [email protected] "head" 427 [email protected] ","
428 [email protected] "," 428 [email protected] " "
429 [email protected] " " 429 [email protected]
430 [email protected] 430 [email protected] ".."
431 [email protected] ".." 431 [email protected] ","
432 [email protected] "," 432 [email protected] " "
433 [email protected] " " 433 [email protected]
434 [email protected] 434 [email protected]
435 [email protected] 435 [email protected] "mid"
436 [email protected] "mid" 436 [email protected] ","
437 [email protected] "," 437 [email protected] " "
438 [email protected] " " 438 [email protected]
439 [email protected] 439 [email protected] ".."
440 [email protected] ".." 440 [email protected] ","
441 [email protected] "," 441 [email protected] " "
442 [email protected] " " 442 [email protected]
443 [email protected] 443 [email protected]
444 [email protected] 444 [email protected] "cons"
445 [email protected] "cons" 445 [email protected] "]"
446 [email protected] "]" 446 [email protected] " "
447 [email protected] " " 447 [email protected] "="
448 [email protected] "=" 448 [email protected] " "
449 [email protected] " " 449 [email protected]
450 [email protected] 450 [email protected] "("
451 [email protected] "(" 451 [email protected] ")"
452 [email protected] ")" 452 [email protected] ";"
453 [email protected] ";" 453 [email protected] "\n"
454 [email protected] "\n" 454 [email protected] "}"
455 [email protected] "}"
456 [email protected] "\n" 455 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast b/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast
index 10434b637..7c092d518 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0145_record_field_pat.rast
@@ -9,68 +9,67 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "S"
22 [email protected] "S" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "{"
25 [email protected] "{" 25 [email protected] " "
26 [email protected] " " 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected] "0"
29 [email protected] "0" 29 [email protected] ":"
30 [email protected] ":" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected] "1"
34 [email protected] "1" 34 [email protected] " "
35 [email protected] " " 35 [email protected] "}"
36 [email protected] "}" 36 [email protected] " "
37 [email protected] " " 37 [email protected] "="
38 [email protected] "=" 38 [email protected] " "
39 [email protected] " " 39 [email protected]
40 [email protected] 40 [email protected] "("
41 [email protected] "(" 41 [email protected] ")"
42 [email protected] ")" 42 [email protected] ";"
43 [email protected] ";" 43 [email protected] "\n "
44 [email protected] "\n " 44 [email protected]
45 [email protected] 45 [email protected] "let"
46 [email protected] "let" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected] "S"
52 [email protected] "S" 52 [email protected] " "
53 [email protected] " " 53 [email protected]
54 [email protected] 54 [email protected] "{"
55 [email protected] "{" 55 [email protected] " "
56 [email protected] " " 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected] "x"
59 [email protected] "x" 59 [email protected] ":"
60 [email protected] ":" 60 [email protected] " "
61 [email protected] " " 61 [email protected]
62 [email protected] 62 [email protected]
63 [email protected] 63 [email protected] "1"
64 [email protected] "1" 64 [email protected] " "
65 [email protected] " " 65 [email protected] "}"
66 [email protected] "}" 66 [email protected] " "
67 [email protected] " " 67 [email protected] "="
68 [email protected] "=" 68 [email protected] " "
69 [email protected] " " 69 [email protected]
70 [email protected] 70 [email protected] "("
71 [email protected] "(" 71 [email protected] ")"
72 [email protected] ")" 72 [email protected] ";"
73 [email protected] ";" 73 [email protected] "\n"
74 [email protected] "\n" 74 [email protected] "}"
75 [email protected] "}"
76 [email protected] "\n" 75 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast b/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast
index 66ad546b9..8382a4f96 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rast
@@ -9,35 +9,34 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected] "&"
25 [email protected] "&" 25 [email protected]
26 [email protected] 26 [email protected] "1"
27 [email protected] "1" 27 [email protected] " "
28 [email protected] " " 28 [email protected] "as"
29 [email protected] "as" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "*"
32 [email protected] "*" 32 [email protected] "const"
33 [email protected] "const" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "i32"
39 [email protected] "i32" 39 [email protected] ";"
40 [email protected] ";" 40 [email protected] "\n"
41 [email protected] "\n" 41 [email protected] "}"
42 [email protected] "}"
43 [email protected] "\n" 42 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast b/crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast
index c2e290a62..f43dfbe63 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0152_arg_with_attr.rast
@@ -9,29 +9,28 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "foo"
20 [email protected] "foo" 20 [email protected]
21 [email protected] 21 [email protected] "("
22 [email protected] "(" 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected] "#"
25 [email protected] "#" 25 [email protected] "["
26 [email protected] "[" 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "attr"
30 [email protected] "attr" 30 [email protected] "]"
31 [email protected] "]" 31 [email protected] " "
32 [email protected] " " 32 [email protected] "92"
33 [email protected] "92" 33 [email protected] ")"
34 [email protected] ")" 34 [email protected] "\n"
35 [email protected] "\n" 35 [email protected] "}"
36 [email protected] "}"
37 [email protected] "\n" 36 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rast b/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rast
index dad3dfe4d..ecac05950 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0155_closure_params.rast
@@ -9,62 +9,61 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "foo"
20 [email protected] "foo" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "="
22 [email protected] "=" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "|"
26 [email protected] "|" 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "bar"
30 [email protected] "bar" 30 [email protected] ","
31 [email protected] "," 31 [email protected] " "
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "baz"
36 [email protected] "baz" 36 [email protected] ":"
37 [email protected] ":" 37 [email protected] " "
38 [email protected] " " 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected] "Baz"
43 [email protected] "Baz" 43 [email protected] ","
44 [email protected] "," 44 [email protected] " "
45 [email protected] " " 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "qux"
49 [email protected] "qux" 49 [email protected] ":"
50 [email protected] ":" 50 [email protected] " "
51 [email protected] " " 51 [email protected]
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected]
56 [email protected] 56 [email protected] "Qux"
57 [email protected] "Qux" 57 [email protected] "::"
58 [email protected] "::" 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected] "Quux"
61 [email protected] "Quux" 61 [email protected] "|"
62 [email protected] "|" 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected] "("
65 [email protected] "(" 65 [email protected] ")"
66 [email protected] ")" 66 [email protected] ";"
67 [email protected] ";" 67 [email protected] "\n"
68 [email protected] "\n" 68 [email protected] "}"
69 [email protected] "}"
70 [email protected] "\n" 69 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0156_fn_def_param.rast b/crates/ra_syntax/test_data/parser/inline/ok/0156_fn_def_param.rast
index 3110bf5c0..092833417 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0156_fn_def_param.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0156_fn_def_param.rast
@@ -38,7 +38,6 @@ [email protected]
38 [email protected] ")" 38 [email protected] ")"
39 [email protected] " " 39 [email protected] " "
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "{"
42 [email protected] "{" 42 [email protected] "}"
43 [email protected] "}"
44 [email protected] "\n" 43 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rast b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rast
index 3f3e6a9a2..88d512f1a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0156_or_pattern.rast
@@ -9,104 +9,103 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "("
19 [email protected] "(" 19 [email protected] ")"
20 [email protected] ")" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "{"
23 [email protected] "{" 23 [email protected] "\n "
24 [email protected] "\n " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "("
27 [email protected] "(" 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "_"
30 [email protected] "_" 30 [email protected] " "
31 [email protected] " " 31 [email protected] "|"
32 [email protected] "|" 32 [email protected] " "
33 [email protected] " " 33 [email protected]
34 [email protected] 34 [email protected] "_"
35 [email protected] "_" 35 [email protected] ")"
36 [email protected] ")" 36 [email protected] " "
37 [email protected] " " 37 [email protected] "=>"
38 [email protected] "=>" 38 [email protected] " "
39 [email protected] " " 39 [email protected]
40 [email protected] 40 [email protected] "("
41 [email protected] "(" 41 [email protected] ")"
42 [email protected] ")" 42 [email protected] ","
43 [email protected] "," 43 [email protected] "\n "
44 [email protected] "\n " 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected] "&"
47 [email protected] "&" 47 [email protected]
48 [email protected] 48 [email protected] "("
49 [email protected] "(" 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected] "_"
52 [email protected] "_" 52 [email protected] " "
53 [email protected] " " 53 [email protected] "|"
54 [email protected] "|" 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] 56 [email protected] "_"
57 [email protected] "_" 57 [email protected] ")"
58 [email protected] ")" 58 [email protected] " "
59 [email protected] " " 59 [email protected] "=>"
60 [email protected] "=>" 60 [email protected] " "
61 [email protected] " " 61 [email protected]
62 [email protected] 62 [email protected] "("
63 [email protected] "(" 63 [email protected] ")"
64 [email protected] ")" 64 [email protected] ","
65 [email protected] "," 65 [email protected] "\n "
66 [email protected] "\n " 66 [email protected]
67 [email protected] 67 [email protected]
68 [email protected] 68 [email protected] "("
69 [email protected] "(" 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected] "_"
72 [email protected] "_" 72 [email protected] " "
73 [email protected] " " 73 [email protected] "|"
74 [email protected] "|" 74 [email protected] " "
75 [email protected] " " 75 [email protected]
76 [email protected] 76 [email protected] "_"
77 [email protected] "_" 77 [email protected] ","
78 [email protected] "," 78 [email protected] ")"
79 [email protected] ")" 79 [email protected] " "
80 [email protected] " " 80 [email protected] "=>"
81 [email protected] "=>" 81 [email protected] " "
82 [email protected] " " 82 [email protected]
83 [email protected] 83 [email protected] "("
84 [email protected] "(" 84 [email protected] ")"
85 [email protected] ")" 85 [email protected] ","
86 [email protected] "," 86 [email protected] "\n "
87 [email protected] "\n " 87 [email protected]
88 [email protected] 88 [email protected]
89 [email protected] 89 [email protected] "["
90 [email protected] "[" 90 [email protected]
91 [email protected] 91 [email protected]
92 [email protected] 92 [email protected] "_"
93 [email protected] "_" 93 [email protected] " "
94 [email protected] " " 94 [email protected] "|"
95 [email protected] "|" 95 [email protected] " "
96 [email protected] " " 96 [email protected]
97 [email protected] 97 [email protected] "_"
98 [email protected] "_" 98 [email protected] ","
99 [email protected] "," 99 [email protected] "]"
100 [email protected] "]" 100 [email protected] " "
101 [email protected] " " 101 [email protected] "=>"
102 [email protected] "=>" 102 [email protected] " "
103 [email protected] " " 103 [email protected]
104 [email protected] 104 [email protected] "("
105 [email protected] "(" 105 [email protected] ")"
106 [email protected] ")" 106 [email protected] ","
107 [email protected] "," 107 [email protected] "\n "
108 [email protected] "\n " 108 [email protected] "}"
109 [email protected] "}" 109 [email protected] "\n"
110 [email protected] "\n" 110 [email protected] "}"
111 [email protected] "}"
112 [email protected] "\n" 111 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast b/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast
index 50db9e967..bd9e8d40f 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rast
@@ -9,30 +9,28 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "v"
21 [email protected] "v" 21 [email protected] " "
22 [email protected] " " 22 [email protected] "="
23 [email protected] "=" 23 [email protected] " "
24 [email protected] " " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "{"
27 [email protected] 27 [email protected]
28 [email protected] "{" 28 [email protected] "1"
29 [email protected] 29 [email protected] "}"
30 [email protected] "1" 30 [email protected] "&"
31 [email protected] "}" 31 [email protected]
32 [email protected] "&" 32 [email protected] "2"
33 [email protected] 33 [email protected] ";"
34 [email protected] "2" 34 [email protected] "\n"
35 [email protected] ";" 35 [email protected] "}"
36 [email protected] "\n"
37 [email protected] "}"
38 [email protected] "\n" 36 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast b/crates/ra_syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast
index c05e05bf3..08333a325 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0158_lambda_ret_block.rast
@@ -9,37 +9,35 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected] "|"
19 [email protected] "|" 19 [email protected] "|"
20 [email protected] "|" 20 [email protected] " "
21 [email protected] " " 21 [email protected]
22 [email protected] 22 [email protected] "->"
23 [email protected] "->" 23 [email protected] " "
24 [email protected] " " 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected] "i32"
29 [email protected] "i32" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "{"
32 [email protected] 32 [email protected] " "
33 [email protected] "{" 33 [email protected]
34 [email protected] " " 34 [email protected] "92"
35 [email protected] 35 [email protected] " "
36 [email protected] "92" 36 [email protected] "}"
37 [email protected] " " 37 [email protected]
38 [email protected] "}" 38 [email protected] "("
39 [email protected] 39 [email protected] ")"
40 [email protected] "(" 40 [email protected] ";"
41 [email protected] ")" 41 [email protected] " "
42 [email protected] ";" 42 [email protected] "}"
43 [email protected] " "
44 [email protected] "}"
45 [email protected] "\n" 43 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast b/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast
index beb6d8010..5f09e4f4a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast
@@ -9,27 +9,26 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "try"
20 [email protected] "try" 20 [email protected] "!"
21 [email protected] "!" 21 [email protected]
22 [email protected] 22 [email protected] "("
23 [email protected] "(" 23 [email protected] "Ok"
24 [email protected] "Ok" 24 [email protected]
25 [email protected] 25 [email protected] "("
26 [email protected] "(" 26 [email protected]
27 [email protected] 27 [email protected] "("
28 [email protected] "(" 28 [email protected] ")"
29 [email protected] ")" 29 [email protected] ")"
30 [email protected] ")" 30 [email protected] ")"
31 [email protected] ")" 31 [email protected] ";"
32 [email protected] ";" 32 [email protected] " "
33 [email protected] " " 33 [email protected] "}"
34 [email protected] "}"
35 [email protected] "\n" 34 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0161_labeled_block.rast b/crates/ra_syntax/test_data/parser/inline/ok/0161_labeled_block.rast
new file mode 100644
index 000000000..9efebd8b8
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0161_labeled_block.rast
@@ -0,0 +1,26 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "f"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] " "
14 [email protected]
15 [email protected]
16 [email protected]
17 [email protected] "\'label"
18 [email protected] ":"
19 [email protected] " "
20 [email protected]
21 [email protected] "{"
22 [email protected] "}"
23 [email protected] ";"
24 [email protected] " "
25 [email protected] "}"
26 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0161_labeled_block.rs b/crates/ra_syntax/test_data/parser/inline/ok/0161_labeled_block.rs
new file mode 100644
index 000000000..18b4ff4b1
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0161_labeled_block.rs
@@ -0,0 +1 @@
fn f() { 'label: {}; }
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0162_unsafe_block.rast b/crates/ra_syntax/test_data/parser/inline/ok/0162_unsafe_block.rast
new file mode 100644
index 000000000..4991f2c36
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0162_unsafe_block.rast
@@ -0,0 +1,23 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "f"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] " "
14 [email protected]
15 [email protected] "unsafe"
16 [email protected] " "
17 [email protected]
18 [email protected] "{"
19 [email protected] " "
20 [email protected] "}"
21 [email protected] " "
22 [email protected] "}"
23 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0162_unsafe_block.rs b/crates/ra_syntax/test_data/parser/inline/ok/0162_unsafe_block.rs
new file mode 100644
index 000000000..dfb9b2a1c
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0162_unsafe_block.rs
@@ -0,0 +1 @@
fn f() { unsafe { } }
diff --git a/crates/ra_syntax/test_data/parser/ok/0005_fn_item.rast b/crates/ra_syntax/test_data/parser/ok/0005_fn_item.rast
index 993ba72b6..0ec237f8e 100644
--- a/crates/ra_syntax/test_data/parser/ok/0005_fn_item.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0005_fn_item.rast
@@ -9,8 +9,7 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n"
14 [email protected] "\n" 14 [email protected] "}"
15 [email protected] "}"
16 [email protected] "\n" 15 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0008_mod_item.rast b/crates/ra_syntax/test_data/parser/ok/0008_mod_item.rast
index 353bf2d2e..37b452ec4 100644
--- a/crates/ra_syntax/test_data/parser/ok/0008_mod_item.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0008_mod_item.rast
@@ -36,10 +36,9 @@ [email protected]
36 [email protected] ")" 36 [email protected] ")"
37 [email protected] " " 37 [email protected] " "
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected] "{"
40 [email protected] "{" 40 [email protected] "\n "
41 [email protected] "\n " 41 [email protected] "}"
42 [email protected] "}"
43 [email protected] "\n " 42 [email protected] "\n "
44 [email protected] 43 [email protected]
45 [email protected] "struct" 44 [email protected] "struct"
diff --git a/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rast b/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rast
index 3919cc78b..0b9bc58e8 100644
--- a/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rast
@@ -31,9 +31,8 @@ [email protected]
31 [email protected] ")" 31 [email protected] ")"
32 [email protected] " " 32 [email protected] " "
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected] "{"
35 [email protected] "{" 35 [email protected] "}"
36 [email protected] "}"
37 [email protected] "\n\n" 36 [email protected] "\n\n"
38 [email protected] 37 [email protected]
39 [email protected] 38 [email protected]
diff --git a/crates/ra_syntax/test_data/parser/ok/0012_visibility.rast b/crates/ra_syntax/test_data/parser/ok/0012_visibility.rast
index 750a045ef..980b34049 100644
--- a/crates/ra_syntax/test_data/parser/ok/0012_visibility.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0012_visibility.rast
@@ -9,9 +9,8 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "}"
14 [email protected] "}"
15 [email protected] "\n" 14 [email protected] "\n"
16 [email protected] 15 [email protected]
17 [email protected] 16 [email protected]
@@ -26,9 +25,8 @@ [email protected]
26 [email protected] ")" 25 [email protected] ")"
27 [email protected] " " 26 [email protected] " "
28 [email protected] 27 [email protected]
29 [email protected] 28 [email protected] "{"
30 [email protected] "{" 29 [email protected] "}"
31 [email protected] "}"
32 [email protected] "\n" 30 [email protected] "\n"
33 [email protected] 31 [email protected]
34 [email protected] 32 [email protected]
@@ -46,9 +44,8 @@ [email protected]
46 [email protected] ")" 44 [email protected] ")"
47 [email protected] " " 45 [email protected] " "
48 [email protected] 46 [email protected]
49 [email protected] 47 [email protected] "{"
50 [email protected] "{" 48 [email protected] "}"
51 [email protected] "}"
52 [email protected] "\n" 49 [email protected] "\n"
53 [email protected] 50 [email protected]
54 [email protected] 51 [email protected]
@@ -66,9 +63,8 @@ [email protected]
66 [email protected] ")" 63 [email protected] ")"
67 [email protected] " " 64 [email protected] " "
68 [email protected] 65 [email protected]
69 [email protected] 66 [email protected] "{"
70 [email protected] "{" 67 [email protected] "}"
71 [email protected] "}"
72 [email protected] "\n" 68 [email protected] "\n"
73 [email protected] 69 [email protected]
74 [email protected] 70 [email protected]
@@ -101,7 +97,6 @@ [email protected]
101 [email protected] ")" 97 [email protected] ")"
102 [email protected] " " 98 [email protected] " "
103 [email protected] 99 [email protected]
104 [email protected] 100 [email protected] "{"
105 [email protected] "{" 101 [email protected] "}"
106 [email protected] "}"
107 [email protected] "\n" 102 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.rast b/crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.rast
index b5747aacd..964cbf5dd 100644
--- a/crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.rast
@@ -23,7 +23,6 @@ [email protected]
23 [email protected] ")" 23 [email protected] ")"
24 [email protected] " " 24 [email protected] " "
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "{"
27 [email protected] "{" 27 [email protected] "}"
28 [email protected] "}"
29 [email protected] "\n" 28 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rast b/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rast
index 643a1d16c..873791f50 100644
--- a/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0021_extern_fn.rast
@@ -12,10 +12,9 @@ [email protected]
12 [email protected] ")" 12 [email protected] ")"
13 [email protected] " " 13 [email protected] " "
14 [email protected] 14 [email protected]
15 [email protected] 15 [email protected] "{"
16 [email protected] "{" 16 [email protected] "\n"
17 [email protected] "\n" 17 [email protected] "}"
18 [email protected] "}"
19 [email protected] "\n\n" 18 [email protected] "\n\n"
20 [email protected] 19 [email protected]
21 [email protected] 20 [email protected]
@@ -32,10 +31,9 @@ [email protected]
32 [email protected] ")" 31 [email protected] ")"
33 [email protected] " " 32 [email protected] " "
34 [email protected] 33 [email protected]
35 [email protected] 34 [email protected] "{"
36 [email protected] "{" 35 [email protected] "\n"
37 [email protected] "\n" 36 [email protected] "}"
38 [email protected] "}"
39 [email protected] "\n\n" 37 [email protected] "\n\n"
40 [email protected] 38 [email protected]
41 [email protected] 39 [email protected]
@@ -52,8 +50,7 @@ [email protected]
52 [email protected] ")" 50 [email protected] ")"
53 [email protected] " " 51 [email protected] " "
54 [email protected] 52 [email protected]
55 [email protected] 53 [email protected] "{"
56 [email protected] "{" 54 [email protected] "\n"
57 [email protected] "\n" 55 [email protected] "}"
58 [email protected] "}"
59 [email protected] "\n" 56 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0025_extern_fn_in_block.rast b/crates/ra_syntax/test_data/parser/ok/0025_extern_fn_in_block.rast
index 60af55837..5701f566e 100644
--- a/crates/ra_syntax/test_data/parser/ok/0025_extern_fn_in_block.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0025_extern_fn_in_block.rast
@@ -9,25 +9,23 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "extern"
17 [email protected] "extern" 17 [email protected] " "
18 [email protected] " " 18 [email protected] "fn"
19 [email protected] "fn" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "f"
22 [email protected] "f" 22 [email protected]
23 [email protected] 23 [email protected] "("
24 [email protected] "(" 24 [email protected] ")"
25 [email protected] ")" 25 [email protected] " "
26 [email protected] " " 26 [email protected]
27 [email protected] 27 [email protected] "{"
28 [email protected] 28 [email protected] "}"
29 [email protected] "{" 29 [email protected] "\n"
30 [email protected] "}" 30 [email protected] "}"
31 [email protected] "\n"
32 [email protected] "}"
33 [email protected] "\n" 31 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0026_const_fn_in_block.rast b/crates/ra_syntax/test_data/parser/ok/0026_const_fn_in_block.rast
index 4432c0163..b029d8692 100644
--- a/crates/ra_syntax/test_data/parser/ok/0026_const_fn_in_block.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0026_const_fn_in_block.rast
@@ -9,24 +9,22 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "const"
16 [email protected] "const" 16 [email protected] " "
17 [email protected] " " 17 [email protected] "fn"
18 [email protected] "fn" 18 [email protected] " "
19 [email protected] " " 19 [email protected]
20 [email protected] 20 [email protected] "f"
21 [email protected] "f" 21 [email protected]
22 [email protected] 22 [email protected] "("
23 [email protected] "(" 23 [email protected] ")"
24 [email protected] ")" 24 [email protected] " "
25 [email protected] " " 25 [email protected]
26 [email protected] 26 [email protected] "{"
27 [email protected] 27 [email protected] "}"
28 [email protected] "{" 28 [email protected] "\n"
29 [email protected] "}" 29 [email protected] "}"
30 [email protected] "\n"
31 [email protected] "}"
32 [email protected] "\n" 30 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast b/crates/ra_syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast
index c0162c609..299bbd136 100644
--- a/crates/ra_syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0027_unsafe_fn_in_block.rast
@@ -9,35 +9,33 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "unsafe"
16 [email protected] "unsafe" 16 [email protected] " "
17 [email protected] " " 17 [email protected] "fn"
18 [email protected] "fn" 18 [email protected] " "
19 [email protected] " " 19 [email protected]
20 [email protected] 20 [email protected] "f"
21 [email protected] "f" 21 [email protected]
22 [email protected] 22 [email protected] "("
23 [email protected] "(" 23 [email protected] ")"
24 [email protected] ")" 24 [email protected] " "
25 [email protected] " " 25 [email protected]
26 [email protected] 26 [email protected] "{"
27 [email protected] 27 [email protected] "}"
28 [email protected] "{" 28 [email protected] "\n "
29 [email protected] "}" 29 [email protected]
30 [email protected] "\n " 30 [email protected] "unsafe"
31 [email protected] 31 [email protected] " "
32 [email protected] "unsafe" 32 [email protected]
33 [email protected] " " 33 [email protected] "{"
34 [email protected] 34 [email protected] " "
35 [email protected] "{" 35 [email protected]
36 [email protected] " " 36 [email protected] "92"
37 [email protected] 37 [email protected] " "
38 [email protected] "92" 38 [email protected] "}"
39 [email protected] " " 39 [email protected] "\n"
40 [email protected] "}" 40 [email protected] "}"
41 [email protected] "\n"
42 [email protected] "}"
43 [email protected] "\n" 41 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0028_operator_binding_power.rast b/crates/ra_syntax/test_data/parser/ok/0028_operator_binding_power.rast
index 6c0daef52..de3c4b786 100644
--- a/crates/ra_syntax/test_data/parser/ok/0028_operator_binding_power.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0028_operator_binding_power.rast
@@ -9,178 +9,177 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "x"
20 [email protected] "x" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "="
22 [email protected] "=" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "1"
27 [email protected] "1" 27 [email protected] " "
28 [email protected] " " 28 [email protected] "+"
29 [email protected] "+" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected] "2"
34 [email protected] "2" 34 [email protected] " "
35 [email protected] " " 35 [email protected] "*"
36 [email protected] "*" 36 [email protected] " "
37 [email protected] " " 37 [email protected]
38 [email protected] 38 [email protected] "3"
39 [email protected] "3" 39 [email protected] " "
40 [email protected] " " 40 [email protected] "%"
41 [email protected] "%" 41 [email protected] " "
42 [email protected] " " 42 [email protected]
43 [email protected] 43 [email protected] "4"
44 [email protected] "4" 44 [email protected] " "
45 [email protected] " " 45 [email protected] "-"
46 [email protected] "-" 46 [email protected] " "
47 [email protected] " " 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected] "5"
50 [email protected] "5" 50 [email protected] " "
51 [email protected] " " 51 [email protected] "/"
52 [email protected] "/" 52 [email protected] " "
53 [email protected] " " 53 [email protected]
54 [email protected] 54 [email protected] "6"
55 [email protected] "6" 55 [email protected] ";"
56 [email protected] ";" 56 [email protected] "\n "
57 [email protected] "\n " 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected] "1"
61 [email protected] "1" 61 [email protected] " "
62 [email protected] " " 62 [email protected] "+"
63 [email protected] "+" 63 [email protected] " "
64 [email protected] " " 64 [email protected]
65 [email protected] 65 [email protected]
66 [email protected] 66 [email protected] "2"
67 [email protected] "2" 67 [email protected] " "
68 [email protected] " " 68 [email protected] "*"
69 [email protected] "*" 69 [email protected] " "
70 [email protected] " " 70 [email protected]
71 [email protected] 71 [email protected] "3"
72 [email protected] "3" 72 [email protected] ";"
73 [email protected] ";" 73 [email protected] "\n "
74 [email protected] "\n " 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] 77 [email protected] "1"
78 [email protected] "1" 78 [email protected] " "
79 [email protected] " " 79 [email protected] "<<"
80 [email protected] "<<" 80 [email protected] " "
81 [email protected] " " 81 [email protected]
82 [email protected] 82 [email protected]
83 [email protected] 83 [email protected] "2"
84 [email protected] "2" 84 [email protected] " "
85 [email protected] " " 85 [email protected] "+"
86 [email protected] "+" 86 [email protected] " "
87 [email protected] " " 87 [email protected]
88 [email protected] 88 [email protected] "3"
89 [email protected] "3" 89 [email protected] ";"
90 [email protected] ";" 90 [email protected] "\n "
91 [email protected] "\n " 91 [email protected]
92 [email protected] 92 [email protected]
93 [email protected] 93 [email protected]
94 [email protected] 94 [email protected] "1"
95 [email protected] "1" 95 [email protected] " "
96 [email protected] " " 96 [email protected] "&"
97 [email protected] "&" 97 [email protected] " "
98 [email protected] " " 98 [email protected]
99 [email protected] 99 [email protected]
100 [email protected] 100 [email protected] "2"
101 [email protected] "2" 101 [email protected] " "
102 [email protected] " " 102 [email protected] ">>"
103 [email protected] ">>" 103 [email protected] " "
104 [email protected] " " 104 [email protected]
105 [email protected] 105 [email protected] "3"
106 [email protected] "3" 106 [email protected] ";"
107 [email protected] ";" 107 [email protected] "\n "
108 [email protected] "\n " 108 [email protected]
109 [email protected] 109 [email protected]
110 [email protected] 110 [email protected]
111 [email protected] 111 [email protected] "1"
112 [email protected] "1" 112 [email protected] " "
113 [email protected] " " 113 [email protected] "^"
114 [email protected] "^" 114 [email protected] " "
115 [email protected] " " 115 [email protected]
116 [email protected] 116 [email protected]
117 [email protected] 117 [email protected] "2"
118 [email protected] "2" 118 [email protected] " "
119 [email protected] " " 119 [email protected] "&"
120 [email protected] "&" 120 [email protected] " "
121 [email protected] " " 121 [email protected]
122 [email protected] 122 [email protected] "3"
123 [email protected] "3" 123 [email protected] ";"
124 [email protected] ";" 124 [email protected] "\n "
125 [email protected] "\n " 125 [email protected]
126 [email protected] 126 [email protected]
127 [email protected] 127 [email protected]
128 [email protected] 128 [email protected] "1"
129 [email protected] "1" 129 [email protected] " "
130 [email protected] " " 130 [email protected] "|"
131 [email protected] "|" 131 [email protected] " "
132 [email protected] " " 132 [email protected]
133 [email protected] 133 [email protected]
134 [email protected] 134 [email protected] "2"
135 [email protected] "2" 135 [email protected] " "
136 [email protected] " " 136 [email protected] "^"
137 [email protected] "^" 137 [email protected] " "
138 [email protected] " " 138 [email protected]
139 [email protected] 139 [email protected] "3"
140 [email protected] "3" 140 [email protected] ";"
141 [email protected] ";" 141 [email protected] "\n "
142 [email protected] "\n " 142 [email protected]
143 [email protected] 143 [email protected]
144 [email protected] 144 [email protected]
145 [email protected] 145 [email protected] "1"
146 [email protected] "1" 146 [email protected] " "
147 [email protected] " " 147 [email protected] "=="
148 [email protected] "==" 148 [email protected] " "
149 [email protected] " " 149 [email protected]
150 [email protected] 150 [email protected]
151 [email protected] 151 [email protected] "2"
152 [email protected] "2" 152 [email protected] " "
153 [email protected] " " 153 [email protected] "|"
154 [email protected] "|" 154 [email protected] " "
155 [email protected] " " 155 [email protected]
156 [email protected] 156 [email protected] "3"
157 [email protected] "3" 157 [email protected] ";"
158 [email protected] ";" 158 [email protected] "\n "
159 [email protected] "\n " 159 [email protected]
160 [email protected] 160 [email protected]
161 [email protected] 161 [email protected]
162 [email protected] 162 [email protected] "1"
163 [email protected] "1" 163 [email protected] " "
164 [email protected] " " 164 [email protected] "&&"
165 [email protected] "&&" 165 [email protected] " "
166 [email protected] " " 166 [email protected]
167 [email protected] 167 [email protected]
168 [email protected] 168 [email protected] "2"
169 [email protected] "2" 169 [email protected] " "
170 [email protected] " " 170 [email protected] "=="
171 [email protected] "==" 171 [email protected] " "
172 [email protected] " " 172 [email protected]
173 [email protected] 173 [email protected] "3"
174 [email protected] "3" 174 [email protected] ";"
175 [email protected] ";" 175 [email protected] "\n "
176 [email protected] "\n " 176 [email protected] "//1 || 2 && 2;"
177 [email protected] "//1 || 2 && 2;" 177 [email protected] "\n "
178 [email protected] "\n " 178 [email protected] "//1 .. 2 || 3;"
179 [email protected] "//1 .. 2 || 3;" 179 [email protected] "\n "
180 [email protected] "\n " 180 [email protected] "//1 = 2 .. 3;"
181 [email protected] "//1 = 2 .. 3;" 181 [email protected] "\n "
182 [email protected] "\n " 182 [email protected] "//---&*1 - --2 * 9;"
183 [email protected] "//---&*1 - --2 * 9;" 183 [email protected] "\n"
184 [email protected] "\n" 184 [email protected] "}"
185 [email protected] "}"
186 [email protected] "\n" 185 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0029_range_forms.rast b/crates/ra_syntax/test_data/parser/ok/0029_range_forms.rast
index 8177bd89b..dc47d68a6 100644
--- a/crates/ra_syntax/test_data/parser/ok/0029_range_forms.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0029_range_forms.rast
@@ -9,144 +9,143 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] ".."
17 [email protected] ".." 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "1"
20 [email protected] "1" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "+"
22 [email protected] "+" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "1"
25 [email protected] "1" 25 [email protected] ";"
26 [email protected] ";" 26 [email protected] "\n "
27 [email protected] "\n " 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected]
30 [email protected] 30 [email protected] ".."
31 [email protected] ".." 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "z"
36 [email protected] "z" 36 [email protected] " "
37 [email protected] " " 37 [email protected] "="
38 [email protected] "=" 38 [email protected] " "
39 [email protected] " " 39 [email protected]
40 [email protected] 40 [email protected] "2"
41 [email protected] "2" 41 [email protected] ";"
42 [email protected] ";" 42 [email protected] "\n "
43 [email protected] "\n " 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected] "x"
50 [email protected] "x" 50 [email protected] " "
51 [email protected] " " 51 [email protected] "="
52 [email protected] "=" 52 [email protected] " "
53 [email protected] " " 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected] "false"
56 [email protected] "false" 56 [email protected] ".."
57 [email protected] ".." 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected] "1"
60 [email protected] "1" 60 [email protected] " "
61 [email protected] " " 61 [email protected] "=="
62 [email protected] "==" 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected] "1"
65 [email protected] "1" 65 [email protected] ";"
66 [email protected] ";" 66 [email protected] "\n "
67 [email protected] "\n " 67 [email protected]
68 [email protected] 68 [email protected] "let"
69 [email protected] "let" 69 [email protected] " "
70 [email protected] " " 70 [email protected]
71 [email protected] 71 [email protected]
72 [email protected] 72 [email protected] "x"
73 [email protected] "x" 73 [email protected] " "
74 [email protected] " " 74 [email protected] "="
75 [email protected] "=" 75 [email protected] " "
76 [email protected] " " 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected] "1"
79 [email protected] "1" 79 [email protected] ".."
80 [email protected] ".." 80 [email protected] ";"
81 [email protected] ";" 81 [email protected] "\n \n "
82 [email protected] "\n \n " 82 [email protected]
83 [email protected] 83 [email protected]
84 [email protected] 84 [email protected] "..="
85 [email protected] "..=" 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected] "1"
88 [email protected] "1" 88 [email protected] " "
89 [email protected] " " 89 [email protected] "+"
90 [email protected] "+" 90 [email protected] " "
91 [email protected] " " 91 [email protected]
92 [email protected] 92 [email protected] "1"
93 [email protected] "1" 93 [email protected] ";"
94 [email protected] ";" 94 [email protected] "\n "
95 [email protected] "\n " 95 [email protected]
96 [email protected] 96 [email protected]
97 [email protected] 97 [email protected]
98 [email protected] 98 [email protected] "..="
99 [email protected] "..=" 99 [email protected]
100 [email protected] 100 [email protected]
101 [email protected] 101 [email protected]
102 [email protected] 102 [email protected]
103 [email protected] 103 [email protected] "z"
104 [email protected] "z" 104 [email protected] " "
105 [email protected] " " 105 [email protected] "="
106 [email protected] "=" 106 [email protected] " "
107 [email protected] " " 107 [email protected]
108 [email protected] 108 [email protected] "2"
109 [email protected] "2" 109 [email protected] ";"
110 [email protected] ";" 110 [email protected] "\n "
111 [email protected] "\n " 111 [email protected]
112 [email protected] 112 [email protected]
113 [email protected] 113 [email protected]
114 [email protected] 114 [email protected]
115 [email protected] 115 [email protected]
116 [email protected] 116 [email protected]
117 [email protected] 117 [email protected] "x"
118 [email protected] "x" 118 [email protected] " "
119 [email protected] " " 119 [email protected] "="
120 [email protected] "=" 120 [email protected] " "
121 [email protected] " " 121 [email protected]
122 [email protected] 122 [email protected]
123 [email protected] 123 [email protected] "false"
124 [email protected] "false" 124 [email protected] "..="
125 [email protected] "..=" 125 [email protected]
126 [email protected] 126 [email protected]
127 [email protected] 127 [email protected] "1"
128 [email protected] "1" 128 [email protected] " "
129 [email protected] " " 129 [email protected] "=="
130 [email protected] "==" 130 [email protected] " "
131 [email protected] " " 131 [email protected]
132 [email protected] 132 [email protected] "1"
133 [email protected] "1" 133 [email protected] ";"
134 [email protected] ";" 134 [email protected] "\n "
135 [email protected] "\n " 135 [email protected]
136 [email protected] 136 [email protected] "let"
137 [email protected] "let" 137 [email protected] " "
138 [email protected] " " 138 [email protected]
139 [email protected] 139 [email protected]
140 [email protected] 140 [email protected] "x"
141 [email protected] "x" 141 [email protected] " "
142 [email protected] " " 142 [email protected] "="
143 [email protected] "=" 143 [email protected] " "
144 [email protected] " " 144 [email protected]
145 [email protected] 145 [email protected]
146 [email protected] 146 [email protected] "1"
147 [email protected] "1" 147 [email protected] ".."
148 [email protected] ".." 148 [email protected] ";"
149 [email protected] ";" 149 [email protected] "\n"
150 [email protected] "\n" 150 [email protected] "}"
151 [email protected] "}"
152 [email protected] "\n" 151 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0030_string_suffixes.rast b/crates/ra_syntax/test_data/parser/ok/0030_string_suffixes.rast
index 953930f6c..86c3b46c4 100644
--- a/crates/ra_syntax/test_data/parser/ok/0030_string_suffixes.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0030_string_suffixes.rast
@@ -9,56 +9,55 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] "_"
19 [email protected] "_" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "="
21 [email protected] "=" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "\'c\'u32"
24 [email protected] "\'c\'u32" 24 [email protected] ";"
25 [email protected] ";" 25 [email protected] "\n "
26 [email protected] "\n " 26 [email protected]
27 [email protected] 27 [email protected] "let"
28 [email protected] "let" 28 [email protected] " "
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected] "_"
31 [email protected] "_" 31 [email protected] " "
32 [email protected] " " 32 [email protected] "="
33 [email protected] "=" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected] "\"string\"invalid"
36 [email protected] "\"string\"invalid" 36 [email protected] ";"
37 [email protected] ";" 37 [email protected] "\n "
38 [email protected] "\n " 38 [email protected]
39 [email protected] 39 [email protected] "let"
40 [email protected] "let" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected] "_"
43 [email protected] "_" 43 [email protected] " "
44 [email protected] " " 44 [email protected] "="
45 [email protected] "=" 45 [email protected] " "
46 [email protected] " " 46 [email protected]
47 [email protected] 47 [email protected] "b\'b\'_suff"
48 [email protected] "b\'b\'_suff" 48 [email protected] ";"
49 [email protected] ";" 49 [email protected] "\n "
50 [email protected] "\n " 50 [email protected]
51 [email protected] 51 [email protected] "let"
52 [email protected] "let" 52 [email protected] " "
53 [email protected] " " 53 [email protected]
54 [email protected] 54 [email protected] "_"
55 [email protected] "_" 55 [email protected] " "
56 [email protected] " " 56 [email protected] "="
57 [email protected] "=" 57 [email protected] " "
58 [email protected] " " 58 [email protected]
59 [email protected] 59 [email protected] "b\"bs\"invalid"
60 [email protected] "b\"bs\"invalid" 60 [email protected] ";"
61 [email protected] ";" 61 [email protected] "\n"
62 [email protected] "\n" 62 [email protected] "}"
63 [email protected] "}"
64 [email protected] "\n" 63 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0032_where_for.rast b/crates/ra_syntax/test_data/parser/ok/0032_where_for.rast
index 68eb16bbd..8d76c4e0b 100644
--- a/crates/ra_syntax/test_data/parser/ok/0032_where_for.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0032_where_for.rast
@@ -85,7 +85,6 @@ [email protected]
85 [email protected] "," 85 [email protected] ","
86 [email protected] "\n" 86 [email protected] "\n"
87 [email protected] 87 [email protected]
88 [email protected] 88 [email protected] "{"
89 [email protected] "{" 89 [email protected] "}"
90 [email protected] "}"
91 [email protected] "\n" 90 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0033_label_break.rast b/crates/ra_syntax/test_data/parser/ok/0033_label_break.rast
index 3977faa60..13b730ded 100644
--- a/crates/ra_syntax/test_data/parser/ok/0033_label_break.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0033_label_break.rast
@@ -11,210 +11,205 @@ [email protected]
11 [email protected] ")" 11 [email protected] ")"
12 [email protected] " " 12 [email protected] " "
13 [email protected] 13 [email protected]
14 [email protected] 14 [email protected] "{"
15 [email protected] "{" 15 [email protected] "\n "
16 [email protected] "\n " 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "\'empty_block"
20 [email protected] "\'empty_block" 20 [email protected] ":"
21 [email protected] ":" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] "{" 24 [email protected] "}"
25 [email protected] "}" 25 [email protected] "\n\n "
26 [email protected] "\n\n " 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected]
29 [email protected] 29 [email protected] "\'block"
30 [email protected] "\'block" 30 [email protected] ":"
31 [email protected] ":" 31 [email protected] " "
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected] "{"
34 [email protected] "{" 34 [email protected] "\n "
35 [email protected] "\n " 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "do_thing"
42 [email protected] "do_thing" 42 [email protected]
43 [email protected] 43 [email protected] "("
44 [email protected] "(" 44 [email protected] ")"
45 [email protected] ")" 45 [email protected] ";"
46 [email protected] ";" 46 [email protected] "\n "
47 [email protected] "\n " 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected] "if"
50 [email protected] "if" 50 [email protected] " "
51 [email protected] " " 51 [email protected]
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected] "condition_not_met"
58 [email protected] "condition_not_met" 58 [email protected]
59 [email protected] 59 [email protected] "("
60 [email protected] "(" 60 [email protected] ")"
61 [email protected] ")" 61 [email protected] " "
62 [email protected] " " 62 [email protected]
63 [email protected] 63 [email protected] "{"
64 [email protected] 64 [email protected] "\n "
65 [email protected] "{" 65 [email protected]
66 [email protected] "\n " 66 [email protected]
67 [email protected] 67 [email protected] "break"
68 [email protected] 68 [email protected] " "
69 [email protected] "break" 69 [email protected] "\'block"
70 [email protected] " " 70 [email protected] ";"
71 [email protected] "\'block" 71 [email protected] "\n "
72 [email protected] ";" 72 [email protected] "}"
73 [email protected] "\n " 73 [email protected] "\n "
74 [email protected] "}" 74 [email protected]
75 [email protected] "\n " 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected]
80 [email protected] 80 [email protected] "do_next_thing"
81 [email protected] 81 [email protected]
82 [email protected] "do_next_thing" 82 [email protected] "("
83 [email protected] 83 [email protected] ")"
84 [email protected] "(" 84 [email protected] ";"
85 [email protected] ")" 85 [email protected] "\n "
86 [email protected] ";" 86 [email protected]
87 [email protected] "\n " 87 [email protected]
88 [email protected] 88 [email protected] "if"
89 [email protected] 89 [email protected] " "
90 [email protected] "if" 90 [email protected]
91 [email protected] " " 91 [email protected]
92 [email protected] 92 [email protected]
93 [email protected] 93 [email protected]
94 [email protected] 94 [email protected]
95 [email protected] 95 [email protected]
96 [email protected] 96 [email protected] "condition_not_met"
97 [email protected] 97 [email protected]
98 [email protected] "condition_not_met" 98 [email protected] "("
99 [email protected] 99 [email protected] ")"
100 [email protected] "(" 100 [email protected] " "
101 [email protected] ")" 101 [email protected]
102 [email protected] " " 102 [email protected] "{"
103 [email protected] 103 [email protected] "\n "
104 [email protected] 104 [email protected]
105 [email protected] "{" 105 [email protected]
106 [email protected] "\n " 106 [email protected] "break"
107 [email protected] 107 [email protected] " "
108 [email protected] 108 [email protected] "\'block"
109 [email protected] "break" 109 [email protected] ";"
110 [email protected] " " 110 [email protected] "\n "
111 [email protected] "\'block" 111 [email protected] "}"
112 [email protected] ";" 112 [email protected] "\n "
113 [email protected] "\n " 113 [email protected]
114 [email protected] "}" 114 [email protected]
115 [email protected] "\n " 115 [email protected]
116 [email protected] 116 [email protected]
117 [email protected] 117 [email protected]
118 [email protected] 118 [email protected]
119 [email protected] 119 [email protected] "do_last_thing"
120 [email protected] 120 [email protected]
121 [email protected] 121 [email protected] "("
122 [email protected] "do_last_thing" 122 [email protected] ")"
123 [email protected] 123 [email protected] ";"
124 [email protected] "(" 124 [email protected] "\n "
125 [email protected] ")" 125 [email protected] "}"
126 [email protected] ";" 126 [email protected] "\n\n "
127 [email protected] "\n " 127 [email protected]
128 [email protected] "}" 128 [email protected] "let"
129 [email protected] "\n\n " 129 [email protected] " "
130 [email protected] 130 [email protected]
131 [email protected] "let" 131 [email protected]
132 [email protected] " " 132 [email protected] "result"
133 [email protected] 133 [email protected] " "
134 [email protected] 134 [email protected] "="
135 [email protected] "result" 135 [email protected] " "
136 [email protected] " " 136 [email protected]
137 [email protected] "=" 137 [email protected]
138 [email protected] " " 138 [email protected] "\'block"
139 [email protected] 139 [email protected] ":"
140 [email protected] 140 [email protected] " "
141 [email protected] "\'block" 141 [email protected]
142 [email protected] ":" 142 [email protected] "{"
143 [email protected] " " 143 [email protected] "\n "
144 [email protected] 144 [email protected]
145 [email protected] "{" 145 [email protected]
146 [email protected] "\n " 146 [email protected] "if"
147 [email protected] 147 [email protected] " "
148 [email protected] 148 [email protected]
149 [email protected] "if" 149 [email protected]
150 [email protected] " " 150 [email protected]
151 [email protected] 151 [email protected]
152 [email protected] 152 [email protected]
153 [email protected] 153 [email protected]
154 [email protected] 154 [email protected] "foo"
155 [email protected] 155 [email protected]
156 [email protected] 156 [email protected] "("
157 [email protected] "foo" 157 [email protected] ")"
158 [email protected] 158 [email protected] " "
159 [email protected] "(" 159 [email protected]
160 [email protected] ")" 160 [email protected] "{"
161 [email protected] " " 161 [email protected] "\n "
162 [email protected] 162 [email protected] "// comment"
163 [email protected] 163 [email protected] "\n "
164 [email protected] "{" 164 [email protected]
165 [email protected] "\n " 165 [email protected]
166 [email protected] "// comment" 166 [email protected] "break"
167 [email protected] "\n " 167 [email protected] " "
168 [email protected] 168 [email protected] "\'block"
169 [email protected] 169 [email protected] " "
170 [email protected] "break" 170 [email protected]
171 [email protected] " " 171 [email protected] "1"
172 [email protected] "\'block" 172 [email protected] ";"
173 [email protected] " " 173 [email protected] "\n "
174 [email protected] 174 [email protected] "}"
175 [email protected] "1" 175 [email protected] "\n "
176 [email protected] ";" 176 [email protected]
177 [email protected] "\n " 177 [email protected]
178 [email protected] "}" 178 [email protected] "if"
179 [email protected] "\n " 179 [email protected] " "
180 [email protected] 180 [email protected]
181 [email protected] 181 [email protected]
182 [email protected] "if" 182 [email protected]
183 [email protected] " " 183 [email protected]
184 [email protected] 184 [email protected]
185 [email protected] 185 [email protected]
186 [email protected] 186 [email protected] "bar"
187 [email protected] 187 [email protected]
188 [email protected] 188 [email protected] "("
189 [email protected] 189 [email protected] ")"
190 [email protected] "bar" 190 [email protected] " "
191 [email protected] 191 [email protected]
192 [email protected] "(" 192 [email protected] "{"
193 [email protected] ")" 193 [email protected] "\n "
194 [email protected] " " 194 [email protected] "/* comment */"
195 [email protected] 195 [email protected] "\n "
196 [email protected] 196 [email protected]
197 [email protected] "{" 197 [email protected]
198 [email protected] "\n " 198 [email protected] "break"
199 [email protected] "/* comment */" 199 [email protected] " "
200 [email protected] "\n " 200 [email protected] "\'block"
201 [email protected] 201 [email protected] " "
202 [email protected] 202 [email protected]
203 [email protected] "break" 203 [email protected] "2"
204 [email protected] " " 204 [email protected] ";"
205 [email protected] "\'block" 205 [email protected] "\n "
206 [email protected] " " 206 [email protected] "}"
207 [email protected] 207 [email protected] "\n "
208 [email protected] "2" 208 [email protected]
209 [email protected] ";" 209 [email protected] "3"
210 [email protected] "\n " 210 [email protected] "\n "
211 [email protected] "}" 211 [email protected] "}"
212 [email protected] "\n " 212 [email protected] ";"
213 [email protected] 213 [email protected] "\n"
214 [email protected] "3" 214 [email protected] "}"
215 [email protected] "\n "
216 [email protected] "}"
217 [email protected] ";"
218 [email protected] "\n"
219 [email protected] "}"
220 [email protected] "\n" 215 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0034_crate_path_in_call.rast b/crates/ra_syntax/test_data/parser/ok/0034_crate_path_in_call.rast
index 3b9e8c71c..21874ae3a 100644
--- a/crates/ra_syntax/test_data/parser/ok/0034_crate_path_in_call.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0034_crate_path_in_call.rast
@@ -9,34 +9,33 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "make_query"
21 [email protected] "make_query" 21 [email protected]
22 [email protected] 22 [email protected] "("
23 [email protected] "(" 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected]
27 [email protected] 27 [email protected]
28 [email protected] 28 [email protected] "crate"
29 [email protected] "crate" 29 [email protected] "::"
30 [email protected] "::" 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected] "module_map"
33 [email protected] "module_map" 33 [email protected] "::"
34 [email protected] "::" 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected] "module_tree"
37 [email protected] "module_tree" 37 [email protected] ")"
38 [email protected] ")" 38 [email protected] ";"
39 [email protected] ";" 39 [email protected] "\n"
40 [email protected] "\n" 40 [email protected] "}"
41 [email protected] "}"
42 [email protected] "\n" 41 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast
index 9af689635..eb59d6e17 100644
--- a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.rast
@@ -139,33 +139,32 @@ [email protected]
139 [email protected] "bool" 139 [email protected] "bool"
140 [email protected] " " 140 [email protected] " "
141 [email protected] 141 [email protected]
142 [email protected] 142 [email protected] "{"
143 [email protected] "{" 143 [email protected] " "
144 [email protected] " " 144 [email protected]
145 [email protected] 145 [email protected] "let"
146 [email protected] "let" 146 [email protected] " "
147 [email protected] " " 147 [email protected]
148 [email protected] 148 [email protected]
149 [email protected] 149 [email protected] "_x"
150 [email protected] "_x" 150 [email protected] ":"
151 [email protected] ":" 151 [email protected] " "
152 [email protected] " " 152 [email protected]
153 [email protected] 153 [email protected]
154 [email protected] 154 [email protected]
155 [email protected] 155 [email protected]
156 [email protected] 156 [email protected] "bool"
157 [email protected] "bool" 157 [email protected] " "
158 [email protected] " " 158 [email protected] "="
159 [email protected] "=" 159 [email protected] " "
160 [email protected] " " 160 [email protected]
161 [email protected] 161 [email protected] "return"
162 [email protected] "return" 162 [email protected] " "
163 [email protected] " " 163 [email protected]
164 [email protected] 164 [email protected] "true"
165 [email protected] "true" 165 [email protected] ";"
166 [email protected] ";" 166 [email protected] " "
167 [email protected] " " 167 [email protected] "}"
168 [email protected] "}"
169 [email protected] "\n\n" 168 [email protected] "\n\n"
170 [email protected] 169 [email protected]
171 [email protected] "fn" 170 [email protected] "fn"
@@ -177,48 +176,46 @@ [email protected]
177 [email protected] ")" 176 [email protected] ")"
178 [email protected] " " 177 [email protected] " "
179 [email protected] 178 [email protected]
180 [email protected] 179 [email protected] "{"
181 [email protected] "{" 180 [email protected] "\n "
182 [email protected] "\n " 181 [email protected]
183 [email protected] 182 [email protected] "fn"
184 [email protected] "fn" 183 [email protected] " "
185 [email protected] " " 184 [email protected]
186 [email protected] 185 [email protected] "f"
187 [email protected] "f" 186 [email protected]
188 [email protected] 187 [email protected] "("
189 [email protected] "(" 188 [email protected]
190 [email protected] 189 [email protected]
191 [email protected] 190 [email protected]
192 [email protected] 191 [email protected] "_x"
193 [email protected] "_x" 192 [email protected] ":"
194 [email protected] ":" 193 [email protected] " "
195 [email protected] " " 194 [email protected]
196 [email protected] 195 [email protected] "("
197 [email protected] "(" 196 [email protected] ")"
198 [email protected] ")" 197 [email protected] ")"
199 [email protected] ")" 198 [email protected] " "
200 [email protected] " " 199 [email protected]
201 [email protected] 200 [email protected] "{"
202 [email protected] 201 [email protected] " "
203 [email protected] "{" 202 [email protected] "}"
204 [email protected] " " 203 [email protected] "\n "
205 [email protected] "}" 204 [email protected]
206 [email protected] "\n " 205 [email protected]
207 [email protected] 206 [email protected]
208 [email protected] 207 [email protected]
209 [email protected] 208 [email protected]
210 [email protected] 209 [email protected]
211 [email protected] 210 [email protected] "f"
212 [email protected] 211 [email protected]
213 [email protected] "f" 212 [email protected] "("
214 [email protected] 213 [email protected]
215 [email protected] "(" 214 [email protected] "return"
216 [email protected] 215 [email protected] ")"
217 [email protected] "return" 216 [email protected] ";"
218 [email protected] ")" 217 [email protected] "\n"
219 [email protected] ";" 218 [email protected] "}"
220 [email protected] "\n"
221 [email protected] "}"
222 [email protected] "\n\n" 219 [email protected] "\n\n"
223 [email protected] 220 [email protected]
224 [email protected] "fn" 221 [email protected] "fn"
@@ -230,189 +227,185 @@ [email protected]
230 [email protected] ")" 227 [email protected] ")"
231 [email protected] " " 228 [email protected] " "
232 [email protected] 229 [email protected]
233 [email protected] 230 [email protected] "{"
234 [email protected] "{" 231 [email protected] "\n "
235 [email protected] "\n " 232 [email protected]
236 [email protected] 233 [email protected] "fn"
237 [email protected] "fn" 234 [email protected] " "
238 [email protected] " " 235 [email protected]
239 [email protected] 236 [email protected] "the"
240 [email protected] "the" 237 [email protected]
241 [email protected] 238 [email protected] "("
242 [email protected] "(" 239 [email protected]
243 [email protected] 240 [email protected]
244 [email protected] 241 [email protected]
245 [email protected] 242 [email protected] "x"
246 [email protected] "x" 243 [email protected] ":"
247 [email protected] ":" 244 [email protected] " "
248 [email protected] " " 245 [email protected]
249 [email protected] 246 [email protected] "&"
250 [email protected] "&" 247 [email protected]
251 [email protected] 248 [email protected]
252 [email protected] 249 [email protected]
253 [email protected] 250 [email protected]
254 [email protected] 251 [email protected] "Cell"
255 [email protected] "Cell" 252 [email protected]
256 [email protected] 253 [email protected] "<"
257 [email protected] "<" 254 [email protected]
258 [email protected] 255 [email protected]
259 [email protected] 256 [email protected]
260 [email protected] 257 [email protected]
261 [email protected] 258 [email protected]
262 [email protected] 259 [email protected] "bool"
263 [email protected] "bool" 260 [email protected] ">"
264 [email protected] ">" 261 [email protected] ")"
265 [email protected] ")" 262 [email protected] " "
266 [email protected] " " 263 [email protected]
267 [email protected] 264 [email protected] "{"
268 [email protected] 265 [email protected] "\n "
269 [email protected] "{" 266 [email protected]
270 [email protected] "\n " 267 [email protected]
271 [email protected] 268 [email protected] "return"
272 [email protected] 269 [email protected] " "
273 [email protected] "return" 270 [email protected]
274 [email protected] " " 271 [email protected] "while"
275 [email protected] 272 [email protected] " "
276 [email protected] "while" 273 [email protected]
277 [email protected] " " 274 [email protected]
278 [email protected] 275 [email protected] "!"
279 [email protected] 276 [email protected]
280 [email protected] "!" 277 [email protected]
281 [email protected] 278 [email protected]
282 [email protected] 279 [email protected]
283 [email protected] 280 [email protected]
284 [email protected] 281 [email protected] "x"
285 [email protected] 282 [email protected] "."
286 [email protected] "x" 283 [email protected]
287 [email protected] "." 284 [email protected] "get"
288 [email protected] 285 [email protected]
289 [email protected] "get" 286 [email protected] "("
290 [email protected] 287 [email protected] ")"
291 [email protected] "(" 288 [email protected] " "
292 [email protected] ")" 289 [email protected]
293 [email protected] " " 290 [email protected] "{"
294 [email protected] 291 [email protected] " "
295 [email protected] 292 [email protected]
296 [email protected] "{" 293 [email protected]
297 [email protected] " " 294 [email protected]
298 [email protected] 295 [email protected]
299 [email protected] 296 [email protected]
300 [email protected] 297 [email protected]
301 [email protected] 298 [email protected] "x"
302 [email protected] 299 [email protected] "."
303 [email protected] 300 [email protected]
304 [email protected] "x" 301 [email protected] "set"
305 [email protected] "." 302 [email protected]
306 [email protected] 303 [email protected] "("
307 [email protected] "set" 304 [email protected]
308 [email protected] 305 [email protected] "true"
309 [email protected] "(" 306 [email protected] ")"
310 [email protected] 307 [email protected] ";"
311 [email protected] "true" 308 [email protected] " "
312 [email protected] ")" 309 [email protected] "}"
313 [email protected] ";" 310 [email protected] ";"
314 [email protected] " " 311 [email protected] "\n "
315 [email protected] "}" 312 [email protected] "}"
316 [email protected] ";" 313 [email protected] "\n "
317 [email protected] "\n " 314 [email protected]
318 [email protected] "}" 315 [email protected] "let"
319 [email protected] "\n " 316 [email protected] " "
320 [email protected] 317 [email protected]
321 [email protected] "let" 318 [email protected]
322 [email protected] " " 319 [email protected] "i"
323 [email protected] 320 [email protected] " "
324 [email protected] 321 [email protected] "="
325 [email protected] "i" 322 [email protected] " "
326 [email protected] " " 323 [email protected]
327 [email protected] "=" 324 [email protected] "&"
328 [email protected] " " 325 [email protected]
329 [email protected] 326 [email protected]
330 [email protected] "&" 327 [email protected]
331 [email protected] 328 [email protected]
332 [email protected] 329 [email protected]
333 [email protected] 330 [email protected]
334 [email protected] 331 [email protected] "Cell"
335 [email protected] 332 [email protected] "::"
336 [email protected] 333 [email protected]
337 [email protected] "Cell" 334 [email protected]
338 [email protected] "::" 335 [email protected] "new"
339 [email protected] 336 [email protected]
340 [email protected] 337 [email protected] "("
341 [email protected] "new" 338 [email protected]
342 [email protected] 339 [email protected] "false"
343 [email protected] "(" 340 [email protected] ")"
344 [email protected] 341 [email protected] ";"
345 [email protected] "false" 342 [email protected] "\n "
346 [email protected] ")" 343 [email protected]
347 [email protected] ";" 344 [email protected] "let"
348 [email protected] "\n " 345 [email protected] " "
349 [email protected] 346 [email protected]
350 [email protected] "let" 347 [email protected]
351 [email protected] " " 348 [email protected] "dont"
352 [email protected] 349 [email protected] " "
353 [email protected] 350 [email protected] "="
354 [email protected] "dont" 351 [email protected] " "
355 [email protected] " " 352 [email protected]
356 [email protected] "=" 353 [email protected] "{"
357 [email protected] " " 354 [email protected]
358 [email protected] 355 [email protected]
359 [email protected] 356 [email protected] "|"
360 [email protected] "{" 357 [email protected] "|"
361 [email protected] 358 [email protected]
362 [email protected] 359 [email protected]
363 [email protected] "|" 360 [email protected]
364 [email protected] "|" 361 [email protected]
365 [email protected] 362 [email protected]
366 [email protected] 363 [email protected] "the"
367 [email protected] 364 [email protected]
368 [email protected] 365 [email protected] "("
369 [email protected] 366 [email protected]
370 [email protected] "the" 367 [email protected]
371 [email protected] 368 [email protected]
372 [email protected] "(" 369 [email protected]
373 [email protected] 370 [email protected] "i"
374 [email protected] 371 [email protected] ")"
375 [email protected] 372 [email protected] "}"
376 [email protected] 373 [email protected] ";"
377 [email protected] "i" 374 [email protected] "\n "
378 [email protected] ")" 375 [email protected]
379 [email protected] "}" 376 [email protected]
380 [email protected] ";" 377 [email protected]
381 [email protected] "\n " 378 [email protected]
382 [email protected] 379 [email protected]
383 [email protected] 380 [email protected]
384 [email protected] 381 [email protected] "dont"
385 [email protected] 382 [email protected]
386 [email protected] 383 [email protected] "("
387 [email protected] 384 [email protected] ")"
388 [email protected] "dont" 385 [email protected] ";"
389 [email protected] 386 [email protected] "\n "
390 [email protected] "(" 387 [email protected]
391 [email protected] ")" 388 [email protected]
392 [email protected] ";" 389 [email protected]
393 [email protected] "\n " 390 [email protected]
394 [email protected] 391 [email protected]
395 [email protected] 392 [email protected] "assert"
396 [email protected] 393 [email protected] "!"
397 [email protected] 394 [email protected]
398 [email protected] 395 [email protected] "("
399 [email protected] "assert" 396 [email protected]
400 [email protected] "!" 397 [email protected] "("
401 [email protected] 398 [email protected] "i"
402 [email protected] "(" 399 [email protected] "."
403 [email protected] 400 [email protected] "get"
404 [email protected] "(" 401 [email protected]
405 [email protected] "i" 402 [email protected] "("
406 [email protected] "." 403 [email protected] ")"
407 [email protected] "get" 404 [email protected] ")"
408 [email protected] 405 [email protected] ")"
409 [email protected] "(" 406 [email protected] ";"
410 [email protected] ")" 407 [email protected] "\n"
411 [email protected] ")" 408 [email protected] "}"
412 [email protected] ")"
413 [email protected] ";"
414 [email protected] "\n"
415 [email protected] "}"
416 [email protected] "\n\n" 409 [email protected] "\n\n"
417 [email protected] 410 [email protected]
418 [email protected] "fn" 411 [email protected] "fn"
@@ -424,170 +417,160 @@ [email protected]
424 [email protected] ")" 417 [email protected] ")"
425 [email protected] " " 418 [email protected] " "
426 [email protected] 419 [email protected]
427 [email protected] 420 [email protected] "{"
428 [email protected] "{" 421 [email protected] "\n "
429 [email protected] "\n " 422 [email protected]
430 [email protected] 423 [email protected] "loop"
431 [email protected] "loop" 424 [email protected] " "
432 [email protected] " " 425 [email protected]
433 [email protected] 426 [email protected] "{"
434 [email protected] 427 [email protected] "\n "
435 [email protected] "{" 428 [email protected]
436 [email protected] "\n " 429 [email protected]
437 [email protected] 430 [email protected] "while"
438 [email protected] 431 [email protected] " "
439 [email protected] "while" 432 [email protected]
440 [email protected] " " 433 [email protected]
441 [email protected] 434 [email protected] "("
442 [email protected] 435 [email protected]
443 [email protected] "(" 436 [email protected] "return"
444 [email protected] 437 [email protected] ")"
445 [email protected] "return" 438 [email protected] " "
446 [email protected] ")" 439 [email protected]
447 [email protected] " " 440 [email protected] "{"
448 [email protected] 441 [email protected] "\n "
449 [email protected] 442 [email protected]
450 [email protected] "{" 443 [email protected] "if"
451 [email protected] "\n " 444 [email protected] " "
452 [email protected] 445 [email protected]
453 [email protected] "if" 446 [email protected]
454 [email protected] " " 447 [email protected] "("
455 [email protected] 448 [email protected]
456 [email protected] 449 [email protected] "return"
457 [email protected] "(" 450 [email protected] ")"
458 [email protected] 451 [email protected] " "
459 [email protected] "return" 452 [email protected]
460 [email protected] ")" 453 [email protected] "{"
461 [email protected] " " 454 [email protected] "\n "
462 [email protected] 455 [email protected]
463 [email protected] 456 [email protected]
464 [email protected] "{" 457 [email protected] "match"
465 [email protected] "\n " 458 [email protected] " "
466 [email protected] 459 [email protected]
467 [email protected] 460 [email protected] "("
468 [email protected] "match" 461 [email protected]
469 [email protected] " " 462 [email protected] "return"
470 [email protected] 463 [email protected] ")"
471 [email protected] "(" 464 [email protected] " "
472 [email protected] 465 [email protected]
473 [email protected] "return" 466 [email protected] "{"
474 [email protected] ")" 467 [email protected] "\n "
475 [email protected] " " 468 [email protected]
476 [email protected] 469 [email protected]
477 [email protected] "{" 470 [email protected]
478 [email protected] "\n " 471 [email protected] "1"
479 [email protected] 472 [email protected] " "
480 [email protected] 473 [email protected] "=>"
481 [email protected] 474 [email protected] " "
482 [email protected] "1" 475 [email protected]
483 [email protected] " " 476 [email protected] "{"
484 [email protected] "=>" 477 [email protected] "\n ..."
485 [email protected] " " 478 [email protected]
486 [email protected] 479 [email protected] "if"
487 [email protected] 480 [email protected] " "
488 [email protected] "{" 481 [email protected]
489 [email protected] "\n ..." 482 [email protected]
490 [email protected] 483 [email protected] "("
491 [email protected] "if" 484 [email protected]
492 [email protected] " " 485 [email protected] "return"
493 [email protected] 486 [email protected] ")"
494 [email protected] 487 [email protected] " "
495 [email protected] "(" 488 [email protected]
496 [email protected] 489 [email protected] "{"
497 [email protected] "return" 490 [email protected] "\n ..."
498 [email protected] ")" 491 [email protected]
499 [email protected] " " 492 [email protected] "return"
500 [email protected] 493 [email protected] "\n ..."
501 [email protected] 494 [email protected] "}"
502 [email protected] "{" 495 [email protected] " "
503 [email protected] "\n ..." 496 [email protected] "else"
504 [email protected] 497 [email protected] " "
505 [email protected] "return" 498 [email protected]
506 [email protected] "\n ..." 499 [email protected] "{"
507 [email protected] "}" 500 [email protected] "\n ..."
508 [email protected] " " 501 [email protected]
509 [email protected] "else" 502 [email protected] "return"
510 [email protected] " " 503 [email protected] "\n ..."
511 [email protected] 504 [email protected] "}"
512 [email protected] 505 [email protected] "\n "
513 [email protected] "{" 506 [email protected] "}"
514 [email protected] "\n ..." 507 [email protected] "\n "
515 [email protected] 508 [email protected]
516 [email protected] "return" 509 [email protected]
517 [email protected] "\n ..." 510 [email protected] "_"
518 [email protected] "}" 511 [email protected] " "
519 [email protected] "\n " 512 [email protected] "=>"
520 [email protected] "}" 513 [email protected] " "
521 [email protected] "\n " 514 [email protected]
522 [email protected] 515 [email protected] "{"
523 [email protected] 516 [email protected] " "
524 [email protected] "_" 517 [email protected]
525 [email protected] " " 518 [email protected] "return"
526 [email protected] "=>" 519 [email protected] " "
527 [email protected] " " 520 [email protected] "}"
528 [email protected] 521 [email protected] "\n "
529 [email protected] 522 [email protected] "}"
530 [email protected] "{" 523 [email protected] ";"
531 [email protected] " " 524 [email protected] "\n "
532 [email protected] 525 [email protected] "}"
533 [email protected] "return" 526 [email protected] " "
534 [email protected] " " 527 [email protected] "else"
535 [email protected] "}" 528 [email protected] " "
536 [email protected] "\n " 529 [email protected]
537 [email protected] "}" 530 [email protected] "if"
538 [email protected] ";" 531 [email protected] " "
539 [email protected] "\n " 532 [email protected]
540 [email protected] "}" 533 [email protected]
541 [email protected] " " 534 [email protected] "("
542 [email protected] "else" 535 [email protected]
543 [email protected] " " 536 [email protected] "return"
544 [email protected] 537 [email protected] ")"
545 [email protected] "if" 538 [email protected] " "
546 [email protected] " " 539 [email protected]
547 [email protected] 540 [email protected] "{"
548 [email protected] 541 [email protected] "\n "
549 [email protected] "(" 542 [email protected]
550 [email protected] 543 [email protected]
551 [email protected] "return" 544 [email protected] "return"
552 [email protected] ")" 545 [email protected] ";"
553 [email protected] " " 546 [email protected] "\n "
554 [email protected] 547 [email protected] "}"
555 [email protected] 548 [email protected] "\n "
556 [email protected] "{" 549 [email protected] "}"
557 [email protected] "\n " 550 [email protected] "\n "
558 [email protected] 551 [email protected]
559 [email protected] 552 [email protected] "if"
560 [email protected] "return" 553 [email protected] " "
561 [email protected] ";" 554 [email protected]
562 [email protected] "\n " 555 [email protected]
563 [email protected] "}" 556 [email protected] "("
564 [email protected] "\n " 557 [email protected]
565 [email protected] "}" 558 [email protected] "return"
566 [email protected] "\n " 559 [email protected] ")"
567 [email protected] 560 [email protected] " "
568 [email protected] "if" 561 [email protected]
569 [email protected] " " 562 [email protected] "{"
570 [email protected] 563 [email protected] " "
571 [email protected] 564 [email protected]
572 [email protected] "(" 565 [email protected]
573 [email protected] 566 [email protected] "break"
574 [email protected] "return" 567 [email protected] ";"
575 [email protected] ")" 568 [email protected] " "
576 [email protected] " " 569 [email protected] "}"
577 [email protected] 570 [email protected] "\n "
578 [email protected] 571 [email protected] "}"
579 [email protected] "{" 572 [email protected] "\n"
580 [email protected] " " 573 [email protected] "}"
581 [email protected]
582 [email protected]
583 [email protected] "break"
584 [email protected] ";"
585 [email protected] " "
586 [email protected] "}"
587 [email protected] "\n "
588 [email protected] "}"
589 [email protected] "\n"
590 [email protected] "}"
591 [email protected] "\n\n" 574 [email protected] "\n\n"
592 [email protected] 575 [email protected]
593 [email protected] "fn" 576 [email protected] "fn"
@@ -599,233 +582,232 @@ [email protected]
599 [email protected] ")" 582 [email protected] ")"
600 [email protected] " " 583 [email protected] " "
601 [email protected] 584 [email protected]
602 [email protected] 585 [email protected] "{"
603 [email protected] "{" 586 [email protected] "\n "
604 [email protected] "\n " 587 [email protected]
605 [email protected] 588 [email protected] "let"
606 [email protected] "let" 589 [email protected] " "
607 [email protected] " " 590 [email protected]
608 [email protected] 591 [email protected] "mut"
609 [email protected] "mut" 592 [email protected] " "
610 [email protected] " " 593 [email protected]
611 [email protected] 594 [email protected] "_x"
612 [email protected] "_x" 595 [email protected] ":"
613 [email protected] ":" 596 [email protected] " "
614 [email protected] " " 597 [email protected]
615 [email protected] 598 [email protected]
616 [email protected] 599 [email protected]
617 [email protected] 600 [email protected]
618 [email protected] 601 [email protected] "isize"
619 [email protected] "isize" 602 [email protected] ";"
620 [email protected] ";" 603 [email protected] "\n "
621 [email protected] "\n " 604 [email protected]
622 [email protected] 605 [email protected] "let"
623 [email protected] "let" 606 [email protected] " "
624 [email protected] " " 607 [email protected]
625 [email protected] 608 [email protected] "mut"
626 [email protected] "mut" 609 [email protected] " "
627 [email protected] " " 610 [email protected]
628 [email protected] 611 [email protected] "_y"
629 [email protected] "_y" 612 [email protected] " "
630 [email protected] " " 613 [email protected] "="
631 [email protected] "=" 614 [email protected] " "
632 [email protected] " " 615 [email protected]
633 [email protected] 616 [email protected]
634 [email protected] 617 [email protected] "("
635 [email protected] "(" 618 [email protected]
636 [email protected] 619 [email protected]
637 [email protected] 620 [email protected]
638 [email protected] 621 [email protected]
639 [email protected] 622 [email protected]
640 [email protected] 623 [email protected] "_x"
641 [email protected] "_x" 624 [email protected] " "
642 [email protected] " " 625 [email protected] "="
643 [email protected] "=" 626 [email protected] " "
644 [email protected] " " 627 [email protected]
645 [email protected] 628 [email protected] "0"
646 [email protected] "0" 629 [email protected] ")"
647 [email protected] ")" 630 [email protected] " "
648 [email protected] " " 631 [email protected] "=="
649 [email protected] "==" 632 [email protected] " "
650 [email protected] " " 633 [email protected]
651 [email protected] 634 [email protected] "("
652 [email protected] "(" 635 [email protected]
653 [email protected] 636 [email protected]
654 [email protected] 637 [email protected]
655 [email protected] 638 [email protected]
656 [email protected] 639 [email protected]
657 [email protected] 640 [email protected] "_x"
658 [email protected] "_x" 641 [email protected] " "
659 [email protected] " " 642 [email protected] "="
660 [email protected] "=" 643 [email protected] " "
661 [email protected] " " 644 [email protected]
662 [email protected] 645 [email protected] "0"
663 [email protected] "0" 646 [email protected] ")"
664 [email protected] ")" 647 [email protected] ";"
665 [email protected] ";" 648 [email protected] "\n "
666 [email protected] "\n " 649 [email protected]
667 [email protected] 650 [email protected] "let"
668 [email protected] "let" 651 [email protected] " "
669 [email protected] " " 652 [email protected]
670 [email protected] 653 [email protected] "mut"
671 [email protected] "mut" 654 [email protected] " "
672 [email protected] " " 655 [email protected]
673 [email protected] 656 [email protected] "_z"
674 [email protected] "_z" 657 [email protected] " "
675 [email protected] " " 658 [email protected] "="
676 [email protected] "=" 659 [email protected] " "
677 [email protected] " " 660 [email protected]
678 [email protected] 661 [email protected]
679 [email protected] 662 [email protected] "("
680 [email protected] "(" 663 [email protected]
681 [email protected] 664 [email protected]
682 [email protected] 665 [email protected]
683 [email protected] 666 [email protected]
684 [email protected] 667 [email protected]
685 [email protected] 668 [email protected] "_x"
686 [email protected] "_x" 669 [email protected] " "
687 [email protected] " " 670 [email protected] "="
688 [email protected] "=" 671 [email protected] " "
689 [email protected] " " 672 [email protected]
690 [email protected] 673 [email protected] "0"
691 [email protected] "0" 674 [email protected] ")"
692 [email protected] ")" 675 [email protected] " "
693 [email protected] " " 676 [email protected] "<"
694 [email protected] "<" 677 [email protected] " "
695 [email protected] " " 678 [email protected]
696 [email protected] 679 [email protected] "("
697 [email protected] "(" 680 [email protected]
698 [email protected] 681 [email protected]
699 [email protected] 682 [email protected]
700 [email protected] 683 [email protected]
701 [email protected] 684 [email protected]
702 [email protected] 685 [email protected] "_x"
703 [email protected] "_x" 686 [email protected] " "
704 [email protected] " " 687 [email protected] "="
705 [email protected] "=" 688 [email protected] " "
706 [email protected] " " 689 [email protected]
707 [email protected] 690 [email protected] "0"
708 [email protected] "0" 691 [email protected] ")"
709 [email protected] ")" 692 [email protected] ";"
710 [email protected] ";" 693 [email protected] "\n "
711 [email protected] "\n " 694 [email protected]
712 [email protected] 695 [email protected] "let"
713 [email protected] "let" 696 [email protected] " "
714 [email protected] " " 697 [email protected]
715 [email protected] 698 [email protected]
716 [email protected] 699 [email protected] "_a"
717 [email protected] "_a" 700 [email protected] " "
718 [email protected] " " 701 [email protected] "="
719 [email protected] "=" 702 [email protected] " "
720 [email protected] " " 703 [email protected]
721 [email protected] 704 [email protected]
722 [email protected] 705 [email protected] "("
723 [email protected] "(" 706 [email protected]
724 [email protected] 707 [email protected]
725 [email protected] 708 [email protected]
726 [email protected] 709 [email protected]
727 [email protected] 710 [email protected]
728 [email protected] 711 [email protected] "_x"
729 [email protected] "_x" 712 [email protected] " "
730 [email protected] " " 713 [email protected] "+="
731 [email protected] "+=" 714 [email protected] " "
732 [email protected] " " 715 [email protected]
733 [email protected] 716 [email protected] "0"
734 [email protected] "0" 717 [email protected] ")"
735 [email protected] ")" 718 [email protected] " "
736 [email protected] " " 719 [email protected] "=="
737 [email protected] "==" 720 [email protected] " "
738 [email protected] " " 721 [email protected]
739 [email protected] 722 [email protected] "("
740 [email protected] "(" 723 [email protected]
741 [email protected] 724 [email protected]
742 [email protected] 725 [email protected]
743 [email protected] 726 [email protected]
744 [email protected] 727 [email protected]
745 [email protected] 728 [email protected] "_x"
746 [email protected] "_x" 729 [email protected] " "
747 [email protected] " " 730 [email protected] "="
748 [email protected] "=" 731 [email protected] " "
749 [email protected] " " 732 [email protected]
750 [email protected] 733 [email protected] "0"
751 [email protected] "0" 734 [email protected] ")"
752 [email protected] ")" 735 [email protected] ";"
753 [email protected] ";" 736 [email protected] "\n "
754 [email protected] "\n " 737 [email protected]
755 [email protected] 738 [email protected] "let"
756 [email protected] "let" 739 [email protected] " "
757 [email protected] " " 740 [email protected]
758 [email protected] 741 [email protected]
759 [email protected] 742 [email protected] "_b"
760 [email protected] "_b" 743 [email protected] " "
761 [email protected] " " 744 [email protected] "="
762 [email protected] "=" 745 [email protected] " "
763 [email protected] " " 746 [email protected]
764 [email protected] 747 [email protected]
765 [email protected] 748 [email protected]
766 [email protected] 749 [email protected]
767 [email protected] 750 [email protected]
768 [email protected] 751 [email protected]
769 [email protected] 752 [email protected] "swap"
770 [email protected] "swap" 753 [email protected]
771 [email protected] 754 [email protected] "("
772 [email protected] "(" 755 [email protected]
773 [email protected] 756 [email protected] "&"
774 [email protected] "&" 757 [email protected] "mut"
775 [email protected] "mut" 758 [email protected] " "
776 [email protected] " " 759 [email protected]
777 [email protected] 760 [email protected]
778 [email protected] 761 [email protected]
779 [email protected] 762 [email protected]
780 [email protected] 763 [email protected] "_y"
781 [email protected] "_y" 764 [email protected] ","
782 [email protected] "," 765 [email protected] " "
783 [email protected] " " 766 [email protected]
784 [email protected] 767 [email protected] "&"
785 [email protected] "&" 768 [email protected] "mut"
786 [email protected] "mut" 769 [email protected] " "
787 [email protected] " " 770 [email protected]
788 [email protected] 771 [email protected]
789 [email protected] 772 [email protected]
790 [email protected] 773 [email protected]
791 [email protected] 774 [email protected] "_z"
792 [email protected] "_z" 775 [email protected] ")"
793 [email protected] ")" 776 [email protected] " "
794 [email protected] " " 777 [email protected] "=="
795 [email protected] "==" 778 [email protected] " "
796 [email protected] " " 779 [email protected]
797 [email protected] 780 [email protected]
798 [email protected] 781 [email protected]
799 [email protected] 782 [email protected]
800 [email protected] 783 [email protected]
801 [email protected] 784 [email protected] "swap"
802 [email protected] "swap" 785 [email protected]
803 [email protected] 786 [email protected] "("
804 [email protected] "(" 787 [email protected]
805 [email protected] 788 [email protected] "&"
806 [email protected] "&" 789 [email protected] "mut"
807 [email protected] "mut" 790 [email protected] " "
808 [email protected] " " 791 [email protected]
809 [email protected] 792 [email protected]
810 [email protected] 793 [email protected]
811 [email protected] 794 [email protected]
812 [email protected] 795 [email protected] "_y"
813 [email protected] "_y" 796 [email protected] ","
814 [email protected] "," 797 [email protected] " "
815 [email protected] " " 798 [email protected]
816 [email protected] 799 [email protected] "&"
817 [email protected] "&" 800 [email protected] "mut"
818 [email protected] "mut" 801 [email protected] " "
819 [email protected] " " 802 [email protected]
820 [email protected] 803 [email protected]
821 [email protected] 804 [email protected]
822 [email protected] 805 [email protected]
823 [email protected] 806 [email protected] "_z"
824 [email protected] "_z" 807 [email protected] ")"
825 [email protected] ")" 808 [email protected] ";"
826 [email protected] ";" 809 [email protected] "\n"
827 [email protected] "\n" 810 [email protected] "}"
828 [email protected] "}"
829 [email protected] "\n\n" 811 [email protected] "\n\n"
830 [email protected] 812 [email protected]
831 [email protected] "fn" 813 [email protected] "fn"
@@ -846,167 +828,165 @@ [email protected]
846 [email protected] "usize" 828 [email protected] "usize"
847 [email protected] " " 829 [email protected] " "
848 [email protected] 830 [email protected]
849 [email protected] 831 [email protected] "{"
850 [email protected] "{" 832 [email protected] "\n "
851 [email protected] "\n " 833 [email protected]
852 [email protected] 834 [email protected] "fn"
853 [email protected] "fn" 835 [email protected] " "
854 [email protected] " " 836 [email protected]
855 [email protected] 837 [email protected] "p"
856 [email protected] "p" 838 [email protected]
857 [email protected] 839 [email protected] "("
858 [email protected] "(" 840 [email protected] ")"
859 [email protected] ")" 841 [email protected] " "
860 [email protected] " " 842 [email protected]
861 [email protected] 843 [email protected] "->"
862 [email protected] "->" 844 [email protected] " "
863 [email protected] " " 845 [email protected]
864 [email protected] 846 [email protected]
865 [email protected] 847 [email protected]
866 [email protected] 848 [email protected]
867 [email protected] 849 [email protected] "bool"
868 [email protected] "bool" 850 [email protected] " "
869 [email protected] " " 851 [email protected]
870 [email protected] 852 [email protected] "{"
871 [email protected] 853 [email protected] " "
872 [email protected] "{" 854 [email protected]
873 [email protected] " " 855 [email protected] "true"
874 [email protected] 856 [email protected] " "
875 [email protected] "true" 857 [email protected] "}"
876 [email protected] " " 858 [email protected] "\n "
877 [email protected] "}" 859 [email protected]
878 [email protected] "\n " 860 [email protected] "let"
879 [email protected] 861 [email protected] " "
880 [email protected] "let" 862 [email protected]
881 [email protected] " " 863 [email protected]
882 [email protected] 864 [email protected] "_a"
883 [email protected] 865 [email protected] " "
884 [email protected] "_a" 866 [email protected] "="
885 [email protected] " " 867 [email protected] " "
886 [email protected] "=" 868 [email protected]
887 [email protected] " " 869 [email protected] "("
888 [email protected] 870 [email protected]
889 [email protected] "(" 871 [email protected]
890 [email protected] 872 [email protected]
891 [email protected] 873 [email protected]
892 [email protected] 874 [email protected]
893 [email protected] 875 [email protected] "assert"
894 [email protected] 876 [email protected] "!"
895 [email protected] "assert" 877 [email protected]
896 [email protected] "!" 878 [email protected] "("
897 [email protected] 879 [email protected]
898 [email protected] "(" 880 [email protected] "("
899 [email protected] 881 [email protected] "true"
900 [email protected] "(" 882 [email protected] ")"
901 [email protected] "true" 883 [email protected] ")"
902 [email protected] ")" 884 [email protected] " "
903 [email protected] ")" 885 [email protected] "=="
904 [email protected] " " 886 [email protected] " "
905 [email protected] "==" 887 [email protected]
906 [email protected] " " 888 [email protected] "("
907 [email protected] 889 [email protected]
908 [email protected] "(" 890 [email protected]
909 [email protected] 891 [email protected]
910 [email protected] 892 [email protected]
911 [email protected] 893 [email protected] "assert"
912 [email protected] 894 [email protected] "!"
913 [email protected] "assert" 895 [email protected]
914 [email protected] "!" 896 [email protected] "("
915 [email protected] 897 [email protected] "p"
916 [email protected] "(" 898 [email protected]
917 [email protected] "p" 899 [email protected] "("
918 [email protected] 900 [email protected] ")"
919 [email protected] "(" 901 [email protected] ")"
920 [email protected] ")" 902 [email protected] ")"
921 [email protected] ")" 903 [email protected] ")"
922 [email protected] ")" 904 [email protected] ";"
923 [email protected] ")" 905 [email protected] "\n "
924 [email protected] ";" 906 [email protected]
925 [email protected] "\n " 907 [email protected] "let"
926 [email protected] 908 [email protected] " "
927 [email protected] "let" 909 [email protected]
928 [email protected] " " 910 [email protected]
929 [email protected] 911 [email protected] "_c"
930 [email protected] 912 [email protected] " "
931 [email protected] "_c" 913 [email protected] "="
932 [email protected] " " 914 [email protected] " "
933 [email protected] "=" 915 [email protected]
934 [email protected] " " 916 [email protected] "("
935 [email protected] 917 [email protected]
936 [email protected] "(" 918 [email protected]
937 [email protected] 919 [email protected]
938 [email protected] 920 [email protected]
939 [email protected] 921 [email protected]
940 [email protected] 922 [email protected] "assert"
941 [email protected] 923 [email protected] "!"
942 [email protected] "assert" 924 [email protected]
943 [email protected] "!" 925 [email protected] "("
944 [email protected] 926 [email protected]
945 [email protected] "(" 927 [email protected] "("
946 [email protected] 928 [email protected] "p"
947 [email protected] "(" 929 [email protected]
948 [email protected] "p" 930 [email protected] "("
949 [email protected] 931 [email protected] ")"
950 [email protected] "(" 932 [email protected] ")"
951 [email protected] ")" 933 [email protected] ")"
952 [email protected] ")" 934 [email protected] " "
953 [email protected] ")" 935 [email protected] "=="
954 [email protected] " " 936 [email protected] " "
955 [email protected] "==" 937 [email protected]
956 [email protected] " " 938 [email protected] "("
957 [email protected] 939 [email protected] ")"
958 [email protected] "(" 940 [email protected] ")"
959 [email protected] ")" 941 [email protected] ";"
960 [email protected] ")" 942 [email protected] "\n "
961 [email protected] ";" 943 [email protected]
962 [email protected] "\n " 944 [email protected] "let"
963 [email protected] 945 [email protected] " "
964 [email protected] "let" 946 [email protected]
965 [email protected] " " 947 [email protected]
966 [email protected] 948 [email protected] "_b"
967 [email protected] 949 [email protected] ":"
968 [email protected] "_b" 950 [email protected] " "
969 [email protected] ":" 951 [email protected]
970 [email protected] " " 952 [email protected]
971 [email protected] 953 [email protected]
972 [email protected] 954 [email protected]
973 [email protected] 955 [email protected] "bool"
974 [email protected] 956 [email protected] " "
975 [email protected] "bool" 957 [email protected] "="
976 [email protected] " " 958 [email protected] " "
977 [email protected] "=" 959 [email protected]
978 [email protected] " " 960 [email protected] "("
979 [email protected] 961 [email protected]
980 [email protected] "(" 962 [email protected]
981 [email protected] 963 [email protected]
982 [email protected] 964 [email protected]
983 [email protected] 965 [email protected]
984 [email protected] 966 [email protected] "println"
985 [email protected] 967 [email protected] "!"
986 [email protected] "println" 968 [email protected]
987 [email protected] "!" 969 [email protected] "("
988 [email protected] 970 [email protected] "\"{}\""
989 [email protected] "(" 971 [email protected] ","
990 [email protected] "\"{}\"" 972 [email protected] " "
991 [email protected] "," 973 [email protected] "0"
992 [email protected] " " 974 [email protected] ")"
993 [email protected] "0" 975 [email protected] " "
994 [email protected] ")" 976 [email protected] "=="
995 [email protected] " " 977 [email protected] " "
996 [email protected] "==" 978 [email protected]
997 [email protected] " " 979 [email protected] "("
998 [email protected] 980 [email protected]
999 [email protected] "(" 981 [email protected] "return"
1000 [email protected] 982 [email protected] " "
1001 [email protected] "return" 983 [email protected]
1002 [email protected] " " 984 [email protected] "0"
1003 [email protected] 985 [email protected] ")"
1004 [email protected] "0" 986 [email protected] ")"
1005 [email protected] ")" 987 [email protected] ";"
1006 [email protected] ")" 988 [email protected] "\n"
1007 [email protected] ";" 989 [email protected] "}"
1008 [email protected] "\n"
1009 [email protected] "}"
1010 [email protected] "\n\n" 990 [email protected] "\n\n"
1011 [email protected] 991 [email protected]
1012 [email protected] "fn" 992 [email protected] "fn"
@@ -1018,144 +998,138 @@ [email protected]
1018 [email protected] ")" 998 [email protected] ")"
1019 [email protected] " " 999 [email protected] " "
1020 [email protected] 1000 [email protected]
1021 [email protected] 1001 [email protected] "{"
1022 [email protected] "{" 1002 [email protected] "\n "
1023 [email protected] "\n " 1003 [email protected]
1024 [email protected] 1004 [email protected]
1025 [email protected] 1005 [email protected] "loop"
1026 [email protected] "loop" 1006 [email protected] " "
1027 [email protected] " " 1007 [email protected]
1028 [email protected] 1008 [email protected] "{"
1029 [email protected] 1009 [email protected] " "
1030 [email protected] "{" 1010 [email protected]
1031 [email protected] " " 1011 [email protected] "if"
1032 [email protected] 1012 [email protected] " "
1033 [email protected] "if" 1013 [email protected]
1034 [email protected] " " 1014 [email protected]
1035 [email protected] 1015 [email protected] "break"
1036 [email protected] 1016 [email protected] " "
1037 [email protected] "break" 1017 [email protected]
1038 [email protected] " " 1018 [email protected] "{"
1039 [email protected] 1019 [email protected] " "
1040 [email protected] 1020 [email protected] "}"
1041 [email protected] "{" 1021 [email protected] " "
1042 [email protected] " " 1022 [email protected] "}"
1043 [email protected] "}" 1023 [email protected] "\n "
1044 [email protected] " " 1024 [email protected]
1045 [email protected] "}" 1025 [email protected] "let"
1046 [email protected] "\n " 1026 [email protected] " "
1047 [email protected] 1027 [email protected]
1048 [email protected] "let" 1028 [email protected] "mut"
1049 [email protected] " " 1029 [email protected] " "
1050 [email protected] 1030 [email protected]
1051 [email protected] "mut" 1031 [email protected] "i"
1052 [email protected] " " 1032 [email protected] " "
1053 [email protected] 1033 [email protected] "="
1054 [email protected] "i" 1034 [email protected] " "
1055 [email protected] " " 1035 [email protected]
1056 [email protected] "=" 1036 [email protected] "0"
1057 [email protected] " " 1037 [email protected] ";"
1058 [email protected] 1038 [email protected] "\n "
1059 [email protected] "0" 1039 [email protected]
1060 [email protected] ";" 1040 [email protected] "loop"
1061 [email protected] "\n " 1041 [email protected] " "
1062 [email protected] 1042 [email protected]
1063 [email protected] "loop" 1043 [email protected] "{"
1064 [email protected] " " 1044 [email protected] " "
1065 [email protected] 1045 [email protected]
1066 [email protected] 1046 [email protected]
1067 [email protected] "{" 1047 [email protected]
1068 [email protected] " " 1048 [email protected]
1069 [email protected] 1049 [email protected]
1070 [email protected] 1050 [email protected]
1071 [email protected] 1051 [email protected] "i"
1072 [email protected] 1052 [email protected] " "
1073 [email protected] 1053 [email protected] "+="
1074 [email protected] 1054 [email protected] " "
1075 [email protected] "i" 1055 [email protected]
1076 [email protected] " " 1056 [email protected] "1"
1077 [email protected] "+=" 1057 [email protected] ";"
1078 [email protected] " " 1058 [email protected] " "
1079 [email protected] 1059 [email protected]
1080 [email protected] "1" 1060 [email protected]
1081 [email protected] ";" 1061 [email protected] "if"
1082 [email protected] " " 1062 [email protected] " "
1083 [email protected] 1063 [email protected]
1084 [email protected] 1064 [email protected]
1085 [email protected] "if" 1065 [email protected]
1086 [email protected] " " 1066 [email protected]
1087 [email protected] 1067 [email protected]
1088 [email protected] 1068 [email protected]
1089 [email protected] 1069 [email protected] "i"
1090 [email protected] 1070 [email protected] " "
1091 [email protected] 1071 [email protected] "=="
1092 [email protected] 1072 [email protected] " "
1093 [email protected] "i" 1073 [email protected]
1094 [email protected] " " 1074 [email protected] "1"
1095 [email protected] "==" 1075 [email protected] " "
1096 [email protected] " " 1076 [email protected]
1097 [email protected] 1077 [email protected] "{"
1098 [email protected] "1" 1078 [email protected] " "
1099 [email protected] " " 1079 [email protected]
1100 [email protected] 1080 [email protected] "match"
1101 [email protected] 1081 [email protected] " "
1102 [email protected] "{" 1082 [email protected]
1103 [email protected] " " 1083 [email protected] "("
1104 [email protected] 1084 [email protected]
1105 [email protected] "match" 1085 [email protected] "continue"
1106 [email protected] " " 1086 [email protected] ")"
1107 [email protected] 1087 [email protected] " "
1108 [email protected] "(" 1088 [email protected]
1109 [email protected] 1089 [email protected] "{"
1110 [email protected] "continue" 1090 [email protected] " "
1111 [email protected] ")" 1091 [email protected]
1112 [email protected] " " 1092 [email protected]
1113 [email protected] 1093 [email protected]
1114 [email protected] "{" 1094 [email protected] "1"
1115 [email protected] " " 1095 [email protected] " "
1116 [email protected] 1096 [email protected] "=>"
1117 [email protected] 1097 [email protected] " "
1118 [email protected] 1098 [email protected]
1119 [email protected] "1" 1099 [email protected] "{"
1120 [email protected] " " 1100 [email protected] " "
1121 [email protected] "=>" 1101 [email protected] "}"
1122 [email protected] " " 1102 [email protected] ","
1123 [email protected] 1103 [email protected] " "
1124 [email protected] 1104 [email protected]
1125 [email protected] "{" 1105 [email protected]
1126 [email protected] " " 1106 [email protected] "_"
1127 [email protected] "}" 1107 [email protected] " "
1128 [email protected] "," 1108 [email protected] "=>"
1129 [email protected] " " 1109 [email protected] " "
1130 [email protected] 1110 [email protected]
1131 [email protected] 1111 [email protected]
1132 [email protected] "_" 1112 [email protected]
1133 [email protected] " " 1113 [email protected]
1134 [email protected] "=>" 1114 [email protected] "panic"
1135 [email protected] " " 1115 [email protected] "!"
1136 [email protected] 1116 [email protected]
1137 [email protected] 1117 [email protected] "("
1138 [email protected] 1118 [email protected] "\"wat\""
1139 [email protected] 1119 [email protected] ")"
1140 [email protected] "panic" 1120 [email protected] " "
1141 [email protected] "!" 1121 [email protected] "}"
1142 [email protected] 1122 [email protected] " "
1143 [email protected] "(" 1123 [email protected] "}"
1144 [email protected] "\"wat\"" 1124 [email protected] "\n "
1145 [email protected] ")" 1125 [email protected]
1146 [email protected] " " 1126 [email protected]
1147 [email protected] "}" 1127 [email protected] "break"
1148 [email protected] " " 1128 [email protected] ";"
1149 [email protected] "}" 1129 [email protected] " "
1150 [email protected] "\n " 1130 [email protected] "}"
1151 [email protected] 1131 [email protected] "\n"
1152 [email protected] 1132 [email protected] "}"
1153 [email protected] "break"
1154 [email protected] ";"
1155 [email protected] " "
1156 [email protected] "}"
1157 [email protected] "\n"
1158 [email protected] "}"
1159 [email protected] "\n\n" 1133 [email protected] "\n\n"
1160 [email protected] 1134 [email protected]
1161 [email protected] "fn" 1135 [email protected] "fn"
@@ -1167,31 +1141,30 @@ [email protected]
1167 [email protected] ")" 1141 [email protected] ")"
1168 [email protected] " " 1142 [email protected] " "
1169 [email protected] 1143 [email protected]
1170 [email protected] 1144 [email protected] "{"
1171 [email protected] "{" 1145 [email protected] " "
1172 [email protected] " " 1146 [email protected]
1173 [email protected] 1147 [email protected] "let"
1174 [email protected] "let" 1148 [email protected] " "
1175 [email protected] " " 1149 [email protected]
1176 [email protected] 1150 [email protected]
1177 [email protected] 1151 [email protected] "_evil"
1178 [email protected] "_evil" 1152 [email protected] " "
1179 [email protected] " " 1153 [email protected] "="
1180 [email protected] "=" 1154 [email protected] " "
1181 [email protected] " " 1155 [email protected]
1182 [email protected] 1156 [email protected]
1183 [email protected] 1157 [email protected]
1184 [email protected] 1158 [email protected]
1185 [email protected] 1159 [email protected] "println"
1186 [email protected] "println" 1160 [email protected] "!"
1187 [email protected] "!" 1161 [email protected]
1188 [email protected] 1162 [email protected] "("
1189 [email protected] "(" 1163 [email protected] "\"lincoln\""
1190 [email protected] "\"lincoln\"" 1164 [email protected] ")"
1191 [email protected] ")" 1165 [email protected] ";"
1192 [email protected] ";" 1166 [email protected] " "
1193 [email protected] " " 1167 [email protected] "}"
1194 [email protected] "}"
1195 [email protected] "\n\n" 1168 [email protected] "\n\n"
1196 [email protected] 1169 [email protected]
1197 [email protected] "fn" 1170 [email protected] "fn"
@@ -1203,114 +1176,113 @@ [email protected]
1203 [email protected] ")" 1176 [email protected] ")"
1204 [email protected] " " 1177 [email protected] " "
1205 [email protected] 1178 [email protected]
1206 [email protected] 1179 [email protected] "{"
1207 [email protected] "{" 1180 [email protected] "\n "
1208 [email protected] "\n " 1181 [email protected]
1209 [email protected] 1182 [email protected]
1210 [email protected] 1183 [email protected]
1211 [email protected] 1184 [email protected]
1212 [email protected] 1185 [email protected]
1213 [email protected] 1186 [email protected] "assert_eq"
1214 [email protected] "assert_eq" 1187 [email protected] "!"
1215 [email protected] "!" 1188 [email protected]
1216 [email protected] 1189 [email protected] "("
1217 [email protected] "(" 1190 [email protected] "String"
1218 [email protected] "String" 1191 [email protected] ":"
1219 [email protected] ":" 1192 [email protected] ":"
1220 [email protected] ":" 1193 [email protected] "from"
1221 [email protected] "from" 1194 [email protected]
1222 [email protected] 1195 [email protected] "("
1223 [email protected] "(" 1196 [email protected] "\".................... ..."
1224 [email protected] "\".................... ..." 1197 [email protected] ")"
1225 [email protected] ")" 1198 [email protected] ","
1226 [email protected] "," 1199 [email protected] "\n "
1227 [email protected] "\n " 1200 [email protected] "format"
1228 [email protected] "format" 1201 [email protected] "!"
1229 [email protected] "!" 1202 [email protected]
1230 [email protected] 1203 [email protected] "("
1231 [email protected] "(" 1204 [email protected] "\"{:?}\""
1232 [email protected] "\"{:?}\"" 1205 [email protected] ","
1233 [email protected] "," 1206 [email protected] " "
1234 [email protected] " " 1207 [email protected] "."
1235 [email protected] "." 1208 [email protected] "."
1236 [email protected] "." 1209 [email protected] " "
1237 [email protected] " " 1210 [email protected] "."
1238 [email protected] "." 1211 [email protected] "."
1239 [email protected] "." 1212 [email protected] " "
1240 [email protected] " " 1213 [email protected] "."
1241 [email protected] "." 1214 [email protected] "."
1242 [email protected] "." 1215 [email protected] " "
1243 [email protected] " " 1216 [email protected] "."
1244 [email protected] "." 1217 [email protected] "."
1245 [email protected] "." 1218 [email protected] " "
1246 [email protected] " " 1219 [email protected] "."
1247 [email protected] "." 1220 [email protected] "."
1248 [email protected] "." 1221 [email protected] " "
1249 [email protected] " " 1222 [email protected] "."
1250 [email protected] "." 1223 [email protected] "."
1251 [email protected] "." 1224 [email protected] " "
1252 [email protected] " " 1225 [email protected] "."
1253 [email protected] "." 1226 [email protected] "."
1254 [email protected] "." 1227 [email protected] " "
1255 [email protected] " " 1228 [email protected] "."
1256 [email protected] "." 1229 [email protected] "."
1257 [email protected] "." 1230 [email protected] " "
1258 [email protected] " " 1231 [email protected] "."
1259 [email protected] "." 1232 [email protected] "."
1260 [email protected] "." 1233 [email protected] " "
1261 [email protected] " " 1234 [email protected] "."
1262 [email protected] "." 1235 [email protected] "."
1263 [email protected] "." 1236 [email protected] " "
1264 [email protected] " " 1237 [email protected] "."
1265 [email protected] "." 1238 [email protected] "."
1266 [email protected] "." 1239 [email protected] " "
1267 [email protected] " " 1240 [email protected] "."
1268 [email protected] "." 1241 [email protected] "."
1269 [email protected] "." 1242 [email protected] " "
1270 [email protected] " " 1243 [email protected] "."
1271 [email protected] "." 1244 [email protected] "."
1272 [email protected] "." 1245 [email protected] "\n ..."
1273 [email protected] "\n ..." 1246 [email protected] "."
1274 [email protected] "." 1247 [email protected] "."
1275 [email protected] "." 1248 [email protected] " "
1276 [email protected] " " 1249 [email protected] "."
1277 [email protected] "." 1250 [email protected] "."
1278 [email protected] "." 1251 [email protected] " "
1279 [email protected] " " 1252 [email protected] "."
1280 [email protected] "." 1253 [email protected] "."
1281 [email protected] "." 1254 [email protected] " "
1282 [email protected] " " 1255 [email protected] "."
1283 [email protected] "." 1256 [email protected] "."
1284 [email protected] "." 1257 [email protected] " "
1285 [email protected] " " 1258 [email protected] "."
1286 [email protected] "." 1259 [email protected] "."
1287 [email protected] "." 1260 [email protected] " "
1288 [email protected] " " 1261 [email protected] "."
1289 [email protected] "." 1262 [email protected] "."
1290 [email protected] "." 1263 [email protected] " "
1291 [email protected] " " 1264 [email protected] "."
1292 [email protected] "." 1265 [email protected] "."
1293 [email protected] "." 1266 [email protected] " "
1294 [email protected] " " 1267 [email protected] "."
1295 [email protected] "." 1268 [email protected] "."
1296 [email protected] "." 1269 [email protected] " "
1297 [email protected] " " 1270 [email protected] "."
1298 [email protected] "." 1271 [email protected] "."
1299 [email protected] "." 1272 [email protected] " "
1300 [email protected] " " 1273 [email protected] "."
1301 [email protected] "." 1274 [email protected] "."
1302 [email protected] "." 1275 [email protected] " "
1303 [email protected] " " 1276 [email protected] "."
1304 [email protected] "." 1277 [email protected] "."
1305 [email protected] "." 1278 [email protected] " "
1306 [email protected] " " 1279 [email protected] "."
1307 [email protected] "." 1280 [email protected] "."
1308 [email protected] "." 1281 [email protected] ")"
1309 [email protected] ")" 1282 [email protected] ")"
1310 [email protected] ")" 1283 [email protected] ";"
1311 [email protected] ";" 1284 [email protected] "\n"
1312 [email protected] "\n" 1285 [email protected] "}"
1313 [email protected] "}"
1314 [email protected] "\n\n" 1286 [email protected] "\n\n"
1315 [email protected] 1287 [email protected]
1316 [email protected] "fn" 1288 [email protected] "fn"
@@ -1333,170 +1305,168 @@ [email protected]
1333 [email protected] ")" 1305 [email protected] ")"
1334 [email protected] " " 1306 [email protected] " "
1335 [email protected] 1307 [email protected]
1336 [email protected] 1308 [email protected] "{"
1337 [email protected] "{" 1309 [email protected] "\n "
1338 [email protected] "\n " 1310 [email protected]
1339 [email protected] 1311 [email protected] "if"
1340 [email protected] "if" 1312 [email protected] " "
1341 [email protected] " " 1313 [email protected]
1342 [email protected] 1314 [email protected]
1343 [email protected] 1315 [email protected]
1344 [email protected] 1316 [email protected]
1345 [email protected] 1317 [email protected]
1346 [email protected] 1318 [email protected]
1347 [email protected] 1319 [email protected] "u8"
1348 [email protected] "u8" 1320 [email protected] " "
1349 [email protected] " " 1321 [email protected] "!="
1350 [email protected] "!=" 1322 [email protected] " "
1351 [email protected] " " 1323 [email protected]
1352 [email protected] 1324 [email protected] "0u8"
1353 [email protected] "0u8" 1325 [email protected] " "
1354 [email protected] " " 1326 [email protected]
1355 [email protected] 1327 [email protected] "{"
1356 [email protected] 1328 [email protected] "\n "
1357 [email protected] "{" 1329 [email protected]
1358 [email protected] "\n " 1330 [email protected]
1359 [email protected] 1331 [email protected]
1360 [email protected] 1332 [email protected]
1361 [email protected] 1333 [email protected]
1362 [email protected] 1334 [email protected] "assert_eq"
1363 [email protected] 1335 [email protected] "!"
1364 [email protected] "assert_eq" 1336 [email protected]
1365 [email protected] "!" 1337 [email protected] "("
1366 [email protected] 1338 [email protected] "8u8"
1367 [email protected] "(" 1339 [email protected] ","
1368 [email protected] "8u8" 1340 [email protected] " "
1369 [email protected] "," 1341 [email protected]
1370 [email protected] " " 1342 [email protected] "{"
1371 [email protected] 1343 [email protected] "\n "
1372 [email protected] "{" 1344 [email protected] "macro_rules"
1373 [email protected] "\n " 1345 [email protected] "!"
1374 [email protected] "macro_rules" 1346 [email protected] " "
1375 [email protected] "!" 1347 [email protected] "u8"
1376 [email protected] " " 1348 [email protected] " "
1377 [email protected] "u8" 1349 [email protected]
1378 [email protected] " " 1350 [email protected] "{"
1379 [email protected] 1351 [email protected] "\n "
1380 [email protected] "{" 1352 [email protected]
1381 [email protected] "\n " 1353 [email protected] "("
1382 [email protected] 1354 [email protected] "u8"
1383 [email protected] "(" 1355 [email protected] ")"
1384 [email protected] "u8" 1356 [email protected] " "
1385 [email protected] ")" 1357 [email protected] "="
1386 [email protected] " " 1358 [email protected] ">"
1387 [email protected] "=" 1359 [email protected] " "
1388 [email protected] ">" 1360 [email protected]
1389 [email protected] " " 1361 [email protected] "{"
1390 [email protected] 1362 [email protected] "\n "
1391 [email protected] "{" 1363 [email protected] "mod"
1392 [email protected] "\n " 1364 [email protected] " "
1393 [email protected] "mod" 1365 [email protected] "u8"
1394 [email protected] " " 1366 [email protected] " "
1395 [email protected] "u8" 1367 [email protected]
1396 [email protected] " " 1368 [email protected] "{"
1397 [email protected] 1369 [email protected] "\n ..."
1398 [email protected] "{" 1370 [email protected] "pub"
1399 [email protected] "\n ..." 1371 [email protected] " "
1400 [email protected] "pub" 1372 [email protected] "fn"
1401 [email protected] " " 1373 [email protected] " "
1402 [email protected] "fn" 1374 [email protected] "u8"
1403 [email protected] " " 1375 [email protected] "<"
1404 [email protected] "u8" 1376 [email protected] "\'u8"
1405 [email protected] "<" 1377 [email protected] ":"
1406 [email protected] "\'u8" 1378 [email protected] " "
1407 [email protected] ":" 1379 [email protected] "\'u8"
1408 [email protected] " " 1380 [email protected] " "
1409 [email protected] "\'u8" 1381 [email protected] "+"
1410 [email protected] " " 1382 [email protected] " "
1411 [email protected] "+" 1383 [email protected] "\'u8"
1412 [email protected] " " 1384 [email protected] ">"
1413 [email protected] "\'u8" 1385 [email protected]
1414 [email protected] ">" 1386 [email protected] "("
1415 [email protected] 1387 [email protected] "u8"
1416 [email protected] "(" 1388 [email protected] ":"
1417 [email protected] "u8" 1389 [email protected] " "
1418 [email protected] ":" 1390 [email protected] "&"
1419 [email protected] " " 1391 [email protected] "\'u8"
1420 [email protected] "&" 1392 [email protected] " "
1421 [email protected] "\'u8" 1393 [email protected] "u8"
1422 [email protected] " " 1394 [email protected] ")"
1423 [email protected] "u8" 1395 [email protected] " "
1424 [email protected] ")" 1396 [email protected] "-"
1425 [email protected] " " 1397 [email protected] ">"
1426 [email protected] "-" 1398 [email protected] " "
1427 [email protected] ">" 1399 [email protected] "&"
1428 [email protected] " " 1400 [email protected] "\'u8"
1429 [email protected] "&" 1401 [email protected] " "
1430 [email protected] "\'u8" 1402 [email protected] "u8"
1431 [email protected] " " 1403 [email protected] " "
1432 [email protected] "u8" 1404 [email protected]
1433 [email protected] " " 1405 [email protected] "{"
1434 [email protected] 1406 [email protected] "\n ..."
1435 [email protected] "{" 1407 [email protected] "\"u8\""
1436 [email protected] "\n ..." 1408 [email protected] ";"
1437 [email protected] "\"u8\"" 1409 [email protected] "\n ..."
1438 [email protected] ";" 1410 [email protected] "u8"
1439 [email protected] "\n ..." 1411 [email protected] "\n ..."
1440 [email protected] "u8" 1412 [email protected] "}"
1441 [email protected] "\n ..." 1413 [email protected] "\n "
1442 [email protected] "}" 1414 [email protected] "}"
1443 [email protected] "\n " 1415 [email protected] "\n "
1444 [email protected] "}" 1416 [email protected] "}"
1445 [email protected] "\n " 1417 [email protected] ";"
1446 [email protected] "}" 1418 [email protected] "\n "
1447 [email protected] ";" 1419 [email protected] "}"
1448 [email protected] "\n " 1420 [email protected] "\n\n "
1449 [email protected] "}" 1421 [email protected] "u8"
1450 [email protected] "\n\n " 1422 [email protected] "!"
1451 [email protected] "u8" 1423 [email protected]
1452 [email protected] "!" 1424 [email protected] "("
1453 [email protected] 1425 [email protected] "u8"
1454 [email protected] "(" 1426 [email protected] ")"
1455 [email protected] "u8" 1427 [email protected] ";"
1456 [email protected] ")" 1428 [email protected] "\n "
1457 [email protected] ";" 1429 [email protected] "let"
1458 [email protected] "\n " 1430 [email protected] " "
1459 [email protected] "let" 1431 [email protected] "&"
1460 [email protected] " " 1432 [email protected] "u8"
1461 [email protected] "&" 1433 [email protected] ":"
1462 [email protected] "u8" 1434 [email protected] " "
1463 [email protected] ":" 1435 [email protected] "&"
1464 [email protected] " " 1436 [email protected] "u8"
1465 [email protected] "&" 1437 [email protected] " "
1466 [email protected] "u8" 1438 [email protected] "="
1467 [email protected] " " 1439 [email protected] " "
1468 [email protected] "=" 1440 [email protected] "u8"
1469 [email protected] " " 1441 [email protected] ":"
1470 [email protected] "u8" 1442 [email protected] ":"
1471 [email protected] ":" 1443 [email protected] "u8"
1472 [email protected] ":" 1444 [email protected]
1473 [email protected] "u8" 1445 [email protected] "("
1474 [email protected] 1446 [email protected] "&"
1475 [email protected] "(" 1447 [email protected] "8u8"
1476 [email protected] "&" 1448 [email protected] ")"
1477 [email protected] "8u8" 1449 [email protected] ";"
1478 [email protected] ")" 1450 [email protected] "\n "
1479 [email protected] ";" 1451 [email protected] "crate"
1480 [email protected] "\n " 1452 [email protected] ":"
1481 [email protected] "crate" 1453 [email protected] ":"
1482 [email protected] ":" 1454 [email protected] "u8"
1483 [email protected] ":" 1455 [email protected]
1484 [email protected] "u8" 1456 [email protected] "("
1485 [email protected] 1457 [email protected] "0u8"
1486 [email protected] "(" 1458 [email protected] ")"
1487 [email protected] "0u8" 1459 [email protected] ";"
1488 [email protected] ")" 1460 [email protected] "\n "
1489 [email protected] ";" 1461 [email protected] "u8"
1490 [email protected] "\n " 1462 [email protected] "\n "
1491 [email protected] "u8" 1463 [email protected] "}"
1492 [email protected] "\n " 1464 [email protected] ")"
1493 [email protected] "}" 1465 [email protected] ";"
1494 [email protected] ")" 1466 [email protected] "\n "
1495 [email protected] ";" 1467 [email protected] "}"
1496 [email protected] "\n " 1468 [email protected] "\n"
1497 [email protected] "}" 1469 [email protected] "}"
1498 [email protected] "\n"
1499 [email protected] "}"
1500 [email protected] "\n\n" 1470 [email protected] "\n\n"
1501 [email protected] 1471 [email protected]
1502 [email protected] "fn" 1472 [email protected] "fn"
@@ -1508,76 +1478,75 @@ [email protected]
1508 [email protected] ")" 1478 [email protected] ")"
1509 [email protected] " " 1479 [email protected] " "
1510 [email protected] 1480 [email protected]
1511 [email protected] 1481 [email protected] "{"
1512 [email protected] "{" 1482 [email protected] "\n "
1513 [email protected] "\n " 1483 [email protected]
1514 [email protected] 1484 [email protected]
1515 [email protected] 1485 [email protected]
1516 [email protected] 1486 [email protected]
1517 [email protected] 1487 [email protected]
1518 [email protected] 1488 [email protected] "assert_eq"
1519 [email protected] "assert_eq" 1489 [email protected] "!"
1520 [email protected] "!" 1490 [email protected]
1521 [email protected] 1491 [email protected] "("
1522 [email protected] "(" 1492 [email protected] "String"
1523 [email protected] "String" 1493 [email protected] ":"
1524 [email protected] ":" 1494 [email protected] ":"
1525 [email protected] ":" 1495 [email protected] "from"
1526 [email protected] "from" 1496 [email protected]
1527 [email protected] 1497 [email protected] "("
1528 [email protected] "(" 1498 [email protected] "\"><>\""
1529 [email protected] "\"><>\"" 1499 [email protected] ")"
1530 [email protected] ")" 1500 [email protected] ","
1531 [email protected] "," 1501 [email protected] "\n "
1532 [email protected] "\n " 1502 [email protected] "String"
1533 [email protected] "String" 1503 [email protected] ":"
1534 [email protected] ":" 1504 [email protected] ":"
1535 [email protected] ":" 1505 [email protected] "<"
1536 [email protected] "<" 1506 [email protected] ">"
1537 [email protected] ">" 1507 [email protected] ":"
1538 [email protected] ":" 1508 [email protected] ":"
1539 [email protected] ":" 1509 [email protected] "from"
1540 [email protected] "from" 1510 [email protected] ":"
1541 [email protected] ":" 1511 [email protected] ":"
1542 [email protected] ":" 1512 [email protected] "<"
1543 [email protected] "<" 1513 [email protected] ">"
1544 [email protected] ">" 1514 [email protected]
1545 [email protected] 1515 [email protected] "("
1546 [email protected] "(" 1516 [email protected] "\"><>\""
1547 [email protected] "\"><>\"" 1517 [email protected] ")"
1548 [email protected] ")" 1518 [email protected] "."
1549 [email protected] "." 1519 [email protected] "chars"
1550 [email protected] "chars" 1520 [email protected] ":"
1551 [email protected] ":" 1521 [email protected] ":"
1552 [email protected] ":" 1522 [email protected] "<"
1553 [email protected] "<" 1523 [email protected] ">"
1554 [email protected] ">" 1524 [email protected]
1555 [email protected] 1525 [email protected] "("
1556 [email protected] "(" 1526 [email protected] ")"
1557 [email protected] ")" 1527 [email protected] "."
1558 [email protected] "." 1528 [email protected] "rev"
1559 [email protected] "rev" 1529 [email protected] ":"
1560 [email protected] ":" 1530 [email protected] ":"
1561 [email protected] ":" 1531 [email protected] "<"
1562 [email protected] "<" 1532 [email protected] ">"
1563 [email protected] ">" 1533 [email protected]
1564 [email protected] 1534 [email protected] "("
1565 [email protected] "(" 1535 [email protected] ")"
1566 [email protected] ")" 1536 [email protected] "."
1567 [email protected] "." 1537 [email protected] "collect"
1568 [email protected] "collect" 1538 [email protected] ":"
1569 [email protected] ":" 1539 [email protected] ":"
1570 [email protected] ":" 1540 [email protected] "<"
1571 [email protected] "<" 1541 [email protected] "String"
1572 [email protected] "String" 1542 [email protected] ">"
1573 [email protected] ">" 1543 [email protected]
1574 [email protected] 1544 [email protected] "("
1575 [email protected] "(" 1545 [email protected] ")"
1576 [email protected] ")" 1546 [email protected] ")"
1577 [email protected] ")" 1547 [email protected] ";"
1578 [email protected] ";" 1548 [email protected] "\n"
1579 [email protected] "\n" 1549 [email protected] "}"
1580 [email protected] "}"
1581 [email protected] "\n\n" 1550 [email protected] "\n\n"
1582 [email protected] 1551 [email protected]
1583 [email protected] "fn" 1552 [email protected] "fn"
@@ -1589,47 +1558,46 @@ [email protected]
1589 [email protected] ")" 1558 [email protected] ")"
1590 [email protected] " " 1559 [email protected] " "
1591 [email protected] 1560 [email protected]
1592 [email protected] 1561 [email protected] "{"
1593 [email protected] "{" 1562 [email protected] "\n "
1594 [email protected] "\n " 1563 [email protected]
1595 [email protected] 1564 [email protected] "union"
1596 [email protected] "union" 1565 [email protected] " "
1597 [email protected] " " 1566 [email protected]
1598 [email protected] 1567 [email protected] "union"
1599 [email protected] "union" 1568 [email protected]
1600 [email protected] 1569 [email protected] "<"
1601 [email protected] "<" 1570 [email protected]
1602 [email protected] 1571 [email protected] "\'union"
1603 [email protected] "\'union" 1572 [email protected] ">"
1604 [email protected] ">" 1573 [email protected] " "
1605 [email protected] " " 1574 [email protected]
1606 [email protected] 1575 [email protected] "{"
1607 [email protected] "{" 1576 [email protected] " "
1608 [email protected] " " 1577 [email protected]
1609 [email protected] 1578 [email protected]
1610 [email protected] 1579 [email protected] "union"
1611 [email protected] "union" 1580 [email protected] ":"
1612 [email protected] ":" 1581 [email protected] " "
1613 [email protected] " " 1582 [email protected]
1614 [email protected] 1583 [email protected] "&"
1615 [email protected] "&" 1584 [email protected] "\'union"
1616 [email protected] "\'union" 1585 [email protected] " "
1617 [email protected] " " 1586 [email protected]
1618 [email protected] 1587 [email protected]
1619 [email protected] 1588 [email protected]
1620 [email protected] 1589 [email protected]
1621 [email protected] 1590 [email protected] "union"
1622 [email protected] "union" 1591 [email protected]
1623 [email protected] 1592 [email protected] "<"
1624 [email protected] "<" 1593 [email protected]
1625 [email protected] 1594 [email protected] "\'union"
1626 [email protected] "\'union" 1595 [email protected] ">"
1627 [email protected] ">" 1596 [email protected] ","
1628 [email protected] "," 1597 [email protected] " "
1629 [email protected] " " 1598 [email protected] "}"
1630 [email protected] "}" 1599 [email protected] "\n"
1631 [email protected] "\n" 1600 [email protected] "}"
1632 [email protected] "}"
1633 [email protected] "\n\n" 1601 [email protected] "\n\n"
1634 [email protected] 1602 [email protected]
1635 [email protected] "fn" 1603 [email protected] "fn"
@@ -1641,121 +1609,118 @@ [email protected]
1641 [email protected] ")" 1609 [email protected] ")"
1642 [email protected] " " 1610 [email protected] " "
1643 [email protected] 1611 [email protected]
1644 [email protected] 1612 [email protected] "{"
1645 [email protected] "{" 1613 [email protected] "\n "
1646 [email protected] "\n " 1614 [email protected]
1647 [email protected] 1615 [email protected] "let"
1648 [email protected] "let" 1616 [email protected] " "
1649 [email protected] " " 1617 [email protected]
1650 [email protected] 1618 [email protected]
1651 [email protected] 1619 [email protected] "val"
1652 [email protected] "val" 1620 [email protected] " "
1653 [email protected] " " 1621 [email protected] "="
1654 [email protected] "=" 1622 [email protected] " "
1655 [email protected] " " 1623 [email protected]
1656 [email protected] 1624 [email protected] "!"
1657 [email protected] "!" 1625 [email protected]
1658 [email protected] 1626 [email protected] "("
1659 [email protected] "(" 1627 [email protected]
1660 [email protected] 1628 [email protected]
1661 [email protected] 1629 [email protected]
1662 [email protected] 1630 [email protected] "("
1663 [email protected] "(" 1631 [email protected]
1664 [email protected] 1632 [email protected]
1665 [email protected] 1633 [email protected] "|"
1666 [email protected] "|" 1634 [email protected]
1667 [email protected] 1635 [email protected]
1668 [email protected] 1636 [email protected] "("
1669 [email protected] "(" 1637 [email protected]
1670 [email protected] 1638 [email protected] ".."
1671 [email protected] ".." 1639 [email protected] ")"
1672 [email protected] ")" 1640 [email protected] ":"
1673 [email protected] ":" 1641 [email protected]
1674 [email protected] 1642 [email protected] "("
1675 [email protected] "(" 1643 [email protected]
1676 [email protected] 1644 [email protected] "_"
1677 [email protected] "_" 1645 [email protected] ","
1678 [email protected] "," 1646 [email protected]
1679 [email protected] 1647 [email protected] "_"
1680 [email protected] "_" 1648 [email protected] ")"
1681 [email protected] ")" 1649 [email protected] ","
1682 [email protected] "," 1650 [email protected]
1683 [email protected] 1651 [email protected]
1684 [email protected] 1652 [email protected]
1685 [email protected] 1653 [email protected] "__"
1686 [email protected] "__" 1654 [email protected] "@"
1687 [email protected] "@" 1655 [email protected]
1688 [email protected] 1656 [email protected] "_"
1689 [email protected] "_" 1657 [email protected] "|"
1690 [email protected] "|" 1658 [email protected]
1691 [email protected] 1659 [email protected]
1692 [email protected] 1660 [email protected]
1693 [email protected] 1661 [email protected]
1694 [email protected] 1662 [email protected] "__"
1695 [email protected] "__" 1663 [email protected] ")"
1696 [email protected] ")" 1664 [email protected]
1697 [email protected] 1665 [email protected] "("
1698 [email protected] "(" 1666 [email protected]
1699 [email protected] 1667 [email protected] "("
1700 [email protected] "(" 1668 [email protected]
1701 [email protected] 1669 [email protected] "&"
1702 [email protected] "&" 1670 [email protected]
1703 [email protected] 1671 [email protected] "*"
1704 [email protected] "*" 1672 [email protected]
1705 [email protected] 1673 [email protected] "\"\\\\\""
1706 [email protected] "\"\\\\\"" 1674 [email protected] ","
1707 [email protected] "," 1675 [email protected]
1708 [email protected] 1676 [email protected] "\'🤔\'"
1709 [email protected] "\'🤔\'" 1677 [email protected] ")"
1710 [email protected] ")" 1678 [email protected] "/**/"
1711 [email protected] "/**/" 1679 [email protected] ","
1712 [email protected] "," 1680 [email protected]
1713 [email protected] 1681 [email protected] "{"
1714 [email protected] 1682 [email protected] "}"
1715 [email protected] "{" 1683 [email protected] ")"
1716 [email protected] "}" 1684 [email protected] "=="
1717 [email protected] ")" 1685 [email protected]
1718 [email protected] "==" 1686 [email protected] "{"
1719 [email protected] 1687 [email protected]
1720 [email protected] 1688 [email protected]
1721 [email protected] "{" 1689 [email protected] "&"
1722 [email protected] 1690 [email protected]
1723 [email protected] 1691 [email protected]
1724 [email protected] "&" 1692 [email protected] "["
1725 [email protected] 1693 [email protected]
1726 [email protected] 1694 [email protected] "..="
1727 [email protected] "[" 1695 [email protected]
1728 [email protected] 1696 [email protected] ".."
1729 [email protected] "..=" 1697 [email protected] "]"
1730 [email protected] 1698 [email protected] "["
1731 [email protected] ".." 1699 [email protected]
1732 [email protected] "]" 1700 [email protected] ".."
1733 [email protected] "[" 1701 [email protected] "]"
1734 [email protected] 1702 [email protected] ";"
1735 [email protected] ".." 1703 [email protected] "}"
1736 [email protected] "]" 1704 [email protected] ")"
1737 [email protected] ";" 1705 [email protected] "//"
1738 [email protected] "}" 1706 [email protected] "\n "
1739 [email protected] ")" 1707 [email protected] ";"
1740 [email protected] "//" 1708 [email protected] "\n "
1741 [email protected] "\n " 1709 [email protected]
1742 [email protected] ";" 1710 [email protected]
1743 [email protected] "\n " 1711 [email protected]
1744 [email protected] 1712 [email protected]
1745 [email protected] 1713 [email protected]
1746 [email protected] 1714 [email protected] "assert"
1747 [email protected] 1715 [email protected] "!"
1748 [email protected] 1716 [email protected]
1749 [email protected] "assert" 1717 [email protected] "("
1750 [email protected] "!" 1718 [email protected] "!"
1751 [email protected] 1719 [email protected] "val"
1752 [email protected] "(" 1720 [email protected] ")"
1753 [email protected] "!" 1721 [email protected] ";"
1754 [email protected] "val" 1722 [email protected] "\n"
1755 [email protected] ")" 1723 [email protected] "}"
1756 [email protected] ";"
1757 [email protected] "\n"
1758 [email protected] "}"
1759 [email protected] "\n\n" 1724 [email protected] "\n\n"
1760 [email protected] 1725 [email protected]
1761 [email protected] "fn" 1726 [email protected] "fn"
@@ -1791,306 +1756,305 @@ [email protected]
1791 [email protected] "Debug" 1756 [email protected] "Debug"
1792 [email protected] " " 1757 [email protected] " "
1793 [email protected] 1758 [email protected]
1794 [email protected] 1759 [email protected] "{"
1795 [email protected] "{" 1760 [email protected] "\n "
1796 [email protected] "\n " 1761 [email protected]
1797 [email protected] 1762 [email protected] "..="
1798 [email protected] "..=" 1763 [email protected]
1799 [email protected] 1764 [email protected] "..="
1800 [email protected] "..=" 1765 [email protected]
1801 [email protected] 1766 [email protected] ".."
1802 [email protected] ".." 1767 [email protected] " "
1803 [email protected] " " 1768 [email protected]
1804 [email protected] 1769 [email protected] ".."
1805 [email protected] ".." 1770 [email protected] " "
1806 [email protected] " " 1771 [email protected]
1807 [email protected] 1772 [email protected] ".."
1808 [email protected] ".." 1773 [email protected] " "
1809 [email protected] " " 1774 [email protected]
1810 [email protected] 1775 [email protected] ".."
1811 [email protected] ".." 1776 [email protected] " "
1812 [email protected] " " 1777 [email protected]
1813 [email protected] 1778 [email protected] ".."
1814 [email protected] ".." 1779 [email protected] " "
1815 [email protected] " " 1780 [email protected]
1816 [email protected] 1781 [email protected] ".."
1817 [email protected] ".." 1782 [email protected] " "
1818 [email protected] " " 1783 [email protected]
1819 [email protected] 1784 [email protected] ".."
1820 [email protected] ".." 1785 [email protected] " "
1821 [email protected] " " 1786 [email protected]
1822 [email protected] 1787 [email protected] ".."
1823 [email protected] ".." 1788 [email protected] " "
1824 [email protected] " " 1789 [email protected]
1825 [email protected] 1790 [email protected] ".."
1826 [email protected] ".." 1791 [email protected] " "
1827 [email protected] " " 1792 [email protected]
1828 [email protected] 1793 [email protected] ".."
1829 [email protected] ".." 1794 [email protected] " "
1830 [email protected] " " 1795 [email protected]
1831 [email protected] 1796 [email protected] ".."
1832 [email protected] ".." 1797 [email protected] " "
1833 [email protected] " " 1798 [email protected]
1834 [email protected] 1799 [email protected] "..="
1835 [email protected] "..=" 1800 [email protected]
1836 [email protected] 1801 [email protected] ".."
1837 [email protected] ".." 1802 [email protected] " "
1838 [email protected] " " 1803 [email protected]
1839 [email protected] 1804 [email protected] ".."
1840 [email protected] ".." 1805 [email protected] "\n "
1841 [email protected] "\n " 1806 [email protected]
1842 [email protected] 1807 [email protected] "..="
1843 [email protected] "..=" 1808 [email protected]
1844 [email protected] 1809 [email protected] ".."
1845 [email protected] ".." 1810 [email protected] " "
1846 [email protected] " " 1811 [email protected]
1847 [email protected] 1812 [email protected] "..="
1848 [email protected] "..=" 1813 [email protected]
1849 [email protected] 1814 [email protected] ".."
1850 [email protected] ".." 1815 [email protected] " "
1851 [email protected] " " 1816 [email protected]
1852 [email protected] 1817 [email protected] ".."
1853 [email protected] ".." 1818 [email protected] " "
1854 [email protected] " " 1819 [email protected]
1855 [email protected] 1820 [email protected] ".."
1856 [email protected] ".." 1821 [email protected] " "
1857 [email protected] " " 1822 [email protected]
1858 [email protected] 1823 [email protected] ".."
1859 [email protected] ".." 1824 [email protected] " "
1860 [email protected] " " 1825 [email protected]
1861 [email protected] 1826 [email protected] ".."
1862 [email protected] ".." 1827 [email protected] " "
1863 [email protected] " " 1828 [email protected]
1864 [email protected] 1829 [email protected] ".."
1865 [email protected] ".." 1830 [email protected] " "
1866 [email protected] " " 1831 [email protected]
1867 [email protected] 1832 [email protected] ".."
1868 [email protected] ".." 1833 [email protected] " "
1869 [email protected] " " 1834 [email protected]
1870 [email protected] 1835 [email protected] ".."
1871 [email protected] ".." 1836 [email protected] " "
1872 [email protected] " " 1837 [email protected]
1873 [email protected] 1838 [email protected] ".."
1874 [email protected] ".." 1839 [email protected] " "
1875 [email protected] " " 1840 [email protected]
1876 [email protected] 1841 [email protected] "..="
1877 [email protected] "..=" 1842 [email protected]
1878 [email protected] 1843 [email protected] "..="
1879 [email protected] "..=" 1844 [email protected]
1880 [email protected] 1845 [email protected] "..="
1881 [email protected] "..=" 1846 [email protected]
1882 [email protected] 1847 [email protected] ".."
1883 [email protected] ".." 1848 [email protected] "\n "
1884 [email protected] "\n " 1849 [email protected]
1885 [email protected] 1850 [email protected] "..="
1886 [email protected] "..=" 1851 [email protected]
1887 [email protected] 1852 [email protected] ".."
1888 [email protected] ".." 1853 [email protected] " "
1889 [email protected] " " 1854 [email protected]
1890 [email protected] 1855 [email protected] "..="
1891 [email protected] "..=" 1856 [email protected]
1892 [email protected] 1857 [email protected] ".."
1893 [email protected] ".." 1858 [email protected] " "
1894 [email protected] " " 1859 [email protected]
1895 [email protected] 1860 [email protected] "..="
1896 [email protected] "..=" 1861 [email protected]
1897 [email protected] 1862 [email protected] ".."
1898 [email protected] ".." 1863 [email protected] " "
1899 [email protected] " " 1864 [email protected]
1900 [email protected] 1865 [email protected] "..="
1901 [email protected] "..=" 1866 [email protected]
1902 [email protected] 1867 [email protected] ".."
1903 [email protected] ".." 1868 [email protected] " "
1904 [email protected] " " 1869 [email protected]
1905 [email protected] 1870 [email protected] ".."
1906 [email protected] ".." 1871 [email protected] " "
1907 [email protected] " " 1872 [email protected]
1908 [email protected] 1873 [email protected] "..="
1909 [email protected] "..=" 1874 [email protected]
1910 [email protected] 1875 [email protected] "..="
1911 [email protected] "..=" 1876 [email protected]
1912 [email protected] 1877 [email protected] ".."
1913 [email protected] ".." 1878 [email protected] " "
1914 [email protected] " " 1879 [email protected]
1915 [email protected] 1880 [email protected] ".."
1916 [email protected] ".." 1881 [email protected] " "
1917 [email protected] " " 1882 [email protected]
1918 [email protected] 1883 [email protected] "..="
1919 [email protected] "..=" 1884 [email protected]
1920 [email protected] 1885 [email protected] ".."
1921 [email protected] ".." 1886 [email protected] " "
1922 [email protected] " " 1887 [email protected]
1923 [email protected] 1888 [email protected] ".."
1924 [email protected] ".." 1889 [email protected] "\n "
1925 [email protected] "\n " 1890 [email protected]
1926 [email protected] 1891 [email protected] "..="
1927 [email protected] "..=" 1892 [email protected]
1928 [email protected] 1893 [email protected] "..="
1929 [email protected] "..=" 1894 [email protected]
1930 [email protected] 1895 [email protected] ".."
1931 [email protected] ".." 1896 [email protected] " "
1932 [email protected] " " 1897 [email protected]
1933 [email protected] 1898 [email protected] ".."
1934 [email protected] ".." 1899 [email protected] " "
1935 [email protected] " " 1900 [email protected]
1936 [email protected] 1901 [email protected] "..="
1937 [email protected] "..=" 1902 [email protected]
1938 [email protected] 1903 [email protected] ".."
1939 [email protected] ".." 1904 [email protected] " "
1940 [email protected] " " 1905 [email protected]
1941 [email protected] 1906 [email protected] "..="
1942 [email protected] "..=" 1907 [email protected]
1943 [email protected] 1908 [email protected] ".."
1944 [email protected] ".." 1909 [email protected] " "
1945 [email protected] " " 1910 [email protected]
1946 [email protected] 1911 [email protected] "..="
1947 [email protected] "..=" 1912 [email protected]
1948 [email protected] 1913 [email protected] ".."
1949 [email protected] ".." 1914 [email protected] " "
1950 [email protected] " " 1915 [email protected]
1951 [email protected] 1916 [email protected] ".."
1952 [email protected] ".." 1917 [email protected] " "
1953 [email protected] " " 1918 [email protected]
1954 [email protected] 1919 [email protected] ".."
1955 [email protected] ".." 1920 [email protected] " "
1956 [email protected] " " 1921 [email protected]
1957 [email protected] 1922 [email protected] ".."
1958 [email protected] ".." 1923 [email protected] " "
1959 [email protected] " " 1924 [email protected]
1960 [email protected] 1925 [email protected] "..="
1961 [email protected] "..=" 1926 [email protected]
1962 [email protected] 1927 [email protected] ".."
1963 [email protected] ".." 1928 [email protected] " "
1964 [email protected] " " 1929 [email protected]
1965 [email protected] 1930 [email protected] ".."
1966 [email protected] ".." 1931 [email protected] "\n "
1967 [email protected] "\n " 1932 [email protected]
1968 [email protected] 1933 [email protected] "..="
1969 [email protected] "..=" 1934 [email protected]
1970 [email protected] 1935 [email protected] ".."
1971 [email protected] ".." 1936 [email protected] " "
1972 [email protected] " " 1937 [email protected]
1973 [email protected] 1938 [email protected] "..="
1974 [email protected] "..=" 1939 [email protected]
1975 [email protected] 1940 [email protected] ".."
1976 [email protected] ".." 1941 [email protected] " "
1977 [email protected] " " 1942 [email protected]
1978 [email protected] 1943 [email protected] "..="
1979 [email protected] "..=" 1944 [email protected]
1980 [email protected] 1945 [email protected] ".."
1981 [email protected] ".." 1946 [email protected] " "
1982 [email protected] " " 1947 [email protected]
1983 [email protected] 1948 [email protected] "..="
1984 [email protected] "..=" 1949 [email protected]
1985 [email protected] 1950 [email protected] ".."
1986 [email protected] ".." 1951 [email protected] " "
1987 [email protected] " " 1952 [email protected]
1988 [email protected] 1953 [email protected] ".."
1989 [email protected] ".." 1954 [email protected] " "
1990 [email protected] " " 1955 [email protected]
1991 [email protected] 1956 [email protected] "..="
1992 [email protected] "..=" 1957 [email protected]
1993 [email protected] 1958 [email protected] ".."
1994 [email protected] ".." 1959 [email protected] " "
1995 [email protected] " " 1960 [email protected]
1996 [email protected] 1961 [email protected] ".."
1997 [email protected] ".." 1962 [email protected] " "
1998 [email protected] " " 1963 [email protected]
1999 [email protected] 1964 [email protected] ".."
2000 [email protected] ".." 1965 [email protected] " "
2001 [email protected] " " 1966 [email protected]
2002 [email protected] 1967 [email protected] "..="
2003 [email protected] "..=" 1968 [email protected]
2004 [email protected] 1969 [email protected] ".."
2005 [email protected] ".." 1970 [email protected] " "
2006 [email protected] " " 1971 [email protected]
2007 [email protected] 1972 [email protected] ".."
2008 [email protected] ".." 1973 [email protected] "\n "
2009 [email protected] "\n " 1974 [email protected]
2010 [email protected] 1975 [email protected] "..="
2011 [email protected] "..=" 1976 [email protected]
2012 [email protected] 1977 [email protected] ".."
2013 [email protected] ".." 1978 [email protected] " "
2014 [email protected] " " 1979 [email protected]
2015 [email protected] 1980 [email protected] "..="
2016 [email protected] "..=" 1981 [email protected]
2017 [email protected] 1982 [email protected] ".."
2018 [email protected] ".." 1983 [email protected] " "
2019 [email protected] " " 1984 [email protected]
2020 [email protected] 1985 [email protected] "..="
2021 [email protected] "..=" 1986 [email protected]
2022 [email protected] 1987 [email protected] ".."
2023 [email protected] ".." 1988 [email protected] " "
2024 [email protected] " " 1989 [email protected]
2025 [email protected] 1990 [email protected] "..="
2026 [email protected] "..=" 1991 [email protected]
2027 [email protected] 1992 [email protected] ".."
2028 [email protected] ".." 1993 [email protected] " "
2029 [email protected] " " 1994 [email protected]
2030 [email protected] 1995 [email protected] ".."
2031 [email protected] ".." 1996 [email protected] " "
2032 [email protected] " " 1997 [email protected]
2033 [email protected] 1998 [email protected] ".."
2034 [email protected] ".." 1999 [email protected] " "
2035 [email protected] " " 2000 [email protected]
2036 [email protected] 2001 [email protected] "..="
2037 [email protected] "..=" 2002 [email protected]
2038 [email protected] 2003 [email protected] ".."
2039 [email protected] ".." 2004 [email protected] " "
2040 [email protected] " " 2005 [email protected]
2041 [email protected] 2006 [email protected] ".."
2042 [email protected] ".." 2007 [email protected] " "
2043 [email protected] " " 2008 [email protected]
2044 [email protected] 2009 [email protected] "..="
2045 [email protected] "..=" 2010 [email protected]
2046 [email protected] 2011 [email protected] ".."
2047 [email protected] ".." 2012 [email protected] " "
2048 [email protected] " " 2013 [email protected]
2049 [email protected] 2014 [email protected] ".."
2050 [email protected] ".." 2015 [email protected] "\n "
2051 [email protected] "\n " 2016 [email protected]
2052 [email protected] 2017 [email protected] "..="
2053 [email protected] "..=" 2018 [email protected]
2054 [email protected] 2019 [email protected] ".."
2055 [email protected] ".." 2020 [email protected] " "
2056 [email protected] " " 2021 [email protected]
2057 [email protected] 2022 [email protected] "..="
2058 [email protected] "..=" 2023 [email protected]
2059 [email protected] 2024 [email protected] ".."
2060 [email protected] ".." 2025 [email protected] " "
2061 [email protected] " " 2026 [email protected]
2062 [email protected] 2027 [email protected] ".."
2063 [email protected] ".." 2028 [email protected] " "
2064 [email protected] " " 2029 [email protected]
2065 [email protected] 2030 [email protected] "..="
2066 [email protected] "..=" 2031 [email protected]
2067 [email protected] 2032 [email protected] "..="
2068 [email protected] "..=" 2033 [email protected]
2069 [email protected] 2034 [email protected] ".."
2070 [email protected] ".." 2035 [email protected] " "
2071 [email protected] " " 2036 [email protected]
2072 [email protected] 2037 [email protected] "..="
2073 [email protected] "..=" 2038 [email protected]
2074 [email protected] 2039 [email protected] "..="
2075 [email protected] "..=" 2040 [email protected]
2076 [email protected] 2041 [email protected] ".."
2077 [email protected] ".." 2042 [email protected] " "
2078 [email protected] " " 2043 [email protected]
2079 [email protected] 2044 [email protected] ".."
2080 [email protected] ".." 2045 [email protected] " "
2081 [email protected] " " 2046 [email protected]
2082 [email protected] 2047 [email protected] ".."
2083 [email protected] ".." 2048 [email protected] " "
2084 [email protected] " " 2049 [email protected]
2085 [email protected] 2050 [email protected] "..="
2086 [email protected] "..=" 2051 [email protected]
2087 [email protected] 2052 [email protected] ".."
2088 [email protected] ".." 2053 [email protected] " "
2089 [email protected] " " 2054 [email protected]
2090 [email protected] 2055 [email protected] ".."
2091 [email protected] ".." 2056 [email protected] "\n"
2092 [email protected] "\n" 2057 [email protected] "}"
2093 [email protected] "}"
2094 [email protected] "\n\n" 2058 [email protected] "\n\n"
2095 [email protected] 2059 [email protected]
2096 [email protected] "fn" 2060 [email protected] "fn"
@@ -2102,30 +2066,29 @@ [email protected]
2102 [email protected] ")" 2066 [email protected] ")"
2103 [email protected] " " 2067 [email protected] " "
2104 [email protected] 2068 [email protected]
2105 [email protected] 2069 [email protected] "{"
2106 [email protected] "{" 2070 [email protected] "\n "
2107 [email protected] "\n " 2071 [email protected] ";"
2108 [email protected] ";" 2072 [email protected] ";"
2109 [email protected] ";" 2073 [email protected] ";"
2110 [email protected] ";" 2074 [email protected]
2111 [email protected] 2075 [email protected]
2112 [email protected] 2076 [email protected] "("
2113 [email protected] "(" 2077 [email protected] ")"
2114 [email protected] ")" 2078 [email protected] ";"
2115 [email protected] ";" 2079 [email protected] ";"
2116 [email protected] ";" 2080 [email protected] ";"
2117 [email protected] ";" 2081 [email protected] ";"
2118 [email protected] ";" 2082 [email protected] ";"
2119 [email protected] ";" 2083 [email protected] ";"
2120 [email protected] ";" 2084 [email protected] ";"
2121 [email protected] ";" 2085 [email protected] ";"
2122 [email protected] ";" 2086 [email protected] ";"
2123 [email protected] ";" 2087 [email protected]
2124 [email protected] 2088 [email protected] "("
2125 [email protected] "(" 2089 [email protected] ")"
2126 [email protected] ")" 2090 [email protected] "\n"
2127 [email protected] "\n" 2091 [email protected] "}"
2128 [email protected] "}"
2129 [email protected] "\n\n" 2092 [email protected] "\n\n"
2130 [email protected] 2093 [email protected]
2131 [email protected] 2094 [email protected]
@@ -2140,190 +2103,189 @@ [email protected]
2140 [email protected] ")" 2103 [email protected] ")"
2141 [email protected] " " 2104 [email protected] " "
2142 [email protected] 2105 [email protected]
2143 [email protected] 2106 [email protected] "{"
2144 [email protected] "{" 2107 [email protected] "\n "
2145 [email protected] "\n " 2108 [email protected]
2146 [email protected] 2109 [email protected]
2147 [email protected] 2110 [email protected]
2148 [email protected] 2111 [email protected]
2149 [email protected] 2112 [email protected]
2150 [email protected] 2113 [email protected]
2151 [email protected] 2114 [email protected] "strange"
2152 [email protected] "strange" 2115 [email protected]
2153 [email protected] 2116 [email protected] "("
2154 [email protected] "(" 2117 [email protected] ")"
2155 [email protected] ")" 2118 [email protected] ";"
2156 [email protected] ";" 2119 [email protected] "\n "
2157 [email protected] "\n " 2120 [email protected]
2158 [email protected] 2121 [email protected]
2159 [email protected] 2122 [email protected]
2160 [email protected] 2123 [email protected]
2161 [email protected] 2124 [email protected]
2162 [email protected] 2125 [email protected]
2163 [email protected] 2126 [email protected] "funny"
2164 [email protected] "funny" 2127 [email protected]
2165 [email protected] 2128 [email protected] "("
2166 [email protected] "(" 2129 [email protected] ")"
2167 [email protected] ")" 2130 [email protected] ";"
2168 [email protected] ";" 2131 [email protected] "\n "
2169 [email protected] "\n " 2132 [email protected]
2170 [email protected] 2133 [email protected]
2171 [email protected] 2134 [email protected]
2172 [email protected] 2135 [email protected]
2173 [email protected] 2136 [email protected]
2174 [email protected] 2137 [email protected]
2175 [email protected] 2138 [email protected] "what"
2176 [email protected] "what" 2139 [email protected]
2177 [email protected] 2140 [email protected] "("
2178 [email protected] "(" 2141 [email protected] ")"
2179 [email protected] ")" 2142 [email protected] ";"
2180 [email protected] ";" 2143 [email protected] "\n "
2181 [email protected] "\n " 2144 [email protected]
2182 [email protected] 2145 [email protected]
2183 [email protected] 2146 [email protected]
2184 [email protected] 2147 [email protected]
2185 [email protected] 2148 [email protected]
2186 [email protected] 2149 [email protected]
2187 [email protected] 2150 [email protected] "zombiejesus"
2188 [email protected] "zombiejesus" 2151 [email protected]
2189 [email protected] 2152 [email protected] "("
2190 [email protected] "(" 2153 [email protected] ")"
2191 [email protected] ")" 2154 [email protected] ";"
2192 [email protected] ";" 2155 [email protected] "\n "
2193 [email protected] "\n " 2156 [email protected]
2194 [email protected] 2157 [email protected]
2195 [email protected] 2158 [email protected]
2196 [email protected] 2159 [email protected]
2197 [email protected] 2160 [email protected]
2198 [email protected] 2161 [email protected]
2199 [email protected] 2162 [email protected] "notsure"
2200 [email protected] "notsure" 2163 [email protected]
2201 [email protected] 2164 [email protected] "("
2202 [email protected] "(" 2165 [email protected] ")"
2203 [email protected] ")" 2166 [email protected] ";"
2204 [email protected] ";" 2167 [email protected] "\n "
2205 [email protected] "\n " 2168 [email protected]
2206 [email protected] 2169 [email protected]
2207 [email protected] 2170 [email protected]
2208 [email protected] 2171 [email protected]
2209 [email protected] 2172 [email protected]
2210 [email protected] 2173 [email protected]
2211 [email protected] 2174 [email protected] "canttouchthis"
2212 [email protected] "canttouchthis" 2175 [email protected]
2213 [email protected] 2176 [email protected] "("
2214 [email protected] "(" 2177 [email protected] ")"
2215 [email protected] ")" 2178 [email protected] ";"
2216 [email protected] ";" 2179 [email protected] "\n "
2217 [email protected] "\n " 2180 [email protected]
2218 [email protected] 2181 [email protected]
2219 [email protected] 2182 [email protected]
2220 [email protected] 2183 [email protected]
2221 [email protected] 2184 [email protected]
2222 [email protected] 2185 [email protected]
2223 [email protected] 2186 [email protected] "angrydome"
2224 [email protected] "angrydome" 2187 [email protected]
2225 [email protected] 2188 [email protected] "("
2226 [email protected] "(" 2189 [email protected] ")"
2227 [email protected] ")" 2190 [email protected] ";"
2228 [email protected] ";" 2191 [email protected] "\n "
2229 [email protected] "\n " 2192 [email protected]
2230 [email protected] 2193 [email protected]
2231 [email protected] 2194 [email protected]
2232 [email protected] 2195 [email protected]
2233 [email protected] 2196 [email protected]
2234 [email protected] 2197 [email protected]
2235 [email protected] 2198 [email protected] "evil_lincoln"
2236 [email protected] "evil_lincoln" 2199 [email protected]
2237 [email protected] 2200 [email protected] "("
2238 [email protected] "(" 2201 [email protected] ")"
2239 [email protected] ")" 2202 [email protected] ";"
2240 [email protected] ";" 2203 [email protected] "\n "
2241 [email protected] "\n " 2204 [email protected]
2242 [email protected] 2205 [email protected]
2243 [email protected] 2206 [email protected]
2244 [email protected] 2207 [email protected]
2245 [email protected] 2208 [email protected]
2246 [email protected] 2209 [email protected]
2247 [email protected] 2210 [email protected] "dots"
2248 [email protected] "dots" 2211 [email protected]
2249 [email protected] 2212 [email protected] "("
2250 [email protected] "(" 2213 [email protected] ")"
2251 [email protected] ")" 2214 [email protected] ";"
2252 [email protected] ";" 2215 [email protected] "\n "
2253 [email protected] "\n " 2216 [email protected]
2254 [email protected] 2217 [email protected]
2255 [email protected] 2218 [email protected]
2256 [email protected] 2219 [email protected]
2257 [email protected] 2220 [email protected]
2258 [email protected] 2221 [email protected]
2259 [email protected] 2222 [email protected] "u8"
2260 [email protected] "u8" 2223 [email protected]
2261 [email protected] 2224 [email protected] "("
2262 [email protected] "(" 2225 [email protected]
2263 [email protected] 2226 [email protected] "8u8"
2264 [email protected] "8u8" 2227 [email protected] ")"
2265 [email protected] ")" 2228 [email protected] ";"
2266 [email protected] ";" 2229 [email protected] "\n "
2267 [email protected] "\n " 2230 [email protected]
2268 [email protected] 2231 [email protected]
2269 [email protected] 2232 [email protected]
2270 [email protected] 2233 [email protected]
2271 [email protected] 2234 [email protected]
2272 [email protected] 2235 [email protected]
2273 [email protected] 2236 [email protected] "fishy"
2274 [email protected] "fishy" 2237 [email protected]
2275 [email protected] 2238 [email protected] "("
2276 [email protected] "(" 2239 [email protected] ")"
2277 [email protected] ")" 2240 [email protected] ";"
2278 [email protected] ";" 2241 [email protected] "\n "
2279 [email protected] "\n " 2242 [email protected]
2280 [email protected] 2243 [email protected]
2281 [email protected] 2244 [email protected]
2282 [email protected] 2245 [email protected]
2283 [email protected] 2246 [email protected]
2284 [email protected] 2247 [email protected]
2285 [email protected] 2248 [email protected] "union"
2286 [email protected] "union" 2249 [email protected]
2287 [email protected] 2250 [email protected] "("
2288 [email protected] "(" 2251 [email protected] ")"
2289 [email protected] ")" 2252 [email protected] ";"
2290 [email protected] ";" 2253 [email protected] "\n "
2291 [email protected] "\n " 2254 [email protected]
2292 [email protected] 2255 [email protected]
2293 [email protected] 2256 [email protected]
2294 [email protected] 2257 [email protected]
2295 [email protected] 2258 [email protected]
2296 [email protected] 2259 [email protected]
2297 [email protected] 2260 [email protected] "special_characters"
2298 [email protected] "special_characters" 2261 [email protected]
2299 [email protected] 2262 [email protected] "("
2300 [email protected] "(" 2263 [email protected] ")"
2301 [email protected] ")" 2264 [email protected] ";"
2302 [email protected] ";" 2265 [email protected] "\n "
2303 [email protected] "\n " 2266 [email protected]
2304 [email protected] 2267 [email protected]
2305 [email protected] 2268 [email protected]
2306 [email protected] 2269 [email protected]
2307 [email protected] 2270 [email protected]
2308 [email protected] 2271 [email protected]
2309 [email protected] 2272 [email protected] "punch_card"
2310 [email protected] "punch_card" 2273 [email protected]
2311 [email protected] 2274 [email protected] "("
2312 [email protected] "(" 2275 [email protected] ")"
2313 [email protected] ")" 2276 [email protected] ";"
2314 [email protected] ";" 2277 [email protected] "\n "
2315 [email protected] "\n " 2278 [email protected]
2316 [email protected] 2279 [email protected]
2317 [email protected] 2280 [email protected]
2318 [email protected] 2281 [email protected]
2319 [email protected] 2282 [email protected]
2320 [email protected] 2283 [email protected]
2321 [email protected] 2284 [email protected] "ktulhu"
2322 [email protected] "ktulhu" 2285 [email protected]
2323 [email protected] 2286 [email protected] "("
2324 [email protected] "(" 2287 [email protected] ")"
2325 [email protected] ")" 2288 [email protected] ";"
2326 [email protected] ";" 2289 [email protected] "\n"
2327 [email protected] "\n" 2290 [email protected] "}"
2328 [email protected] "}"
2329 [email protected] "\n" 2291 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0036_fully_qualified.rast b/crates/ra_syntax/test_data/parser/ok/0036_fully_qualified.rast
index 8f616623b..a64a82e94 100644
--- a/crates/ra_syntax/test_data/parser/ok/0036_fully_qualified.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0036_fully_qualified.rast
@@ -76,18 +76,17 @@ [email protected]
76 [email protected] "," 76 [email protected] ","
77 [email protected] "\n" 77 [email protected] "\n"
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected] "{"
80 [email protected] "{" 80 [email protected] "\n "
81 [email protected] "\n " 81 [email protected]
82 [email protected] 82 [email protected]
83 [email protected] 83 [email protected] "\"\""
84 [email protected] "\"\"" 84 [email protected] "."
85 [email protected] "." 85 [email protected]
86 [email protected] 86 [email protected] "to_owned"
87 [email protected] "to_owned" 87 [email protected]
88 [email protected] 88 [email protected] "("
89 [email protected] "(" 89 [email protected] ")"
90 [email protected] ")" 90 [email protected] "\n"
91 [email protected] "\n" 91 [email protected] "}"
92 [email protected] "}"
93 [email protected] "\n" 92 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0038_where_pred_type.rast b/crates/ra_syntax/test_data/parser/ok/0038_where_pred_type.rast
index 14d82feb0..7fd414090 100644
--- a/crates/ra_syntax/test_data/parser/ok/0038_where_pred_type.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0038_where_pred_type.rast
@@ -38,6 +38,5 @@ [email protected]
38 [email protected] "Foo" 38 [email protected] "Foo"
39 [email protected] " " 39 [email protected] " "
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "{"
42 [email protected] "{" 42 [email protected] "}"
43 [email protected] "}"
diff --git a/crates/ra_syntax/test_data/parser/ok/0039_raw_fn_item.rast b/crates/ra_syntax/test_data/parser/ok/0039_raw_fn_item.rast
index d38a60665..17be2c238 100644
--- a/crates/ra_syntax/test_data/parser/ok/0039_raw_fn_item.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0039_raw_fn_item.rast
@@ -9,8 +9,7 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n"
14 [email protected] "\n" 14 [email protected] "}"
15 [email protected] "}"
16 [email protected] "\n" 15 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0041_raw_keywords.rast b/crates/ra_syntax/test_data/parser/ok/0041_raw_keywords.rast
index db25bc2b8..acf32a852 100644
--- a/crates/ra_syntax/test_data/parser/ok/0041_raw_keywords.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0041_raw_keywords.rast
@@ -9,42 +9,41 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] " "
14 [email protected] " " 14 [email protected]
15 [email protected] 15 [email protected] "let"
16 [email protected] "let" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "r#struct"
20 [email protected] "r#struct" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "="
22 [email protected] "=" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected] "92"
25 [email protected] "92" 25 [email protected] ";"
26 [email protected] ";" 26 [email protected] " "
27 [email protected] " " 27 [email protected]
28 [email protected] 28 [email protected] "let"
29 [email protected] "let" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected] "r#trait"
33 [email protected] "r#trait" 33 [email protected] " "
34 [email protected] " " 34 [email protected] "="
35 [email protected] "=" 35 [email protected] " "
36 [email protected] " " 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "r#struct"
42 [email protected] "r#struct" 42 [email protected] " "
43 [email protected] " " 43 [email protected] "*"
44 [email protected] "*" 44 [email protected] " "
45 [email protected] " " 45 [email protected]
46 [email protected] 46 [email protected] "2"
47 [email protected] "2" 47 [email protected] ";"
48 [email protected] ";" 48 [email protected] " "
49 [email protected] " " 49 [email protected] "}"
50 [email protected] "}"
diff --git a/crates/ra_syntax/test_data/parser/ok/0042_ufcs_call_list.rast b/crates/ra_syntax/test_data/parser/ok/0042_ufcs_call_list.rast
index 9704bea95..468982b74 100644
--- a/crates/ra_syntax/test_data/parser/ok/0042_ufcs_call_list.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0042_ufcs_call_list.rast
@@ -39,20 +39,19 @@ [email protected]
39 [email protected] "bool" 39 [email protected] "bool"
40 [email protected] " " 40 [email protected] " "
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected] "{"
43 [email protected] "{" 43 [email protected] "\n "
44 [email protected] "\n " 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "unimplemented"
49 [email protected] "unimplemented" 49 [email protected] "!"
50 [email protected] "!" 50 [email protected]
51 [email protected] 51 [email protected] "("
52 [email protected] "(" 52 [email protected] ")"
53 [email protected] ")" 53 [email protected] "\n "
54 [email protected] "\n " 54 [email protected] "}"
55 [email protected] "}"
56 [email protected] "\n" 55 [email protected] "\n"
57 [email protected] "}" 56 [email protected] "}"
58 [email protected] "\n\n" 57 [email protected] "\n\n"
@@ -76,9 +75,8 @@ [email protected]
76 [email protected] ")" 75 [email protected] ")"
77 [email protected] " " 76 [email protected] " "
78 [email protected] 77 [email protected]
79 [email protected] 78 [email protected] "{"
80 [email protected] "{" 79 [email protected] "}"
81 [email protected] "}"
82 [email protected] "\n\n" 80 [email protected] "\n\n"
83 [email protected] 81 [email protected]
84 [email protected] "fn" 82 [email protected] "fn"
@@ -90,37 +88,36 @@ [email protected]
90 [email protected] ")" 88 [email protected] ")"
91 [email protected] " " 89 [email protected] " "
92 [email protected] 90 [email protected]
93 [email protected] 91 [email protected] "{"
94 [email protected] "{" 92 [email protected] "\n "
95 [email protected] "\n " 93 [email protected]
96 [email protected] 94 [email protected]
97 [email protected] 95 [email protected]
98 [email protected] 96 [email protected]
99 [email protected] 97 [email protected]
100 [email protected] 98 [email protected] "baz"
101 [email protected] "baz" 99 [email protected]
102 [email protected] 100 [email protected] "("
103 [email protected] "(" 101 [email protected]
104 [email protected] 102 [email protected]
105 [email protected] 103 [email protected]
106 [email protected] 104 [email protected]
107 [email protected] 105 [email protected]
108 [email protected] 106 [email protected] "<"
109 [email protected] "<" 107 [email protected]
110 [email protected] 108 [email protected]
111 [email protected] 109 [email protected]
112 [email protected] 110 [email protected]
113 [email protected] 111 [email protected] "Foo"
114 [email protected] "Foo" 112 [email protected] ">"
115 [email protected] ">" 113 [email protected] "::"
116 [email protected] "::" 114 [email protected]
117 [email protected] 115 [email protected]
118 [email protected] 116 [email protected] "bar"
119 [email protected] "bar" 117 [email protected]
120 [email protected] 118 [email protected] "("
121 [email protected] "(" 119 [email protected] ")"
122 [email protected] ")" 120 [email protected] ")"
123 [email protected] ")" 121 [email protected] "\n"
124 [email protected] "\n" 122 [email protected] "}"
125 [email protected] "}"
126 [email protected] "\n" 123 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.rast b/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.rast
index 6e5b25748..900eeb445 100644
--- a/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0043_complex_assignment.rast
@@ -40,71 +40,70 @@ [email protected]
40 [email protected] ")" 40 [email protected] ")"
41 [email protected] " " 41 [email protected] " "
42 [email protected] 42 [email protected]
43 [email protected] 43 [email protected] "{"
44 [email protected] "{" 44 [email protected] "\n "
45 [email protected] "\n " 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected] "Repr"
54 [email protected] "Repr" 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] 56 [email protected] "{"
57 [email protected] "{" 57 [email protected] " "
58 [email protected] " " 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected] "raw"
61 [email protected] "raw" 61 [email protected] ":"
62 [email protected] ":" 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected] "["
65 [email protected] "[" 65 [email protected]
66 [email protected] 66 [email protected] "0"
67 [email protected] "0" 67 [email protected] "]"
68 [email protected] "]" 68 [email protected] " "
69 [email protected] " " 69 [email protected] "}"
70 [email protected] "}" 70 [email protected] "."
71 [email protected] "." 71 [email protected]
72 [email protected] 72 [email protected] "raw"
73 [email protected] "raw" 73 [email protected] "["
74 [email protected] "[" 74 [email protected]
75 [email protected] 75 [email protected] "0"
76 [email protected] "0" 76 [email protected] "]"
77 [email protected] "]" 77 [email protected] " "
78 [email protected] " " 78 [email protected] "="
79 [email protected] "=" 79 [email protected] " "
80 [email protected] " " 80 [email protected]
81 [email protected] 81 [email protected] "0"
82 [email protected] "0" 82 [email protected] ";"
83 [email protected] ";" 83 [email protected] "\n "
84 [email protected] "\n " 84 [email protected]
85 [email protected] 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected]
88 [email protected] 88 [email protected]
89 [email protected] 89 [email protected]
90 [email protected] 90 [email protected] "Repr"
91 [email protected] "Repr" 91 [email protected]
92 [email protected] 92 [email protected] "{"
93 [email protected] "{" 93 [email protected]
94 [email protected] 94 [email protected]
95 [email protected] 95 [email protected] "raw"
96 [email protected] "raw" 96 [email protected] ":"
97 [email protected] ":" 97 [email protected]
98 [email protected] 98 [email protected] "["
99 [email protected] "[" 99 [email protected]
100 [email protected] 100 [email protected] "0"
101 [email protected] "0" 101 [email protected] "]"
102 [email protected] "]" 102 [email protected] "}"
103 [email protected] "}" 103 [email protected]
104 [email protected] 104 [email protected] "("
105 [email protected] "(" 105 [email protected] ")"
106 [email protected] ")" 106 [email protected] ";"
107 [email protected] ";" 107 [email protected] "\n"
108 [email protected] "\n" 108 [email protected] "}"
109 [email protected] "}"
110 [email protected] "\n" 109 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0044_let_attrs.rast b/crates/ra_syntax/test_data/parser/ok/0044_let_attrs.rast
index f1eef3be0..6d941487b 100644
--- a/crates/ra_syntax/test_data/parser/ok/0044_let_attrs.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0044_let_attrs.rast
@@ -11,66 +11,65 @@ [email protected]
11 [email protected] ")" 11 [email protected] ")"
12 [email protected] " " 12 [email protected] " "
13 [email protected] 13 [email protected]
14 [email protected] 14 [email protected] "{"
15 [email protected] "{" 15 [email protected] "\n "
16 [email protected] "\n " 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected] "#"
19 [email protected] "#" 19 [email protected] "["
20 [email protected] "[" 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected] "cfg"
24 [email protected] "cfg" 24 [email protected]
25 [email protected] 25 [email protected] "("
26 [email protected] "(" 26 [email protected] "feature"
27 [email protected] "feature" 27 [email protected] " "
28 [email protected] " " 28 [email protected] "="
29 [email protected] "=" 29 [email protected] " "
30 [email protected] " " 30 [email protected] "\"backtrace\""
31 [email protected] "\"backtrace\"" 31 [email protected] ")"
32 [email protected] ")" 32 [email protected] "]"
33 [email protected] "]" 33 [email protected] "\n "
34 [email protected] "\n " 34 [email protected] "let"
35 [email protected] "let" 35 [email protected] " "
36 [email protected] " " 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "exit_code"
39 [email protected] "exit_code" 39 [email protected] " "
40 [email protected] " " 40 [email protected] "="
41 [email protected] "=" 41 [email protected] " "
42 [email protected] " " 42 [email protected]
43 [email protected] 43 [email protected]
44 [email protected] 44 [email protected]
45 [email protected] 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected] "panic"
49 [email protected] "panic" 49 [email protected] "::"
50 [email protected] "::" 50 [email protected]
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "catch_unwind"
53 [email protected] "catch_unwind" 53 [email protected]
54 [email protected] 54 [email protected] "("
55 [email protected] "(" 55 [email protected]
56 [email protected] 56 [email protected] "move"
57 [email protected] "move" 57 [email protected] " "
58 [email protected] " " 58 [email protected]
59 [email protected] 59 [email protected] "|"
60 [email protected] "|" 60 [email protected] "|"
61 [email protected] "|" 61 [email protected] " "
62 [email protected] " " 62 [email protected]
63 [email protected] 63 [email protected]
64 [email protected] 64 [email protected]
65 [email protected] 65 [email protected]
66 [email protected] 66 [email protected]
67 [email protected] 67 [email protected] "main"
68 [email protected] "main" 68 [email protected]
69 [email protected] 69 [email protected] "("
70 [email protected] "(" 70 [email protected] ")"
71 [email protected] ")" 71 [email protected] ")"
72 [email protected] ")" 72 [email protected] ";"
73 [email protected] ";" 73 [email protected] "\n"
74 [email protected] "\n" 74 [email protected] "}"
75 [email protected] "}"
76 [email protected] "\n" 75 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.rast b/crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.rast
index f79feec19..e8b095251 100644
--- a/crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.rast
@@ -9,86 +9,83 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "#"
16 [email protected] "#" 16 [email protected] "!"
17 [email protected] "!" 17 [email protected] "["
18 [email protected] "[" 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected] "doc"
22 [email protected] "doc" 22 [email protected]
23 [email protected] 23 [email protected] "("
24 [email protected] "(" 24 [email protected] "\"Inner attributes all ..."
25 [email protected] "\"Inner attributes all ..." 25 [email protected] ")"
26 [email protected] ")" 26 [email protected] "]"
27 [email protected] "]" 27 [email protected] "\n "
28 [email protected] "\n " 28 [email protected] "//! As are ModuleDoc ..."
29 [email protected] "//! As are ModuleDoc ..." 29 [email protected] "\n "
30 [email protected] "\n " 30 [email protected]
31 [email protected] 31 [email protected]
32 [email protected] 32 [email protected] "{"
33 [email protected] 33 [email protected] "\n "
34 [email protected] "{" 34 [email protected]
35 [email protected] "\n " 35 [email protected] "#"
36 [email protected] 36 [email protected] "!"
37 [email protected] "#" 37 [email protected] "["
38 [email protected] "!" 38 [email protected]
39 [email protected] "[" 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "doc"
42 [email protected] 42 [email protected]
43 [email protected] "doc" 43 [email protected] "("
44 [email protected] 44 [email protected] "\"Inner attributes are ..."
45 [email protected] "(" 45 [email protected] ")"
46 [email protected] "\"Inner attributes are ..." 46 [email protected] "]"
47 [email protected] ")" 47 [email protected] "\n "
48 [email protected] "]" 48 [email protected]
49 [email protected] "\n " 49 [email protected] "#"
50 [email protected] 50 [email protected] "!"
51 [email protected] "#" 51 [email protected] "["
52 [email protected] "!" 52 [email protected]
53 [email protected] "[" 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected] "doc"
56 [email protected] 56 [email protected]
57 [email protected] "doc" 57 [email protected] "("
58 [email protected] 58 [email protected] "\"Being validated is n ..."
59 [email protected] "(" 59 [email protected] ")"
60 [email protected] "\"Being validated is n ..." 60 [email protected] "]"
61 [email protected] ")" 61 [email protected] "\n "
62 [email protected] "]" 62 [email protected] "//! As are ModuleDoc ..."
63 [email protected] "\n " 63 [email protected] "\n "
64 [email protected] "//! As are ModuleDoc ..." 64 [email protected] "}"
65 [email protected] "\n " 65 [email protected] ";"
66 [email protected] "}" 66 [email protected] "\n "
67 [email protected] ";" 67 [email protected]
68 [email protected] "\n " 68 [email protected] "{"
69 [email protected] 69 [email protected] "\n "
70 [email protected] 70 [email protected]
71 [email protected] "{" 71 [email protected] "#"
72 [email protected] "\n " 72 [email protected] "!"
73 [email protected] 73 [email protected] "["
74 [email protected] "#" 74 [email protected]
75 [email protected] "!" 75 [email protected]
76 [email protected] "[" 76 [email protected]
77 [email protected] 77 [email protected] "doc"
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected] "("
80 [email protected] "doc" 80 [email protected] "\"Inner attributes are ..."
81 [email protected] 81 [email protected] ")"
82 [email protected] "(" 82 [email protected] "]"
83 [email protected] "\"Inner attributes are ..." 83 [email protected] "\n "
84 [email protected] ")" 84 [email protected] "//! As are ModuleDoc ..."
85 [email protected] "]" 85 [email protected] "\n "
86 [email protected] "\n " 86 [email protected] "}"
87 [email protected] "//! As are ModuleDoc ..." 87 [email protected] "\n"
88 [email protected] "\n " 88 [email protected] "}"
89 [email protected] "}"
90 [email protected] "\n"
91 [email protected] "}"
92 [email protected] "\n\n" 89 [email protected] "\n\n"
93 [email protected] "// https://github.com ..." 90 [email protected] "// https://github.com ..."
94 [email protected] "\n" 91 [email protected] "\n"
@@ -156,26 +153,25 @@ [email protected]
156 [email protected] ")" 153 [email protected] ")"
157 [email protected] " " 154 [email protected] " "
158 [email protected] 155 [email protected]
159 [email protected] 156 [email protected] "{"
160 [email protected] "{" 157 [email protected] "\n "
161 [email protected] "\n " 158 [email protected]
162 [email protected] 159 [email protected] "#"
163 [email protected] "#" 160 [email protected] "!"
164 [email protected] "!" 161 [email protected] "["
165 [email protected] "[" 162 [email protected]
166 [email protected] 163 [email protected]
167 [email protected] 164 [email protected]
168 [email protected] 165 [email protected] "allow"
169 [email protected] "allow" 166 [email protected]
170 [email protected] 167 [email protected] "("
171 [email protected] "(" 168 [email protected] "unused_variables"
172 [email protected] "unused_variables" 169 [email protected] ")"
173 [email protected] ")" 170 [email protected] "]"
174 [email protected] "]" 171 [email protected] " "
175 [email protected] " " 172 [email protected] "// this is `inner_at ..."
176 [email protected] "// this is `inner_at ..." 173 [email protected] "\n "
177 [email protected] "\n " 174 [email protected] "}"
178 [email protected] "}"
179 [email protected] "\n" 175 [email protected] "\n"
180 [email protected] "}" 176 [email protected] "}"
181 [email protected] "\n" 177 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast b/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast
index 1cf12d670..38e44e48a 100644
--- a/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0047_minus_in_inner_pattern.rast
@@ -11,252 +11,250 @@ [email protected]
11 [email protected] ")" 11 [email protected] ")"
12 [email protected] " " 12 [email protected] " "
13 [email protected] 13 [email protected]
14 [email protected] 14 [email protected] "{"
15 [email protected] "{" 15 [email protected] "\n "
16 [email protected] "\n " 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected] "match"
19 [email protected] "match" 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "Some"
26 [email protected] "Some" 26 [email protected]
27 [email protected] 27 [email protected] "("
28 [email protected] "(" 28 [email protected]
29 [email protected] 29 [email protected] "-"
30 [email protected] "-" 30 [email protected]
31 [email protected] 31 [email protected] "1"
32 [email protected] "1" 32 [email protected] ")"
33 [email protected] ")" 33 [email protected] " "
34 [email protected] " " 34 [email protected]
35 [email protected] 35 [email protected] "{"
36 [email protected] "{" 36 [email protected] "\n "
37 [email protected] "\n " 37 [email protected]
38 [email protected] 38 [email protected]
39 [email protected] 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected] "Some"
43 [email protected] "Some" 43 [email protected] "("
44 [email protected] "(" 44 [email protected]
45 [email protected] 45 [email protected] "-"
46 [email protected] "-" 46 [email protected]
47 [email protected] 47 [email protected] "1"
48 [email protected] "1" 48 [email protected] ")"
49 [email protected] ")" 49 [email protected] " "
50 [email protected] " " 50 [email protected] "=>"
51 [email protected] "=>" 51 [email protected] " "
52 [email protected] " " 52 [email protected]
53 [email protected] 53 [email protected] "("
54 [email protected] "(" 54 [email protected] ")"
55 [email protected] ")" 55 [email protected] ","
56 [email protected] "," 56 [email protected] "\n "
57 [email protected] "\n " 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected] "_"
60 [email protected] "_" 60 [email protected] " "
61 [email protected] " " 61 [email protected] "=>"
62 [email protected] "=>" 62 [email protected] " "
63 [email protected] " " 63 [email protected]
64 [email protected] 64 [email protected] "("
65 [email protected] "(" 65 [email protected] ")"
66 [email protected] ")" 66 [email protected] ","
67 [email protected] "," 67 [email protected] "\n "
68 [email protected] "\n " 68 [email protected] "}"
69 [email protected] "}" 69 [email protected] "\n\n "
70 [email protected] "\n\n " 70 [email protected]
71 [email protected] 71 [email protected]
72 [email protected] 72 [email protected] "match"
73 [email protected] "match" 73 [email protected] " "
74 [email protected] " " 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected] "Some"
80 [email protected] "Some" 80 [email protected]
81 [email protected] 81 [email protected] "("
82 [email protected] "(" 82 [email protected]
83 [email protected] 83 [email protected] "("
84 [email protected] "(" 84 [email protected]
85 [email protected] 85 [email protected] "-"
86 [email protected] "-" 86 [email protected]
87 [email protected] 87 [email protected] "1"
88 [email protected] "1" 88 [email protected] ","
89 [email protected] "," 89 [email protected] " "
90 [email protected] " " 90 [email protected]
91 [email protected] 91 [email protected] "-"
92 [email protected] "-" 92 [email protected]
93 [email protected] 93 [email protected] "1"
94 [email protected] "1" 94 [email protected] ")"
95 [email protected] ")" 95 [email protected] ")"
96 [email protected] ")" 96 [email protected] " "
97 [email protected] " " 97 [email protected]
98 [email protected] 98 [email protected] "{"
99 [email protected] "{" 99 [email protected] "\n "
100 [email protected] "\n " 100 [email protected]
101 [email protected] 101 [email protected]
102 [email protected] 102 [email protected]
103 [email protected] 103 [email protected]
104 [email protected] 104 [email protected]
105 [email protected] 105 [email protected] "Some"
106 [email protected] "Some" 106 [email protected] "("
107 [email protected] "(" 107 [email protected]
108 [email protected] 108 [email protected] "("
109 [email protected] "(" 109 [email protected]
110 [email protected] 110 [email protected] "-"
111 [email protected] "-" 111 [email protected]
112 [email protected] 112 [email protected] "1"
113 [email protected] "1" 113 [email protected] ","
114 [email protected] "," 114 [email protected] " "
115 [email protected] " " 115 [email protected]
116 [email protected] 116 [email protected] "-"
117 [email protected] "-" 117 [email protected]
118 [email protected] 118 [email protected] "1"
119 [email protected] "1" 119 [email protected] ")"
120 [email protected] ")" 120 [email protected] ")"
121 [email protected] ")" 121 [email protected] " "
122 [email protected] " " 122 [email protected] "=>"
123 [email protected] "=>" 123 [email protected] " "
124 [email protected] " " 124 [email protected]
125 [email protected] 125 [email protected] "("
126 [email protected] "(" 126 [email protected] ")"
127 [email protected] ")" 127 [email protected] ","
128 [email protected] "," 128 [email protected] "\n "
129 [email protected] "\n " 129 [email protected]
130 [email protected] 130 [email protected]
131 [email protected] 131 [email protected] "_"
132 [email protected] "_" 132 [email protected] " "
133 [email protected] " " 133 [email protected] "=>"
134 [email protected] "=>" 134 [email protected] " "
135 [email protected] " " 135 [email protected]
136 [email protected] 136 [email protected] "("
137 [email protected] "(" 137 [email protected] ")"
138 [email protected] ")" 138 [email protected] ","
139 [email protected] "," 139 [email protected] "\n "
140 [email protected] "\n " 140 [email protected] "}"
141 [email protected] "}" 141 [email protected] "\n\n "
142 [email protected] "\n\n " 142 [email protected]
143 [email protected] 143 [email protected]
144 [email protected] 144 [email protected] "match"
145 [email protected] "match" 145 [email protected] " "
146 [email protected] " " 146 [email protected]
147 [email protected] 147 [email protected]
148 [email protected] 148 [email protected]
149 [email protected] 149 [email protected]
150 [email protected] 150 [email protected]
151 [email protected] 151 [email protected]
152 [email protected] 152 [email protected] "A"
153 [email protected] "A" 153 [email protected] "::"
154 [email protected] "::" 154 [email protected]
155 [email protected] 155 [email protected]
156 [email protected] 156 [email protected] "B"
157 [email protected] "B" 157 [email protected]
158 [email protected] 158 [email protected] "("
159 [email protected] "(" 159 [email protected]
160 [email protected] 160 [email protected] "-"
161 [email protected] "-" 161 [email protected]
162 [email protected] 162 [email protected] "1"
163 [email protected] "1" 163 [email protected] ","
164 [email protected] "," 164 [email protected] " "
165 [email protected] " " 165 [email protected]
166 [email protected] 166 [email protected] "-"
167 [email protected] "-" 167 [email protected]
168 [email protected] 168 [email protected] "1"
169 [email protected] "1" 169 [email protected] ")"
170 [email protected] ")" 170 [email protected] " "
171 [email protected] " " 171 [email protected]
172 [email protected] 172 [email protected] "{"
173 [email protected] "{" 173 [email protected] "\n "
174 [email protected] "\n " 174 [email protected]
175 [email protected] 175 [email protected]
176 [email protected] 176 [email protected]
177 [email protected] 177 [email protected]
178 [email protected] 178 [email protected]
179 [email protected] 179 [email protected]
180 [email protected] 180 [email protected] "A"
181 [email protected] "A" 181 [email protected] "::"
182 [email protected] "::" 182 [email protected]
183 [email protected] 183 [email protected]
184 [email protected] 184 [email protected] "B"
185 [email protected] "B" 185 [email protected] "("
186 [email protected] "(" 186 [email protected]
187 [email protected] 187 [email protected] "-"
188 [email protected] "-" 188 [email protected]
189 [email protected] 189 [email protected] "1"
190 [email protected] "1" 190 [email protected] ","
191 [email protected] "," 191 [email protected] " "
192 [email protected] " " 192 [email protected]
193 [email protected] 193 [email protected] "-"
194 [email protected] "-" 194 [email protected]
195 [email protected] 195 [email protected] "1"
196 [email protected] "1" 196 [email protected] ")"
197 [email protected] ")" 197 [email protected] " "
198 [email protected] " " 198 [email protected] "=>"
199 [email protected] "=>" 199 [email protected] " "
200 [email protected] " " 200 [email protected]
201 [email protected] 201 [email protected] "("
202 [email protected] "(" 202 [email protected] ")"
203 [email protected] ")" 203 [email protected] ","
204 [email protected] "," 204 [email protected] "\n "
205 [email protected] "\n " 205 [email protected]
206 [email protected] 206 [email protected]
207 [email protected] 207 [email protected] "_"
208 [email protected] "_" 208 [email protected] " "
209 [email protected] " " 209 [email protected] "=>"
210 [email protected] "=>" 210 [email protected] " "
211 [email protected] " " 211 [email protected]
212 [email protected] 212 [email protected] "("
213 [email protected] "(" 213 [email protected] ")"
214 [email protected] ")" 214 [email protected] ","
215 [email protected] "," 215 [email protected] "\n "
216 [email protected] "\n " 216 [email protected] "}"
217 [email protected] "}" 217 [email protected] "\n\n "
218 [email protected] "\n\n " 218 [email protected]
219 [email protected] 219 [email protected] "if"
220 [email protected] "if" 220 [email protected] " "
221 [email protected] " " 221 [email protected]
222 [email protected] 222 [email protected] "let"
223 [email protected] "let" 223 [email protected] " "
224 [email protected] " " 224 [email protected]
225 [email protected] 225 [email protected]
226 [email protected] 226 [email protected]
227 [email protected] 227 [email protected]
228 [email protected] 228 [email protected] "Some"
229 [email protected] "Some" 229 [email protected] "("
230 [email protected] "(" 230 [email protected]
231 [email protected] 231 [email protected] "-"
232 [email protected] "-" 232 [email protected]
233 [email protected] 233 [email protected] "1"
234 [email protected] "1" 234 [email protected] ")"
235 [email protected] ")" 235 [email protected] " "
236 [email protected] " " 236 [email protected] "="
237 [email protected] "=" 237 [email protected] " "
238 [email protected] " " 238 [email protected]
239 [email protected] 239 [email protected]
240 [email protected] 240 [email protected]
241 [email protected] 241 [email protected]
242 [email protected] 242 [email protected]
243 [email protected] 243 [email protected] "Some"
244 [email protected] "Some" 244 [email protected]
245 [email protected] 245 [email protected] "("
246 [email protected] "(" 246 [email protected]
247 [email protected] 247 [email protected] "-"
248 [email protected] "-" 248 [email protected]
249 [email protected] 249 [email protected] "1"
250 [email protected] "1" 250 [email protected] ")"
251 [email protected] ")" 251 [email protected] " "
252 [email protected] " " 252 [email protected]
253 [email protected] 253 [email protected] "{"
254 [email protected] 254 [email protected] "\n "
255 [email protected] "{" 255 [email protected] "}"
256 [email protected] "\n " 256 [email protected] "\n"
257 [email protected] "}" 257 [email protected] "}"
258 [email protected] "\n"
259 [email protected] "}"
260 [email protected] "\n\n" 258 [email protected] "\n\n"
261 [email protected] 259 [email protected]
262 [email protected] "enum" 260 [email protected] "enum"
@@ -317,7 +315,6 @@ [email protected]
317 [email protected] ")" 315 [email protected] ")"
318 [email protected] " " 316 [email protected] " "
319 [email protected] 317 [email protected]
320 [email protected] 318 [email protected] "{"
321 [email protected] "{" 319 [email protected] "}"
322 [email protected] "}"
323 [email protected] "\n" 320 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0048_compound_assignment.rast b/crates/ra_syntax/test_data/parser/ok/0048_compound_assignment.rast
index 9c2701bf7..28233c5d0 100644
--- a/crates/ra_syntax/test_data/parser/ok/0048_compound_assignment.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0048_compound_assignment.rast
@@ -11,191 +11,190 @@ [email protected]
11 [email protected] ")" 11 [email protected] ")"
12 [email protected] " " 12 [email protected] " "
13 [email protected] 13 [email protected]
14 [email protected] 14 [email protected] "{"
15 [email protected] "{" 15 [email protected] "\n "
16 [email protected] "\n " 16 [email protected]
17 [email protected] 17 [email protected] "let"
18 [email protected] "let" 18 [email protected] " "
19 [email protected] " " 19 [email protected]
20 [email protected] 20 [email protected] "mut"
21 [email protected] "mut" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "a"
24 [email protected] "a" 24 [email protected] " "
25 [email protected] " " 25 [email protected] "="
26 [email protected] "=" 26 [email protected] " "
27 [email protected] " " 27 [email protected]
28 [email protected] 28 [email protected] "0"
29 [email protected] "0" 29 [email protected] ";"
30 [email protected] ";" 30 [email protected] "\n "
31 [email protected] "\n " 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected] "a"
38 [email protected] "a" 38 [email protected] " "
39 [email protected] " " 39 [email protected] "+="
40 [email protected] "+=" 40 [email protected] " "
41 [email protected] " " 41 [email protected]
42 [email protected] 42 [email protected] "1"
43 [email protected] "1" 43 [email protected] ";"
44 [email protected] ";" 44 [email protected] "\n "
45 [email protected] "\n " 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected]
51 [email protected] 51 [email protected] "a"
52 [email protected] "a" 52 [email protected] " "
53 [email protected] " " 53 [email protected] "-="
54 [email protected] "-=" 54 [email protected] " "
55 [email protected] " " 55 [email protected]
56 [email protected] 56 [email protected] "2"
57 [email protected] "2" 57 [email protected] ";"
58 [email protected] ";" 58 [email protected] "\n "
59 [email protected] "\n " 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected]
62 [email protected] 62 [email protected]
63 [email protected] 63 [email protected]
64 [email protected] 64 [email protected]
65 [email protected] 65 [email protected] "a"
66 [email protected] "a" 66 [email protected] " "
67 [email protected] " " 67 [email protected] "*="
68 [email protected] "*=" 68 [email protected] " "
69 [email protected] " " 69 [email protected]
70 [email protected] 70 [email protected] "3"
71 [email protected] "3" 71 [email protected] ";"
72 [email protected] ";" 72 [email protected] "\n "
73 [email protected] "\n " 73 [email protected]
74 [email protected] 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected] "a"
80 [email protected] "a" 80 [email protected] " "
81 [email protected] " " 81 [email protected] "%="
82 [email protected] "%=" 82 [email protected] " "
83 [email protected] " " 83 [email protected]
84 [email protected] 84 [email protected] "4"
85 [email protected] "4" 85 [email protected] ";"
86 [email protected] ";" 86 [email protected] "\n "
87 [email protected] "\n " 87 [email protected]
88 [email protected] 88 [email protected]
89 [email protected] 89 [email protected]
90 [email protected] 90 [email protected]
91 [email protected] 91 [email protected]
92 [email protected] 92 [email protected]
93 [email protected] 93 [email protected] "a"
94 [email protected] "a" 94 [email protected] " "
95 [email protected] " " 95 [email protected] "/="
96 [email protected] "/=" 96 [email protected] " "
97 [email protected] " " 97 [email protected]
98 [email protected] 98 [email protected] "5"
99 [email protected] "5" 99 [email protected] ";"
100 [email protected] ";" 100 [email protected] "\n "
101 [email protected] "\n " 101 [email protected]
102 [email protected] 102 [email protected]
103 [email protected] 103 [email protected]
104 [email protected] 104 [email protected]
105 [email protected] 105 [email protected]
106 [email protected] 106 [email protected]
107 [email protected] 107 [email protected] "a"
108 [email protected] "a" 108 [email protected] " "
109 [email protected] " " 109 [email protected] "|="
110 [email protected] "|=" 110 [email protected] " "
111 [email protected] " " 111 [email protected]
112 [email protected] 112 [email protected] "6"
113 [email protected] "6" 113 [email protected] ";"
114 [email protected] ";" 114 [email protected] "\n "
115 [email protected] "\n " 115 [email protected]
116 [email protected] 116 [email protected]
117 [email protected] 117 [email protected]
118 [email protected] 118 [email protected]
119 [email protected] 119 [email protected]
120 [email protected] 120 [email protected]
121 [email protected] 121 [email protected] "a"
122 [email protected] "a" 122 [email protected] " "
123 [email protected] " " 123 [email protected] "&="
124 [email protected] "&=" 124 [email protected] " "
125 [email protected] " " 125 [email protected]
126 [email protected] 126 [email protected] "7"
127 [email protected] "7" 127 [email protected] ";"
128 [email protected] ";" 128 [email protected] "\n "
129 [email protected] "\n " 129 [email protected]
130 [email protected] 130 [email protected]
131 [email protected] 131 [email protected]
132 [email protected] 132 [email protected]
133 [email protected] 133 [email protected]
134 [email protected] 134 [email protected]
135 [email protected] 135 [email protected] "a"
136 [email protected] "a" 136 [email protected] " "
137 [email protected] " " 137 [email protected] "^="
138 [email protected] "^=" 138 [email protected] " "
139 [email protected] " " 139 [email protected]
140 [email protected] 140 [email protected] "8"
141 [email protected] "8" 141 [email protected] ";"
142 [email protected] ";" 142 [email protected] "\n "
143 [email protected] "\n " 143 [email protected]
144 [email protected] 144 [email protected]
145 [email protected] 145 [email protected]
146 [email protected] 146 [email protected]
147 [email protected] 147 [email protected]
148 [email protected] 148 [email protected]
149 [email protected] 149 [email protected] "a"
150 [email protected] "a" 150 [email protected] " "
151 [email protected] " " 151 [email protected] "<="
152 [email protected] "<=" 152 [email protected] " "
153 [email protected] " " 153 [email protected]
154 [email protected] 154 [email protected] "9"
155 [email protected] "9" 155 [email protected] ";"
156 [email protected] ";" 156 [email protected] "\n "
157 [email protected] "\n " 157 [email protected]
158 [email protected] 158 [email protected]
159 [email protected] 159 [email protected]
160 [email protected] 160 [email protected]
161 [email protected] 161 [email protected]
162 [email protected] 162 [email protected]
163 [email protected] 163 [email protected] "a"
164 [email protected] "a" 164 [email protected] " "
165 [email protected] " " 165 [email protected] ">="
166 [email protected] ">=" 166 [email protected] " "
167 [email protected] " " 167 [email protected]
168 [email protected] 168 [email protected] "10"
169 [email protected] "10" 169 [email protected] ";"
170 [email protected] ";" 170 [email protected] "\n "
171 [email protected] "\n " 171 [email protected]
172 [email protected] 172 [email protected]
173 [email protected] 173 [email protected]
174 [email protected] 174 [email protected]
175 [email protected] 175 [email protected]
176 [email protected] 176 [email protected]
177 [email protected] 177 [email protected] "a"
178 [email protected] "a" 178 [email protected] " "
179 [email protected] " " 179 [email protected] ">>="
180 [email protected] ">>=" 180 [email protected] " "
181 [email protected] " " 181 [email protected]
182 [email protected] 182 [email protected] "11"
183 [email protected] "11" 183 [email protected] ";"
184 [email protected] ";" 184 [email protected] "\n "
185 [email protected] "\n " 185 [email protected]
186 [email protected] 186 [email protected]
187 [email protected] 187 [email protected]
188 [email protected] 188 [email protected]
189 [email protected] 189 [email protected]
190 [email protected] 190 [email protected]
191 [email protected] 191 [email protected] "a"
192 [email protected] "a" 192 [email protected] " "
193 [email protected] " " 193 [email protected] "<<="
194 [email protected] "<<=" 194 [email protected] " "
195 [email protected] " " 195 [email protected]
196 [email protected] 196 [email protected] "12"
197 [email protected] "12" 197 [email protected] ";"
198 [email protected] ";" 198 [email protected] "\n"
199 [email protected] "\n" 199 [email protected] "}"
200 [email protected] "}"
201 [email protected] "\n" 200 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0049_async_block.rast b/crates/ra_syntax/test_data/parser/ok/0049_async_block.rast
index 750527bb9..0569488f8 100644
--- a/crates/ra_syntax/test_data/parser/ok/0049_async_block.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0049_async_block.rast
@@ -9,28 +9,27 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected] "async"
17 [email protected] "async" 17 [email protected] " "
18 [email protected] " " 18 [email protected]
19 [email protected] 19 [email protected] "{"
20 [email protected] "{" 20 [email protected] "}"
21 [email protected] "}" 21 [email protected] ";"
22 [email protected] ";" 22 [email protected] "\n "
23 [email protected] "\n " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "async"
26 [email protected] "async" 26 [email protected] " "
27 [email protected] " " 27 [email protected] "move"
28 [email protected] "move" 28 [email protected] " "
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected] "{"
31 [email protected] "{" 31 [email protected] "}"
32 [email protected] "}" 32 [email protected] ";"
33 [email protected] ";" 33 [email protected] "\n"
34 [email protected] "\n" 34 [email protected] "}"
35 [email protected] "}"
36 [email protected] "\n\n" 35 [email protected] "\n\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0050_async_block_as_argument.rast b/crates/ra_syntax/test_data/parser/ok/0050_async_block_as_argument.rast
index b5577e933..7847da085 100644
--- a/crates/ra_syntax/test_data/parser/ok/0050_async_block_as_argument.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0050_async_block_as_argument.rast
@@ -49,9 +49,8 @@ [email protected]
49 [email protected] ")" 49 [email protected] ")"
50 [email protected] " " 50 [email protected] " "
51 [email protected] 51 [email protected]
52 [email protected] 52 [email protected] "{"
53 [email protected] "{" 53 [email protected] "}"
54 [email protected] "}"
55 [email protected] "\n\n" 54 [email protected] "\n\n"
56 [email protected] 55 [email protected]
57 [email protected] "fn" 56 [email protected] "fn"
@@ -63,30 +62,29 @@ [email protected]
63 [email protected] ")" 62 [email protected] ")"
64 [email protected] " " 63 [email protected] " "
65 [email protected] 64 [email protected]
66 [email protected] 65 [email protected] "{"
67 [email protected] "{" 66 [email protected] "\n "
68 [email protected] "\n " 67 [email protected]
69 [email protected] 68 [email protected]
70 [email protected] 69 [email protected]
71 [email protected] 70 [email protected]
72 [email protected] 71 [email protected]
73 [email protected] 72 [email protected] "foo"
74 [email protected] "foo" 73 [email protected]
75 [email protected] 74 [email protected] "("
76 [email protected] "(" 75 [email protected]
77 [email protected] 76 [email protected] "async"
78 [email protected] "async" 77 [email protected] " "
79 [email protected] " " 78 [email protected] "move"
80 [email protected] "move" 79 [email protected] " "
81 [email protected] " " 80 [email protected]
82 [email protected] 81 [email protected] "{"
83 [email protected] "{" 82 [email protected] " "
84 [email protected] " " 83 [email protected]
85 [email protected] 84 [email protected] "12"
86 [email protected] "12" 85 [email protected] " "
87 [email protected] " " 86 [email protected] "}"
88 [email protected] "}" 87 [email protected] ")"
89 [email protected] ")" 88 [email protected] "\n"
90 [email protected] "\n" 89 [email protected] "}"
91 [email protected] "}"
92 [email protected] "\n" 90 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast b/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast
index 6aacc2141..816740a7c 100644
--- a/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.rast
@@ -38,9 +38,8 @@ [email protected]
38 [email protected] ")" 38 [email protected] ")"
39 [email protected] " " 39 [email protected] " "
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "{"
42 [email protected] "{" 42 [email protected] "}"
43 [email protected] "}"
44 [email protected] "\n" 43 [email protected] "\n"
45 [email protected] 44 [email protected]
46 [email protected] "fn" 45 [email protected] "fn"
@@ -72,9 +71,8 @@ [email protected]
72 [email protected] ")" 71 [email protected] ")"
73 [email protected] " " 72 [email protected] " "
74 [email protected] 73 [email protected]
75 [email protected] 74 [email protected] "{"
76 [email protected] "{" 75 [email protected] "}"
77 [email protected] "}"
78 [email protected] "\n\n" 76 [email protected] "\n\n"
79 [email protected] 77 [email protected]
80 [email protected] 78 [email protected]
@@ -185,9 +183,8 @@ [email protected]
185 [email protected] "(" 183 [email protected] "("
186 [email protected] ")" 184 [email protected] ")"
187 [email protected] 185 [email protected]
188 [email protected] 186 [email protected] "{"
189 [email protected] "{" 187 [email protected] "}"
190 [email protected] "}"
191 [email protected] "\n\n" 188 [email protected] "\n\n"
192 [email protected] 189 [email protected]
193 [email protected] "trait" 190 [email protected] "trait"
@@ -287,9 +284,8 @@ [email protected]
287 [email protected] ")" 284 [email protected] ")"
288 [email protected] " " 285 [email protected] " "
289 [email protected] 286 [email protected]
290 [email protected] 287 [email protected] "{"
291 [email protected] "{" 288 [email protected] "}"
292 [email protected] "}"
293 [email protected] "\n " 289 [email protected] "\n "
294 [email protected] 290 [email protected]
295 [email protected] "fn" 291 [email protected] "fn"
@@ -312,9 +308,8 @@ [email protected]
312 [email protected] ")" 308 [email protected] ")"
313 [email protected] " " 309 [email protected] " "
314 [email protected] 310 [email protected]
315 [email protected] 311 [email protected] "{"
316 [email protected] "{" 312 [email protected] "}"
317 [email protected] "}"
318 [email protected] "\n " 313 [email protected] "\n "
319 [email protected] 314 [email protected]
320 [email protected] "fn" 315 [email protected] "fn"
@@ -338,9 +333,8 @@ [email protected]
338 [email protected] ")" 333 [email protected] ")"
339 [email protected] " " 334 [email protected] " "
340 [email protected] 335 [email protected]
341 [email protected] 336 [email protected] "{"
342 [email protected] "{" 337 [email protected] "}"
343 [email protected] "}"
344 [email protected] "\n " 338 [email protected] "\n "
345 [email protected] 339 [email protected]
346 [email protected] "fn" 340 [email protected] "fn"
@@ -371,9 +365,8 @@ [email protected]
371 [email protected] ")" 365 [email protected] ")"
372 [email protected] " " 366 [email protected] " "
373 [email protected] 367 [email protected]
374 [email protected] 368 [email protected] "{"
375 [email protected] "{" 369 [email protected] "}"
376 [email protected] "}"
377 [email protected] "\n " 370 [email protected] "\n "
378 [email protected] 371 [email protected]
379 [email protected] "fn" 372 [email protected] "fn"
@@ -404,9 +397,8 @@ [email protected]
404 [email protected] ")" 397 [email protected] ")"
405 [email protected] " " 398 [email protected] " "
406 [email protected] 399 [email protected]
407 [email protected] 400 [email protected] "{"
408 [email protected] "{" 401 [email protected] "}"
409 [email protected] "}"
410 [email protected] "\n " 402 [email protected] "\n "
411 [email protected] 403 [email protected]
412 [email protected] "fn" 404 [email protected] "fn"
@@ -439,9 +431,8 @@ [email protected]
439 [email protected] ")" 431 [email protected] ")"
440 [email protected] " " 432 [email protected] " "
441 [email protected] 433 [email protected]
442 [email protected] 434 [email protected] "{"
443 [email protected] "{" 435 [email protected] "}"
444 [email protected] "}"
445 [email protected] "\n " 436 [email protected] "\n "
446 [email protected] 437 [email protected]
447 [email protected] "fn" 438 [email protected] "fn"
@@ -471,9 +462,8 @@ [email protected]
471 [email protected] ")" 462 [email protected] ")"
472 [email protected] " " 463 [email protected] " "
473 [email protected] 464 [email protected]
474 [email protected] 465 [email protected] "{"
475 [email protected] "{" 466 [email protected] "}"
476 [email protected] "}"
477 [email protected] "\n " 467 [email protected] "\n "
478 [email protected] 468 [email protected]
479 [email protected] "fn" 469 [email protected] "fn"
@@ -512,8 +502,7 @@ [email protected]
512 [email protected] ")" 502 [email protected] ")"
513 [email protected] " " 503 [email protected] " "
514 [email protected] 504 [email protected]
515 [email protected] 505 [email protected] "{"
516 [email protected] "{" 506 [email protected] "}"
517 [email protected] "}"
518 [email protected] "\n" 507 [email protected] "\n"
519 [email protected] "}" 508 [email protected] "}"
diff --git a/crates/ra_syntax/test_data/parser/ok/0052_for_range_block.rast b/crates/ra_syntax/test_data/parser/ok/0052_for_range_block.rast
index f376f86a7..65cfa7bc5 100644
--- a/crates/ra_syntax/test_data/parser/ok/0052_for_range_block.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0052_for_range_block.rast
@@ -9,73 +9,70 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "for"
16 [email protected] "for" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected] "_x"
20 [email protected] "_x" 20 [email protected] " "
21 [email protected] " " 21 [email protected] "in"
22 [email protected] "in" 22 [email protected] " "
23 [email protected] " " 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "0"
26 [email protected] "0" 26 [email protected] " "
27 [email protected] " " 27 [email protected] ".."
28 [email protected] ".." 28 [email protected] " "
29 [email protected] " " 29 [email protected]
30 [email protected] 30 [email protected]
31 [email protected] 31 [email protected] "("
32 [email protected] "(" 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected] "0"
35 [email protected] "0" 35 [email protected] " "
36 [email protected] " " 36 [email protected] ".."
37 [email protected] ".." 37 [email protected] " "
38 [email protected] " " 38 [email protected]
39 [email protected] 39 [email protected] "{"
40 [email protected] 40 [email protected]
41 [email protected] "{" 41 [email protected]
42 [email protected] 42 [email protected] "1"
43 [email protected] 43 [email protected] " "
44 [email protected] "1" 44 [email protected] "+"
45 [email protected] " " 45 [email protected] " "
46 [email protected] "+" 46 [email protected]
47 [email protected] " " 47 [email protected] "2"
48 [email protected] 48 [email protected] "}"
49 [email protected] "2" 49 [email protected] ")"
50 [email protected] "}" 50 [email protected] "."
51 [email protected] ")" 51 [email protected]
52 [email protected] "." 52 [email protected] "sum"
53 [email protected] 53 [email protected]
54 [email protected] "sum" 54 [email protected] "::"
55 [email protected] 55 [email protected] "<"
56 [email protected] "::" 56 [email protected]
57 [email protected] "<" 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected] "u32"
62 [email protected] 62 [email protected] ">"
63 [email protected] "u32" 63 [email protected]
64 [email protected] ">" 64 [email protected] "("
65 [email protected] 65 [email protected] ")"
66 [email protected] "(" 66 [email protected] " "
67 [email protected] ")" 67 [email protected]
68 [email protected] " " 68 [email protected] "{"
69 [email protected] 69 [email protected] "\n "
70 [email protected] 70 [email protected]
71 [email protected] "{" 71 [email protected]
72 [email protected] "\n " 72 [email protected] "break"
73 [email protected] 73 [email protected] ";"
74 [email protected] 74 [email protected] "\n "
75 [email protected] "break" 75 [email protected] "}"
76 [email protected] ";" 76 [email protected] "\n"
77 [email protected] "\n " 77 [email protected] "}"
78 [email protected] "}"
79 [email protected] "\n"
80 [email protected] "}"
81 [email protected] "\n" 78 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast b/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast
index f20819bd2..d6aec7ab9 100644
--- a/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0054_qual_path_in_type_arg.rast
@@ -32,9 +32,8 @@ [email protected]
32 [email protected] ">" 32 [email protected] ">"
33 [email protected] " " 33 [email protected] " "
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "{"
36 [email protected] "{" 36 [email protected] "}"
37 [email protected] "}"
38 [email protected] "\n\n" 37 [email protected] "\n\n"
39 [email protected] 38 [email protected]
40 [email protected] "fn" 39 [email protected] "fn"
@@ -75,9 +74,8 @@ [email protected]
75 [email protected] ")" 74 [email protected] ")"
76 [email protected] " " 75 [email protected] " "
77 [email protected] 76 [email protected]
78 [email protected] 77 [email protected] "{"
79 [email protected] "{" 78 [email protected] "}"
80 [email protected] "}"
81 [email protected] "\n\n" 79 [email protected] "\n\n"
82 [email protected] 80 [email protected]
83 [email protected] "fn" 81 [email protected] "fn"
@@ -120,7 +118,6 @@ [email protected]
120 [email protected] ")" 118 [email protected] ")"
121 [email protected] " " 119 [email protected] " "
122 [email protected] 120 [email protected]
123 [email protected] 121 [email protected] "{"
124 [email protected] "{" 122 [email protected] "}"
125 [email protected] "}"
126 [email protected] "\n" 123 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rast b/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rast
index dcdb3cc6d..9e0cec35f 100644
--- a/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0055_dot_dot_dot.rast
@@ -22,29 +22,28 @@ [email protected]
22 [email protected] ")" 22 [email protected] ")"
23 [email protected] " " 23 [email protected] " "
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected] "{"
26 [email protected] "{" 26 [email protected] "\n "
27 [email protected] "\n " 27 [email protected]
28 [email protected] 28 [email protected] "let"
29 [email protected] "let" 29 [email protected] " "
30 [email protected] " " 30 [email protected]
31 [email protected] 31 [email protected] "("
32 [email protected] "(" 32 [email protected] ")"
33 [email protected] ")" 33 [email protected] ":"
34 [email protected] ":" 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected] "::"
38 [email protected] "::" 38 [email protected]
39 [email protected] 39 [email protected] "X"
40 [email protected] "X" 40 [email protected] " "
41 [email protected] " " 41 [email protected] "="
42 [email protected] "=" 42 [email protected] " "
43 [email protected] " " 43 [email protected]
44 [email protected] 44 [email protected] "("
45 [email protected] "(" 45 [email protected] ")"
46 [email protected] ")" 46 [email protected] ";"
47 [email protected] ";" 47 [email protected] "\n"
48 [email protected] "\n" 48 [email protected] "}"
49 [email protected] "}"
50 [email protected] "\n" 49 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.rast b/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.rast
index 6176a9620..7fa3033ac 100644
--- a/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.rast
@@ -9,58 +9,56 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "if"
16 [email protected] "if" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected]
21 [email protected] 21 [email protected]
22 [email protected] 22 [email protected] "1.0f32"
23 [email protected] "1.0f32" 23 [email protected] "."
24 [email protected] "." 24 [email protected]
25 [email protected] 25 [email protected] "floor"
26 [email protected] "floor" 26 [email protected]
27 [email protected] 27 [email protected] "("
28 [email protected] "(" 28 [email protected] ")"
29 [email protected] ")" 29 [email protected] " "
30 [email protected] " " 30 [email protected] "as"
31 [email protected] "as" 31 [email protected] " "
32 [email protected] " " 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected]
36 [email protected] 36 [email protected] "i64"
37 [email protected] "i64" 37 [email protected] " "
38 [email protected] " " 38 [email protected] "!="
39 [email protected] "!=" 39 [email protected] " "
40 [email protected] " " 40 [email protected]
41 [email protected] 41 [email protected]
42 [email protected] 42 [email protected]
43 [email protected] 43 [email protected] "1.0f32"
44 [email protected] "1.0f32" 44 [email protected] "."
45 [email protected] "." 45 [email protected]
46 [email protected] 46 [email protected] "floor"
47 [email protected] "floor" 47 [email protected]
48 [email protected] 48 [email protected] "("
49 [email protected] "(" 49 [email protected] ")"
50 [email protected] ")" 50 [email protected] " "
51 [email protected] " " 51 [email protected] "as"
52 [email protected] "as" 52 [email protected] " "
53 [email protected] " " 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected]
56 [email protected] 56 [email protected]
57 [email protected] 57 [email protected] "i64"
58 [email protected] "i64" 58 [email protected] " "
59 [email protected] " " 59 [email protected]
60 [email protected] 60 [email protected] "{"
61 [email protected] 61 [email protected] "}"
62 [email protected] "{" 62 [email protected] "\n"
63 [email protected] "}" 63 [email protected] "}"
64 [email protected] "\n"
65 [email protected] "}"
66 [email protected] "\n" 64 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0057_loop_in_call.rast b/crates/ra_syntax/test_data/parser/ok/0057_loop_in_call.rast
index 342fe23f5..d93968016 100644
--- a/crates/ra_syntax/test_data/parser/ok/0057_loop_in_call.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0057_loop_in_call.rast
@@ -20,9 +20,8 @@ [email protected]
20 [email protected] ")" 20 [email protected] ")"
21 [email protected] " " 21 [email protected] " "
22 [email protected] 22 [email protected]
23 [email protected] 23 [email protected] "{"
24 [email protected] "{" 24 [email protected] "}"
25 [email protected] "}"
26 [email protected] "\n\n" 25 [email protected] "\n\n"
27 [email protected] 26 [email protected]
28 [email protected] "fn" 27 [email protected] "fn"
@@ -34,26 +33,24 @@ [email protected]
34 [email protected] ")" 33 [email protected] ")"
35 [email protected] " " 34 [email protected] " "
36 [email protected] 35 [email protected]
37 [email protected] 36 [email protected] "{"
38 [email protected] "{" 37 [email protected] "\n "
39 [email protected] "\n " 38 [email protected]
40 [email protected] 39 [email protected]
41 [email protected] 40 [email protected]
42 [email protected] 41 [email protected]
43 [email protected] 42 [email protected]
44 [email protected] 43 [email protected]
45 [email protected] 44 [email protected] "foo"
46 [email protected] "foo" 45 [email protected]
47 [email protected] 46 [email protected] "("
48 [email protected] "(" 47 [email protected]
49 [email protected] 48 [email protected] "loop"
50 [email protected] "loop" 49 [email protected] " "
51 [email protected] " " 50 [email protected]
52 [email protected] 51 [email protected] "{"
53 [email protected] 52 [email protected] "}"
54 [email protected] "{" 53 [email protected] ")"
55 [email protected] "}" 54 [email protected] ";"
56 [email protected] ")" 55 [email protected] "\n"
57 [email protected] ";" 56 [email protected] "}"
58 [email protected] "\n"
59 [email protected] "}"
diff --git a/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rast b/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rast
index 360b6e044..b5c72ee36 100644
--- a/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rast
@@ -9,89 +9,88 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected] "1"
19 [email protected] "1" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "+"
21 [email protected] "+" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected] "*"
24 [email protected] "*" 24 [email protected]
25 [email protected] 25 [email protected] "&"
26 [email protected] "&" 26 [email protected]
27 [email protected] 27 [email protected] "2"
28 [email protected] "2" 28 [email protected] " "
29 [email protected] " " 29 [email protected] "+"
30 [email protected] "+" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected] "3"
33 [email protected] "3" 33 [email protected] ";"
34 [email protected] ";" 34 [email protected] "\n "
35 [email protected] "\n " 35 [email protected]
36 [email protected] 36 [email protected]
37 [email protected] 37 [email protected]
38 [email protected] 38 [email protected] "*"
39 [email protected] "*" 39 [email protected]
40 [email protected] 40 [email protected] "&"
41 [email protected] "&" 41 [email protected]
42 [email protected] 42 [email protected] "1"
43 [email protected] "1" 43 [email protected] " "
44 [email protected] " " 44 [email protected] "as"
45 [email protected] "as" 45 [email protected] " "
46 [email protected] " " 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected] "u64"
51 [email protected] "u64" 51 [email protected] ";"
52 [email protected] ";" 52 [email protected] "\n "
53 [email protected] "\n " 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected] "*"
56 [email protected] "*" 56 [email protected]
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected]
59 [email protected] 59 [email protected]
60 [email protected] 60 [email protected]
61 [email protected] 61 [email protected] "x"
62 [email protected] "x" 62 [email protected]
63 [email protected] 63 [email protected] "("
64 [email protected] "(" 64 [email protected]
65 [email protected] 65 [email protected] "1"
66 [email protected] "1" 66 [email protected] ")"
67 [email protected] ")" 67 [email protected] ";"
68 [email protected] ";" 68 [email protected] "\n "
69 [email protected] "\n " 69 [email protected]
70 [email protected] 70 [email protected]
71 [email protected] 71 [email protected] "&"
72 [email protected] "&" 72 [email protected]
73 [email protected] 73 [email protected]
74 [email protected] 74 [email protected]
75 [email protected] 75 [email protected]
76 [email protected] 76 [email protected]
77 [email protected] 77 [email protected] "x"
78 [email protected] "x" 78 [email protected] "["
79 [email protected] "[" 79 [email protected]
80 [email protected] 80 [email protected] "1"
81 [email protected] "1" 81 [email protected] "]"
82 [email protected] "]" 82 [email protected] ";"
83 [email protected] ";" 83 [email protected] "\n "
84 [email protected] "\n " 84 [email protected]
85 [email protected] 85 [email protected]
86 [email protected] 86 [email protected]
87 [email protected] 87 [email protected] "-"
88 [email protected] "-" 88 [email protected]
89 [email protected] 89 [email protected] "1"
90 [email protected] "1" 90 [email protected] ".."
91 [email protected] ".." 91 [email protected]
92 [email protected] 92 [email protected] "2"
93 [email protected] "2" 93 [email protected] ";"
94 [email protected] ";" 94 [email protected] "\n"
95 [email protected] "\n" 95 [email protected] "}"
96 [email protected] "}"
97 [email protected] "\n" 96 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rast b/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rast
index 225b1d0b6..ddcb139c1 100644
--- a/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rast
@@ -9,93 +9,89 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected]
19 [email protected] 19 [email protected]
20 [email protected] 20 [email protected] "Some"
21 [email protected] "Some" 21 [email protected]
22 [email protected] 22 [email protected] "("
23 [email protected] "(" 23 [email protected]
24 [email protected] 24 [email protected] "for"
25 [email protected] "for" 25 [email protected] " "
26 [email protected] " " 26 [email protected]
27 [email protected] 27 [email protected] "_"
28 [email protected] "_" 28 [email protected] " "
29 [email protected] " " 29 [email protected] "in"
30 [email protected] "in" 30 [email protected] " "
31 [email protected] " " 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected] "["
34 [email protected] "[" 34 [email protected]
35 [email protected] 35 [email protected] "1"
36 [email protected] "1" 36 [email protected] "]"
37 [email protected] "]" 37 [email protected] "."
38 [email protected] "." 38 [email protected]
39 [email protected] 39 [email protected] "into_iter"
40 [email protected] "into_iter" 40 [email protected]
41 [email protected] 41 [email protected] "("
42 [email protected] "(" 42 [email protected] ")"
43 [email protected] ")" 43 [email protected] " "
44 [email protected] " " 44 [email protected]
45 [email protected] 45 [email protected] "{"
46 [email protected] 46 [email protected] "}"
47 [email protected] "{" 47 [email protected] ")"
48 [email protected] "}" 48 [email protected] ";"
49 [email protected] ")" 49 [email protected] "\n "
50 [email protected] ";" 50 [email protected]
51 [email protected] "\n " 51 [email protected]
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected]
54 [email protected] 54 [email protected]
55 [email protected] 55 [email protected]
56 [email protected] 56 [email protected] "Some"
57 [email protected] 57 [email protected]
58 [email protected] "Some" 58 [email protected] "("
59 [email protected] 59 [email protected]
60 [email protected] "(" 60 [email protected] "loop"
61 [email protected] 61 [email protected] " "
62 [email protected] "loop" 62 [email protected]
63 [email protected] " " 63 [email protected] "{"
64 [email protected] 64 [email protected] " "
65 [email protected] 65 [email protected]
66 [email protected] "{" 66 [email protected]
67 [email protected] " " 67 [email protected] "break"
68 [email protected] 68 [email protected] ";"
69 [email protected] 69 [email protected] " "
70 [email protected] "break" 70 [email protected] "}"
71 [email protected] ";" 71 [email protected] ")"
72 [email protected] " " 72 [email protected] ";"
73 [email protected] "}" 73 [email protected] "\n "
74 [email protected] ")" 74 [email protected]
75 [email protected] ";" 75 [email protected]
76 [email protected] "\n " 76 [email protected]
77 [email protected] 77 [email protected]
78 [email protected] 78 [email protected]
79 [email protected] 79 [email protected]
80 [email protected] 80 [email protected] "Some"
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "("
83 [email protected] "Some" 83 [email protected]
84 [email protected] 84 [email protected] "while"
85 [email protected] "(" 85 [email protected] " "
86 [email protected] 86 [email protected]
87 [email protected] "while" 87 [email protected]
88 [email protected] " " 88 [email protected] "true"
89 [email protected] 89 [email protected] " "
90 [email protected] 90 [email protected]
91 [email protected] "true" 91 [email protected] "{"
92 [email protected] " " 92 [email protected] "}"
93 [email protected] 93 [email protected] ")"
94 [email protected] 94 [email protected] ";"
95 [email protected] "{" 95 [email protected] "\n"
96 [email protected] "}" 96 [email protected] "}"
97 [email protected] ")"
98 [email protected] ";"
99 [email protected] "\n"
100 [email protected] "}"
101 [email protected] "\n" 97 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0060_as_range.rast b/crates/ra_syntax/test_data/parser/ok/0060_as_range.rast
index a52a08ed0..098152fc3 100644
--- a/crates/ra_syntax/test_data/parser/ok/0060_as_range.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0060_as_range.rast
@@ -9,48 +9,47 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected]
16 [email protected] 16 [email protected]
17 [email protected] 17 [email protected]
18 [email protected] 18 [email protected] "0"
19 [email protected] "0" 19 [email protected] " "
20 [email protected] " " 20 [email protected] "as"
21 [email protected] "as" 21 [email protected] " "
22 [email protected] " " 22 [email protected]
23 [email protected] 23 [email protected]
24 [email protected] 24 [email protected]
25 [email protected] 25 [email protected]
26 [email protected] 26 [email protected] "usize"
27 [email protected] "usize" 27 [email protected] " "
28 [email protected] " " 28 [email protected] ".."
29 [email protected] ".." 29 [email protected] ";"
30 [email protected] ";" 30 [email protected] "\n "
31 [email protected] "\n " 31 [email protected]
32 [email protected] 32 [email protected]
33 [email protected] 33 [email protected]
34 [email protected] 34 [email protected]
35 [email protected] 35 [email protected] "1"
36 [email protected] "1" 36 [email protected] " "
37 [email protected] " " 37 [email protected] "+"
38 [email protected] "+" 38 [email protected] " "
39 [email protected] " " 39 [email protected]
40 [email protected] 40 [email protected]
41 [email protected] 41 [email protected] "2"
42 [email protected] "2" 42 [email protected] " "
43 [email protected] " " 43 [email protected] "as"
44 [email protected] "as" 44 [email protected] " "
45 [email protected] " " 45 [email protected]
46 [email protected] 46 [email protected]
47 [email protected] 47 [email protected]
48 [email protected] 48 [email protected]
49 [email protected] 49 [email protected] "usize"
50 [email protected] "usize" 50 [email protected] " "
51 [email protected] " " 51 [email protected] ".."
52 [email protected] ".." 52 [email protected] ";"
53 [email protected] ";" 53 [email protected] "\n"
54 [email protected] "\n" 54 [email protected] "}"
55 [email protected] "}"
56 [email protected] "\n" 55 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0061_match_full_range.rast b/crates/ra_syntax/test_data/parser/ok/0061_match_full_range.rast
index b8974c942..c6e982976 100644
--- a/crates/ra_syntax/test_data/parser/ok/0061_match_full_range.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0061_match_full_range.rast
@@ -9,19 +9,18 @@ [email protected]
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected] "{"
13 [email protected] "{" 13 [email protected] "\n "
14 [email protected] "\n " 14 [email protected]
15 [email protected] 15 [email protected] "match"
16 [email protected] "match" 16 [email protected] " "
17 [email protected] " " 17 [email protected]
18 [email protected] 18 [email protected] ".."
19 [email protected] ".." 19 [email protected] " "
20 [email protected] " " 20 [email protected]
21 [email protected] 21 [email protected] "{"
22 [email protected] "{" 22 [email protected] "\n "
23 [email protected] "\n " 23 [email protected] "}"
24 [email protected] "}" 24 [email protected] "\n"
25 [email protected] "\n" 25 [email protected] "}"
26 [email protected] "}"
27 [email protected] "\n" 26 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rast b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rast
index 46f370eec..bf791ee2b 100644
--- a/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rast
@@ -70,107 +70,106 @@ [email protected]
70 [email protected] ")" 70 [email protected] ")"
71 [email protected] " " 71 [email protected] " "
72 [email protected] 72 [email protected]
73 [email protected] 73 [email protected] "{"
74 [email protected] "{" 74 [email protected] "\n "
75 [email protected] "\n " 75 [email protected]
76 [email protected] 76 [email protected] "macro"
77 [email protected] "macro" 77 [email protected] " "
78 [email protected] " " 78 [email protected]
79 [email protected] 79 [email protected] "test_merge"
80 [email protected] "test_merge" 80 [email protected]
81 [email protected] 81 [email protected]
82 [email protected] 82 [email protected] "("
83 [email protected] "(" 83 [email protected]
84 [email protected] 84 [email protected] "["
85 [email protected] "[" 85 [email protected] "$"
86 [email protected] "$" 86 [email protected]
87 [email protected] 87 [email protected] "("
88 [email protected] "(" 88 [email protected] "$"
89 [email protected] "$" 89 [email protected] "input"
90 [email protected] "input" 90 [email protected] ":"
91 [email protected] ":" 91 [email protected] "expr"
92 [email protected] "expr" 92 [email protected] ")"
93 [email protected] ")" 93 [email protected] ","
94 [email protected] "," 94 [email protected] "*"
95 [email protected] "*" 95 [email protected] " "
96 [email protected] " " 96 [email protected] "$"
97 [email protected] "$" 97 [email protected]
98 [email protected] 98 [email protected] "("
99 [email protected] "(" 99 [email protected] ","
100 [email protected] "," 100 [email protected] ")"
101 [email protected] ")" 101 [email protected] "*"
102 [email protected] "*" 102 [email protected] "]"
103 [email protected] "]" 103 [email protected] ","
104 [email protected] "," 104 [email protected] " "
105 [email protected] " " 105 [email protected]
106 [email protected] 106 [email protected] "["
107 [email protected] "[" 107 [email protected] "$"
108 [email protected] "$" 108 [email protected]
109 [email protected] 109 [email protected] "("
110 [email protected] "(" 110 [email protected] "$"
111 [email protected] "$" 111 [email protected] "output"
112 [email protected] "output" 112 [email protected] ":"
113 [email protected] ":" 113 [email protected] "expr"
114 [email protected] "expr" 114 [email protected] ")"
115 [email protected] ")" 115 [email protected] ","
116 [email protected] "," 116 [email protected] "*"
117 [email protected] "*" 117 [email protected] " "
118 [email protected] " " 118 [email protected] "$"
119 [email protected] "$" 119 [email protected]
120 [email protected] 120 [email protected] "("
121 [email protected] "(" 121 [email protected] ","
122 [email protected] "," 122 [email protected] ")"
123 [email protected] ")" 123 [email protected] "*"
124 [email protected] "*" 124 [email protected] "]"
125 [email protected] "]" 125 [email protected] ")"
126 [email protected] ")" 126 [email protected] " "
127 [email protected] " " 127 [email protected]
128 [email protected] 128 [email protected] "{"
129 [email protected] "{" 129 [email protected] "\n "
130 [email protected] "\n " 130 [email protected] "assert_eq"
131 [email protected] "assert_eq" 131 [email protected] "!"
132 [email protected] "!" 132 [email protected]
133 [email protected] 133 [email protected] "("
134 [email protected] "(" 134 [email protected] "\n "
135 [email protected] "\n " 135 [email protected] "merge_use_trees"
136 [email protected] "merge_use_trees" 136 [email protected]
137 [email protected] 137 [email protected] "("
138 [email protected] "(" 138 [email protected] "parse_use_trees"
139 [email protected] "parse_use_trees" 139 [email protected] "!"
140 [email protected] "!" 140 [email protected]
141 [email protected] 141 [email protected] "("
142 [email protected] "(" 142 [email protected] "$"
143 [email protected] "$" 143 [email protected]
144 [email protected] 144 [email protected] "("
145 [email protected] "(" 145 [email protected] "$"
146 [email protected] "$" 146 [email protected] "input"
147 [email protected] "input" 147 [email protected] ","
148 [email protected] "," 148 [email protected] ")"
149 [email protected] ")" 149 [email protected] "*"
150 [email protected] "*" 150 [email protected] ")"
151 [email protected] ")" 151 [email protected] ")"
152 [email protected] ")" 152 [email protected] ","
153 [email protected] "," 153 [email protected] "\n "
154 [email protected] "\n " 154 [email protected] "parse_use_trees"
155 [email protected] "parse_use_trees" 155 [email protected] "!"
156 [email protected] "!" 156 [email protected]
157 [email protected] 157 [email protected] "("
158 [email protected] "(" 158 [email protected] "$"
159 [email protected] "$" 159 [email protected]
160 [email protected] 160 [email protected] "("
161 [email protected] "(" 161 [email protected] "$"
162 [email protected] "$" 162 [email protected] "output"
163 [email protected] "output" 163 [email protected] ","
164 [email protected] "," 164 [email protected] ")"
165 [email protected] ")" 165 [email protected] "*"
166 [email protected] "*" 166 [email protected] ")"
167 [email protected] ")" 167 [email protected] ","
168 [email protected] "," 168 [email protected] "\n "
169 [email protected] "\n " 169 [email protected] ")"
170 [email protected] ")" 170 [email protected] ";"
171 [email protected] ";" 171 [email protected] "\n "
172 [email protected] "\n " 172 [email protected] "}"
173 [email protected] "}" 173 [email protected] "\n"
174 [email protected] "\n" 174 [email protected] "}"
175 [email protected] "}"
176 [email protected] "\n" 175 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast b/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast
index 1cd77aa14..886b211d0 100644
--- a/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0063_trait_fn_patterns.rast
@@ -47,9 +47,8 @@ [email protected]
47 [email protected] ")" 47 [email protected] ")"
48 [email protected] " " 48 [email protected] " "
49 [email protected] 49 [email protected]
50 [email protected] 50 [email protected] "{"
51 [email protected] "{" 51 [email protected] "}"
52 [email protected] "}"
53 [email protected] "\n " 52 [email protected] "\n "
54 [email protected] 53 [email protected]
55 [email protected] "fn" 54 [email protected] "fn"
@@ -90,9 +89,8 @@ [email protected]
90 [email protected] ")" 89 [email protected] ")"
91 [email protected] " " 90 [email protected] " "
92 [email protected] 91 [email protected]
93 [email protected] 92 [email protected] "{"
94 [email protected] "{" 93 [email protected] "}"
95 [email protected] "}"
96 [email protected] "\n " 94 [email protected] "\n "
97 [email protected] 95 [email protected]
98 [email protected] "fn" 96 [email protected] "fn"
@@ -122,9 +120,8 @@ [email protected]
122 [email protected] ")" 120 [email protected] ")"
123 [email protected] " " 121 [email protected] " "
124 [email protected] 122 [email protected]
125 [email protected] 123 [email protected] "{"
126 [email protected] "{" 124 [email protected] "}"
127 [email protected] "}"
128 [email protected] "\n " 125 [email protected] "\n "
129 [email protected] 126 [email protected]
130 [email protected] "fn" 127 [email protected] "fn"
@@ -155,9 +152,8 @@ [email protected]
155 [email protected] ")" 152 [email protected] ")"
156 [email protected] " " 153 [email protected] " "
157 [email protected] 154 [email protected]
158 [email protected] 155 [email protected] "{"
159 [email protected] "{" 156 [email protected] "}"
160 [email protected] "}"
161 [email protected] "\n " 157 [email protected] "\n "
162 [email protected] 158 [email protected]
163 [email protected] "fn" 159 [email protected] "fn"
diff --git a/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast b/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast
index 4f9a14066..a0423806c 100644
--- a/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0064_impl_fn_params.rast
@@ -50,9 +50,8 @@ [email protected]
50 [email protected] ")" 50 [email protected] ")"
51 [email protected] " " 51 [email protected] " "
52 [email protected] 52 [email protected]
53 [email protected] 53 [email protected] "{"
54 [email protected] "{" 54 [email protected] "}"
55 [email protected] "}"
56 [email protected] "\n " 55 [email protected] "\n "
57 [email protected] 56 [email protected]
58 [email protected] "fn" 57 [email protected] "fn"
@@ -93,9 +92,8 @@ [email protected]
93 [email protected] ")" 92 [email protected] ")"
94 [email protected] " " 93 [email protected] " "
95 [email protected] 94 [email protected]
96 [email protected] 95 [email protected] "{"
97 [email protected] "{" 96 [email protected] "}"
98 [email protected] "}"
99 [email protected] "\n " 97 [email protected] "\n "
100 [email protected] 98 [email protected]
101 [email protected] "fn" 99 [email protected] "fn"
@@ -125,9 +123,8 @@ [email protected]
125 [email protected] ")" 123 [email protected] ")"
126 [email protected] " " 124 [email protected] " "
127 [email protected] 125 [email protected]
128 [email protected] 126 [email protected] "{"
129 [email protected] "{" 127 [email protected] "}"
130 [email protected] "}"
131 [email protected] "\n " 128 [email protected] "\n "
132 [email protected] 129 [email protected]
133 [email protected] "fn" 130 [email protected] "fn"
@@ -158,9 +155,8 @@ [email protected]
158 [email protected] ")" 155 [email protected] ")"
159 [email protected] " " 156 [email protected] " "
160 [email protected] 157 [email protected]
161 [email protected] 158 [email protected] "{"
162 [email protected] "{" 159 [email protected] "}"
163 [email protected] "}"
164 [email protected] "\n" 160 [email protected] "\n"
165 [email protected] "}" 161 [email protected] "}"
166 [email protected] "\n" 162 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0065_comment_newline.rast b/crates/ra_syntax/test_data/parser/ok/0065_comment_newline.rast
index 3294f4901..d1fffdd63 100644
--- a/crates/ra_syntax/test_data/parser/ok/0065_comment_newline.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0065_comment_newline.rast
@@ -11,7 +11,6 @@ [email protected]
11 [email protected] ")" 11 [email protected] ")"
12 [email protected] " " 12 [email protected] " "
13 [email protected] 13 [email protected]
14 [email protected] 14 [email protected] "{"
15 [email protected] "{" 15 [email protected] "}"
16 [email protected] "}"
17 [email protected] "\n" 16 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast b/crates/ra_syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
index 633b14000..eb2f8eb3c 100644
--- a/crates/ra_syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0065_plus_after_fn_trait_bound.rast
@@ -55,7 +55,6 @@ [email protected]
55 [email protected] "Send" 55 [email protected] "Send"
56 [email protected] " " 56 [email protected] " "
57 [email protected] 57 [email protected]
58 [email protected] 58 [email protected] "{"
59 [email protected] "{" 59 [email protected] "}"
60 [email protected] "}"
61 [email protected] "\n" 60 [email protected] "\n"
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs
index e656260c7..25554f583 100644
--- a/crates/ra_text_edit/src/lib.rs
+++ b/crates/ra_text_edit/src/lib.rs
@@ -1,36 +1,170 @@
1//! FIXME: write short doc here 1//! Representation of a `TextEdit`.
2//!
3//! `rust-analyzer` never mutates text itself and only sends diffs to clients,
4//! so `TextEdit` is the ultimate representation of the work done by
5//! rust-analyzer.
6use std::{slice, vec};
2 7
3mod text_edit; 8pub use text_size::{TextRange, TextSize};
4 9
5use text_size::{TextRange, TextSize}; 10/// `InsertDelete` -- a single "atomic" change to text
6 11///
7pub use crate::text_edit::{TextEdit, TextEditBuilder}; 12/// Must not overlap with other `InDel`s
8
9/// Must not overlap with other `AtomTextEdit`s
10#[derive(Debug, Clone)] 13#[derive(Debug, Clone)]
11pub struct AtomTextEdit { 14pub struct Indel {
15 pub insert: String,
12 /// Refers to offsets in the original text 16 /// Refers to offsets in the original text
13 pub delete: TextRange, 17 pub delete: TextRange,
14 pub insert: String,
15} 18}
16 19
17impl AtomTextEdit { 20#[derive(Default, Debug, Clone)]
18 pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit { 21pub struct TextEdit {
19 AtomTextEdit { delete: range, insert: replace_with } 22 indels: Vec<Indel>,
20 } 23}
21 24
22 pub fn delete(range: TextRange) -> AtomTextEdit { 25#[derive(Debug, Default, Clone)]
23 AtomTextEdit::replace(range, String::new()) 26pub struct TextEditBuilder {
24 } 27 indels: Vec<Indel>,
28}
25 29
26 pub fn insert(offset: TextSize, text: String) -> AtomTextEdit { 30impl Indel {
27 AtomTextEdit::replace(TextRange::empty(offset), text) 31 pub fn insert(offset: TextSize, text: String) -> Indel {
32 Indel::replace(TextRange::empty(offset), text)
33 }
34 pub fn delete(range: TextRange) -> Indel {
35 Indel::replace(range, String::new())
36 }
37 pub fn replace(range: TextRange, replace_with: String) -> Indel {
38 Indel { delete: range, insert: replace_with }
28 } 39 }
29 40
30 pub fn apply(&self, mut text: String) -> String { 41 pub fn apply(&self, text: &mut String) {
31 let start: usize = self.delete.start().into(); 42 let start: usize = self.delete.start().into();
32 let end: usize = self.delete.end().into(); 43 let end: usize = self.delete.end().into();
33 text.replace_range(start..end, &self.insert); 44 text.replace_range(start..end, &self.insert);
34 text
35 } 45 }
36} 46}
47
48impl TextEdit {
49 pub fn insert(offset: TextSize, text: String) -> TextEdit {
50 let mut builder = TextEditBuilder::default();
51 builder.insert(offset, text);
52 builder.finish()
53 }
54
55 pub fn delete(range: TextRange) -> TextEdit {
56 let mut builder = TextEditBuilder::default();
57 builder.delete(range);
58 builder.finish()
59 }
60
61 pub fn replace(range: TextRange, replace_with: String) -> TextEdit {
62 let mut builder = TextEditBuilder::default();
63 builder.replace(range, replace_with);
64 builder.finish()
65 }
66
67 pub fn len(&self) -> usize {
68 self.indels.len()
69 }
70
71 pub fn is_empty(&self) -> bool {
72 self.indels.is_empty()
73 }
74
75 pub fn iter(&self) -> slice::Iter<'_, Indel> {
76 self.indels.iter()
77 }
78
79 pub fn into_iter(self) -> vec::IntoIter<Indel> {
80 self.indels.into_iter()
81 }
82
83 pub fn apply(&self, text: &mut String) {
84 match self.len() {
85 0 => return,
86 1 => {
87 self.indels[0].apply(text);
88 return;
89 }
90 _ => (),
91 }
92
93 let mut total_len = TextSize::of(&*text);
94 for indel in self.indels.iter() {
95 total_len += TextSize::of(&indel.insert);
96 total_len -= indel.delete.end() - indel.delete.start();
97 }
98 let mut buf = String::with_capacity(total_len.into());
99 let mut prev = 0;
100 for indel in self.indels.iter() {
101 let start: usize = indel.delete.start().into();
102 let end: usize = indel.delete.end().into();
103 if start > prev {
104 buf.push_str(&text[prev..start]);
105 }
106 buf.push_str(&indel.insert);
107 prev = end;
108 }
109 buf.push_str(&text[prev..text.len()]);
110 assert_eq!(TextSize::of(&buf), total_len);
111
112 // FIXME: figure out a way to mutate the text in-place or reuse the
113 // memory in some other way
114 *text = buf
115 }
116
117 pub fn union(&mut self, other: TextEdit) -> Result<(), TextEdit> {
118 // FIXME: can be done without allocating intermediate vector
119 let mut all = self.iter().chain(other.iter()).collect::<Vec<_>>();
120 if !check_disjoint(&mut all) {
121 return Err(other);
122 }
123 self.indels.extend(other.indels);
124 assert!(check_disjoint(&mut self.indels));
125 Ok(())
126 }
127
128 pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> {
129 let mut res = offset;
130 for indel in self.indels.iter() {
131 if indel.delete.start() >= offset {
132 break;
133 }
134 if offset < indel.delete.end() {
135 return None;
136 }
137 res += TextSize::of(&indel.insert);
138 res -= indel.delete.len();
139 }
140 Some(res)
141 }
142}
143
144impl TextEditBuilder {
145 pub fn replace(&mut self, range: TextRange, replace_with: String) {
146 self.indels.push(Indel::replace(range, replace_with))
147 }
148 pub fn delete(&mut self, range: TextRange) {
149 self.indels.push(Indel::delete(range))
150 }
151 pub fn insert(&mut self, offset: TextSize, text: String) {
152 self.indels.push(Indel::insert(offset, text))
153 }
154 pub fn finish(self) -> TextEdit {
155 let mut indels = self.indels;
156 assert!(check_disjoint(&mut indels));
157 TextEdit { indels }
158 }
159 pub fn invalidates_offset(&self, offset: TextSize) -> bool {
160 self.indels.iter().any(|indel| indel.delete.contains_inclusive(offset))
161 }
162}
163
164fn check_disjoint(indels: &mut [impl std::borrow::Borrow<Indel>]) -> bool {
165 indels.sort_by_key(|indel| (indel.borrow().delete.start(), indel.borrow().delete.end()));
166 indels
167 .iter()
168 .zip(indels.iter().skip(1))
169 .all(|(l, r)| l.borrow().delete.end() <= r.borrow().delete.start())
170}
diff --git a/crates/ra_text_edit/src/text_edit.rs b/crates/ra_text_edit/src/text_edit.rs
deleted file mode 100644
index eabab4b4d..000000000
--- a/crates/ra_text_edit/src/text_edit.rs
+++ /dev/null
@@ -1,102 +0,0 @@
1//! FIXME: write short doc here
2
3use crate::AtomTextEdit;
4
5use text_size::{TextRange, TextSize};
6
7#[derive(Debug, Clone)]
8pub struct TextEdit {
9 atoms: Vec<AtomTextEdit>,
10}
11
12#[derive(Debug, Default)]
13pub struct TextEditBuilder {
14 atoms: Vec<AtomTextEdit>,
15}
16
17impl TextEditBuilder {
18 pub fn replace(&mut self, range: TextRange, replace_with: String) {
19 self.atoms.push(AtomTextEdit::replace(range, replace_with))
20 }
21 pub fn delete(&mut self, range: TextRange) {
22 self.atoms.push(AtomTextEdit::delete(range))
23 }
24 pub fn insert(&mut self, offset: TextSize, text: String) {
25 self.atoms.push(AtomTextEdit::insert(offset, text))
26 }
27 pub fn finish(self) -> TextEdit {
28 TextEdit::from_atoms(self.atoms)
29 }
30 pub fn invalidates_offset(&self, offset: TextSize) -> bool {
31 self.atoms.iter().any(|atom| atom.delete.contains_inclusive(offset))
32 }
33}
34
35impl TextEdit {
36 pub fn insert(offset: TextSize, text: String) -> TextEdit {
37 let mut builder = TextEditBuilder::default();
38 builder.insert(offset, text);
39 builder.finish()
40 }
41
42 pub fn delete(range: TextRange) -> TextEdit {
43 let mut builder = TextEditBuilder::default();
44 builder.delete(range);
45 builder.finish()
46 }
47
48 pub fn replace(range: TextRange, replace_with: String) -> TextEdit {
49 let mut builder = TextEditBuilder::default();
50 builder.replace(range, replace_with);
51 builder.finish()
52 }
53
54 pub(crate) fn from_atoms(mut atoms: Vec<AtomTextEdit>) -> TextEdit {
55 atoms.sort_by_key(|a| (a.delete.start(), a.delete.end()));
56 for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) {
57 assert!(a1.delete.end() <= a2.delete.start())
58 }
59 TextEdit { atoms }
60 }
61
62 pub fn as_atoms(&self) -> &[AtomTextEdit] {
63 &self.atoms
64 }
65
66 pub fn apply(&self, text: &str) -> String {
67 let mut total_len = TextSize::of(text);
68 for atom in self.atoms.iter() {
69 total_len += TextSize::of(&atom.insert);
70 total_len -= atom.delete.end() - atom.delete.start();
71 }
72 let mut buf = String::with_capacity(total_len.into());
73 let mut prev = 0;
74 for atom in self.atoms.iter() {
75 let start: usize = atom.delete.start().into();
76 let end: usize = atom.delete.end().into();
77 if start > prev {
78 buf.push_str(&text[prev..start]);
79 }
80 buf.push_str(&atom.insert);
81 prev = end;
82 }
83 buf.push_str(&text[prev..text.len()]);
84 assert_eq!(TextSize::of(&buf), total_len);
85 buf
86 }
87
88 pub fn apply_to_offset(&self, offset: TextSize) -> Option<TextSize> {
89 let mut res = offset;
90 for atom in self.atoms.iter() {
91 if atom.delete.start() >= offset {
92 break;
93 }
94 if offset < atom.delete.end() {
95 return None;
96 }
97 res += TextSize::of(&atom.insert);
98 res -= atom.delete.len();
99 }
100 Some(res)
101 }
102}
diff --git a/crates/ra_toolchain/Cargo.toml b/crates/ra_toolchain/Cargo.toml
new file mode 100644
index 000000000..1873fbe16
--- /dev/null
+++ b/crates/ra_toolchain/Cargo.toml
@@ -0,0 +1,8 @@
1[package]
2edition = "2018"
3name = "ra_toolchain"
4version = "0.1.0"
5authors = ["rust-analyzer developers"]
6
7[dependencies]
8home = "0.5.3"
diff --git a/crates/ra_toolchain/src/lib.rs b/crates/ra_toolchain/src/lib.rs
new file mode 100644
index 000000000..3d2865e09
--- /dev/null
+++ b/crates/ra_toolchain/src/lib.rs
@@ -0,0 +1,63 @@
1//! This crate contains a single public function
2//! [`get_path_for_executable`](fn.get_path_for_executable.html).
3//! See docs there for more information.
4use std::{env, iter, path::PathBuf};
5
6pub fn cargo() -> PathBuf {
7 get_path_for_executable("cargo")
8}
9
10pub fn rustc() -> PathBuf {
11 get_path_for_executable("rustc")
12}
13
14pub fn rustup() -> PathBuf {
15 get_path_for_executable("rustup")
16}
17
18/// Return a `PathBuf` to use for the given executable.
19///
20/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that
21/// gives a valid Cargo executable; or it may return a full path to a valid
22/// Cargo.
23fn get_path_for_executable(executable_name: &'static str) -> PathBuf {
24 // The current implementation checks three places for an executable to use:
25 // 1) Appropriate environment variable (erroring if this is set but not a usable executable)
26 // example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
27 // 2) `<executable_name>`
28 // example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH
29 // 3) `~/.cargo/bin/<executable_name>`
30 // example: for cargo, this tries ~/.cargo/bin/cargo
31 // It seems that this is a reasonable place to try for cargo, rustc, and rustup
32 let env_var = executable_name.to_ascii_uppercase();
33 if let Some(path) = env::var_os(&env_var) {
34 return path.into();
35 }
36
37 if lookup_in_path(executable_name) {
38 return executable_name.into();
39 }
40
41 if let Some(mut path) = home::home_dir() {
42 path.push(".cargo");
43 path.push("bin");
44 path.push(executable_name);
45 if path.is_file() {
46 return path;
47 }
48 }
49 executable_name.into()
50}
51
52fn lookup_in_path(exec: &str) -> bool {
53 let paths = env::var_os("PATH").unwrap_or_default();
54 let mut candidates = env::split_paths(&paths).flat_map(|path| {
55 let candidate = path.join(&exec);
56 let with_exe = match env::consts::EXE_EXTENSION {
57 "" => None,
58 it => Some(candidate.with_extension(it)),
59 };
60 iter::once(candidate).chain(with_exe)
61 });
62 candidates.any(|it| it.is_file())
63}
diff --git a/crates/ra_tt/src/buffer.rs b/crates/ra_tt/src/buffer.rs
index 14b3f707d..5967f44cd 100644
--- a/crates/ra_tt/src/buffer.rs
+++ b/crates/ra_tt/src/buffer.rs
@@ -42,7 +42,9 @@ impl<'t> TokenBuffer<'t> {
42 buffers: &mut Vec<Box<[Entry<'t>]>>, 42 buffers: &mut Vec<Box<[Entry<'t>]>>,
43 next: Option<EntryPtr>, 43 next: Option<EntryPtr>,
44 ) -> usize { 44 ) -> usize {
45 let mut entries = vec![]; 45 // Must contain everything in tokens and then the Entry::End
46 let start_capacity = tokens.len() + 1;
47 let mut entries = Vec::with_capacity(start_capacity);
46 let mut children = vec![]; 48 let mut children = vec![];
47 49
48 for (idx, tt) in tokens.iter().enumerate() { 50 for (idx, tt) in tokens.iter().enumerate() {
diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs
index 5248e026c..342ddbe32 100644
--- a/crates/ra_tt/src/lib.rs
+++ b/crates/ra_tt/src/lib.rs
@@ -243,7 +243,7 @@ impl Subtree {
243 243
244pub mod buffer; 244pub mod buffer;
245 245
246#[derive(Debug, PartialEq, Eq)] 246#[derive(Debug, PartialEq, Eq, Clone)]
247pub enum ExpansionError { 247pub enum ExpansionError {
248 IOError(String), 248 IOError(String),
249 JsonError(String), 249 JsonError(String),
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 8c94f430a..9b2d29b1d 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -53,6 +53,7 @@ winapi = "0.3.8"
53 53
54[dev-dependencies] 54[dev-dependencies]
55tempfile = "3.1.0" 55tempfile = "3.1.0"
56insta = "0.16.0"
56test_utils = { path = "../test_utils" } 57test_utils = { path = "../test_utils" }
57 58
58[features] 59[features]
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs
index 22a84b50c..09908458d 100644
--- a/crates/rust-analyzer/src/bin/main.rs
+++ b/crates/rust-analyzer/src/bin/main.rs
@@ -60,7 +60,7 @@ fn main() -> Result<()> {
60 60
61fn setup_logging() -> Result<()> { 61fn setup_logging() -> Result<()> {
62 std::env::set_var("RUST_BACKTRACE", "short"); 62 std::env::set_var("RUST_BACKTRACE", "short");
63 env_logger::try_init()?; 63 env_logger::try_init_from_env("RA_LOG")?;
64 ra_prof::init(); 64 ra_prof::init();
65 Ok(()) 65 Ok(())
66} 66}
@@ -100,9 +100,8 @@ fn run_server() -> Result<()> {
100 if let Some(value) = &initialize_params.initialization_options { 100 if let Some(value) = &initialize_params.initialization_options {
101 config.update(value); 101 config.update(value);
102 } 102 }
103 if let Some(caps) = &initialize_params.capabilities.text_document { 103 config.update_caps(&initialize_params.capabilities);
104 config.update_caps(caps); 104
105 }
106 config 105 config
107 }; 106 };
108 107
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index c0d320926..4c417c270 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -1,6 +1,5 @@
1//! Advertizes the capabilities of the LSP Server. 1//! Advertizes the capabilities of the LSP Server.
2 2use std::env;
3use crate::semantic_tokens;
4 3
5use lsp_types::{ 4use lsp_types::{
6 CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability, 5 CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability,
@@ -11,12 +10,19 @@ use lsp_types::{
11 ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, 10 ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
12 TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, 11 TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
13}; 12};
13use serde_json::json;
14
15use crate::semantic_tokens;
14 16
15pub fn server_capabilities() -> ServerCapabilities { 17pub fn server_capabilities() -> ServerCapabilities {
16 ServerCapabilities { 18 ServerCapabilities {
17 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { 19 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
18 open_close: Some(true), 20 open_close: Some(true),
19 change: Some(TextDocumentSyncKind::Incremental), 21 change: Some(if env::var("RA_NO_INCREMENTAL_SYNC").is_ok() {
22 TextDocumentSyncKind::Full
23 } else {
24 TextDocumentSyncKind::Incremental
25 }),
20 will_save: None, 26 will_save: None,
21 will_save_wait_until: None, 27 will_save_wait_until: None,
22 save: Some(SaveOptions::default()), 28 save: Some(SaveOptions::default()),
@@ -43,7 +49,7 @@ pub fn server_capabilities() -> ServerCapabilities {
43 code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions { 49 code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions {
44 // Advertise support for all built-in CodeActionKinds 50 // Advertise support for all built-in CodeActionKinds
45 code_action_kinds: Some(vec![ 51 code_action_kinds: Some(vec![
46 String::new(), 52 lsp_types::code_action_kind::EMPTY.to_string(),
47 lsp_types::code_action_kind::QUICKFIX.to_string(), 53 lsp_types::code_action_kind::QUICKFIX.to_string(),
48 lsp_types::code_action_kind::REFACTOR.to_string(), 54 lsp_types::code_action_kind::REFACTOR.to_string(),
49 lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(), 55 lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(),
@@ -86,6 +92,8 @@ pub fn server_capabilities() -> ServerCapabilities {
86 } 92 }
87 .into(), 93 .into(),
88 ), 94 ),
89 experimental: Default::default(), 95 experimental: Some(json!({
96 "joinLines": true,
97 })),
90 } 98 }
91} 99}
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs
index 10c25666a..5e5a17943 100644
--- a/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -27,7 +27,7 @@ impl CargoTargetSpec {
27 RunnableKind::Test { test_id, attr } => { 27 RunnableKind::Test { test_id, attr } => {
28 args.push("test".to_string()); 28 args.push("test".to_string());
29 if let Some(spec) = spec { 29 if let Some(spec) = spec {
30 spec.push_to(&mut args); 30 spec.push_to(&mut args, kind);
31 } 31 }
32 extra_args.push(test_id.to_string()); 32 extra_args.push(test_id.to_string());
33 if let TestId::Path(_) = test_id { 33 if let TestId::Path(_) = test_id {
@@ -35,13 +35,13 @@ impl CargoTargetSpec {
35 } 35 }
36 extra_args.push("--nocapture".to_string()); 36 extra_args.push("--nocapture".to_string());
37 if attr.ignore { 37 if attr.ignore {
38 extra_args.push("--ignored".to_string()) 38 extra_args.push("--ignored".to_string());
39 } 39 }
40 } 40 }
41 RunnableKind::TestMod { path } => { 41 RunnableKind::TestMod { path } => {
42 args.push("test".to_string()); 42 args.push("test".to_string());
43 if let Some(spec) = spec { 43 if let Some(spec) = spec {
44 spec.push_to(&mut args); 44 spec.push_to(&mut args, kind);
45 } 45 }
46 extra_args.push(path.to_string()); 46 extra_args.push(path.to_string());
47 extra_args.push("--nocapture".to_string()); 47 extra_args.push("--nocapture".to_string());
@@ -49,7 +49,7 @@ impl CargoTargetSpec {
49 RunnableKind::Bench { test_id } => { 49 RunnableKind::Bench { test_id } => {
50 args.push("bench".to_string()); 50 args.push("bench".to_string());
51 if let Some(spec) = spec { 51 if let Some(spec) = spec {
52 spec.push_to(&mut args); 52 spec.push_to(&mut args, kind);
53 } 53 }
54 extra_args.push(test_id.to_string()); 54 extra_args.push(test_id.to_string());
55 if let TestId::Path(_) = test_id { 55 if let TestId::Path(_) = test_id {
@@ -57,10 +57,19 @@ impl CargoTargetSpec {
57 } 57 }
58 extra_args.push("--nocapture".to_string()); 58 extra_args.push("--nocapture".to_string());
59 } 59 }
60 RunnableKind::DocTest { test_id } => {
61 args.push("test".to_string());
62 args.push("--doc".to_string());
63 if let Some(spec) = spec {
64 spec.push_to(&mut args, kind);
65 }
66 extra_args.push(test_id.to_string());
67 extra_args.push("--nocapture".to_string());
68 }
60 RunnableKind::Bin => { 69 RunnableKind::Bin => {
61 args.push("run".to_string()); 70 args.push("run".to_string());
62 if let Some(spec) = spec { 71 if let Some(spec) = spec {
63 spec.push_to(&mut args); 72 spec.push_to(&mut args, kind);
64 } 73 }
65 } 74 }
66 } 75 }
@@ -91,9 +100,14 @@ impl CargoTargetSpec {
91 Ok(res) 100 Ok(res)
92 } 101 }
93 102
94 pub(crate) fn push_to(self, buf: &mut Vec<String>) { 103 pub(crate) fn push_to(self, buf: &mut Vec<String>, kind: &RunnableKind) {
95 buf.push("--package".to_string()); 104 buf.push("--package".to_string());
96 buf.push(self.package); 105 buf.push(self.package);
106
107 // Can't mix --doc with other target flags
108 if let RunnableKind::DocTest { .. } = kind {
109 return;
110 }
97 match self.target_kind { 111 match self.target_kind {
98 TargetKind::Bin => { 112 TargetKind::Bin => {
99 buf.push("--bin".to_string()); 113 buf.push("--bin".to_string());
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs
index a865a7c7e..39ce77900 100644
--- a/crates/rust-analyzer/src/cli.rs
+++ b/crates/rust-analyzer/src/cli.rs
@@ -16,6 +16,7 @@ use ra_syntax::{AstNode, SourceFile};
16pub use analysis_bench::{analysis_bench, BenchWhat, Position}; 16pub use analysis_bench::{analysis_bench, BenchWhat, Position};
17pub use analysis_stats::analysis_stats; 17pub use analysis_stats::analysis_stats;
18pub use diagnostics::diagnostics; 18pub use diagnostics::diagnostics;
19pub use load_cargo::load_cargo;
19 20
20#[derive(Clone, Copy)] 21#[derive(Clone, Copy)]
21pub enum Verbosity { 22pub enum Verbosity {
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs
index 6147ae207..b20efe98d 100644
--- a/crates/rust-analyzer/src/cli/analysis_bench.rs
+++ b/crates/rust-analyzer/src/cli/analysis_bench.rs
@@ -105,7 +105,7 @@ pub fn analysis_bench(
105 if is_completion { 105 if is_completion {
106 let options = CompletionConfig::default(); 106 let options = CompletionConfig::default();
107 let res = do_work(&mut host, file_id, |analysis| { 107 let res = do_work(&mut host, file_id, |analysis| {
108 analysis.completions(file_position, &options) 108 analysis.completions(&options, file_position)
109 }); 109 });
110 if verbosity.is_verbose() { 110 if verbosity.is_verbose() {
111 println!("\n{:#?}", res); 111 println!("\n{:#?}", res);
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index d0a71120a..8eaf75ff6 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -22,7 +22,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
22 SourceRootId(r.0) 22 SourceRootId(r.0)
23} 23}
24 24
25pub(crate) fn load_cargo( 25pub fn load_cargo(
26 root: &Path, 26 root: &Path,
27 load_out_dirs_from_check: bool, 27 load_out_dirs_from_check: bool,
28 with_proc_macro: bool, 28 with_proc_macro: bool,
@@ -149,7 +149,7 @@ pub(crate) fn load(
149 149
150 // FIXME: cfg options? 150 // FIXME: cfg options?
151 let default_cfg_options = { 151 let default_cfg_options = {
152 let mut opts = get_rustc_cfg_options(); 152 let mut opts = get_rustc_cfg_options(None);
153 opts.insert_atom("test".into()); 153 opts.insert_atom("test".into());
154 opts.insert_atom("debug_assertion".into()); 154 opts.insert_atom("debug_assertion".into());
155 opts 155 opts
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 177da94cc..d75c48597 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -9,9 +9,9 @@
9 9
10use std::{ffi::OsString, path::PathBuf}; 10use std::{ffi::OsString, path::PathBuf};
11 11
12use lsp_types::TextDocumentClientCapabilities; 12use lsp_types::ClientCapabilities;
13use ra_flycheck::FlycheckConfig; 13use ra_flycheck::FlycheckConfig;
14use ra_ide::{CompletionConfig, InlayHintsConfig}; 14use ra_ide::{AssistConfig, CompletionConfig, InlayHintsConfig};
15use ra_project_model::CargoConfig; 15use ra_project_model::CargoConfig;
16use serde::Deserialize; 16use serde::Deserialize;
17 17
@@ -32,7 +32,38 @@ pub struct Config {
32 32
33 pub inlay_hints: InlayHintsConfig, 33 pub inlay_hints: InlayHintsConfig,
34 pub completion: CompletionConfig, 34 pub completion: CompletionConfig,
35 pub assist: AssistConfig,
35 pub call_info_full: bool, 36 pub call_info_full: bool,
37 pub lens: LensConfig,
38}
39
40#[derive(Clone, Debug, PartialEq, Eq)]
41pub struct LensConfig {
42 pub run: bool,
43 pub debug: bool,
44 pub impementations: bool,
45}
46
47impl Default for LensConfig {
48 fn default() -> Self {
49 Self { run: true, debug: true, impementations: true }
50 }
51}
52
53impl LensConfig {
54 pub const NO_LENS: LensConfig = Self { run: false, debug: false, impementations: false };
55
56 pub fn any(&self) -> bool {
57 self.impementations || self.runnable()
58 }
59
60 pub fn none(&self) -> bool {
61 !self.any()
62 }
63
64 pub fn runnable(&self) -> bool {
65 self.run || self.debug
66 }
36} 67}
37 68
38#[derive(Debug, Clone)] 69#[derive(Debug, Clone)]
@@ -49,7 +80,6 @@ pub enum FilesWatcher {
49 80
50#[derive(Debug, Clone)] 81#[derive(Debug, Clone)]
51pub struct NotificationsConfig { 82pub struct NotificationsConfig {
52 pub workspace_loaded: bool,
53 pub cargo_toml_not_found: bool, 83 pub cargo_toml_not_found: bool,
54} 84}
55 85
@@ -71,6 +101,7 @@ pub struct ClientCapsConfig {
71 pub line_folding_only: bool, 101 pub line_folding_only: bool,
72 pub hierarchical_symbols: bool, 102 pub hierarchical_symbols: bool,
73 pub code_action_literals: bool, 103 pub code_action_literals: bool,
104 pub work_done_progress: bool,
74} 105}
75 106
76impl Default for Config { 107impl Default for Config {
@@ -83,16 +114,14 @@ impl Default for Config {
83 lru_capacity: None, 114 lru_capacity: None,
84 proc_macro_srv: None, 115 proc_macro_srv: None,
85 files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() }, 116 files: FilesConfig { watcher: FilesWatcher::Notify, exclude: Vec::new() },
86 notifications: NotificationsConfig { 117 notifications: NotificationsConfig { cargo_toml_not_found: true },
87 workspace_loaded: true,
88 cargo_toml_not_found: true,
89 },
90 118
91 cargo: CargoConfig::default(), 119 cargo: CargoConfig::default(),
92 rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() }, 120 rustfmt: RustfmtConfig::Rustfmt { extra_args: Vec::new() },
93 check: Some(FlycheckConfig::CargoCommand { 121 check: Some(FlycheckConfig::CargoCommand {
94 command: "check".to_string(), 122 command: "check".to_string(),
95 all_targets: true, 123 all_targets: true,
124 all_features: true,
96 extra_args: Vec::new(), 125 extra_args: Vec::new(),
97 }), 126 }),
98 127
@@ -108,7 +137,9 @@ impl Default for Config {
108 add_call_argument_snippets: true, 137 add_call_argument_snippets: true,
109 ..CompletionConfig::default() 138 ..CompletionConfig::default()
110 }, 139 },
140 assist: AssistConfig::default(),
111 call_info_full: true, 141 call_info_full: true,
142 lens: LensConfig::default(),
112 } 143 }
113 } 144 }
114} 145}
@@ -129,13 +160,13 @@ impl Config {
129 Some("client") => FilesWatcher::Client, 160 Some("client") => FilesWatcher::Client,
130 Some("notify") | _ => FilesWatcher::Notify 161 Some("notify") | _ => FilesWatcher::Notify
131 }; 162 };
132 set(value, "/notifications/workspaceLoaded", &mut self.notifications.workspace_loaded);
133 set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found); 163 set(value, "/notifications/cargoTomlNotFound", &mut self.notifications.cargo_toml_not_found);
134 164
135 set(value, "/cargo/noDefaultFeatures", &mut self.cargo.no_default_features); 165 set(value, "/cargo/noDefaultFeatures", &mut self.cargo.no_default_features);
136 set(value, "/cargo/allFeatures", &mut self.cargo.all_features); 166 set(value, "/cargo/allFeatures", &mut self.cargo.all_features);
137 set(value, "/cargo/features", &mut self.cargo.features); 167 set(value, "/cargo/features", &mut self.cargo.features);
138 set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); 168 set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check);
169 set(value, "/cargo/target", &mut self.cargo.target);
139 170
140 match get(value, "/procMacro/enable") { 171 match get(value, "/procMacro/enable") {
141 Some(true) => { 172 Some(true) => {
@@ -177,12 +208,13 @@ impl Config {
177 } 208 }
178 // otherwise configure command customizations 209 // otherwise configure command customizations
179 _ => { 210 _ => {
180 if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets }) 211 if let Some(FlycheckConfig::CargoCommand { command, extra_args, all_targets, all_features })
181 = &mut self.check 212 = &mut self.check
182 { 213 {
183 set(value, "/checkOnSave/extraArgs", extra_args); 214 set(value, "/checkOnSave/extraArgs", extra_args);
184 set(value, "/checkOnSave/command", command); 215 set(value, "/checkOnSave/command", command);
185 set(value, "/checkOnSave/allTargets", all_targets); 216 set(value, "/checkOnSave/allTargets", all_targets);
217 set(value, "/checkOnSave/allFeatures", all_features);
186 } 218 }
187 } 219 }
188 }; 220 };
@@ -197,6 +229,16 @@ impl Config {
197 set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets); 229 set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets);
198 set(value, "/callInfo/full", &mut self.call_info_full); 230 set(value, "/callInfo/full", &mut self.call_info_full);
199 231
232 let mut lens_enabled = true;
233 set(value, "/lens/enable", &mut lens_enabled);
234 if lens_enabled {
235 set(value, "/lens/run", &mut self.lens.run);
236 set(value, "/lens/debug", &mut self.lens.debug);
237 set(value, "/lens/implementations", &mut self.lens.impementations);
238 } else {
239 self.lens = LensConfig::NO_LENS;
240 }
241
200 log::info!("Config::update() = {:#?}", self); 242 log::info!("Config::update() = {:#?}", self);
201 243
202 fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> { 244 fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> {
@@ -210,30 +252,51 @@ impl Config {
210 } 252 }
211 } 253 }
212 254
213 pub fn update_caps(&mut self, caps: &TextDocumentClientCapabilities) { 255 pub fn update_caps(&mut self, caps: &ClientCapabilities) {
214 if let Some(value) = caps.definition.as_ref().and_then(|it| it.link_support) { 256 if let Some(doc_caps) = caps.text_document.as_ref() {
215 self.client_caps.location_link = value; 257 if let Some(value) = doc_caps.definition.as_ref().and_then(|it| it.link_support) {
216 } 258 self.client_caps.location_link = value;
217 if let Some(value) = caps.folding_range.as_ref().and_then(|it| it.line_folding_only) { 259 }
218 self.client_caps.line_folding_only = value 260 if let Some(value) = doc_caps.folding_range.as_ref().and_then(|it| it.line_folding_only)
219 } 261 {
220 if let Some(value) = 262 self.client_caps.line_folding_only = value
221 caps.document_symbol.as_ref().and_then(|it| it.hierarchical_document_symbol_support) 263 }
222 { 264 if let Some(value) = doc_caps
223 self.client_caps.hierarchical_symbols = value 265 .document_symbol
224 } 266 .as_ref()
225 if let Some(value) = 267 .and_then(|it| it.hierarchical_document_symbol_support)
226 caps.code_action.as_ref().and_then(|it| Some(it.code_action_literal_support.is_some())) 268 {
227 { 269 self.client_caps.hierarchical_symbols = value
228 self.client_caps.code_action_literals = value; 270 }
229 } 271 if let Some(value) = doc_caps
230 self.completion.allow_snippets(false); 272 .code_action
231 if let Some(completion) = &caps.completion { 273 .as_ref()
232 if let Some(completion_item) = &completion.completion_item { 274 .and_then(|it| Some(it.code_action_literal_support.is_some()))
233 if let Some(value) = completion_item.snippet_support { 275 {
234 self.completion.allow_snippets(value); 276 self.client_caps.code_action_literals = value;
277 }
278
279 self.completion.allow_snippets(false);
280 if let Some(completion) = &doc_caps.completion {
281 if let Some(completion_item) = &completion.completion_item {
282 if let Some(value) = completion_item.snippet_support {
283 self.completion.allow_snippets(value);
284 }
235 } 285 }
236 } 286 }
237 } 287 }
288
289 if let Some(window_caps) = caps.window.as_ref() {
290 if let Some(value) = window_caps.work_done_progress {
291 self.client_caps.work_done_progress = value;
292 }
293 }
294
295 self.assist.allow_snippets(false);
296 if let Some(experimental) = &caps.experimental {
297 let enable =
298 experimental.get("snippetTextEdit").and_then(|it| it.as_bool()) == Some(true);
299 self.assist.allow_snippets(enable);
300 }
238 } 301 }
239} 302}
diff --git a/crates/rust-analyzer/src/conv.rs b/crates/rust-analyzer/src/conv.rs
deleted file mode 100644
index 7be5ebcdb..000000000
--- a/crates/rust-analyzer/src/conv.rs
+++ /dev/null
@@ -1,727 +0,0 @@
1//! Convenience module responsible for translating between rust-analyzer's types
2//! and LSP types.
3
4use lsp_types::{
5 self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation,
6 Location, LocationLink, MarkupContent, MarkupKind, ParameterInformation, ParameterLabel,
7 Position, Range, RenameFile, ResourceOp, SemanticTokenModifier, SemanticTokenType,
8 SignatureInformation, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, TextDocumentItem,
9 TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, WorkspaceEdit,
10};
11use ra_ide::{
12 translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
13 FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag,
14 InlayHint, InlayKind, InsertTextFormat, LineCol, LineIndex, NavigationTarget, RangeInfo,
15 ReferenceAccess, Severity, SourceChange, SourceFileEdit,
16};
17use ra_syntax::{SyntaxKind, TextRange, TextSize};
18use ra_text_edit::{AtomTextEdit, TextEdit};
19use ra_vfs::LineEndings;
20
21use crate::{
22 req,
23 semantic_tokens::{self, ModifierSet, CONSTANT, CONTROL_FLOW, MUTABLE, UNSAFE},
24 world::WorldSnapshot,
25 Result,
26};
27use semantic_tokens::{
28 ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, FORMAT_SPECIFIER, LIFETIME, TYPE_ALIAS, UNION,
29 UNRESOLVED_REFERENCE,
30};
31
32pub trait Conv {
33 type Output;
34 fn conv(self) -> Self::Output;
35}
36
37pub trait ConvWith<CTX> {
38 type Output;
39 fn conv_with(self, ctx: CTX) -> Self::Output;
40}
41
42pub trait TryConvWith<CTX> {
43 type Output;
44 fn try_conv_with(self, ctx: CTX) -> Result<Self::Output>;
45}
46
47impl Conv for SyntaxKind {
48 type Output = SymbolKind;
49
50 fn conv(self) -> <Self as Conv>::Output {
51 match self {
52 SyntaxKind::FN_DEF => SymbolKind::Function,
53 SyntaxKind::STRUCT_DEF => SymbolKind::Struct,
54 SyntaxKind::ENUM_DEF => SymbolKind::Enum,
55 SyntaxKind::ENUM_VARIANT => SymbolKind::EnumMember,
56 SyntaxKind::TRAIT_DEF => SymbolKind::Interface,
57 SyntaxKind::MACRO_CALL => SymbolKind::Function,
58 SyntaxKind::MODULE => SymbolKind::Module,
59 SyntaxKind::TYPE_ALIAS_DEF => SymbolKind::TypeParameter,
60 SyntaxKind::RECORD_FIELD_DEF => SymbolKind::Field,
61 SyntaxKind::STATIC_DEF => SymbolKind::Constant,
62 SyntaxKind::CONST_DEF => SymbolKind::Constant,
63 SyntaxKind::IMPL_DEF => SymbolKind::Object,
64 _ => SymbolKind::Variable,
65 }
66 }
67}
68
69impl Conv for ReferenceAccess {
70 type Output = ::lsp_types::DocumentHighlightKind;
71
72 fn conv(self) -> Self::Output {
73 use lsp_types::DocumentHighlightKind;
74 match self {
75 ReferenceAccess::Read => DocumentHighlightKind::Read,
76 ReferenceAccess::Write => DocumentHighlightKind::Write,
77 }
78 }
79}
80
81impl Conv for CompletionItemKind {
82 type Output = ::lsp_types::CompletionItemKind;
83
84 fn conv(self) -> <Self as Conv>::Output {
85 use lsp_types::CompletionItemKind::*;
86 match self {
87 CompletionItemKind::Keyword => Keyword,
88 CompletionItemKind::Snippet => Snippet,
89 CompletionItemKind::Module => Module,
90 CompletionItemKind::Function => Function,
91 CompletionItemKind::Struct => Struct,
92 CompletionItemKind::Enum => Enum,
93 CompletionItemKind::EnumVariant => EnumMember,
94 CompletionItemKind::BuiltinType => Struct,
95 CompletionItemKind::Binding => Variable,
96 CompletionItemKind::Field => Field,
97 CompletionItemKind::Trait => Interface,
98 CompletionItemKind::TypeAlias => Struct,
99 CompletionItemKind::Const => Constant,
100 CompletionItemKind::Static => Value,
101 CompletionItemKind::Method => Method,
102 CompletionItemKind::TypeParam => TypeParameter,
103 CompletionItemKind::Macro => Method,
104 CompletionItemKind::Attribute => EnumMember,
105 }
106 }
107}
108
109impl Conv for Severity {
110 type Output = DiagnosticSeverity;
111 fn conv(self) -> DiagnosticSeverity {
112 match self {
113 Severity::Error => DiagnosticSeverity::Error,
114 Severity::WeakWarning => DiagnosticSeverity::Hint,
115 }
116 }
117}
118
119impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem {
120 type Output = ::lsp_types::CompletionItem;
121
122 fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionItem {
123 let mut additional_text_edits = Vec::new();
124 let mut text_edit = None;
125 // LSP does not allow arbitrary edits in completion, so we have to do a
126 // non-trivial mapping here.
127 for atom_edit in self.text_edit().as_atoms() {
128 if atom_edit.delete.contains_range(self.source_range()) {
129 text_edit = Some(if atom_edit.delete == self.source_range() {
130 atom_edit.conv_with((ctx.0, ctx.1))
131 } else {
132 assert!(self.source_range().end() == atom_edit.delete.end());
133 let range1 =
134 TextRange::new(atom_edit.delete.start(), self.source_range().start());
135 let range2 = self.source_range();
136 let edit1 = AtomTextEdit::replace(range1, String::new());
137 let edit2 = AtomTextEdit::replace(range2, atom_edit.insert.clone());
138 additional_text_edits.push(edit1.conv_with((ctx.0, ctx.1)));
139 edit2.conv_with((ctx.0, ctx.1))
140 })
141 } else {
142 assert!(self.source_range().intersect(atom_edit.delete).is_none());
143 additional_text_edits.push(atom_edit.conv_with((ctx.0, ctx.1)));
144 }
145 }
146 let text_edit = text_edit.unwrap();
147
148 let mut res = lsp_types::CompletionItem {
149 label: self.label().to_string(),
150 detail: self.detail().map(|it| it.to_string()),
151 filter_text: Some(self.lookup().to_string()),
152 kind: self.kind().map(|it| it.conv()),
153 text_edit: Some(text_edit.into()),
154 additional_text_edits: Some(additional_text_edits),
155 documentation: self.documentation().map(|it| it.conv()),
156 deprecated: Some(self.deprecated()),
157 command: if self.trigger_call_info() {
158 let cmd = lsp_types::Command {
159 title: "triggerParameterHints".into(),
160 command: "editor.action.triggerParameterHints".into(),
161 arguments: None,
162 };
163 Some(cmd)
164 } else {
165 None
166 },
167 ..Default::default()
168 };
169
170 if self.score().is_some() {
171 res.preselect = Some(true)
172 }
173
174 if self.deprecated() {
175 res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated])
176 }
177
178 res.insert_text_format = Some(match self.insert_text_format() {
179 InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet,
180 InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText,
181 });
182
183 res
184 }
185}
186
187impl ConvWith<&LineIndex> for Position {
188 type Output = TextSize;
189
190 fn conv_with(self, line_index: &LineIndex) -> TextSize {
191 let line_col = LineCol { line: self.line as u32, col_utf16: self.character as u32 };
192 line_index.offset(line_col)
193 }
194}
195
196impl ConvWith<&LineIndex> for TextSize {
197 type Output = Position;
198
199 fn conv_with(self, line_index: &LineIndex) -> Position {
200 let line_col = line_index.line_col(self);
201 Position::new(u64::from(line_col.line), u64::from(line_col.col_utf16))
202 }
203}
204
205impl ConvWith<&LineIndex> for TextRange {
206 type Output = Range;
207
208 fn conv_with(self, line_index: &LineIndex) -> Range {
209 Range::new(self.start().conv_with(line_index), self.end().conv_with(line_index))
210 }
211}
212
213impl ConvWith<&LineIndex> for Range {
214 type Output = TextRange;
215
216 fn conv_with(self, line_index: &LineIndex) -> TextRange {
217 TextRange::new(self.start.conv_with(line_index), self.end.conv_with(line_index))
218 }
219}
220
221impl Conv for ra_ide::Documentation {
222 type Output = lsp_types::Documentation;
223 fn conv(self) -> Documentation {
224 Documentation::MarkupContent(MarkupContent {
225 kind: MarkupKind::Markdown,
226 value: crate::markdown::format_docs(self.as_str()),
227 })
228 }
229}
230
231impl ConvWith<bool> for ra_ide::FunctionSignature {
232 type Output = lsp_types::SignatureInformation;
233 fn conv_with(self, concise: bool) -> Self::Output {
234 let (label, documentation, params) = if concise {
235 let mut params = self.parameters;
236 if self.has_self_param {
237 params.remove(0);
238 }
239 (params.join(", "), None, params)
240 } else {
241 (self.to_string(), self.doc.map(|it| it.conv()), self.parameters)
242 };
243
244 let parameters: Vec<ParameterInformation> = params
245 .into_iter()
246 .map(|param| ParameterInformation {
247 label: ParameterLabel::Simple(param),
248 documentation: None,
249 })
250 .collect();
251
252 SignatureInformation { label, documentation, parameters: Some(parameters) }
253 }
254}
255
256impl ConvWith<(&LineIndex, LineEndings)> for TextEdit {
257 type Output = Vec<lsp_types::TextEdit>;
258
259 fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> Vec<lsp_types::TextEdit> {
260 self.as_atoms().iter().map_conv_with(ctx).collect()
261 }
262}
263
264impl ConvWith<(&LineIndex, LineEndings)> for &AtomTextEdit {
265 type Output = lsp_types::TextEdit;
266
267 fn conv_with(
268 self,
269 (line_index, line_endings): (&LineIndex, LineEndings),
270 ) -> lsp_types::TextEdit {
271 let mut new_text = self.insert.clone();
272 if line_endings == LineEndings::Dos {
273 new_text = new_text.replace('\n', "\r\n");
274 }
275 lsp_types::TextEdit { range: self.delete.conv_with(line_index), new_text }
276 }
277}
278
279pub(crate) struct FoldConvCtx<'a> {
280 pub(crate) text: &'a str,
281 pub(crate) line_index: &'a LineIndex,
282 pub(crate) line_folding_only: bool,
283}
284
285impl ConvWith<&FoldConvCtx<'_>> for Fold {
286 type Output = lsp_types::FoldingRange;
287
288 fn conv_with(self, ctx: &FoldConvCtx) -> lsp_types::FoldingRange {
289 let kind = match self.kind {
290 FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
291 FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
292 FoldKind::Mods => None,
293 FoldKind::Block => None,
294 };
295
296 let range = self.range.conv_with(&ctx.line_index);
297
298 if ctx.line_folding_only {
299 // Clients with line_folding_only == true (such as VSCode) will fold the whole end line
300 // even if it contains text not in the folding range. To prevent that we exclude
301 // range.end.line from the folding region if there is more text after range.end
302 // on the same line.
303 let has_more_text_on_end_line = ctx.text
304 [TextRange::new(self.range.end(), TextSize::of(ctx.text))]
305 .chars()
306 .take_while(|it| *it != '\n')
307 .any(|it| !it.is_whitespace());
308
309 let end_line = if has_more_text_on_end_line {
310 range.end.line.saturating_sub(1)
311 } else {
312 range.end.line
313 };
314
315 lsp_types::FoldingRange {
316 start_line: range.start.line,
317 start_character: None,
318 end_line,
319 end_character: None,
320 kind,
321 }
322 } else {
323 lsp_types::FoldingRange {
324 start_line: range.start.line,
325 start_character: Some(range.start.character),
326 end_line: range.end.line,
327 end_character: Some(range.end.character),
328 kind,
329 }
330 }
331 }
332}
333
334impl ConvWith<&LineIndex> for InlayHint {
335 type Output = req::InlayHint;
336 fn conv_with(self, line_index: &LineIndex) -> Self::Output {
337 req::InlayHint {
338 label: self.label.to_string(),
339 range: self.range.conv_with(line_index),
340 kind: match self.kind {
341 InlayKind::ParameterHint => req::InlayKind::ParameterHint,
342 InlayKind::TypeHint => req::InlayKind::TypeHint,
343 InlayKind::ChainingHint => req::InlayKind::ChainingHint,
344 },
345 }
346 }
347}
348
349impl Conv for Highlight {
350 type Output = (u32, u32);
351
352 fn conv(self) -> Self::Output {
353 let mut mods = ModifierSet::default();
354 let type_ = match self.tag {
355 HighlightTag::Struct => SemanticTokenType::STRUCT,
356 HighlightTag::Enum => SemanticTokenType::ENUM,
357 HighlightTag::Union => UNION,
358 HighlightTag::TypeAlias => TYPE_ALIAS,
359 HighlightTag::Trait => SemanticTokenType::INTERFACE,
360 HighlightTag::BuiltinType => BUILTIN_TYPE,
361 HighlightTag::SelfType => SemanticTokenType::TYPE,
362 HighlightTag::Field => SemanticTokenType::MEMBER,
363 HighlightTag::Function => SemanticTokenType::FUNCTION,
364 HighlightTag::Module => SemanticTokenType::NAMESPACE,
365 HighlightTag::Constant => {
366 mods |= CONSTANT;
367 mods |= SemanticTokenModifier::STATIC;
368 SemanticTokenType::VARIABLE
369 }
370 HighlightTag::Static => {
371 mods |= SemanticTokenModifier::STATIC;
372 SemanticTokenType::VARIABLE
373 }
374 HighlightTag::EnumVariant => ENUM_MEMBER,
375 HighlightTag::Macro => SemanticTokenType::MACRO,
376 HighlightTag::Local => SemanticTokenType::VARIABLE,
377 HighlightTag::TypeParam => SemanticTokenType::TYPE_PARAMETER,
378 HighlightTag::Lifetime => LIFETIME,
379 HighlightTag::ByteLiteral | HighlightTag::NumericLiteral => SemanticTokenType::NUMBER,
380 HighlightTag::CharLiteral | HighlightTag::StringLiteral => SemanticTokenType::STRING,
381 HighlightTag::Comment => SemanticTokenType::COMMENT,
382 HighlightTag::Attribute => ATTRIBUTE,
383 HighlightTag::Keyword => SemanticTokenType::KEYWORD,
384 HighlightTag::UnresolvedReference => UNRESOLVED_REFERENCE,
385 HighlightTag::FormatSpecifier => FORMAT_SPECIFIER,
386 };
387
388 for modifier in self.modifiers.iter() {
389 let modifier = match modifier {
390 HighlightModifier::Definition => SemanticTokenModifier::DECLARATION,
391 HighlightModifier::ControlFlow => CONTROL_FLOW,
392 HighlightModifier::Mutable => MUTABLE,
393 HighlightModifier::Unsafe => UNSAFE,
394 };
395 mods |= modifier;
396 }
397
398 (semantic_tokens::type_index(type_), mods.0)
399 }
400}
401
402impl<T: ConvWith<CTX>, CTX> ConvWith<CTX> for Option<T> {
403 type Output = Option<T::Output>;
404
405 fn conv_with(self, ctx: CTX) -> Self::Output {
406 self.map(|x| ConvWith::conv_with(x, ctx))
407 }
408}
409
410impl TryConvWith<&WorldSnapshot> for &Url {
411 type Output = FileId;
412 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> {
413 world.uri_to_file_id(self)
414 }
415}
416
417impl TryConvWith<&WorldSnapshot> for FileId {
418 type Output = Url;
419 fn try_conv_with(self, world: &WorldSnapshot) -> Result<Url> {
420 world.file_id_to_uri(self)
421 }
422}
423
424impl TryConvWith<&WorldSnapshot> for &TextDocumentItem {
425 type Output = FileId;
426 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> {
427 self.uri.try_conv_with(world)
428 }
429}
430
431impl TryConvWith<&WorldSnapshot> for &VersionedTextDocumentIdentifier {
432 type Output = FileId;
433 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> {
434 self.uri.try_conv_with(world)
435 }
436}
437
438impl TryConvWith<&WorldSnapshot> for &TextDocumentIdentifier {
439 type Output = FileId;
440 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileId> {
441 world.uri_to_file_id(&self.uri)
442 }
443}
444
445impl TryConvWith<&WorldSnapshot> for &TextDocumentPositionParams {
446 type Output = FilePosition;
447 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FilePosition> {
448 let file_id = self.text_document.try_conv_with(world)?;
449 let line_index = world.analysis().file_line_index(file_id)?;
450 let offset = self.position.conv_with(&line_index);
451 Ok(FilePosition { file_id, offset })
452 }
453}
454
455impl TryConvWith<&WorldSnapshot> for (&TextDocumentIdentifier, Range) {
456 type Output = FileRange;
457 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileRange> {
458 let file_id = self.0.try_conv_with(world)?;
459 let line_index = world.analysis().file_line_index(file_id)?;
460 let range = self.1.conv_with(&line_index);
461 Ok(FileRange { file_id, range })
462 }
463}
464
465impl<T: TryConvWith<CTX>, CTX: Copy> TryConvWith<CTX> for Vec<T> {
466 type Output = Vec<<T as TryConvWith<CTX>>::Output>;
467 fn try_conv_with(self, ctx: CTX) -> Result<Self::Output> {
468 let mut res = Vec::with_capacity(self.len());
469 for item in self {
470 res.push(item.try_conv_with(ctx)?);
471 }
472 Ok(res)
473 }
474}
475
476impl TryConvWith<&WorldSnapshot> for SourceChange {
477 type Output = req::SourceChange;
478 fn try_conv_with(self, world: &WorldSnapshot) -> Result<req::SourceChange> {
479 let cursor_position = match self.cursor_position {
480 None => None,
481 Some(pos) => {
482 let line_index = world.analysis().file_line_index(pos.file_id)?;
483 let edit = self
484 .source_file_edits
485 .iter()
486 .find(|it| it.file_id == pos.file_id)
487 .map(|it| &it.edit);
488 let line_col = match edit {
489 Some(edit) => translate_offset_with_edit(&*line_index, pos.offset, edit),
490 None => line_index.line_col(pos.offset),
491 };
492 let position =
493 Position::new(u64::from(line_col.line), u64::from(line_col.col_utf16));
494 Some(TextDocumentPositionParams {
495 text_document: TextDocumentIdentifier::new(pos.file_id.try_conv_with(world)?),
496 position,
497 })
498 }
499 };
500 let mut document_changes: Vec<DocumentChangeOperation> = Vec::new();
501 for resource_op in self.file_system_edits.try_conv_with(world)? {
502 document_changes.push(DocumentChangeOperation::Op(resource_op));
503 }
504 for text_document_edit in self.source_file_edits.try_conv_with(world)? {
505 document_changes.push(DocumentChangeOperation::Edit(text_document_edit));
506 }
507 let workspace_edit = WorkspaceEdit {
508 changes: None,
509 document_changes: Some(DocumentChanges::Operations(document_changes)),
510 };
511 Ok(req::SourceChange { label: self.label, workspace_edit, cursor_position })
512 }
513}
514
515impl TryConvWith<&WorldSnapshot> for SourceFileEdit {
516 type Output = TextDocumentEdit;
517 fn try_conv_with(self, world: &WorldSnapshot) -> Result<TextDocumentEdit> {
518 let text_document = VersionedTextDocumentIdentifier {
519 uri: self.file_id.try_conv_with(world)?,
520 version: None,
521 };
522 let line_index = world.analysis().file_line_index(self.file_id)?;
523 let line_endings = world.file_line_endings(self.file_id);
524 let edits =
525 self.edit.as_atoms().iter().map_conv_with((&line_index, line_endings)).collect();
526 Ok(TextDocumentEdit { text_document, edits })
527 }
528}
529
530impl TryConvWith<&WorldSnapshot> for FileSystemEdit {
531 type Output = ResourceOp;
532 fn try_conv_with(self, world: &WorldSnapshot) -> Result<ResourceOp> {
533 let res = match self {
534 FileSystemEdit::CreateFile { source_root, path } => {
535 let uri = world.path_to_uri(source_root, &path)?;
536 ResourceOp::Create(CreateFile { uri, options: None })
537 }
538 FileSystemEdit::MoveFile { src, dst_source_root, dst_path } => {
539 let old_uri = world.file_id_to_uri(src)?;
540 let new_uri = world.path_to_uri(dst_source_root, &dst_path)?;
541 ResourceOp::Rename(RenameFile { old_uri, new_uri, options: None })
542 }
543 };
544 Ok(res)
545 }
546}
547
548impl TryConvWith<&WorldSnapshot> for &NavigationTarget {
549 type Output = Location;
550 fn try_conv_with(self, world: &WorldSnapshot) -> Result<Location> {
551 let line_index = world.analysis().file_line_index(self.file_id())?;
552 let range = self.range();
553 to_location(self.file_id(), range, &world, &line_index)
554 }
555}
556
557impl TryConvWith<&WorldSnapshot> for (FileId, RangeInfo<NavigationTarget>) {
558 type Output = LocationLink;
559 fn try_conv_with(self, world: &WorldSnapshot) -> Result<LocationLink> {
560 let (src_file_id, target) = self;
561
562 let target_uri = target.info.file_id().try_conv_with(world)?;
563 let src_line_index = world.analysis().file_line_index(src_file_id)?;
564 let tgt_line_index = world.analysis().file_line_index(target.info.file_id())?;
565
566 let target_range = target.info.full_range().conv_with(&tgt_line_index);
567
568 let target_selection_range = target
569 .info
570 .focus_range()
571 .map(|it| it.conv_with(&tgt_line_index))
572 .unwrap_or(target_range);
573
574 let res = LocationLink {
575 origin_selection_range: Some(target.range.conv_with(&src_line_index)),
576 target_uri,
577 target_range,
578 target_selection_range,
579 };
580 Ok(res)
581 }
582}
583
584impl TryConvWith<&WorldSnapshot> for (FileId, RangeInfo<Vec<NavigationTarget>>) {
585 type Output = req::GotoDefinitionResponse;
586 fn try_conv_with(self, world: &WorldSnapshot) -> Result<req::GotoTypeDefinitionResponse> {
587 let (file_id, RangeInfo { range, info: navs }) = self;
588 let links = navs
589 .into_iter()
590 .map(|nav| (file_id, RangeInfo::new(range, nav)))
591 .try_conv_with_to_vec(world)?;
592 if world.config.client_caps.location_link {
593 Ok(links.into())
594 } else {
595 let locations: Vec<Location> = links
596 .into_iter()
597 .map(|link| Location { uri: link.target_uri, range: link.target_selection_range })
598 .collect();
599 Ok(locations.into())
600 }
601 }
602}
603
604pub fn to_call_hierarchy_item(
605 file_id: FileId,
606 range: TextRange,
607 world: &WorldSnapshot,
608 line_index: &LineIndex,
609 nav: NavigationTarget,
610) -> Result<lsp_types::CallHierarchyItem> {
611 Ok(lsp_types::CallHierarchyItem {
612 name: nav.name().to_string(),
613 kind: nav.kind().conv(),
614 tags: None,
615 detail: nav.description().map(|it| it.to_string()),
616 uri: file_id.try_conv_with(&world)?,
617 range: nav.range().conv_with(&line_index),
618 selection_range: range.conv_with(&line_index),
619 })
620}
621
622pub fn to_location(
623 file_id: FileId,
624 range: TextRange,
625 world: &WorldSnapshot,
626 line_index: &LineIndex,
627) -> Result<Location> {
628 let url = file_id.try_conv_with(world)?;
629 let loc = Location::new(url, range.conv_with(line_index));
630 Ok(loc)
631}
632
633pub trait MapConvWith<CTX>: Sized {
634 type Output;
635
636 fn map_conv_with(self, ctx: CTX) -> ConvWithIter<Self, CTX> {
637 ConvWithIter { iter: self, ctx }
638 }
639}
640
641impl<CTX, I> MapConvWith<CTX> for I
642where
643 I: Iterator,
644 I::Item: ConvWith<CTX>,
645{
646 type Output = <I::Item as ConvWith<CTX>>::Output;
647}
648
649pub struct ConvWithIter<I, CTX> {
650 iter: I,
651 ctx: CTX,
652}
653
654impl<I, CTX> Iterator for ConvWithIter<I, CTX>
655where
656 I: Iterator,
657 I::Item: ConvWith<CTX>,
658 CTX: Copy,
659{
660 type Item = <I::Item as ConvWith<CTX>>::Output;
661
662 fn next(&mut self) -> Option<Self::Item> {
663 self.iter.next().map(|item| item.conv_with(self.ctx))
664 }
665}
666
667pub trait TryConvWithToVec<CTX>: Sized {
668 type Output;
669
670 fn try_conv_with_to_vec(self, ctx: CTX) -> Result<Vec<Self::Output>>;
671}
672
673impl<I, CTX> TryConvWithToVec<CTX> for I
674where
675 I: Iterator,
676 I::Item: TryConvWith<CTX>,
677 CTX: Copy,
678{
679 type Output = <I::Item as TryConvWith<CTX>>::Output;
680
681 fn try_conv_with_to_vec(self, ctx: CTX) -> Result<Vec<Self::Output>> {
682 self.map(|it| it.try_conv_with(ctx)).collect()
683 }
684}
685
686#[cfg(test)]
687mod tests {
688 use super::*;
689 use test_utils::extract_ranges;
690
691 #[test]
692 fn conv_fold_line_folding_only_fixup() {
693 let text = r#"<fold>mod a;
694mod b;
695mod c;</fold>
696
697fn main() <fold>{
698 if cond <fold>{
699 a::do_a();
700 }</fold> else <fold>{
701 b::do_b();
702 }</fold>
703}</fold>"#;
704
705 let (ranges, text) = extract_ranges(text, "fold");
706 assert_eq!(ranges.len(), 4);
707 let folds = vec![
708 Fold { range: ranges[0], kind: FoldKind::Mods },
709 Fold { range: ranges[1], kind: FoldKind::Block },
710 Fold { range: ranges[2], kind: FoldKind::Block },
711 Fold { range: ranges[3], kind: FoldKind::Block },
712 ];
713
714 let line_index = LineIndex::new(&text);
715 let ctx = FoldConvCtx { text: &text, line_index: &line_index, line_folding_only: true };
716 let converted: Vec<_> = folds.into_iter().map_conv_with(&ctx).collect();
717
718 let expected_lines = [(0, 2), (4, 10), (5, 6), (7, 9)];
719 assert_eq!(converted.len(), expected_lines.len());
720 for (folding_range, (start_line, end_line)) in converted.iter().zip(expected_lines.iter()) {
721 assert_eq!(folding_range.start_line, *start_line);
722 assert_eq!(folding_range.start_character, None);
723 assert_eq!(folding_range.end_line, *end_line);
724 assert_eq!(folding_range.end_character, None);
725 }
726 }
727}
diff --git a/crates/rust-analyzer/src/diagnostics.rs b/crates/rust-analyzer/src/diagnostics.rs
index e7924f0a3..25856c543 100644
--- a/crates/rust-analyzer/src/diagnostics.rs
+++ b/crates/rust-analyzer/src/diagnostics.rs
@@ -1,10 +1,13 @@
1//! Book keeping for keeping diagnostics easily in sync with the client. 1//! Book keeping for keeping diagnostics easily in sync with the client.
2pub(crate) mod to_proto;
2 3
3use std::{collections::HashMap, sync::Arc}; 4use std::{collections::HashMap, sync::Arc};
4 5
5use lsp_types::{CodeActionOrCommand, Diagnostic, Range}; 6use lsp_types::{Diagnostic, Range};
6use ra_ide::FileId; 7use ra_ide::FileId;
7 8
9use crate::lsp_ext;
10
8pub type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>; 11pub type CheckFixes = Arc<HashMap<FileId, Vec<Fix>>>;
9 12
10#[derive(Debug, Default, Clone)] 13#[derive(Debug, Default, Clone)]
@@ -17,13 +20,13 @@ pub struct DiagnosticCollection {
17#[derive(Debug, Clone)] 20#[derive(Debug, Clone)]
18pub struct Fix { 21pub struct Fix {
19 pub range: Range, 22 pub range: Range,
20 pub action: CodeActionOrCommand, 23 pub action: lsp_ext::CodeAction,
21} 24}
22 25
23#[derive(Debug)] 26#[derive(Debug)]
24pub enum DiagnosticTask { 27pub enum DiagnosticTask {
25 ClearCheck, 28 ClearCheck,
26 AddCheck(FileId, Diagnostic, Vec<CodeActionOrCommand>), 29 AddCheck(FileId, Diagnostic, Vec<lsp_ext::CodeAction>),
27 SetNative(FileId, Vec<Diagnostic>), 30 SetNative(FileId, Vec<Diagnostic>),
28} 31}
29 32
@@ -37,7 +40,7 @@ impl DiagnosticCollection {
37 &mut self, 40 &mut self,
38 file_id: FileId, 41 file_id: FileId,
39 diagnostic: Diagnostic, 42 diagnostic: Diagnostic,
40 fixes: Vec<CodeActionOrCommand>, 43 fixes: Vec<lsp_ext::CodeAction>,
41 ) { 44 ) {
42 let diagnostics = self.check.entry(file_id).or_default(); 45 let diagnostics = self.check.entry(file_id).or_default();
43 for existing_diagnostic in diagnostics.iter() { 46 for existing_diagnostic in diagnostics.iter() {
diff --git a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_clippy_pass_by_ref.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_clippy_pass_by_ref.snap
index 4c9db0385..d7f9ec049 100644
--- a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_clippy_pass_by_ref.snap
+++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_clippy_pass_by_ref.snap
@@ -1,5 +1,5 @@
1--- 1---
2source: crates/ra_flycheck/src/conv/test.rs 2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: diag 3expression: diag
4--- 4---
5[ 5[
diff --git a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_handles_macro_location.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_handles_macro_location.snap
index 7cde4d867..a59faf254 100644
--- a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_handles_macro_location.snap
+++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_handles_macro_location.snap
@@ -1,5 +1,5 @@
1--- 1---
2source: crates/ra_flycheck/src/conv/test.rs 2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: diag 3expression: diag
4--- 4---
5[ 5[
diff --git a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_macro_compiler_error.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_macro_compiler_error.snap
index 1cc37e087..3c78e7f36 100644
--- a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_macro_compiler_error.snap
+++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_macro_compiler_error.snap
@@ -1,5 +1,5 @@
1--- 1---
2source: crates/ra_flycheck/src/conv/test.rs 2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: diag 3expression: diag
4--- 4---
5[ 5[
diff --git a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_multi_line_fix.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap
index 615ed8378..96466b5c9 100644
--- a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_multi_line_fix.snap
+++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_multi_line_fix.snap
@@ -1,5 +1,5 @@
1--- 1---
2source: crates/ra_flycheck/src/conv/test.rs 2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: diag 3expression: diag
4--- 4---
5[ 5[
@@ -68,9 +68,9 @@ expression: diag
68 kind: Some( 68 kind: Some(
69 "quickfix", 69 "quickfix",
70 ), 70 ),
71 diagnostics: None, 71 command: None,
72 edit: Some( 72 edit: Some(
73 WorkspaceEdit { 73 SnippetWorkspaceEdit {
74 changes: Some( 74 changes: Some(
75 { 75 {
76 "file:///test/src/main.rs": [ 76 "file:///test/src/main.rs": [
@@ -106,8 +106,6 @@ expression: diag
106 document_changes: None, 106 document_changes: None,
107 }, 107 },
108 ), 108 ),
109 command: None,
110 is_preferred: None,
111 }, 109 },
112 ], 110 ],
113 }, 111 },
diff --git a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_incompatible_type_for_trait.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_incompatible_type_for_trait.snap
index 0df0fce18..46d0c56d2 100644
--- a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_incompatible_type_for_trait.snap
+++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_incompatible_type_for_trait.snap
@@ -1,5 +1,5 @@
1--- 1---
2source: crates/ra_flycheck/src/conv/test.rs 2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: diag 3expression: diag
4--- 4---
5[ 5[
diff --git a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_mismatched_type.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_mismatched_type.snap
index 28ebcb3b3..4182929ba 100644
--- a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_mismatched_type.snap
+++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_mismatched_type.snap
@@ -1,5 +1,5 @@
1--- 1---
2source: crates/ra_flycheck/src/conv/test.rs 2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: diag 3expression: diag
4--- 4---
5[ 5[
diff --git a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_unused_variable.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap
index 5e0873281..8f962277f 100644
--- a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_unused_variable.snap
+++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_unused_variable.snap
@@ -1,5 +1,5 @@
1--- 1---
2source: crates/ra_flycheck/src/conv/test.rs 2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: diag 3expression: diag
4--- 4---
5[ 5[
@@ -53,9 +53,9 @@ expression: diag
53 kind: Some( 53 kind: Some(
54 "quickfix", 54 "quickfix",
55 ), 55 ),
56 diagnostics: None, 56 command: None,
57 edit: Some( 57 edit: Some(
58 WorkspaceEdit { 58 SnippetWorkspaceEdit {
59 changes: Some( 59 changes: Some(
60 { 60 {
61 "file:///test/driver/subcommand/repl.rs": [ 61 "file:///test/driver/subcommand/repl.rs": [
@@ -78,8 +78,6 @@ expression: diag
78 document_changes: None, 78 document_changes: None,
79 }, 79 },
80 ), 80 ),
81 command: None,
82 is_preferred: None,
83 }, 81 },
84 ], 82 ],
85 }, 83 },
diff --git a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_wrong_number_of_parameters.snap b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_wrong_number_of_parameters.snap
index e500d3cd6..f6ab05004 100644
--- a/crates/ra_flycheck/src/conv/snapshots/ra_flycheck__conv__test__snap_rustc_wrong_number_of_parameters.snap
+++ b/crates/rust-analyzer/src/diagnostics/snapshots/rust_analyzer__diagnostics__to_proto__tests__snap_rustc_wrong_number_of_parameters.snap
@@ -1,5 +1,5 @@
1--- 1---
2source: crates/ra_flycheck/src/conv/test.rs 2source: crates/rust-analyzer/src/diagnostics/to_proto.rs
3expression: diag 3expression: diag
4--- 4---
5[ 5[
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
new file mode 100644
index 000000000..afea59525
--- /dev/null
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -0,0 +1,1399 @@
1//! This module provides the functionality needed to convert diagnostics from
2//! `cargo check` json format to the LSP diagnostic format.
3use std::{
4 collections::HashMap,
5 path::{Component, Path, Prefix},
6 str::FromStr,
7};
8
9use lsp_types::{
10 Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, DiagnosticTag, Location,
11 NumberOrString, Position, Range, TextEdit, Url,
12};
13use ra_flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion};
14use stdx::format_to;
15
16use crate::{lsp_ext, Result};
17
18/// Converts a Rust level string to a LSP severity
19fn map_level_to_severity(val: DiagnosticLevel) -> Option<DiagnosticSeverity> {
20 let res = match val {
21 DiagnosticLevel::Ice => DiagnosticSeverity::Error,
22 DiagnosticLevel::Error => DiagnosticSeverity::Error,
23 DiagnosticLevel::Warning => DiagnosticSeverity::Warning,
24 DiagnosticLevel::Note => DiagnosticSeverity::Information,
25 DiagnosticLevel::Help => DiagnosticSeverity::Hint,
26 DiagnosticLevel::Unknown => return None,
27 };
28 Some(res)
29}
30
31/// Check whether a file name is from macro invocation
32fn is_from_macro(file_name: &str) -> bool {
33 file_name.starts_with('<') && file_name.ends_with('>')
34}
35
36/// Converts a Rust macro span to a LSP location recursively
37fn map_macro_span_to_location(
38 span_macro: &DiagnosticSpanMacroExpansion,
39 workspace_root: &Path,
40) -> Option<Location> {
41 if !is_from_macro(&span_macro.span.file_name) {
42 return Some(map_span_to_location(&span_macro.span, workspace_root));
43 }
44
45 if let Some(expansion) = &span_macro.span.expansion {
46 return map_macro_span_to_location(&expansion, workspace_root);
47 }
48
49 None
50}
51
52/// Converts a Rust span to a LSP location, resolving macro expansion site if neccesary
53fn map_span_to_location(span: &DiagnosticSpan, workspace_root: &Path) -> Location {
54 if span.expansion.is_some() {
55 let expansion = span.expansion.as_ref().unwrap();
56 if let Some(macro_range) = map_macro_span_to_location(&expansion, workspace_root) {
57 return macro_range;
58 }
59 }
60
61 map_span_to_location_naive(span, workspace_root)
62}
63
64/// Converts a Rust span to a LSP location
65fn map_span_to_location_naive(span: &DiagnosticSpan, workspace_root: &Path) -> Location {
66 let mut file_name = workspace_root.to_path_buf();
67 file_name.push(&span.file_name);
68 let uri = url_from_path_with_drive_lowercasing(file_name).unwrap();
69
70 // FIXME: this doesn't handle UTF16 offsets correctly
71 let range = Range::new(
72 Position::new(span.line_start as u64 - 1, span.column_start as u64 - 1),
73 Position::new(span.line_end as u64 - 1, span.column_end as u64 - 1),
74 );
75
76 Location { uri, range }
77}
78
79/// Converts a secondary Rust span to a LSP related information
80///
81/// If the span is unlabelled this will return `None`.
82fn map_secondary_span_to_related(
83 span: &DiagnosticSpan,
84 workspace_root: &Path,
85) -> Option<DiagnosticRelatedInformation> {
86 let message = span.label.clone()?;
87 let location = map_span_to_location(span, workspace_root);
88 Some(DiagnosticRelatedInformation { location, message })
89}
90
91/// Determines if diagnostic is related to unused code
92fn is_unused_or_unnecessary(rd: &ra_flycheck::Diagnostic) -> bool {
93 match &rd.code {
94 Some(code) => match code.code.as_str() {
95 "dead_code" | "unknown_lints" | "unreachable_code" | "unused_attributes"
96 | "unused_imports" | "unused_macros" | "unused_variables" => true,
97 _ => false,
98 },
99 None => false,
100 }
101}
102
103/// Determines if diagnostic is related to deprecated code
104fn is_deprecated(rd: &ra_flycheck::Diagnostic) -> bool {
105 match &rd.code {
106 Some(code) => code.code.as_str() == "deprecated",
107 None => false,
108 }
109}
110
111enum MappedRustChildDiagnostic {
112 Related(DiagnosticRelatedInformation),
113 SuggestedFix(lsp_ext::CodeAction),
114 MessageLine(String),
115}
116
117fn map_rust_child_diagnostic(
118 rd: &ra_flycheck::Diagnostic,
119 workspace_root: &Path,
120) -> MappedRustChildDiagnostic {
121 let spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect();
122 if spans.is_empty() {
123 // `rustc` uses these spanless children as a way to print multi-line
124 // messages
125 return MappedRustChildDiagnostic::MessageLine(rd.message.clone());
126 }
127
128 let mut edit_map: HashMap<Url, Vec<TextEdit>> = HashMap::new();
129 for &span in &spans {
130 match (&span.suggestion_applicability, &span.suggested_replacement) {
131 (Some(Applicability::MachineApplicable), Some(suggested_replacement)) => {
132 let location = map_span_to_location(span, workspace_root);
133 let edit = TextEdit::new(location.range, suggested_replacement.clone());
134 edit_map.entry(location.uri).or_default().push(edit);
135 }
136 _ => {}
137 }
138 }
139
140 if edit_map.is_empty() {
141 MappedRustChildDiagnostic::Related(DiagnosticRelatedInformation {
142 location: map_span_to_location(spans[0], workspace_root),
143 message: rd.message.clone(),
144 })
145 } else {
146 MappedRustChildDiagnostic::SuggestedFix(lsp_ext::CodeAction {
147 title: rd.message.clone(),
148 kind: Some("quickfix".to_string()),
149 edit: Some(lsp_ext::SnippetWorkspaceEdit {
150 // FIXME: there's no good reason to use edit_map here....
151 changes: Some(edit_map),
152 document_changes: None,
153 }),
154 command: None,
155 })
156 }
157}
158
159#[derive(Debug)]
160pub(crate) struct MappedRustDiagnostic {
161 pub location: Location,
162 pub diagnostic: Diagnostic,
163 pub fixes: Vec<lsp_ext::CodeAction>,
164}
165
166/// Converts a Rust root diagnostic to LSP form
167///
168/// This flattens the Rust diagnostic by:
169///
170/// 1. Creating a LSP diagnostic with the root message and primary span.
171/// 2. Adding any labelled secondary spans to `relatedInformation`
172/// 3. Categorising child diagnostics as either `SuggestedFix`es,
173/// `relatedInformation` or additional message lines.
174///
175/// If the diagnostic has no primary span this will return `None`
176pub(crate) fn map_rust_diagnostic_to_lsp(
177 rd: &ra_flycheck::Diagnostic,
178 workspace_root: &Path,
179) -> Vec<MappedRustDiagnostic> {
180 let primary_spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect();
181 if primary_spans.is_empty() {
182 return Vec::new();
183 }
184
185 let severity = map_level_to_severity(rd.level);
186
187 let mut source = String::from("rustc");
188 let mut code = rd.code.as_ref().map(|c| c.code.clone());
189 if let Some(code_val) = &code {
190 // See if this is an RFC #2103 scoped lint (e.g. from Clippy)
191 let scoped_code: Vec<&str> = code_val.split("::").collect();
192 if scoped_code.len() == 2 {
193 source = String::from(scoped_code[0]);
194 code = Some(String::from(scoped_code[1]));
195 }
196 }
197
198 let mut needs_primary_span_label = true;
199 let mut related_information = Vec::new();
200 let mut tags = Vec::new();
201
202 for secondary_span in rd.spans.iter().filter(|s| !s.is_primary) {
203 let related = map_secondary_span_to_related(secondary_span, workspace_root);
204 if let Some(related) = related {
205 related_information.push(related);
206 }
207 }
208
209 let mut fixes = Vec::new();
210 let mut message = rd.message.clone();
211 for child in &rd.children {
212 let child = map_rust_child_diagnostic(&child, workspace_root);
213 match child {
214 MappedRustChildDiagnostic::Related(related) => related_information.push(related),
215 MappedRustChildDiagnostic::SuggestedFix(code_action) => fixes.push(code_action),
216 MappedRustChildDiagnostic::MessageLine(message_line) => {
217 format_to!(message, "\n{}", message_line);
218
219 // These secondary messages usually duplicate the content of the
220 // primary span label.
221 needs_primary_span_label = false;
222 }
223 }
224 }
225
226 if is_unused_or_unnecessary(rd) {
227 tags.push(DiagnosticTag::Unnecessary);
228 }
229
230 if is_deprecated(rd) {
231 tags.push(DiagnosticTag::Deprecated);
232 }
233
234 primary_spans
235 .iter()
236 .map(|primary_span| {
237 let location = map_span_to_location(&primary_span, workspace_root);
238
239 let mut message = message.clone();
240 if needs_primary_span_label {
241 if let Some(primary_span_label) = &primary_span.label {
242 format_to!(message, "\n{}", primary_span_label);
243 }
244 }
245
246 // If error occurs from macro expansion, add related info pointing to
247 // where the error originated
248 if !is_from_macro(&primary_span.file_name) && primary_span.expansion.is_some() {
249 let def_loc = map_span_to_location_naive(&primary_span, workspace_root);
250 related_information.push(DiagnosticRelatedInformation {
251 location: def_loc,
252 message: "Error originated from macro here".to_string(),
253 });
254 }
255
256 let diagnostic = Diagnostic {
257 range: location.range,
258 severity,
259 code: code.clone().map(NumberOrString::String),
260 source: Some(source.clone()),
261 message,
262 related_information: if related_information.is_empty() {
263 None
264 } else {
265 Some(related_information.clone())
266 },
267 tags: if tags.is_empty() { None } else { Some(tags.clone()) },
268 };
269
270 MappedRustDiagnostic { location, diagnostic, fixes: fixes.clone() }
271 })
272 .collect()
273}
274
275/// Returns a `Url` object from a given path, will lowercase drive letters if present.
276/// This will only happen when processing windows paths.
277///
278/// When processing non-windows path, this is essentially the same as `Url::from_file_path`.
279pub fn url_from_path_with_drive_lowercasing(path: impl AsRef<Path>) -> Result<Url> {
280 let component_has_windows_drive = path.as_ref().components().any(|comp| {
281 if let Component::Prefix(c) = comp {
282 return matches!(c.kind(), Prefix::Disk(_) | Prefix::VerbatimDisk(_));
283 }
284 false
285 });
286
287 // VSCode expects drive letters to be lowercased, where rust will uppercase the drive letters.
288 let res = if component_has_windows_drive {
289 let url_original = Url::from_file_path(&path)
290 .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?;
291
292 let drive_partition: Vec<&str> = url_original.as_str().rsplitn(2, ':').collect();
293
294 // There is a drive partition, but we never found a colon.
295 // This should not happen, but in this case we just pass it through.
296 if drive_partition.len() == 1 {
297 return Ok(url_original);
298 }
299
300 let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0];
301 let url = Url::from_str(&joined).expect("This came from a valid `Url`");
302
303 url
304 } else {
305 Url::from_file_path(&path)
306 .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?
307 };
308 Ok(res)
309}
310
311#[cfg(test)]
312mod tests {
313 use super::*;
314
315 // `Url` is not able to parse windows paths on unix machines.
316 #[test]
317 #[cfg(target_os = "windows")]
318 fn test_lowercase_drive_letter_with_drive() {
319 let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap();
320
321 assert_eq!(url.to_string(), "file:///c:/Test");
322 }
323
324 #[test]
325 #[cfg(target_os = "windows")]
326 fn test_drive_without_colon_passthrough() {
327 let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap();
328
329 assert_eq!(url.to_string(), "file://localhost/C$/my_dir");
330 }
331
332 #[cfg(not(windows))]
333 fn parse_diagnostic(val: &str) -> ra_flycheck::Diagnostic {
334 serde_json::from_str::<ra_flycheck::Diagnostic>(val).unwrap()
335 }
336
337 #[test]
338 #[cfg(not(windows))]
339 fn snap_rustc_incompatible_type_for_trait() {
340 let diag = parse_diagnostic(
341 r##"{
342 "message": "method `next` has an incompatible type for trait",
343 "code": {
344 "code": "E0053",
345 "explanation": "\nThe parameters of any trait method must match between a trait implementation\nand the trait definition.\n\nHere are a couple examples of this error:\n\n```compile_fail,E0053\ntrait Foo {\n fn foo(x: u16);\n fn bar(&self);\n}\n\nstruct Bar;\n\nimpl Foo for Bar {\n // error, expected u16, found i16\n fn foo(x: i16) { }\n\n // error, types differ in mutability\n fn bar(&mut self) { }\n}\n```\n"
346 },
347 "level": "error",
348 "spans": [
349 {
350 "file_name": "compiler/ty/list_iter.rs",
351 "byte_start": 1307,
352 "byte_end": 1350,
353 "line_start": 52,
354 "line_end": 52,
355 "column_start": 5,
356 "column_end": 48,
357 "is_primary": true,
358 "text": [
359 {
360 "text": " fn next(&self) -> Option<&'list ty::Ref<M>> {",
361 "highlight_start": 5,
362 "highlight_end": 48
363 }
364 ],
365 "label": "types differ in mutability",
366 "suggested_replacement": null,
367 "suggestion_applicability": null,
368 "expansion": null
369 }
370 ],
371 "children": [
372 {
373 "message": "expected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>`",
374 "code": null,
375 "level": "note",
376 "spans": [],
377 "children": [],
378 "rendered": null
379 }
380 ],
381 "rendered": "error[E0053]: method `next` has an incompatible type for trait\n --> compiler/ty/list_iter.rs:52:5\n |\n52 | fn next(&self) -> Option<&'list ty::Ref<M>> {\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability\n |\n = note: expected type `fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref<M>>`\n\n"
382 }
383 "##,
384 );
385
386 let workspace_root = Path::new("/test/");
387 let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root);
388 insta::assert_debug_snapshot!(diag);
389 }
390
391 #[test]
392 #[cfg(not(windows))]
393 fn snap_rustc_unused_variable() {
394 let diag = parse_diagnostic(
395 r##"{
396 "message": "unused variable: `foo`",
397 "code": {
398 "code": "unused_variables",
399 "explanation": null
400 },
401 "level": "warning",
402 "spans": [
403 {
404 "file_name": "driver/subcommand/repl.rs",
405 "byte_start": 9228,
406 "byte_end": 9231,
407 "line_start": 291,
408 "line_end": 291,
409 "column_start": 9,
410 "column_end": 12,
411 "is_primary": true,
412 "text": [
413 {
414 "text": " let foo = 42;",
415 "highlight_start": 9,
416 "highlight_end": 12
417 }
418 ],
419 "label": null,
420 "suggested_replacement": null,
421 "suggestion_applicability": null,
422 "expansion": null
423 }
424 ],
425 "children": [
426 {
427 "message": "#[warn(unused_variables)] on by default",
428 "code": null,
429 "level": "note",
430 "spans": [],
431 "children": [],
432 "rendered": null
433 },
434 {
435 "message": "consider prefixing with an underscore",
436 "code": null,
437 "level": "help",
438 "spans": [
439 {
440 "file_name": "driver/subcommand/repl.rs",
441 "byte_start": 9228,
442 "byte_end": 9231,
443 "line_start": 291,
444 "line_end": 291,
445 "column_start": 9,
446 "column_end": 12,
447 "is_primary": true,
448 "text": [
449 {
450 "text": " let foo = 42;",
451 "highlight_start": 9,
452 "highlight_end": 12
453 }
454 ],
455 "label": null,
456 "suggested_replacement": "_foo",
457 "suggestion_applicability": "MachineApplicable",
458 "expansion": null
459 }
460 ],
461 "children": [],
462 "rendered": null
463 }
464 ],
465 "rendered": "warning: unused variable: `foo`\n --> driver/subcommand/repl.rs:291:9\n |\n291 | let foo = 42;\n | ^^^ help: consider prefixing with an underscore: `_foo`\n |\n = note: #[warn(unused_variables)] on by default\n\n"
466 }"##,
467 );
468
469 let workspace_root = Path::new("/test/");
470 let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root);
471 insta::assert_debug_snapshot!(diag);
472 }
473
474 #[test]
475 #[cfg(not(windows))]
476 fn snap_rustc_wrong_number_of_parameters() {
477 let diag = parse_diagnostic(
478 r##"{
479 "message": "this function takes 2 parameters but 3 parameters were supplied",
480 "code": {
481 "code": "E0061",
482 "explanation": "\nThe number of arguments passed to a function must match the number of arguments\nspecified in the function signature.\n\nFor example, a function like:\n\n```\nfn f(a: u16, b: &str) {}\n```\n\nMust always be called with exactly two arguments, e.g., `f(2, \"test\")`.\n\nNote that Rust does not have a notion of optional function arguments or\nvariadic functions (except for its C-FFI).\n"
483 },
484 "level": "error",
485 "spans": [
486 {
487 "file_name": "compiler/ty/select.rs",
488 "byte_start": 8787,
489 "byte_end": 9241,
490 "line_start": 219,
491 "line_end": 231,
492 "column_start": 5,
493 "column_end": 6,
494 "is_primary": false,
495 "text": [
496 {
497 "text": " pub fn add_evidence(",
498 "highlight_start": 5,
499 "highlight_end": 25
500 },
501 {
502 "text": " &mut self,",
503 "highlight_start": 1,
504 "highlight_end": 19
505 },
506 {
507 "text": " target_poly: &ty::Ref<ty::Poly>,",
508 "highlight_start": 1,
509 "highlight_end": 41
510 },
511 {
512 "text": " evidence_poly: &ty::Ref<ty::Poly>,",
513 "highlight_start": 1,
514 "highlight_end": 43
515 },
516 {
517 "text": " ) {",
518 "highlight_start": 1,
519 "highlight_end": 8
520 },
521 {
522 "text": " match target_poly {",
523 "highlight_start": 1,
524 "highlight_end": 28
525 },
526 {
527 "text": " ty::Ref::Var(tvar, _) => self.add_var_evidence(tvar, evidence_poly),",
528 "highlight_start": 1,
529 "highlight_end": 81
530 },
531 {
532 "text": " ty::Ref::Fixed(target_ty) => {",
533 "highlight_start": 1,
534 "highlight_end": 43
535 },
536 {
537 "text": " let evidence_ty = evidence_poly.resolve_to_ty();",
538 "highlight_start": 1,
539 "highlight_end": 65
540 },
541 {
542 "text": " self.add_evidence_ty(target_ty, evidence_poly, evidence_ty)",
543 "highlight_start": 1,
544 "highlight_end": 76
545 },
546 {
547 "text": " }",
548 "highlight_start": 1,
549 "highlight_end": 14
550 },
551 {
552 "text": " }",
553 "highlight_start": 1,
554 "highlight_end": 10
555 },
556 {
557 "text": " }",
558 "highlight_start": 1,
559 "highlight_end": 6
560 }
561 ],
562 "label": "defined here",
563 "suggested_replacement": null,
564 "suggestion_applicability": null,
565 "expansion": null
566 },
567 {
568 "file_name": "compiler/ty/select.rs",
569 "byte_start": 4045,
570 "byte_end": 4057,
571 "line_start": 104,
572 "line_end": 104,
573 "column_start": 18,
574 "column_end": 30,
575 "is_primary": true,
576 "text": [
577 {
578 "text": " self.add_evidence(target_fixed, evidence_fixed, false);",
579 "highlight_start": 18,
580 "highlight_end": 30
581 }
582 ],
583 "label": "expected 2 parameters",
584 "suggested_replacement": null,
585 "suggestion_applicability": null,
586 "expansion": null
587 }
588 ],
589 "children": [],
590 "rendered": "error[E0061]: this function takes 2 parameters but 3 parameters were supplied\n --> compiler/ty/select.rs:104:18\n |\n104 | self.add_evidence(target_fixed, evidence_fixed, false);\n | ^^^^^^^^^^^^ expected 2 parameters\n...\n219 | / pub fn add_evidence(\n220 | | &mut self,\n221 | | target_poly: &ty::Ref<ty::Poly>,\n222 | | evidence_poly: &ty::Ref<ty::Poly>,\n... |\n230 | | }\n231 | | }\n | |_____- defined here\n\n"
591 }"##,
592 );
593
594 let workspace_root = Path::new("/test/");
595 let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root);
596 insta::assert_debug_snapshot!(diag);
597 }
598
599 #[test]
600 #[cfg(not(windows))]
601 fn snap_clippy_pass_by_ref() {
602 let diag = parse_diagnostic(
603 r##"{
604 "message": "this argument is passed by reference, but would be more efficient if passed by value",
605 "code": {
606 "code": "clippy::trivially_copy_pass_by_ref",
607 "explanation": null
608 },
609 "level": "warning",
610 "spans": [
611 {
612 "file_name": "compiler/mir/tagset.rs",
613 "byte_start": 941,
614 "byte_end": 946,
615 "line_start": 42,
616 "line_end": 42,
617 "column_start": 24,
618 "column_end": 29,
619 "is_primary": true,
620 "text": [
621 {
622 "text": " pub fn is_disjoint(&self, other: Self) -> bool {",
623 "highlight_start": 24,
624 "highlight_end": 29
625 }
626 ],
627 "label": null,
628 "suggested_replacement": null,
629 "suggestion_applicability": null,
630 "expansion": null
631 }
632 ],
633 "children": [
634 {
635 "message": "lint level defined here",
636 "code": null,
637 "level": "note",
638 "spans": [
639 {
640 "file_name": "compiler/lib.rs",
641 "byte_start": 8,
642 "byte_end": 19,
643 "line_start": 1,
644 "line_end": 1,
645 "column_start": 9,
646 "column_end": 20,
647 "is_primary": true,
648 "text": [
649 {
650 "text": "#![warn(clippy::all)]",
651 "highlight_start": 9,
652 "highlight_end": 20
653 }
654 ],
655 "label": null,
656 "suggested_replacement": null,
657 "suggestion_applicability": null,
658 "expansion": null
659 }
660 ],
661 "children": [],
662 "rendered": null
663 },
664 {
665 "message": "#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]",
666 "code": null,
667 "level": "note",
668 "spans": [],
669 "children": [],
670 "rendered": null
671 },
672 {
673 "message": "for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref",
674 "code": null,
675 "level": "help",
676 "spans": [],
677 "children": [],
678 "rendered": null
679 },
680 {
681 "message": "consider passing by value instead",
682 "code": null,
683 "level": "help",
684 "spans": [
685 {
686 "file_name": "compiler/mir/tagset.rs",
687 "byte_start": 941,
688 "byte_end": 946,
689 "line_start": 42,
690 "line_end": 42,
691 "column_start": 24,
692 "column_end": 29,
693 "is_primary": true,
694 "text": [
695 {
696 "text": " pub fn is_disjoint(&self, other: Self) -> bool {",
697 "highlight_start": 24,
698 "highlight_end": 29
699 }
700 ],
701 "label": null,
702 "suggested_replacement": "self",
703 "suggestion_applicability": "Unspecified",
704 "expansion": null
705 }
706 ],
707 "children": [],
708 "rendered": null
709 }
710 ],
711 "rendered": "warning: this argument is passed by reference, but would be more efficient if passed by value\n --> compiler/mir/tagset.rs:42:24\n |\n42 | pub fn is_disjoint(&self, other: Self) -> bool {\n | ^^^^^ help: consider passing by value instead: `self`\n |\nnote: lint level defined here\n --> compiler/lib.rs:1:9\n |\n1 | #![warn(clippy::all)]\n | ^^^^^^^^^^^\n = note: #[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref\n\n"
712 }"##,
713 );
714
715 let workspace_root = Path::new("/test/");
716 let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root);
717 insta::assert_debug_snapshot!(diag);
718 }
719
720 #[test]
721 #[cfg(not(windows))]
722 fn snap_rustc_mismatched_type() {
723 let diag = parse_diagnostic(
724 r##"{
725 "message": "mismatched types",
726 "code": {
727 "code": "E0308",
728 "explanation": "\nThis error occurs when the compiler was unable to infer the concrete type of a\nvariable. It can occur for several cases, the most common of which is a\nmismatch in the expected type that the compiler inferred for a variable's\ninitializing expression, and the actual type explicitly assigned to the\nvariable.\n\nFor example:\n\n```compile_fail,E0308\nlet x: i32 = \"I am not a number!\";\n// ~~~ ~~~~~~~~~~~~~~~~~~~~\n// | |\n// | initializing expression;\n// | compiler infers type `&str`\n// |\n// type `i32` assigned to variable `x`\n```\n"
729 },
730 "level": "error",
731 "spans": [
732 {
733 "file_name": "runtime/compiler_support.rs",
734 "byte_start": 1589,
735 "byte_end": 1594,
736 "line_start": 48,
737 "line_end": 48,
738 "column_start": 65,
739 "column_end": 70,
740 "is_primary": true,
741 "text": [
742 {
743 "text": " let layout = alloc::Layout::from_size_align_unchecked(size, align);",
744 "highlight_start": 65,
745 "highlight_end": 70
746 }
747 ],
748 "label": "expected usize, found u32",
749 "suggested_replacement": null,
750 "suggestion_applicability": null,
751 "expansion": null
752 }
753 ],
754 "children": [],
755 "rendered": "error[E0308]: mismatched types\n --> runtime/compiler_support.rs:48:65\n |\n48 | let layout = alloc::Layout::from_size_align_unchecked(size, align);\n | ^^^^^ expected usize, found u32\n\n"
756 }"##,
757 );
758
759 let workspace_root = Path::new("/test/");
760 let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root);
761 insta::assert_debug_snapshot!(diag);
762 }
763
764 #[test]
765 #[cfg(not(windows))]
766 fn snap_handles_macro_location() {
767 let diag = parse_diagnostic(
768 r##"{
769 "rendered": "error[E0277]: can't compare `{integer}` with `&str`\n --> src/main.rs:2:5\n |\n2 | assert_eq!(1, \"love\");\n | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &str`\n |\n = help: the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`\n = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)\n\n",
770 "children": [
771 {
772 "children": [],
773 "code": null,
774 "level": "help",
775 "message": "the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
776 "rendered": null,
777 "spans": []
778 }
779 ],
780 "code": {
781 "code": "E0277",
782 "explanation": "\nYou tried to use a type which doesn't implement some trait in a place which\nexpected that trait. Erroneous code example:\n\n```compile_fail,E0277\n// here we declare the Foo trait with a bar method\ntrait Foo {\n fn bar(&self);\n}\n\n// we now declare a function which takes an object implementing the Foo trait\nfn some_func<T: Foo>(foo: T) {\n foo.bar();\n}\n\nfn main() {\n // we now call the method with the i32 type, which doesn't implement\n // the Foo trait\n some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied\n}\n```\n\nIn order to fix this error, verify that the type you're using does implement\nthe trait. Example:\n\n```\ntrait Foo {\n fn bar(&self);\n}\n\nfn some_func<T: Foo>(foo: T) {\n foo.bar(); // we can now use this method since i32 implements the\n // Foo trait\n}\n\n// we implement the trait on the i32 type\nimpl Foo for i32 {\n fn bar(&self) {}\n}\n\nfn main() {\n some_func(5i32); // ok!\n}\n```\n\nOr in a generic context, an erroneous code example would look like:\n\n```compile_fail,E0277\nfn some_func<T>(foo: T) {\n println!(\"{:?}\", foo); // error: the trait `core::fmt::Debug` is not\n // implemented for the type `T`\n}\n\nfn main() {\n // We now call the method with the i32 type,\n // which *does* implement the Debug trait.\n some_func(5i32);\n}\n```\n\nNote that the error here is in the definition of the generic function: Although\nwe only call it with a parameter that does implement `Debug`, the compiler\nstill rejects the function: It must work with all possible input types. In\norder to make this example compile, we need to restrict the generic type we're\naccepting:\n\n```\nuse std::fmt;\n\n// Restrict the input type to types that implement Debug.\nfn some_func<T: fmt::Debug>(foo: T) {\n println!(\"{:?}\", foo);\n}\n\nfn main() {\n // Calling the method is still fine, as i32 implements Debug.\n some_func(5i32);\n\n // This would fail to compile now:\n // struct WithoutDebug;\n // some_func(WithoutDebug);\n}\n```\n\nRust only looks at the signature of the called function, as such it must\nalready specify all requirements that will be used for every type parameter.\n"
783 },
784 "level": "error",
785 "message": "can't compare `{integer}` with `&str`",
786 "spans": [
787 {
788 "byte_end": 155,
789 "byte_start": 153,
790 "column_end": 33,
791 "column_start": 31,
792 "expansion": {
793 "def_site_span": {
794 "byte_end": 940,
795 "byte_start": 0,
796 "column_end": 6,
797 "column_start": 1,
798 "expansion": null,
799 "file_name": "<::core::macros::assert_eq macros>",
800 "is_primary": false,
801 "label": null,
802 "line_end": 36,
803 "line_start": 1,
804 "suggested_replacement": null,
805 "suggestion_applicability": null,
806 "text": [
807 {
808 "highlight_end": 35,
809 "highlight_start": 1,
810 "text": "($ left : expr, $ right : expr) =>"
811 },
812 {
813 "highlight_end": 3,
814 "highlight_start": 1,
815 "text": "({"
816 },
817 {
818 "highlight_end": 33,
819 "highlight_start": 1,
820 "text": " match (& $ left, & $ right)"
821 },
822 {
823 "highlight_end": 7,
824 "highlight_start": 1,
825 "text": " {"
826 },
827 {
828 "highlight_end": 34,
829 "highlight_start": 1,
830 "text": " (left_val, right_val) =>"
831 },
832 {
833 "highlight_end": 11,
834 "highlight_start": 1,
835 "text": " {"
836 },
837 {
838 "highlight_end": 46,
839 "highlight_start": 1,
840 "text": " if ! (* left_val == * right_val)"
841 },
842 {
843 "highlight_end": 15,
844 "highlight_start": 1,
845 "text": " {"
846 },
847 {
848 "highlight_end": 25,
849 "highlight_start": 1,
850 "text": " panic !"
851 },
852 {
853 "highlight_end": 57,
854 "highlight_start": 1,
855 "text": " (r#\"assertion failed: `(left == right)`"
856 },
857 {
858 "highlight_end": 16,
859 "highlight_start": 1,
860 "text": " left: `{:?}`,"
861 },
862 {
863 "highlight_end": 18,
864 "highlight_start": 1,
865 "text": " right: `{:?}`\"#,"
866 },
867 {
868 "highlight_end": 47,
869 "highlight_start": 1,
870 "text": " & * left_val, & * right_val)"
871 },
872 {
873 "highlight_end": 15,
874 "highlight_start": 1,
875 "text": " }"
876 },
877 {
878 "highlight_end": 11,
879 "highlight_start": 1,
880 "text": " }"
881 },
882 {
883 "highlight_end": 7,
884 "highlight_start": 1,
885 "text": " }"
886 },
887 {
888 "highlight_end": 42,
889 "highlight_start": 1,
890 "text": " }) ; ($ left : expr, $ right : expr,) =>"
891 },
892 {
893 "highlight_end": 49,
894 "highlight_start": 1,
895 "text": "({ $ crate :: assert_eq ! ($ left, $ right) }) ;"
896 },
897 {
898 "highlight_end": 53,
899 "highlight_start": 1,
900 "text": "($ left : expr, $ right : expr, $ ($ arg : tt) +) =>"
901 },
902 {
903 "highlight_end": 3,
904 "highlight_start": 1,
905 "text": "({"
906 },
907 {
908 "highlight_end": 37,
909 "highlight_start": 1,
910 "text": " match (& ($ left), & ($ right))"
911 },
912 {
913 "highlight_end": 7,
914 "highlight_start": 1,
915 "text": " {"
916 },
917 {
918 "highlight_end": 34,
919 "highlight_start": 1,
920 "text": " (left_val, right_val) =>"
921 },
922 {
923 "highlight_end": 11,
924 "highlight_start": 1,
925 "text": " {"
926 },
927 {
928 "highlight_end": 46,
929 "highlight_start": 1,
930 "text": " if ! (* left_val == * right_val)"
931 },
932 {
933 "highlight_end": 15,
934 "highlight_start": 1,
935 "text": " {"
936 },
937 {
938 "highlight_end": 25,
939 "highlight_start": 1,
940 "text": " panic !"
941 },
942 {
943 "highlight_end": 57,
944 "highlight_start": 1,
945 "text": " (r#\"assertion failed: `(left == right)`"
946 },
947 {
948 "highlight_end": 16,
949 "highlight_start": 1,
950 "text": " left: `{:?}`,"
951 },
952 {
953 "highlight_end": 22,
954 "highlight_start": 1,
955 "text": " right: `{:?}`: {}\"#,"
956 },
957 {
958 "highlight_end": 72,
959 "highlight_start": 1,
960 "text": " & * left_val, & * right_val, $ crate :: format_args !"
961 },
962 {
963 "highlight_end": 33,
964 "highlight_start": 1,
965 "text": " ($ ($ arg) +))"
966 },
967 {
968 "highlight_end": 15,
969 "highlight_start": 1,
970 "text": " }"
971 },
972 {
973 "highlight_end": 11,
974 "highlight_start": 1,
975 "text": " }"
976 },
977 {
978 "highlight_end": 7,
979 "highlight_start": 1,
980 "text": " }"
981 },
982 {
983 "highlight_end": 6,
984 "highlight_start": 1,
985 "text": " }) ;"
986 }
987 ]
988 },
989 "macro_decl_name": "assert_eq!",
990 "span": {
991 "byte_end": 38,
992 "byte_start": 16,
993 "column_end": 27,
994 "column_start": 5,
995 "expansion": null,
996 "file_name": "src/main.rs",
997 "is_primary": false,
998 "label": null,
999 "line_end": 2,
1000 "line_start": 2,
1001 "suggested_replacement": null,
1002 "suggestion_applicability": null,
1003 "text": [
1004 {
1005 "highlight_end": 27,
1006 "highlight_start": 5,
1007 "text": " assert_eq!(1, \"love\");"
1008 }
1009 ]
1010 }
1011 },
1012 "file_name": "<::core::macros::assert_eq macros>",
1013 "is_primary": true,
1014 "label": "no implementation for `{integer} == &str`",
1015 "line_end": 7,
1016 "line_start": 7,
1017 "suggested_replacement": null,
1018 "suggestion_applicability": null,
1019 "text": [
1020 {
1021 "highlight_end": 33,
1022 "highlight_start": 31,
1023 "text": " if ! (* left_val == * right_val)"
1024 }
1025 ]
1026 }
1027 ]
1028 }"##,
1029 );
1030
1031 let workspace_root = Path::new("/test/");
1032 let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root);
1033 insta::assert_debug_snapshot!(diag);
1034 }
1035
1036 #[test]
1037 #[cfg(not(windows))]
1038 fn snap_macro_compiler_error() {
1039 let diag = parse_diagnostic(
1040 r##"{
1041 "rendered": "error: Please register your known path in the path module\n --> crates/ra_hir_def/src/path.rs:265:9\n |\n265 | compile_error!(\"Please register your known path in the path module\")\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n | \n ::: crates/ra_hir_def/src/data.rs:80:16\n |\n80 | let path = path![std::future::Future];\n | -------------------------- in this macro invocation\n\n",
1042 "children": [],
1043 "code": null,
1044 "level": "error",
1045 "message": "Please register your known path in the path module",
1046 "spans": [
1047 {
1048 "byte_end": 8285,
1049 "byte_start": 8217,
1050 "column_end": 77,
1051 "column_start": 9,
1052 "expansion": {
1053 "def_site_span": {
1054 "byte_end": 8294,
1055 "byte_start": 7858,
1056 "column_end": 2,
1057 "column_start": 1,
1058 "expansion": null,
1059 "file_name": "crates/ra_hir_def/src/path.rs",
1060 "is_primary": false,
1061 "label": null,
1062 "line_end": 267,
1063 "line_start": 254,
1064 "suggested_replacement": null,
1065 "suggestion_applicability": null,
1066 "text": [
1067 {
1068 "highlight_end": 28,
1069 "highlight_start": 1,
1070 "text": "macro_rules! __known_path {"
1071 },
1072 {
1073 "highlight_end": 37,
1074 "highlight_start": 1,
1075 "text": " (std::iter::IntoIterator) => {};"
1076 },
1077 {
1078 "highlight_end": 33,
1079 "highlight_start": 1,
1080 "text": " (std::result::Result) => {};"
1081 },
1082 {
1083 "highlight_end": 29,
1084 "highlight_start": 1,
1085 "text": " (std::ops::Range) => {};"
1086 },
1087 {
1088 "highlight_end": 33,
1089 "highlight_start": 1,
1090 "text": " (std::ops::RangeFrom) => {};"
1091 },
1092 {
1093 "highlight_end": 33,
1094 "highlight_start": 1,
1095 "text": " (std::ops::RangeFull) => {};"
1096 },
1097 {
1098 "highlight_end": 31,
1099 "highlight_start": 1,
1100 "text": " (std::ops::RangeTo) => {};"
1101 },
1102 {
1103 "highlight_end": 40,
1104 "highlight_start": 1,
1105 "text": " (std::ops::RangeToInclusive) => {};"
1106 },
1107 {
1108 "highlight_end": 38,
1109 "highlight_start": 1,
1110 "text": " (std::ops::RangeInclusive) => {};"
1111 },
1112 {
1113 "highlight_end": 27,
1114 "highlight_start": 1,
1115 "text": " (std::ops::Try) => {};"
1116 },
1117 {
1118 "highlight_end": 22,
1119 "highlight_start": 1,
1120 "text": " ($path:path) => {"
1121 },
1122 {
1123 "highlight_end": 77,
1124 "highlight_start": 1,
1125 "text": " compile_error!(\"Please register your known path in the path module\")"
1126 },
1127 {
1128 "highlight_end": 7,
1129 "highlight_start": 1,
1130 "text": " };"
1131 },
1132 {
1133 "highlight_end": 2,
1134 "highlight_start": 1,
1135 "text": "}"
1136 }
1137 ]
1138 },
1139 "macro_decl_name": "$crate::__known_path!",
1140 "span": {
1141 "byte_end": 8427,
1142 "byte_start": 8385,
1143 "column_end": 51,
1144 "column_start": 9,
1145 "expansion": {
1146 "def_site_span": {
1147 "byte_end": 8611,
1148 "byte_start": 8312,
1149 "column_end": 2,
1150 "column_start": 1,
1151 "expansion": null,
1152 "file_name": "crates/ra_hir_def/src/path.rs",
1153 "is_primary": false,
1154 "label": null,
1155 "line_end": 277,
1156 "line_start": 270,
1157 "suggested_replacement": null,
1158 "suggestion_applicability": null,
1159 "text": [
1160 {
1161 "highlight_end": 22,
1162 "highlight_start": 1,
1163 "text": "macro_rules! __path {"
1164 },
1165 {
1166 "highlight_end": 43,
1167 "highlight_start": 1,
1168 "text": " ($start:ident $(:: $seg:ident)*) => ({"
1169 },
1170 {
1171 "highlight_end": 51,
1172 "highlight_start": 1,
1173 "text": " $crate::__known_path!($start $(:: $seg)*);"
1174 },
1175 {
1176 "highlight_end": 87,
1177 "highlight_start": 1,
1178 "text": " $crate::path::ModPath::from_simple_segments($crate::path::PathKind::Abs, vec!["
1179 },
1180 {
1181 "highlight_end": 76,
1182 "highlight_start": 1,
1183 "text": " $crate::path::__name![$start], $($crate::path::__name![$seg],)*"
1184 },
1185 {
1186 "highlight_end": 11,
1187 "highlight_start": 1,
1188 "text": " ])"
1189 },
1190 {
1191 "highlight_end": 8,
1192 "highlight_start": 1,
1193 "text": " });"
1194 },
1195 {
1196 "highlight_end": 2,
1197 "highlight_start": 1,
1198 "text": "}"
1199 }
1200 ]
1201 },
1202 "macro_decl_name": "path!",
1203 "span": {
1204 "byte_end": 2966,
1205 "byte_start": 2940,
1206 "column_end": 42,
1207 "column_start": 16,
1208 "expansion": null,
1209 "file_name": "crates/ra_hir_def/src/data.rs",
1210 "is_primary": false,
1211 "label": null,
1212 "line_end": 80,
1213 "line_start": 80,
1214 "suggested_replacement": null,
1215 "suggestion_applicability": null,
1216 "text": [
1217 {
1218 "highlight_end": 42,
1219 "highlight_start": 16,
1220 "text": " let path = path![std::future::Future];"
1221 }
1222 ]
1223 }
1224 },
1225 "file_name": "crates/ra_hir_def/src/path.rs",
1226 "is_primary": false,
1227 "label": null,
1228 "line_end": 272,
1229 "line_start": 272,
1230 "suggested_replacement": null,
1231 "suggestion_applicability": null,
1232 "text": [
1233 {
1234 "highlight_end": 51,
1235 "highlight_start": 9,
1236 "text": " $crate::__known_path!($start $(:: $seg)*);"
1237 }
1238 ]
1239 }
1240 },
1241 "file_name": "crates/ra_hir_def/src/path.rs",
1242 "is_primary": true,
1243 "label": null,
1244 "line_end": 265,
1245 "line_start": 265,
1246 "suggested_replacement": null,
1247 "suggestion_applicability": null,
1248 "text": [
1249 {
1250 "highlight_end": 77,
1251 "highlight_start": 9,
1252 "text": " compile_error!(\"Please register your known path in the path module\")"
1253 }
1254 ]
1255 }
1256 ]
1257 }
1258 "##,
1259 );
1260
1261 let workspace_root = Path::new("/test/");
1262 let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root);
1263 insta::assert_debug_snapshot!(diag);
1264 }
1265
1266 #[test]
1267 #[cfg(not(windows))]
1268 fn snap_multi_line_fix() {
1269 let diag = parse_diagnostic(
1270 r##"{
1271 "rendered": "warning: returning the result of a let binding from a block\n --> src/main.rs:4:5\n |\n3 | let a = (0..10).collect();\n | -------------------------- unnecessary let binding\n4 | a\n | ^\n |\n = note: `#[warn(clippy::let_and_return)]` on by default\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return\nhelp: return the expression directly\n |\n3 | \n4 | (0..10).collect()\n |\n\n",
1272 "children": [
1273 {
1274 "children": [],
1275 "code": null,
1276 "level": "note",
1277 "message": "`#[warn(clippy::let_and_return)]` on by default",
1278 "rendered": null,
1279 "spans": []
1280 },
1281 {
1282 "children": [],
1283 "code": null,
1284 "level": "help",
1285 "message": "for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return",
1286 "rendered": null,
1287 "spans": []
1288 },
1289 {
1290 "children": [],
1291 "code": null,
1292 "level": "help",
1293 "message": "return the expression directly",
1294 "rendered": null,
1295 "spans": [
1296 {
1297 "byte_end": 55,
1298 "byte_start": 29,
1299 "column_end": 31,
1300 "column_start": 5,
1301 "expansion": null,
1302 "file_name": "src/main.rs",
1303 "is_primary": true,
1304 "label": null,
1305 "line_end": 3,
1306 "line_start": 3,
1307 "suggested_replacement": "",
1308 "suggestion_applicability": "MachineApplicable",
1309 "text": [
1310 {
1311 "highlight_end": 31,
1312 "highlight_start": 5,
1313 "text": " let a = (0..10).collect();"
1314 }
1315 ]
1316 },
1317 {
1318 "byte_end": 61,
1319 "byte_start": 60,
1320 "column_end": 6,
1321 "column_start": 5,
1322 "expansion": null,
1323 "file_name": "src/main.rs",
1324 "is_primary": true,
1325 "label": null,
1326 "line_end": 4,
1327 "line_start": 4,
1328 "suggested_replacement": "(0..10).collect()",
1329 "suggestion_applicability": "MachineApplicable",
1330 "text": [
1331 {
1332 "highlight_end": 6,
1333 "highlight_start": 5,
1334 "text": " a"
1335 }
1336 ]
1337 }
1338 ]
1339 }
1340 ],
1341 "code": {
1342 "code": "clippy::let_and_return",
1343 "explanation": null
1344 },
1345 "level": "warning",
1346 "message": "returning the result of a let binding from a block",
1347 "spans": [
1348 {
1349 "byte_end": 55,
1350 "byte_start": 29,
1351 "column_end": 31,
1352 "column_start": 5,
1353 "expansion": null,
1354 "file_name": "src/main.rs",
1355 "is_primary": false,
1356 "label": "unnecessary let binding",
1357 "line_end": 3,
1358 "line_start": 3,
1359 "suggested_replacement": null,
1360 "suggestion_applicability": null,
1361 "text": [
1362 {
1363 "highlight_end": 31,
1364 "highlight_start": 5,
1365 "text": " let a = (0..10).collect();"
1366 }
1367 ]
1368 },
1369 {
1370 "byte_end": 61,
1371 "byte_start": 60,
1372 "column_end": 6,
1373 "column_start": 5,
1374 "expansion": null,
1375 "file_name": "src/main.rs",
1376 "is_primary": true,
1377 "label": null,
1378 "line_end": 4,
1379 "line_start": 4,
1380 "suggested_replacement": null,
1381 "suggestion_applicability": null,
1382 "text": [
1383 {
1384 "highlight_end": 6,
1385 "highlight_start": 5,
1386 "text": " a"
1387 }
1388 ]
1389 }
1390 ]
1391 }
1392 "##,
1393 );
1394
1395 let workspace_root = Path::new("/test/");
1396 let diag = map_rust_diagnostic_to_lsp(&diag, workspace_root);
1397 insta::assert_debug_snapshot!(diag);
1398 }
1399}
diff --git a/crates/rust-analyzer/src/from_proto.rs b/crates/rust-analyzer/src/from_proto.rs
new file mode 100644
index 000000000..4bb16a496
--- /dev/null
+++ b/crates/rust-analyzer/src/from_proto.rs
@@ -0,0 +1,42 @@
1//! Conversion lsp_types types to rust-analyzer specific ones.
2use ra_db::{FileId, FilePosition, FileRange};
3use ra_ide::{LineCol, LineIndex};
4use ra_syntax::{TextRange, TextSize};
5
6use crate::{world::WorldSnapshot, Result};
7
8pub(crate) fn offset(line_index: &LineIndex, position: lsp_types::Position) -> TextSize {
9 let line_col = LineCol { line: position.line as u32, col_utf16: position.character as u32 };
10 line_index.offset(line_col)
11}
12
13pub(crate) fn text_range(line_index: &LineIndex, range: lsp_types::Range) -> TextRange {
14 let start = offset(line_index, range.start);
15 let end = offset(line_index, range.end);
16 TextRange::new(start, end)
17}
18
19pub(crate) fn file_id(world: &WorldSnapshot, url: &lsp_types::Url) -> Result<FileId> {
20 world.uri_to_file_id(url)
21}
22
23pub(crate) fn file_position(
24 world: &WorldSnapshot,
25 tdpp: lsp_types::TextDocumentPositionParams,
26) -> Result<FilePosition> {
27 let file_id = file_id(world, &tdpp.text_document.uri)?;
28 let line_index = world.analysis().file_line_index(file_id)?;
29 let offset = offset(&*line_index, tdpp.position);
30 Ok(FilePosition { file_id, offset })
31}
32
33pub(crate) fn file_range(
34 world: &WorldSnapshot,
35 text_document_identifier: lsp_types::TextDocumentIdentifier,
36 range: lsp_types::Range,
37) -> Result<FileRange> {
38 let file_id = file_id(world, &text_document_identifier.uri)?;
39 let line_index = world.analysis().file_line_index(file_id)?;
40 let range = text_range(&line_index, range);
41 Ok(FileRange { file_id, range })
42}
diff --git a/crates/rust-analyzer/src/lib.rs b/crates/rust-analyzer/src/lib.rs
index 036bf62a7..57d0e9218 100644
--- a/crates/rust-analyzer/src/lib.rs
+++ b/crates/rust-analyzer/src/lib.rs
@@ -20,10 +20,11 @@ macro_rules! eprintln {
20mod vfs_glob; 20mod vfs_glob;
21mod caps; 21mod caps;
22mod cargo_target_spec; 22mod cargo_target_spec;
23mod conv; 23mod to_proto;
24mod from_proto;
24mod main_loop; 25mod main_loop;
25mod markdown; 26mod markdown;
26pub mod req; 27pub mod lsp_ext;
27pub mod config; 28pub mod config;
28mod world; 29mod world;
29mod diagnostics; 30mod diagnostics;
diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 0dae6bad4..1bb1b02ab 100644
--- a/crates/rust-analyzer/src/req.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -1,25 +1,12 @@
1//! Defines `rust-analyzer` specific custom messages. 1//! rust-analyzer extensions to the LSP.
2 2
3use std::{collections::HashMap, path::PathBuf};
4
5use lsp_types::request::Request;
3use lsp_types::{Location, Position, Range, TextDocumentIdentifier}; 6use lsp_types::{Location, Position, Range, TextDocumentIdentifier};
4use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
5use serde::{Deserialize, Serialize}; 8use serde::{Deserialize, Serialize};
6 9
7pub use lsp_types::{
8 notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens,
9 CodeLensParams, CompletionParams, CompletionResponse, ConfigurationItem, ConfigurationParams,
10 DiagnosticTag, DidChangeConfigurationParams, DidChangeWatchedFilesParams,
11 DidChangeWatchedFilesRegistrationOptions, DocumentHighlightParams,
12 DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse,
13 FileSystemWatcher, GotoDefinitionParams, GotoDefinitionResponse, Hover, HoverParams,
14 InitializeResult, MessageType, PartialResultParams, ProgressParams, ProgressParamsValue,
15 ProgressToken, PublishDiagnosticsParams, ReferenceParams, Registration, RegistrationParams,
16 SelectionRange, SelectionRangeParams, SemanticTokensParams, SemanticTokensRangeParams,
17 SemanticTokensRangeResult, SemanticTokensResult, ServerCapabilities, ShowMessageParams,
18 SignatureHelp, SignatureHelpParams, SymbolKind, TextDocumentEdit, TextDocumentPositionParams,
19 TextEdit, WorkDoneProgressParams, WorkspaceEdit, WorkspaceSymbolParams,
20};
21use std::path::PathBuf;
22
23pub enum AnalyzerStatus {} 10pub enum AnalyzerStatus {}
24 11
25impl Request for AnalyzerStatus { 12impl Request for AnalyzerStatus {
@@ -91,7 +78,7 @@ pub struct FindMatchingBraceParams {
91pub enum ParentModule {} 78pub enum ParentModule {}
92 79
93impl Request for ParentModule { 80impl Request for ParentModule {
94 type Params = TextDocumentPositionParams; 81 type Params = lsp_types::TextDocumentPositionParams;
95 type Result = Vec<Location>; 82 type Result = Vec<Location>;
96 const METHOD: &'static str = "rust-analyzer/parentModule"; 83 const METHOD: &'static str = "rust-analyzer/parentModule";
97} 84}
@@ -100,22 +87,22 @@ pub enum JoinLines {}
100 87
101impl Request for JoinLines { 88impl Request for JoinLines {
102 type Params = JoinLinesParams; 89 type Params = JoinLinesParams;
103 type Result = SourceChange; 90 type Result = Vec<lsp_types::TextEdit>;
104 const METHOD: &'static str = "rust-analyzer/joinLines"; 91 const METHOD: &'static str = "experimental/joinLines";
105} 92}
106 93
107#[derive(Deserialize, Serialize, Debug)] 94#[derive(Deserialize, Serialize, Debug)]
108#[serde(rename_all = "camelCase")] 95#[serde(rename_all = "camelCase")]
109pub struct JoinLinesParams { 96pub struct JoinLinesParams {
110 pub text_document: TextDocumentIdentifier, 97 pub text_document: TextDocumentIdentifier,
111 pub range: Range, 98 pub ranges: Vec<Range>,
112} 99}
113 100
114pub enum OnEnter {} 101pub enum OnEnter {}
115 102
116impl Request for OnEnter { 103impl Request for OnEnter {
117 type Params = TextDocumentPositionParams; 104 type Params = lsp_types::TextDocumentPositionParams;
118 type Result = Option<SourceChange>; 105 type Result = Option<SnippetWorkspaceEdit>;
119 const METHOD: &'static str = "rust-analyzer/onEnter"; 106 const METHOD: &'static str = "rust-analyzer/onEnter";
120} 107}
121 108
@@ -150,8 +137,8 @@ pub struct Runnable {
150#[serde(rename_all = "camelCase")] 137#[serde(rename_all = "camelCase")]
151pub struct SourceChange { 138pub struct SourceChange {
152 pub label: String, 139 pub label: String,
153 pub workspace_edit: WorkspaceEdit, 140 pub workspace_edit: SnippetWorkspaceEdit,
154 pub cursor_position: Option<TextDocumentPositionParams>, 141 pub cursor_position: Option<lsp_types::TextDocumentPositionParams>,
155} 142}
156 143
157pub enum InlayHints {} 144pub enum InlayHints {}
@@ -196,3 +183,54 @@ pub struct SsrParams {
196 pub query: String, 183 pub query: String,
197 pub parse_only: bool, 184 pub parse_only: bool,
198} 185}
186
187pub enum CodeActionRequest {}
188
189impl Request for CodeActionRequest {
190 type Params = lsp_types::CodeActionParams;
191 type Result = Option<Vec<CodeAction>>;
192 const METHOD: &'static str = "textDocument/codeAction";
193}
194
195#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
196pub struct CodeAction {
197 pub title: String,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 pub kind: Option<String>,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 pub command: Option<lsp_types::Command>,
202 #[serde(skip_serializing_if = "Option::is_none")]
203 pub edit: Option<SnippetWorkspaceEdit>,
204}
205
206#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
207#[serde(rename_all = "camelCase")]
208pub struct SnippetWorkspaceEdit {
209 #[serde(skip_serializing_if = "Option::is_none")]
210 pub changes: Option<HashMap<lsp_types::Url, Vec<lsp_types::TextEdit>>>,
211 #[serde(skip_serializing_if = "Option::is_none")]
212 pub document_changes: Option<Vec<SnippetDocumentChangeOperation>>,
213}
214
215#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
216#[serde(untagged, rename_all = "lowercase")]
217pub enum SnippetDocumentChangeOperation {
218 Op(lsp_types::ResourceOp),
219 Edit(SnippetTextDocumentEdit),
220}
221
222#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
223#[serde(rename_all = "camelCase")]
224pub struct SnippetTextDocumentEdit {
225 pub text_document: lsp_types::VersionedTextDocumentIdentifier,
226 pub edits: Vec<SnippetTextEdit>,
227}
228
229#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
230#[serde(rename_all = "camelCase")]
231pub struct SnippetTextEdit {
232 pub range: Range,
233 pub new_text: String,
234 #[serde(skip_serializing_if = "Option::is_none")]
235 pub insert_text_format: Option<lsp_types::InsertTextFormat>,
236}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 0a0e616c9..87795fffb 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -25,7 +25,7 @@ use lsp_types::{
25 WorkDoneProgressBegin, WorkDoneProgressCreateParams, WorkDoneProgressEnd, 25 WorkDoneProgressBegin, WorkDoneProgressCreateParams, WorkDoneProgressEnd,
26 WorkDoneProgressReport, 26 WorkDoneProgressReport,
27}; 27};
28use ra_flycheck::{url_from_path_with_drive_lowercasing, CheckTask}; 28use ra_flycheck::{CheckTask, Status};
29use ra_ide::{Canceled, FileId, LibraryData, LineIndex, SourceRootId}; 29use ra_ide::{Canceled, FileId, LibraryData, LineIndex, SourceRootId};
30use ra_prof::profile; 30use ra_prof::profile;
31use ra_project_model::{PackageRoot, ProjectWorkspace}; 31use ra_project_model::{PackageRoot, ProjectWorkspace};
@@ -37,13 +37,12 @@ use threadpool::ThreadPool;
37 37
38use crate::{ 38use crate::{
39 config::{Config, FilesWatcher}, 39 config::{Config, FilesWatcher},
40 conv::{ConvWith, TryConvWith}, 40 diagnostics::{to_proto::url_from_path_with_drive_lowercasing, DiagnosticTask},
41 diagnostics::DiagnosticTask, 41 from_proto, lsp_ext,
42 main_loop::{ 42 main_loop::{
43 pending_requests::{PendingRequest, PendingRequests}, 43 pending_requests::{PendingRequest, PendingRequests},
44 subscriptions::Subscriptions, 44 subscriptions::Subscriptions,
45 }, 45 },
46 req,
47 world::{WorldSnapshot, WorldState}, 46 world::{WorldSnapshot, WorldState},
48 Result, 47 Result,
49}; 48};
@@ -96,23 +95,21 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
96 let mut world_state = { 95 let mut world_state = {
97 let workspaces = { 96 let workspaces = {
98 // FIXME: support dynamic workspace loading. 97 // FIXME: support dynamic workspace loading.
99 let mut visited = FxHashSet::default(); 98 let project_roots: FxHashSet<_> = ws_roots
100 let project_roots = ws_roots
101 .iter() 99 .iter()
102 .filter_map(|it| ra_project_model::ProjectRoot::discover(it).ok()) 100 .filter_map(|it| ra_project_model::ProjectRoot::discover(it).ok())
103 .flatten() 101 .flatten()
104 .filter(|it| visited.insert(it.clone())) 102 .collect();
105 .collect::<Vec<_>>();
106 103
107 if project_roots.is_empty() && config.notifications.cargo_toml_not_found { 104 if project_roots.is_empty() && config.notifications.cargo_toml_not_found {
108 show_message( 105 show_message(
109 req::MessageType::Error, 106 lsp_types::MessageType::Error,
110 format!( 107 format!(
111 "rust-analyzer failed to discover workspace, no Cargo.toml found, dirs searched: {}", 108 "rust-analyzer failed to discover workspace, no Cargo.toml found, dirs searched: {}",
112 ws_roots.iter().format_with(", ", |it, f| f(&it.display())) 109 ws_roots.iter().format_with(", ", |it, f| f(&it.display()))
113 ), 110 ),
114 &connection.sender, 111 &connection.sender,
115 ); 112 );
116 }; 113 };
117 114
118 project_roots 115 project_roots
@@ -126,7 +123,7 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
126 .map_err(|err| { 123 .map_err(|err| {
127 log::error!("failed to load workspace: {:#}", err); 124 log::error!("failed to load workspace: {:#}", err);
128 show_message( 125 show_message(
129 req::MessageType::Error, 126 lsp_types::MessageType::Error,
130 format!("rust-analyzer failed to load workspace: {:#}", err), 127 format!("rust-analyzer failed to load workspace: {:#}", err),
131 &connection.sender, 128 &connection.sender,
132 ); 129 );
@@ -144,23 +141,25 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
144 .collect::<std::result::Result<Vec<_>, _>>()?; 141 .collect::<std::result::Result<Vec<_>, _>>()?;
145 142
146 if let FilesWatcher::Client = config.files.watcher { 143 if let FilesWatcher::Client = config.files.watcher {
147 let registration_options = req::DidChangeWatchedFilesRegistrationOptions { 144 let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
148 watchers: workspaces 145 watchers: workspaces
149 .iter() 146 .iter()
150 .flat_map(ProjectWorkspace::to_roots) 147 .flat_map(ProjectWorkspace::to_roots)
151 .filter(PackageRoot::is_member) 148 .filter(PackageRoot::is_member)
152 .map(|root| format!("{}/**/*.rs", root.path().display())) 149 .map(|root| format!("{}/**/*.rs", root.path().display()))
153 .map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None }) 150 .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
154 .collect(), 151 .collect(),
155 }; 152 };
156 let registration = req::Registration { 153 let registration = lsp_types::Registration {
157 id: "file-watcher".to_string(), 154 id: "file-watcher".to_string(),
158 method: "workspace/didChangeWatchedFiles".to_string(), 155 method: "workspace/didChangeWatchedFiles".to_string(),
159 register_options: Some(serde_json::to_value(registration_options).unwrap()), 156 register_options: Some(serde_json::to_value(registration_options).unwrap()),
160 }; 157 };
161 let params = req::RegistrationParams { registrations: vec![registration] }; 158 let params = lsp_types::RegistrationParams { registrations: vec![registration] };
162 let request = 159 let request = request_new::<lsp_types::request::RegisterCapability>(
163 request_new::<req::RegisterCapability>(loop_state.next_request_id(), params); 160 loop_state.next_request_id(),
161 params,
162 );
164 connection.sender.send(request.into()).unwrap(); 163 connection.sender.send(request.into()).unwrap();
165 } 164 }
166 165
@@ -175,7 +174,6 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
175 }; 174 };
176 175
177 loop_state.roots_total = world_state.vfs.read().n_roots(); 176 loop_state.roots_total = world_state.vfs.read().n_roots();
178 loop_state.roots_scanned = 0;
179 177
180 let pool = ThreadPool::default(); 178 let pool = ThreadPool::default();
181 let (task_sender, task_receiver) = unbounded::<Task>(); 179 let (task_sender, task_receiver) = unbounded::<Task>();
@@ -260,14 +258,14 @@ impl fmt::Debug for Event {
260 258
261 match self { 259 match self {
262 Event::Msg(Message::Notification(not)) => { 260 Event::Msg(Message::Notification(not)) => {
263 if notification_is::<req::DidOpenTextDocument>(not) 261 if notification_is::<lsp_types::notification::DidOpenTextDocument>(not)
264 || notification_is::<req::DidChangeTextDocument>(not) 262 || notification_is::<lsp_types::notification::DidChangeTextDocument>(not)
265 { 263 {
266 return debug_verbose_not(not, f); 264 return debug_verbose_not(not, f);
267 } 265 }
268 } 266 }
269 Event::Task(Task::Notify(not)) => { 267 Event::Task(Task::Notify(not)) => {
270 if notification_is::<req::PublishDiagnostics>(not) { 268 if notification_is::<lsp_types::notification::PublishDiagnostics>(not) {
271 return debug_verbose_not(not, f); 269 return debug_verbose_not(not, f);
272 } 270 }
273 } 271 }
@@ -402,10 +400,12 @@ fn loop_turn(
402 } 400 }
403 401
404 let max_in_flight_libs = pool.max_count().saturating_sub(2).max(1); 402 let max_in_flight_libs = pool.max_count().saturating_sub(2).max(1);
405 while loop_state.in_flight_libraries < max_in_flight_libs 403 while loop_state.in_flight_libraries < max_in_flight_libs {
406 && !loop_state.pending_libraries.is_empty() 404 let (root, files) = match loop_state.pending_libraries.pop() {
407 { 405 Some(it) => it,
408 let (root, files) = loop_state.pending_libraries.pop().unwrap(); 406 None => break,
407 };
408
409 loop_state.in_flight_libraries += 1; 409 loop_state.in_flight_libraries += 1;
410 let sender = libdata_sender.clone(); 410 let sender = libdata_sender.clone();
411 pool.execute(move || { 411 pool.execute(move || {
@@ -416,7 +416,7 @@ fn loop_turn(
416 } 416 }
417 417
418 let show_progress = 418 let show_progress =
419 !loop_state.workspace_loaded && world_state.config.notifications.workspace_loaded; 419 !loop_state.workspace_loaded && world_state.config.client_caps.work_done_progress;
420 420
421 if !loop_state.workspace_loaded 421 if !loop_state.workspace_loaded
422 && loop_state.roots_scanned == loop_state.roots_total 422 && loop_state.roots_scanned == loop_state.roots_total
@@ -453,7 +453,7 @@ fn loop_turn(
453 log::error!("overly long loop turn: {:?}", loop_duration); 453 log::error!("overly long loop turn: {:?}", loop_duration);
454 if env::var("RA_PROFILE").is_ok() { 454 if env::var("RA_PROFILE").is_ok() {
455 show_message( 455 show_message(
456 req::MessageType::Error, 456 lsp_types::MessageType::Error,
457 format!("overly long loop turn: {:?}", loop_duration), 457 format!("overly long loop turn: {:?}", loop_duration),
458 &connection.sender, 458 &connection.sender,
459 ); 459 );
@@ -503,45 +503,51 @@ fn on_request(
503 request_received, 503 request_received,
504 }; 504 };
505 pool_dispatcher 505 pool_dispatcher
506 .on_sync::<req::CollectGarbage>(|s, ()| Ok(s.collect_garbage()))? 506 .on_sync::<lsp_ext::CollectGarbage>(|s, ()| Ok(s.collect_garbage()))?
507 .on_sync::<req::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? 507 .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))?
508 .on_sync::<req::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))? 508 .on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))?
509 .on_sync::<req::SelectionRangeRequest>(|s, p| { 509 .on_sync::<lsp_types::request::SelectionRangeRequest>(|s, p| {
510 handlers::handle_selection_range(s.snapshot(), p) 510 handlers::handle_selection_range(s.snapshot(), p)
511 })? 511 })?
512 .on_sync::<req::FindMatchingBrace>(|s, p| { 512 .on_sync::<lsp_ext::FindMatchingBrace>(|s, p| {
513 handlers::handle_find_matching_brace(s.snapshot(), p) 513 handlers::handle_find_matching_brace(s.snapshot(), p)
514 })? 514 })?
515 .on::<req::AnalyzerStatus>(handlers::handle_analyzer_status)? 515 .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)?
516 .on::<req::SyntaxTree>(handlers::handle_syntax_tree)? 516 .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)?
517 .on::<req::ExpandMacro>(handlers::handle_expand_macro)? 517 .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)?
518 .on::<req::OnTypeFormatting>(handlers::handle_on_type_formatting)? 518 .on::<lsp_ext::ParentModule>(handlers::handle_parent_module)?
519 .on::<req::DocumentSymbolRequest>(handlers::handle_document_symbol)? 519 .on::<lsp_ext::Runnables>(handlers::handle_runnables)?
520 .on::<req::WorkspaceSymbol>(handlers::handle_workspace_symbol)? 520 .on::<lsp_ext::InlayHints>(handlers::handle_inlay_hints)?
521 .on::<req::GotoDefinition>(handlers::handle_goto_definition)? 521 .on::<lsp_ext::CodeActionRequest>(handlers::handle_code_action)?
522 .on::<req::GotoImplementation>(handlers::handle_goto_implementation)? 522 .on::<lsp_types::request::OnTypeFormatting>(handlers::handle_on_type_formatting)?
523 .on::<req::GotoTypeDefinition>(handlers::handle_goto_type_definition)? 523 .on::<lsp_types::request::DocumentSymbolRequest>(handlers::handle_document_symbol)?
524 .on::<req::ParentModule>(handlers::handle_parent_module)? 524 .on::<lsp_types::request::WorkspaceSymbol>(handlers::handle_workspace_symbol)?
525 .on::<req::Runnables>(handlers::handle_runnables)? 525 .on::<lsp_types::request::GotoDefinition>(handlers::handle_goto_definition)?
526 .on::<req::Completion>(handlers::handle_completion)? 526 .on::<lsp_types::request::GotoImplementation>(handlers::handle_goto_implementation)?
527 .on::<req::CodeActionRequest>(handlers::handle_code_action)? 527 .on::<lsp_types::request::GotoTypeDefinition>(handlers::handle_goto_type_definition)?
528 .on::<req::CodeLensRequest>(handlers::handle_code_lens)? 528 .on::<lsp_types::request::Completion>(handlers::handle_completion)?
529 .on::<req::CodeLensResolve>(handlers::handle_code_lens_resolve)? 529 .on::<lsp_types::request::CodeLensRequest>(handlers::handle_code_lens)?
530 .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? 530 .on::<lsp_types::request::CodeLensResolve>(handlers::handle_code_lens_resolve)?
531 .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)? 531 .on::<lsp_types::request::FoldingRangeRequest>(handlers::handle_folding_range)?
532 .on::<req::HoverRequest>(handlers::handle_hover)? 532 .on::<lsp_types::request::SignatureHelpRequest>(handlers::handle_signature_help)?
533 .on::<req::PrepareRenameRequest>(handlers::handle_prepare_rename)? 533 .on::<lsp_types::request::HoverRequest>(handlers::handle_hover)?
534 .on::<req::Rename>(handlers::handle_rename)? 534 .on::<lsp_types::request::PrepareRenameRequest>(handlers::handle_prepare_rename)?
535 .on::<req::References>(handlers::handle_references)? 535 .on::<lsp_types::request::Rename>(handlers::handle_rename)?
536 .on::<req::Formatting>(handlers::handle_formatting)? 536 .on::<lsp_types::request::References>(handlers::handle_references)?
537 .on::<req::DocumentHighlightRequest>(handlers::handle_document_highlight)? 537 .on::<lsp_types::request::Formatting>(handlers::handle_formatting)?
538 .on::<req::InlayHints>(handlers::handle_inlay_hints)? 538 .on::<lsp_types::request::DocumentHighlightRequest>(handlers::handle_document_highlight)?
539 .on::<req::CallHierarchyPrepare>(handlers::handle_call_hierarchy_prepare)? 539 .on::<lsp_types::request::CallHierarchyPrepare>(handlers::handle_call_hierarchy_prepare)?
540 .on::<req::CallHierarchyIncomingCalls>(handlers::handle_call_hierarchy_incoming)? 540 .on::<lsp_types::request::CallHierarchyIncomingCalls>(
541 .on::<req::CallHierarchyOutgoingCalls>(handlers::handle_call_hierarchy_outgoing)? 541 handlers::handle_call_hierarchy_incoming,
542 .on::<req::SemanticTokensRequest>(handlers::handle_semantic_tokens)? 542 )?
543 .on::<req::SemanticTokensRangeRequest>(handlers::handle_semantic_tokens_range)? 543 .on::<lsp_types::request::CallHierarchyOutgoingCalls>(
544 .on::<req::Ssr>(handlers::handle_ssr)? 544 handlers::handle_call_hierarchy_outgoing,
545 )?
546 .on::<lsp_types::request::SemanticTokensRequest>(handlers::handle_semantic_tokens)?
547 .on::<lsp_types::request::SemanticTokensRangeRequest>(
548 handlers::handle_semantic_tokens_range,
549 )?
550 .on::<lsp_ext::Ssr>(handlers::handle_ssr)?
545 .finish(); 551 .finish();
546 Ok(()) 552 Ok(())
547} 553}
@@ -552,7 +558,7 @@ fn on_notification(
552 loop_state: &mut LoopState, 558 loop_state: &mut LoopState,
553 not: Notification, 559 not: Notification,
554) -> Result<()> { 560) -> Result<()> {
555 let not = match notification_cast::<req::Cancel>(not) { 561 let not = match notification_cast::<lsp_types::notification::Cancel>(not) {
556 Ok(params) => { 562 Ok(params) => {
557 let id: RequestId = match params.id { 563 let id: RequestId = match params.id {
558 NumberOrString::Number(id) => id.into(), 564 NumberOrString::Number(id) => id.into(),
@@ -570,7 +576,7 @@ fn on_notification(
570 } 576 }
571 Err(not) => not, 577 Err(not) => not,
572 }; 578 };
573 let not = match notification_cast::<req::DidOpenTextDocument>(not) { 579 let not = match notification_cast::<lsp_types::notification::DidOpenTextDocument>(not) {
574 Ok(params) => { 580 Ok(params) => {
575 let uri = params.text_document.uri; 581 let uri = params.text_document.uri;
576 let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?; 582 let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?;
@@ -583,11 +589,11 @@ fn on_notification(
583 } 589 }
584 Err(not) => not, 590 Err(not) => not,
585 }; 591 };
586 let not = match notification_cast::<req::DidChangeTextDocument>(not) { 592 let not = match notification_cast::<lsp_types::notification::DidChangeTextDocument>(not) {
587 Ok(params) => { 593 Ok(params) => {
588 let DidChangeTextDocumentParams { text_document, content_changes } = params; 594 let DidChangeTextDocumentParams { text_document, content_changes } = params;
589 let world = state.snapshot(); 595 let world = state.snapshot();
590 let file_id = text_document.try_conv_with(&world)?; 596 let file_id = from_proto::file_id(&world, &text_document.uri)?;
591 let line_index = world.analysis().file_line_index(file_id)?; 597 let line_index = world.analysis().file_line_index(file_id)?;
592 let uri = text_document.uri; 598 let uri = text_document.uri;
593 let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?; 599 let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?;
@@ -598,7 +604,7 @@ fn on_notification(
598 } 604 }
599 Err(not) => not, 605 Err(not) => not,
600 }; 606 };
601 let not = match notification_cast::<req::DidSaveTextDocument>(not) { 607 let not = match notification_cast::<lsp_types::notification::DidSaveTextDocument>(not) {
602 Ok(_params) => { 608 Ok(_params) => {
603 if let Some(flycheck) = &state.flycheck { 609 if let Some(flycheck) = &state.flycheck {
604 flycheck.update(); 610 flycheck.update();
@@ -607,7 +613,7 @@ fn on_notification(
607 } 613 }
608 Err(not) => not, 614 Err(not) => not,
609 }; 615 };
610 let not = match notification_cast::<req::DidCloseTextDocument>(not) { 616 let not = match notification_cast::<lsp_types::notification::DidCloseTextDocument>(not) {
611 Ok(params) => { 617 Ok(params) => {
612 let uri = params.text_document.uri; 618 let uri = params.text_document.uri;
613 let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?; 619 let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?;
@@ -615,22 +621,22 @@ fn on_notification(
615 loop_state.subscriptions.remove_sub(FileId(file_id.0)); 621 loop_state.subscriptions.remove_sub(FileId(file_id.0));
616 } 622 }
617 let params = 623 let params =
618 req::PublishDiagnosticsParams { uri, diagnostics: Vec::new(), version: None }; 624 lsp_types::PublishDiagnosticsParams { uri, diagnostics: Vec::new(), version: None };
619 let not = notification_new::<req::PublishDiagnostics>(params); 625 let not = notification_new::<lsp_types::notification::PublishDiagnostics>(params);
620 msg_sender.send(not.into()).unwrap(); 626 msg_sender.send(not.into()).unwrap();
621 return Ok(()); 627 return Ok(());
622 } 628 }
623 Err(not) => not, 629 Err(not) => not,
624 }; 630 };
625 let not = match notification_cast::<req::DidChangeConfiguration>(not) { 631 let not = match notification_cast::<lsp_types::notification::DidChangeConfiguration>(not) {
626 Ok(_) => { 632 Ok(_) => {
627 // As stated in https://github.com/microsoft/language-server-protocol/issues/676, 633 // As stated in https://github.com/microsoft/language-server-protocol/issues/676,
628 // this notification's parameters should be ignored and the actual config queried separately. 634 // this notification's parameters should be ignored and the actual config queried separately.
629 let request_id = loop_state.next_request_id(); 635 let request_id = loop_state.next_request_id();
630 let request = request_new::<req::WorkspaceConfiguration>( 636 let request = request_new::<lsp_types::request::WorkspaceConfiguration>(
631 request_id.clone(), 637 request_id.clone(),
632 req::ConfigurationParams { 638 lsp_types::ConfigurationParams {
633 items: vec![req::ConfigurationItem { 639 items: vec![lsp_types::ConfigurationItem {
634 scope_uri: None, 640 scope_uri: None,
635 section: Some("rust-analyzer".to_string()), 641 section: Some("rust-analyzer".to_string()),
636 }], 642 }],
@@ -643,7 +649,7 @@ fn on_notification(
643 } 649 }
644 Err(not) => not, 650 Err(not) => not,
645 }; 651 };
646 let not = match notification_cast::<req::DidChangeWatchedFiles>(not) { 652 let not = match notification_cast::<lsp_types::notification::DidChangeWatchedFiles>(not) {
647 Ok(params) => { 653 Ok(params) => {
648 let mut vfs = state.vfs.write(); 654 let mut vfs = state.vfs.write();
649 for change in params.changes { 655 for change in params.changes {
@@ -667,19 +673,23 @@ fn apply_document_changes(
667 mut line_index: Cow<'_, LineIndex>, 673 mut line_index: Cow<'_, LineIndex>,
668 content_changes: Vec<TextDocumentContentChangeEvent>, 674 content_changes: Vec<TextDocumentContentChangeEvent>,
669) { 675) {
676 // Remove when https://github.com/rust-analyzer/rust-analyzer/issues/4263 is fixed.
677 let backup_text = old_text.clone();
678 let backup_changes = content_changes.clone();
679
670 // The changes we got must be applied sequentially, but can cross lines so we 680 // The changes we got must be applied sequentially, but can cross lines so we
671 // have to keep our line index updated. 681 // have to keep our line index updated.
672 // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we 682 // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we
673 // remember the last valid line in the index and only rebuild it if needed. 683 // remember the last valid line in the index and only rebuild it if needed.
674 enum IndexValid { 684 enum IndexValid {
675 All, 685 All,
676 UpToLine(u64), 686 UpToLineExclusive(u64),
677 } 687 }
678 688
679 impl IndexValid { 689 impl IndexValid {
680 fn covers(&self, line: u64) -> bool { 690 fn covers(&self, line: u64) -> bool {
681 match *self { 691 match *self {
682 IndexValid::UpToLine(to) => to >= line, 692 IndexValid::UpToLineExclusive(to) => to > line,
683 _ => true, 693 _ => true,
684 } 694 }
685 } 695 }
@@ -689,16 +699,28 @@ fn apply_document_changes(
689 for change in content_changes { 699 for change in content_changes {
690 match change.range { 700 match change.range {
691 Some(range) => { 701 Some(range) => {
692 if !index_valid.covers(range.start.line) { 702 if !index_valid.covers(range.end.line) {
693 line_index = Cow::Owned(LineIndex::new(&old_text)); 703 line_index = Cow::Owned(LineIndex::new(&old_text));
694 } 704 }
695 index_valid = IndexValid::UpToLine(range.start.line); 705 index_valid = IndexValid::UpToLineExclusive(range.start.line);
696 let range = range.conv_with(&line_index); 706 let range = from_proto::text_range(&line_index, range);
697 old_text.replace_range(Range::<usize>::from(range), &change.text); 707 let mut text = old_text.to_owned();
708 match std::panic::catch_unwind(move || {
709 text.replace_range(Range::<usize>::from(range), &change.text);
710 text
711 }) {
712 Ok(t) => *old_text = t,
713 Err(e) => {
714 eprintln!("Bug in incremental text synchronization. Please report the following output on https://github.com/rust-analyzer/rust-analyzer/issues/4263");
715 dbg!(&backup_text);
716 dbg!(&backup_changes);
717 std::panic::resume_unwind(e);
718 }
719 }
698 } 720 }
699 None => { 721 None => {
700 *old_text = change.text; 722 *old_text = change.text;
701 index_valid = IndexValid::UpToLine(0); 723 index_valid = IndexValid::UpToLineExclusive(0);
702 } 724 }
703 } 725 }
704 } 726 }
@@ -714,27 +736,70 @@ fn on_check_task(
714 task_sender.send(Task::Diagnostic(DiagnosticTask::ClearCheck))?; 736 task_sender.send(Task::Diagnostic(DiagnosticTask::ClearCheck))?;
715 } 737 }
716 738
717 CheckTask::AddDiagnostic { url, diagnostic, fixes } => { 739 CheckTask::AddDiagnostic { workspace_root, diagnostic } => {
718 let path = url.to_file_path().map_err(|()| format!("invalid uri: {}", url))?; 740 let diagnostics = crate::diagnostics::to_proto::map_rust_diagnostic_to_lsp(
719 let file_id = match world_state.vfs.read().path2file(&path) { 741 &diagnostic,
720 Some(file) => FileId(file.0), 742 &workspace_root,
721 None => { 743 );
722 log::error!("File with cargo diagnostic not found in VFS: {}", path.display()); 744 for diag in diagnostics {
723 return Ok(()); 745 let path = diag
724 } 746 .location
725 }; 747 .uri
748 .to_file_path()
749 .map_err(|()| format!("invalid uri: {}", diag.location.uri))?;
750 let file_id = match world_state.vfs.read().path2file(&path) {
751 Some(file) => FileId(file.0),
752 None => {
753 log::error!(
754 "File with cargo diagnostic not found in VFS: {}",
755 path.display()
756 );
757 return Ok(());
758 }
759 };
726 760
727 task_sender 761 task_sender.send(Task::Diagnostic(DiagnosticTask::AddCheck(
728 .send(Task::Diagnostic(DiagnosticTask::AddCheck(file_id, diagnostic, fixes)))?; 762 file_id,
763 diag.diagnostic,
764 diag.fixes.into_iter().map(|it| it.into()).collect(),
765 )))?;
766 }
729 } 767 }
730 768
731 CheckTask::Status(progress) => { 769 CheckTask::Status(status) => {
732 let params = req::ProgressParams { 770 if world_state.config.client_caps.work_done_progress {
733 token: req::ProgressToken::String("rustAnalyzer/cargoWatcher".to_string()), 771 let progress = match status {
734 value: req::ProgressParamsValue::WorkDone(progress), 772 Status::Being => {
735 }; 773 lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin {
736 let not = notification_new::<req::Progress>(params); 774 title: "Running `cargo check`".to_string(),
737 task_sender.send(Task::Notify(not)).unwrap(); 775 cancellable: Some(false),
776 message: None,
777 percentage: None,
778 })
779 }
780 Status::Progress(target) => {
781 lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport {
782 cancellable: Some(false),
783 message: Some(target),
784 percentage: None,
785 })
786 }
787 Status::End => {
788 lsp_types::WorkDoneProgress::End(lsp_types::WorkDoneProgressEnd {
789 message: None,
790 })
791 }
792 };
793
794 let params = lsp_types::ProgressParams {
795 token: lsp_types::ProgressToken::String(
796 "rustAnalyzer/cargoWatcher".to_string(),
797 ),
798 value: lsp_types::ProgressParamsValue::WorkDone(progress),
799 };
800 let not = notification_new::<lsp_types::notification::Progress>(params);
801 task_sender.send(Task::Notify(not)).unwrap();
802 }
738 } 803 }
739 }; 804 };
740 805
@@ -755,8 +820,8 @@ fn on_diagnostic_task(task: DiagnosticTask, msg_sender: &Sender<Message>, state:
755 }; 820 };
756 821
757 let diagnostics = state.diagnostics.diagnostics_for(file_id).cloned().collect(); 822 let diagnostics = state.diagnostics.diagnostics_for(file_id).cloned().collect();
758 let params = req::PublishDiagnosticsParams { uri, diagnostics, version: None }; 823 let params = lsp_types::PublishDiagnosticsParams { uri, diagnostics, version: None };
759 let not = notification_new::<req::PublishDiagnostics>(params); 824 let not = notification_new::<lsp_types::notification::PublishDiagnostics>(params);
760 msg_sender.send(not.into()).unwrap(); 825 msg_sender.send(not.into()).unwrap();
761 } 826 }
762} 827}
@@ -769,10 +834,10 @@ fn send_startup_progress(sender: &Sender<Message>, loop_state: &mut LoopState) {
769 834
770 match (prev, loop_state.workspace_loaded) { 835 match (prev, loop_state.workspace_loaded) {
771 (None, false) => { 836 (None, false) => {
772 let work_done_progress_create = request_new::<req::WorkDoneProgressCreate>( 837 let work_done_progress_create = request_new::<lsp_types::request::WorkDoneProgressCreate>(
773 loop_state.next_request_id(), 838 loop_state.next_request_id(),
774 WorkDoneProgressCreateParams { 839 WorkDoneProgressCreateParams {
775 token: req::ProgressToken::String("rustAnalyzer/startup".into()), 840 token: lsp_types::ProgressToken::String("rustAnalyzer/startup".into()),
776 }, 841 },
777 ); 842 );
778 sender.send(work_done_progress_create.into()).unwrap(); 843 sender.send(work_done_progress_create.into()).unwrap();
@@ -804,10 +869,11 @@ fn send_startup_progress(sender: &Sender<Message>, loop_state: &mut LoopState) {
804 } 869 }
805 870
806 fn send_startup_progress_notif(sender: &Sender<Message>, work_done_progress: WorkDoneProgress) { 871 fn send_startup_progress_notif(sender: &Sender<Message>, work_done_progress: WorkDoneProgress) {
807 let notif = notification_new::<req::Progress>(req::ProgressParams { 872 let notif =
808 token: req::ProgressToken::String("rustAnalyzer/startup".into()), 873 notification_new::<lsp_types::notification::Progress>(lsp_types::ProgressParams {
809 value: req::ProgressParamsValue::WorkDone(work_done_progress), 874 token: lsp_types::ProgressToken::String("rustAnalyzer/startup".into()),
810 }); 875 value: lsp_types::ProgressParamsValue::WorkDone(work_done_progress),
876 });
811 sender.send(notif.into()).unwrap(); 877 sender.send(notif.into()).unwrap();
812 } 878 }
813} 879}
@@ -829,7 +895,7 @@ impl<'a> PoolDispatcher<'a> {
829 f: fn(&mut WorldState, R::Params) -> Result<R::Result>, 895 f: fn(&mut WorldState, R::Params) -> Result<R::Result>,
830 ) -> Result<&mut Self> 896 ) -> Result<&mut Self>
831 where 897 where
832 R: req::Request + 'static, 898 R: lsp_types::request::Request + 'static,
833 R::Params: DeserializeOwned + panic::UnwindSafe + 'static, 899 R::Params: DeserializeOwned + panic::UnwindSafe + 'static,
834 R::Result: Serialize + 'static, 900 R::Result: Serialize + 'static,
835 { 901 {
@@ -852,7 +918,7 @@ impl<'a> PoolDispatcher<'a> {
852 /// Dispatches the request onto thread pool 918 /// Dispatches the request onto thread pool
853 fn on<R>(&mut self, f: fn(WorldSnapshot, R::Params) -> Result<R::Result>) -> Result<&mut Self> 919 fn on<R>(&mut self, f: fn(WorldSnapshot, R::Params) -> Result<R::Result>) -> Result<&mut Self>
854 where 920 where
855 R: req::Request + 'static, 921 R: lsp_types::request::Request + 'static,
856 R::Params: DeserializeOwned + Send + 'static, 922 R::Params: DeserializeOwned + Send + 'static,
857 R::Result: Serialize + 'static, 923 R::Result: Serialize + 'static,
858 { 924 {
@@ -878,7 +944,7 @@ impl<'a> PoolDispatcher<'a> {
878 944
879 fn parse<R>(&mut self) -> Option<(RequestId, R::Params)> 945 fn parse<R>(&mut self) -> Option<(RequestId, R::Params)>
880 where 946 where
881 R: req::Request + 'static, 947 R: lsp_types::request::Request + 'static,
882 R::Params: DeserializeOwned + 'static, 948 R::Params: DeserializeOwned + 'static,
883 { 949 {
884 let req = self.req.take()?; 950 let req = self.req.take()?;
@@ -915,7 +981,7 @@ impl<'a> PoolDispatcher<'a> {
915 981
916fn result_to_task<R>(id: RequestId, result: Result<R::Result>) -> Task 982fn result_to_task<R>(id: RequestId, result: Result<R::Result>) -> Task
917where 983where
918 R: req::Request + 'static, 984 R: lsp_types::request::Request + 'static,
919 R::Params: DeserializeOwned + 'static, 985 R::Params: DeserializeOwned + 'static,
920 R::Result: Serialize + 'static, 986 R::Result: Serialize + 'static,
921{ 987{
@@ -971,10 +1037,14 @@ fn update_file_notifications_on_threadpool(
971 } 1037 }
972} 1038}
973 1039
974pub fn show_message(typ: req::MessageType, message: impl Into<String>, sender: &Sender<Message>) { 1040pub fn show_message(
1041 typ: lsp_types::MessageType,
1042 message: impl Into<String>,
1043 sender: &Sender<Message>,
1044) {
975 let message = message.into(); 1045 let message = message.into();
976 let params = req::ShowMessageParams { typ, message }; 1046 let params = lsp_types::ShowMessageParams { typ, message };
977 let not = notification_new::<req::ShowMessage>(params); 1047 let not = notification_new::<lsp_types::notification::ShowMessage>(params);
978 sender.send(not.into()).unwrap(); 1048 sender.send(not.into()).unwrap();
979} 1049}
980 1050
@@ -1068,5 +1138,17 @@ mod tests {
1068 assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n"); 1138 assert_eq!(text, "the quick foxes\nDREAM\nthey have quiet dreams\nDON'T THEY?\n");
1069 run(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]); 1139 run(&mut text, c![0, 10; 1, 5 => "", 2, 0; 2, 12 => ""]);
1070 assert_eq!(text, "the quick \nthey have quiet dreams\n"); 1140 assert_eq!(text, "the quick \nthey have quiet dreams\n");
1141
1142 text = String::from("❤️");
1143 run(&mut text, c![0, 0; 0, 0 => "a"]);
1144 assert_eq!(text, "a❤️");
1145
1146 text = String::from("a\nb");
1147 run(&mut text, c![0, 1; 1, 0 => "\nțc", 0, 1; 1, 1 => "d"]);
1148 assert_eq!(text, "adcb");
1149
1150 text = String::from("a\nb");
1151 run(&mut text, c![0, 1; 1, 0 => "ț\nc", 0, 2; 0, 2 => "c"]);
1152 assert_eq!(text, "ațc\ncb");
1071 } 1153 }
1072} 1154}
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 0f623949e..121964718 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -11,17 +11,18 @@ use lsp_server::ErrorCode;
11use lsp_types::{ 11use lsp_types::{
12 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, 12 CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
13 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, 13 CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams,
14 CodeAction, CodeActionResponse, CodeLens, Command, CompletionItem, Diagnostic, 14 CodeLens, Command, CompletionItem, Diagnostic, DocumentFormattingParams, DocumentHighlight,
15 DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeParams, 15 DocumentSymbol, FoldingRange, FoldingRangeParams, Hover, HoverContents, Location,
16 Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, 16 MarkupContent, MarkupKind, Position, PrepareRenameResponse, Range, RenameParams,
17 Range, RenameParams, SemanticTokensParams, SemanticTokensRangeParams, 17 SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult,
18 SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, 18 SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, Url, WorkspaceEdit,
19 TextEdit, Url, WorkspaceEdit,
20}; 19};
21use ra_ide::{ 20use ra_ide::{
22 Assist, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope, 21 Assist, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope,
22 TextEdit,
23}; 23};
24use ra_prof::profile; 24use ra_prof::profile;
25use ra_project_model::TargetKind;
25use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize}; 26use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize};
26use rustc_hash::FxHashMap; 27use rustc_hash::FxHashMap;
27use serde::{Deserialize, Serialize}; 28use serde::{Deserialize, Serialize};
@@ -31,14 +32,10 @@ use stdx::format_to;
31use crate::{ 32use crate::{
32 cargo_target_spec::CargoTargetSpec, 33 cargo_target_spec::CargoTargetSpec,
33 config::RustfmtConfig, 34 config::RustfmtConfig,
34 conv::{
35 to_call_hierarchy_item, to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith,
36 TryConvWithToVec,
37 },
38 diagnostics::DiagnosticTask, 35 diagnostics::DiagnosticTask,
39 from_json, 36 from_json, from_proto,
40 req::{self, InlayHint, InlayHintsParams}, 37 lsp_ext::{self, InlayHint, InlayHintsParams},
41 semantic_tokens::SemanticTokensBuilder, 38 to_proto,
42 world::WorldSnapshot, 39 world::WorldSnapshot,
43 LspError, Result, 40 LspError, Result,
44}; 41};
@@ -46,57 +43,60 @@ use crate::{
46pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> { 43pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> {
47 let _p = profile("handle_analyzer_status"); 44 let _p = profile("handle_analyzer_status");
48 let mut buf = world.status(); 45 let mut buf = world.status();
49 format_to!(buf, "\n\nrequests:"); 46 format_to!(buf, "\n\nrequests:\n");
50 let requests = world.latest_requests.read(); 47 let requests = world.latest_requests.read();
51 for (is_last, r) in requests.iter() { 48 for (is_last, r) in requests.iter() {
52 let mark = if is_last { "*" } else { " " }; 49 let mark = if is_last { "*" } else { " " };
53 format_to!(buf, "{}{:4} {:<36}{}ms", mark, r.id, r.method, r.duration.as_millis()); 50 format_to!(buf, "{}{:4} {:<36}{}ms\n", mark, r.id, r.method, r.duration.as_millis());
54 } 51 }
55 Ok(buf) 52 Ok(buf)
56} 53}
57 54
58pub fn handle_syntax_tree(world: WorldSnapshot, params: req::SyntaxTreeParams) -> Result<String> { 55pub fn handle_syntax_tree(
56 world: WorldSnapshot,
57 params: lsp_ext::SyntaxTreeParams,
58) -> Result<String> {
59 let _p = profile("handle_syntax_tree"); 59 let _p = profile("handle_syntax_tree");
60 let id = params.text_document.try_conv_with(&world)?; 60 let id = from_proto::file_id(&world, &params.text_document.uri)?;
61 let line_index = world.analysis().file_line_index(id)?; 61 let line_index = world.analysis().file_line_index(id)?;
62 let text_range = params.range.map(|p| p.conv_with(&line_index)); 62 let text_range = params.range.map(|r| from_proto::text_range(&line_index, r));
63 let res = world.analysis().syntax_tree(id, text_range)?; 63 let res = world.analysis().syntax_tree(id, text_range)?;
64 Ok(res) 64 Ok(res)
65} 65}
66 66
67pub fn handle_expand_macro( 67pub fn handle_expand_macro(
68 world: WorldSnapshot, 68 world: WorldSnapshot,
69 params: req::ExpandMacroParams, 69 params: lsp_ext::ExpandMacroParams,
70) -> Result<Option<req::ExpandedMacro>> { 70) -> Result<Option<lsp_ext::ExpandedMacro>> {
71 let _p = profile("handle_expand_macro"); 71 let _p = profile("handle_expand_macro");
72 let file_id = params.text_document.try_conv_with(&world)?; 72 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
73 let line_index = world.analysis().file_line_index(file_id)?; 73 let line_index = world.analysis().file_line_index(file_id)?;
74 let offset = params.position.map(|p| p.conv_with(&line_index)); 74 let offset = params.position.map(|p| from_proto::offset(&line_index, p));
75 75
76 match offset { 76 match offset {
77 None => Ok(None), 77 None => Ok(None),
78 Some(offset) => { 78 Some(offset) => {
79 let res = world.analysis().expand_macro(FilePosition { file_id, offset })?; 79 let res = world.analysis().expand_macro(FilePosition { file_id, offset })?;
80 Ok(res.map(|it| req::ExpandedMacro { name: it.name, expansion: it.expansion })) 80 Ok(res.map(|it| lsp_ext::ExpandedMacro { name: it.name, expansion: it.expansion }))
81 } 81 }
82 } 82 }
83} 83}
84 84
85pub fn handle_selection_range( 85pub fn handle_selection_range(
86 world: WorldSnapshot, 86 world: WorldSnapshot,
87 params: req::SelectionRangeParams, 87 params: lsp_types::SelectionRangeParams,
88) -> Result<Option<Vec<req::SelectionRange>>> { 88) -> Result<Option<Vec<lsp_types::SelectionRange>>> {
89 let _p = profile("handle_selection_range"); 89 let _p = profile("handle_selection_range");
90 let file_id = params.text_document.try_conv_with(&world)?; 90 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
91 let line_index = world.analysis().file_line_index(file_id)?; 91 let line_index = world.analysis().file_line_index(file_id)?;
92 let res: Result<Vec<req::SelectionRange>> = params 92 let res: Result<Vec<lsp_types::SelectionRange>> = params
93 .positions 93 .positions
94 .into_iter() 94 .into_iter()
95 .map_conv_with(&line_index)
96 .map(|position| { 95 .map(|position| {
96 let offset = from_proto::offset(&line_index, position);
97 let mut ranges = Vec::new(); 97 let mut ranges = Vec::new();
98 { 98 {
99 let mut range = TextRange::new(position, position); 99 let mut range = TextRange::new(offset, offset);
100 loop { 100 loop {
101 ranges.push(range); 101 ranges.push(range);
102 let frange = FileRange { file_id, range }; 102 let frange = FileRange { file_id, range };
@@ -108,13 +108,13 @@ pub fn handle_selection_range(
108 } 108 }
109 } 109 }
110 } 110 }
111 let mut range = req::SelectionRange { 111 let mut range = lsp_types::SelectionRange {
112 range: ranges.last().unwrap().conv_with(&line_index), 112 range: to_proto::range(&line_index, *ranges.last().unwrap()),
113 parent: None, 113 parent: None,
114 }; 114 };
115 for r in ranges.iter().rev().skip(1) { 115 for &r in ranges.iter().rev().skip(1) {
116 range = req::SelectionRange { 116 range = lsp_types::SelectionRange {
117 range: r.conv_with(&line_index), 117 range: to_proto::range(&line_index, r),
118 parent: Some(Box::new(range)), 118 parent: Some(Box::new(range)),
119 } 119 }
120 } 120 }
@@ -127,57 +127,68 @@ pub fn handle_selection_range(
127 127
128pub fn handle_find_matching_brace( 128pub fn handle_find_matching_brace(
129 world: WorldSnapshot, 129 world: WorldSnapshot,
130 params: req::FindMatchingBraceParams, 130 params: lsp_ext::FindMatchingBraceParams,
131) -> Result<Vec<Position>> { 131) -> Result<Vec<Position>> {
132 let _p = profile("handle_find_matching_brace"); 132 let _p = profile("handle_find_matching_brace");
133 let file_id = params.text_document.try_conv_with(&world)?; 133 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
134 let line_index = world.analysis().file_line_index(file_id)?; 134 let line_index = world.analysis().file_line_index(file_id)?;
135 let res = params 135 let res = params
136 .offsets 136 .offsets
137 .into_iter() 137 .into_iter()
138 .map_conv_with(&line_index) 138 .map(|position| {
139 .map(|offset| { 139 let offset = from_proto::offset(&line_index, position);
140 if let Ok(Some(matching_brace_offset)) = 140 let offset = match world.analysis().matching_brace(FilePosition { file_id, offset }) {
141 world.analysis().matching_brace(FilePosition { file_id, offset }) 141 Ok(Some(matching_brace_offset)) => matching_brace_offset,
142 { 142 Err(_) | Ok(None) => offset,
143 matching_brace_offset 143 };
144 } else { 144 to_proto::position(&line_index, offset)
145 offset
146 }
147 }) 145 })
148 .map_conv_with(&line_index)
149 .collect(); 146 .collect();
150 Ok(res) 147 Ok(res)
151} 148}
152 149
153pub fn handle_join_lines( 150pub fn handle_join_lines(
154 world: WorldSnapshot, 151 world: WorldSnapshot,
155 params: req::JoinLinesParams, 152 params: lsp_ext::JoinLinesParams,
156) -> Result<req::SourceChange> { 153) -> Result<Vec<lsp_types::TextEdit>> {
157 let _p = profile("handle_join_lines"); 154 let _p = profile("handle_join_lines");
158 let frange = (&params.text_document, params.range).try_conv_with(&world)?; 155 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
159 world.analysis().join_lines(frange)?.try_conv_with(&world) 156 let line_index = world.analysis().file_line_index(file_id)?;
157 let line_endings = world.file_line_endings(file_id);
158 let mut res = TextEdit::default();
159 for range in params.ranges {
160 let range = from_proto::text_range(&line_index, range);
161 let edit = world.analysis().join_lines(FileRange { file_id, range })?;
162 match res.union(edit) {
163 Ok(()) => (),
164 Err(_edit) => {
165 // just ignore overlapping edits
166 }
167 }
168 }
169 let res = to_proto::text_edit_vec(&line_index, line_endings, res);
170 Ok(res)
160} 171}
161 172
162pub fn handle_on_enter( 173pub fn handle_on_enter(
163 world: WorldSnapshot, 174 world: WorldSnapshot,
164 params: req::TextDocumentPositionParams, 175 params: lsp_types::TextDocumentPositionParams,
165) -> Result<Option<req::SourceChange>> { 176) -> Result<Option<lsp_ext::SnippetWorkspaceEdit>> {
166 let _p = profile("handle_on_enter"); 177 let _p = profile("handle_on_enter");
167 let position = params.try_conv_with(&world)?; 178 let position = from_proto::file_position(&world, params)?;
168 match world.analysis().on_enter(position)? { 179 match world.analysis().on_enter(position)? {
169 None => Ok(None), 180 None => Ok(None),
170 Some(edit) => Ok(Some(edit.try_conv_with(&world)?)), 181 Some(source_change) => to_proto::snippet_workspace_edit(&world, source_change).map(Some),
171 } 182 }
172} 183}
173 184
174// Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`. 185// Don't forget to add new trigger characters to `ServerCapabilities` in `caps.rs`.
175pub fn handle_on_type_formatting( 186pub fn handle_on_type_formatting(
176 world: WorldSnapshot, 187 world: WorldSnapshot,
177 params: req::DocumentOnTypeFormattingParams, 188 params: lsp_types::DocumentOnTypeFormattingParams,
178) -> Result<Option<Vec<TextEdit>>> { 189) -> Result<Option<Vec<lsp_types::TextEdit>>> {
179 let _p = profile("handle_on_type_formatting"); 190 let _p = profile("handle_on_type_formatting");
180 let mut position = params.text_document_position.try_conv_with(&world)?; 191 let mut position = from_proto::file_position(&world, params.text_document_position)?;
181 let line_index = world.analysis().file_line_index(position.file_id)?; 192 let line_index = world.analysis().file_line_index(position.file_id)?;
182 let line_endings = world.file_line_endings(position.file_id); 193 let line_endings = world.file_line_endings(position.file_id);
183 194
@@ -207,18 +218,17 @@ pub fn handle_on_type_formatting(
207 // This should be a single-file edit 218 // This should be a single-file edit
208 let edit = edit.source_file_edits.pop().unwrap(); 219 let edit = edit.source_file_edits.pop().unwrap();
209 220
210 let change: Vec<TextEdit> = edit.edit.conv_with((&line_index, line_endings)); 221 let change = to_proto::text_edit_vec(&line_index, line_endings, edit.edit);
211 Ok(Some(change)) 222 Ok(Some(change))
212} 223}
213 224
214pub fn handle_document_symbol( 225pub fn handle_document_symbol(
215 world: WorldSnapshot, 226 world: WorldSnapshot,
216 params: req::DocumentSymbolParams, 227 params: lsp_types::DocumentSymbolParams,
217) -> Result<Option<req::DocumentSymbolResponse>> { 228) -> Result<Option<lsp_types::DocumentSymbolResponse>> {
218 let _p = profile("handle_document_symbol"); 229 let _p = profile("handle_document_symbol");
219 let file_id = params.text_document.try_conv_with(&world)?; 230 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
220 let line_index = world.analysis().file_line_index(file_id)?; 231 let line_index = world.analysis().file_line_index(file_id)?;
221 let url = file_id.try_conv_with(&world)?;
222 232
223 let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); 233 let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new();
224 234
@@ -226,10 +236,10 @@ pub fn handle_document_symbol(
226 let doc_symbol = DocumentSymbol { 236 let doc_symbol = DocumentSymbol {
227 name: symbol.label, 237 name: symbol.label,
228 detail: symbol.detail, 238 detail: symbol.detail,
229 kind: symbol.kind.conv(), 239 kind: to_proto::symbol_kind(symbol.kind),
230 deprecated: Some(symbol.deprecated), 240 deprecated: Some(symbol.deprecated),
231 range: symbol.node_range.conv_with(&line_index), 241 range: to_proto::range(&line_index, symbol.node_range),
232 selection_range: symbol.navigation_range.conv_with(&line_index), 242 selection_range: to_proto::range(&line_index, symbol.navigation_range),
233 children: None, 243 children: None,
234 }; 244 };
235 parents.push((doc_symbol, symbol.parent)); 245 parents.push((doc_symbol, symbol.parent));
@@ -248,40 +258,41 @@ pub fn handle_document_symbol(
248 } 258 }
249 } 259 }
250 260
251 if world.config.client_caps.hierarchical_symbols { 261 let res = if world.config.client_caps.hierarchical_symbols {
252 Ok(Some(document_symbols.into())) 262 document_symbols.into()
253 } else { 263 } else {
264 let url = to_proto::url(&world, file_id)?;
254 let mut symbol_information = Vec::<SymbolInformation>::new(); 265 let mut symbol_information = Vec::<SymbolInformation>::new();
255 for symbol in document_symbols { 266 for symbol in document_symbols {
256 flatten_document_symbol(&symbol, None, &url, &mut symbol_information); 267 flatten_document_symbol(&symbol, None, &url, &mut symbol_information);
257 } 268 }
269 symbol_information.into()
270 };
271 return Ok(Some(res));
258 272
259 Ok(Some(symbol_information.into())) 273 fn flatten_document_symbol(
260 } 274 symbol: &DocumentSymbol,
261} 275 container_name: Option<String>,
262 276 url: &Url,
263fn flatten_document_symbol( 277 res: &mut Vec<SymbolInformation>,
264 symbol: &DocumentSymbol, 278 ) {
265 container_name: Option<String>, 279 res.push(SymbolInformation {
266 url: &Url, 280 name: symbol.name.clone(),
267 res: &mut Vec<SymbolInformation>, 281 kind: symbol.kind,
268) { 282 deprecated: symbol.deprecated,
269 res.push(SymbolInformation { 283 location: Location::new(url.clone(), symbol.range),
270 name: symbol.name.clone(), 284 container_name: container_name,
271 kind: symbol.kind, 285 });
272 deprecated: symbol.deprecated,
273 location: Location::new(url.clone(), symbol.range),
274 container_name: container_name,
275 });
276 286
277 for child in symbol.children.iter().flatten() { 287 for child in symbol.children.iter().flatten() {
278 flatten_document_symbol(child, Some(symbol.name.clone()), url, res); 288 flatten_document_symbol(child, Some(symbol.name.clone()), url, res);
289 }
279 } 290 }
280} 291}
281 292
282pub fn handle_workspace_symbol( 293pub fn handle_workspace_symbol(
283 world: WorldSnapshot, 294 world: WorldSnapshot,
284 params: req::WorkspaceSymbolParams, 295 params: lsp_types::WorkspaceSymbolParams,
285) -> Result<Option<Vec<SymbolInformation>>> { 296) -> Result<Option<Vec<SymbolInformation>>> {
286 let _p = profile("handle_workspace_symbol"); 297 let _p = profile("handle_workspace_symbol");
287 let all_symbols = params.query.contains('#'); 298 let all_symbols = params.query.contains('#');
@@ -312,8 +323,8 @@ pub fn handle_workspace_symbol(
312 for nav in world.analysis().symbol_search(query)? { 323 for nav in world.analysis().symbol_search(query)? {
313 let info = SymbolInformation { 324 let info = SymbolInformation {
314 name: nav.name().to_string(), 325 name: nav.name().to_string(),
315 kind: nav.kind().conv(), 326 kind: to_proto::symbol_kind(nav.kind()),
316 location: nav.try_conv_with(world)?, 327 location: to_proto::location(world, nav.file_range())?,
317 container_name: nav.container_name().map(|v| v.to_string()), 328 container_name: nav.container_name().map(|v| v.to_string()),
318 deprecated: None, 329 deprecated: None,
319 }; 330 };
@@ -325,86 +336,110 @@ pub fn handle_workspace_symbol(
325 336
326pub fn handle_goto_definition( 337pub fn handle_goto_definition(
327 world: WorldSnapshot, 338 world: WorldSnapshot,
328 params: req::GotoDefinitionParams, 339 params: lsp_types::GotoDefinitionParams,
329) -> Result<Option<req::GotoDefinitionResponse>> { 340) -> Result<Option<lsp_types::GotoDefinitionResponse>> {
330 let _p = profile("handle_goto_definition"); 341 let _p = profile("handle_goto_definition");
331 let position = params.text_document_position_params.try_conv_with(&world)?; 342 let position = from_proto::file_position(&world, params.text_document_position_params)?;
332 let nav_info = match world.analysis().goto_definition(position)? { 343 let nav_info = match world.analysis().goto_definition(position)? {
333 None => return Ok(None), 344 None => return Ok(None),
334 Some(it) => it, 345 Some(it) => it,
335 }; 346 };
336 let res = (position.file_id, nav_info).try_conv_with(&world)?; 347 let res = to_proto::goto_definition_response(
348 &world,
349 FileRange { file_id: position.file_id, range: nav_info.range },
350 nav_info.info,
351 )?;
337 Ok(Some(res)) 352 Ok(Some(res))
338} 353}
339 354
340pub fn handle_goto_implementation( 355pub fn handle_goto_implementation(
341 world: WorldSnapshot, 356 world: WorldSnapshot,
342 params: req::GotoImplementationParams, 357 params: lsp_types::request::GotoImplementationParams,
343) -> Result<Option<req::GotoImplementationResponse>> { 358) -> Result<Option<lsp_types::request::GotoImplementationResponse>> {
344 let _p = profile("handle_goto_implementation"); 359 let _p = profile("handle_goto_implementation");
345 let position = params.text_document_position_params.try_conv_with(&world)?; 360 let position = from_proto::file_position(&world, params.text_document_position_params)?;
346 let nav_info = match world.analysis().goto_implementation(position)? { 361 let nav_info = match world.analysis().goto_implementation(position)? {
347 None => return Ok(None), 362 None => return Ok(None),
348 Some(it) => it, 363 Some(it) => it,
349 }; 364 };
350 let res = (position.file_id, nav_info).try_conv_with(&world)?; 365 let res = to_proto::goto_definition_response(
366 &world,
367 FileRange { file_id: position.file_id, range: nav_info.range },
368 nav_info.info,
369 )?;
351 Ok(Some(res)) 370 Ok(Some(res))
352} 371}
353 372
354pub fn handle_goto_type_definition( 373pub fn handle_goto_type_definition(
355 world: WorldSnapshot, 374 world: WorldSnapshot,
356 params: req::GotoTypeDefinitionParams, 375 params: lsp_types::request::GotoTypeDefinitionParams,
357) -> Result<Option<req::GotoTypeDefinitionResponse>> { 376) -> Result<Option<lsp_types::request::GotoTypeDefinitionResponse>> {
358 let _p = profile("handle_goto_type_definition"); 377 let _p = profile("handle_goto_type_definition");
359 let position = params.text_document_position_params.try_conv_with(&world)?; 378 let position = from_proto::file_position(&world, params.text_document_position_params)?;
360 let nav_info = match world.analysis().goto_type_definition(position)? { 379 let nav_info = match world.analysis().goto_type_definition(position)? {
361 None => return Ok(None), 380 None => return Ok(None),
362 Some(it) => it, 381 Some(it) => it,
363 }; 382 };
364 let res = (position.file_id, nav_info).try_conv_with(&world)?; 383 let res = to_proto::goto_definition_response(
384 &world,
385 FileRange { file_id: position.file_id, range: nav_info.range },
386 nav_info.info,
387 )?;
365 Ok(Some(res)) 388 Ok(Some(res))
366} 389}
367 390
368pub fn handle_parent_module( 391pub fn handle_parent_module(
369 world: WorldSnapshot, 392 world: WorldSnapshot,
370 params: req::TextDocumentPositionParams, 393 params: lsp_types::TextDocumentPositionParams,
371) -> Result<Vec<Location>> { 394) -> Result<Vec<Location>> {
372 let _p = profile("handle_parent_module"); 395 let _p = profile("handle_parent_module");
373 let position = params.try_conv_with(&world)?; 396 let position = from_proto::file_position(&world, params)?;
374 world.analysis().parent_module(position)?.iter().try_conv_with_to_vec(&world) 397 world
398 .analysis()
399 .parent_module(position)?
400 .into_iter()
401 .map(|it| to_proto::location(&world, it.file_range()))
402 .collect::<Result<Vec<_>>>()
375} 403}
376 404
377pub fn handle_runnables( 405pub fn handle_runnables(
378 world: WorldSnapshot, 406 world: WorldSnapshot,
379 params: req::RunnablesParams, 407 params: lsp_ext::RunnablesParams,
380) -> Result<Vec<req::Runnable>> { 408) -> Result<Vec<lsp_ext::Runnable>> {
381 let _p = profile("handle_runnables"); 409 let _p = profile("handle_runnables");
382 let file_id = params.text_document.try_conv_with(&world)?; 410 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
383 let line_index = world.analysis().file_line_index(file_id)?; 411 let line_index = world.analysis().file_line_index(file_id)?;
384 let offset = params.position.map(|it| it.conv_with(&line_index)); 412 let offset = params.position.map(|it| from_proto::offset(&line_index, it));
385 let mut res = Vec::new(); 413 let mut res = Vec::new();
386 let workspace_root = world.workspace_root_for(file_id); 414 let workspace_root = world.workspace_root_for(file_id);
415 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?;
387 for runnable in world.analysis().runnables(file_id)? { 416 for runnable in world.analysis().runnables(file_id)? {
388 if let Some(offset) = offset { 417 if let Some(offset) = offset {
389 if !runnable.range.contains_inclusive(offset) { 418 if !runnable.range.contains_inclusive(offset) {
390 continue; 419 continue;
391 } 420 }
392 } 421 }
422 // Do not suggest binary run on other target than binary
423 if let RunnableKind::Bin = runnable.kind {
424 if let Some(spec) = &cargo_spec {
425 match spec.target_kind {
426 TargetKind::Bin => {}
427 _ => continue,
428 }
429 }
430 }
393 res.push(to_lsp_runnable(&world, file_id, runnable)?); 431 res.push(to_lsp_runnable(&world, file_id, runnable)?);
394 } 432 }
433
395 // Add `cargo check` and `cargo test` for the whole package 434 // Add `cargo check` and `cargo test` for the whole package
396 match CargoTargetSpec::for_file(&world, file_id)? { 435 match cargo_spec {
397 Some(spec) => { 436 Some(spec) => {
398 for &cmd in ["check", "test"].iter() { 437 for &cmd in ["check", "test"].iter() {
399 res.push(req::Runnable { 438 res.push(lsp_ext::Runnable {
400 range: Default::default(), 439 range: Default::default(),
401 label: format!("cargo {} -p {}", cmd, spec.package), 440 label: format!("cargo {} -p {}", cmd, spec.package),
402 bin: "cargo".to_string(), 441 bin: "cargo".to_string(),
403 args: { 442 args: vec![cmd.to_string(), "--package".to_string(), spec.package.clone()],
404 let mut args = vec![cmd.to_string()];
405 spec.clone().push_to(&mut args);
406 args
407 },
408 extra_args: Vec::new(), 443 extra_args: Vec::new(),
409 env: FxHashMap::default(), 444 env: FxHashMap::default(),
410 cwd: workspace_root.map(|root| root.to_owned()), 445 cwd: workspace_root.map(|root| root.to_owned()),
@@ -412,7 +447,7 @@ pub fn handle_runnables(
412 } 447 }
413 } 448 }
414 None => { 449 None => {
415 res.push(req::Runnable { 450 res.push(lsp_ext::Runnable {
416 range: Default::default(), 451 range: Default::default(),
417 label: "cargo check --workspace".to_string(), 452 label: "cargo check --workspace".to_string(),
418 bin: "cargo".to_string(), 453 bin: "cargo".to_string(),
@@ -428,10 +463,10 @@ pub fn handle_runnables(
428 463
429pub fn handle_completion( 464pub fn handle_completion(
430 world: WorldSnapshot, 465 world: WorldSnapshot,
431 params: req::CompletionParams, 466 params: lsp_types::CompletionParams,
432) -> Result<Option<req::CompletionResponse>> { 467) -> Result<Option<lsp_types::CompletionResponse>> {
433 let _p = profile("handle_completion"); 468 let _p = profile("handle_completion");
434 let position = params.text_document_position.try_conv_with(&world)?; 469 let position = from_proto::file_position(&world, params.text_document_position)?;
435 let completion_triggered_after_single_colon = { 470 let completion_triggered_after_single_colon = {
436 let mut res = false; 471 let mut res = false;
437 if let Some(ctx) = params.context { 472 if let Some(ctx) = params.context {
@@ -454,14 +489,16 @@ pub fn handle_completion(
454 return Ok(None); 489 return Ok(None);
455 } 490 }
456 491
457 let items = match world.analysis().completions(position, &world.config.completion)? { 492 let items = match world.analysis().completions(&world.config.completion, position)? {
458 None => return Ok(None), 493 None => return Ok(None),
459 Some(items) => items, 494 Some(items) => items,
460 }; 495 };
461 let line_index = world.analysis().file_line_index(position.file_id)?; 496 let line_index = world.analysis().file_line_index(position.file_id)?;
462 let line_endings = world.file_line_endings(position.file_id); 497 let line_endings = world.file_line_endings(position.file_id);
463 let items: Vec<CompletionItem> = 498 let items: Vec<CompletionItem> = items
464 items.into_iter().map(|item| item.conv_with((&line_index, line_endings))).collect(); 499 .into_iter()
500 .map(|item| to_proto::completion_item(&line_index, line_endings, item))
501 .collect();
465 502
466 Ok(Some(items.into())) 503 Ok(Some(items.into()))
467} 504}
@@ -471,52 +508,51 @@ pub fn handle_folding_range(
471 params: FoldingRangeParams, 508 params: FoldingRangeParams,
472) -> Result<Option<Vec<FoldingRange>>> { 509) -> Result<Option<Vec<FoldingRange>>> {
473 let _p = profile("handle_folding_range"); 510 let _p = profile("handle_folding_range");
474 let file_id = params.text_document.try_conv_with(&world)?; 511 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
475 let folds = world.analysis().folding_ranges(file_id)?; 512 let folds = world.analysis().folding_ranges(file_id)?;
476 let text = world.analysis().file_text(file_id)?; 513 let text = world.analysis().file_text(file_id)?;
477 let line_index = world.analysis().file_line_index(file_id)?; 514 let line_index = world.analysis().file_line_index(file_id)?;
478 let ctx = FoldConvCtx { 515 let line_folding_only = world.config.client_caps.line_folding_only;
479 text: &text, 516 let res = folds
480 line_index: &line_index, 517 .into_iter()
481 line_folding_only: world.config.client_caps.line_folding_only, 518 .map(|it| to_proto::folding_range(&*text, &line_index, line_folding_only, it))
482 }; 519 .collect();
483 let res = Some(folds.into_iter().map_conv_with(&ctx).collect()); 520 Ok(Some(res))
484 Ok(res)
485} 521}
486 522
487pub fn handle_signature_help( 523pub fn handle_signature_help(
488 world: WorldSnapshot, 524 world: WorldSnapshot,
489 params: req::SignatureHelpParams, 525 params: lsp_types::SignatureHelpParams,
490) -> Result<Option<req::SignatureHelp>> { 526) -> Result<Option<lsp_types::SignatureHelp>> {
491 let _p = profile("handle_signature_help"); 527 let _p = profile("handle_signature_help");
492 let position = params.text_document_position_params.try_conv_with(&world)?; 528 let position = from_proto::file_position(&world, params.text_document_position_params)?;
493 if let Some(call_info) = world.analysis().call_info(position)? { 529 let call_info = match world.analysis().call_info(position)? {
494 let concise = !world.config.call_info_full; 530 None => return Ok(None),
495 let mut active_parameter = call_info.active_parameter.map(|it| it as i64); 531 Some(it) => it,
496 if concise && call_info.signature.has_self_param { 532 };
497 active_parameter = active_parameter.map(|it| it.saturating_sub(1)); 533 let concise = !world.config.call_info_full;
498 } 534 let mut active_parameter = call_info.active_parameter.map(|it| it as i64);
499 let sig_info = call_info.signature.conv_with(concise); 535 if concise && call_info.signature.has_self_param {
500 536 active_parameter = active_parameter.map(|it| it.saturating_sub(1));
501 Ok(Some(req::SignatureHelp {
502 signatures: vec![sig_info],
503 active_signature: Some(0),
504 active_parameter,
505 }))
506 } else {
507 Ok(None)
508 } 537 }
538 let sig_info = to_proto::signature_information(call_info.signature, concise);
539
540 Ok(Some(lsp_types::SignatureHelp {
541 signatures: vec![sig_info],
542 active_signature: Some(0),
543 active_parameter,
544 }))
509} 545}
510 546
511pub fn handle_hover(world: WorldSnapshot, params: req::HoverParams) -> Result<Option<Hover>> { 547pub fn handle_hover(world: WorldSnapshot, params: lsp_types::HoverParams) -> Result<Option<Hover>> {
512 let _p = profile("handle_hover"); 548 let _p = profile("handle_hover");
513 let position = params.text_document_position_params.try_conv_with(&world)?; 549 let position = from_proto::file_position(&world, params.text_document_position_params)?;
514 let info = match world.analysis().hover(position)? { 550 let info = match world.analysis().hover(position)? {
515 None => return Ok(None), 551 None => return Ok(None),
516 Some(info) => info, 552 Some(info) => info,
517 }; 553 };
518 let line_index = world.analysis.file_line_index(position.file_id)?; 554 let line_index = world.analysis.file_line_index(position.file_id)?;
519 let range = info.range.conv_with(&line_index); 555 let range = to_proto::range(&line_index, info.range);
520 let res = Hover { 556 let res = Hover {
521 contents: HoverContents::Markup(MarkupContent { 557 contents: HoverContents::Markup(MarkupContent {
522 kind: MarkupKind::Markdown, 558 kind: MarkupKind::Markdown,
@@ -529,10 +565,10 @@ pub fn handle_hover(world: WorldSnapshot, params: req::HoverParams) -> Result<Op
529 565
530pub fn handle_prepare_rename( 566pub fn handle_prepare_rename(
531 world: WorldSnapshot, 567 world: WorldSnapshot,
532 params: req::TextDocumentPositionParams, 568 params: lsp_types::TextDocumentPositionParams,
533) -> Result<Option<PrepareRenameResponse>> { 569) -> Result<Option<PrepareRenameResponse>> {
534 let _p = profile("handle_prepare_rename"); 570 let _p = profile("handle_prepare_rename");
535 let position = params.try_conv_with(&world)?; 571 let position = from_proto::file_position(&world, params)?;
536 572
537 let optional_change = world.analysis().rename(position, "dummy")?; 573 let optional_change = world.analysis().rename(position, "dummy")?;
538 let range = match optional_change { 574 let range = match optional_change {
@@ -540,15 +576,14 @@ pub fn handle_prepare_rename(
540 Some(it) => it.range, 576 Some(it) => it.range,
541 }; 577 };
542 578
543 let file_id = params.text_document.try_conv_with(&world)?; 579 let line_index = world.analysis().file_line_index(position.file_id)?;
544 let line_index = world.analysis().file_line_index(file_id)?; 580 let range = to_proto::range(&line_index, range);
545 let range = range.conv_with(&line_index);
546 Ok(Some(PrepareRenameResponse::Range(range))) 581 Ok(Some(PrepareRenameResponse::Range(range)))
547} 582}
548 583
549pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Option<WorkspaceEdit>> { 584pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Option<WorkspaceEdit>> {
550 let _p = profile("handle_rename"); 585 let _p = profile("handle_rename");
551 let position = params.text_document_position.try_conv_with(&world)?; 586 let position = from_proto::file_position(&world, params.text_document_position)?;
552 587
553 if params.new_name.is_empty() { 588 if params.new_name.is_empty() {
554 return Err(LspError::new( 589 return Err(LspError::new(
@@ -559,22 +594,20 @@ pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result<Optio
559 } 594 }
560 595
561 let optional_change = world.analysis().rename(position, &*params.new_name)?; 596 let optional_change = world.analysis().rename(position, &*params.new_name)?;
562 let change = match optional_change { 597 let source_change = match optional_change {
563 None => return Ok(None), 598 None => return Ok(None),
564 Some(it) => it.info, 599 Some(it) => it.info,
565 }; 600 };
566 601 let workspace_edit = to_proto::workspace_edit(&world, source_change)?;
567 let source_change_req = change.try_conv_with(&world)?; 602 Ok(Some(workspace_edit))
568
569 Ok(Some(source_change_req.workspace_edit))
570} 603}
571 604
572pub fn handle_references( 605pub fn handle_references(
573 world: WorldSnapshot, 606 world: WorldSnapshot,
574 params: req::ReferenceParams, 607 params: lsp_types::ReferenceParams,
575) -> Result<Option<Vec<Location>>> { 608) -> Result<Option<Vec<Location>>> {
576 let _p = profile("handle_references"); 609 let _p = profile("handle_references");
577 let position = params.text_document_position.try_conv_with(&world)?; 610 let position = from_proto::file_position(&world, params.text_document_position)?;
578 611
579 let refs = match world.analysis().find_all_refs(position, None)? { 612 let refs = match world.analysis().find_all_refs(position, None)? {
580 None => return Ok(None), 613 None => return Ok(None),
@@ -583,33 +616,13 @@ pub fn handle_references(
583 616
584 let locations = if params.context.include_declaration { 617 let locations = if params.context.include_declaration {
585 refs.into_iter() 618 refs.into_iter()
586 .filter_map(|reference| { 619 .filter_map(|reference| to_proto::location(&world, reference.file_range).ok())
587 let line_index =
588 world.analysis().file_line_index(reference.file_range.file_id).ok()?;
589 to_location(
590 reference.file_range.file_id,
591 reference.file_range.range,
592 &world,
593 &line_index,
594 )
595 .ok()
596 })
597 .collect() 620 .collect()
598 } else { 621 } else {
599 // Only iterate over the references if include_declaration was false 622 // Only iterate over the references if include_declaration was false
600 refs.references() 623 refs.references()
601 .iter() 624 .iter()
602 .filter_map(|reference| { 625 .filter_map(|reference| to_proto::location(&world, reference.file_range).ok())
603 let line_index =
604 world.analysis().file_line_index(reference.file_range.file_id).ok()?;
605 to_location(
606 reference.file_range.file_id,
607 reference.file_range.range,
608 &world,
609 &line_index,
610 )
611 .ok()
612 })
613 .collect() 626 .collect()
614 }; 627 };
615 628
@@ -619,14 +632,14 @@ pub fn handle_references(
619pub fn handle_formatting( 632pub fn handle_formatting(
620 world: WorldSnapshot, 633 world: WorldSnapshot,
621 params: DocumentFormattingParams, 634 params: DocumentFormattingParams,
622) -> Result<Option<Vec<TextEdit>>> { 635) -> Result<Option<Vec<lsp_types::TextEdit>>> {
623 let _p = profile("handle_formatting"); 636 let _p = profile("handle_formatting");
624 let file_id = params.text_document.try_conv_with(&world)?; 637 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
625 let file = world.analysis().file_text(file_id)?; 638 let file = world.analysis().file_text(file_id)?;
626 let crate_ids = world.analysis().crate_for(file_id)?; 639 let crate_ids = world.analysis().crate_for(file_id)?;
627 640
628 let file_line_index = world.analysis().file_line_index(file_id)?; 641 let file_line_index = world.analysis().file_line_index(file_id)?;
629 let end_position = TextSize::of(file.as_str()).conv_with(&file_line_index); 642 let end_position = to_proto::position(&file_line_index, TextSize::of(file.as_str()));
630 643
631 let mut rustfmt = match &world.config.rustfmt { 644 let mut rustfmt = match &world.config.rustfmt {
632 RustfmtConfig::Rustfmt { extra_args } => { 645 RustfmtConfig::Rustfmt { extra_args } => {
@@ -686,42 +699,30 @@ pub fn handle_formatting(
686 } 699 }
687 } 700 }
688 701
689 Ok(Some(vec![TextEdit { 702 Ok(Some(vec![lsp_types::TextEdit {
690 range: Range::new(Position::new(0, 0), end_position), 703 range: Range::new(Position::new(0, 0), end_position),
691 new_text: captured_stdout, 704 new_text: captured_stdout,
692 }])) 705 }]))
693} 706}
694 707
695fn create_single_code_action(assist: Assist, world: &WorldSnapshot) -> Result<CodeAction> {
696 let arg = to_value(assist.source_change.try_conv_with(world)?)?;
697 let title = assist.label;
698 let command = Command {
699 title: title.clone(),
700 command: "rust-analyzer.applySourceChange".to_string(),
701 arguments: Some(vec![arg]),
702 };
703
704 Ok(CodeAction {
705 title,
706 kind: Some(String::new()),
707 diagnostics: None,
708 edit: None,
709 command: Some(command),
710 is_preferred: None,
711 })
712}
713
714pub fn handle_code_action( 708pub fn handle_code_action(
715 world: WorldSnapshot, 709 world: WorldSnapshot,
716 params: req::CodeActionParams, 710 params: lsp_types::CodeActionParams,
717) -> Result<Option<CodeActionResponse>> { 711) -> Result<Option<Vec<lsp_ext::CodeAction>>> {
718 let _p = profile("handle_code_action"); 712 let _p = profile("handle_code_action");
719 let file_id = params.text_document.try_conv_with(&world)?; 713 // We intentionally don't support command-based actions, as those either
714 // requires custom client-code anyway, or requires server-initiated edits.
715 // Server initiated edits break causality, so we avoid those as well.
716 if !world.config.client_caps.code_action_literals {
717 return Ok(None);
718 }
719
720 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
720 let line_index = world.analysis().file_line_index(file_id)?; 721 let line_index = world.analysis().file_line_index(file_id)?;
721 let range = params.range.conv_with(&line_index); 722 let range = from_proto::text_range(&line_index, params.range);
722 723
723 let diagnostics = world.analysis().diagnostics(file_id)?; 724 let diagnostics = world.analysis().diagnostics(file_id)?;
724 let mut res = CodeActionResponse::default(); 725 let mut res: Vec<lsp_ext::CodeAction> = Vec::new();
725 726
726 let fixes_from_diagnostics = diagnostics 727 let fixes_from_diagnostics = diagnostics
727 .into_iter() 728 .into_iter()
@@ -731,26 +732,13 @@ pub fn handle_code_action(
731 732
732 for source_edit in fixes_from_diagnostics { 733 for source_edit in fixes_from_diagnostics {
733 let title = source_edit.label.clone(); 734 let title = source_edit.label.clone();
734 let edit = source_edit.try_conv_with(&world)?; 735 let edit = to_proto::snippet_workspace_edit(&world, source_edit)?;
735 736 let action = lsp_ext::CodeAction { title, kind: None, edit: Some(edit), command: None };
736 let command = Command { 737 res.push(action);
737 title,
738 command: "rust-analyzer.applySourceChange".to_string(),
739 arguments: Some(vec![to_value(edit).unwrap()]),
740 };
741 let action = CodeAction {
742 title: command.title.clone(),
743 kind: None,
744 diagnostics: None,
745 edit: None,
746 command: Some(command),
747 is_preferred: None,
748 };
749 res.push(action.into());
750 } 738 }
751 739
752 for fix in world.check_fixes.get(&file_id).into_iter().flatten() { 740 for fix in world.check_fixes.get(&file_id).into_iter().flatten() {
753 let fix_range = fix.range.conv_with(&line_index); 741 let fix_range = from_proto::text_range(&line_index, fix.range);
754 if fix_range.intersect(range).is_none() { 742 if fix_range.intersect(range).is_none() {
755 continue; 743 continue;
756 } 744 }
@@ -758,34 +746,41 @@ pub fn handle_code_action(
758 } 746 }
759 747
760 let mut grouped_assists: FxHashMap<String, (usize, Vec<Assist>)> = FxHashMap::default(); 748 let mut grouped_assists: FxHashMap<String, (usize, Vec<Assist>)> = FxHashMap::default();
761 for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() { 749 for assist in
750 world.analysis().assists(&world.config.assist, FileRange { file_id, range })?.into_iter()
751 {
762 match &assist.group_label { 752 match &assist.group_label {
763 Some(label) => grouped_assists 753 Some(label) => grouped_assists
764 .entry(label.to_owned()) 754 .entry(label.to_owned())
765 .or_insert_with(|| { 755 .or_insert_with(|| {
766 let idx = res.len(); 756 let idx = res.len();
767 let dummy = Command::new(String::new(), String::new(), None); 757 let dummy = lsp_ext::CodeAction {
768 res.push(dummy.into()); 758 title: String::new(),
759 kind: None,
760 command: None,
761 edit: None,
762 };
763 res.push(dummy);
769 (idx, Vec::new()) 764 (idx, Vec::new())
770 }) 765 })
771 .1 766 .1
772 .push(assist), 767 .push(assist),
773 None => { 768 None => {
774 res.push(create_single_code_action(assist, &world)?.into()); 769 res.push(to_proto::code_action(&world, assist)?.into());
775 } 770 }
776 } 771 }
777 } 772 }
778 773
779 for (group_label, (idx, assists)) in grouped_assists { 774 for (group_label, (idx, assists)) in grouped_assists {
780 if assists.len() == 1 { 775 if assists.len() == 1 {
781 res[idx] = 776 res[idx] = to_proto::code_action(&world, assists.into_iter().next().unwrap())?.into();
782 create_single_code_action(assists.into_iter().next().unwrap(), &world)?.into();
783 } else { 777 } else {
784 let title = group_label; 778 let title = group_label;
785 779
786 let mut arguments = Vec::with_capacity(assists.len()); 780 let mut arguments = Vec::with_capacity(assists.len());
787 for assist in assists { 781 for assist in assists {
788 arguments.push(to_value(assist.source_change.try_conv_with(&world)?)?); 782 let source_change = to_proto::source_change(&world, assist.source_change)?;
783 arguments.push(to_value(source_change)?);
789 } 784 }
790 785
791 let command = Some(Command { 786 let command = Some(Command {
@@ -793,121 +788,127 @@ pub fn handle_code_action(
793 command: "rust-analyzer.selectAndApplySourceChange".to_string(), 788 command: "rust-analyzer.selectAndApplySourceChange".to_string(),
794 arguments: Some(vec![serde_json::Value::Array(arguments)]), 789 arguments: Some(vec![serde_json::Value::Array(arguments)]),
795 }); 790 });
796 res[idx] = CodeAction { 791 res[idx] = lsp_ext::CodeAction { title, kind: None, edit: None, command };
797 title,
798 kind: None,
799 diagnostics: None,
800 edit: None,
801 command,
802 is_preferred: None,
803 }
804 .into();
805 } 792 }
806 } 793 }
807 794
808 // If the client only supports commands then filter the list
809 // and remove and actions that depend on edits.
810 if !world.config.client_caps.code_action_literals {
811 // FIXME: use drain_filter once it hits stable.
812 res = res
813 .into_iter()
814 .filter_map(|it| match it {
815 cmd @ lsp_types::CodeActionOrCommand::Command(_) => Some(cmd),
816 lsp_types::CodeActionOrCommand::CodeAction(action) => match action.command {
817 Some(cmd) if action.edit.is_none() => {
818 Some(lsp_types::CodeActionOrCommand::Command(cmd))
819 }
820 _ => None,
821 },
822 })
823 .collect();
824 }
825 Ok(Some(res)) 795 Ok(Some(res))
826} 796}
827 797
828pub fn handle_code_lens( 798pub fn handle_code_lens(
829 world: WorldSnapshot, 799 world: WorldSnapshot,
830 params: req::CodeLensParams, 800 params: lsp_types::CodeLensParams,
831) -> Result<Option<Vec<CodeLens>>> { 801) -> Result<Option<Vec<CodeLens>>> {
832 let _p = profile("handle_code_lens"); 802 let _p = profile("handle_code_lens");
833 let file_id = params.text_document.try_conv_with(&world)?;
834 let line_index = world.analysis().file_line_index(file_id)?;
835
836 let mut lenses: Vec<CodeLens> = Default::default(); 803 let mut lenses: Vec<CodeLens> = Default::default();
837 804
838 // Gather runnables 805 if world.config.lens.none() {
839 for runnable in world.analysis().runnables(file_id)? { 806 // early return before any db query!
840 let title = match &runnable.kind { 807 return Ok(Some(lenses));
841 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶️\u{fe0e}Run Test",
842 RunnableKind::Bench { .. } => "Run Bench",
843 RunnableKind::Bin => "Run",
844 }
845 .to_string();
846 let mut r = to_lsp_runnable(&world, file_id, runnable)?;
847 let lens = CodeLens {
848 range: r.range,
849 command: Some(Command {
850 title,
851 command: "rust-analyzer.runSingle".into(),
852 arguments: Some(vec![to_value(&r).unwrap()]),
853 }),
854 data: None,
855 };
856 lenses.push(lens);
857
858 if r.args[0] == "run" {
859 r.args[0] = "build".into();
860 } else {
861 r.args.push("--no-run".into());
862 }
863 let debug_lens = CodeLens {
864 range: r.range,
865 command: Some(Command {
866 title: "Debug".into(),
867 command: "rust-analyzer.debugSingle".into(),
868 arguments: Some(vec![to_value(r).unwrap()]),
869 }),
870 data: None,
871 };
872 lenses.push(debug_lens);
873 } 808 }
874 809
875 // Handle impls 810 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
876 lenses.extend( 811 let line_index = world.analysis().file_line_index(file_id)?;
877 world 812 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?;
878 .analysis() 813
879 .file_structure(file_id)? 814 if world.config.lens.runnable() {
880 .into_iter() 815 // Gather runnables
881 .filter(|it| match it.kind { 816 for runnable in world.analysis().runnables(file_id)? {
882 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true, 817 let (run_title, debugee) = match &runnable.kind {
883 _ => false, 818 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => {
884 }) 819 ("▶\u{fe0e} Run Test", true)
885 .map(|it| { 820 }
886 let range = it.node_range.conv_with(&line_index); 821 RunnableKind::DocTest { .. } => {
887 let pos = range.start; 822 // cargo does not support -no-run for doctests
888 let lens_params = req::GotoImplementationParams { 823 ("▶\u{fe0e} Run Doctest", false)
889 text_document_position_params: req::TextDocumentPositionParams::new( 824 }
890 params.text_document.clone(), 825 RunnableKind::Bench { .. } => {
891 pos, 826 // Nothing wrong with bench debugging
892 ), 827 ("Run Bench", true)
893 work_done_progress_params: Default::default(), 828 }
894 partial_result_params: Default::default(), 829 RunnableKind::Bin => {
830 // Do not suggest binary run on other target than binary
831 match &cargo_spec {
832 Some(spec) => match spec.target_kind {
833 TargetKind::Bin => ("Run", true),
834 _ => continue,
835 },
836 None => continue,
837 }
838 }
839 };
840
841 let mut r = to_lsp_runnable(&world, file_id, runnable)?;
842 if world.config.lens.run {
843 let lens = CodeLens {
844 range: r.range,
845 command: Some(Command {
846 title: run_title.to_string(),
847 command: "rust-analyzer.runSingle".into(),
848 arguments: Some(vec![to_value(&r).unwrap()]),
849 }),
850 data: None,
895 }; 851 };
896 CodeLens { 852 lenses.push(lens);
897 range, 853 }
898 command: None, 854
899 data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()), 855 if debugee && world.config.lens.debug {
856 if r.args[0] == "run" {
857 r.args[0] = "build".into();
858 } else {
859 r.args.push("--no-run".into());
900 } 860 }
901 }), 861 let debug_lens = CodeLens {
902 ); 862 range: r.range,
863 command: Some(Command {
864 title: "Debug".into(),
865 command: "rust-analyzer.debugSingle".into(),
866 arguments: Some(vec![to_value(r).unwrap()]),
867 }),
868 data: None,
869 };
870 lenses.push(debug_lens);
871 }
872 }
873 }
903 874
875 if world.config.lens.impementations {
876 // Handle impls
877 lenses.extend(
878 world
879 .analysis()
880 .file_structure(file_id)?
881 .into_iter()
882 .filter(|it| match it.kind {
883 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true,
884 _ => false,
885 })
886 .map(|it| {
887 let range = to_proto::range(&line_index, it.node_range);
888 let pos = range.start;
889 let lens_params = lsp_types::request::GotoImplementationParams {
890 text_document_position_params: lsp_types::TextDocumentPositionParams::new(
891 params.text_document.clone(),
892 pos,
893 ),
894 work_done_progress_params: Default::default(),
895 partial_result_params: Default::default(),
896 };
897 CodeLens {
898 range,
899 command: None,
900 data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()),
901 }
902 }),
903 );
904 }
904 Ok(Some(lenses)) 905 Ok(Some(lenses))
905} 906}
906 907
907#[derive(Debug, Serialize, Deserialize)] 908#[derive(Debug, Serialize, Deserialize)]
908#[serde(rename_all = "camelCase")] 909#[serde(rename_all = "camelCase")]
909enum CodeLensResolveData { 910enum CodeLensResolveData {
910 Impls(req::GotoImplementationParams), 911 Impls(lsp_types::request::GotoImplementationParams),
911} 912}
912 913
913pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> { 914pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Result<CodeLens> {
@@ -918,9 +919,9 @@ pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Re
918 Some(CodeLensResolveData::Impls(lens_params)) => { 919 Some(CodeLensResolveData::Impls(lens_params)) => {
919 let locations: Vec<Location> = 920 let locations: Vec<Location> =
920 match handle_goto_implementation(world, lens_params.clone())? { 921 match handle_goto_implementation(world, lens_params.clone())? {
921 Some(req::GotoDefinitionResponse::Scalar(loc)) => vec![loc], 922 Some(lsp_types::GotoDefinitionResponse::Scalar(loc)) => vec![loc],
922 Some(req::GotoDefinitionResponse::Array(locs)) => locs, 923 Some(lsp_types::GotoDefinitionResponse::Array(locs)) => locs,
923 Some(req::GotoDefinitionResponse::Link(links)) => links 924 Some(lsp_types::GotoDefinitionResponse::Link(links)) => links
924 .into_iter() 925 .into_iter()
925 .map(|link| Location::new(link.target_uri, link.target_selection_range)) 926 .map(|link| Location::new(link.target_uri, link.target_selection_range))
926 .collect(), 927 .collect(),
@@ -957,37 +958,39 @@ pub fn handle_code_lens_resolve(world: WorldSnapshot, code_lens: CodeLens) -> Re
957 958
958pub fn handle_document_highlight( 959pub fn handle_document_highlight(
959 world: WorldSnapshot, 960 world: WorldSnapshot,
960 params: req::DocumentHighlightParams, 961 params: lsp_types::DocumentHighlightParams,
961) -> Result<Option<Vec<DocumentHighlight>>> { 962) -> Result<Option<Vec<DocumentHighlight>>> {
962 let _p = profile("handle_document_highlight"); 963 let _p = profile("handle_document_highlight");
963 let file_id = params.text_document_position_params.text_document.try_conv_with(&world)?; 964 let position = from_proto::file_position(&world, params.text_document_position_params)?;
964 let line_index = world.analysis().file_line_index(file_id)?; 965 let line_index = world.analysis().file_line_index(position.file_id)?;
965 966
966 let refs = match world.analysis().find_all_refs( 967 let refs = match world
967 params.text_document_position_params.try_conv_with(&world)?, 968 .analysis()
968 Some(SearchScope::single_file(file_id)), 969 .find_all_refs(position, Some(SearchScope::single_file(position.file_id)))?
969 )? { 970 {
970 None => return Ok(None), 971 None => return Ok(None),
971 Some(refs) => refs, 972 Some(refs) => refs,
972 }; 973 };
973 974
974 Ok(Some( 975 let res = refs
975 refs.into_iter() 976 .into_iter()
976 .filter(|reference| reference.file_range.file_id == file_id) 977 .filter(|reference| reference.file_range.file_id == position.file_id)
977 .map(|reference| DocumentHighlight { 978 .map(|reference| DocumentHighlight {
978 range: reference.file_range.range.conv_with(&line_index), 979 range: to_proto::range(&line_index, reference.file_range.range),
979 kind: reference.access.map(|it| it.conv()), 980 kind: reference.access.map(to_proto::document_highlight_kind),
980 }) 981 })
981 .collect(), 982 .collect();
982 )) 983 Ok(Some(res))
983} 984}
984 985
985pub fn handle_ssr(world: WorldSnapshot, params: req::SsrParams) -> Result<req::SourceChange> { 986pub fn handle_ssr(
987 world: WorldSnapshot,
988 params: lsp_ext::SsrParams,
989) -> Result<lsp_ext::SourceChange> {
986 let _p = profile("handle_ssr"); 990 let _p = profile("handle_ssr");
987 world 991 let source_change =
988 .analysis() 992 world.analysis().structural_search_replace(&params.query, params.parse_only)??;
989 .structural_search_replace(&params.query, params.parse_only)?? 993 to_proto::source_change(&world, source_change)
990 .try_conv_with(&world)
991} 994}
992 995
993pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<DiagnosticTask> { 996pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<DiagnosticTask> {
@@ -998,8 +1001,8 @@ pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<Dia
998 .diagnostics(file_id)? 1001 .diagnostics(file_id)?
999 .into_iter() 1002 .into_iter()
1000 .map(|d| Diagnostic { 1003 .map(|d| Diagnostic {
1001 range: d.range.conv_with(&line_index), 1004 range: to_proto::range(&line_index, d.range),
1002 severity: Some(d.severity.conv()), 1005 severity: Some(to_proto::diagnostic_severity(d.severity)),
1003 code: None, 1006 code: None,
1004 source: Some("rust-analyzer".to_string()), 1007 source: Some("rust-analyzer".to_string()),
1005 message: d.message, 1008 message: d.message,
@@ -1014,18 +1017,22 @@ fn to_lsp_runnable(
1014 world: &WorldSnapshot, 1017 world: &WorldSnapshot,
1015 file_id: FileId, 1018 file_id: FileId,
1016 runnable: Runnable, 1019 runnable: Runnable,
1017) -> Result<req::Runnable> { 1020) -> Result<lsp_ext::Runnable> {
1018 let spec = CargoTargetSpec::for_file(world, file_id)?; 1021 let spec = CargoTargetSpec::for_file(world, file_id)?;
1022 let target = spec.as_ref().map(|s| s.target.clone());
1019 let (args, extra_args) = CargoTargetSpec::runnable_args(spec, &runnable.kind)?; 1023 let (args, extra_args) = CargoTargetSpec::runnable_args(spec, &runnable.kind)?;
1020 let line_index = world.analysis().file_line_index(file_id)?; 1024 let line_index = world.analysis().file_line_index(file_id)?;
1021 let label = match &runnable.kind { 1025 let label = match &runnable.kind {
1022 RunnableKind::Test { test_id, .. } => format!("test {}", test_id), 1026 RunnableKind::Test { test_id, .. } => format!("test {}", test_id),
1023 RunnableKind::TestMod { path } => format!("test-mod {}", path), 1027 RunnableKind::TestMod { path } => format!("test-mod {}", path),
1024 RunnableKind::Bench { test_id } => format!("bench {}", test_id), 1028 RunnableKind::Bench { test_id } => format!("bench {}", test_id),
1025 RunnableKind::Bin => "run binary".to_string(), 1029 RunnableKind::DocTest { test_id, .. } => format!("doctest {}", test_id),
1030 RunnableKind::Bin => {
1031 target.map_or_else(|| "run binary".to_string(), |t| format!("run {}", t))
1032 }
1026 }; 1033 };
1027 Ok(req::Runnable { 1034 Ok(lsp_ext::Runnable {
1028 range: runnable.range.conv_with(&line_index), 1035 range: to_proto::range(&line_index, runnable.range),
1029 label, 1036 label,
1030 bin: "cargo".to_string(), 1037 bin: "cargo".to_string(),
1031 args, 1038 args,
@@ -1044,13 +1051,13 @@ pub fn handle_inlay_hints(
1044 params: InlayHintsParams, 1051 params: InlayHintsParams,
1045) -> Result<Vec<InlayHint>> { 1052) -> Result<Vec<InlayHint>> {
1046 let _p = profile("handle_inlay_hints"); 1053 let _p = profile("handle_inlay_hints");
1047 let file_id = params.text_document.try_conv_with(&world)?; 1054 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
1048 let analysis = world.analysis(); 1055 let analysis = world.analysis();
1049 let line_index = analysis.file_line_index(file_id)?; 1056 let line_index = analysis.file_line_index(file_id)?;
1050 Ok(analysis 1057 Ok(analysis
1051 .inlay_hints(file_id, &world.config.inlay_hints)? 1058 .inlay_hints(file_id, &world.config.inlay_hints)?
1052 .into_iter() 1059 .into_iter()
1053 .map_conv_with(&line_index) 1060 .map(|it| to_proto::inlay_int(&line_index, it))
1054 .collect()) 1061 .collect())
1055} 1062}
1056 1063
@@ -1059,21 +1066,19 @@ pub fn handle_call_hierarchy_prepare(
1059 params: CallHierarchyPrepareParams, 1066 params: CallHierarchyPrepareParams,
1060) -> Result<Option<Vec<CallHierarchyItem>>> { 1067) -> Result<Option<Vec<CallHierarchyItem>>> {
1061 let _p = profile("handle_call_hierarchy_prepare"); 1068 let _p = profile("handle_call_hierarchy_prepare");
1062 let position = params.text_document_position_params.try_conv_with(&world)?; 1069 let position = from_proto::file_position(&world, params.text_document_position_params)?;
1063 let file_id = position.file_id;
1064 1070
1065 let nav_info = match world.analysis().call_hierarchy(position)? { 1071 let nav_info = match world.analysis().call_hierarchy(position)? {
1066 None => return Ok(None), 1072 None => return Ok(None),
1067 Some(it) => it, 1073 Some(it) => it,
1068 }; 1074 };
1069 1075
1070 let line_index = world.analysis().file_line_index(file_id)?; 1076 let RangeInfo { range: _, info: navs } = nav_info;
1071 let RangeInfo { range, info: navs } = nav_info;
1072 let res = navs 1077 let res = navs
1073 .into_iter() 1078 .into_iter()
1074 .filter(|it| it.kind() == SyntaxKind::FN_DEF) 1079 .filter(|it| it.kind() == SyntaxKind::FN_DEF)
1075 .filter_map(|it| to_call_hierarchy_item(file_id, range, &world, &line_index, it).ok()) 1080 .map(|it| to_proto::call_hierarchy_item(&world, it))
1076 .collect(); 1081 .collect::<Result<Vec<_>>>()?;
1077 1082
1078 Ok(Some(res)) 1083 Ok(Some(res))
1079} 1084}
@@ -1086,7 +1091,7 @@ pub fn handle_call_hierarchy_incoming(
1086 let item = params.item; 1091 let item = params.item;
1087 1092
1088 let doc = TextDocumentIdentifier::new(item.uri); 1093 let doc = TextDocumentIdentifier::new(item.uri);
1089 let frange: FileRange = (&doc, item.range).try_conv_with(&world)?; 1094 let frange = from_proto::file_range(&world, doc, item.range)?;
1090 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; 1095 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
1091 1096
1092 let call_items = match world.analysis().incoming_calls(fpos)? { 1097 let call_items = match world.analysis().incoming_calls(fpos)? {
@@ -1099,11 +1104,14 @@ pub fn handle_call_hierarchy_incoming(
1099 for call_item in call_items.into_iter() { 1104 for call_item in call_items.into_iter() {
1100 let file_id = call_item.target.file_id(); 1105 let file_id = call_item.target.file_id();
1101 let line_index = world.analysis().file_line_index(file_id)?; 1106 let line_index = world.analysis().file_line_index(file_id)?;
1102 let range = call_item.target.range(); 1107 let item = to_proto::call_hierarchy_item(&world, call_item.target)?;
1103 let item = to_call_hierarchy_item(file_id, range, &world, &line_index, call_item.target)?;
1104 res.push(CallHierarchyIncomingCall { 1108 res.push(CallHierarchyIncomingCall {
1105 from: item, 1109 from: item,
1106 from_ranges: call_item.ranges.iter().map(|it| it.conv_with(&line_index)).collect(), 1110 from_ranges: call_item
1111 .ranges
1112 .into_iter()
1113 .map(|it| to_proto::range(&line_index, it))
1114 .collect(),
1107 }); 1115 });
1108 } 1116 }
1109 1117
@@ -1118,7 +1126,7 @@ pub fn handle_call_hierarchy_outgoing(
1118 let item = params.item; 1126 let item = params.item;
1119 1127
1120 let doc = TextDocumentIdentifier::new(item.uri); 1128 let doc = TextDocumentIdentifier::new(item.uri);
1121 let frange: FileRange = (&doc, item.range).try_conv_with(&world)?; 1129 let frange = from_proto::file_range(&world, doc, item.range)?;
1122 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; 1130 let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
1123 1131
1124 let call_items = match world.analysis().outgoing_calls(fpos)? { 1132 let call_items = match world.analysis().outgoing_calls(fpos)? {
@@ -1131,11 +1139,14 @@ pub fn handle_call_hierarchy_outgoing(
1131 for call_item in call_items.into_iter() { 1139 for call_item in call_items.into_iter() {
1132 let file_id = call_item.target.file_id(); 1140 let file_id = call_item.target.file_id();
1133 let line_index = world.analysis().file_line_index(file_id)?; 1141 let line_index = world.analysis().file_line_index(file_id)?;
1134 let range = call_item.target.range(); 1142 let item = to_proto::call_hierarchy_item(&world, call_item.target)?;
1135 let item = to_call_hierarchy_item(file_id, range, &world, &line_index, call_item.target)?;
1136 res.push(CallHierarchyOutgoingCall { 1143 res.push(CallHierarchyOutgoingCall {
1137 to: item, 1144 to: item,
1138 from_ranges: call_item.ranges.iter().map(|it| it.conv_with(&line_index)).collect(), 1145 from_ranges: call_item
1146 .ranges
1147 .into_iter()
1148 .map(|it| to_proto::range(&line_index, it))
1149 .collect(),
1139 }); 1150 });
1140 } 1151 }
1141 1152
@@ -1148,26 +1159,13 @@ pub fn handle_semantic_tokens(
1148) -> Result<Option<SemanticTokensResult>> { 1159) -> Result<Option<SemanticTokensResult>> {
1149 let _p = profile("handle_semantic_tokens"); 1160 let _p = profile("handle_semantic_tokens");
1150 1161
1151 let file_id = params.text_document.try_conv_with(&world)?; 1162 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
1152 let text = world.analysis().file_text(file_id)?; 1163 let text = world.analysis().file_text(file_id)?;
1153 let line_index = world.analysis().file_line_index(file_id)?; 1164 let line_index = world.analysis().file_line_index(file_id)?;
1154 1165
1155 let mut builder = SemanticTokensBuilder::default(); 1166 let highlights = world.analysis().highlight(file_id)?;
1156 1167 let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
1157 for highlight_range in world.analysis().highlight(file_id)?.into_iter() { 1168 Ok(Some(semantic_tokens.into()))
1158 let (token_index, modifier_bitset) = highlight_range.highlight.conv();
1159 for mut range in line_index.lines(highlight_range.range) {
1160 if text[range].ends_with('\n') {
1161 range = TextRange::new(range.start(), range.end() - TextSize::of('\n'));
1162 }
1163 let range = range.conv_with(&line_index);
1164 builder.push(range, token_index, modifier_bitset);
1165 }
1166 }
1167
1168 let tokens = builder.build();
1169
1170 Ok(Some(tokens.into()))
1171} 1169}
1172 1170
1173pub fn handle_semantic_tokens_range( 1171pub fn handle_semantic_tokens_range(
@@ -1176,17 +1174,11 @@ pub fn handle_semantic_tokens_range(
1176) -> Result<Option<SemanticTokensRangeResult>> { 1174) -> Result<Option<SemanticTokensRangeResult>> {
1177 let _p = profile("handle_semantic_tokens_range"); 1175 let _p = profile("handle_semantic_tokens_range");
1178 1176
1179 let frange = (&params.text_document, params.range).try_conv_with(&world)?; 1177 let frange = from_proto::file_range(&world, params.text_document, params.range)?;
1178 let text = world.analysis().file_text(frange.file_id)?;
1180 let line_index = world.analysis().file_line_index(frange.file_id)?; 1179 let line_index = world.analysis().file_line_index(frange.file_id)?;
1181 1180
1182 let mut builder = SemanticTokensBuilder::default(); 1181 let highlights = world.analysis().highlight_range(frange)?;
1183 1182 let semantic_tokens = to_proto::semantic_tokens(&text, &line_index, highlights);
1184 for highlight_range in world.analysis().highlight_range(frange)?.into_iter() { 1183 Ok(Some(semantic_tokens.into()))
1185 let (token_type, token_modifiers) = highlight_range.highlight.conv();
1186 builder.push(highlight_range.range.conv_with(&line_index), token_type, token_modifiers);
1187 }
1188
1189 let tokens = builder.build();
1190
1191 Ok(Some(tokens.into()))
1192} 1184}
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
new file mode 100644
index 000000000..f6f4bb134
--- /dev/null
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -0,0 +1,614 @@
1//! Conversion of rust-analyzer specific types to lsp_types equivalents.
2use ra_db::{FileId, FileRange};
3use ra_ide::{
4 Assist, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, FoldKind,
5 FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, Indel,
6 InlayHint, InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess, Severity,
7 SourceChange, SourceFileEdit, TextEdit,
8};
9use ra_syntax::{SyntaxKind, TextRange, TextSize};
10use ra_vfs::LineEndings;
11
12use crate::{lsp_ext, semantic_tokens, world::WorldSnapshot, Result};
13
14pub(crate) fn position(line_index: &LineIndex, offset: TextSize) -> lsp_types::Position {
15 let line_col = line_index.line_col(offset);
16 let line = u64::from(line_col.line);
17 let character = u64::from(line_col.col_utf16);
18 lsp_types::Position::new(line, character)
19}
20
21pub(crate) fn range(line_index: &LineIndex, range: TextRange) -> lsp_types::Range {
22 let start = position(line_index, range.start());
23 let end = position(line_index, range.end());
24 lsp_types::Range::new(start, end)
25}
26
27pub(crate) fn symbol_kind(syntax_kind: SyntaxKind) -> lsp_types::SymbolKind {
28 match syntax_kind {
29 SyntaxKind::FN_DEF => lsp_types::SymbolKind::Function,
30 SyntaxKind::STRUCT_DEF => lsp_types::SymbolKind::Struct,
31 SyntaxKind::ENUM_DEF => lsp_types::SymbolKind::Enum,
32 SyntaxKind::ENUM_VARIANT => lsp_types::SymbolKind::EnumMember,
33 SyntaxKind::TRAIT_DEF => lsp_types::SymbolKind::Interface,
34 SyntaxKind::MACRO_CALL => lsp_types::SymbolKind::Function,
35 SyntaxKind::MODULE => lsp_types::SymbolKind::Module,
36 SyntaxKind::TYPE_ALIAS_DEF => lsp_types::SymbolKind::TypeParameter,
37 SyntaxKind::RECORD_FIELD_DEF => lsp_types::SymbolKind::Field,
38 SyntaxKind::STATIC_DEF => lsp_types::SymbolKind::Constant,
39 SyntaxKind::CONST_DEF => lsp_types::SymbolKind::Constant,
40 SyntaxKind::IMPL_DEF => lsp_types::SymbolKind::Object,
41 _ => lsp_types::SymbolKind::Variable,
42 }
43}
44
45pub(crate) fn document_highlight_kind(
46 reference_access: ReferenceAccess,
47) -> lsp_types::DocumentHighlightKind {
48 match reference_access {
49 ReferenceAccess::Read => lsp_types::DocumentHighlightKind::Read,
50 ReferenceAccess::Write => lsp_types::DocumentHighlightKind::Write,
51 }
52}
53
54pub(crate) fn diagnostic_severity(severity: Severity) -> lsp_types::DiagnosticSeverity {
55 match severity {
56 Severity::Error => lsp_types::DiagnosticSeverity::Error,
57 Severity::WeakWarning => lsp_types::DiagnosticSeverity::Hint,
58 }
59}
60
61pub(crate) fn documentation(documentation: Documentation) -> lsp_types::Documentation {
62 let value = crate::markdown::format_docs(documentation.as_str());
63 let markup_content = lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value };
64 lsp_types::Documentation::MarkupContent(markup_content)
65}
66
67pub(crate) fn insert_text_format(
68 insert_text_format: InsertTextFormat,
69) -> lsp_types::InsertTextFormat {
70 match insert_text_format {
71 InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet,
72 InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText,
73 }
74}
75
76pub(crate) fn completion_item_kind(
77 completion_item_kind: CompletionItemKind,
78) -> lsp_types::CompletionItemKind {
79 match completion_item_kind {
80 CompletionItemKind::Keyword => lsp_types::CompletionItemKind::Keyword,
81 CompletionItemKind::Snippet => lsp_types::CompletionItemKind::Snippet,
82 CompletionItemKind::Module => lsp_types::CompletionItemKind::Module,
83 CompletionItemKind::Function => lsp_types::CompletionItemKind::Function,
84 CompletionItemKind::Struct => lsp_types::CompletionItemKind::Struct,
85 CompletionItemKind::Enum => lsp_types::CompletionItemKind::Enum,
86 CompletionItemKind::EnumVariant => lsp_types::CompletionItemKind::EnumMember,
87 CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::Struct,
88 CompletionItemKind::Binding => lsp_types::CompletionItemKind::Variable,
89 CompletionItemKind::Field => lsp_types::CompletionItemKind::Field,
90 CompletionItemKind::Trait => lsp_types::CompletionItemKind::Interface,
91 CompletionItemKind::TypeAlias => lsp_types::CompletionItemKind::Struct,
92 CompletionItemKind::Const => lsp_types::CompletionItemKind::Constant,
93 CompletionItemKind::Static => lsp_types::CompletionItemKind::Value,
94 CompletionItemKind::Method => lsp_types::CompletionItemKind::Method,
95 CompletionItemKind::TypeParam => lsp_types::CompletionItemKind::TypeParameter,
96 CompletionItemKind::Macro => lsp_types::CompletionItemKind::Method,
97 CompletionItemKind::Attribute => lsp_types::CompletionItemKind::EnumMember,
98 }
99}
100
101pub(crate) fn text_edit(
102 line_index: &LineIndex,
103 line_endings: LineEndings,
104 indel: Indel,
105) -> lsp_types::TextEdit {
106 let range = range(line_index, indel.delete);
107 let new_text = match line_endings {
108 LineEndings::Unix => indel.insert,
109 LineEndings::Dos => indel.insert.replace('\n', "\r\n"),
110 };
111 lsp_types::TextEdit { range, new_text }
112}
113
114pub(crate) fn snippet_text_edit(
115 line_index: &LineIndex,
116 line_endings: LineEndings,
117 is_snippet: bool,
118 indel: Indel,
119) -> lsp_ext::SnippetTextEdit {
120 let text_edit = text_edit(line_index, line_endings, indel);
121 let insert_text_format =
122 if is_snippet { Some(lsp_types::InsertTextFormat::Snippet) } else { None };
123 lsp_ext::SnippetTextEdit {
124 range: text_edit.range,
125 new_text: text_edit.new_text,
126 insert_text_format,
127 }
128}
129
130pub(crate) fn text_edit_vec(
131 line_index: &LineIndex,
132 line_endings: LineEndings,
133 text_edit: TextEdit,
134) -> Vec<lsp_types::TextEdit> {
135 text_edit.into_iter().map(|indel| self::text_edit(line_index, line_endings, indel)).collect()
136}
137
138pub(crate) fn completion_item(
139 line_index: &LineIndex,
140 line_endings: LineEndings,
141 completion_item: CompletionItem,
142) -> lsp_types::CompletionItem {
143 let mut additional_text_edits = Vec::new();
144 let mut text_edit = None;
145 // LSP does not allow arbitrary edits in completion, so we have to do a
146 // non-trivial mapping here.
147 let source_range = completion_item.source_range();
148 for indel in completion_item.text_edit().iter() {
149 if indel.delete.contains_range(source_range) {
150 text_edit = Some(if indel.delete == source_range {
151 self::text_edit(line_index, line_endings, indel.clone())
152 } else {
153 assert!(source_range.end() == indel.delete.end());
154 let range1 = TextRange::new(indel.delete.start(), source_range.start());
155 let range2 = source_range;
156 let indel1 = Indel::replace(range1, String::new());
157 let indel2 = Indel::replace(range2, indel.insert.clone());
158 additional_text_edits.push(self::text_edit(line_index, line_endings, indel1));
159 self::text_edit(line_index, line_endings, indel2)
160 })
161 } else {
162 assert!(source_range.intersect(indel.delete).is_none());
163 let text_edit = self::text_edit(line_index, line_endings, indel.clone());
164 additional_text_edits.push(text_edit);
165 }
166 }
167 let text_edit = text_edit.unwrap();
168
169 let mut res = lsp_types::CompletionItem {
170 label: completion_item.label().to_string(),
171 detail: completion_item.detail().map(|it| it.to_string()),
172 filter_text: Some(completion_item.lookup().to_string()),
173 kind: completion_item.kind().map(completion_item_kind),
174 text_edit: Some(text_edit.into()),
175 additional_text_edits: Some(additional_text_edits),
176 documentation: completion_item.documentation().map(documentation),
177 deprecated: Some(completion_item.deprecated()),
178 ..Default::default()
179 };
180
181 if completion_item.score().is_some() {
182 res.preselect = Some(true);
183 // HACK: sort preselect items first
184 res.sort_text = Some(format!(" {}", completion_item.label()));
185 }
186
187 if completion_item.deprecated() {
188 res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated])
189 }
190
191 if completion_item.trigger_call_info() {
192 res.command = Some(lsp_types::Command {
193 title: "triggerParameterHints".into(),
194 command: "editor.action.triggerParameterHints".into(),
195 arguments: None,
196 });
197 }
198
199 res.insert_text_format = Some(insert_text_format(completion_item.insert_text_format()));
200
201 res
202}
203
204pub(crate) fn signature_information(
205 signature: FunctionSignature,
206 concise: bool,
207) -> lsp_types::SignatureInformation {
208 let (label, documentation, params) = if concise {
209 let mut params = signature.parameters;
210 if signature.has_self_param {
211 params.remove(0);
212 }
213 (params.join(", "), None, params)
214 } else {
215 (signature.to_string(), signature.doc.map(documentation), signature.parameters)
216 };
217
218 let parameters: Vec<lsp_types::ParameterInformation> = params
219 .into_iter()
220 .map(|param| lsp_types::ParameterInformation {
221 label: lsp_types::ParameterLabel::Simple(param),
222 documentation: None,
223 })
224 .collect();
225
226 lsp_types::SignatureInformation { label, documentation, parameters: Some(parameters) }
227}
228
229pub(crate) fn inlay_int(line_index: &LineIndex, inlay_hint: InlayHint) -> lsp_ext::InlayHint {
230 lsp_ext::InlayHint {
231 label: inlay_hint.label.to_string(),
232 range: range(line_index, inlay_hint.range),
233 kind: match inlay_hint.kind {
234 InlayKind::ParameterHint => lsp_ext::InlayKind::ParameterHint,
235 InlayKind::TypeHint => lsp_ext::InlayKind::TypeHint,
236 InlayKind::ChainingHint => lsp_ext::InlayKind::ChainingHint,
237 },
238 }
239}
240
241pub(crate) fn semantic_tokens(
242 text: &str,
243 line_index: &LineIndex,
244 highlights: Vec<HighlightedRange>,
245) -> lsp_types::SemanticTokens {
246 let mut builder = semantic_tokens::SemanticTokensBuilder::default();
247
248 for highlight_range in highlights {
249 let (type_, mods) = semantic_token_type_and_modifiers(highlight_range.highlight);
250 let token_index = semantic_tokens::type_index(type_);
251 let modifier_bitset = mods.0;
252
253 for mut text_range in line_index.lines(highlight_range.range) {
254 if text[text_range].ends_with('\n') {
255 text_range =
256 TextRange::new(text_range.start(), text_range.end() - TextSize::of('\n'));
257 }
258 let range = range(&line_index, text_range);
259 builder.push(range, token_index, modifier_bitset);
260 }
261 }
262
263 builder.build()
264}
265
266fn semantic_token_type_and_modifiers(
267 highlight: Highlight,
268) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) {
269 let mut mods = semantic_tokens::ModifierSet::default();
270 let type_ = match highlight.tag {
271 HighlightTag::Struct => lsp_types::SemanticTokenType::STRUCT,
272 HighlightTag::Enum => lsp_types::SemanticTokenType::ENUM,
273 HighlightTag::Union => semantic_tokens::UNION,
274 HighlightTag::TypeAlias => semantic_tokens::TYPE_ALIAS,
275 HighlightTag::Trait => lsp_types::SemanticTokenType::INTERFACE,
276 HighlightTag::BuiltinType => semantic_tokens::BUILTIN_TYPE,
277 HighlightTag::SelfType => lsp_types::SemanticTokenType::TYPE,
278 HighlightTag::Field => lsp_types::SemanticTokenType::PROPERTY,
279 HighlightTag::Function => lsp_types::SemanticTokenType::FUNCTION,
280 HighlightTag::Module => lsp_types::SemanticTokenType::NAMESPACE,
281 HighlightTag::Constant => {
282 mods |= semantic_tokens::CONSTANT;
283 mods |= lsp_types::SemanticTokenModifier::STATIC;
284 lsp_types::SemanticTokenType::VARIABLE
285 }
286 HighlightTag::Static => {
287 mods |= lsp_types::SemanticTokenModifier::STATIC;
288 lsp_types::SemanticTokenType::VARIABLE
289 }
290 HighlightTag::EnumVariant => semantic_tokens::ENUM_MEMBER,
291 HighlightTag::Macro => lsp_types::SemanticTokenType::MACRO,
292 HighlightTag::Local => lsp_types::SemanticTokenType::VARIABLE,
293 HighlightTag::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
294 HighlightTag::Lifetime => semantic_tokens::LIFETIME,
295 HighlightTag::ByteLiteral | HighlightTag::NumericLiteral => {
296 lsp_types::SemanticTokenType::NUMBER
297 }
298 HighlightTag::CharLiteral | HighlightTag::StringLiteral => {
299 lsp_types::SemanticTokenType::STRING
300 }
301 HighlightTag::Comment => lsp_types::SemanticTokenType::COMMENT,
302 HighlightTag::Attribute => semantic_tokens::ATTRIBUTE,
303 HighlightTag::Keyword => lsp_types::SemanticTokenType::KEYWORD,
304 HighlightTag::UnresolvedReference => semantic_tokens::UNRESOLVED_REFERENCE,
305 HighlightTag::FormatSpecifier => semantic_tokens::FORMAT_SPECIFIER,
306 };
307
308 for modifier in highlight.modifiers.iter() {
309 let modifier = match modifier {
310 HighlightModifier::Definition => lsp_types::SemanticTokenModifier::DECLARATION,
311 HighlightModifier::ControlFlow => semantic_tokens::CONTROL_FLOW,
312 HighlightModifier::Mutable => semantic_tokens::MUTABLE,
313 HighlightModifier::Unsafe => semantic_tokens::UNSAFE,
314 };
315 mods |= modifier;
316 }
317
318 (type_, mods)
319}
320
321pub(crate) fn folding_range(
322 text: &str,
323 line_index: &LineIndex,
324 line_folding_only: bool,
325 fold: Fold,
326) -> lsp_types::FoldingRange {
327 let kind = match fold.kind {
328 FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
329 FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
330 FoldKind::Mods | FoldKind::Block => None,
331 };
332
333 let range = range(line_index, fold.range);
334
335 if line_folding_only {
336 // Clients with line_folding_only == true (such as VSCode) will fold the whole end line
337 // even if it contains text not in the folding range. To prevent that we exclude
338 // range.end.line from the folding region if there is more text after range.end
339 // on the same line.
340 let has_more_text_on_end_line = text[TextRange::new(fold.range.end(), TextSize::of(text))]
341 .chars()
342 .take_while(|it| *it != '\n')
343 .any(|it| !it.is_whitespace());
344
345 let end_line = if has_more_text_on_end_line {
346 range.end.line.saturating_sub(1)
347 } else {
348 range.end.line
349 };
350
351 lsp_types::FoldingRange {
352 start_line: range.start.line,
353 start_character: None,
354 end_line,
355 end_character: None,
356 kind,
357 }
358 } else {
359 lsp_types::FoldingRange {
360 start_line: range.start.line,
361 start_character: Some(range.start.character),
362 end_line: range.end.line,
363 end_character: Some(range.end.character),
364 kind,
365 }
366 }
367}
368
369pub(crate) fn url(world: &WorldSnapshot, file_id: FileId) -> Result<lsp_types::Url> {
370 world.file_id_to_uri(file_id)
371}
372
373pub(crate) fn versioned_text_document_identifier(
374 world: &WorldSnapshot,
375 file_id: FileId,
376 version: Option<i64>,
377) -> Result<lsp_types::VersionedTextDocumentIdentifier> {
378 let res = lsp_types::VersionedTextDocumentIdentifier { uri: url(world, file_id)?, version };
379 Ok(res)
380}
381
382pub(crate) fn location(world: &WorldSnapshot, frange: FileRange) -> Result<lsp_types::Location> {
383 let url = url(world, frange.file_id)?;
384 let line_index = world.analysis().file_line_index(frange.file_id)?;
385 let range = range(&line_index, frange.range);
386 let loc = lsp_types::Location::new(url, range);
387 Ok(loc)
388}
389
390pub(crate) fn location_link(
391 world: &WorldSnapshot,
392 src: FileRange,
393 target: NavigationTarget,
394) -> Result<lsp_types::LocationLink> {
395 let src_location = location(world, src)?;
396 let (target_uri, target_range, target_selection_range) = location_info(world, target)?;
397 let res = lsp_types::LocationLink {
398 origin_selection_range: Some(src_location.range),
399 target_uri,
400 target_range,
401 target_selection_range,
402 };
403 Ok(res)
404}
405
406fn location_info(
407 world: &WorldSnapshot,
408 target: NavigationTarget,
409) -> Result<(lsp_types::Url, lsp_types::Range, lsp_types::Range)> {
410 let line_index = world.analysis().file_line_index(target.file_id())?;
411
412 let target_uri = url(world, target.file_id())?;
413 let target_range = range(&line_index, target.full_range());
414 let target_selection_range =
415 target.focus_range().map(|it| range(&line_index, it)).unwrap_or(target_range);
416 Ok((target_uri, target_range, target_selection_range))
417}
418
419pub(crate) fn goto_definition_response(
420 world: &WorldSnapshot,
421 src: FileRange,
422 targets: Vec<NavigationTarget>,
423) -> Result<lsp_types::GotoDefinitionResponse> {
424 if world.config.client_caps.location_link {
425 let links = targets
426 .into_iter()
427 .map(|nav| location_link(world, src, nav))
428 .collect::<Result<Vec<_>>>()?;
429 Ok(links.into())
430 } else {
431 let locations = targets
432 .into_iter()
433 .map(|nav| {
434 location(
435 world,
436 FileRange {
437 file_id: nav.file_id(),
438 range: nav.focus_range().unwrap_or(nav.range()),
439 },
440 )
441 })
442 .collect::<Result<Vec<_>>>()?;
443 Ok(locations.into())
444 }
445}
446
447pub(crate) fn snippet_text_document_edit(
448 world: &WorldSnapshot,
449 is_snippet: bool,
450 source_file_edit: SourceFileEdit,
451) -> Result<lsp_ext::SnippetTextDocumentEdit> {
452 let text_document = versioned_text_document_identifier(world, source_file_edit.file_id, None)?;
453 let line_index = world.analysis().file_line_index(source_file_edit.file_id)?;
454 let line_endings = world.file_line_endings(source_file_edit.file_id);
455 let edits = source_file_edit
456 .edit
457 .into_iter()
458 .map(|it| snippet_text_edit(&line_index, line_endings, is_snippet, it.clone()))
459 .collect();
460 Ok(lsp_ext::SnippetTextDocumentEdit { text_document, edits })
461}
462
463pub(crate) fn resource_op(
464 world: &WorldSnapshot,
465 file_system_edit: FileSystemEdit,
466) -> Result<lsp_types::ResourceOp> {
467 let res = match file_system_edit {
468 FileSystemEdit::CreateFile { source_root, path } => {
469 let uri = world.path_to_uri(source_root, &path)?;
470 lsp_types::ResourceOp::Create(lsp_types::CreateFile { uri, options: None })
471 }
472 FileSystemEdit::MoveFile { src, dst_source_root, dst_path } => {
473 let old_uri = world.file_id_to_uri(src)?;
474 let new_uri = world.path_to_uri(dst_source_root, &dst_path)?;
475 lsp_types::ResourceOp::Rename(lsp_types::RenameFile { old_uri, new_uri, options: None })
476 }
477 };
478 Ok(res)
479}
480
481pub(crate) fn source_change(
482 world: &WorldSnapshot,
483 source_change: SourceChange,
484) -> Result<lsp_ext::SourceChange> {
485 let label = source_change.label.clone();
486 let workspace_edit = self::snippet_workspace_edit(world, source_change)?;
487 Ok(lsp_ext::SourceChange { label, workspace_edit, cursor_position: None })
488}
489
490pub(crate) fn snippet_workspace_edit(
491 world: &WorldSnapshot,
492 source_change: SourceChange,
493) -> Result<lsp_ext::SnippetWorkspaceEdit> {
494 let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
495 for op in source_change.file_system_edits {
496 let op = resource_op(&world, op)?;
497 document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Op(op));
498 }
499 for edit in source_change.source_file_edits {
500 let edit = snippet_text_document_edit(&world, source_change.is_snippet, edit)?;
501 document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit));
502 }
503 let workspace_edit =
504 lsp_ext::SnippetWorkspaceEdit { changes: None, document_changes: Some(document_changes) };
505 Ok(workspace_edit)
506}
507
508pub(crate) fn workspace_edit(
509 world: &WorldSnapshot,
510 source_change: SourceChange,
511) -> Result<lsp_types::WorkspaceEdit> {
512 assert!(!source_change.is_snippet);
513 snippet_workspace_edit(world, source_change).map(|it| it.into())
514}
515
516impl From<lsp_ext::SnippetWorkspaceEdit> for lsp_types::WorkspaceEdit {
517 fn from(snippet_workspace_edit: lsp_ext::SnippetWorkspaceEdit) -> lsp_types::WorkspaceEdit {
518 lsp_types::WorkspaceEdit {
519 changes: None,
520 document_changes: snippet_workspace_edit.document_changes.map(|changes| {
521 lsp_types::DocumentChanges::Operations(
522 changes
523 .into_iter()
524 .map(|change| match change {
525 lsp_ext::SnippetDocumentChangeOperation::Op(op) => {
526 lsp_types::DocumentChangeOperation::Op(op)
527 }
528 lsp_ext::SnippetDocumentChangeOperation::Edit(edit) => {
529 lsp_types::DocumentChangeOperation::Edit(
530 lsp_types::TextDocumentEdit {
531 text_document: edit.text_document,
532 edits: edit
533 .edits
534 .into_iter()
535 .map(|edit| lsp_types::TextEdit {
536 range: edit.range,
537 new_text: edit.new_text,
538 })
539 .collect(),
540 },
541 )
542 }
543 })
544 .collect(),
545 )
546 }),
547 }
548 }
549}
550
551pub fn call_hierarchy_item(
552 world: &WorldSnapshot,
553 target: NavigationTarget,
554) -> Result<lsp_types::CallHierarchyItem> {
555 let name = target.name().to_string();
556 let detail = target.description().map(|it| it.to_string());
557 let kind = symbol_kind(target.kind());
558 let (uri, range, selection_range) = location_info(world, target)?;
559 Ok(lsp_types::CallHierarchyItem { name, kind, tags: None, detail, uri, range, selection_range })
560}
561
562#[cfg(test)]
563mod tests {
564 use test_utils::extract_ranges;
565
566 use super::*;
567
568 #[test]
569 fn conv_fold_line_folding_only_fixup() {
570 let text = r#"<fold>mod a;
571mod b;
572mod c;</fold>
573
574fn main() <fold>{
575 if cond <fold>{
576 a::do_a();
577 }</fold> else <fold>{
578 b::do_b();
579 }</fold>
580}</fold>"#;
581
582 let (ranges, text) = extract_ranges(text, "fold");
583 assert_eq!(ranges.len(), 4);
584 let folds = vec![
585 Fold { range: ranges[0], kind: FoldKind::Mods },
586 Fold { range: ranges[1], kind: FoldKind::Block },
587 Fold { range: ranges[2], kind: FoldKind::Block },
588 Fold { range: ranges[3], kind: FoldKind::Block },
589 ];
590
591 let line_index = LineIndex::new(&text);
592 let converted: Vec<lsp_types::FoldingRange> =
593 folds.into_iter().map(|it| folding_range(&text, &line_index, true, it)).collect();
594
595 let expected_lines = [(0, 2), (4, 10), (5, 6), (7, 9)];
596 assert_eq!(converted.len(), expected_lines.len());
597 for (folding_range, (start_line, end_line)) in converted.iter().zip(expected_lines.iter()) {
598 assert_eq!(folding_range.start_line, *start_line);
599 assert_eq!(folding_range.start_character, None);
600 assert_eq!(folding_range.end_line, *end_line);
601 assert_eq!(folding_range.end_character, None);
602 }
603 }
604}
605
606pub(crate) fn code_action(world: &WorldSnapshot, assist: Assist) -> Result<lsp_ext::CodeAction> {
607 let res = lsp_ext::CodeAction {
608 title: assist.label,
609 kind: Some(String::new()),
610 edit: Some(snippet_workspace_edit(world, assist.source_change)?),
611 command: None,
612 };
613 Ok(res)
614}
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index 34941931b..367272925 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -11,7 +11,7 @@ use std::{
11use crossbeam_channel::{unbounded, Receiver}; 11use crossbeam_channel::{unbounded, Receiver};
12use lsp_types::Url; 12use lsp_types::Url;
13use parking_lot::RwLock; 13use parking_lot::RwLock;
14use ra_flycheck::{url_from_path_with_drive_lowercasing, Flycheck, FlycheckConfig}; 14use ra_flycheck::{Flycheck, FlycheckConfig};
15use ra_ide::{ 15use ra_ide::{
16 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, 16 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
17}; 17};
@@ -22,7 +22,9 @@ use stdx::format_to;
22 22
23use crate::{ 23use crate::{
24 config::Config, 24 config::Config,
25 diagnostics::{CheckFixes, DiagnosticCollection}, 25 diagnostics::{
26 to_proto::url_from_path_with_drive_lowercasing, CheckFixes, DiagnosticCollection,
27 },
26 main_loop::pending_requests::{CompletedRequest, LatestRequests}, 28 main_loop::pending_requests::{CompletedRequest, LatestRequests},
27 vfs_glob::{Glob, RustPackageFilterBuilder}, 29 vfs_glob::{Glob, RustPackageFilterBuilder},
28 LspError, Result, 30 LspError, Result,
@@ -131,21 +133,12 @@ impl WorldState {
131 133
132 // FIXME: Read default cfgs from config 134 // FIXME: Read default cfgs from config
133 let default_cfg_options = { 135 let default_cfg_options = {
134 let mut opts = get_rustc_cfg_options(); 136 let mut opts = get_rustc_cfg_options(config.cargo.target.as_ref());
135 opts.insert_atom("test".into()); 137 opts.insert_atom("test".into());
136 opts.insert_atom("debug_assertion".into()); 138 opts.insert_atom("debug_assertion".into());
137 opts 139 opts
138 }; 140 };
139 141
140 // Create crate graph from all the workspaces
141 let mut crate_graph = CrateGraph::default();
142 let mut load = |path: &std::path::Path| {
143 // Some path from metadata will be non canonicalized, e.g. /foo/../bar/lib.rs
144 let path = path.canonicalize().ok()?;
145 let vfs_file = vfs.load(&path);
146 vfs_file.map(|f| FileId(f.0))
147 };
148
149 let proc_macro_client = match &config.proc_macro_srv { 142 let proc_macro_client = match &config.proc_macro_srv {
150 None => ProcMacroClient::dummy(), 143 None => ProcMacroClient::dummy(),
151 Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) { 144 Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) {
@@ -161,19 +154,22 @@ impl WorldState {
161 }, 154 },
162 }; 155 };
163 156
164 workspaces 157 // Create crate graph from all the workspaces
165 .iter() 158 let mut crate_graph = CrateGraph::default();
166 .map(|ws| { 159 let mut load = |path: &Path| {
167 ws.to_crate_graph( 160 // Some path from metadata will be non canonicalized, e.g. /foo/../bar/lib.rs
168 &default_cfg_options, 161 let path = path.canonicalize().ok()?;
169 &extern_source_roots, 162 let vfs_file = vfs.load(&path);
170 &proc_macro_client, 163 vfs_file.map(|f| FileId(f.0))
171 &mut load, 164 };
172 ) 165 for ws in workspaces.iter() {
173 }) 166 crate_graph.extend(ws.to_crate_graph(
174 .for_each(|graph| { 167 &default_cfg_options,
175 crate_graph.extend(graph); 168 &extern_source_roots,
176 }); 169 &proc_macro_client,
170 &mut load,
171 ));
172 }
177 change.set_crate_graph(crate_graph); 173 change.set_crate_graph(crate_graph);
178 174
179 let flycheck = config.check.as_ref().and_then(|c| create_flycheck(&workspaces, c)); 175 let flycheck = config.check.as_ref().and_then(|c| create_flycheck(&workspaces, c));
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs
index 07b8114c6..4e94c37e1 100644
--- a/crates/rust-analyzer/tests/heavy_tests/main.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/main.rs
@@ -3,14 +3,16 @@ mod support;
3use std::{collections::HashMap, path::PathBuf, time::Instant}; 3use std::{collections::HashMap, path::PathBuf, time::Instant};
4 4
5use lsp_types::{ 5use lsp_types::{
6 CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, 6 notification::DidOpenTextDocument,
7 GotoDefinitionParams, HoverParams, PartialResultParams, Position, Range, TextDocumentItem, 7 request::{
8 TextDocumentPositionParams, WorkDoneProgressParams, 8 CodeActionRequest, Completion, Formatting, GotoDefinition, GotoTypeDefinition, HoverRequest,
9}; 9 },
10use rust_analyzer::req::{ 10 CodeActionContext, CodeActionParams, CompletionParams, DidOpenTextDocumentParams,
11 CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, 11 DocumentFormattingParams, FormattingOptions, GotoDefinitionParams, HoverParams,
12 Formatting, GotoDefinition, HoverRequest, OnEnter, Runnables, RunnablesParams, 12 PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams,
13 WorkDoneProgressParams,
13}; 14};
15use rust_analyzer::lsp_ext::{OnEnter, Runnables, RunnablesParams};
14use serde_json::json; 16use serde_json::json;
15use tempfile::TempDir; 17use tempfile::TempDir;
16use test_utils::skip_slow_tests; 18use test_utils::skip_slow_tests;
@@ -149,7 +151,7 @@ fn main() {}
149 "cwd": server.path().join("foo") 151 "cwd": server.path().join("foo")
150 }, 152 },
151 { 153 {
152 "args": [ "check", "--package", "foo", "--test", "spam" ], 154 "args": [ "check", "--package", "foo" ],
153 "extraArgs": [], 155 "extraArgs": [],
154 "bin": "cargo", 156 "bin": "cargo",
155 "env": {}, 157 "env": {},
@@ -161,7 +163,7 @@ fn main() {}
161 "cwd": server.path().join("foo") 163 "cwd": server.path().join("foo")
162 }, 164 },
163 { 165 {
164 "args": [ "test", "--package", "foo", "--test", "spam" ], 166 "args": [ "test", "--package", "foo" ],
165 "extraArgs": [], 167 "extraArgs": [],
166 "bin": "cargo", 168 "bin": "cargo",
167 "env": {}, 169 "env": {},
@@ -331,29 +333,17 @@ fn main() {}
331 partial_result_params: PartialResultParams::default(), 333 partial_result_params: PartialResultParams::default(),
332 work_done_progress_params: WorkDoneProgressParams::default(), 334 work_done_progress_params: WorkDoneProgressParams::default(),
333 }, 335 },
334 json!([ 336 json!([{
335 { 337 "edit": {
336 "command": { 338 "documentChanges": [
337 "arguments": [
338 { 339 {
339 "cursorPosition": null, 340 "kind": "create",
340 "label": "create module", 341 "uri": "file:///[..]/src/bar.rs"
341 "workspaceEdit": {
342 "documentChanges": [
343 {
344 "kind": "create",
345 "uri": "file:///[..]/src/bar.rs"
346 }
347 ]
348 }
349 } 342 }
350 ], 343 ]
351 "command": "rust-analyzer.applySourceChange",
352 "title": "create module"
353 }, 344 },
354 "title": "create module" 345 "title": "Create module"
355 } 346 }]),
356 ]),
357 ); 347 );
358 348
359 server.request::<CodeActionRequest>( 349 server.request::<CodeActionRequest>(
@@ -414,29 +404,17 @@ fn main() {{}}
414 partial_result_params: PartialResultParams::default(), 404 partial_result_params: PartialResultParams::default(),
415 work_done_progress_params: WorkDoneProgressParams::default(), 405 work_done_progress_params: WorkDoneProgressParams::default(),
416 }, 406 },
417 json!([ 407 json!([{
418 { 408 "edit": {
419 "command": { 409 "documentChanges": [
420 "arguments": [
421 { 410 {
422 "cursorPosition": null, 411 "kind": "create",
423 "label": "create module", 412 "uri": "file://[..]/src/bar.rs"
424 "workspaceEdit": {
425 "documentChanges": [
426 {
427 "kind": "create",
428 "uri": "file:///[..]/src/bar.rs"
429 }
430 ]
431 }
432 } 413 }
433 ], 414 ]
434 "command": "rust-analyzer.applySourceChange",
435 "title": "create module"
436 }, 415 },
437 "title": "create module" 416 "title": "Create module"
438 } 417 }]),
439 ]),
440 ); 418 );
441 419
442 server.request::<CodeActionRequest>( 420 server.request::<CodeActionRequest>(
@@ -496,27 +474,21 @@ fn main() {{}}
496 position: Position { line: 0, character: 5 }, 474 position: Position { line: 0, character: 5 },
497 }, 475 },
498 json!({ 476 json!({
499 "cursorPosition": { 477 "documentChanges": [
500 "position": { "character": 4, "line": 1 }, 478 {
501 "textDocument": { "uri": "file:///[..]src/m0.rs" } 479 "edits": [
502 }, 480 {
503 "label": "on enter", 481 "insertTextFormat": 2,
504 "workspaceEdit": { 482 "newText": "\n/// $0",
505 "documentChanges": [ 483 "range": {
506 { 484 "end": { "character": 5, "line": 0 },
507 "edits": [ 485 "start": { "character": 5, "line": 0 }
508 {
509 "newText": "\n/// ",
510 "range": {
511 "end": { "character": 5, "line": 0 },
512 "start": { "character": 5, "line": 0 }
513 }
514 } 486 }
515 ], 487 }
516 "textDocument": { "uri": "file:///[..]src/m0.rs", "version": null } 488 ],
517 } 489 "textDocument": { "uri": "file:///[..]src/m0.rs", "version": null }
518 ] 490 }
519 } 491 ]
520 }), 492 }),
521 ); 493 );
522 let elapsed = start.elapsed(); 494 let elapsed = start.elapsed();
@@ -548,33 +520,27 @@ version = \"0.0.0\"
548 position: Position { line: 0, character: 8 }, 520 position: Position { line: 0, character: 8 },
549 }, 521 },
550 json!({ 522 json!({
551 "cursorPosition": { 523 "documentChanges": [
552 "position": { "line": 1, "character": 4 }, 524 {
553 "textDocument": { "uri": "file:///[..]src/main.rs" } 525 "edits": [
554 }, 526 {
555 "label": "on enter", 527 "insertTextFormat": 2,
556 "workspaceEdit": { 528 "newText": "\r\n/// $0",
557 "documentChanges": [ 529 "range": {
558 { 530 "end": { "line": 0, "character": 8 },
559 "edits": [ 531 "start": { "line": 0, "character": 8 }
560 {
561 "newText": "\r\n/// ",
562 "range": {
563 "end": { "line": 0, "character": 8 },
564 "start": { "line": 0, "character": 8 }
565 }
566 } 532 }
567 ], 533 }
568 "textDocument": { "uri": "file:///[..]src/main.rs", "version": null } 534 ],
569 } 535 "textDocument": { "uri": "file:///[..]src/main.rs", "version": null }
570 ] 536 }
571 } 537 ]
572 }), 538 }),
573 ); 539 );
574} 540}
575 541
576#[test] 542#[test]
577fn resolve_include_concat_env() { 543fn out_dirs_check() {
578 if skip_slow_tests() { 544 if skip_slow_tests() {
579 return; 545 return;
580 } 546 }
@@ -597,11 +563,28 @@ fn main() {
597 r#"pub fn message() -> &'static str { "Hello, World!" }"#, 563 r#"pub fn message() -> &'static str { "Hello, World!" }"#,
598 ) 564 )
599 .unwrap(); 565 .unwrap();
566 println!("cargo:rustc-cfg=atom_cfg");
567 println!("cargo:rustc-cfg=featlike=\"set\"");
600 println!("cargo:rerun-if-changed=build.rs"); 568 println!("cargo:rerun-if-changed=build.rs");
601} 569}
602//- src/main.rs 570//- src/main.rs
603include!(concat!(env!("OUT_DIR"), "/hello.rs")); 571include!(concat!(env!("OUT_DIR"), "/hello.rs"));
604 572
573#[cfg(atom_cfg)]
574struct A;
575#[cfg(bad_atom_cfg)]
576struct A;
577#[cfg(featlike = "set")]
578struct B;
579#[cfg(featlike = "not_set")]
580struct B;
581
582fn main() {
583 let va = A;
584 let vb = B;
585 message();
586}
587
605fn main() { message(); } 588fn main() { message(); }
606"###, 589"###,
607 ) 590 )
@@ -613,12 +596,98 @@ fn main() { message(); }
613 let res = server.send_request::<GotoDefinition>(GotoDefinitionParams { 596 let res = server.send_request::<GotoDefinition>(GotoDefinitionParams {
614 text_document_position_params: TextDocumentPositionParams::new( 597 text_document_position_params: TextDocumentPositionParams::new(
615 server.doc_id("src/main.rs"), 598 server.doc_id("src/main.rs"),
616 Position::new(2, 15), 599 Position::new(14, 8),
617 ), 600 ),
618 work_done_progress_params: Default::default(), 601 work_done_progress_params: Default::default(),
619 partial_result_params: Default::default(), 602 partial_result_params: Default::default(),
620 }); 603 });
621 assert!(format!("{}", res).contains("hello.rs")); 604 assert!(format!("{}", res).contains("hello.rs"));
605 server.request::<GotoTypeDefinition>(
606 GotoDefinitionParams {
607 text_document_position_params: TextDocumentPositionParams::new(
608 server.doc_id("src/main.rs"),
609 Position::new(12, 9),
610 ),
611 work_done_progress_params: Default::default(),
612 partial_result_params: Default::default(),
613 },
614 json!([{
615 "originSelectionRange": {
616 "end": {
617 "character": 10,
618 "line": 12
619 },
620 "start": {
621 "character": 8,
622 "line": 12
623 }
624 },
625 "targetRange": {
626 "end": {
627 "character": 9,
628 "line": 3
629 },
630 "start": {
631 "character": 0,
632 "line": 2
633 }
634 },
635 "targetSelectionRange": {
636 "end": {
637 "character": 8,
638 "line": 3
639 },
640 "start": {
641 "character": 7,
642 "line": 3
643 }
644 },
645 "targetUri": "file:///[..]src/main.rs"
646 }]),
647 );
648 server.request::<GotoTypeDefinition>(
649 GotoDefinitionParams {
650 text_document_position_params: TextDocumentPositionParams::new(
651 server.doc_id("src/main.rs"),
652 Position::new(13, 9),
653 ),
654 work_done_progress_params: Default::default(),
655 partial_result_params: Default::default(),
656 },
657 json!([{
658 "originSelectionRange": {
659 "end": {
660 "character": 10,
661 "line": 13
662 },
663 "start": {
664 "character": 8,
665 "line":13
666 }
667 },
668 "targetRange": {
669 "end": {
670 "character": 9,
671 "line": 7
672 },
673 "start": {
674 "character": 0,
675 "line":6
676 }
677 },
678 "targetSelectionRange": {
679 "end": {
680 "character": 8,
681 "line": 7
682 },
683 "start": {
684 "character": 7,
685 "line": 7
686 }
687 },
688 "targetUri": "file:///[..]src/main.rs"
689 }]),
690 );
622} 691}
623 692
624#[test] 693#[test]
diff --git a/crates/rust-analyzer/tests/heavy_tests/support.rs b/crates/rust-analyzer/tests/heavy_tests/support.rs
index 8d47ee4f6..9acbae066 100644
--- a/crates/rust-analyzer/tests/heavy_tests/support.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/support.rs
@@ -13,15 +13,15 @@ use lsp_types::{
13 request::Shutdown, 13 request::Shutdown,
14 DidOpenTextDocumentParams, TextDocumentIdentifier, TextDocumentItem, Url, WorkDoneProgress, 14 DidOpenTextDocumentParams, TextDocumentIdentifier, TextDocumentItem, Url, WorkDoneProgress,
15}; 15};
16use lsp_types::{ProgressParams, ProgressParamsValue};
16use serde::Serialize; 17use serde::Serialize;
17use serde_json::{to_string_pretty, Value}; 18use serde_json::{to_string_pretty, Value};
18use tempfile::TempDir; 19use tempfile::TempDir;
19use test_utils::{find_mismatch, parse_fixture}; 20use test_utils::{find_mismatch, parse_fixture};
20 21
21use req::{ProgressParams, ProgressParamsValue};
22use rust_analyzer::{ 22use rust_analyzer::{
23 config::{ClientCapsConfig, Config}, 23 config::{ClientCapsConfig, Config},
24 main_loop, req, 24 main_loop,
25}; 25};
26 26
27pub struct Project<'a> { 27pub struct Project<'a> {
@@ -80,6 +80,7 @@ impl<'a> Project<'a> {
80 client_caps: ClientCapsConfig { 80 client_caps: ClientCapsConfig {
81 location_link: true, 81 location_link: true,
82 code_action_literals: true, 82 code_action_literals: true,
83 work_done_progress: true,
83 ..Default::default() 84 ..Default::default()
84 }, 85 },
85 with_sysroot: self.with_sysroot, 86 with_sysroot: self.with_sysroot,
@@ -206,7 +207,7 @@ impl Server {
206 Message::Notification(n) if n.method == "$/progress" => { 207 Message::Notification(n) if n.method == "$/progress" => {
207 match n.clone().extract::<ProgressParams>("$/progress").unwrap() { 208 match n.clone().extract::<ProgressParams>("$/progress").unwrap() {
208 ProgressParams { 209 ProgressParams {
209 token: req::ProgressToken::String(ref token), 210 token: lsp_types::ProgressToken::String(ref token),
210 value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(_)), 211 value: ProgressParamsValue::WorkDone(WorkDoneProgress::End(_)),
211 } if token == "rustAnalyzer/startup" => true, 212 } if token == "rustAnalyzer/startup" => true,
212 _ => false, 213 _ => false,
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index 01cdf452c..71a57fba2 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -102,3 +102,25 @@ pub fn timeit(label: &'static str) -> impl Drop {
102 102
103 Guard { label, start: Instant::now() } 103 Guard { label, start: Instant::now() }
104} 104}
105
106pub fn to_lower_snake_case(s: &str) -> String {
107 let mut buf = String::with_capacity(s.len());
108 let mut prev = false;
109 for c in s.chars() {
110 if c.is_ascii_uppercase() && prev {
111 buf.push('_')
112 }
113 prev = true;
114
115 buf.push(c.to_ascii_lowercase());
116 }
117 buf
118}
119
120pub fn replace(buf: &mut String, from: char, to: &str) {
121 if !buf.contains(from) {
122 return;
123 }
124 // FIXME: do this in place.
125 *buf = buf.replace(from, to)
126}
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index b1365444a..be2cfbaa2 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -7,7 +7,7 @@
7//! * marks (see the eponymous module). 7//! * marks (see the eponymous module).
8 8
9#[macro_use] 9#[macro_use]
10pub mod marks; 10pub mod mark;
11 11
12use std::{ 12use std::{
13 fs, 13 fs,
@@ -155,7 +155,7 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
155 res 155 res
156} 156}
157 157
158#[derive(Debug)] 158#[derive(Debug, Eq, PartialEq)]
159pub struct FixtureEntry { 159pub struct FixtureEntry {
160 pub meta: String, 160 pub meta: String,
161 pub text: String, 161 pub text: String,
@@ -170,19 +170,26 @@ pub struct FixtureEntry {
170/// // - other meta 170/// // - other meta
171/// ``` 171/// ```
172pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> { 172pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> {
173 let margin = fixture 173 let fixture = indent_first_line(fixture);
174 .lines() 174 let margin = fixture_margin(&fixture);
175 .filter(|it| it.trim_start().starts_with("//-"))
176 .map(|it| it.len() - it.trim_start().len())
177 .next()
178 .expect("empty fixture");
179 175
180 let mut lines = fixture 176 let mut lines = fixture
181 .split('\n') // don't use `.lines` to not drop `\r\n` 177 .split('\n') // don't use `.lines` to not drop `\r\n`
182 .filter_map(|line| { 178 .enumerate()
179 .filter_map(|(ix, line)| {
183 if line.len() >= margin { 180 if line.len() >= margin {
184 assert!(line[..margin].trim().is_empty()); 181 assert!(line[..margin].trim().is_empty());
185 Some(&line[margin..]) 182 let line_content = &line[margin..];
183 if !line_content.starts_with("//-") {
184 assert!(
185 !line_content.contains("//-"),
186 r#"Metadata line {} has invalid indentation. All metadata lines need to have the same indentation.
187The offending line: {:?}"#,
188 ix,
189 line
190 );
191 }
192 Some(line_content)
186 } else { 193 } else {
187 assert!(line.trim().is_empty()); 194 assert!(line.trim().is_empty());
188 None 195 None
@@ -202,6 +209,85 @@ pub fn parse_fixture(fixture: &str) -> Vec<FixtureEntry> {
202 res 209 res
203} 210}
204 211
212/// Adjusts the indentation of the first line to the minimum indentation of the rest of the lines.
213/// This allows fixtures to start off in a different indentation, e.g. to align the first line with
214/// the other lines visually:
215/// ```
216/// let fixture = "//- /lib.rs
217/// mod foo;
218/// //- /foo.rs
219/// fn bar() {}
220/// ";
221/// assert_eq!(fixture_margin(fixture),
222/// " //- /lib.rs
223/// mod foo;
224/// //- /foo.rs
225/// fn bar() {}
226/// ")
227/// ```
228fn indent_first_line(fixture: &str) -> String {
229 if fixture.is_empty() {
230 return String::new();
231 }
232 let mut lines = fixture.lines();
233 let first_line = lines.next().unwrap();
234 if first_line.contains("//-") {
235 let rest = lines.collect::<Vec<_>>().join("\n");
236 let fixed_margin = fixture_margin(&rest);
237 let fixed_indent = fixed_margin - indent_len(first_line);
238 format!("\n{}{}\n{}", " ".repeat(fixed_indent), first_line, rest)
239 } else {
240 fixture.to_owned()
241 }
242}
243
244fn fixture_margin(fixture: &str) -> usize {
245 fixture
246 .lines()
247 .filter(|it| it.trim_start().starts_with("//-"))
248 .map(indent_len)
249 .next()
250 .expect("empty fixture")
251}
252
253fn indent_len(s: &str) -> usize {
254 s.len() - s.trim_start().len()
255}
256
257#[test]
258#[should_panic]
259fn parse_fixture_checks_further_indented_metadata() {
260 parse_fixture(
261 r"
262 //- /lib.rs
263 mod bar;
264
265 fn foo() {}
266 //- /bar.rs
267 pub fn baz() {}
268 ",
269 );
270}
271
272#[test]
273fn parse_fixture_can_handle_dedented_first_line() {
274 let fixture = "//- /lib.rs
275 mod foo;
276 //- /foo.rs
277 struct Bar;
278";
279 assert_eq!(
280 parse_fixture(fixture),
281 parse_fixture(
282 "//- /lib.rs
283mod foo;
284//- /foo.rs
285struct Bar;
286"
287 )
288 )
289}
290
205/// Same as `parse_fixture`, except it allow empty fixture 291/// Same as `parse_fixture`, except it allow empty fixture
206pub fn parse_single_fixture(fixture: &str) -> Option<FixtureEntry> { 292pub fn parse_single_fixture(fixture: &str) -> Option<FixtureEntry> {
207 if !fixture.lines().any(|it| it.trim_start().starts_with("//-")) { 293 if !fixture.lines().any(|it| it.trim_start().starts_with("//-")) {
diff --git a/crates/test_utils/src/marks.rs b/crates/test_utils/src/mark.rs
index c3185e860..7c309a894 100644
--- a/crates/test_utils/src/marks.rs
+++ b/crates/test_utils/src/mark.rs
@@ -7,18 +7,18 @@
7//! ``` 7//! ```
8//! #[test] 8//! #[test]
9//! fn test_foo() { 9//! fn test_foo() {
10//! covers!(test_foo); 10//! mark::check!(test_foo);
11//! } 11//! }
12//! ``` 12//! ```
13//! 13//!
14//! and in the code under test you write 14//! and in the code under test you write
15//! 15//!
16//! ``` 16//! ```
17//! # use test_utils::tested_by; 17//! # use test_utils::mark;
18//! # fn some_condition() -> bool { true } 18//! # fn some_condition() -> bool { true }
19//! fn foo() { 19//! fn foo() {
20//! if some_condition() { 20//! if some_condition() {
21//! tested_by!(test_foo); 21//! mark::hit!(test_foo);
22//! } 22//! }
23//! } 23//! }
24//! ``` 24//! ```
@@ -29,43 +29,31 @@
29use std::sync::atomic::{AtomicUsize, Ordering}; 29use std::sync::atomic::{AtomicUsize, Ordering};
30 30
31#[macro_export] 31#[macro_export]
32macro_rules! tested_by { 32macro_rules! _hit {
33 ($ident:ident; force) => {{
34 {
35 // sic! use call-site crate
36 crate::marks::$ident.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
37 }
38 }};
39 ($ident:ident) => {{ 33 ($ident:ident) => {{
40 #[cfg(test)] 34 #[cfg(test)]
41 { 35 {
42 // sic! use call-site crate 36 extern "C" {
43 crate::marks::$ident.fetch_add(1, std::sync::atomic::Ordering::SeqCst); 37 #[no_mangle]
38 static $ident: std::sync::atomic::AtomicUsize;
39 }
40 unsafe {
41 $ident.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
42 }
44 } 43 }
45 }}; 44 }};
46} 45}
46pub use _hit as hit;
47 47
48#[macro_export] 48#[macro_export]
49macro_rules! covers { 49macro_rules! _check {
50 // sic! use call-site crate
51 ($ident:ident) => { 50 ($ident:ident) => {
52 $crate::covers!(crate::$ident) 51 #[no_mangle]
53 }; 52 static $ident: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
54 ($krate:ident :: $ident:ident) => { 53 let _checker = $crate::mark::MarkChecker::new(&$ident);
55 let _checker = $crate::marks::MarkChecker::new(&$krate::marks::$ident);
56 };
57}
58
59#[macro_export]
60macro_rules! marks {
61 ($($ident:ident)*) => {
62 $(
63 #[allow(bad_style)]
64 pub static $ident: std::sync::atomic::AtomicUsize =
65 std::sync::atomic::AtomicUsize::new(0);
66 )*
67 }; 54 };
68} 55}
56pub use _check as check;
69 57
70pub struct MarkChecker { 58pub struct MarkChecker {
71 mark: &'static AtomicUsize, 59 mark: &'static AtomicUsize,
diff --git a/docs/dev/README.md b/docs/dev/README.md
index f230dc1db..65cc9fc12 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -74,7 +74,7 @@ relevant test and execute it (VS Code includes an action for running a single
74test). 74test).
75 75
76However, launching a VS Code instance with locally build language server is 76However, launching a VS Code instance with locally build language server is
77possible. There's **"Run Extension (Dev Server)"** launch configuration for this. 77possible. There's **"Run Extension (Debug Build)"** launch configuration for this.
78 78
79In general, I use one of the following workflows for fixing bugs and 79In general, I use one of the following workflows for fixing bugs and
80implementing features. 80implementing features.
@@ -86,7 +86,7 @@ then just do printf-driven development/debugging. As a sanity check after I'm
86done, I use `cargo xtask install --server` and **Reload Window** action in VS 86done, I use `cargo xtask install --server` and **Reload Window** action in VS
87Code to sanity check that the thing works as I expect. 87Code to sanity check that the thing works as I expect.
88 88
89If the problem concerns only the VS Code extension, I use **Run Extension** 89If the problem concerns only the VS Code extension, I use **Run Installed Extension**
90launch configuration from `launch.json`. Notably, this uses the usual 90launch configuration from `launch.json`. Notably, this uses the usual
91`rust-analyzer` binary from `PATH`. For this it is important to have the following 91`rust-analyzer` binary from `PATH`. For this it is important to have the following
92in `setting.json` file: 92in `setting.json` file:
@@ -134,7 +134,7 @@ To log all communication between the server and the client, there are two choice
134 134
135* you can log on the server side, by running something like 135* you can log on the server side, by running something like
136 ``` 136 ```
137 env RUST_LOG=gen_lsp_server=trace code . 137 env RA_LOG=gen_lsp_server=trace code .
138 ``` 138 ```
139 139
140* you can log on the client side, by enabling `"rust-analyzer.trace.server": 140* you can log on the client side, by enabling `"rust-analyzer.trace.server":
diff --git a/docs/dev/debugging.md b/docs/dev/debugging.md
index bece6a572..59a83f7d7 100644
--- a/docs/dev/debugging.md
+++ b/docs/dev/debugging.md
@@ -22,11 +22,11 @@ where **only** the `rust-analyzer` extension being debugged is enabled.
22 22
23## Debug TypeScript VSCode extension 23## Debug TypeScript VSCode extension
24 24
25- `Run Extension` - runs the extension with the globally installed `rust-analyzer` binary. 25- `Run Installed Extension` - runs the extension with the globally installed `rust-analyzer` binary.
26- `Run Extension (Dev Server)` - runs extension with the locally built LSP server (`target/debug/rust-analyzer`). 26- `Run Extension (Debug Build)` - runs extension with the locally built LSP server (`target/debug/rust-analyzer`).
27 27
28TypeScript debugging is configured to watch your source edits and recompile. 28TypeScript debugging is configured to watch your source edits and recompile.
29To apply changes to an already running debug process press <kbd>Ctrl+Shift+P</kbd> and run the following command in your `[Extension Development Host]` 29To apply changes to an already running debug process, press <kbd>Ctrl+Shift+P</kbd> and run the following command in your `[Extension Development Host]`
30 30
31``` 31```
32> Developer: Reload Window 32> Developer: Reload Window
@@ -47,7 +47,7 @@ To apply changes to an already running debug process press <kbd>Ctrl+Shift+P</kb
47 debug = 2 47 debug = 2
48 ``` 48 ```
49 49
50- Select `Run Extension (Dev Server)` to run your locally built `target/debug/rust-analyzer`. 50- Select `Run Extension (Debug Build)` to run your locally built `target/debug/rust-analyzer`.
51 51
52- In the original VSCode window once again select the `Attach To Server` debug configuration. 52- In the original VSCode window once again select the `Attach To Server` debug configuration.
53 53
@@ -76,11 +76,11 @@ Make sure you open a rust file in the `[Extension Development Host]` and try aga
76 76
77Make sure you have run `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`. 77Make sure you have run `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`.
78 78
79By default this should reset back to 1 everytime you log in. 79By default this should reset back to 1 every time you log in.
80 80
81### Breakpoints are never being hit 81### Breakpoints are never being hit
82 82
83Check your version of `lldb` if it's version 6 and lower use the `classic` adapter type. 83Check your version of `lldb`. If it's version 6 and lower, use the `classic` adapter type.
84It's `lldb.adapterType` in settings file. 84It's `lldb.adapterType` in settings file.
85 85
86If you're running `lldb` version 7 change the lldb adapter type to `bundled` or `native`. 86If you're running `lldb` version 7, change the lldb adapter type to `bundled` or `native`.
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
new file mode 100644
index 000000000..0e3a0af1c
--- /dev/null
+++ b/docs/dev/lsp-extensions.md
@@ -0,0 +1,86 @@
1# LSP Extensions
2
3This document describes LSP extensions used by rust-analyzer.
4It's a best effort document, when in doubt, consult the source (and send a PR with clarification ;-) ).
5We aim to upstream all non Rust-specific extensions to the protocol, but this is not a top priority.
6All capabilities are enabled via `experimental` field of `ClientCapabilities`.
7
8## `SnippetTextEdit`
9
10**Client Capability:** `{ "snippetTextEdit": boolean }`
11
12If this capability is set, `WorkspaceEdit`s returned from `codeAction` requests might contain `SnippetTextEdit`s instead of usual `TextEdit`s:
13
14```typescript
15interface SnippetTextEdit extends TextEdit {
16 insertTextFormat?: InsertTextFormat;
17}
18```
19
20```typescript
21export interface TextDocumentEdit {
22 textDocument: VersionedTextDocumentIdentifier;
23 edits: (TextEdit | SnippetTextEdit)[];
24}
25```
26
27When applying such code action, the editor should insert snippet, with tab stops and placeholder.
28At the moment, rust-analyzer guarantees that only a single edit will have `InsertTextFormat.Snippet`.
29
30### Example
31
32"Add `derive`" code action transforms `struct S;` into `#[derive($0)] struct S;`
33
34### Unresolved Questions
35
36* Where exactly are `SnippetTextEdit`s allowed (only in code actions at the moment)?
37* Can snippets span multiple files (so far, no)?
38
39## `joinLines`
40
41**Server Capability:** `{ "joinLines": boolean }`
42
43This request is send from client to server to handle "Join Lines" editor action.
44
45**Method:** `experimental/JoinLines`
46
47**Request:**
48
49```typescript
50interface JoinLinesParams {
51 textDocument: TextDocumentIdentifier,
52 /// Currently active selections/cursor offsets.
53 /// This is an array to support multiple cursors.
54 ranges: Range[],
55}
56```
57
58**Response:**
59
60```typescript
61TextEdit[]
62```
63
64### Example
65
66```rust
67fn main() {
68 /*cursor here*/let x = {
69 92
70 };
71}
72```
73
74`experimental/joinLines` yields (curly braces are automagiacally removed)
75
76```rust
77fn main() {
78 let x = 92;
79}
80```
81
82### Unresolved Question
83
84* What is the position of the cursor after `joinLines`?
85 Currently this is left to editor's discretion, but it might be useful to specify on the server via snippets.
86 However, it then becomes unclear how it works with multi cursor.
diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md
index 33973ffec..c2864bbbc 100644
--- a/docs/dev/syntax.md
+++ b/docs/dev/syntax.md
@@ -64,7 +64,7 @@ struct Token {
64} 64}
65``` 65```
66 66
67All the difference bettwen the above sketch and the real implementation are strictly due to optimizations. 67All the difference between the above sketch and the real implementation are strictly due to optimizations.
68 68
69Points of note: 69Points of note:
70* The tree is untyped. Each node has a "type tag", `SyntaxKind`. 70* The tree is untyped. Each node has a "type tag", `SyntaxKind`.
@@ -72,7 +72,7 @@ Points of note:
72* Trivia and non-trivia tokens are not distinguished on the type level. 72* Trivia and non-trivia tokens are not distinguished on the type level.
73* Each token carries its full text. 73* Each token carries its full text.
74* The original text can be recovered by concatenating the texts of all tokens in order. 74* The original text can be recovered by concatenating the texts of all tokens in order.
75* Accessing a child of particular type (for example, parameter list of a function) generarly involves linerary traversing the children, looking for a specific `kind`. 75* Accessing a child of particular type (for example, parameter list of a function) generally involves linerary traversing the children, looking for a specific `kind`.
76* Modifying the tree is roughly `O(depth)`. 76* Modifying the tree is roughly `O(depth)`.
77 We don't make special efforts to guarantree that the depth is not liner, but, in practice, syntax trees are branchy and shallow. 77 We don't make special efforts to guarantree that the depth is not liner, but, in practice, syntax trees are branchy and shallow.
78* If mandatory (grammar wise) node is missing from the input, it's just missing from the tree. 78* If mandatory (grammar wise) node is missing from the input, it's just missing from the tree.
@@ -123,7 +123,7 @@ To more compactly store the children, we box *both* interior nodes and tokens, a
123`Either<Arc<Node>, Arc<Token>>` as a single pointer with a tag in the last bit. 123`Either<Arc<Node>, Arc<Token>>` as a single pointer with a tag in the last bit.
124 124
125To avoid allocating EVERY SINGLE TOKEN on the heap, syntax trees use interning. 125To avoid allocating EVERY SINGLE TOKEN on the heap, syntax trees use interning.
126Because the tree is fully imutable, it's valid to structuraly share subtrees. 126Because the tree is fully immutable, it's valid to structurally share subtrees.
127For example, in `1 + 1`, there will be a *single* token for `1` with ref count 2; the same goes for the ` ` whitespace token. 127For example, in `1 + 1`, there will be a *single* token for `1` with ref count 2; the same goes for the ` ` whitespace token.
128Interior nodes are shared as well (for example in `(1 + 1) * (1 + 1)`). 128Interior nodes are shared as well (for example in `(1 + 1) * (1 + 1)`).
129 129
@@ -134,8 +134,8 @@ Currently, the interner is created per-file, but it will be easy to use a per-th
134 134
135We use a `TextSize`, a newtyped `u32`, to store the length of the text. 135We use a `TextSize`, a newtyped `u32`, to store the length of the text.
136 136
137We currently use `SmolStr`, an small object optimized string to store text. 137We currently use `SmolStr`, a small object optimized string to store text.
138This was mostly relevant *before* we implmented tree interning, to avoid allocating common keywords and identifiers. We should switch to storing text data alongside the interned tokens. 138This was mostly relevant *before* we implemented tree interning, to avoid allocating common keywords and identifiers. We should switch to storing text data alongside the interned tokens.
139 139
140#### Alternative designs 140#### Alternative designs
141 141
@@ -162,12 +162,12 @@ Explicit trivia nodes, like in `rowan`, are used by IntelliJ.
162 162
163##### Accessing Children 163##### Accessing Children
164 164
165As noted before, accesing a specific child in the node requires a linear traversal of the children (though we can skip tokens, beacuse the tag is encoded in the pointer itself). 165As noted before, accessing a specific child in the node requires a linear traversal of the children (though we can skip tokens, because the tag is encoded in the pointer itself).
166It is possible to recover O(1) access with another representation. 166It is possible to recover O(1) access with another representation.
167We explicitly store optional and missing (required by the grammar, but not present) nodes. 167We explicitly store optional and missing (required by the grammar, but not present) nodes.
168That is, we use `Option<Node>` for children. 168That is, we use `Option<Node>` for children.
169We also remove trivia tokens from the tree. 169We also remove trivia tokens from the tree.
170This way, each child kind genrerally occupies a fixed position in a parent, and we can use index access to fetch it. 170This way, each child kind generally occupies a fixed position in a parent, and we can use index access to fetch it.
171The cost is that we now need to allocate space for all not-present optional nodes. 171The cost is that we now need to allocate space for all not-present optional nodes.
172So, `fn foo() {}` will have slots for visibility, unsafeness, attributes, abi and return type. 172So, `fn foo() {}` will have slots for visibility, unsafeness, attributes, abi and return type.
173 173
@@ -193,7 +193,7 @@ Modeling this with immutable trees is possible, but annoying.
193### Syntax Nodes 193### Syntax Nodes
194 194
195A function green tree is not super-convenient to use. 195A function green tree is not super-convenient to use.
196The biggest problem is acessing parents (there are no parent pointers!). 196The biggest problem is accessing parents (there are no parent pointers!).
197But there are also "identify" issues. 197But there are also "identify" issues.
198Let's say you want to write a code which builds a list of expressions in a file: `fn collect_exrepssions(file: GreenNode) -> HashSet<GreenNode>`. 198Let's say you want to write a code which builds a list of expressions in a file: `fn collect_exrepssions(file: GreenNode) -> HashSet<GreenNode>`.
199For the input like 199For the input like
@@ -207,7 +207,7 @@ fn main() {
207} 207}
208``` 208```
209 209
210both copies of the `x + 2` expression are representing by equal (and, with interning in mind, actualy the same) green nodes. 210both copies of the `x + 2` expression are representing by equal (and, with interning in mind, actually the same) green nodes.
211Green trees just can't differentiate between the two. 211Green trees just can't differentiate between the two.
212 212
213`SyntaxNode` adds parent pointers and identify semantics to green nodes. 213`SyntaxNode` adds parent pointers and identify semantics to green nodes.
@@ -285,9 +285,9 @@ They also point to the parent (and, consequently, to the root) with an owning `R
285In other words, one needs *one* arc bump when initiating a traversal. 285In other words, one needs *one* arc bump when initiating a traversal.
286 286
287To get rid of allocations, `rowan` takes advantage of `SyntaxNode: !Sync` and uses a thread-local free list of `SyntaxNode`s. 287To get rid of allocations, `rowan` takes advantage of `SyntaxNode: !Sync` and uses a thread-local free list of `SyntaxNode`s.
288In a typical traversal, you only directly hold a few `SyntaxNode`s at a time (and their ancesstors indirectly), so a free list proportional to the depth of the tree removes all allocations in a typical case. 288In a typical traversal, you only directly hold a few `SyntaxNode`s at a time (and their ancestors indirectly), so a free list proportional to the depth of the tree removes all allocations in a typical case.
289 289
290So, while traversal is not exactly incrementing a pointer, it's still prety cheep: tls + rc bump! 290So, while traversal is not exactly incrementing a pointer, it's still pretty cheap: TLS + rc bump!
291 291
292Traversal also yields (cheap) owned nodes, which improves ergonomics quite a bit. 292Traversal also yields (cheap) owned nodes, which improves ergonomics quite a bit.
293 293
@@ -308,15 +308,15 @@ struct SyntaxData {
308} 308}
309``` 309```
310 310
311This allows using true pointer equality for comparision of identities of `SyntaxNodes`. 311This allows using true pointer equality for comparison of identities of `SyntaxNodes`.
312rust-analyzer used to have this design as well, but since we've switch to cursors. 312rust-analyzer used to have this design as well, but we've since switched to cursors.
313The main problem with memoizing the red nodes is that it more than doubles the memory requirenments for fully realized syntax trees. 313The main problem with memoizing the red nodes is that it more than doubles the memory requirements for fully realized syntax trees.
314In contrast, cursors generally retain only a path to the root. 314In contrast, cursors generally retain only a path to the root.
315C# combats increased memory usage by using weak references. 315C# combats increased memory usage by using weak references.
316 316
317### AST 317### AST
318 318
319`GreenTree`s are untyped and homogeneous, because it makes accomodating error nodes, arbitrary whitespace and comments natural, and because it makes possible to write generic tree traversals. 319`GreenTree`s are untyped and homogeneous, because it makes accommodating error nodes, arbitrary whitespace and comments natural, and because it makes possible to write generic tree traversals.
320However, when working with a specific node, like a function definition, one would want a strongly typed API. 320However, when working with a specific node, like a function definition, one would want a strongly typed API.
321 321
322This is what is provided by the AST layer. AST nodes are transparent wrappers over untyped syntax nodes: 322This is what is provided by the AST layer. AST nodes are transparent wrappers over untyped syntax nodes:
@@ -397,7 +397,7 @@ impl HasVisbility for FnDef {
397Points of note: 397Points of note:
398 398
399* Like `SyntaxNode`s, AST nodes are cheap to clone pointer-sized owned values. 399* Like `SyntaxNode`s, AST nodes are cheap to clone pointer-sized owned values.
400* All "fields" are optional, to accomodate incomplete and/or erroneous source code. 400* All "fields" are optional, to accommodate incomplete and/or erroneous source code.
401* It's always possible to go from an ast node to an untyped `SyntaxNode`. 401* It's always possible to go from an ast node to an untyped `SyntaxNode`.
402* It's possible to go in the opposite direction with a checked cast. 402* It's possible to go in the opposite direction with a checked cast.
403* `enum`s allow modeling of arbitrary intersecting subsets of AST types. 403* `enum`s allow modeling of arbitrary intersecting subsets of AST types.
@@ -437,13 +437,13 @@ impl GreenNodeBuilder {
437} 437}
438``` 438```
439 439
440The parser, ultimatelly, needs to invoke the `GreenNodeBuilder`. 440The parser, ultimately, needs to invoke the `GreenNodeBuilder`.
441There are two principal sources of inputs for the parser: 441There are two principal sources of inputs for the parser:
442 * source text, which contains trivia tokens (whitespace and comments) 442 * source text, which contains trivia tokens (whitespace and comments)
443 * token trees from macros, which lack trivia 443 * token trees from macros, which lack trivia
444 444
445Additionaly, input tokens do not correspond 1-to-1 with output tokens. 445Additionally, input tokens do not correspond 1-to-1 with output tokens.
446For example, two consequtive `>` tokens might be glued, by the parser, into a single `>>`. 446For example, two consecutive `>` tokens might be glued, by the parser, into a single `>>`.
447 447
448For these reasons, the parser crate defines a callback interfaces for both input tokens and output trees. 448For these reasons, the parser crate defines a callback interfaces for both input tokens and output trees.
449The explicit glue layer then bridges various gaps. 449The explicit glue layer then bridges various gaps.
@@ -491,7 +491,7 @@ Syntax errors are not stored directly in the tree.
491The primary motivation for this is that syntax tree is not necessary produced by the parser, it may also be assembled manually from pieces (which happens all the time in refactorings). 491The primary motivation for this is that syntax tree is not necessary produced by the parser, it may also be assembled manually from pieces (which happens all the time in refactorings).
492Instead, parser reports errors to an error sink, which stores them in a `Vec`. 492Instead, parser reports errors to an error sink, which stores them in a `Vec`.
493If possible, errors are not reported during parsing and are postponed for a separate validation step. 493If possible, errors are not reported during parsing and are postponed for a separate validation step.
494For example, parser accepts visibility modifiers on trait methods, but then a separate tree traversal flags all such visibilites as erroneous. 494For example, parser accepts visibility modifiers on trait methods, but then a separate tree traversal flags all such visibilities as erroneous.
495 495
496### Macros 496### Macros
497 497
@@ -501,7 +501,7 @@ Specifically, `TreeSink` constructs the tree in lockstep with draining the origi
501In the process, it records which tokens of the tree correspond to which tokens of the input, by using text ranges to identify syntax tokens. 501In the process, it records which tokens of the tree correspond to which tokens of the input, by using text ranges to identify syntax tokens.
502The end result is that parsing an expanded code yields a syntax tree and a mapping of text-ranges of the tree to original tokens. 502The end result is that parsing an expanded code yields a syntax tree and a mapping of text-ranges of the tree to original tokens.
503 503
504To deal with precedence in cases like `$expr * 1`, we use special invisible parenthesis, which are explicitelly handled by the parser 504To deal with precedence in cases like `$expr * 1`, we use special invisible parenthesis, which are explicitly handled by the parser
505 505
506### Whitespace & Comments 506### Whitespace & Comments
507 507
diff --git a/docs/user/assists.md b/docs/user/assists.md
index 6c6943622..4ad7ea59d 100644
--- a/docs/user/assists.md
+++ b/docs/user/assists.md
@@ -17,7 +17,7 @@ struct S;
17struct S; 17struct S;
18 18
19impl Debug for S { 19impl Debug for S {
20 20 $0
21} 21}
22``` 22```
23 23
@@ -33,7 +33,7 @@ struct Point {
33} 33}
34 34
35// AFTER 35// AFTER
36#[derive()] 36#[derive($0)]
37struct Point { 37struct Point {
38 x: u32, 38 x: u32,
39 y: u32, 39 y: u32,
@@ -77,7 +77,7 @@ fn foo() {
77} 77}
78 78
79fn bar(arg: &str, baz: Baz) { 79fn bar(arg: &str, baz: Baz) {
80 todo!() 80 ${0:todo!()}
81} 81}
82 82
83``` 83```
@@ -105,16 +105,16 @@ Adds a new inherent impl for a type.
105```rust 105```rust
106// BEFORE 106// BEFORE
107struct Ctx<T: Clone> { 107struct Ctx<T: Clone> {
108 data: T,┃ 108 data: T,┃
109} 109}
110 110
111// AFTER 111// AFTER
112struct Ctx<T: Clone> { 112struct Ctx<T: Clone> {
113 data: T, 113 data: T,
114} 114}
115 115
116impl<T: Clone> Ctx<T> { 116impl<T: Clone> Ctx<T> {
117 117 $0
118} 118}
119``` 119```
120 120
@@ -146,7 +146,7 @@ trait Trait {
146impl Trait for () { 146impl Trait for () {
147 Type X = (); 147 Type X = ();
148 fn foo(&self) {} 148 fn foo(&self) {}
149 fn bar(&self) {} 149 $0fn bar(&self) {}
150 150
151} 151}
152``` 152```
@@ -175,7 +175,9 @@ trait Trait<T> {
175} 175}
176 176
177impl Trait<u32> for () { 177impl Trait<u32> for () {
178 fn foo(&self) -> u32 { todo!() } 178 fn foo(&self) -> u32 {
179 ${0:todo!()}
180 }
179 181
180} 182}
181``` 183```
@@ -196,11 +198,29 @@ struct Ctx<T: Clone> {
196} 198}
197 199
198impl<T: Clone> Ctx<T> { 200impl<T: Clone> Ctx<T> {
199 fn new(data: T) -> Self { Self { data } } 201 fn $0new(data: T) -> Self { Self { data } }
200} 202}
201 203
202``` 204```
203 205
206## `add_turbo_fish`
207
208Adds `::<_>` to a call of a generic method or function.
209
210```rust
211// BEFORE
212fn make<T>() -> T { todo!() }
213fn main() {
214 let x = make┃();
215}
216
217// AFTER
218fn make<T>() -> T { todo!() }
219fn main() {
220 let x = make::<${0:_}>();
221}
222```
223
204## `apply_demorgan` 224## `apply_demorgan`
205 225
206Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws). 226Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
@@ -239,6 +259,18 @@ fn main() {
239} 259}
240``` 260```
241 261
262## `change_return_type_to_result`
263
264Change the function's return type to Result.
265
266```rust
267// BEFORE
268fn foo() -> i32┃ { 42i32 }
269
270// AFTER
271fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
272```
273
242## `change_visibility` 274## `change_visibility`
243 275
244Adds or changes existing visibility specifier. 276Adds or changes existing visibility specifier.
@@ -293,12 +325,34 @@ enum Action { Move { distance: u32 }, Stop }
293 325
294fn handle(action: Action) { 326fn handle(action: Action) {
295 match action { 327 match action {
296 Action::Move { distance } => {} 328 $0Action::Move { distance } => {}
297 Action::Stop => {} 329 Action::Stop => {}
298 } 330 }
299} 331}
300``` 332```
301 333
334## `fix_visibility`
335
336Makes inaccessible item public.
337
338```rust
339// BEFORE
340mod m {
341 fn frobnicate() {}
342}
343fn main() {
344 m::frobnicate┃() {}
345}
346
347// AFTER
348mod m {
349 $0pub(crate) fn frobnicate() {}
350}
351fn main() {
352 m::frobnicate() {}
353}
354```
355
302## `flip_binexpr` 356## `flip_binexpr`
303 357
304Flips operands of a binary expression. 358Flips operands of a binary expression.
@@ -372,7 +426,7 @@ fn main() {
372 426
373// AFTER 427// AFTER
374fn main() { 428fn main() {
375 let var_name = (1 + 2); 429 let $0var_name = (1 + 2);
376 var_name * 4; 430 var_name * 4;
377} 431}
378``` 432```
@@ -679,7 +733,7 @@ fn main() {
679 let x: Result<i32, i32> = Result::Ok(92); 733 let x: Result<i32, i32> = Result::Ok(92);
680 let y = match x { 734 let y = match x {
681 Ok(a) => a, 735 Ok(a) => a,
682 _ => unreachable!(), 736 $0_ => unreachable!(),
683 }; 737 };
684} 738}
685``` 739```
@@ -695,3 +749,21 @@ use std::┃collections::HashMap;
695// AFTER 749// AFTER
696use std::{collections::HashMap}; 750use std::{collections::HashMap};
697``` 751```
752
753## `unwrap_block`
754
755This assist removes if...else, for, while and loop control statements to just keep the body.
756
757```rust
758// BEFORE
759fn foo() {
760 if true {┃
761 println!("foo");
762 }
763}
764
765// AFTER
766fn foo() {
767 println!("foo");
768}
769```
diff --git a/docs/user/features.md b/docs/user/features.md
index b9a365fc1..340bce835 100644
--- a/docs/user/features.md
+++ b/docs/user/features.md
@@ -143,9 +143,9 @@ takes arguments, the cursor is positioned inside the parenthesis.
143There are postfix completions, which can be triggered by typing something like 143There are postfix completions, which can be triggered by typing something like
144`foo().if`. The word after `.` determines postfix completion. Possible variants are: 144`foo().if`. The word after `.` determines postfix completion. Possible variants are:
145 145
146- `expr.if` -> `if expr {}` 146- `expr.if` -> `if expr {}` or `if let ... {}` for `Option` or `Result`
147- `expr.match` -> `match expr {}` 147- `expr.match` -> `match expr {}`
148- `expr.while` -> `while expr {}` 148- `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result`
149- `expr.ref` -> `&expr` 149- `expr.ref` -> `&expr`
150- `expr.refm` -> `&mut expr` 150- `expr.refm` -> `&mut expr`
151- `expr.not` -> `!expr` 151- `expr.not` -> `!expr`
@@ -161,6 +161,16 @@ There also snippet completions:
161#### Inside Modules 161#### Inside Modules
162 162
163- `tfn` -> `#[test] fn f(){}` 163- `tfn` -> `#[test] fn f(){}`
164- `tmod` ->
165```rust
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[test]
171 fn test_fn() {}
172}
173```
164 174
165### Code Highlighting 175### Code Highlighting
166 176
diff --git a/docs/user/readme.adoc b/docs/user/readme.adoc
index b1af72ce6..40ed54809 100644
--- a/docs/user/readme.adoc
+++ b/docs/user/readme.adoc
@@ -57,9 +57,13 @@ To disable this notification put the following to `settings.json`
57---- 57----
58==== 58====
59 59
60The server binary is stored in `~/.config/Code/User/globalStorage/matklad.rust-analyzer` (Linux) or in `~/.Library/Application Support/Code/User/globalStorage/matklad.rust-analyzer` (macOS) or in `%APPDATA%\Code\User\globalStorage` (Windows). 60The server binary is stored in:
61 61
62Note that we only support the latest version of VS Code. 62* Linux: `~/.config/Code/User/globalStorage/matklad.rust-analyzer`
63* macOS: `~/Library/Application Support/Code/User/globalStorage/matklad.rust-analyzer`
64* Windows: `%APPDATA%\Code\User\globalStorage\matklad.rust-analyzer`
65
66Note that we only support two most recent versions of VS Code.
63 67
64==== Updates 68==== Updates
65 69
@@ -104,7 +108,7 @@ Here are some useful self-diagnostic commands:
104 108
105* **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary 109* **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary
106* **Rust Analyzer: Status** prints some statistics about the server, like the few latest LSP requests 110* **Rust Analyzer: Status** prints some statistics about the server, like the few latest LSP requests
107* To enable server-side logging, run with `env RUST_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel. 111* To enable server-side logging, run with `env RA_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel.
108* To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel. 112* To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel.
109* To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools. 113* To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools.
110 114
@@ -135,17 +139,16 @@ If your editor can't find the binary even though the binary is on your `$PATH`,
135 139
136==== Arch Linux 140==== Arch Linux
137 141
138The `rust-analyzer` binary can be installed from AUR (Arch User Repository): 142The `rust-analyzer` binary can be installed from the repos or AUR (Arch User Repository):
139 143
140- https://aur.archlinux.org/packages/rust-analyzer-bin[`rust-analyzer-bin`] (binary from GitHub releases) 144- https://www.archlinux.org/packages/community/x86_64/rust-analyzer/[`rust-analyzer`] (built from latest tagged source)
141- https://aur.archlinux.org/packages/rust-analyzer[`rust-analyzer`] (built from latest tagged source) 145- https://aur.archlinux.org/packages/rust-analyzer-git[`rust-analyzer-git`] (latest Git version)
142- https://aur.archlinux.org/packages/rust-analyzer-git[`rust-analyzer-git`] (latest git version)
143 146
144Install it with AUR helper of your choice, for example: 147Install it with pacman, for example:
145 148
146[source,bash] 149[source,bash]
147---- 150----
148$ yay -S rust-analyzer-bin 151$ pacman -S rust-analyzer
149---- 152----
150 153
151=== Emacs 154=== Emacs
@@ -159,11 +162,11 @@ Emacs support is maintained as part of the https://github.com/emacs-lsp/lsp-mode
1593. Run `lsp` in a Rust buffer. 1623. Run `lsp` in a Rust buffer.
1604. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys. 1634. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys.
161 164
162=== Vim 165=== Vim/NeoVim
163 166
164Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. 167Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. Not needed if the extension can install/update it on its own, coc-rust-analyzer is one example.
165 168
166The are several LSP client implementations for vim: 169The are several LSP client implementations for vim or neovim:
167 170
168==== coc-rust-analyzer 171==== coc-rust-analyzer
169 172
@@ -183,7 +186,7 @@ The are several LSP client implementations for vim:
183 186
1841. Install LanguageClient-neovim by following the instructions 1871. Install LanguageClient-neovim by following the instructions
185 https://github.com/autozimu/LanguageClient-neovim[here] 188 https://github.com/autozimu/LanguageClient-neovim[here]
186 * The github project wiki has extra tips on configuration 189 * The GitHub project wiki has extra tips on configuration
187 190
1882. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists): 1912. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists):
189+ 192+
@@ -216,17 +219,11 @@ let g:ycm_language_server =
216 219
217==== ALE 220==== ALE
218 221
219To add the LSP server to https://github.com/dense-analysis/ale[ale]: 222To use the LSP server in https://github.com/dense-analysis/ale[ale]:
220 223
221[source,vim] 224[source,vim]
222---- 225----
223call ale#linter#Define('rust', { 226let g:ale_linters = {'rust': ['analyzer']}
224\ 'name': 'rust-analyzer',
225\ 'lsp': 'stdio',
226\ 'executable': 'rust-analyzer',
227\ 'command': '%e',
228\ 'project_root': '.',
229\})
230---- 227----
231 228
232==== nvim-lsp 229==== nvim-lsp
@@ -252,7 +249,7 @@ If it worked, you should see "rust-analyzer, Line X, Column Y" on the left side
252 249
253If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>> section on installing the language server binary. 250If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>> section on installing the language server binary.
254 251
255=== Gnome Builder 252=== GNOME Builder
256 253
257Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. 254Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
258 255
diff --git a/editors/code/.vscodeignore b/editors/code/.vscodeignore
index ac411f8e2..257b744bf 100644
--- a/editors/code/.vscodeignore
+++ b/editors/code/.vscodeignore
@@ -3,5 +3,6 @@
3!package.json 3!package.json
4!package-lock.json 4!package-lock.json
5!ra_syntax_tree.tmGrammar.json 5!ra_syntax_tree.tmGrammar.json
6!rust.tmGrammar.json
6!icon.png 7!icon.png
7!README.md 8!README.md
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json
index 55ba5351d..06178990f 100644
--- a/editors/code/package-lock.json
+++ b/editors/code/package-lock.json
@@ -88,15 +88,15 @@
88 "dev": true 88 "dev": true
89 }, 89 },
90 "@types/node": { 90 "@types/node": {
91 "version": "12.12.37", 91 "version": "12.12.39",
92 "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.37.tgz", 92 "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.39.tgz",
93 "integrity": "sha512-4mXKoDptrXAwZErQHrLzpe0FN/0Wmf5JRniSVIdwUrtDf9wnmEV1teCNLBo/TwuXhkK/bVegoEn/wmb+x0AuPg==", 93 "integrity": "sha512-pADGfwnDkr6zagDwEiCVE4yQrv7XDkoeVa4OfA9Ju/zRTk6YNDLGtQbkdL4/56mCQQCs4AhNrBIag6jrp7ZuOg==",
94 "dev": true 94 "dev": true
95 }, 95 },
96 "@types/node-fetch": { 96 "@types/node-fetch": {
97 "version": "2.5.6", 97 "version": "2.5.7",
98 "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.6.tgz", 98 "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz",
99 "integrity": "sha512-2w0NTwMWF1d3NJMK0Uiq2UNN8htVCyOWOD0jIPjPgC5Ph/YP4dVhs9YxxcMcuLuwAslz0dVEcZQUaqkLs3IzOQ==", 99 "integrity": "sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==",
100 "dev": true, 100 "dev": true,
101 "requires": { 101 "requires": {
102 "@types/node": "*", 102 "@types/node": "*",
@@ -113,31 +113,31 @@
113 } 113 }
114 }, 114 },
115 "@types/vscode": { 115 "@types/vscode": {
116 "version": "1.44.0", 116 "version": "1.45.0",
117 "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.44.0.tgz", 117 "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.45.0.tgz",
118 "integrity": "sha512-WJZtZlinE3meRdH+I7wTsIhpz/GLhqEQwmPGeh4s1irWLwMzCeTV8WZ+pgPTwrDXoafVUWwo1LiZ9HJVHFlJSQ==", 118 "integrity": "sha512-b0Gyir7sPBCqiKLygAhn/AYVfzWD+SMPkWltBrIuPEyTOxSU1wVApWY/FcxYO2EWTRacoubTl4+gvZf86RkecA==",
119 "dev": true 119 "dev": true
120 }, 120 },
121 "@typescript-eslint/eslint-plugin": { 121 "@typescript-eslint/eslint-plugin": {
122 "version": "2.29.0", 122 "version": "2.33.0",
123 "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.29.0.tgz", 123 "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.33.0.tgz",
124 "integrity": "sha512-X/YAY7azKirENm4QRpT7OVmzok02cSkqeIcLmdz6gXUQG4Hk0Fi9oBAynSAyNXeGdMRuZvjBa0c1Lu0dn/u6VA==", 124 "integrity": "sha512-QV6P32Btu1sCI/kTqjTNI/8OpCYyvlGjW5vD8MpTIg+HGE5S88HtT1G+880M4bXlvXj/NjsJJG0aGcVh0DdbeQ==",
125 "dev": true, 125 "dev": true,
126 "requires": { 126 "requires": {
127 "@typescript-eslint/experimental-utils": "2.29.0", 127 "@typescript-eslint/experimental-utils": "2.33.0",
128 "functional-red-black-tree": "^1.0.1", 128 "functional-red-black-tree": "^1.0.1",
129 "regexpp": "^3.0.0", 129 "regexpp": "^3.0.0",
130 "tsutils": "^3.17.1" 130 "tsutils": "^3.17.1"
131 } 131 }
132 }, 132 },
133 "@typescript-eslint/experimental-utils": { 133 "@typescript-eslint/experimental-utils": {
134 "version": "2.29.0", 134 "version": "2.33.0",
135 "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.29.0.tgz", 135 "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.33.0.tgz",
136 "integrity": "sha512-H/6VJr6eWYstyqjWXBP2Nn1hQJyvJoFdDtsHxGiD+lEP7piGnGpb/ZQd+z1ZSB1F7dN+WsxUDh8+S4LwI+f3jw==", 136 "integrity": "sha512-qzPM2AuxtMrRq78LwyZa8Qn6gcY8obkIrBs1ehqmQADwkYzTE1Pb4y2W+U3rE/iFkSWcWHG2LS6MJfj6SmHApg==",
137 "dev": true, 137 "dev": true,
138 "requires": { 138 "requires": {
139 "@types/json-schema": "^7.0.3", 139 "@types/json-schema": "^7.0.3",
140 "@typescript-eslint/typescript-estree": "2.29.0", 140 "@typescript-eslint/typescript-estree": "2.33.0",
141 "eslint-scope": "^5.0.0", 141 "eslint-scope": "^5.0.0",
142 "eslint-utils": "^2.0.0" 142 "eslint-utils": "^2.0.0"
143 }, 143 },
@@ -154,21 +154,21 @@
154 } 154 }
155 }, 155 },
156 "@typescript-eslint/parser": { 156 "@typescript-eslint/parser": {
157 "version": "2.29.0", 157 "version": "2.33.0",
158 "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.29.0.tgz", 158 "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.33.0.tgz",
159 "integrity": "sha512-H78M+jcu5Tf6m/5N8iiFblUUv+HJDguMSdFfzwa6vSg9lKR8Mk9BsgeSjO8l2EshKnJKcbv0e8IDDOvSNjl0EA==", 159 "integrity": "sha512-AUtmwUUhJoH6yrtxZMHbRUEMsC2G6z5NSxg9KsROOGqNXasM71I8P2NihtumlWTUCRld70vqIZ6Pm4E5PAziEA==",
160 "dev": true, 160 "dev": true,
161 "requires": { 161 "requires": {
162 "@types/eslint-visitor-keys": "^1.0.0", 162 "@types/eslint-visitor-keys": "^1.0.0",
163 "@typescript-eslint/experimental-utils": "2.29.0", 163 "@typescript-eslint/experimental-utils": "2.33.0",
164 "@typescript-eslint/typescript-estree": "2.29.0", 164 "@typescript-eslint/typescript-estree": "2.33.0",
165 "eslint-visitor-keys": "^1.1.0" 165 "eslint-visitor-keys": "^1.1.0"
166 } 166 }
167 }, 167 },
168 "@typescript-eslint/typescript-estree": { 168 "@typescript-eslint/typescript-estree": {
169 "version": "2.29.0", 169 "version": "2.33.0",
170 "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.29.0.tgz", 170 "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.33.0.tgz",
171 "integrity": "sha512-3YGbtnWy4az16Egy5Fj5CckkVlpIh0MADtAQza+jiMADRSKkjdpzZp/5WuvwK/Qib3Z0HtzrDFeWanS99dNhnA==", 171 "integrity": "sha512-d8rY6/yUxb0+mEwTShCQF2zYQdLlqihukNfG9IUlLYz5y1CH6G/9XYbrxQLq3Z14RNvkCC6oe+OcFlyUpwUbkg==",
172 "dev": true, 172 "dev": true,
173 "requires": { 173 "requires": {
174 "debug": "^4.1.1", 174 "debug": "^4.1.1",
@@ -176,8 +176,16 @@
176 "glob": "^7.1.6", 176 "glob": "^7.1.6",
177 "is-glob": "^4.0.1", 177 "is-glob": "^4.0.1",
178 "lodash": "^4.17.15", 178 "lodash": "^4.17.15",
179 "semver": "^6.3.0", 179 "semver": "^7.3.2",
180 "tsutils": "^3.17.1" 180 "tsutils": "^3.17.1"
181 },
182 "dependencies": {
183 "semver": {
184 "version": "7.3.2",
185 "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
186 "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
187 "dev": true
188 }
181 } 189 }
182 }, 190 },
183 "acorn": { 191 "acorn": {
@@ -1066,11 +1074,6 @@
1066 "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1074 "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
1067 "dev": true 1075 "dev": true
1068 }, 1076 },
1069 "jsonc-parser": {
1070 "version": "2.2.1",
1071 "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.2.1.tgz",
1072 "integrity": "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w=="
1073 },
1074 "leven": { 1077 "leven": {
1075 "version": "3.1.0", 1078 "version": "3.1.0",
1076 "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", 1079 "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -1165,18 +1168,18 @@
1165 "dev": true 1168 "dev": true
1166 }, 1169 },
1167 "mime-db": { 1170 "mime-db": {
1168 "version": "1.43.0", 1171 "version": "1.44.0",
1169 "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 1172 "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
1170 "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", 1173 "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
1171 "dev": true 1174 "dev": true
1172 }, 1175 },
1173 "mime-types": { 1176 "mime-types": {
1174 "version": "2.1.26", 1177 "version": "2.1.27",
1175 "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 1178 "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
1176 "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 1179 "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
1177 "dev": true, 1180 "dev": true,
1178 "requires": { 1181 "requires": {
1179 "mime-db": "1.43.0" 1182 "mime-db": "1.44.0"
1180 } 1183 }
1181 }, 1184 },
1182 "mimic-fn": { 1185 "mimic-fn": {
@@ -1457,9 +1460,9 @@
1457 } 1460 }
1458 }, 1461 },
1459 "rollup": { 1462 "rollup": {
1460 "version": "2.7.1", 1463 "version": "2.10.0",
1461 "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.7.1.tgz", 1464 "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.10.0.tgz",
1462 "integrity": "sha512-c1FCjY8HK1nAq0bTZHaR72ZknpP7p0EjxbcVc6BcmtOosurK//P5jtwxX+f/4fgtbrjczqf0uvR+EdtxpriE8g==", 1465 "integrity": "sha512-7BmpEfUN9P6esJzWIn3DmR//90mW6YwYB1t3y48LpF8ITpYtL8s1kEirMKqUu44dVH/6a/rs0EuwYVL3FuRDoA==",
1463 "dev": true, 1466 "dev": true,
1464 "requires": { 1467 "requires": {
1465 "fsevents": "~2.1.2" 1468 "fsevents": "~2.1.2"
@@ -1689,9 +1692,9 @@
1689 } 1692 }
1690 }, 1693 },
1691 "tslib": { 1694 "tslib": {
1692 "version": "1.11.1", 1695 "version": "1.12.0",
1693 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", 1696 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.12.0.tgz",
1694 "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", 1697 "integrity": "sha512-5rxCQkP0kytf4H1T4xz1imjxaUUPMvc5aWp0rJ/VMIN7ClRiH1FwFvBt8wOeMasp/epeUnmSW6CixSIePtiLqA==",
1695 "dev": true 1698 "dev": true
1696 }, 1699 },
1697 "tsutils": { 1700 "tsutils": {
@@ -1735,9 +1738,9 @@
1735 } 1738 }
1736 }, 1739 },
1737 "typescript": { 1740 "typescript": {
1738 "version": "3.8.3", 1741 "version": "3.9.2",
1739 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", 1742 "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.2.tgz",
1740 "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", 1743 "integrity": "sha512-q2ktq4n/uLuNNShyayit+DTobV2ApPEo/6so68JaD5ojvc/6GClBipedB9zNWYxRSAlZXAe405Rlijzl6qDiSw==",
1741 "dev": true 1744 "dev": true
1742 }, 1745 },
1743 "typescript-formatter": { 1746 "typescript-formatter": {
diff --git a/editors/code/package.json b/editors/code/package.json
index d30673791..78f647baa 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -33,22 +33,21 @@
33 "fix": " tsfmt -r && eslint -c .eslintrc.js --ext ts ./src --fix" 33 "fix": " tsfmt -r && eslint -c .eslintrc.js --ext ts ./src --fix"
34 }, 34 },
35 "dependencies": { 35 "dependencies": {
36 "jsonc-parser": "^2.2.1",
37 "node-fetch": "^2.6.0", 36 "node-fetch": "^2.6.0",
38 "vscode-languageclient": "7.0.0-next.1" 37 "vscode-languageclient": "7.0.0-next.1"
39 }, 38 },
40 "devDependencies": { 39 "devDependencies": {
41 "@rollup/plugin-commonjs": "^11.1.0", 40 "@rollup/plugin-commonjs": "^11.1.0",
42 "@rollup/plugin-node-resolve": "^7.1.3", 41 "@rollup/plugin-node-resolve": "^7.1.3",
43 "@types/node": "^12.12.37", 42 "@types/node": "^12.12.39",
44 "@types/node-fetch": "^2.5.6", 43 "@types/node-fetch": "^2.5.7",
45 "@types/vscode": "^1.44.0", 44 "@types/vscode": "^1.44.0",
46 "@typescript-eslint/eslint-plugin": "^2.29.0", 45 "@typescript-eslint/eslint-plugin": "^2.33.0",
47 "@typescript-eslint/parser": "^2.29.0", 46 "@typescript-eslint/parser": "^2.33.0",
48 "eslint": "^6.8.0", 47 "eslint": "^6.8.0",
49 "rollup": "^2.7.1", 48 "rollup": "^2.10.0",
50 "tslib": "^1.11.1", 49 "tslib": "^1.12.0",
51 "typescript": "^3.8.3", 50 "typescript": "^3.9.2",
52 "typescript-formatter": "^7.2.2", 51 "typescript-formatter": "^7.2.2",
53 "vsce": "^1.75.0" 52 "vsce": "^1.75.0"
54 }, 53 },
@@ -122,6 +121,16 @@
122 "category": "Rust Analyzer" 121 "category": "Rust Analyzer"
123 }, 122 },
124 { 123 {
124 "command": "rust-analyzer.debug",
125 "title": "Debug",
126 "category": "Rust Analyzer"
127 },
128 {
129 "command": "rust-analyzer.newDebugConfig",
130 "title": "Generate launch configuration",
131 "category": "Rust Analyzer"
132 },
133 {
125 "command": "rust-analyzer.analyzerStatus", 134 "command": "rust-analyzer.analyzerStatus",
126 "title": "Status", 135 "title": "Status",
127 "category": "Rust Analyzer" 136 "category": "Rust Analyzer"
@@ -205,11 +214,6 @@
205 "default": [], 214 "default": [],
206 "description": "Paths to exclude from analysis." 215 "description": "Paths to exclude from analysis."
207 }, 216 },
208 "rust-analyzer.notifications.workspaceLoaded": {
209 "type": "boolean",
210 "default": true,
211 "markdownDescription": "Whether to show `workspace loaded` message."
212 },
213 "rust-analyzer.notifications.cargoTomlNotFound": { 217 "rust-analyzer.notifications.cargoTomlNotFound": {
214 "type": "boolean", 218 "type": "boolean",
215 "default": true, 219 "default": true,
@@ -238,6 +242,14 @@
238 "default": false, 242 "default": false,
239 "markdownDescription": "Run `cargo check` on startup to get the correct value for package OUT_DIRs" 243 "markdownDescription": "Run `cargo check` on startup to get the correct value for package OUT_DIRs"
240 }, 244 },
245 "rust-analyzer.cargo.target": {
246 "type": [
247 "null",
248 "string"
249 ],
250 "default": null,
251 "description": "Specify the compilation target"
252 },
241 "rust-analyzer.rustfmt.extraArgs": { 253 "rust-analyzer.rustfmt.extraArgs": {
242 "type": "array", 254 "type": "array",
243 "items": { 255 "items": {
@@ -286,27 +298,37 @@
286 "minItems": 1 298 "minItems": 1
287 }, 299 },
288 "default": null, 300 "default": null,
289 "markdownDescription": "Advanced option, fully override the command rust-analyzer uses for checking. The command should include `--message=format=json` or similar option." 301 "markdownDescription": "Advanced option, fully override the command rust-analyzer uses for checking. The command should include `--message-format=json` or similar option."
290 }, 302 },
291 "rust-analyzer.checkOnSave.allTargets": { 303 "rust-analyzer.checkOnSave.allTargets": {
292 "type": "boolean", 304 "type": "boolean",
293 "default": true, 305 "default": true,
294 "markdownDescription": "Check all targets and tests (will be passed as `--all-targets`)" 306 "markdownDescription": "Check all targets and tests (will be passed as `--all-targets`)"
295 }, 307 },
308 "rust-analyzer.checkOnSave.allFeatures": {
309 "type": "boolean",
310 "default": true,
311 "markdownDescription": "Check with all features (will be passed as `--all-features`)"
312 },
313 "rust-analyzer.inlayHints.enable": {
314 "type": "boolean",
315 "default": true,
316 "description": "Whether to show inlay hints"
317 },
296 "rust-analyzer.inlayHints.typeHints": { 318 "rust-analyzer.inlayHints.typeHints": {
297 "type": "boolean", 319 "type": "boolean",
298 "default": true, 320 "default": true,
299 "description": "Whether to show inlay type hints" 321 "description": "Whether to show inlay type hints for variables."
300 }, 322 },
301 "rust-analyzer.inlayHints.chainingHints": { 323 "rust-analyzer.inlayHints.chainingHints": {
302 "type": "boolean", 324 "type": "boolean",
303 "default": true, 325 "default": true,
304 "description": "Whether to show inlay type hints for method chains" 326 "description": "Whether to show inlay type hints for method chains."
305 }, 327 },
306 "rust-analyzer.inlayHints.parameterHints": { 328 "rust-analyzer.inlayHints.parameterHints": {
307 "type": "boolean", 329 "type": "boolean",
308 "default": true, 330 "default": true,
309 "description": "Whether to show function parameter name inlay hints at the call site" 331 "description": "Whether to show function parameter name inlay hints at the call site."
310 }, 332 },
311 "rust-analyzer.inlayHints.maxLength": { 333 "rust-analyzer.inlayHints.maxLength": {
312 "type": [ 334 "type": [
@@ -398,7 +420,7 @@
398 "ms-vscode.cpptools" 420 "ms-vscode.cpptools"
399 ], 421 ],
400 "default": "auto", 422 "default": "auto",
401 "description": "Preffered debug engine.", 423 "description": "Preferred debug engine.",
402 "markdownEnumDescriptions": [ 424 "markdownEnumDescriptions": [
403 "First try to use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb), if it's not installed try to use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools).", 425 "First try to use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb), if it's not installed try to use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools).",
404 "Use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)", 426 "Use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)",
@@ -411,6 +433,36 @@
411 "default": { 433 "default": {
412 "/rustc/<id>": "${env:USERPROFILE}/.rustup/toolchains/<toolchain-id>/lib/rustlib/src/rust" 434 "/rustc/<id>": "${env:USERPROFILE}/.rustup/toolchains/<toolchain-id>/lib/rustlib/src/rust"
413 } 435 }
436 },
437 "rust-analyzer.debug.openDebugPane": {
438 "description": "Whether to open up the Debug Pane on debugging start.",
439 "type": "boolean",
440 "default": false
441 },
442 "rust-analyzer.debug.engineSettings": {
443 "type": "object",
444 "default": {},
445 "description": "Optional settings passed to the debug engine. Example:\n{ \"lldb\": { \"terminal\":\"external\"} }"
446 },
447 "rust-analyzer.lens.enable": {
448 "description": "Whether to show CodeLens in Rust files.",
449 "type": "boolean",
450 "default": true
451 },
452 "rust-analyzer.lens.run": {
453 "markdownDescription": "Whether to show Run lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
454 "type": "boolean",
455 "default": true
456 },
457 "rust-analyzer.lens.debug": {
458 "markdownDescription": "Whether to show Debug lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
459 "type": "boolean",
460 "default": true
461 },
462 "rust-analyzer.lens.implementations": {
463 "markdownDescription": "Whether to show Implementations lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
464 "type": "boolean",
465 "default": true
414 } 466 }
415 } 467 }
416 }, 468 },
@@ -457,6 +509,11 @@
457 ], 509 ],
458 "grammars": [ 510 "grammars": [
459 { 511 {
512 "language": "rust",
513 "scopeName": "source.rust",
514 "path": "rust.tmGrammar.json"
515 },
516 {
460 "language": "ra_syntax_tree", 517 "language": "ra_syntax_tree",
461 "scopeName": "source.ra_syntax_tree", 518 "scopeName": "source.ra_syntax_tree",
462 "path": "ra_syntax_tree.tmGrammar.json" 519 "path": "ra_syntax_tree.tmGrammar.json"
@@ -539,6 +596,10 @@
539 { 596 {
540 "id": "unresolvedReference", 597 "id": "unresolvedReference",
541 "description": "Style for names which can not be resolved due to compilation errors" 598 "description": "Style for names which can not be resolved due to compilation errors"
599 },
600 {
601 "id": "formatSpecifier",
602 "description": "Style for {} placeholders in format strings"
542 } 603 }
543 ], 604 ],
544 "semanticTokenModifiers": [ 605 "semanticTokenModifiers": [
@@ -563,26 +624,41 @@
563 { 624 {
564 "language": "rust", 625 "language": "rust",
565 "scopes": { 626 "scopes": {
627 "macro": [
628 "entity.name.function.macro.rust"
629 ],
566 "attribute": [ 630 "attribute": [
567 "meta.attribute" 631 "meta.attribute.rust"
568 ], 632 ],
569 "builtinType": [ 633 "builtinType": [
570 "support.type.primitive" 634 "support.type.primitive.rust"
571 ], 635 ],
572 "lifetime": [ 636 "lifetime": [
573 "entity.name.lifetime.rust" 637 "storage.modifier.lifetime.rust"
574 ], 638 ],
575 "typeAlias": [ 639 "typeAlias": [
576 "entity.name.typeAlias" 640 "entity.name.type.typeAlias.rust"
577 ], 641 ],
578 "union": [ 642 "union": [
579 "entity.name.union" 643 "entity.name.type.union.rust"
644 ],
645 "struct": [
646 "entity.name.type.struct.rust"
647 ],
648 "keyword": [
649 "keyword.other.rust"
580 ], 650 ],
581 "keyword.unsafe": [ 651 "keyword.controlFlow": [
582 "keyword.other.unsafe" 652 "keyword.control.rust"
583 ], 653 ],
584 "variable.constant": [ 654 "variable.constant": [
585 "entity.name.constant" 655 "variable.other.constant.rust"
656 ],
657 "formatSpecifier": [
658 "punctuation.section.embedded.rust"
659 ],
660 "*.mutable": [
661 "markup.underline"
586 ] 662 ]
587 } 663 }
588 } 664 }
diff --git a/editors/code/rust.tmGrammar.json b/editors/code/rust.tmGrammar.json
new file mode 100644
index 000000000..aa0811326
--- /dev/null
+++ b/editors/code/rust.tmGrammar.json
@@ -0,0 +1,681 @@
1{
2 "name": "Rust",
3 "scopeName": "source.rust",
4 "patterns": [
5 {
6 "comment": "Implementation",
7 "begin": "\\b(impl)\\b",
8 "end": "\\{",
9 "beginCaptures": {
10 "1": {
11 "name": "storage.type.rust"
12 }
13 },
14 "patterns": [
15 {
16 "include": "#block_comment"
17 },
18 {
19 "include": "#line_comment"
20 },
21 {
22 "include": "#sigils"
23 },
24 {
25 "include": "#mut"
26 },
27 {
28 "include": "#dyn"
29 },
30 {
31 "include": "#ref_lifetime"
32 },
33 {
34 "include": "#core_types"
35 },
36 {
37 "include": "#core_marker"
38 },
39 {
40 "include": "#core_traits"
41 },
42 {
43 "include": "#std_types"
44 },
45 {
46 "include": "#std_traits"
47 },
48 {
49 "include": "#type_params"
50 },
51 {
52 "include": "#where"
53 },
54 {
55 "name": "storage.type.rust",
56 "match": "\\bfor\\b"
57 },
58 {
59 "include": "#type"
60 }
61 ]
62 },
63 {
64 "include": "#block_doc_comment"
65 },
66 {
67 "include": "#block_comment"
68 },
69 {
70 "include": "#line_doc_comment"
71 },
72 {
73 "include": "#line_comment"
74 },
75 {
76 "comment": "Attribute",
77 "name": "meta.attribute.rust",
78 "begin": "#\\!?\\[",
79 "end": "\\]",
80 "patterns": [
81 {
82 "include": "#string_literal"
83 },
84 {
85 "include": "#block_doc_comment"
86 },
87 {
88 "include": "#block_comment"
89 },
90 {
91 "include": "#line_doc_comment"
92 },
93 {
94 "include": "#line_comment"
95 }
96 ]
97 },
98 {
99 "comment": "Single-quote string literal (character)",
100 "name": "string.quoted.single.rust",
101 "match": "b?'([^'\\\\]|\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.))'"
102 },
103 {
104 "include": "#string_literal"
105 },
106 {
107 "include": "#raw_string_literal"
108 },
109 {
110 "comment": "Floating point literal (fraction)",
111 "name": "constant.numeric.float.rust",
112 "match": "\\b[0-9][0-9_]*\\.[0-9][0-9_]*([eE][+-]?[0-9_]+)?(f32|f64)?\\b"
113 },
114 {
115 "comment": "Floating point literal (exponent)",
116 "name": "constant.numeric.float.rust",
117 "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?[eE][+-]?[0-9_]+(f32|f64)?\\b"
118 },
119 {
120 "comment": "Floating point literal (typed)",
121 "name": "constant.numeric.float.rust",
122 "match": "\\b[0-9][0-9_]*(\\.[0-9][0-9_]*)?([eE][+-]?[0-9_]+)?(f32|f64)\\b"
123 },
124 {
125 "comment": "Integer literal (decimal)",
126 "name": "constant.numeric.integer.decimal.rust",
127 "match": "\\b[0-9][0-9_]*([ui](8|16|32|64|128|s|size))?\\b"
128 },
129 {
130 "comment": "Integer literal (hexadecimal)",
131 "name": "constant.numeric.integer.hexadecimal.rust",
132 "match": "\\b0x[a-fA-F0-9_]+([ui](8|16|32|64|128|s|size))?\\b"
133 },
134 {
135 "comment": "Integer literal (octal)",
136 "name": "constant.numeric.integer.octal.rust",
137 "match": "\\b0o[0-7_]+([ui](8|16|32|64|128|s|size))?\\b"
138 },
139 {
140 "comment": "Integer literal (binary)",
141 "name": "constant.numeric.integer.binary.rust",
142 "match": "\\b0b[01_]+([ui](8|16|32|64|128|s|size))?\\b"
143 },
144 {
145 "comment": "Static storage modifier",
146 "name": "storage.modifier.static.rust",
147 "match": "\\bstatic\\b"
148 },
149 {
150 "comment": "Boolean constant",
151 "name": "constant.language.boolean.rust",
152 "match": "\\b(true|false)\\b"
153 },
154 {
155 "comment": "Control keyword",
156 "name": "keyword.control.rust",
157 "match": "\\b(async|await|break|continue|else|if|in|for|loop|match|return|try|while)\\b"
158 },
159 {
160 "comment": "Keyword",
161 "name": "keyword.other.rust",
162 "match": "\\b(crate|extern|mod|let|ref|use|super|move|as)\\b"
163 },
164 {
165 "comment": "Reserved keyword",
166 "name": "invalid.deprecated.rust",
167 "match": "\\b(abstract|alignof|become|do|final|macro|offsetof|override|priv|proc|pure|sizeof|typeof|virtual|yield)\\b"
168 },
169 {
170 "include": "#unsafe"
171 },
172 {
173 "include": "#sigils"
174 },
175 {
176 "include": "#self"
177 },
178 {
179 "include": "#mut"
180 },
181 {
182 "include": "#dyn"
183 },
184 {
185 "include": "#impl"
186 },
187 {
188 "include": "#box"
189 },
190 {
191 "include": "#lifetime"
192 },
193 {
194 "include": "#ref_lifetime"
195 },
196 {
197 "include": "#const"
198 },
199 {
200 "include": "#pub"
201 },
202 {
203 "comment": "Miscellaneous operator",
204 "name": "keyword.operator.misc.rust",
205 "match": "(=>|::)"
206 },
207 {
208 "comment": "Comparison operator",
209 "name": "keyword.operator.comparison.rust",
210 "match": "(&&|\\|\\||==|!=)"
211 },
212 {
213 "comment": "Assignment operator",
214 "name": "keyword.operator.assignment.rust",
215 "match": "(\\+=|-=|/=|\\*=|%=|\\^=|&=|\\|=|<<=|>>=|=)"
216 },
217 {
218 "comment": "Arithmetic operator",
219 "name": "keyword.operator.arithmetic.rust",
220 "match": "(!|\\+|-|/|\\*|%|\\^|&|\\||<<|>>)"
221 },
222 {
223 "comment": "Comparison operator (second group because of regex precedence)",
224 "name": "keyword.operator.comparison.rust",
225 "match": "(<=|>=|<|>)"
226 },
227 {
228 "include": "#core_types"
229 },
230 {
231 "include": "#core_vars"
232 },
233 {
234 "include": "#core_marker"
235 },
236 {
237 "include": "#core_traits"
238 },
239 {
240 "include": "#std_types"
241 },
242 {
243 "include": "#std_traits"
244 },
245 {
246 "comment": "Built-in macro",
247 "name": "support.function.builtin.rust",
248 "match": "\\b(macro_rules|compile_error|format_args|env|option_env|concat_idents|concat|line|column|file|stringify|include|include_str|include_bytes|module_path|cfg)!"
249 },
250 {
251 "comment": "Core macro",
252 "name": "support.function.core.rust",
253 "match": "\\b(panic|assert|assert_eq|assert_ne|debug_assert|debug_assert_eq|debug_assert_ne|try|write|writeln|unreachable|unimplemented)!"
254 },
255 {
256 "comment": "Standard library macro",
257 "name": "support.function.std.rust",
258 "match": "\\b(format|print|println|eprint|eprintln|select|vec)!"
259 },
260 {
261 "comment": "Logging macro",
262 "name": "support.function.log.rust",
263 "match": "\\b(log|error|warn|info|debug|trace|log_enabled)!"
264 },
265 {
266 "comment": "Invokation of a macro",
267 "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*\\!)\\s*[({\\[]",
268 "captures": {
269 "1": {
270 "name": "entity.name.function.macro.rust"
271 }
272 }
273 },
274 {
275 "comment": "Function call",
276 "match": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*\\(",
277 "captures": {
278 "1": {
279 "name": "entity.name.function.rust"
280 }
281 }
282 },
283 {
284 "comment": "Function call with type parameters",
285 "begin": "\\b([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)\\s*(::)(?=\\s*<.*>\\s*\\()",
286 "end": "\\(",
287 "captures": {
288 "1": {
289 "name": "entity.name.function.rust"
290 },
291 "2": {
292 "name": "keyword.operator.misc.rust"
293 }
294 },
295 "patterns": [
296 {
297 "include": "#type_params"
298 }
299 ]
300 },
301 {
302 "comment": "Function definition",
303 "begin": "\\b(fn)\\s+([A-Za-z][A-Za-z0-9_]*|_[A-Za-z0-9_]+)",
304 "end": "[\\{;]",
305 "beginCaptures": {
306 "1": {
307 "name": "keyword.other.fn.rust"
308 },
309 "2": {
310 "name": "entity.name.function.rust"
311 }
312 },
313 "patterns": [
314 {
315 "include": "#block_comment"
316 },
317 {
318 "include": "#line_comment"
319 },
320 {
321 "include": "#sigils"
322 },
323 {
324 "include": "#self"
325 },
326 {
327 "include": "#mut"
328 },
329 {
330 "include": "#dyn"
331 },
332 {
333 "include": "#impl"
334 },
335 {
336 "include": "#ref_lifetime"
337 },
338 {
339 "include": "#core_types"
340 },
341 {
342 "include": "#core_marker"
343 },
344 {
345 "include": "#core_traits"
346 },
347 {
348 "include": "#std_types"
349 },
350 {
351 "include": "#std_traits"
352 },
353 {
354 "include": "#type_params"
355 },
356 {
357 "include": "#const"
358 },
359 {
360 "include": "#where"
361 },
362 {
363 "include": "#unsafe"
364 },
365 {
366 "comment": "Function arguments",
367 "match": "\bfn\b",
368 "name": "keyword.other.fn.rust"
369 }
370 ]
371 },
372 {
373 "comment": "Type declaration",
374 "begin": "\\b(enum|struct|trait|union)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
375 "end": "[\\{\\(;]",
376 "beginCaptures": {
377 "1": {
378 "name": "storage.type.rust"
379 },
380 "2": {
381 "name": "entity.name.type.rust"
382 }
383 },
384 "patterns": [
385 {
386 "include": "#block_comment"
387 },
388 {
389 "include": "#line_comment"
390 },
391 {
392 "include": "#core_traits"
393 },
394 {
395 "include": "#std_traits"
396 },
397 {
398 "include": "#type_params"
399 },
400 {
401 "include": "#core_types"
402 },
403 {
404 "include": "#pub"
405 },
406 {
407 "include": "#where"
408 }
409 ]
410 },
411 {
412 "comment": "Type alias",
413 "begin": "\\b(type)\\s+([a-zA-Z_][a-zA-Z0-9_]*)",
414 "end": ";",
415 "beginCaptures": {
416 "1": {
417 "name": "storage.type.rust"
418 },
419 "2": {
420 "name": "entity.name.type.rust"
421 }
422 },
423 "patterns": [
424 {
425 "include": "#block_comment"
426 },
427 {
428 "include": "#line_comment"
429 },
430 {
431 "include": "#sigils"
432 },
433 {
434 "include": "#mut"
435 },
436 {
437 "include": "#dyn"
438 },
439 {
440 "include": "#impl"
441 },
442 {
443 "include": "#lifetime"
444 },
445 {
446 "include": "#ref_lifetime"
447 },
448 {
449 "include": "#core_types"
450 },
451 {
452 "include": "#core_marker"
453 },
454 {
455 "include": "#core_traits"
456 },
457 {
458 "include": "#std_types"
459 },
460 {
461 "include": "#std_traits"
462 },
463 {
464 "include": "#type_params"
465 }
466 ]
467 }
468 ],
469 "repository": {
470 "block_doc_comment": {
471 "comment": "Block documentation comment",
472 "name": "comment.block.documentation.rust",
473 "begin": "/\\*[\\*!](?![\\*/])",
474 "end": "\\*/",
475 "patterns": [
476 {
477 "include": "#block_doc_comment"
478 },
479 {
480 "include": "#block_comment"
481 }
482 ]
483 },
484 "block_comment": {
485 "comment": "Block comment",
486 "name": "comment.block.rust",
487 "begin": "/\\*",
488 "end": "\\*/",
489 "patterns": [
490 {
491 "include": "#block_doc_comment"
492 },
493 {
494 "include": "#block_comment"
495 }
496 ]
497 },
498 "line_doc_comment": {
499 "comment": "Single-line documentation comment",
500 "name": "comment.line.documentation.rust",
501 "begin": "//[!/](?=[^/])",
502 "end": "$"
503 },
504 "line_comment": {
505 "comment": "Single-line comment",
506 "name": "comment.line.double-slash.rust",
507 "begin": "//",
508 "end": "$"
509 },
510 "escaped_character": {
511 "name": "constant.character.escape.rust",
512 "match": "\\\\(x[0-9A-Fa-f]{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)"
513 },
514 "string_literal": {
515 "comment": "Double-quote string literal",
516 "name": "string.quoted.double.rust",
517 "begin": "b?\"",
518 "end": "\"",
519 "patterns": [
520 {
521 "include": "#escaped_character"
522 }
523 ]
524 },
525 "raw_string_literal": {
526 "comment": "Raw double-quote string literal",
527 "name": "string.quoted.double.raw.rust",
528 "begin": "b?r(#*)\"",
529 "end": "\"\\1"
530 },
531 "sigils": {
532 "comment": "Sigil",
533 "name": "keyword.operator.sigil.rust",
534 "match": "[&*](?=[a-zA-Z0-9_\\(\\[\\|\\\"]+)"
535 },
536 "self": {
537 "comment": "Self variable",
538 "name": "variable.language.rust",
539 "match": "\\bself\\b"
540 },
541 "mut": {
542 "comment": "Mutable storage modifier",
543 "name": "storage.modifier.mut.rust",
544 "match": "\\bmut\\b"
545 },
546 "dyn": {
547 "comment": "Dynamic modifier",
548 "name": "storage.modifier.dyn.rust",
549 "match": "\\bdyn\\b"
550 },
551 "impl": {
552 "comment": "Existential type modifier",
553 "name": "storage.modifier.impl.rust",
554 "match": "\\bimpl\\b"
555 },
556 "box": {
557 "comment": "Box storage modifier",
558 "name": "storage.modifier.box.rust",
559 "match": "\\bbox\\b"
560 },
561 "const": {
562 "comment": "Const storage modifier",
563 "name": "storage.modifier.const.rust",
564 "match": "\\bconst\\b"
565 },
566 "pub": {
567 "comment": "Visibility modifier",
568 "name": "storage.modifier.visibility.rust",
569 "match": "\\bpub\\b"
570 },
571 "unsafe": {
572 "comment": "Unsafe code keyword",
573 "name": "keyword.other.unsafe.rust",
574 "match": "\\bunsafe\\b"
575 },
576 "where": {
577 "comment": "Generic where clause",
578 "name": "keyword.other.where.rust",
579 "match": "\\bwhere\\b"
580 },
581 "lifetime": {
582 "comment": "Named lifetime",
583 "name": "storage.modifier.lifetime.rust",
584 "match": "'([a-zA-Z_][a-zA-Z0-9_]*)\\b"
585 },
586 "ref_lifetime": {
587 "comment": "Reference with named lifetime",
588 "match": "(&)('[a-zA-Z_][a-zA-Z0-9_]*)\\b",
589 "captures": {
590 "1": {
591 "name": "keyword.operator.sigil.rust"
592 },
593 "2": {
594 "name": "storage.modifier.lifetime.rust"
595 }
596 }
597 },
598 "core_types": {
599 "comment": "Built-in/core type",
600 "name": "support.type.primitive.rust",
601 "match": "\\b(bool|char|usize|isize|u8|u16|u32|u64|u128|i8|i16|i32|i64|i128|f32|f64|str|Self)\\b"
602 },
603 "core_vars": {
604 "comment": "Core type variant",
605 "name": "support.constant.core.rust",
606 "match": "\\b(Some|None|Ok|Err)\\b"
607 },
608 "core_marker": {
609 "comment": "Core trait (marker)",
610 "name": "entity.name.type.marker.rust",
611 "match": "\\b(Copy|Send|Sized|Sync)\\b"
612 },
613 "core_traits": {
614 "comment": "Core trait",
615 "name": "entity.name.type.core.rust",
616 "match": "\\b(Drop|Fn|FnMut|FnOnce|Clone|PartialEq|PartialOrd|Eq|Ord|AsRef|AsMut|Into|From|Default|Iterator|Extend|IntoIterator|DoubleEndedIterator|ExactSizeIterator)\\b"
617 },
618 "std_types": {
619 "comment": "Standard library type",
620 "name": "entity.name.type.class.std.rust",
621 "match": "\\b(Box|String|Vec|Path|PathBuf|Option|Result)\\b"
622 },
623 "std_traits": {
624 "comment": "Standard library trait",
625 "name": "entity.name.type.std.rust",
626 "match": "\\b(ToOwned|ToString)\\b"
627 },
628 "type": {
629 "comment": "A type",
630 "name": "entity.name.type.rust",
631 "match": "\\b([A-Za-z][_A-Za-z0-9]*|_[_A-Za-z0-9]+)\\b"
632 },
633 "type_params": {
634 "comment": "Type parameters",
635 "name": "meta.type_params.rust",
636 "begin": "<(?![=<])",
637 "end": "(?<![-])>",
638 "patterns": [
639 {
640 "include": "#block_comment"
641 },
642 {
643 "include": "#line_comment"
644 },
645 {
646 "include": "#sigils"
647 },
648 {
649 "include": "#mut"
650 },
651 {
652 "include": "#dyn"
653 },
654 {
655 "include": "#impl"
656 },
657 {
658 "include": "#lifetime"
659 },
660 {
661 "include": "#core_types"
662 },
663 {
664 "include": "#core_marker"
665 },
666 {
667 "include": "#core_traits"
668 },
669 {
670 "include": "#std_types"
671 },
672 {
673 "include": "#std_traits"
674 },
675 {
676 "include": "#type_params"
677 }
678 ]
679 }
680 }
681} \ No newline at end of file
diff --git a/editors/code/src/cargo.ts b/editors/code/src/cargo.ts
index a328ba9bd..6a41873d0 100644
--- a/editors/code/src/cargo.ts
+++ b/editors/code/src/cargo.ts
@@ -1,6 +1,9 @@
1import * as cp from 'child_process'; 1import * as cp from 'child_process';
2import * as os from 'os';
3import * as path from 'path';
2import * as readline from 'readline'; 4import * as readline from 'readline';
3import { OutputChannel } from 'vscode'; 5import { OutputChannel } from 'vscode';
6import { isValidExecutable } from './util';
4 7
5interface CompilationArtifact { 8interface CompilationArtifact {
6 fileName: string; 9 fileName: string;
@@ -10,17 +13,9 @@ interface CompilationArtifact {
10} 13}
11 14
12export class Cargo { 15export class Cargo {
13 rootFolder: string; 16 constructor(readonly rootFolder: string, readonly output: OutputChannel) { }
14 env?: Record<string, string>;
15 output: OutputChannel;
16
17 public constructor(cargoTomlFolder: string, output: OutputChannel, env: Record<string, string> | undefined = undefined) {
18 this.rootFolder = cargoTomlFolder;
19 this.output = output;
20 this.env = env;
21 }
22 17
23 public async artifactsFromArgs(cargoArgs: string[]): Promise<CompilationArtifact[]> { 18 private async artifactsFromArgs(cargoArgs: string[]): Promise<CompilationArtifact[]> {
24 const artifacts: CompilationArtifact[] = []; 19 const artifacts: CompilationArtifact[] = [];
25 20
26 try { 21 try {
@@ -37,17 +32,13 @@ export class Cargo {
37 isTest: message.profile.test 32 isTest: message.profile.test
38 }); 33 });
39 } 34 }
40 } 35 } else if (message.reason === 'compiler-message') {
41 else if (message.reason === 'compiler-message') {
42 this.output.append(message.message.rendered); 36 this.output.append(message.message.rendered);
43 } 37 }
44 }, 38 },
45 stderr => { 39 stderr => this.output.append(stderr),
46 this.output.append(stderr);
47 }
48 ); 40 );
49 } 41 } catch (err) {
50 catch (err) {
51 this.output.show(true); 42 this.output.show(true);
52 throw new Error(`Cargo invocation has failed: ${err}`); 43 throw new Error(`Cargo invocation has failed: ${err}`);
53 } 44 }
@@ -55,11 +46,27 @@ export class Cargo {
55 return artifacts; 46 return artifacts;
56 } 47 }
57 48
58 public async executableFromArgs(args: string[]): Promise<string> { 49 async executableFromArgs(args: readonly string[]): Promise<string> {
59 const cargoArgs = [...args]; // to remain args unchanged 50 const cargoArgs = [...args, "--message-format=json"];
60 cargoArgs.push("--message-format=json");
61 51
62 const artifacts = await this.artifactsFromArgs(cargoArgs); 52 // arguments for a runnable from the quick pick should be updated.
53 // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_code_lens
54 switch (cargoArgs[0]) {
55 case "run": cargoArgs[0] = "build"; break;
56 case "test": {
57 if (cargoArgs.indexOf("--no-run") === -1) {
58 cargoArgs.push("--no-run");
59 }
60 break;
61 }
62 }
63
64 let artifacts = await this.artifactsFromArgs(cargoArgs);
65 if (cargoArgs[0] === "test") {
66 // for instance, `crates\rust-analyzer\tests\heavy_tests\main.rs` tests
67 // produce 2 artifacts: {"kind": "bin"} and {"kind": "test"}
68 artifacts = artifacts.filter(a => a.isTest);
69 }
63 70
64 if (artifacts.length === 0) { 71 if (artifacts.length === 0) {
65 throw new Error('No compilation artifacts'); 72 throw new Error('No compilation artifacts');
@@ -70,24 +77,27 @@ export class Cargo {
70 return artifacts[0].fileName; 77 return artifacts[0].fileName;
71 } 78 }
72 79
73 runCargo( 80 private runCargo(
74 cargoArgs: string[], 81 cargoArgs: string[],
75 onStdoutJson: (obj: any) => void, 82 onStdoutJson: (obj: any) => void,
76 onStderrString: (data: string) => void 83 onStderrString: (data: string) => void
77 ): Promise<number> { 84 ): Promise<number> {
78 return new Promise<number>((resolve, reject) => { 85 return new Promise((resolve, reject) => {
79 const cargo = cp.spawn('cargo', cargoArgs, { 86 let cargoPath;
87 try {
88 cargoPath = getCargoPathOrFail();
89 } catch (err) {
90 return reject(err);
91 }
92
93 const cargo = cp.spawn(cargoPath, cargoArgs, {
80 stdio: ['ignore', 'pipe', 'pipe'], 94 stdio: ['ignore', 'pipe', 'pipe'],
81 cwd: this.rootFolder, 95 cwd: this.rootFolder
82 env: this.env,
83 }); 96 });
84 97
85 cargo.on('error', err => { 98 cargo.on('error', err => reject(new Error(`could not launch cargo: ${err}`)));
86 reject(new Error(`could not launch cargo: ${err}`)); 99
87 }); 100 cargo.stderr.on('data', chunk => onStderrString(chunk.toString()));
88 cargo.stderr.on('data', chunk => {
89 onStderrString(chunk.toString());
90 });
91 101
92 const rl = readline.createInterface({ input: cargo.stdout }); 102 const rl = readline.createInterface({ input: cargo.stdout });
93 rl.on('line', line => { 103 rl.on('line', line => {
@@ -103,4 +113,28 @@ export class Cargo {
103 }); 113 });
104 }); 114 });
105 } 115 }
106} \ No newline at end of file 116}
117
118// Mirrors `ra_env::get_path_for_executable` implementation
119function getCargoPathOrFail(): string {
120 const envVar = process.env.CARGO;
121 const executableName = "cargo";
122
123 if (envVar) {
124 if (isValidExecutable(envVar)) return envVar;
125
126 throw new Error(`\`${envVar}\` environment variable points to something that's not a valid executable`);
127 }
128
129 if (isValidExecutable(executableName)) return executableName;
130
131 const standardLocation = path.join(os.homedir(), '.cargo', 'bin', executableName);
132
133 if (isValidExecutable(standardLocation)) return standardLocation;
134
135 throw new Error(
136 `Failed to find \`${executableName}\` executable. ` +
137 `Make sure \`${executableName}\` is in \`$PATH\`, ` +
138 `or set \`${envVar}\` to point to a valid executable.`
139 );
140}
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index cffdcf11a..fac1a0be3 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -31,24 +31,79 @@ export function createClient(serverPath: string, cwd: string): lc.LanguageClient
31 const res = await next(document, token); 31 const res = await next(document, token);
32 if (res === undefined) throw new Error('busy'); 32 if (res === undefined) throw new Error('busy');
33 return res; 33 return res;
34 },
35 async provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken, _next: lc.ProvideCodeActionsSignature) {
36 const params: lc.CodeActionParams = {
37 textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
38 range: client.code2ProtocolConverter.asRange(range),
39 context: client.code2ProtocolConverter.asCodeActionContext(context)
40 };
41 return client.sendRequest(lc.CodeActionRequest.type, params, token).then((values) => {
42 if (values === null) return undefined;
43 const result: (vscode.CodeAction | vscode.Command)[] = [];
44 for (const item of values) {
45 if (lc.CodeAction.is(item)) {
46 const action = client.protocol2CodeConverter.asCodeAction(item);
47 if (isSnippetEdit(item)) {
48 action.command = {
49 command: "rust-analyzer.applySnippetWorkspaceEdit",
50 title: "",
51 arguments: [action.edit],
52 };
53 action.edit = undefined;
54 }
55 result.push(action);
56 } else {
57 const command = client.protocol2CodeConverter.asCommand(item);
58 result.push(command);
59 }
60 }
61 return result;
62 },
63 (_error) => undefined
64 );
34 } 65 }
66
35 } as any 67 } as any
36 }; 68 };
37 69
38 const res = new lc.LanguageClient( 70 const client = new lc.LanguageClient(
39 'rust-analyzer', 71 'rust-analyzer',
40 'Rust Analyzer Language Server', 72 'Rust Analyzer Language Server',
41 serverOptions, 73 serverOptions,
42 clientOptions, 74 clientOptions,
43 ); 75 );
44 76
45 // To turn on all proposed features use: res.registerProposedFeatures(); 77 // To turn on all proposed features use: client.registerProposedFeatures();
46 // Here we want to enable CallHierarchyFeature and SemanticTokensFeature 78 // Here we want to enable CallHierarchyFeature and SemanticTokensFeature
47 // since they are available on stable. 79 // since they are available on stable.
48 // Note that while these features are stable in vscode their LSP protocol 80 // Note that while these features are stable in vscode their LSP protocol
49 // implementations are still in the "proposed" category for 3.16. 81 // implementations are still in the "proposed" category for 3.16.
50 res.registerFeature(new CallHierarchyFeature(res)); 82 client.registerFeature(new CallHierarchyFeature(client));
51 res.registerFeature(new SemanticTokensFeature(res)); 83 client.registerFeature(new SemanticTokensFeature(client));
84 client.registerFeature(new SnippetTextEditFeature());
85
86 return client;
87}
52 88
53 return res; 89class SnippetTextEditFeature implements lc.StaticFeature {
90 fillClientCapabilities(capabilities: lc.ClientCapabilities): void {
91 const caps: any = capabilities.experimental ?? {};
92 caps.snippetTextEdit = true;
93 capabilities.experimental = caps;
94 }
95 initialize(_capabilities: lc.ServerCapabilities<any>, _documentSelector: lc.DocumentSelector | undefined): void {
96 }
97}
98
99function isSnippetEdit(action: lc.CodeAction): boolean {
100 const documentChanges = action.edit?.documentChanges ?? [];
101 for (const edit of documentChanges) {
102 if (lc.TextDocumentEdit.is(edit)) {
103 if (edit.edits.some((indel) => (indel as any).insertTextFormat === lc.InsertTextFormat.Snippet)) {
104 return true;
105 }
106 }
107 }
108 return false;
54} 109}
diff --git a/editors/code/src/color_theme.ts b/editors/code/src/color_theme.ts
deleted file mode 100644
index 5b9327b28..000000000
--- a/editors/code/src/color_theme.ts
+++ /dev/null
@@ -1,129 +0,0 @@
1import * as fs from 'fs';
2import * as jsonc from 'jsonc-parser';
3import * as path from 'path';
4import * as vscode from 'vscode';
5
6export interface TextMateRuleSettings {
7 foreground?: string;
8 background?: string;
9 fontStyle?: string;
10}
11
12export class ColorTheme {
13 private rules: Map<string, TextMateRuleSettings> = new Map();
14
15 static load(): ColorTheme {
16 // Find out current color theme
17 const themeName = vscode.workspace
18 .getConfiguration('workbench')
19 .get('colorTheme');
20
21 if (typeof themeName !== 'string') {
22 // console.warn('workbench.colorTheme is', themeName)
23 return new ColorTheme();
24 }
25 return loadThemeNamed(themeName);
26 }
27
28 static fromRules(rules: TextMateRule[]): ColorTheme {
29 const res = new ColorTheme();
30 for (const rule of rules) {
31 const scopes = typeof rule.scope === 'undefined'
32 ? []
33 : typeof rule.scope === 'string'
34 ? [rule.scope]
35 : rule.scope;
36
37 for (const scope of scopes) {
38 res.rules.set(scope, rule.settings);
39 }
40 }
41 return res;
42 }
43
44 lookup(scopes: string[]): TextMateRuleSettings {
45 let res: TextMateRuleSettings = {};
46 for (const scope of scopes) {
47 this.rules.forEach((value, key) => {
48 if (scope.startsWith(key)) {
49 res = mergeRuleSettings(res, value);
50 }
51 });
52 }
53 return res;
54 }
55
56 mergeFrom(other: ColorTheme) {
57 other.rules.forEach((value, key) => {
58 const merged = mergeRuleSettings(this.rules.get(key), value);
59 this.rules.set(key, merged);
60 });
61 }
62}
63
64function loadThemeNamed(themeName: string): ColorTheme {
65 function isTheme(extension: vscode.Extension<unknown>): boolean {
66 return (
67 extension.extensionKind === vscode.ExtensionKind.UI &&
68 extension.packageJSON.contributes &&
69 extension.packageJSON.contributes.themes
70 );
71 }
72
73 const themePaths: string[] = vscode.extensions.all
74 .filter(isTheme)
75 .flatMap(
76 ext => ext.packageJSON.contributes.themes
77 .filter((it: any) => (it.id || it.label) === themeName)
78 .map((it: any) => path.join(ext.extensionPath, it.path))
79 );
80
81 const res = new ColorTheme();
82 for (const themePath of themePaths) {
83 res.mergeFrom(loadThemeFile(themePath));
84 }
85
86 const globalCustomizations: any = vscode.workspace.getConfiguration('editor').get('tokenColorCustomizations');
87 res.mergeFrom(ColorTheme.fromRules(globalCustomizations?.textMateRules ?? []));
88
89 const themeCustomizations: any = vscode.workspace.getConfiguration('editor.tokenColorCustomizations').get(`[${themeName}]`);
90 res.mergeFrom(ColorTheme.fromRules(themeCustomizations?.textMateRules ?? []));
91
92
93 return res;
94}
95
96function loadThemeFile(themePath: string): ColorTheme {
97 let text;
98 try {
99 text = fs.readFileSync(themePath, 'utf8');
100 } catch {
101 return new ColorTheme();
102 }
103 const obj = jsonc.parse(text);
104 const tokenColors: TextMateRule[] = obj?.tokenColors ?? [];
105 const res = ColorTheme.fromRules(tokenColors);
106
107 for (const include of obj?.include ?? []) {
108 const includePath = path.join(path.dirname(themePath), include);
109 res.mergeFrom(loadThemeFile(includePath));
110 }
111
112 return res;
113}
114
115interface TextMateRule {
116 scope: string | string[];
117 settings: TextMateRuleSettings;
118}
119
120function mergeRuleSettings(
121 defaultSetting: TextMateRuleSettings | undefined,
122 override: TextMateRuleSettings,
123): TextMateRuleSettings {
124 return {
125 foreground: override.foreground ?? defaultSetting?.foreground,
126 background: override.background ?? defaultSetting?.background,
127 fontStyle: override.fontStyle ?? defaultSetting?.fontStyle,
128 };
129}
diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts
index bdb7fc3b0..e5ed77e32 100644
--- a/editors/code/src/commands/index.ts
+++ b/editors/code/src/commands/index.ts
@@ -4,6 +4,7 @@ import * as ra from '../rust-analyzer-api';
4 4
5import { Ctx, Cmd } from '../ctx'; 5import { Ctx, Cmd } from '../ctx';
6import * as sourceChange from '../source_change'; 6import * as sourceChange from '../source_change';
7import { assert } from '../util';
7 8
8export * from './analyzer_status'; 9export * from './analyzer_status';
9export * from './matching_brace'; 10export * from './matching_brace';
@@ -51,3 +52,58 @@ export function selectAndApplySourceChange(ctx: Ctx): Cmd {
51 } 52 }
52 }; 53 };
53} 54}
55
56export function applySnippetWorkspaceEditCommand(_ctx: Ctx): Cmd {
57 return async (edit: vscode.WorkspaceEdit) => {
58 await applySnippetWorkspaceEdit(edit);
59 };
60}
61
62export async function applySnippetWorkspaceEdit(edit: vscode.WorkspaceEdit) {
63 assert(edit.entries().length === 1, `bad ws edit: ${JSON.stringify(edit)}`);
64 const [uri, edits] = edit.entries()[0];
65
66 const editor = vscode.window.visibleTextEditors.find((it) => it.document.uri.toString() === uri.toString());
67 if (!editor) return;
68
69 let selection: vscode.Selection | undefined = undefined;
70 let lineDelta = 0;
71 await editor.edit((builder) => {
72 for (const indel of edits) {
73 const parsed = parseSnippet(indel.newText);
74 if (parsed) {
75 const [newText, [placeholderStart, placeholderLength]] = parsed;
76 const prefix = newText.substr(0, placeholderStart);
77 const lastNewline = prefix.lastIndexOf('\n');
78
79 const startLine = indel.range.start.line + lineDelta + countLines(prefix);
80 const startColumn = lastNewline === -1 ?
81 indel.range.start.character + placeholderStart
82 : prefix.length - lastNewline - 1;
83 const endColumn = startColumn + placeholderLength;
84 selection = new vscode.Selection(
85 new vscode.Position(startLine, startColumn),
86 new vscode.Position(startLine, endColumn),
87 );
88 builder.replace(indel.range, newText);
89 } else {
90 lineDelta = countLines(indel.newText) - (indel.range.end.line - indel.range.start.line);
91 builder.replace(indel.range, indel.newText);
92 }
93 }
94 });
95 if (selection) editor.selection = selection;
96}
97
98function parseSnippet(snip: string): [string, [number, number]] | undefined {
99 const m = snip.match(/\$(0|\{0:([^}]*)\})/);
100 if (!m) return undefined;
101 const placeholder = m[2] ?? "";
102 const range: [number, number] = [m.index!!, placeholder.length];
103 const insert = snip.replace(m[0], placeholder);
104 return [insert, range];
105}
106
107function countLines(text: string): number {
108 return (text.match(/\n/g) || []).length;
109}
diff --git a/editors/code/src/commands/join_lines.ts b/editors/code/src/commands/join_lines.ts
index de0614653..0bf1ee6e6 100644
--- a/editors/code/src/commands/join_lines.ts
+++ b/editors/code/src/commands/join_lines.ts
@@ -1,7 +1,7 @@
1import * as ra from '../rust-analyzer-api'; 1import * as ra from '../rust-analyzer-api';
2import * as lc from 'vscode-languageclient';
2 3
3import { Ctx, Cmd } from '../ctx'; 4import { Ctx, Cmd } from '../ctx';
4import { applySourceChange } from '../source_change';
5 5
6export function joinLines(ctx: Ctx): Cmd { 6export function joinLines(ctx: Ctx): Cmd {
7 return async () => { 7 return async () => {
@@ -9,10 +9,14 @@ export function joinLines(ctx: Ctx): Cmd {
9 const client = ctx.client; 9 const client = ctx.client;
10 if (!editor || !client) return; 10 if (!editor || !client) return;
11 11
12 const change = await client.sendRequest(ra.joinLines, { 12 const items: lc.TextEdit[] = await client.sendRequest(ra.joinLines, {
13 range: client.code2ProtocolConverter.asRange(editor.selection), 13 ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)),
14 textDocument: { uri: editor.document.uri.toString() }, 14 textDocument: { uri: editor.document.uri.toString() },
15 }); 15 });
16 await applySourceChange(ctx, change); 16 editor.edit((builder) => {
17 client.protocol2CodeConverter.asTextEdits(items).forEach((edit) => {
18 builder.replace(edit.range, edit.newText);
19 });
20 });
17 }; 21 };
18} 22}
diff --git a/editors/code/src/commands/on_enter.ts b/editors/code/src/commands/on_enter.ts
index 285849db7..a7871c31e 100644
--- a/editors/code/src/commands/on_enter.ts
+++ b/editors/code/src/commands/on_enter.ts
@@ -1,8 +1,8 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2import * as ra from '../rust-analyzer-api'; 2import * as ra from '../rust-analyzer-api';
3 3
4import { applySourceChange } from '../source_change';
5import { Cmd, Ctx } from '../ctx'; 4import { Cmd, Ctx } from '../ctx';
5import { applySnippetWorkspaceEdit } from '.';
6 6
7async function handleKeypress(ctx: Ctx) { 7async function handleKeypress(ctx: Ctx) {
8 const editor = ctx.activeRustEditor; 8 const editor = ctx.activeRustEditor;
@@ -21,7 +21,8 @@ async function handleKeypress(ctx: Ctx) {
21 }); 21 });
22 if (!change) return false; 22 if (!change) return false;
23 23
24 await applySourceChange(ctx, change); 24 const workspaceEdit = client.protocol2CodeConverter.asWorkspaceEdit(change);
25 await applySnippetWorkspaceEdit(workspaceEdit);
25 return true; 26 return true;
26} 27}
27 28
diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts
index d77e8188c..0bd30fb07 100644
--- a/editors/code/src/commands/runnables.ts
+++ b/editors/code/src/commands/runnables.ts
@@ -1,43 +1,93 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2import * as lc from 'vscode-languageclient'; 2import * as lc from 'vscode-languageclient';
3import * as ra from '../rust-analyzer-api'; 3import * as ra from '../rust-analyzer-api';
4import * as os from "os";
5 4
6import { Ctx, Cmd } from '../ctx'; 5import { Ctx, Cmd } from '../ctx';
7import { Cargo } from '../cargo'; 6import { startDebugSession, getDebugConfiguration } from '../debug';
8 7
9export function run(ctx: Ctx): Cmd { 8const quickPickButtons = [{ iconPath: new vscode.ThemeIcon("save"), tooltip: "Save as a launch.json configurtation." }];
10 let prevRunnable: RunnableQuickPick | undefined;
11 9
12 return async () => { 10async function selectRunnable(ctx: Ctx, prevRunnable?: RunnableQuickPick, debuggeeOnly = false, showButtons: boolean = true): Promise<RunnableQuickPick | undefined> {
13 const editor = ctx.activeRustEditor; 11 const editor = ctx.activeRustEditor;
14 const client = ctx.client; 12 const client = ctx.client;
15 if (!editor || !client) return; 13 if (!editor || !client) return;
16 14
17 const textDocument: lc.TextDocumentIdentifier = { 15 const textDocument: lc.TextDocumentIdentifier = {
18 uri: editor.document.uri.toString(), 16 uri: editor.document.uri.toString(),
19 }; 17 };
20 18
21 const runnables = await client.sendRequest(ra.runnables, { 19 const runnables = await client.sendRequest(ra.runnables, {
22 textDocument, 20 textDocument,
23 position: client.code2ProtocolConverter.asPosition( 21 position: client.code2ProtocolConverter.asPosition(
24 editor.selection.active, 22 editor.selection.active,
25 ), 23 ),
26 }); 24 });
27 const items: RunnableQuickPick[] = []; 25 const items: RunnableQuickPick[] = [];
28 if (prevRunnable) { 26 if (prevRunnable) {
29 items.push(prevRunnable); 27 items.push(prevRunnable);
28 }
29 for (const r of runnables) {
30 if (
31 prevRunnable &&
32 JSON.stringify(prevRunnable.runnable) === JSON.stringify(r)
33 ) {
34 continue;
30 } 35 }
31 for (const r of runnables) { 36
32 if ( 37 if (debuggeeOnly && (r.label.startsWith('doctest') || r.label.startsWith('cargo'))) {
33 prevRunnable && 38 continue;
34 JSON.stringify(prevRunnable.runnable) === JSON.stringify(r)
35 ) {
36 continue;
37 }
38 items.push(new RunnableQuickPick(r));
39 } 39 }
40 const item = await vscode.window.showQuickPick(items); 40 items.push(new RunnableQuickPick(r));
41 }
42
43 if (items.length === 0) {
44 // it is the debug case, run always has at least 'cargo check ...'
45 // see crates\rust-analyzer\src\main_loop\handlers.rs, handle_runnables
46 vscode.window.showErrorMessage("There's no debug target!");
47 return;
48 }
49
50 return await new Promise((resolve) => {
51 const disposables: vscode.Disposable[] = [];
52 const close = (result?: RunnableQuickPick) => {
53 resolve(result);
54 disposables.forEach(d => d.dispose());
55 };
56
57 const quickPick = vscode.window.createQuickPick<RunnableQuickPick>();
58 quickPick.items = items;
59 quickPick.title = "Select Runnable";
60 if (showButtons) {
61 quickPick.buttons = quickPickButtons;
62 }
63 disposables.push(
64 quickPick.onDidHide(() => close()),
65 quickPick.onDidAccept(() => close(quickPick.selectedItems[0])),
66 quickPick.onDidTriggerButton((_button) => {
67 (async () => await makeDebugConfig(ctx, quickPick.activeItems[0]))();
68 close();
69 }),
70 quickPick.onDidChangeActive((active) => {
71 if (showButtons && active.length > 0) {
72 if (active[0].label.startsWith('cargo')) {
73 // save button makes no sense for `cargo test` or `cargo check`
74 quickPick.buttons = [];
75 } else if (quickPick.buttons.length === 0) {
76 quickPick.buttons = quickPickButtons;
77 }
78 }
79 }),
80 quickPick
81 );
82 quickPick.show();
83 });
84}
85
86export function run(ctx: Ctx): Cmd {
87 let prevRunnable: RunnableQuickPick | undefined;
88
89 return async () => {
90 const item = await selectRunnable(ctx, prevRunnable);
41 if (!item) return; 91 if (!item) return;
42 92
43 item.detail = 'rerun'; 93 item.detail = 'rerun';
@@ -64,71 +114,54 @@ export function runSingle(ctx: Ctx): Cmd {
64 }; 114 };
65} 115}
66 116
67function getLldbDebugConfig(config: ra.Runnable, sourceFileMap: Record<string, string>): vscode.DebugConfiguration { 117export function debug(ctx: Ctx): Cmd {
68 return { 118 let prevDebuggee: RunnableQuickPick | undefined;
69 type: "lldb",
70 request: "launch",
71 name: config.label,
72 cargo: {
73 args: config.args,
74 },
75 args: config.extraArgs,
76 cwd: config.cwd,
77 sourceMap: sourceFileMap
78 };
79}
80
81const debugOutput = vscode.window.createOutputChannel("Debug");
82 119
83async function getCppvsDebugConfig(config: ra.Runnable, sourceFileMap: Record<string, string>): Promise<vscode.DebugConfiguration> { 120 return async () => {
84 debugOutput.clear(); 121 const item = await selectRunnable(ctx, prevDebuggee, true);
85 122 if (!item) return;
86 const cargo = new Cargo(config.cwd || '.', debugOutput);
87 const executable = await cargo.executableFromArgs(config.args);
88 123
89 // if we are here, there were no compilation errors. 124 item.detail = 'restart';
90 return { 125 prevDebuggee = item;
91 type: (os.platform() === "win32") ? "cppvsdbg" : 'cppdbg', 126 return await startDebugSession(ctx, item.runnable);
92 request: "launch",
93 name: config.label,
94 program: executable,
95 args: config.extraArgs,
96 cwd: config.cwd,
97 sourceFileMap: sourceFileMap,
98 }; 127 };
99} 128}
100 129
101export function debugSingle(ctx: Ctx): Cmd { 130export function debugSingle(ctx: Ctx): Cmd {
102 return async (config: ra.Runnable) => { 131 return async (config: ra.Runnable) => {
103 const editor = ctx.activeRustEditor; 132 await startDebugSession(ctx, config);
104 if (!editor) return; 133 };
134}
105 135
106 const lldbId = "vadimcn.vscode-lldb"; 136async function makeDebugConfig(ctx: Ctx, item: RunnableQuickPick): Promise<void> {
107 const cpptoolsId = "ms-vscode.cpptools"; 137 const scope = ctx.activeRustEditor?.document.uri;
138 if (!scope) return;
108 139
109 const debugEngineId = ctx.config.debug.engine; 140 const debugConfig = await getDebugConfiguration(ctx, item.runnable);
110 let debugEngine = null; 141 if (!debugConfig) return;
111 if (debugEngineId === "auto") {
112 debugEngine = vscode.extensions.getExtension(lldbId);
113 if (!debugEngine) {
114 debugEngine = vscode.extensions.getExtension(cpptoolsId);
115 }
116 }
117 else {
118 debugEngine = vscode.extensions.getExtension(debugEngineId);
119 }
120 142
121 if (!debugEngine) { 143 const wsLaunchSection = vscode.workspace.getConfiguration("launch", scope);
122 vscode.window.showErrorMessage(`Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=${lldbId})` 144 const configurations = wsLaunchSection.get<any[]>("configurations") || [];
123 + ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=${cpptoolsId}) extension for debugging.`); 145
124 return; 146 const index = configurations.findIndex(c => c.name === debugConfig.name);
125 } 147 if (index !== -1) {
148 const answer = await vscode.window.showErrorMessage(`Launch configuration '${debugConfig.name}' already exists!`, 'Cancel', 'Update');
149 if (answer === "Cancel") return;
150
151 configurations[index] = debugConfig;
152 } else {
153 configurations.push(debugConfig);
154 }
155
156 await wsLaunchSection.update("configurations", configurations);
157}
126 158
127 const debugConfig = lldbId === debugEngine.id 159export function newDebugConfig(ctx: Ctx): Cmd {
128 ? getLldbDebugConfig(config, ctx.config.debug.sourceFileMap) 160 return async () => {
129 : await getCppvsDebugConfig(config, ctx.config.debug.sourceFileMap); 161 const item = await selectRunnable(ctx, undefined, true, false);
162 if (!item) return;
130 163
131 return vscode.debug.startDebugging(undefined, debugConfig); 164 await makeDebugConfig(ctx, item);
132 }; 165 };
133} 166}
134 167
diff --git a/editors/code/src/commands/ssr.ts b/editors/code/src/commands/ssr.ts
index 6fee051fd..4ef8cdf04 100644
--- a/editors/code/src/commands/ssr.ts
+++ b/editors/code/src/commands/ssr.ts
@@ -11,7 +11,7 @@ export function ssr(ctx: Ctx): Cmd {
11 11
12 const options: vscode.InputBoxOptions = { 12 const options: vscode.InputBoxOptions = {
13 value: "() ==>> ()", 13 value: "() ==>> ()",
14 prompt: "EnteR request, for example 'Foo($a:expr) ==> Foo::new($a)' ", 14 prompt: "Enter request, for example 'Foo($a:expr) ==> Foo::new($a)' ",
15 validateInput: async (x: string) => { 15 validateInput: async (x: string) => {
16 try { 16 try {
17 await client.sendRequest(ra.ssr, { query: x, parseOnly: true }); 17 await client.sendRequest(ra.ssr, { query: x, parseOnly: true });
diff --git a/editors/code/src/commands/syntax_tree.ts b/editors/code/src/commands/syntax_tree.ts
index cfcf47b2f..a5446c327 100644
--- a/editors/code/src/commands/syntax_tree.ts
+++ b/editors/code/src/commands/syntax_tree.ts
@@ -206,7 +206,7 @@ class AstInspector implements vscode.HoverProvider, vscode.DefinitionProvider, D
206 } 206 }
207 207
208 private parseRustTextRange(doc: vscode.TextDocument, astLine: string): undefined | vscode.Range { 208 private parseRustTextRange(doc: vscode.TextDocument, astLine: string): undefined | vscode.Range {
209 const parsedRange = /\[(\d+); (\d+)\)/.exec(astLine); 209 const parsedRange = /(\d+)\.\.(\d+)/.exec(astLine);
210 if (!parsedRange) return; 210 if (!parsedRange) return;
211 211
212 const [begin, end] = parsedRange 212 const [begin, end] = parsedRange
@@ -225,7 +225,7 @@ class AstInspector implements vscode.HoverProvider, vscode.DefinitionProvider, D
225 return doc.positionAt(targetOffset); 225 return doc.positionAt(targetOffset);
226 } 226 }
227 227
228 // Shitty workaround for crlf line endings 228 // Dirty workaround for crlf line endings
229 // We are still in this prehistoric era of carriage returns here... 229 // We are still in this prehistoric era of carriage returns here...
230 230
231 let line = 0; 231 let line = 0;
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 110e54180..ee294fbe3 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -16,6 +16,10 @@ export class Config {
16 "files", 16 "files",
17 "highlighting", 17 "highlighting",
18 "updates.channel", 18 "updates.channel",
19 "lens.enable",
20 "lens.run",
21 "lens.debug",
22 "lens.implementations",
19 ] 23 ]
20 .map(opt => `${this.rootSection}.${opt}`); 24 .map(opt => `${this.rootSection}.${opt}`);
21 25
@@ -94,6 +98,7 @@ export class Config {
94 98
95 get inlayHints() { 99 get inlayHints() {
96 return { 100 return {
101 enable: this.get<boolean>("inlayHints.enable"),
97 typeHints: this.get<boolean>("inlayHints.typeHints"), 102 typeHints: this.get<boolean>("inlayHints.typeHints"),
98 parameterHints: this.get<boolean>("inlayHints.parameterHints"), 103 parameterHints: this.get<boolean>("inlayHints.parameterHints"),
99 chainingHints: this.get<boolean>("inlayHints.chainingHints"), 104 chainingHints: this.get<boolean>("inlayHints.chainingHints"),
@@ -108,10 +113,23 @@ export class Config {
108 } 113 }
109 114
110 get debug() { 115 get debug() {
116 // "/rustc/<id>" used by suggestions only.
117 const { ["/rustc/<id>"]: _, ...sourceFileMap } = this.get<Record<string, string>>("debug.sourceFileMap");
118
111 return { 119 return {
112 engine: this.get<string>("debug.engine"), 120 engine: this.get<string>("debug.engine"),
113 sourceFileMap: this.get<Record<string, string>>("debug.sourceFileMap"), 121 engineSettings: this.get<object>("debug.engineSettings"),
122 openUpDebugPane: this.get<boolean>("debug.openUpDebugPane"),
123 sourceFileMap: sourceFileMap
114 }; 124 };
115 } 125 }
116 126
127 get lens() {
128 return {
129 enable: this.get<boolean>("lens.enable"),
130 run: this.get<boolean>("lens.run"),
131 debug: this.get<boolean>("lens.debug"),
132 implementations: this.get<boolean>("lens.implementations"),
133 };
134 }
117} 135}
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
new file mode 100644
index 000000000..d3fe588e8
--- /dev/null
+++ b/editors/code/src/debug.ts
@@ -0,0 +1,124 @@
1import * as os from "os";
2import * as vscode from 'vscode';
3import * as path from 'path';
4import * as ra from './rust-analyzer-api';
5
6import { Cargo } from './cargo';
7import { Ctx } from "./ctx";
8
9const debugOutput = vscode.window.createOutputChannel("Debug");
10type DebugConfigProvider = (config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>) => vscode.DebugConfiguration;
11
12function getLldbDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration {
13 return {
14 type: "lldb",
15 request: "launch",
16 name: config.label,
17 program: executable,
18 args: config.extraArgs,
19 cwd: config.cwd,
20 sourceMap: sourceFileMap,
21 sourceLanguages: ["rust"]
22 };
23}
24
25function getCppvsDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration {
26 return {
27 type: (os.platform() === "win32") ? "cppvsdbg" : "cppdbg",
28 request: "launch",
29 name: config.label,
30 program: executable,
31 args: config.extraArgs,
32 cwd: config.cwd,
33 sourceFileMap: sourceFileMap,
34 };
35}
36
37async function getDebugExecutable(config: ra.Runnable): Promise<string> {
38 const cargo = new Cargo(config.cwd || '.', debugOutput);
39 const executable = await cargo.executableFromArgs(config.args);
40
41 // if we are here, there were no compilation errors.
42 return executable;
43}
44
45export async function getDebugConfiguration(ctx: Ctx, config: ra.Runnable): Promise<vscode.DebugConfiguration | undefined> {
46 const editor = ctx.activeRustEditor;
47 if (!editor) return;
48
49 const knownEngines: Record<string, DebugConfigProvider> = {
50 "vadimcn.vscode-lldb": getLldbDebugConfig,
51 "ms-vscode.cpptools": getCppvsDebugConfig
52 };
53 const debugOptions = ctx.config.debug;
54
55 let debugEngine = null;
56 if (debugOptions.engine === "auto") {
57 for (var engineId in knownEngines) {
58 debugEngine = vscode.extensions.getExtension(engineId);
59 if (debugEngine) break;
60 }
61 } else {
62 debugEngine = vscode.extensions.getExtension(debugOptions.engine);
63 }
64
65 if (!debugEngine) {
66 vscode.window.showErrorMessage(`Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)`
67 + ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`);
68 return;
69 }
70
71 debugOutput.clear();
72 if (ctx.config.debug.openUpDebugPane) {
73 debugOutput.show(true);
74 }
75
76 const wsFolder = path.normalize(vscode.workspace.workspaceFolders![0].uri.fsPath); // folder exists or RA is not active.
77 function simplifyPath(p: string): string {
78 return path.normalize(p).replace(wsFolder, '${workspaceRoot}');
79 }
80
81 const executable = await getDebugExecutable(config);
82 const debugConfig = knownEngines[debugEngine.id](config, simplifyPath(executable), debugOptions.sourceFileMap);
83 if (debugConfig.type in debugOptions.engineSettings) {
84 const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
85 for (var key in settingsMap) {
86 debugConfig[key] = settingsMap[key];
87 }
88 }
89
90 if (debugConfig.name === "run binary") {
91 // The LSP side: crates\rust-analyzer\src\main_loop\handlers.rs,
92 // fn to_lsp_runnable(...) with RunnableKind::Bin
93 debugConfig.name = `run ${path.basename(executable)}`;
94 }
95
96 if (debugConfig.cwd) {
97 debugConfig.cwd = simplifyPath(debugConfig.cwd);
98 }
99
100 return debugConfig;
101}
102
103export async function startDebugSession(ctx: Ctx, config: ra.Runnable): Promise<boolean> {
104 let debugConfig: vscode.DebugConfiguration | undefined = undefined;
105 let message = "";
106
107 const wsLaunchSection = vscode.workspace.getConfiguration("launch");
108 const configurations = wsLaunchSection.get<any[]>("configurations") || [];
109
110 const index = configurations.findIndex(c => c.name === config.label);
111 if (-1 !== index) {
112 debugConfig = configurations[index];
113 message = " (from launch.json)";
114 debugOutput.clear();
115 } else {
116 debugConfig = await getDebugConfiguration(ctx, config);
117 }
118
119 if (!debugConfig) return false;
120
121 debugOutput.appendLine(`Launching debug configuration${message}:`);
122 debugOutput.appendLine(JSON.stringify(debugConfig, null, 2));
123 return vscode.debug.startDebugging(undefined, debugConfig);
124}
diff --git a/editors/code/src/inlay_hints.ts b/editors/code/src/inlay_hints.ts
index a09531797..a2b07d003 100644
--- a/editors/code/src/inlay_hints.ts
+++ b/editors/code/src/inlay_hints.ts
@@ -10,13 +10,13 @@ export function activateInlayHints(ctx: Ctx) {
10 const maybeUpdater = { 10 const maybeUpdater = {
11 updater: null as null | HintsUpdater, 11 updater: null as null | HintsUpdater,
12 async onConfigChange() { 12 async onConfigChange() {
13 if ( 13 const anyEnabled = ctx.config.inlayHints.typeHints
14 !ctx.config.inlayHints.typeHints && 14 || ctx.config.inlayHints.parameterHints
15 !ctx.config.inlayHints.parameterHints && 15 || ctx.config.inlayHints.chainingHints;
16 !ctx.config.inlayHints.chainingHints 16 const enabled = ctx.config.inlayHints.enable && anyEnabled;
17 ) { 17
18 return this.dispose(); 18 if (!enabled) return this.dispose();
19 } 19
20 await sleep(100); 20 await sleep(100);
21 if (this.updater) { 21 if (this.updater) {
22 this.updater.syncCacheAndRenderHints(); 22 this.updater.syncCacheAndRenderHints();
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index efd56a84b..8b0a9d870 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -8,10 +8,9 @@ import { activateInlayHints } from './inlay_hints';
8import { activateStatusDisplay } from './status_display'; 8import { activateStatusDisplay } from './status_display';
9import { Ctx } from './ctx'; 9import { Ctx } from './ctx';
10import { Config, NIGHTLY_TAG } from './config'; 10import { Config, NIGHTLY_TAG } from './config';
11import { log, assert } from './util'; 11import { log, assert, isValidExecutable } from './util';
12import { PersistentState } from './persistent_state'; 12import { PersistentState } from './persistent_state';
13import { fetchRelease, download } from './net'; 13import { fetchRelease, download } from './net';
14import { spawnSync } from 'child_process';
15import { activateTaskProvider } from './tasks'; 14import { activateTaskProvider } from './tasks';
16 15
17let ctx: Ctx | undefined; 16let ctx: Ctx | undefined;
@@ -78,6 +77,8 @@ export async function activate(context: vscode.ExtensionContext) {
78 ctx.registerCommand('syntaxTree', commands.syntaxTree); 77 ctx.registerCommand('syntaxTree', commands.syntaxTree);
79 ctx.registerCommand('expandMacro', commands.expandMacro); 78 ctx.registerCommand('expandMacro', commands.expandMacro);
80 ctx.registerCommand('run', commands.run); 79 ctx.registerCommand('run', commands.run);
80 ctx.registerCommand('debug', commands.debug);
81 ctx.registerCommand('newDebugConfig', commands.newDebugConfig);
81 82
82 defaultOnEnter.dispose(); 83 defaultOnEnter.dispose();
83 ctx.registerCommand('onEnter', commands.onEnter); 84 ctx.registerCommand('onEnter', commands.onEnter);
@@ -90,6 +91,7 @@ export async function activate(context: vscode.ExtensionContext) {
90 ctx.registerCommand('debugSingle', commands.debugSingle); 91 ctx.registerCommand('debugSingle', commands.debugSingle);
91 ctx.registerCommand('showReferences', commands.showReferences); 92 ctx.registerCommand('showReferences', commands.showReferences);
92 ctx.registerCommand('applySourceChange', commands.applySourceChange); 93 ctx.registerCommand('applySourceChange', commands.applySourceChange);
94 ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand);
93 ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange); 95 ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange);
94 96
95 ctx.pushCleanup(activateTaskProvider(workspaceFolder)); 97 ctx.pushCleanup(activateTaskProvider(workspaceFolder));
@@ -179,10 +181,7 @@ async function bootstrapServer(config: Config, state: PersistentState): Promise<
179 181
180 log.debug("Using server binary at", path); 182 log.debug("Using server binary at", path);
181 183
182 const res = spawnSync(path, ["--version"], { encoding: 'utf8' }); 184 if (!isValidExecutable(path)) {
183 log.debug("Checked binary availability via --version", res);
184 log.debug(res, "--version output:", res.output);
185 if (res.status !== 0) {
186 throw new Error(`Failed to execute ${path} --version`); 185 throw new Error(`Failed to execute ${path} --version`);
187 } 186 }
188 187
diff --git a/editors/code/src/rust-analyzer-api.ts b/editors/code/src/rust-analyzer-api.ts
index 400ac3714..8ed56c173 100644
--- a/editors/code/src/rust-analyzer-api.ts
+++ b/editors/code/src/rust-analyzer-api.ts
@@ -64,12 +64,12 @@ export const parentModule = request<lc.TextDocumentPositionParams, Vec<lc.Locati
64 64
65export interface JoinLinesParams { 65export interface JoinLinesParams {
66 textDocument: lc.TextDocumentIdentifier; 66 textDocument: lc.TextDocumentIdentifier;
67 range: lc.Range; 67 ranges: lc.Range[];
68} 68}
69export const joinLines = request<JoinLinesParams, SourceChange>("joinLines"); 69export const joinLines = new lc.RequestType<JoinLinesParams, lc.TextEdit[], unknown>('experimental/joinLines');
70 70
71 71
72export const onEnter = request<lc.TextDocumentPositionParams, Option<SourceChange>>("onEnter"); 72export const onEnter = request<lc.TextDocumentPositionParams, Option<lc.WorkspaceEdit>>("onEnter");
73 73
74export interface RunnablesParams { 74export interface RunnablesParams {
75 textDocument: lc.TextDocumentIdentifier; 75 textDocument: lc.TextDocumentIdentifier;
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts
index 6f91f81d6..127a9e911 100644
--- a/editors/code/src/util.ts
+++ b/editors/code/src/util.ts
@@ -1,6 +1,7 @@
1import * as lc from "vscode-languageclient"; 1import * as lc from "vscode-languageclient";
2import * as vscode from "vscode"; 2import * as vscode from "vscode";
3import { strict as nativeAssert } from "assert"; 3import { strict as nativeAssert } from "assert";
4import { spawnSync } from "child_process";
4 5
5export function assert(condition: boolean, explanation: string): asserts condition { 6export function assert(condition: boolean, explanation: string): asserts condition {
6 try { 7 try {
@@ -82,3 +83,13 @@ export function isRustDocument(document: vscode.TextDocument): document is RustD
82export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor { 83export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor {
83 return isRustDocument(editor.document); 84 return isRustDocument(editor.document);
84} 85}
86
87export function isValidExecutable(path: string): boolean {
88 log.debug("Checking availability of a binary at", path);
89
90 const res = spawnSync(path, ["--version"], { encoding: 'utf8' });
91
92 log.debug(res, "--version output:", res.output);
93
94 return res.status === 0;
95}
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 703fb9be9..394a7bc88 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -162,6 +162,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
162 "RECORD_LIT", 162 "RECORD_LIT",
163 "RECORD_FIELD_LIST", 163 "RECORD_FIELD_LIST",
164 "RECORD_FIELD", 164 "RECORD_FIELD",
165 "EFFECT_EXPR",
165 "BOX_EXPR", 166 "BOX_EXPR",
166 // postfix 167 // postfix
167 "CALL_EXPR", 168 "CALL_EXPR",
@@ -176,7 +177,6 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc {
176 "PREFIX_EXPR", 177 "PREFIX_EXPR",
177 "RANGE_EXPR", // just weird 178 "RANGE_EXPR", // just weird
178 "BIN_EXPR", 179 "BIN_EXPR",
179 "BLOCK",
180 "EXTERN_BLOCK", 180 "EXTERN_BLOCK",
181 "EXTERN_ITEM_LIST", 181 "EXTERN_ITEM_LIST",
182 "ENUM_VARIANT", 182 "ENUM_VARIANT",
@@ -230,6 +230,7 @@ pub(crate) struct AstSrc<'a> {
230} 230}
231 231
232pub(crate) struct AstNodeSrc<'a> { 232pub(crate) struct AstNodeSrc<'a> {
233 pub(crate) doc: &'a [&'a str],
233 pub(crate) name: &'a str, 234 pub(crate) name: &'a str,
234 pub(crate) traits: &'a [&'a str], 235 pub(crate) traits: &'a [&'a str],
235 pub(crate) fields: &'a [Field<'a>], 236 pub(crate) fields: &'a [Field<'a>],
@@ -247,6 +248,7 @@ pub(crate) enum FieldSrc<'a> {
247} 248}
248 249
249pub(crate) struct AstEnumSrc<'a> { 250pub(crate) struct AstEnumSrc<'a> {
251 pub(crate) doc: &'a [&'a str],
250 pub(crate) name: &'a str, 252 pub(crate) name: &'a str,
251 pub(crate) traits: &'a [&'a str], 253 pub(crate) traits: &'a [&'a str],
252 pub(crate) variants: &'a [&'a str], 254 pub(crate) variants: &'a [&'a str],
@@ -254,12 +256,14 @@ pub(crate) struct AstEnumSrc<'a> {
254 256
255macro_rules! ast_nodes { 257macro_rules! ast_nodes {
256 ($( 258 ($(
259 $(#[doc = $doc:expr])+
257 struct $name:ident$(: $($trait:ident),*)? { 260 struct $name:ident$(: $($trait:ident),*)? {
258 $($field_name:ident $(![$token:tt])? $(: $ty:tt)?),*$(,)? 261 $($field_name:ident $(![$token:tt])? $(: $ty:tt)?),*$(,)?
259 } 262 }
260 )*) => { 263 )*) => {
261 [$( 264 [$(
262 AstNodeSrc { 265 AstNodeSrc {
266 doc: &[$($doc),*],
263 name: stringify!($name), 267 name: stringify!($name),
264 traits: &[$($(stringify!($trait)),*)?], 268 traits: &[$($(stringify!($trait)),*)?],
265 fields: &[ 269 fields: &[
@@ -288,12 +292,14 @@ macro_rules! field {
288 292
289macro_rules! ast_enums { 293macro_rules! ast_enums {
290 ($( 294 ($(
295 $(#[doc = $doc:expr])+
291 enum $name:ident $(: $($trait:ident),*)? { 296 enum $name:ident $(: $($trait:ident),*)? {
292 $($variant:ident),*$(,)? 297 $($variant:ident),*$(,)?
293 } 298 }
294 )*) => { 299 )*) => {
295 [$( 300 [$(
296 AstEnumSrc { 301 AstEnumSrc {
302 doc: &[$($doc),*],
297 name: stringify!($name), 303 name: stringify!($name),
298 traits: &[$($(stringify!($trait)),*)?], 304 traits: &[$($(stringify!($trait)),*)?],
299 variants: &[$(stringify!($variant)),*], 305 variants: &[$(stringify!($variant)),*],
@@ -305,10 +311,35 @@ macro_rules! ast_enums {
305pub(crate) const AST_SRC: AstSrc = AstSrc { 311pub(crate) const AST_SRC: AstSrc = AstSrc {
306 tokens: &["Whitespace", "Comment", "String", "RawString"], 312 tokens: &["Whitespace", "Comment", "String", "RawString"],
307 nodes: &ast_nodes! { 313 nodes: &ast_nodes! {
308 struct SourceFile: ModuleItemOwner, AttrsOwner { 314 /// The entire Rust source file. Includes all top-level inner attributes and module items.
315 ///
316 /// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html)
317 struct SourceFile: ModuleItemOwner, AttrsOwner, DocCommentsOwner {
309 modules: [Module], 318 modules: [Module],
310 } 319 }
311 320
321 /// Function definition either with body or not.
322 /// Includes all of its attributes and doc comments.
323 ///
324 /// ```
325 /// ❰
326 /// /// Docs
327 /// #[attr]
328 /// pub extern "C" fn foo<T>(#[attr] Patern {p}: Pattern) -> u32
329 /// where
330 /// T: Debug
331 /// {
332 /// 42
333 /// }
334 /// ❱
335 ///
336 /// extern "C" {
337 /// ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱
338 /// }
339 /// ```
340 ///
341 /// - [Reference](https://doc.rust-lang.org/reference/items/functions.html)
342 /// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions)
312 struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { 343 struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner {
313 Abi, 344 Abi,
314 T![const], 345 T![const],
@@ -322,42 +353,201 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
322 T![;] 353 T![;]
323 } 354 }
324 355
356 /// Return type annotation.
357 ///
358 /// ```
359 /// fn foo(a: u32) ❰ -> Option<u32> ❱ { Some(a) }
360 /// ```
361 ///
362 /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
325 struct RetType { T![->], TypeRef } 363 struct RetType { T![->], TypeRef }
326 364
365 /// Struct definition.
366 /// Includes all of its attributes and doc comments.
367 ///
368 /// ```
369 /// ❰
370 /// /// Docs
371 /// #[attr]
372 /// struct Foo<T> where T: Debug {
373 /// /// Docs
374 /// #[attr]
375 /// pub a: u32,
376 /// b: T,
377 /// }
378 /// ❱
379 ///
380 /// ❰ struct Foo; ❱
381 /// ❰ struct Foo<T>(#[attr] T) where T: Debug; ❱
382 /// ```
383 ///
384 /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
327 struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { 385 struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
328 T![struct], 386 T![struct],
329 FieldDefList, 387 FieldDefList,
330 T![;] 388 T![;]
331 } 389 }
332 390
391 /// Union definition.
392 /// Includes all of its attributes and doc comments.
393 ///
394 /// ```
395 /// ❰
396 /// /// Docs
397 /// #[attr]
398 /// pub union Foo<T> where T: Debug {
399 /// /// Docs
400 /// #[attr]
401 /// a: T,
402 /// b: u32,
403 /// }
404 /// ❱
405 /// ```
406 ///
407 /// [Reference](https://doc.rust-lang.org/reference/items/unions.html)
333 struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { 408 struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
334 T![union], 409 T![union],
335 RecordFieldDefList, 410 RecordFieldDefList,
336 } 411 }
337 412
413 /// Record field definition list including enclosing curly braces.
414 ///
415 /// ```
416 /// struct Foo // same for union
417 /// ❰
418 /// {
419 /// a: u32,
420 /// b: bool,
421 /// }
422 /// ❱
423 /// ```
424 ///
425 /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
338 struct RecordFieldDefList { T!['{'], fields: [RecordFieldDef], T!['}'] } 426 struct RecordFieldDefList { T!['{'], fields: [RecordFieldDef], T!['}'] }
427
428 /// Record field definition including its attributes and doc comments.
429 ///
430 /// ` ``
431 /// same for union
432 /// struct Foo {
433 /// ❰
434 /// /// Docs
435 /// #[attr]
436 /// pub a: u32
437 /// ❱
438 ///
439 /// ❰ b: bool ❱
440 /// }
441 /// ```
442 ///
443 /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
339 struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } 444 struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { }
340 445
446 /// Tuple field definition list including enclosing parens.
447 ///
448 /// ```
449 /// struct Foo ❰ (u32, String, Vec<u32>) ❱;
450 /// ```
451 ///
452 /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
341 struct TupleFieldDefList { T!['('], fields: [TupleFieldDef], T![')'] } 453 struct TupleFieldDefList { T!['('], fields: [TupleFieldDef], T![')'] }
454
455 /// Tuple field definition including its attributes.
456 ///
457 /// ```
458 /// struct Foo(❰ #[attr] u32 ❱);
459 /// ```
460 ///
461 /// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
342 struct TupleFieldDef: VisibilityOwner, AttrsOwner { 462 struct TupleFieldDef: VisibilityOwner, AttrsOwner {
343 TypeRef, 463 TypeRef,
344 } 464 }
345 465
466 /// Enum definition.
467 /// Includes all of its attributes and doc comments.
468 ///
469 /// ```
470 /// ❰
471 /// /// Docs
472 /// #[attr]
473 /// pub enum Foo<T> where T: Debug {
474 /// /// Docs
475 /// #[attr]
476 /// Bar,
477 /// Baz(#[attr] u32),
478 /// Bruh {
479 /// a: u32,
480 /// /// Docs
481 /// #[attr]
482 /// b: T,
483 /// }
484 /// }
485 /// ❱
486 /// ```
487 ///
488 /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
346 struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { 489 struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner {
347 T![enum], 490 T![enum],
348 variant_list: EnumVariantList, 491 variant_list: EnumVariantList,
349 } 492 }
493
494 /// Enum variant definition list including enclosing curly braces.
495 ///
496 /// ```
497 /// enum Foo
498 /// ❰
499 /// {
500 /// Bar,
501 /// Baz(u32),
502 /// Bruh {
503 /// a: u32
504 /// }
505 /// }
506 /// ❱
507 /// ```
508 ///
509 /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
350 struct EnumVariantList { 510 struct EnumVariantList {
351 T!['{'], 511 T!['{'],
352 variants: [EnumVariant], 512 variants: [EnumVariant],
353 T!['}'] 513 T!['}']
354 } 514 }
515
516 /// Enum variant definition including its attributes and discriminant value definition.
517 ///
518 /// ```
519 /// enum Foo {
520 /// ❰
521 /// /// Docs
522 /// #[attr]
523 /// Bar
524 /// ❱
525 ///
526 /// // same for tuple and record variants
527 /// }
528 /// ```
529 ///
530 /// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
355 struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner { 531 struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner {
356 FieldDefList, 532 FieldDefList,
357 T![=], 533 T![=],
358 Expr 534 Expr
359 } 535 }
360 536
537 /// Trait definition.
538 /// Includes all of its attributes and doc comments.
539 ///
540 /// ```
541 /// ❰
542 /// /// Docs
543 /// #[attr]
544 /// pub unsafe trait Foo<T>: Debug where T: Debug {
545 /// // ...
546 /// }
547 /// ❱
548 /// ```
549 ///
550 /// [Reference](https://doc.rust-lang.org/reference/items/traits.html)
361 struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { 551 struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner {
362 T![unsafe], 552 T![unsafe],
363 T![auto], 553 T![auto],
@@ -365,18 +555,73 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
365 ItemList, 555 ItemList,
366 } 556 }
367 557
558 /// Module definition either with body or not.
559 /// Includes all of its inner and outer attributes, module items, doc comments.
560 ///
561 /// ```
562 /// ❰
563 /// /// Docs
564 /// #[attr]
565 /// pub mod foo;
566 /// ❱
567 ///
568 /// ❰
569 /// /// Docs
570 /// #[attr]
571 /// pub mod bar {
572 /// //! Inner docs
573 /// #![inner_attr]
574 /// }
575 /// ❱
576 /// ```
577 ///
578 /// [Reference](https://doc.rust-lang.org/reference/items/modules.html)
368 struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { 579 struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner {
369 T![mod], 580 T![mod],
370 ItemList, 581 ItemList,
371 T![;] 582 T![;]
372 } 583 }
373 584
585 /// Item defintion list.
586 /// This is used for both top-level items and impl block items.
587 ///
588 /// ```
589 /// ❰
590 /// fn foo {}
591 /// struct Bar;
592 /// enum Baz;
593 /// trait Bruh;
594 /// const BRUUH: u32 = 42;
595 /// ❱
596 ///
597 /// impl Foo
598 /// ❰
599 /// {
600 /// fn bar() {}
601 /// const BAZ: u32 = 42;
602 /// }
603 /// ❱
604 /// ```
605 ///
606 /// [Reference](https://doc.rust-lang.org/reference/items.html)
374 struct ItemList: ModuleItemOwner { 607 struct ItemList: ModuleItemOwner {
375 T!['{'], 608 T!['{'],
376 impl_items: [ImplItem], 609 assoc_items: [AssocItem],
377 T!['}'] 610 T!['}']
378 } 611 }
379 612
613 /// Constant variable definition.
614 /// Includes all of its attributes and doc comments.
615 ///
616 /// ```
617 /// ❰
618 /// /// Docs
619 /// #[attr]
620 /// pub const FOO: u32 = 42;
621 /// ❱
622 /// ```
623 ///
624 /// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html)
380 struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { 625 struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
381 T![default], 626 T![default],
382 T![const], 627 T![const],
@@ -385,6 +630,19 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
385 T![;] 630 T![;]
386 } 631 }
387 632
633
634 /// Static variable definition.
635 /// Includes all of its attributes and doc comments.
636 ///
637 /// ```
638 /// ❰
639 /// /// Docs
640 /// #[attr]
641 /// pub static mut FOO: u32 = 42;
642 /// ❱
643 /// ```
644 ///
645 /// [Reference](https://doc.rust-lang.org/reference/items/static-items.html)
388 struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { 646 struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner {
389 T![static], 647 T![static],
390 T![mut], 648 T![mut],
@@ -393,6 +651,24 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
393 T![;] 651 T![;]
394 } 652 }
395 653
654 /// Type alias definition.
655 /// Includes associated type clauses with type bounds.
656 ///
657 /// ```
658 /// ❰
659 /// /// Docs
660 /// #[attr]
661 /// pub type Foo<T> where T: Debug = T;
662 /// ❱
663 ///
664 /// trait Bar {
665 /// ❰ type Baz: Debug; ❱
666 /// ❰ type Bruh = String; ❱
667 /// ❰ type Bruuh: Debug = u32; ❱
668 /// }
669 /// ```
670 ///
671 /// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html)
396 struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { 672 struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner {
397 T![default], 673 T![default],
398 T![type], 674 T![type],
@@ -401,7 +677,21 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
401 T![;] 677 T![;]
402 } 678 }
403 679
404 struct ImplDef: TypeParamsOwner, AttrsOwner { 680 /// Inherent and trait impl definition.
681 /// Includes all of its inner and outer attributes.
682 ///
683 /// ```
684 /// ❰
685 /// #[attr]
686 /// unsafe impl<T> const !Foo for Bar where T: Debug {
687 /// #![inner_attr]
688 /// // ...
689 /// }
690 /// ❱
691 /// ```
692 ///
693 /// [Reference](https://doc.rust-lang.org/reference/items/implementations.html)
694 struct ImplDef: TypeParamsOwner, AttrsOwner, DocCommentsOwner {
405 T![default], 695 T![default],
406 T![const], 696 T![const],
407 T![unsafe], 697 T![unsafe],
@@ -411,73 +701,611 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
411 ItemList, 701 ItemList,
412 } 702 }
413 703
704
705 /// Parenthesized type reference.
706 /// Note: parens are only used for grouping, this is not a tuple type.
707 ///
708 /// ```
709 /// // This is effectively just `u32`.
710 /// // Single-item tuple must be defined with a trailing comma: `(u32,)`
711 /// type Foo = ❰ (u32) ❱;
712 ///
713 /// let bar: &'static ❰ (dyn Debug) ❱ = "bruh";
714 /// ```
414 struct ParenType { T!['('], TypeRef, T![')'] } 715 struct ParenType { T!['('], TypeRef, T![')'] }
716
717 /// Unnamed tuple type.
718 ///
719 /// ```
720 /// let foo: ❰ (u32, bool) ❱ = (42, true);
721 /// ```
722 ///
723 /// [Reference](https://doc.rust-lang.org/reference/types/tuple.html)
415 struct TupleType { T!['('], fields: [TypeRef], T![')'] } 724 struct TupleType { T!['('], fields: [TypeRef], T![')'] }
725
726 /// The never type (i.e. the exclamation point).
727 ///
728 /// ```
729 /// type T = ❰ ! ❱;
730 ///
731 /// fn no_return() -> ❰ ! ❱ {
732 /// loop {}
733 /// }
734 /// ```
735 ///
736 /// [Reference](https://doc.rust-lang.org/reference/types/never.html)
416 struct NeverType { T![!] } 737 struct NeverType { T![!] }
738
739 /// Path to a type.
740 /// Includes single identifier type names and elaborate paths with
741 /// generic parameters.
742 ///
743 /// ```
744 /// type Foo = ❰ String ❱;
745 /// type Bar = ❰ std::vec::Vec<T> ❱;
746 /// type Baz = ❰ ::bruh::<Bruuh as Iterator>::Item ❱;
747 /// ```
748 ///
749 /// [Reference](https://doc.rust-lang.org/reference/paths.html)
417 struct PathType { Path } 750 struct PathType { Path }
751
752 /// Raw pointer type.
753 ///
754 /// ```
755 /// type Foo = ❰ *const u32 ❱;
756 /// type Bar = ❰ *mut u32 ❱;
757 /// ```
758 ///
759 /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut)
418 struct PointerType { T![*], T![const], T![mut], TypeRef } 760 struct PointerType { T![*], T![const], T![mut], TypeRef }
761
762 /// Array type.
763 ///
764 /// ```
765 /// type Foo = ❰ [u32; 24 - 3] ❱;
766 /// ```
767 ///
768 /// [Reference](https://doc.rust-lang.org/reference/types/array.html)
419 struct ArrayType { T!['['], TypeRef, T![;], Expr, T![']'] } 769 struct ArrayType { T!['['], TypeRef, T![;], Expr, T![']'] }
770
771 /// Slice type.
772 ///
773 /// ```
774 /// type Foo = ❰ [u8] ❱;
775 /// ```
776 ///
777 /// [Reference](https://doc.rust-lang.org/reference/types/slice.html)
420 struct SliceType { T!['['], TypeRef, T![']'] } 778 struct SliceType { T!['['], TypeRef, T![']'] }
779
780 /// Reference type.
781 ///
782 /// ```
783 /// type Foo = ❰ &'static str ❱;
784 /// ```
785 ///
786 /// [Reference](https://doc.rust-lang.org/reference/types/pointer.html)
421 struct ReferenceType { T![&], T![lifetime], T![mut], TypeRef } 787 struct ReferenceType { T![&], T![lifetime], T![mut], TypeRef }
788
789 /// Placeholder type (i.e. the underscore).
790 ///
791 /// ```
792 /// let foo: ❰ _ ❱ = 42_u32;
793 /// ```
794 ///
795 /// [Reference](https://doc.rust-lang.org/reference/types/inferred.html)
422 struct PlaceholderType { T![_] } 796 struct PlaceholderType { T![_] }
797
798 /// Function pointer type (not to be confused with `Fn*` family of traits).
799 ///
800 /// ```
801 /// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱;
802 ///
803 /// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱;
804 /// ```
805 ///
806 /// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html)
423 struct FnPointerType { Abi, T![unsafe], T![fn], ParamList, RetType } 807 struct FnPointerType { Abi, T![unsafe], T![fn], ParamList, RetType }
808
809 /// Higher order type.
810 ///
811 /// ```
812 /// type Foo = ❰ for<'a> fn(&'a str) ❱;
813 /// ```
814 ///
815 /// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html)
424 struct ForType { T![for], TypeParamList, TypeRef } 816 struct ForType { T![for], TypeParamList, TypeRef }
817
818 /// Opaque `impl Trait` type.
819 ///
820 /// ```
821 /// fn foo(bar: ❰ impl Debug + Eq ❱) {}
822 /// ```
823 ///
824 /// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html)
425 struct ImplTraitType: TypeBoundsOwner { T![impl] } 825 struct ImplTraitType: TypeBoundsOwner { T![impl] }
826
827 /// Trait object type.
828 ///
829 /// ```
830 /// type Foo = ❰ dyn Debug ❱;
831 /// ```
832 ///
833 /// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html)
426 struct DynTraitType: TypeBoundsOwner { T![dyn] } 834 struct DynTraitType: TypeBoundsOwner { T![dyn] }
427 835
836 /// Tuple literal.
837 ///
838 /// ```
839 /// ❰ (42, true) ❱;
840 /// ```
841 ///
842 /// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html)
428 struct TupleExpr: AttrsOwner { T!['('], exprs: [Expr], T![')'] } 843 struct TupleExpr: AttrsOwner { T!['('], exprs: [Expr], T![')'] }
844
845 /// Array literal.
846 ///
847 /// ```
848 /// ❰ [#![inner_attr] true, false, true] ❱;
849 ///
850 /// ❰ ["baz"; 24] ❱;
851 /// ```
852 ///
853 /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
429 struct ArrayExpr: AttrsOwner { T!['['], exprs: [Expr], T![;], T![']'] } 854 struct ArrayExpr: AttrsOwner { T!['['], exprs: [Expr], T![;], T![']'] }
855
856 /// Parenthesized expression.
857 /// Note: parens are only used for grouping, this is not a tuple literal.
858 ///
859 /// ```
860 /// ❰ (#![inner_attr] 2 + 2) ❱ * 2;
861 /// ```
862 ///
863 /// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html)
430 struct ParenExpr: AttrsOwner { T!['('], Expr, T![')'] } 864 struct ParenExpr: AttrsOwner { T!['('], Expr, T![')'] }
431 struct PathExpr { Path } 865
866 /// Path to a symbol in expression context.
867 /// Includes single identifier variable names and elaborate paths with
868 /// generic parameters.
869 ///
870 /// ```
871 /// ❰ Some::<i32> ❱;
872 /// ❰ foo ❱ + 42;
873 /// ❰ Vec::<i32>::push ❱;
874 /// ❰ <[i32]>::reverse ❱;
875 /// ❰ <String as std::borrow::Borrow<str>>::borrow ❱;
876 /// ```
877 ///
878 /// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html)
879 struct PathExpr { Path }
880
881 /// Anonymous callable object literal a.k.a. closure, lambda or functor.
882 ///
883 /// ```
884 /// ❰ || 42 ❱;
885 /// ❰ |a: u32| val + 1 ❱;
886 /// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱;
887 /// ❰ move || baz ❱;
888 /// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱
889 /// ```
890 ///
891 /// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html)
432 struct LambdaExpr: AttrsOwner { 892 struct LambdaExpr: AttrsOwner {
433 T![static], 893 T![static], // Note(@matklad): I belive this is (used to be?) syntax for generators
434 T![async], 894 T![async],
435 T![move], 895 T![move],
436 ParamList, 896 ParamList,
437 RetType, 897 RetType,
438 body: Expr, 898 body: Expr,
439 } 899 }
900
901 /// If expression. Includes both regular `if` and `if let` forms.
902 /// Beware that `else if` is a special case syntax sugar, because in general
903 /// there has to be block expression after `else`.
904 ///
905 /// ```
906 /// ❰ if bool_cond { 42 } ❱
907 /// ❰ if bool_cond { 42 } else { 24 } ❱
908 /// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱
909 ///
910 /// ❰
911 /// if let Pattern(foo) = bar {
912 /// foo
913 /// } else {
914 /// panic!();
915 /// }
916 /// ❱
917 /// ```
918 ///
919 /// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
440 struct IfExpr: AttrsOwner { T![if], Condition } 920 struct IfExpr: AttrsOwner { T![if], Condition }
921
922 /// Unconditional loop expression.
923 ///
924 /// ```
925 /// ❰
926 /// loop {
927 /// // yeah, it's that simple...
928 /// }
929 /// ❱
930 /// ```
931 ///
932 /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html)
441 struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] } 933 struct LoopExpr: AttrsOwner, LoopBodyOwner { T![loop] }
934
935 /// Block expression with an optional prefix (label, try ketword,
936 /// unsafe keyword, async keyword...).
937 ///
938 /// ```
939 /// ❰
940 /// 'label: try {
941 /// None?
942 /// }
943 /// ❱
944 /// ```
945 ///
946 /// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html)
947 /// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks)
948 /// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks)
949 struct EffectExpr: AttrsOwner { Label, T![try], T![unsafe], T![async], BlockExpr }
950
951
952 /// For loop expression.
953 /// Note: record struct literals are not valid as iterable expression
954 /// due to ambiguity.
955 ///
956 /// ```
957 /// ❰
958 /// for i in (0..4) {
959 /// dbg!(i);
960 /// }
961 /// ❱
962 /// ```
963 ///
964 /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops)
442 struct ForExpr: AttrsOwner, LoopBodyOwner { 965 struct ForExpr: AttrsOwner, LoopBodyOwner {
443 T![for], 966 T![for],
444 Pat, 967 Pat,
445 T![in], 968 T![in],
446 iterable: Expr, 969 iterable: Expr,
447 } 970 }
971
972 /// While loop expression. Includes both regular `while` and `while let` forms.
973 ///
974 /// ```
975 /// ❰
976 /// while bool_cond {
977 /// 42;
978 /// }
979 /// ❱
980 /// ❰
981 /// while let Pattern(foo) = bar {
982 /// bar += 1;
983 /// }
984 /// ❱
985 /// ```
986 ///
987 /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
448 struct WhileExpr: AttrsOwner, LoopBodyOwner { T![while], Condition } 988 struct WhileExpr: AttrsOwner, LoopBodyOwner { T![while], Condition }
989
990 /// Continue expression.
991 ///
992 /// ```
993 /// while bool_cond {
994 /// ❰ continue ❱;
995 /// }
996 ///
997 /// 'outer: loop {
998 /// loop {
999 /// ❰ continue 'outer ❱;
1000 /// }
1001 /// }
1002 ///
1003 /// ```
1004 ///
1005 /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)
449 struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] } 1006 struct ContinueExpr: AttrsOwner { T![continue], T![lifetime] }
1007
1008 /// Break expression.
1009 ///
1010 /// ```
1011 /// while bool_cond {
1012 /// ❰ break ❱;
1013 /// }
1014 /// 'outer: loop {
1015 /// for foo in bar {
1016 /// ❰ break 'outer ❱;
1017 /// }
1018 /// }
1019 /// 'outer: loop {
1020 /// loop {
1021 /// ❰ break 'outer 42 ❱;
1022 /// }
1023 /// }
1024 /// ```
1025 ///
1026 /// [Refernce](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions)
450 struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr } 1027 struct BreakExpr: AttrsOwner { T![break], T![lifetime], Expr }
1028
1029 /// Label.
1030 ///
1031 /// ```
1032 /// ❰ 'outer: ❱ loop {}
1033 ///
1034 /// let foo = ❰ 'bar: ❱ loop {}
1035 ///
1036 /// ❰ 'baz: ❱ {
1037 /// break 'baz;
1038 /// }
1039 /// ```
1040 ///
1041 /// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html?highlight=label#loop-labels)
1042 /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
451 struct Label { T![lifetime] } 1043 struct Label { T![lifetime] }
452 struct BlockExpr: AttrsOwner { Label, T![unsafe], T![async], Block } 1044
1045 /// Block expression. Includes unsafe blocks and block labels.
1046 ///
1047 /// ```
1048 /// let foo = ❰
1049 /// {
1050 /// #![inner_attr]
1051 /// ❰ { } ❱
1052 ///
1053 /// ❰ 'label: { break 'label } ❱
1054 /// }
1055 /// ❱;
1056 /// ```
1057 ///
1058 /// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html)
1059 /// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
1060 struct BlockExpr: AttrsOwner, ModuleItemOwner {
1061 T!['{'], statements: [Stmt], Expr, T!['}'],
1062 }
1063
1064 /// Return expression.
1065 ///
1066 /// ```
1067 /// || ❰ return 42 ❱;
1068 ///
1069 /// fn bar() {
1070 /// ❰ return ❱;
1071 /// }
1072 /// ```
1073 ///
1074 /// [Reference](https://doc.rust-lang.org/reference/expressions/return-expr.html)
453 struct ReturnExpr: AttrsOwner { Expr } 1075 struct ReturnExpr: AttrsOwner { Expr }
1076
1077 /// Call expression (not to be confused with method call expression, it is
1078 /// a separate ast node).
1079 ///
1080 /// ```
1081 /// ❰ foo() ❱;
1082 /// ❰ &str::len("bar") ❱;
1083 /// ❰ <&str as PartialEq<&str>>::eq(&"", &"") ❱;
1084 /// ```
1085 ///
1086 /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
454 struct CallExpr: ArgListOwner { Expr } 1087 struct CallExpr: ArgListOwner { Expr }
1088
1089 /// Method call expression.
1090 ///
1091 /// ```
1092 /// ❰ receiver_expr.method() ❱;
1093 /// ❰ receiver_expr.method::<T>(42, true) ❱;
1094 ///
1095 /// ❰ ❰ ❰ foo.bar() ❱ .baz() ❱ .bruh() ❱;
1096 /// ```
1097 ///
1098 /// [Reference](https://doc.rust-lang.org/reference/expressions/method-call-expr.html)
455 struct MethodCallExpr: AttrsOwner, ArgListOwner { 1099 struct MethodCallExpr: AttrsOwner, ArgListOwner {
456 Expr, T![.], NameRef, TypeArgList, 1100 Expr, T![.], NameRef, TypeArgList,
457 } 1101 }
1102
1103 /// Index expression a.k.a. subscript operator call.
1104 ///
1105 /// ```
1106 /// ❰ foo[42] ❱;
1107 /// ```
1108 ///
1109 /// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
458 struct IndexExpr: AttrsOwner { T!['['], T![']'] } 1110 struct IndexExpr: AttrsOwner { T!['['], T![']'] }
1111
1112 /// Field access expression.
1113 ///
1114 /// ```
1115 /// ❰ expr.bar ❱;
1116 ///
1117 /// ❰ ❰ ❰ foo.bar ❱ .baz ❱ .bruh ❱;
1118 /// ```
1119 ///
1120 /// [Reference](https://doc.rust-lang.org/reference/expressions/field-expr.html)
459 struct FieldExpr: AttrsOwner { Expr, T![.], NameRef } 1121 struct FieldExpr: AttrsOwner { Expr, T![.], NameRef }
1122
1123 /// Await operator call expression.
1124 ///
1125 /// ```
1126 /// ❰ expr.await ❱;
1127 /// ```
1128 ///
1129 /// [Reference](https://doc.rust-lang.org/reference/expressions/await-expr.html)
460 struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] } 1130 struct AwaitExpr: AttrsOwner { Expr, T![.], T![await] }
461 struct TryExpr: AttrsOwner { T![try], Expr } 1131
1132 /// The question mark operator call.
1133 ///
1134 /// ```
1135 /// ❰ expr? ❱;
1136 /// ```
1137 ///
1138 /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator)
1139 struct TryExpr: AttrsOwner { Expr, T![?] }
1140
1141 /// Type cast expression.
1142 ///
1143 /// ```
1144 /// ❰ expr as T ❱;
1145 /// ```
1146 ///
1147 /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#type-cast-expressions)
462 struct CastExpr: AttrsOwner { Expr, T![as], TypeRef } 1148 struct CastExpr: AttrsOwner { Expr, T![as], TypeRef }
1149
1150
1151 /// Borrow operator call.
1152 ///
1153 /// ```
1154 /// ❰ &foo ❱;
1155 /// ❰ &mut bar ❱;
1156 /// ```
1157 ///
1158 /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#borrow-operators)
463 struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr } 1159 struct RefExpr: AttrsOwner { T![&], T![raw], T![mut], Expr }
1160
1161 /// Prefix operator call. This is either `!` or `*` or `-`.
1162 ///
1163 /// ```
1164 /// ❰ !foo ❱;
1165 /// ❰ *bar ❱;
1166 /// ❰ -42 ❱;
1167 /// ```
1168 ///
1169 /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html)
464 struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr } 1170 struct PrefixExpr: AttrsOwner { /*PrefixOp,*/ Expr }
1171
1172 /// Box operator call.
1173 ///
1174 /// ```
1175 /// ❰ box 42 ❱;
1176 /// ```
1177 ///
1178 /// [RFC](https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b1d20284b43f87cbe1c6/text/0809-box-and-in-for-stdlib.md)
465 struct BoxExpr: AttrsOwner { T![box], Expr } 1179 struct BoxExpr: AttrsOwner { T![box], Expr }
1180
1181 /// Range operator call.
1182 ///
1183 /// ```
1184 /// ❰ 0..42 ❱;
1185 /// ❰ ..42 ❱;
1186 /// ❰ 0.. ❱;
1187 /// ❰ .. ❱;
1188 /// ❰ 0..=42 ❱;
1189 /// ❰ ..=42 ❱;
1190 /// ```
1191 ///
1192 /// [Reference](https://doc.rust-lang.org/reference/expressions/range-expr.html)
466 struct RangeExpr: AttrsOwner { /*RangeOp*/ } 1193 struct RangeExpr: AttrsOwner { /*RangeOp*/ }
1194
1195
1196 /// Binary operator call.
1197 /// Includes all arithmetic, logic, bitwise and assignment operators.
1198 ///
1199 /// ```
1200 /// ❰ 2 + ❰ 2 * 2 ❱ ❱;
1201 /// ❰ ❰ true && false ❱ || true ❱;
1202 /// ```
1203 ///
1204 /// [Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators)
467 struct BinExpr: AttrsOwner { /*BinOp*/ } 1205 struct BinExpr: AttrsOwner { /*BinOp*/ }
1206
1207
1208 /// [Raw] string, [raw] byte string, char, byte, integer, float or bool literal.
1209 ///
1210 /// ```
1211 /// ❰ "str" ❱;
1212 /// ❰ br##"raw byte str"## ❱;
1213 /// ❰ 'c' ❱;
1214 /// ❰ b'c' ❱;
1215 /// ❰ 42 ❱;
1216 /// ❰ 1e9 ❱;
1217 /// ❰ true ❱;
1218 /// ```
1219 ///
1220 /// [Reference](https://doc.rust-lang.org/reference/expressions/literal-expr.html)
468 struct Literal { /*LiteralToken*/ } 1221 struct Literal { /*LiteralToken*/ }
469 1222
1223 /// Match expression.
1224 ///
1225 /// ```
1226 /// ❰
1227 /// match expr {
1228 /// Pat1 => {}
1229 /// Pat2(_) => 42,
1230 /// }
1231 /// ❱
1232 /// ```
1233 ///
1234 /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
470 struct MatchExpr: AttrsOwner { T![match], Expr, MatchArmList } 1235 struct MatchExpr: AttrsOwner { T![match], Expr, MatchArmList }
1236
1237 /// Match arm list part of match expression. Includes its inner attributes.
1238 ///
1239 /// ```
1240 /// match expr
1241 /// ❰
1242 /// {
1243 /// #![inner_attr]
1244 /// Pat1 => {}
1245 /// Pat2(_) => 42,
1246 /// }
1247 /// ❱
1248 /// ```
1249 ///
1250 /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
471 struct MatchArmList: AttrsOwner { T!['{'], arms: [MatchArm], T!['}'] } 1251 struct MatchArmList: AttrsOwner { T!['{'], arms: [MatchArm], T!['}'] }
1252
1253
1254 /// Match arm.
1255 /// Note: record struct literals are not valid as target match expression
1256 /// due to ambiguity.
1257 /// ```
1258 /// match expr {
1259 /// ❰ #[attr] Pattern(it) if bool_cond => it ❱,
1260 /// }
1261 /// ```
1262 ///
1263 /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html)
472 struct MatchArm: AttrsOwner { 1264 struct MatchArm: AttrsOwner {
473 pat: Pat, 1265 pat: Pat,
474 guard: MatchGuard, 1266 guard: MatchGuard,
475 T![=>], 1267 T![=>],
476 Expr, 1268 Expr,
477 } 1269 }
1270
1271 /// Match guard.
1272 ///
1273 /// ```
1274 /// match expr {
1275 /// Pattern(it) ❰ if bool_cond ❱ => it,
1276 /// }
1277 /// ```
1278 ///
1279 /// [Reference](https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards)
478 struct MatchGuard { T![if], Expr } 1280 struct MatchGuard { T![if], Expr }
479 1281
1282 /// Record literal expression. The same syntax is used for structs,
1283 /// unions and record enum variants.
1284 ///
1285 /// ```
1286 /// ❰
1287 /// foo::Bar {
1288 /// #![inner_attr]
1289 /// baz: 42,
1290 /// bruh: true,
1291 /// ..spread
1292 /// }
1293 /// ❱
1294 /// ```
1295 ///
1296 /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
480 struct RecordLit { Path, RecordFieldList} 1297 struct RecordLit { Path, RecordFieldList}
1298
1299 /// Record field list including enclosing curly braces.
1300 ///
1301 /// foo::Bar ❰
1302 /// {
1303 /// baz: 42,
1304 /// ..spread
1305 /// }
1306 /// ❱
1307 ///
1308 /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
481 struct RecordFieldList { 1309 struct RecordFieldList {
482 T!['{'], 1310 T!['{'],
483 fields: [RecordField], 1311 fields: [RecordField],
@@ -485,22 +1313,162 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
485 spread: Expr, 1313 spread: Expr,
486 T!['}'] 1314 T!['}']
487 } 1315 }
1316
1317 /// Record field.
1318 ///
1319 /// ```
1320 /// foo::Bar {
1321 /// ❰ #[attr] baz: 42 ❱
1322 /// }
1323 /// ```
1324 ///
1325 /// [Reference](https://doc.rust-lang.org/reference/expressions/struct-expr.html)
488 struct RecordField: AttrsOwner { NameRef, T![:], Expr } 1326 struct RecordField: AttrsOwner { NameRef, T![:], Expr }
489 1327
1328 /// Disjunction of patterns.
1329 ///
1330 /// ```
1331 /// let ❰ Foo(it) | Bar(it) | Baz(it) ❱ = bruh;
1332 /// ```
1333 ///
1334 /// [Reference](https://doc.rust-lang.org/reference/patterns.html)
490 struct OrPat { pats: [Pat] } 1335 struct OrPat { pats: [Pat] }
1336
1337 /// Parenthesized pattern.
1338 /// Note: parens are only used for grouping, this is not a tuple pattern.
1339 ///
1340 /// ```
1341 /// if let ❰ &(0..=42) ❱ = foo {}
1342 /// ```
1343 ///
1344 /// https://doc.rust-lang.org/reference/patterns.html#grouped-patterns
491 struct ParenPat { T!['('], Pat, T![')'] } 1345 struct ParenPat { T!['('], Pat, T![')'] }
1346
1347 /// Reference pattern.
1348 /// Note: this has nothing to do with `ref` keyword, the latter is used in bind patterns.
1349 ///
1350 /// ```
1351 /// let ❰ &mut foo ❱ = bar;
1352 ///
1353 /// let ❰ & ❰ &mut ❰ &_ ❱ ❱ ❱ = baz;
1354 /// ```
1355 ///
1356 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns)
492 struct RefPat { T![&], T![mut], Pat } 1357 struct RefPat { T![&], T![mut], Pat }
1358
1359 /// Box pattern.
1360 ///
1361 /// ```
1362 /// let ❰ box foo ❱ = box 42;
1363 /// ```
1364 ///
1365 /// [Unstable book](https://doc.rust-lang.org/unstable-book/language-features/box-patterns.html)
493 struct BoxPat { T![box], Pat } 1366 struct BoxPat { T![box], Pat }
1367
1368 /// Bind pattern.
1369 ///
1370 /// ```
1371 /// match foo {
1372 /// Some(❰ ref mut bar ❱) => {}
1373 /// ❰ baz @ None ❱ => {}
1374 /// }
1375 /// ```
1376 ///
1377 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#identifier-patterns)
494 struct BindPat: AttrsOwner, NameOwner { T![ref], T![mut], T![@], Pat } 1378 struct BindPat: AttrsOwner, NameOwner { T![ref], T![mut], T![@], Pat }
1379
1380 /// Placeholder pattern a.k.a. the wildcard pattern or the underscore.
1381 ///
1382 /// ```
1383 /// let ❰ _ ❱ = foo;
1384 /// ```
1385 ///
1386 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#wildcard-pattern)
495 struct PlaceholderPat { T![_] } 1387 struct PlaceholderPat { T![_] }
1388
1389 /// Rest-of-the record/tuple pattern.
1390 /// Note: this is not the unbonded range pattern (even more: it doesn't exist).
1391 ///
1392 /// ```
1393 /// let Foo { bar, ❰ .. ❱ } = baz;
1394 /// let (❰ .. ❱, bruh) = (42, 24, 42);
1395 /// let Bruuh(❰ .. ❱) = bruuuh;
1396 /// ```
1397 ///
1398 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
496 struct DotDotPat { T![..] } 1399 struct DotDotPat { T![..] }
1400
1401 /// Path pattern.
1402 /// Doesn't include the underscore pattern (it is a special case, namely `PlaceholderPat`).
1403 ///
1404 /// ```
1405 /// let ❰ foo::bar::Baz ❱ { .. } = bruh;
1406 /// if let ❰ CONST ❱ = 42 {}
1407 /// ```
1408 ///
1409 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#path-patterns)
497 struct PathPat { Path } 1410 struct PathPat { Path }
1411
1412 /// Slice pattern.
1413 ///
1414 /// ```
1415 /// let ❰ [foo, bar, baz] ❱ = [1, 2, 3];
1416 /// ```
1417 ///
1418 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#slice-patterns)
498 struct SlicePat { T!['['], args: [Pat], T![']'] } 1419 struct SlicePat { T!['['], args: [Pat], T![']'] }
499 struct RangePat { /*RangeSeparator*/ } 1420
1421 /// Range pattern.
1422 ///
1423 /// ```
1424 /// match foo {
1425 /// ❰ 0..42 ❱ => {}
1426 /// ❰ 0..=42 ❱ => {}
1427 /// }
1428 /// ```
1429 ///
1430 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#range-patterns)
1431 struct RangePat { } // FIXME(@matklad): here should be T![..], T![..=] I think, if we don't already have an accessor in expresions_ext
1432
1433 /// Literal pattern.
1434 /// Includes only bool, number, char, and string literals.
1435 ///
1436 /// ```
1437 /// match foo {
1438 /// Number(❰ 42 ❱) => {}
1439 /// String(❰ "42" ❱) => {}
1440 /// Bool(❰ true ❱) => {}
1441 /// }
1442 /// ```
1443 ///
1444 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#literal-patterns)
500 struct LiteralPat { Literal } 1445 struct LiteralPat { Literal }
1446
1447 /// Macro invocation in pattern position.
1448 ///
1449 /// ```
1450 /// let ❰ foo!(my custom syntax) ❱ = baz;
1451 ///
1452 /// ```
1453 /// [Reference](https://doc.rust-lang.org/reference/macros.html#macro-invocation)
501 struct MacroPat { MacroCall } 1454 struct MacroPat { MacroCall }
502 1455
1456 /// Record literal pattern.
1457 ///
1458 /// ```
1459 /// let ❰ foo::Bar { baz, .. } ❱ = bruh;
1460 /// ```
1461 ///
1462 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
503 struct RecordPat { RecordFieldPatList, Path } 1463 struct RecordPat { RecordFieldPatList, Path }
1464
1465 /// Record literal's field patterns list including enclosing curly braces.
1466 ///
1467 /// ```
1468 /// let foo::Bar ❰ { baz, bind @ bruh, .. } ❱ = bruuh;
1469 /// ``
1470 ///
1471 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
504 struct RecordFieldPatList { 1472 struct RecordFieldPatList {
505 T!['{'], 1473 T!['{'],
506 pats: [RecordInnerPat], 1474 pats: [RecordInnerPat],
@@ -509,20 +1477,148 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
509 T![..], 1477 T![..],
510 T!['}'] 1478 T!['}']
511 } 1479 }
1480
1481 /// Record literal's field pattern.
1482 /// Note: record literal can also match tuple structs.
1483 ///
1484 /// ```
1485 /// let Foo { ❰ bar: _ ❱ } = baz;
1486 /// let TupleStruct { ❰ 0: _ ❱ } = bruh;
1487 /// ```
1488 ///
1489 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#struct-patterns)
512 struct RecordFieldPat: AttrsOwner { NameRef, T![:], Pat } 1490 struct RecordFieldPat: AttrsOwner { NameRef, T![:], Pat }
513 1491
1492 /// Tuple struct literal pattern.
1493 ///
1494 /// ```
1495 /// let ❰ foo::Bar(baz, bruh) ❱ = bruuh;
1496 /// ```
1497 ///
1498 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-struct-patterns)
514 struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] } 1499 struct TupleStructPat { Path, T!['('], args: [Pat], T![')'] }
1500
1501 /// Tuple pattern.
1502 /// Note: this doesn't include tuple structs (see `TupleStructPat`)
1503 ///
1504 /// ```
1505 /// let ❰ (foo, bar, .., baz) ❱ = bruh;
1506 /// ```
1507 ///
1508 /// [Reference](https://doc.rust-lang.org/reference/patterns.html#tuple-patterns)
515 struct TuplePat { T!['('], args: [Pat], T![')'] } 1509 struct TuplePat { T!['('], args: [Pat], T![')'] }
516 1510
1511 /// Visibility.
1512 ///
1513 /// ```
1514 /// ❰ pub mod ❱ foo;
1515 /// ❰ pub(crate) ❱ struct Bar;
1516 /// ❰ pub(self) ❱ enum Baz {}
1517 /// ❰ pub(super) ❱ fn bruh() {}
1518 /// ❰ pub(in bruuh::bruuuh) ❱ type T = u64;
1519 /// ```
1520 ///
1521 /// [Reference](https://doc.rust-lang.org/reference/visibility-and-privacy.html)
517 struct Visibility { T![pub], T![super], T![self], T![crate] } 1522 struct Visibility { T![pub], T![super], T![self], T![crate] }
1523
1524 /// Single identifier.
1525 /// Note(@matklad): `Name` is for things that install a new name into the scope,
1526 /// `NameRef` is a usage of a name. Most of the time, this definition/reference
1527 /// distinction can be determined purely syntactically, ie in
1528 /// ```
1529 /// fn foo() { foo() }
1530 /// ```
1531 /// the first foo is `Name`, the second one is `NameRef`.
1532 /// The notable exception are patterns, where in
1533 /// ``
1534 /// let x = 92
1535 /// ```
1536 /// `x` can be semantically either a name or a name ref, depeding on
1537 /// wether there's an `x` constant in scope.
1538 /// We use `Name` for patterns, and disambiguate semantically (see `NameClass` in ide_db).
1539 ///
1540 /// ```
1541 /// let ❰ foo ❱ = bar;
1542 /// struct ❰ Baz ❱;
1543 /// fn ❰ bruh ❱() {}
1544 /// ```
1545 ///
1546 /// [Reference](https://doc.rust-lang.org/reference/identifiers.html)
518 struct Name { T![ident] } 1547 struct Name { T![ident] }
519 struct NameRef { /*NameRefToken*/ }
520 1548
521 struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner { 1549 /// Reference to a name.
1550 /// See the explanation on the difference between `Name` and `NameRef`
1551 /// in `Name` ast node docs.
1552 ///
1553 /// ```
1554 /// let foo = ❰ bar ❱(❰ Baz(❰ bruh ❱) ❱;
1555 /// ```
1556 ///
1557 /// [Reference](https://doc.rust-lang.org/reference/identifiers.html)
1558 struct NameRef { }
1559
1560 /// Macro call.
1561 /// Includes all of its attributes and doc comments.
1562 ///
1563 /// ```
1564 /// ❰
1565 /// /// Docs
1566 /// #[attr]
1567 /// macro_rules! foo { // macro rules is also a macro call
1568 /// ($bar: tt) => {}
1569 /// }
1570 /// ❱
1571 ///
1572 /// // semicolon is a part of `MacroCall` when it is used in item positions
1573 /// ❰ foo!(); ❱
1574 ///
1575 /// fn main() {
1576 /// ❰ foo!() ❱; // macro call in expression positions doesn't include the semi
1577 /// }
1578 /// ```
1579 ///
1580 /// [Reference](https://doc.rust-lang.org/reference/macros.html)
1581 struct MacroCall: NameOwner, AttrsOwner, DocCommentsOwner {
522 Path, T![!], TokenTree, T![;] 1582 Path, T![!], TokenTree, T![;]
523 } 1583 }
1584
1585 /// Attribute.
1586 ///
1587 /// ```
1588 /// ❰ #![inner_attr] ❱
1589 ///
1590 /// ❰ #[attr] ❱
1591 /// ❰ #[foo = "bar"] ❱
1592 /// ❰ #[baz(bruh::bruuh = "42")] ❱
1593 /// struct Foo;
1594 /// ```
1595 ///
1596 /// [Reference](https://doc.rust-lang.org/reference/attributes.html)
524 struct Attr { T![#], T![!], T!['['], Path, T![=], input: AttrInput, T![']'] } 1597 struct Attr { T![#], T![!], T!['['], Path, T![=], input: AttrInput, T![']'] }
1598
1599 /// Stores a list of lexer tokens and other `TokenTree`s.
1600 /// It appears in attributes, macro_rules and macro call (foo!)
1601 ///
1602 /// ```
1603 /// macro_call! ❰ { my syntax here } ❱;
1604 /// ```
1605 ///
1606 /// [Reference](https://doc.rust-lang.org/reference/macros.html)
525 struct TokenTree {} 1607 struct TokenTree {}
1608
1609 /// Generic lifetime, type and constants parameters list **declaration**.
1610 ///
1611 /// ```
1612 /// fn foo❰ <'a, 'b, T, U, const BAR: u64> ❱() {}
1613 ///
1614 /// struct Baz❰ <T> ❱(T);
1615 ///
1616 /// impl❰ <T> ❱ Bruh<T> {}
1617 ///
1618 /// type Bruuh = for❰ <'a> ❱ fn(&'a str) -> &'a str;
1619 /// ```
1620 ///
1621 /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
526 struct TypeParamList { 1622 struct TypeParamList {
527 T![<], 1623 T![<],
528 generic_params: [GenericParam], 1624 generic_params: [GenericParam],
@@ -531,21 +1627,141 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
531 const_params: [ConstParam], 1627 const_params: [ConstParam],
532 T![>] 1628 T![>]
533 } 1629 }
1630
1631 /// Single type parameter **declaration**.
1632 ///
1633 /// ```
1634 /// fn foo<❰ K ❱, ❰ I ❱, ❰ E: Debug ❱, ❰ V = DefaultType ❱>() {}
1635 /// ```
1636 ///
1637 /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
534 struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { 1638 struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner {
535 T![=], 1639 T![=],
536 default_type: TypeRef, 1640 default_type: TypeRef,
537 } 1641 }
1642
1643 /// Const generic parameter **declaration**.
1644 /// ```
1645 /// fn foo<T, U, ❰ const BAR: usize ❱, ❰ const BAZ: bool ❱>() {}
1646 /// ```
1647 ///
1648 /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter)
538 struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { 1649 struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner {
539 T![=], 1650 T![=],
540 default_val: Expr, 1651 default_val: Expr,
541 } 1652 }
1653
1654 /// Lifetime parameter **declaration**.
1655 ///
1656 /// ```
1657 /// fn foo<❰ 'a ❱, ❰ 'b ❱, V, G, D>(bar: &'a str, baz: &'b mut str) {}
1658 /// ```
1659 ///
1660 /// [Reference](https://doc.rust-lang.org/reference/items/generics.html)
542 struct LifetimeParam: AttrsOwner { T![lifetime] } 1661 struct LifetimeParam: AttrsOwner { T![lifetime] }
543 struct TypeBound { T![lifetime], /* Question, */ T![const], /* Question, */ TypeRef} 1662
1663 /// Type bound declaration clause.
1664 ///
1665 /// ```
1666 /// fn foo<T: ❰ ?Sized ❱ + ❰ Debug ❱>() {}
1667 ///
1668 /// trait Bar<T>
1669 /// where
1670 /// T: ❰ Send ❱ + ❰ Sync ❱
1671 /// {
1672 /// type Baz: ❰ !Sync ❱ + ❰ Debug ❱ + ❰ ?const Add ❱;
1673 /// }
1674 /// ```
1675 ///
1676 /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html)
1677 struct TypeBound { T![lifetime], /* Question, */ T![const], /* Question, */ TypeRef }
1678
1679 /// Type bounds list.
1680 ///
1681 /// ```
1682 ///
1683 /// fn foo<T: ❰ ?Sized + Debug ❱>() {}
1684 ///
1685 /// trait Bar<T>
1686 /// where
1687 /// T: ❰ Send + Sync ❱
1688 /// {
1689 /// type Baz: ❰ !Sync + Debug ❱;
1690 /// }
1691 /// ```
1692 ///
1693 /// [Reference](https://doc.rust-lang.org/reference/trait-bounds.html)
544 struct TypeBoundList { bounds: [TypeBound] } 1694 struct TypeBoundList { bounds: [TypeBound] }
1695
1696 /// Single where predicate.
1697 ///
1698 /// ```
1699 /// trait Foo<'a, 'b, T>
1700 /// where
1701 /// ❰ 'a: 'b ❱,
1702 /// ❰ T: IntoIterator ❱,
1703 /// ❰ for<'c> <T as IntoIterator>::Item: Bar<'c> ❱
1704 /// {}
1705 /// ```
1706 ///
1707 /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses)
545 struct WherePred: TypeBoundsOwner { T![lifetime], TypeRef } 1708 struct WherePred: TypeBoundsOwner { T![lifetime], TypeRef }
1709
1710 /// Where clause.
1711 ///
1712 /// ```
1713 /// trait Foo<'a, T> ❰ where 'a: 'static, T: Debug ❱ {}
1714 ///
1715 /// ```
1716 ///
1717 /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses)
546 struct WhereClause { T![where], predicates: [WherePred] } 1718 struct WhereClause { T![where], predicates: [WherePred] }
1719
1720 /// Abi declaration.
1721 /// Note: the abi string is optional.
1722 ///
1723 /// ```
1724 /// ❰ extern "C" ❱ {
1725 /// fn foo() {}
1726 /// }
1727 ///
1728 /// type Bar = ❰ extern ❱ fn() -> u32;
1729 ///
1730 /// type Baz = ❰ extern r#"stdcall"# ❱ fn() -> bool;
1731 /// ```
1732 ///
1733 /// - [Extern blocks reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
1734 /// - [FFI function pointers reference](https://doc.rust-lang.org/reference/items/functions.html#functions)
547 struct Abi { /*String*/ } 1735 struct Abi { /*String*/ }
1736
1737 /// Expression statement.
1738 ///
1739 /// ```
1740 /// ❰ 42; ❱
1741 /// ❰ foo(); ❱
1742 /// ❰ (); ❱
1743 /// ❰ {}; ❱
1744 ///
1745 /// // constructions with trailing curly brace can omit the semicolon
1746 /// // but only when there are satements immediately after them (this is important!)
1747 /// ❰ if bool_cond { } ❱
1748 /// ❰ loop {} ❱
1749 /// ❰ somestatment; ❱
1750 /// ```
1751 ///
1752 /// [Reference](https://doc.rust-lang.org/reference/statements.html)
548 struct ExprStmt: AttrsOwner { Expr, T![;] } 1753 struct ExprStmt: AttrsOwner { Expr, T![;] }
1754
1755 /// Let statement.
1756 ///
1757 /// ```
1758 /// ❰ #[attr] let foo; ❱
1759 /// ❰ let bar: u64; ❱
1760 /// ❰ let baz = 42; ❱
1761 /// ❰ let bruh: bool = true; ❱
1762 /// ```
1763 ///
1764 /// [Reference](https://doc.rust-lang.org/reference/statements.html#let-statements)
549 struct LetStmt: AttrsOwner, TypeAscriptionOwner { 1765 struct LetStmt: AttrsOwner, TypeAscriptionOwner {
550 T![let], 1766 T![let],
551 Pat, 1767 Pat,
@@ -553,48 +1769,192 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
553 initializer: Expr, 1769 initializer: Expr,
554 T![;], 1770 T![;],
555 } 1771 }
1772
1773 /// Condition of `if` or `while` expression.
1774 ///
1775 /// ```
1776 /// if ❰ true ❱ {}
1777 /// if ❰ let Pat(foo) = bar ❱ {}
1778 ///
1779 /// while ❰ true ❱ {}
1780 /// while ❰ let Pat(baz) = bruh ❱ {}
1781 /// ```
1782 ///
1783 /// [If expression reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
1784 /// [While expression reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
556 struct Condition { T![let], Pat, T![=], Expr } 1785 struct Condition { T![let], Pat, T![=], Expr }
557 struct Block: AttrsOwner, ModuleItemOwner { 1786
558 T!['{'], 1787 /// Parameter list **declaration**.
559 statements: [Stmt], 1788 ///
560 Expr, 1789 /// ```
561 T!['}'], 1790 /// fn foo❰ (a: u32, b: bool) ❱ -> u32 {}
562 } 1791 /// let bar = ❰ |a, b| ❱ {};
563 struct ParamList { 1792 ///
1793 /// impl Baz {
1794 /// fn bruh❰ (&self, a: u32) ❱ {}
1795 /// }
1796 /// ```
1797 ///
1798 /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)ocs to codegen script
1799 struct ParamList { // FIXME: this node is used by closure expressions too, but hey use pipes instead of parens...
564 T!['('], 1800 T!['('],
565 SelfParam, 1801 SelfParam,
566 params: [Param], 1802 params: [Param],
567 T![')'] 1803 T![')']
568 } 1804 }
1805
1806 /// Self parameter **declaration**.
1807 ///
1808 /// ```
1809 /// impl Bruh {
1810 /// fn foo(❰ self ❱) {}
1811 /// fn bar(❰ &self ❱) {}
1812 /// fn baz(❰ &mut self ❱) {}
1813 /// fn blah<'a>(❰ &'a self ❱) {}
1814 /// fn blin(❰ self: Box<Self> ❱) {}
1815 /// }
1816 /// ```
1817 ///
1818 /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
569 struct SelfParam: TypeAscriptionOwner, AttrsOwner { T![&], T![mut], T![lifetime], T![self] } 1819 struct SelfParam: TypeAscriptionOwner, AttrsOwner { T![&], T![mut], T![lifetime], T![self] }
1820
1821 /// Parameter **declaration**.
1822 ///
1823 /// ```
1824 /// fn foo(❰ #[attr] Pat(bar): Pat(u32) ❱, ❰ #[attr] _: bool ❱) {}
1825 ///
1826 /// extern "C" {
1827 /// fn bar(❰ baz: u32 ❱, ❰ ... ❱) -> u32;
1828 /// }
1829 /// ```
1830 ///
1831 /// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
570 struct Param: TypeAscriptionOwner, AttrsOwner { 1832 struct Param: TypeAscriptionOwner, AttrsOwner {
571 Pat, 1833 Pat,
572 T![...] 1834 T![...]
573 } 1835 }
1836
1837 /// Use declaration.
1838 ///
1839 /// ```
1840 /// ❰ #[attr] pub use foo; ❱
1841 /// ❰ use bar as baz; ❱
1842 /// ❰ use bruh::{self, bruuh}; ❱
1843 /// ❰ use { blin::blen, blah::* };
1844 /// ```
1845 ///
1846 /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
574 struct UseItem: AttrsOwner, VisibilityOwner { 1847 struct UseItem: AttrsOwner, VisibilityOwner {
575 T![use], 1848 T![use],
576 UseTree, 1849 UseTree,
577 } 1850 }
1851
1852 /// Use tree.
1853 ///
1854 /// ```
1855 /// pub use ❰ foo::❰ * ❱ ❱;
1856 /// use ❰ bar as baz ❱;
1857 /// use ❰ bruh::bruuh::{ ❰ self ❱, ❰ blin ❱ } ❱;
1858 /// use ❰ { ❰ blin::blen ❱ } ❱
1859 /// ```
1860 ///
1861 /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
578 struct UseTree { 1862 struct UseTree {
579 Path, T![*], UseTreeList, Alias 1863 Path, T![*], UseTreeList, Alias
580 } 1864 }
1865
1866 /// Item alias.
1867 /// Note: this is not the type alias.
1868 ///
1869 /// ```
1870 /// use foo ❰ as bar ❱;
1871 /// use baz::{bruh ❰ as _ ❱};
1872 /// extern crate bruuh ❰ as blin ❱;
1873 /// ```
1874 ///
1875 /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
581 struct Alias: NameOwner { T![as] } 1876 struct Alias: NameOwner { T![as] }
1877
1878 /// Sublist of use trees.
1879 ///
1880 /// ```
1881 /// use bruh::bruuh::❰ { ❰ self ❱, ❰ blin ❱ } ❱;
1882 /// use ❰ { blin::blen::❰ {} ❱ } ❱
1883 /// ```
1884 ///
1885 /// [Reference](https://doc.rust-lang.org/reference/items/use-declarations.html)
582 struct UseTreeList { T!['{'], use_trees: [UseTree], T!['}'] } 1886 struct UseTreeList { T!['{'], use_trees: [UseTree], T!['}'] }
1887
1888 /// Extern crate item.
1889 ///
1890 /// ```
1891 /// ❰ #[attr] pub extern crate foo; ❱
1892 /// ❰ extern crate self as bar; ❱
1893 /// ```
1894 ///
1895 /// [Reference](https://doc.rust-lang.org/reference/items/extern-crates.html)
583 struct ExternCrateItem: AttrsOwner, VisibilityOwner { 1896 struct ExternCrateItem: AttrsOwner, VisibilityOwner {
584 T![extern], T![crate], NameRef, Alias, 1897 T![extern], T![crate], NameRef, Alias,
585 } 1898 }
1899
1900 /// Call site arguments list.
1901 ///
1902 /// ```
1903 /// foo::<T, U>❰ (42, true) ❱;
1904 /// ```
1905 ///
1906 /// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
586 struct ArgList { 1907 struct ArgList {
587 T!['('], 1908 T!['('],
588 args: [Expr], 1909 args: [Expr],
589 T![')'] 1910 T![')']
590 } 1911 }
1912
1913 /// Path to a symbol. Includes single identifier names and elaborate paths with
1914 /// generic parameters.
1915 ///
1916 /// ```
1917 /// (0..10).❰ ❰ collect ❱ ::<Vec<_>> ❱();
1918 /// ❰ ❰ ❰ Vec ❱ ::<u8> ❱ ::with_capacity ❱(1024);
1919 /// ❰ ❰ <❰ Foo ❱ as ❰ ❰ bar ❱ ::Bar ❱> ❱ ::baz ❱();
1920 /// ❰ ❰ <❰ bruh ❱> ❱ ::bruuh ❱();
1921 /// ```
1922 ///
1923 /// [Reference](https://doc.rust-lang.org/reference/paths.html)
591 struct Path { 1924 struct Path {
592 segment: PathSegment, 1925 segment: PathSegment,
1926 T![::],
593 qualifier: Path, 1927 qualifier: Path,
594 } 1928 }
1929
1930 /// Segment of the path to a symbol.
1931 /// Only path segment of an absolute path holds the `::` token,
1932 /// all other `::` tokens that connect path segments reside under `Path` itself.`
1933 ///
1934 /// ```
1935 /// (0..10).❰ collect ❱ :: ❰ <Vec<_>> ❱();
1936 /// ❰ Vec ❱ :: ❰ <u8> ❱ :: ❰ with_capacity ❱(1024);
1937 /// ❰ <❰ Foo ❱ as ❰ bar ❱ :: ❰ Bar ❱> ❱ :: ❰ baz ❱();
1938 /// ❰ <❰ bruh ❱> ❱ :: ❰ bruuh ❱();
1939 ///
1940 /// // Note that only in this case `::` token is inlcuded:
1941 /// ❰ ::foo ❱;
1942 /// ```
1943 ///
1944 /// [Reference](https://doc.rust-lang.org/reference/paths.html)
595 struct PathSegment { 1945 struct PathSegment {
596 T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] 1946 T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>]
597 } 1947 }
1948
1949 /// List of type arguments that are passed at generic instantiation site.
1950 ///
1951 /// ```
1952 /// type _ = Foo ❰ ::<'a, u64, Item = Bar, 42, {true}> ❱::Bar;
1953 ///
1954 /// Vec❰ ::<bool> ❱::();
1955 /// ```
1956 ///
1957 /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
598 struct TypeArgList { 1958 struct TypeArgList {
599 T![::], 1959 T![::],
600 T![<], 1960 T![<],
@@ -605,48 +1965,142 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
605 const_args: [ConstArg], 1965 const_args: [ConstArg],
606 T![>] 1966 T![>]
607 } 1967 }
1968
1969 /// Type argument that is passed at generic instantiation site.
1970 ///
1971 /// ```
1972 /// type _ = Foo::<'a, ❰ u64 ❱, ❰ bool ❱, Item = Bar, 42>::Baz;
1973 /// ```
1974 ///
1975 /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
608 struct TypeArg { TypeRef } 1976 struct TypeArg { TypeRef }
1977
1978 /// Associated type argument that is passed at generic instantiation site.
1979 /// ```
1980 /// type Foo = Bar::<'a, u64, bool, ❰ Item = Baz ❱, 42>::Bruh;
1981 ///
1982 /// trait Bruh<T>: Iterator<❰ Item: Debug ❱> {}
1983 /// ```
1984 ///
609 struct AssocTypeArg : TypeBoundsOwner { NameRef, T![=], TypeRef } 1985 struct AssocTypeArg : TypeBoundsOwner { NameRef, T![=], TypeRef }
1986
1987 /// Lifetime argument that is passed at generic instantiation site.
1988 ///
1989 /// ```
1990 /// fn foo<'a>(s: &'a str) {
1991 /// bar::<❰ 'a ❱>(s);
1992 /// }
1993 /// ```
1994 ///
1995 /// [Reference](https://doc.rust-lang.org/reference/paths.html#paths-in-expressions)
610 struct LifetimeArg { T![lifetime] } 1996 struct LifetimeArg { T![lifetime] }
611 struct ConstArg { Literal, T![=], BlockExpr }
612 1997
613 struct MacroItems: ModuleItemOwner{ } 1998 /// Constant value argument that is passed at generic instantiation site.
1999 ///
2000 /// ```
2001 /// foo::<u32, ❰ { true } ❱>();
2002 ///
2003 /// bar::<❰ { 2 + 2} ❱>();
2004 /// ```
2005 ///
2006 /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#declaring-a-const-parameter)
2007 struct ConstArg { Literal, BlockExpr }
2008
2009
2010 /// FIXME: (@edwin0cheng) Remove it to use ItemList instead
2011 /// https://github.com/rust-analyzer/rust-analyzer/pull/4083#discussion_r422666243
2012 ///
2013 /// [Reference](https://doc.rust-lang.org/reference/macros.html)
2014 struct MacroItems: ModuleItemOwner { }
614 2015
2016 /// FIXME: (@edwin0cheng) add some documentation here. As per the writing
2017 /// of this comment this ast node is not used.
2018 ///
2019 /// ```
2020 /// // FIXME: example here
2021 /// ```
2022 ///
2023 /// [Reference](https://doc.rust-lang.org/reference/macros.html)
615 struct MacroStmts { 2024 struct MacroStmts {
616 statements: [Stmt], 2025 statements: [Stmt],
617 Expr, 2026 Expr,
618 } 2027 }
619 2028
2029 /// List of items in an extern block.
2030 ///
2031 /// ```
2032 /// extern "C" ❰
2033 /// {
2034 /// fn foo();
2035 /// static var: u32;
2036 /// }
2037 /// ❱
2038 /// ```
2039 ///
2040 /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
620 struct ExternItemList: ModuleItemOwner { 2041 struct ExternItemList: ModuleItemOwner {
621 T!['{'], 2042 T!['{'],
622 extern_items: [ExternItem], 2043 extern_items: [ExternItem],
623 T!['}'] 2044 T!['}']
624 } 2045 }
625 2046
2047 /// Extern block.
2048 ///
2049 /// ```
2050 /// ❰
2051 /// extern "C" {
2052 /// fn foo();
2053 /// }
2054 /// ❱
2055 ///
2056 /// ```
2057 ///
2058 /// [Reference](https://doc.rust-lang.org/reference/items/external-blocks.html)
626 struct ExternBlock { 2059 struct ExternBlock {
627 Abi, 2060 Abi,
628 ExternItemList 2061 ExternItemList
629 } 2062 }
630 2063
2064 /// Meta item in an attribute.
2065 ///
2066 /// ```
2067 /// #[❰ bar::baz = "42" ❱]
2068 /// #[❰ bruh(bruuh("true")) ❱]
2069 /// struct Foo;
2070 /// ```
2071 ///
2072 /// [Reference](https://doc.rust-lang.org/reference/attributes.html?highlight=meta,item#meta-item-attribute-syntax)
631 struct MetaItem { 2073 struct MetaItem {
632 Path, T![=], AttrInput, nested_meta_items: [MetaItem] 2074 Path, T![=], AttrInput, nested_meta_items: [MetaItem]
633 } 2075 }
634 2076
2077 /// Macro 2.0 definition.
2078 /// Their syntax is still WIP by rustc team...
2079 /// ```
2080 /// ❰
2081 /// macro foo { }
2082 /// ❱
2083 /// ```
2084 ///
2085 /// [RFC](https://github.com/rust-lang/rfcs/blob/master/text/1584-macros.md)
635 struct MacroDef { 2086 struct MacroDef {
636 Name, TokenTree 2087 Name, TokenTree
637 } 2088 }
638 }, 2089 },
639 enums: &ast_enums! { 2090 enums: &ast_enums! {
2091 /// Any kind of nominal type definition.
640 enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner { 2092 enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner {
641 StructDef, EnumDef, UnionDef, 2093 StructDef, EnumDef, UnionDef,
642 } 2094 }
643 2095
2096 /// Any kind of **declared** generic parameter
644 enum GenericParam { 2097 enum GenericParam {
645 LifetimeParam, 2098 LifetimeParam,
646 TypeParam, 2099 TypeParam,
647 ConstParam 2100 ConstParam
648 } 2101 }
649 2102
2103 /// Any kind of generic argument passed at instantiation site
650 enum GenericArg { 2104 enum GenericArg {
651 LifetimeArg, 2105 LifetimeArg,
652 TypeArg, 2106 TypeArg,
@@ -654,6 +2108,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
654 AssocTypeArg 2108 AssocTypeArg
655 } 2109 }
656 2110
2111 /// Any kind of construct valid in type context
657 enum TypeRef { 2112 enum TypeRef {
658 ParenType, 2113 ParenType,
659 TupleType, 2114 TupleType,
@@ -670,6 +2125,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
670 DynTraitType, 2125 DynTraitType,
671 } 2126 }
672 2127
2128 /// Any kind of top-level item that may appear in a module
673 enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner { 2129 enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner {
674 StructDef, 2130 StructDef,
675 UnionDef, 2131 UnionDef,
@@ -687,16 +2143,23 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
687 ExternBlock 2143 ExternBlock
688 } 2144 }
689 2145
690 /* impl blocks can also contain MacroCall */ 2146
691 enum ImplItem: NameOwner, AttrsOwner { 2147
2148 /// Any kind of item that may appear in an impl block
2149 ///
2150 /// // FIXME: impl blocks can also contain MacroCall
2151 enum AssocItem: NameOwner, AttrsOwner {
692 FnDef, TypeAliasDef, ConstDef 2152 FnDef, TypeAliasDef, ConstDef
693 } 2153 }
694 2154
695 /* extern blocks can also contain MacroCall */ 2155 /// Any kind of item that may appear in an extern block
2156 ///
2157 /// // FIXME: extern blocks can also contain MacroCall
696 enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner { 2158 enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner {
697 FnDef, StaticDef 2159 FnDef, StaticDef
698 } 2160 }
699 2161
2162 /// Any kind of expression
700 enum Expr: AttrsOwner { 2163 enum Expr: AttrsOwner {
701 TupleExpr, 2164 TupleExpr,
702 ArrayExpr, 2165 ArrayExpr,
@@ -720,6 +2183,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
720 FieldExpr, 2183 FieldExpr,
721 AwaitExpr, 2184 AwaitExpr,
722 TryExpr, 2185 TryExpr,
2186 EffectExpr,
723 CastExpr, 2187 CastExpr,
724 RefExpr, 2188 RefExpr,
725 PrefixExpr, 2189 PrefixExpr,
@@ -730,6 +2194,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
730 BoxExpr, 2194 BoxExpr,
731 } 2195 }
732 2196
2197 /// Any kind of pattern
733 enum Pat { 2198 enum Pat {
734 OrPat, 2199 OrPat,
735 ParenPat, 2200 ParenPat,
@@ -748,18 +2213,26 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
748 MacroPat, 2213 MacroPat,
749 } 2214 }
750 2215
2216 /// Any kind of pattern that appears directly inside of the curly
2217 /// braces of a record pattern
751 enum RecordInnerPat { 2218 enum RecordInnerPat {
752 RecordFieldPat, 2219 RecordFieldPat,
753 BindPat 2220 BindPat
754 } 2221 }
755 2222
2223 /// Any kind of input to an attribute
756 enum AttrInput { Literal, TokenTree } 2224 enum AttrInput { Literal, TokenTree }
2225
2226 /// Any kind of statement
2227 /// Note: there are no empty statements, these are just represented as
2228 /// bare semicolons without a dedicated statement ast node.
757 enum Stmt { 2229 enum Stmt {
758 LetStmt, 2230 LetStmt,
759 ExprStmt, 2231 ExprStmt,
760 // macro calls are parsed as expression statements */ 2232 // macro calls are parsed as expression statements
761 } 2233 }
762 2234
2235 /// Any kind of fields list (record or tuple field lists)
763 enum FieldDefList { 2236 enum FieldDefList {
764 RecordFieldDefList, 2237 RecordFieldDefList,
765 TupleFieldDefList, 2238 TupleFieldDefList,
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs
index 0e4dcb95a..b4907f4b2 100644
--- a/xtask/src/codegen.rs
+++ b/xtask/src/codegen.rs
@@ -27,7 +27,7 @@ const AST_NODES: &str = "crates/ra_syntax/src/ast/generated/nodes.rs";
27const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs"; 27const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs";
28 28
29const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; 29const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers";
30const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs"; 30const ASSISTS_TESTS: &str = "crates/ra_assists/src/tests/generated.rs";
31const ASSISTS_DOCS: &str = "docs/user/assists.md"; 31const ASSISTS_DOCS: &str = "docs/user/assists.md";
32 32
33#[derive(Debug, PartialEq, Eq, Clone, Copy)] 33#[derive(Debug, PartialEq, Eq, Clone, Copy)]
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs
index 31d606535..4bd6b5f0c 100644
--- a/xtask/src/codegen/gen_assists_docs.rs
+++ b/xtask/src/codegen/gen_assists_docs.rs
@@ -101,14 +101,14 @@ fn collect_assists() -> Result<Vec<Assist>> {
101} 101}
102 102
103fn generate_tests(assists: &[Assist], mode: Mode) -> Result<()> { 103fn generate_tests(assists: &[Assist], mode: Mode) -> Result<()> {
104 let mut buf = String::from("use super::check;\n"); 104 let mut buf = String::from("use super::check_doc_test;\n");
105 105
106 for assist in assists.iter() { 106 for assist in assists.iter() {
107 let test = format!( 107 let test = format!(
108 r######" 108 r######"
109#[test] 109#[test]
110fn doctest_{}() {{ 110fn doctest_{}() {{
111 check( 111 check_doc_test(
112 "{}", 112 "{}",
113r#####" 113r#####"
114{}"#####, r#####" 114{}"#####, r#####"
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index e9dc09552..19d5594f5 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -3,7 +3,7 @@
3//! Specifically, it generates the `SyntaxKind` enum and a number of newtype 3//! Specifically, it generates the `SyntaxKind` enum and a number of newtype
4//! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. 4//! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`.
5 5
6use std::collections::HashSet; 6use std::{collections::HashSet, fmt::Write};
7 7
8use proc_macro2::{Punct, Spacing}; 8use proc_macro2::{Punct, Spacing};
9use quote::{format_ident, quote}; 9use quote::{format_ident, quote};
@@ -102,6 +102,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
102 }); 102 });
103 ( 103 (
104 quote! { 104 quote! {
105 #[pretty_doc_comment_placeholder_workaround]
105 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 106 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
106 pub struct #name { 107 pub struct #name {
107 pub(crate) syntax: SyntaxNode, 108 pub(crate) syntax: SyntaxNode,
@@ -145,6 +146,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
145 146
146 ( 147 (
147 quote! { 148 quote! {
149 #[pretty_doc_comment_placeholder_workaround]
148 #[derive(Debug, Clone, PartialEq, Eq, Hash)] 150 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
149 pub enum #name { 151 pub enum #name {
150 #(#variants(#variants),)* 152 #(#variants(#variants),)*
@@ -230,10 +232,29 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> {
230 }; 232 };
231 233
232 let ast = ast.to_string().replace("T ! [ ", "T![").replace(" ] )", "])"); 234 let ast = ast.to_string().replace("T ! [ ", "T![").replace(" ] )", "])");
233 let pretty = crate::reformat(ast)?.replace("#[derive", "\n#[derive"); 235
236 let mut res = String::with_capacity(ast.len() * 2);
237
238 let mut docs =
239 grammar.nodes.iter().map(|it| it.doc).chain(grammar.enums.iter().map(|it| it.doc));
240
241 for chunk in ast.split("# [ pretty_doc_comment_placeholder_workaround ]") {
242 res.push_str(chunk);
243 if let Some(doc) = docs.next() {
244 write_doc_comment(doc, &mut res);
245 }
246 }
247
248 let pretty = crate::reformat(res)?;
234 Ok(pretty) 249 Ok(pretty)
235} 250}
236 251
252fn write_doc_comment(contents: &[&str], dest: &mut String) {
253 for line in contents {
254 writeln!(dest, "///{}", line).unwrap();
255 }
256}
257
237fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> { 258fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> {
238 let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar 259 let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar
239 .punct 260 .punct
@@ -432,6 +453,7 @@ impl Field<'_> {
432 ":" => "colon", 453 ":" => "colon",
433 "::" => "coloncolon", 454 "::" => "coloncolon",
434 "#" => "pound", 455 "#" => "pound",
456 "?" => "question_mark",
435 _ => name, 457 _ => name,
436 }; 458 };
437 format_ident!("{}_token", name) 459 format_ident!("{}_token", name)
diff --git a/xtask/tests/tidy-tests/cli.rs b/xtask/tests/tidy-tests/cli.rs
deleted file mode 100644
index f5b00a8b8..000000000
--- a/xtask/tests/tidy-tests/cli.rs
+++ /dev/null
@@ -1,32 +0,0 @@
1use xtask::{
2 codegen::{self, Mode},
3 run_rustfmt,
4};
5
6#[test]
7fn generated_grammar_is_fresh() {
8 if let Err(error) = codegen::generate_syntax(Mode::Verify) {
9 panic!("{}. Please update it by running `cargo xtask codegen`", error);
10 }
11}
12
13#[test]
14fn generated_tests_are_fresh() {
15 if let Err(error) = codegen::generate_parser_tests(Mode::Verify) {
16 panic!("{}. Please update tests by running `cargo xtask codegen`", error);
17 }
18}
19
20#[test]
21fn generated_assists_are_fresh() {
22 if let Err(error) = codegen::generate_assists_docs(Mode::Verify) {
23 panic!("{}. Please update assists by running `cargo xtask codegen`", error);
24 }
25}
26
27#[test]
28fn check_code_formatting() {
29 if let Err(error) = run_rustfmt(Mode::Verify) {
30 panic!("{}. Please format the code by running `cargo format`", error);
31 }
32}
diff --git a/xtask/tests/tidy-tests/main.rs b/xtask/tests/tidy.rs
index ead642acc..2e9fcf07c 100644
--- a/xtask/tests/tidy-tests/main.rs
+++ b/xtask/tests/tidy.rs
@@ -1,11 +1,41 @@
1mod cli;
2
3use std::{ 1use std::{
4 collections::HashMap, 2 collections::HashMap,
5 path::{Path, PathBuf}, 3 path::{Path, PathBuf},
6}; 4};
7 5
8use xtask::{not_bash::fs2, project_root, rust_files}; 6use xtask::{
7 codegen::{self, Mode},
8 not_bash::fs2,
9 project_root, run_rustfmt, rust_files,
10};
11
12#[test]
13fn generated_grammar_is_fresh() {
14 if let Err(error) = codegen::generate_syntax(Mode::Verify) {
15 panic!("{}. Please update it by running `cargo xtask codegen`", error);
16 }
17}
18
19#[test]
20fn generated_tests_are_fresh() {
21 if let Err(error) = codegen::generate_parser_tests(Mode::Verify) {
22 panic!("{}. Please update tests by running `cargo xtask codegen`", error);
23 }
24}
25
26#[test]
27fn generated_assists_are_fresh() {
28 if let Err(error) = codegen::generate_assists_docs(Mode::Verify) {
29 panic!("{}. Please update assists by running `cargo xtask codegen`", error);
30 }
31}
32
33#[test]
34fn check_code_formatting() {
35 if let Err(error) = run_rustfmt(Mode::Verify) {
36 panic!("{}. Please format the code by running `cargo format`", error);
37 }
38}
9 39
10#[test] 40#[test]
11fn rust_files_are_tidy() { 41fn rust_files_are_tidy() {
@@ -24,9 +54,10 @@ fn check_todo(path: &Path, text: &str) {
24 // This file itself is whitelisted since this test itself contains matches. 54 // This file itself is whitelisted since this test itself contains matches.
25 "tests/cli.rs", 55 "tests/cli.rs",
26 // Some of our assists generate `todo!()` so those files are whitelisted. 56 // Some of our assists generate `todo!()` so those files are whitelisted.
27 "doc_tests/generated.rs", 57 "tests/generated.rs",
28 "handlers/add_missing_impl_members.rs", 58 "handlers/add_missing_impl_members.rs",
29 "handlers/add_function.rs", 59 "handlers/add_function.rs",
60 "handlers/add_turbo_fish.rs",
30 // To support generating `todo!()` in assists, we have `expr_todo()` in ast::make. 61 // To support generating `todo!()` in assists, we have `expr_todo()` in ast::make.
31 "ast/make.rs", 62 "ast/make.rs",
32 ]; 63 ];
@@ -106,7 +137,6 @@ impl TidyDocs {
106 } 137 }
107 138
108 let whitelist = [ 139 let whitelist = [
109 "ra_db",
110 "ra_hir", 140 "ra_hir",
111 "ra_hir_expand", 141 "ra_hir_expand",
112 "ra_ide", 142 "ra_ide",
@@ -115,7 +145,6 @@ impl TidyDocs {
115 "ra_prof", 145 "ra_prof",
116 "ra_project_model", 146 "ra_project_model",
117 "ra_syntax", 147 "ra_syntax",
118 "ra_text_edit",
119 "ra_tt", 148 "ra_tt",
120 "ra_hir_ty", 149 "ra_hir_ty",
121 ]; 150 ];