aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/gen_lsp_server/Cargo.toml3
-rw-r--r--crates/gen_lsp_server/src/msg.rs12
-rw-r--r--crates/ra_analysis/src/completion.rs466
-rw-r--r--crates/ra_analysis/src/completion/complete_fn_param.rs102
-rw-r--r--crates/ra_analysis/src/completion/complete_keyword.rs204
-rw-r--r--crates/ra_analysis/src/completion/complete_path.rs95
-rw-r--r--crates/ra_analysis/src/completion/complete_scope.rs173
-rw-r--r--crates/ra_analysis/src/completion/complete_snippet.rs73
-rw-r--r--crates/ra_analysis/src/completion/completion_context.rs156
-rw-r--r--crates/ra_analysis/src/completion/completion_item.rs214
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs294
-rw-r--r--crates/ra_analysis/src/db.rs12
-rw-r--r--crates/ra_analysis/src/imp.rs25
-rw-r--r--crates/ra_analysis/src/lib.rs52
-rw-r--r--crates/ra_analysis/src/symbol_index.rs4
-rw-r--r--crates/ra_analysis/tests/tests.rs62
-rw-r--r--crates/ra_db/src/input.rs62
-rw-r--r--crates/ra_db/src/lib.rs2
-rw-r--r--crates/ra_db/src/loc2id.rs7
-rw-r--r--crates/ra_editor/src/folding_ranges.rs74
-rw-r--r--crates/ra_editor/src/typing.rs58
-rw-r--r--crates/ra_hir/src/function.rs2
-rw-r--r--crates/ra_hir/src/function/scope.rs48
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/module.rs2
-rw-r--r--crates/ra_hir/src/module/imp.rs8
-rw-r--r--crates/ra_hir/src/module/nameres.rs2
-rw-r--r--crates/ra_hir/src/module/nameres/tests.rs19
-rw-r--r--crates/ra_hir/src/path.rs21
-rw-r--r--crates/ra_hir/src/source_binder.rs12
-rw-r--r--crates/ra_lsp_server/Cargo.toml1
-rw-r--r--crates/ra_lsp_server/src/conv.rs78
-rw-r--r--crates/ra_lsp_server/src/main.rs4
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs58
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs39
-rw-r--r--crates/ra_lsp_server/src/req.rs2
-rw-r--r--crates/ra_lsp_server/src/server_world.rs11
-rw-r--r--crates/ra_syntax/src/ast.rs2
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs12
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs20
-rw-r--r--crates/ra_syntax/src/grammar/items.rs4
-rw-r--r--crates/ra_syntax/src/grammar/items/traits.rs2
-rw-r--r--crates/ra_syntax/src/grammar/items/use_item.rs2
-rw-r--r--crates/ra_syntax/src/grammar/type_args.rs2
-rw-r--r--crates/ra_syntax/src/grammar/type_params.rs9
-rw-r--r--crates/ra_syntax/src/grammar/types.rs6
-rw-r--r--crates/ra_syntax/src/lexer.rs2
-rw-r--r--crates/ra_syntax/src/string_lexing/byte.rs2
-rw-r--r--crates/ra_syntax/src/string_lexing/byte_string.rs2
-rw-r--r--crates/ra_syntax/src/string_lexing/char.rs2
-rw-r--r--crates/ra_syntax/src/string_lexing/string.rs2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0028_macro_2.0.rs (renamed from crates/ra_syntax/tests/data/parser/ok/0034_macro_2.0.rs)1
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0028_macro_2.0.txt (renamed from crates/ra_syntax/tests/data/parser/ok/0034_macro_2.0.txt)4
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0058_type_arg.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0063_lambda_expr.txt91
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt148
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0001_array_type_missing_semi.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0023_array_type_missing_semi.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0001_array_type_missing_semi.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0023_array_type_missing_semi.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0108_misplaced_label_err.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0108_misplaced_label_err.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0003_pointer_type_no_mutability.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0021_pointer_type_no_mutability.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0003_pointer_type_no_mutability.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0021_pointer_type_no_mutability.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0111_impl_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0111_impl_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0005_fn_pointer_type_missing_fn.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0006_unsafe_block_in_mod.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0013_unsafe_block_in_mod.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/err/0006_unsafe_block_in_mod.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0013_unsafe_block_in_mod.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0049_trait_item_list.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0049_trait_item_list.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0002_use_tree_list.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0118_use_tree_list.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0002_use_tree_list.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0118_use_tree_list.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0004_value_parameters_no_patterns.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0096_value_parameters_no_patterns.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0004_value_parameters_no_patterns.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0096_value_parameters_no_patterns.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0060_function_type_params.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0060_function_type_params.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0055_self_param.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0055_self_param.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0041_type_param_bounds.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0041_type_param_bounds.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0008_path_part.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0072_path_part.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0008_path_part.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0072_path_part.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0009_loop_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0084_loop_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0009_loop_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0084_loop_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0010_extern_block.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0003_extern_block.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0010_extern_block.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0003_extern_block.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0011_field_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0052_field_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0011_field_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0052_field_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0016_type_item_where_clause.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0016_type_item_where_clause.txt)1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0013_pointer_type_mut.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0022_pointer_type_mut.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0013_pointer_type_mut.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0022_pointer_type_mut.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0014_never_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0020_never_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0014_never_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0020_never_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0015_continue_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0105_continue_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0015_continue_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0105_continue_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0016_unsafe_trait.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0007_unsafe_trait.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0016_unsafe_trait.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0007_unsafe_trait.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0017_array_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0024_array_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0017_array_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0024_array_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0104_arb_self_types.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0104_arb_self_types.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0019_unary_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0074_unary_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0019_unary_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0074_unary_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0020_use_star.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0116_use_star.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0020_use_star.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0116_use_star.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0073_impl_item_list.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0073_impl_item_list.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0022_crate_visibility.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0037_crate_visibility.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0022_crate_visibility.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0037_crate_visibility.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0023_placeholder_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0027_placeholder_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0023_placeholder_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0027_placeholder_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0024_slice_pat.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0089_slice_pat.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0024_slice_pat.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0089_slice_pat.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0025_slice_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0025_slice_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0025_slice_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0025_slice_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0026_tuple_pat_fields.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0071_tuple_pat_fields.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0026_tuple_pat_fields.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0071_tuple_pat_fields.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0027_ref_pat.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0035_ref_pat.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0027_ref_pat.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0035_ref_pat.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0063_impl_trait_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0063_impl_trait_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0079_cast_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0079_cast_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0030_cond.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0076_cond.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0030_cond.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0076_cond.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0031_while_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0077_while_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0031_while_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0077_while_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0032_fn_pointer_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0028_fn_pointer_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0032_fn_pointer_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0028_fn_pointer_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0033_reference_type;.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0026_reference_type;.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0033_reference_type;.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0026_reference_type;.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0034_break_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0106_break_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0034_break_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0106_break_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0068_pub_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0068_pub_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0036_unsafe_extern_fn.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0012_unsafe_extern_fn.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0036_unsafe_extern_fn.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0012_unsafe_extern_fn.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0037_qual_paths.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0101_qual_paths.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0037_qual_paths.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0101_qual_paths.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0038_full_range_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0102_full_range_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0038_full_range_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0102_full_range_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0039_type_arg.rs1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0039_type_arg.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0058_type_arg.txt)8
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0099_crate_keyword_vis.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0099_crate_keyword_vis.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0056_trait_item.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0056_trait_item.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0043_call_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0043_call_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0043_use_alias.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0115_use_alias.rs)2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0043_use_alias.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0115_use_alias.txt)41
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0044_block_items.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0053_block_items.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0044_block_items.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0053_block_items.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0097_param_list_opt_patterns.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0097_param_list_opt_patterns.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0046_singleton_tuple_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0019_singleton_tuple_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0046_singleton_tuple_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0019_singleton_tuple_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0010_unsafe_default_impl.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0010_unsafe_default_impl.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0095_path_type_with_bounds.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0095_path_type_with_bounds.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0049_let_stmt;.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0050_let_stmt;.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0049_let_stmt;.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0050_let_stmt;.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0050_fn_decl.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0091_fn_decl.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0050_fn_decl.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0091_fn_decl.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0051_unit_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0018_unit_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0051_unit_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0018_unit_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0052_path_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0032_path_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0052_path_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0032_path_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0053_path_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0039_path_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0053_path_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0039_path_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0054_field_attrs.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0103_field_attrs.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0054_field_attrs.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0103_field_attrs.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0092_literal_pattern.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0092_literal_pattern.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0098_where_clause.rs)1
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0098_where_clause.txt)44
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0057_const_fn.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0002_const_fn.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0057_const_fn.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0002_const_fn.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0059_match_arms_commas.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0085_match_arms_commas.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0059_match_arms_commas.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0085_match_arms_commas.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0005_extern_crate.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0005_extern_crate.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0061_struct_lit.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0061_struct_lit.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0061_struct_lit.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0061_struct_lit.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0062_mod_contents.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0078_mod_contents.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0062_mod_contents.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0078_mod_contents.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0048_impl_item_neg.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0048_impl_item_neg.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0064_if_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0065_if_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0064_if_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0065_if_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0100_dyn_trait_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0100_dyn_trait_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0069_match_arm.rs)2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt146
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0067_crate_path.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0112_crate_path.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0067_crate_path.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0112_crate_path.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0068_union_items.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0110_union_items.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0068_union_items.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0110_union_items.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0069_use_tree_list_after_path.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0117_use_tree_list_after_path.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0069_use_tree_list_after_path.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0117_use_tree_list_after_path.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0070_stmt_bin_expr_ambiguity.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0071_match_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0070_match_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0071_match_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0070_match_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0072_return_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0068_return_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0072_return_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0068_return_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0073_type_item_type_params.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0014_type_item_type_params.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0073_type_item_type_params.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0014_type_item_type_params.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0074_stmt_postfix_expr_ambiguity.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0075_block.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0045_block.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0075_block.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0045_block.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0076_function_where_clause.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0059_function_where_clause.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0076_function_where_clause.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0059_function_where_clause.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0077_try_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0075_try_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0077_try_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0075_try_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0078_type_item.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0015_type_item.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0078_type_item.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0015_type_item.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0047_impl_item.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0079_impl_item.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0047_impl_item.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0080_postfix_range.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0083_postfix_range.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0080_postfix_range.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0083_postfix_range.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0081_for_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0031_for_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0081_for_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0031_for_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0082_ref_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0044_ref_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0082_ref_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0044_ref_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0083_struct_items.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0109_struct_items.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0083_struct_items.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0109_struct_items.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0084_paren_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0017_paren_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0084_paren_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0017_paren_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0085_expr_literals.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0040_expr_literals.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0085_expr_literals.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0040_expr_literals.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0086_function_ret_type.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0038_function_ret_type.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0086_function_ret_type.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0038_function_ret_type.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0087_unsafe_impl.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0008_unsafe_impl.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0087_unsafe_impl.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0008_unsafe_impl.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0088_break_ambiguity.rs6
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0088_break_ambiguity.txt65
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0089_extern_fn.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0004_extern_fn.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0089_extern_fn.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0004_extern_fn.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0090_type_param_default.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0042_type_param_default.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0090_type_param_default.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0042_type_param_default.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0091_auto_trait.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0057_auto_trait.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0091_auto_trait.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0057_auto_trait.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0092_fn_pointer_type_with_ret.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0030_fn_pointer_type_with_ret.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0092_fn_pointer_type_with_ret.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0030_fn_pointer_type_with_ret.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0093_index_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0081_index_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0093_index_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0081_index_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0094_unsafe_auto_trait.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0009_unsafe_auto_trait.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0094_unsafe_auto_trait.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0009_unsafe_auto_trait.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0095_placeholder_pat.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0036_placeholder_pat.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0095_placeholder_pat.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0036_placeholder_pat.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0096_no_semi_after_block.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0096_no_semi_after_block.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0097_default_impl.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0046_default_impl.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0097_default_impl.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0046_default_impl.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0098_const_unsafe_fn.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0001_const_unsafe_fn.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0098_const_unsafe_fn.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0001_const_unsafe_fn.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0099_param_list.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0064_param_list.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0099_param_list.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0064_param_list.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0100_for_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0085_for_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0100_for_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0085_for_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0101_unsafe_fn.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0011_unsafe_fn.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0101_unsafe_fn.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0011_unsafe_fn.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0102_field_pat_list.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0054_field_pat_list.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0102_field_pat_list.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0054_field_pat_list.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0103_array_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0086_array_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0103_array_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0086_array_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0104_path_fn_trait_args.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0093_path_fn_trait_args.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0104_path_fn_trait_args.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0093_path_fn_trait_args.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0105_block_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0067_block_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0105_block_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0067_block_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0066_lambda_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0106_lambda_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0066_lambda_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0107_method_call_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0051_method_call_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0107_method_call_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0051_method_call_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0108_tuple_expr.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0080_tuple_expr.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0108_tuple_expr.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0080_tuple_expr.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0109_label.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0107_label.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0109_label.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0107_label.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0110_use_path.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0114_use_path.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0110_use_path.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0114_use_path.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0111_tuple_pat.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0082_tuple_pat.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0111_tuple_pat.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0082_tuple_pat.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.rs (renamed from crates/ra_syntax/tests/data/parser/inline/0034_bind_pat.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0112_bind_pat.txt (renamed from crates/ra_syntax/tests/data/parser/inline/0034_bind_pat.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0113_nocontentexpr.rs3
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0113_nocontentexpr.txt56
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0029_range_forms.txt44
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0034_crate_path_in_call.rs (renamed from crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0034_crate_path_in_call.txt (renamed from crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.txt)0
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0034_macro_stuck.txt250
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.rs154
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt2244
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.rs8
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0036_fully_qualified.txt88
-rw-r--r--crates/ra_syntax/tests/test.rs48
-rw-r--r--crates/ra_text_edit/src/text_edit.rs4
-rw-r--r--crates/test_utils/src/lib.rs61
-rw-r--r--crates/tools/src/bin/pre-commit.rs3
-rw-r--r--crates/tools/src/lib.rs10
-rw-r--r--crates/tools/src/main.rs77
308 files changed, 4569 insertions, 1571 deletions
diff --git a/crates/gen_lsp_server/Cargo.toml b/crates/gen_lsp_server/Cargo.toml
index 6c91e38aa..9776a82e3 100644
--- a/crates/gen_lsp_server/Cargo.toml
+++ b/crates/gen_lsp_server/Cargo.toml
@@ -12,6 +12,5 @@ languageserver-types = "0.53.0"
12log = "0.4.3" 12log = "0.4.3"
13failure = "0.1.2" 13failure = "0.1.2"
14serde_json = "1.0.24" 14serde_json = "1.0.24"
15serde = "1.0.71" 15serde = { version = "1.0.71", features = ["derive"] }
16serde_derive = "1.0.71"
17crossbeam-channel = "0.2.4" 16crossbeam-channel = "0.2.4"
diff --git a/crates/gen_lsp_server/src/msg.rs b/crates/gen_lsp_server/src/msg.rs
index 22d273d55..f68cbc541 100644
--- a/crates/gen_lsp_server/src/msg.rs
+++ b/crates/gen_lsp_server/src/msg.rs
@@ -1,13 +1,13 @@
1use std::io::{BufRead, Write}; 1use std::io::{BufRead, Write};
2 2
3use languageserver_types::{notification::Notification, request::Request}; 3use languageserver_types::{notification::Notification, request::Request};
4use serde_derive::{Deserialize, Serialize}; 4use serde::{Deserialize, Serialize};
5use serde_json::{from_str, from_value, to_string, to_value, Value}; 5use serde_json::{from_str, from_value, to_string, to_value, Value};
6use failure::{bail, format_err}; 6use failure::{bail, format_err};
7 7
8use crate::Result; 8use crate::Result;
9 9
10#[derive(Debug, Serialize, Deserialize, Clone)] 10#[derive(Serialize, Deserialize, Debug, Clone)]
11#[serde(untagged)] 11#[serde(untagged)]
12pub enum RawMessage { 12pub enum RawMessage {
13 Request(RawRequest), 13 Request(RawRequest),
@@ -152,12 +152,18 @@ impl RawNotification {
152 params: to_value(params).unwrap(), 152 params: to_value(params).unwrap(),
153 } 153 }
154 } 154 }
155 pub fn is<N>(&self) -> bool
156 where
157 N: Notification,
158 {
159 self.method == N::METHOD
160 }
155 pub fn cast<N>(self) -> ::std::result::Result<N::Params, RawNotification> 161 pub fn cast<N>(self) -> ::std::result::Result<N::Params, RawNotification>
156 where 162 where
157 N: Notification, 163 N: Notification,
158 N::Params: serde::de::DeserializeOwned, 164 N::Params: serde::de::DeserializeOwned,
159 { 165 {
160 if self.method != N::METHOD { 166 if !self.is::<N>() {
161 return Err(self); 167 return Err(self);
162 } 168 }
163 Ok(from_value(self.params).unwrap()) 169 Ok(from_value(self.params).unwrap())
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs
index f480af611..d742d6295 100644
--- a/crates/ra_analysis/src/completion.rs
+++ b/crates/ra_analysis/src/completion.rs
@@ -1,444 +1,60 @@
1mod reference_completion; 1mod completion_item;
2mod completion_context;
3
4mod complete_fn_param;
5mod complete_keyword;
6mod complete_snippet;
7mod complete_path;
8mod complete_scope;
2 9
3use ra_editor::find_node_at_offset;
4use ra_text_edit::AtomTextEdit;
5use ra_syntax::{
6 algo::visit::{visitor_ctx, VisitorCtx},
7 ast,
8 AstNode,
9 SyntaxNodeRef,
10};
11use ra_db::SyntaxDatabase; 10use ra_db::SyntaxDatabase;
12use rustc_hash::{FxHashMap};
13use hir::source_binder;
14 11
15use crate::{ 12use crate::{
16 db, 13 db,
17 Cancelable, FilePosition 14 Cancelable, FilePosition,
15 completion::{
16 completion_item::{Completions, CompletionKind},
17 completion_context::CompletionContext,
18 },
18}; 19};
19 20
20#[derive(Debug)] 21pub use crate::completion::completion_item::{CompletionItem, InsertText, CompletionItemKind};
21pub struct CompletionItem {
22 /// What user sees in pop-up
23 pub label: String,
24 /// What string is used for filtering, defaults to label
25 pub lookup: Option<String>,
26 /// What is inserted, defaults to label
27 pub snippet: Option<String>,
28}
29 22
23/// Main entry point for copmletion. We run comletion as a two-phase process.
24///
25/// First, we look at the position and collect a so-called `CompletionContext.
26/// This is a somewhat messy process, because, during completion, syntax tree is
27/// incomplete and can look readlly weired.
28///
29/// Once the context is collected, we run a series of completion routines whihc
30/// look at the context and produce completion items.
30pub(crate) fn completions( 31pub(crate) fn completions(
31 db: &db::RootDatabase, 32 db: &db::RootDatabase,
32 position: FilePosition, 33 position: FilePosition,
33) -> Cancelable<Option<Vec<CompletionItem>>> { 34) -> Cancelable<Option<Completions>> {
34 let original_file = db.source_file(position.file_id); 35 let original_file = db.source_file(position.file_id);
35 // Insert a fake ident to get a valid parse tree 36 let ctx = ctry!(CompletionContext::new(db, &original_file, position)?);
36 let file = {
37 let edit = AtomTextEdit::insert(position.offset, "intellijRulezz".to_string());
38 original_file.reparse(&edit)
39 };
40
41 let module = ctry!(source_binder::module_from_position(db, position)?);
42 37
43 let mut res = Vec::new(); 38 let mut acc = Completions::default();
44 let mut has_completions = false;
45 // First, let's try to complete a reference to some declaration.
46 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
47 has_completions = true;
48 reference_completion::completions(&mut res, db, &module, &file, name_ref)?;
49 // special case, `trait T { fn foo(i_am_a_name_ref) {} }`
50 if is_node::<ast::Param>(name_ref.syntax()) {
51 param_completions(name_ref.syntax(), &mut res);
52 }
53 }
54 39
55 // Otherwise, if this is a declaration, use heuristics to suggest a name. 40 complete_fn_param::complete_fn_param(&mut acc, &ctx);
56 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { 41 complete_keyword::complete_expr_keyword(&mut acc, &ctx);
57 if is_node::<ast::Param>(name.syntax()) { 42 complete_snippet::complete_expr_snippet(&mut acc, &ctx);
58 has_completions = true; 43 complete_snippet::complete_item_snippet(&mut acc, &ctx);
59 param_completions(name.syntax(), &mut res); 44 complete_path::complete_path(&mut acc, &ctx)?;
60 } 45 complete_scope::complete_scope(&mut acc, &ctx)?;
61 }
62 let res = if has_completions { Some(res) } else { None };
63 Ok(res)
64}
65
66fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec<CompletionItem>) {
67 let mut params = FxHashMap::default();
68 for node in ctx.ancestors() {
69 let _ = visitor_ctx(&mut params)
70 .visit::<ast::SourceFile, _>(process)
71 .visit::<ast::ItemList, _>(process)
72 .accept(node);
73 }
74 params
75 .into_iter()
76 .filter_map(|(label, (count, param))| {
77 let lookup = param.pat()?.syntax().text().to_string();
78 if count < 2 {
79 None
80 } else {
81 Some((label, lookup))
82 }
83 })
84 .for_each(|(label, lookup)| {
85 acc.push(CompletionItem {
86 label,
87 lookup: Some(lookup),
88 snippet: None,
89 })
90 });
91
92 fn process<'a, N: ast::FnDefOwner<'a>>(
93 node: N,
94 params: &mut FxHashMap<String, (u32, ast::Param<'a>)>,
95 ) {
96 node.functions()
97 .filter_map(|it| it.param_list())
98 .flat_map(|it| it.params())
99 .for_each(|param| {
100 let text = param.syntax().text().to_string();
101 params.entry(text).or_insert((0, param)).0 += 1;
102 })
103 }
104}
105 46
106fn is_node<'a, N: AstNode<'a>>(node: SyntaxNodeRef<'a>) -> bool { 47 Ok(Some(acc))
107 match node.ancestors().filter_map(N::cast).next() {
108 None => false,
109 Some(n) => n.syntax().range() == node.range(),
110 }
111} 48}
112 49
113#[cfg(test)] 50#[cfg(test)]
114mod tests { 51fn check_completion(code: &str, expected_completions: &str, kind: CompletionKind) {
115 use test_utils::assert_eq_dbg; 52 use crate::mock_analysis::{single_file_with_position, analysis_and_position};
116 53 let (analysis, position) = if code.contains("//-") {
117 use crate::mock_analysis::single_file_with_position; 54 analysis_and_position(code)
118 55 } else {
119 use super::*; 56 single_file_with_position(code)
120 57 };
121 fn check_scope_completion(code: &str, expected_completions: &str) { 58 let completions = completions(&analysis.imp.db, position).unwrap().unwrap();
122 let (analysis, position) = single_file_with_position(code); 59 completions.assert_match(expected_completions, kind);
123 let completions = completions(&analysis.imp.db, position)
124 .unwrap()
125 .unwrap()
126 .into_iter()
127 .filter(|c| c.snippet.is_none())
128 .collect::<Vec<_>>();
129 assert_eq_dbg(expected_completions, &completions);
130 }
131
132 fn check_snippet_completion(code: &str, expected_completions: &str) {
133 let (analysis, position) = single_file_with_position(code);
134 let completions = completions(&analysis.imp.db, position)
135 .unwrap()
136 .unwrap()
137 .into_iter()
138 .filter(|c| c.snippet.is_some())
139 .collect::<Vec<_>>();
140 assert_eq_dbg(expected_completions, &completions);
141 }
142
143 #[test]
144 fn test_completion_let_scope() {
145 check_scope_completion(
146 r"
147 fn quux(x: i32) {
148 let y = 92;
149 1 + <|>;
150 let z = ();
151 }
152 ",
153 r#"[CompletionItem { label: "y", lookup: None, snippet: None },
154 CompletionItem { label: "x", lookup: None, snippet: None },
155 CompletionItem { label: "quux", lookup: None, snippet: None }]"#,
156 );
157 }
158
159 #[test]
160 fn test_completion_if_let_scope() {
161 check_scope_completion(
162 r"
163 fn quux() {
164 if let Some(x) = foo() {
165 let y = 92;
166 };
167 if let Some(a) = bar() {
168 let b = 62;
169 1 + <|>
170 }
171 }
172 ",
173 r#"[CompletionItem { label: "b", lookup: None, snippet: None },
174 CompletionItem { label: "a", lookup: None, snippet: None },
175 CompletionItem { label: "quux", lookup: None, snippet: None }]"#,
176 );
177 }
178
179 #[test]
180 fn test_completion_for_scope() {
181 check_scope_completion(
182 r"
183 fn quux() {
184 for x in &[1, 2, 3] {
185 <|>
186 }
187 }
188 ",
189 r#"[CompletionItem { label: "x", lookup: None, snippet: None },
190 CompletionItem { label: "quux", lookup: None, snippet: None }]"#,
191 );
192 }
193
194 #[test]
195 fn test_completion_mod_scope() {
196 check_scope_completion(
197 r"
198 struct Foo;
199 enum Baz {}
200 fn quux() {
201 <|>
202 }
203 ",
204 r#"[CompletionItem { label: "quux", lookup: None, snippet: None },
205 CompletionItem { label: "Foo", lookup: None, snippet: None },
206 CompletionItem { label: "Baz", lookup: None, snippet: None }]"#,
207 );
208 }
209
210 #[test]
211 fn test_completion_mod_scope_no_self_use() {
212 check_scope_completion(
213 r"
214 use foo<|>;
215 ",
216 r#"[]"#,
217 );
218 }
219
220 #[test]
221 fn test_completion_self_path() {
222 check_scope_completion(
223 r"
224 use self::m::<|>;
225
226 mod m {
227 struct Bar;
228 }
229 ",
230 r#"[CompletionItem { label: "Bar", lookup: None, snippet: None }]"#,
231 );
232 }
233
234 #[test]
235 fn test_completion_mod_scope_nested() {
236 check_scope_completion(
237 r"
238 struct Foo;
239 mod m {
240 struct Bar;
241 fn quux() { <|> }
242 }
243 ",
244 r#"[CompletionItem { label: "quux", lookup: None, snippet: None },
245 CompletionItem { label: "Bar", lookup: None, snippet: None }]"#,
246 );
247 }
248
249 #[test]
250 fn test_complete_type() {
251 check_scope_completion(
252 r"
253 struct Foo;
254 fn x() -> <|>
255 ",
256 r#"[CompletionItem { label: "Foo", lookup: None, snippet: None },
257 CompletionItem { label: "x", lookup: None, snippet: None }]"#,
258 )
259 }
260
261 #[test]
262 fn test_complete_shadowing() {
263 check_scope_completion(
264 r"
265 fn foo() -> {
266 let bar = 92;
267 {
268 let bar = 62;
269 <|>
270 }
271 }
272 ",
273 r#"[CompletionItem { label: "bar", lookup: None, snippet: None },
274 CompletionItem { label: "foo", lookup: None, snippet: None }]"#,
275 )
276 }
277
278 #[test]
279 fn test_complete_self() {
280 check_scope_completion(
281 r"
282 impl S { fn foo(&self) { <|> } }
283 ",
284 r#"[CompletionItem { label: "self", lookup: None, snippet: None }]"#,
285 )
286 }
287
288 #[test]
289 fn test_completion_kewords() {
290 check_snippet_completion(r"
291 fn quux() {
292 <|>
293 }
294 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
295 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
296 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
297 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
298 CompletionItem { label: "return", lookup: None, snippet: Some("return") },
299 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
300 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
301 }
302
303 #[test]
304 fn test_completion_else() {
305 check_snippet_completion(r"
306 fn quux() {
307 if true {
308 ()
309 } <|>
310 }
311 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
312 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
313 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
314 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
315 CompletionItem { label: "else", lookup: None, snippet: Some("else {$0}") },
316 CompletionItem { label: "else if", lookup: None, snippet: Some("else if $0 {}") },
317 CompletionItem { label: "return", lookup: None, snippet: Some("return") },
318 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
319 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
320 }
321
322 #[test]
323 fn test_completion_return_value() {
324 check_snippet_completion(r"
325 fn quux() -> i32 {
326 <|>
327 92
328 }
329 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
330 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
331 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
332 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
333 CompletionItem { label: "return", lookup: None, snippet: Some("return $0;") },
334 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
335 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
336 check_snippet_completion(r"
337 fn quux() {
338 <|>
339 92
340 }
341 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
342 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
343 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
344 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
345 CompletionItem { label: "return", lookup: None, snippet: Some("return;") },
346 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
347 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
348 }
349
350 #[test]
351 fn test_completion_return_no_stmt() {
352 check_snippet_completion(r"
353 fn quux() -> i32 {
354 match () {
355 () => <|>
356 }
357 }
358 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
359 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
360 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
361 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
362 CompletionItem { label: "return", lookup: None, snippet: Some("return $0") },
363 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
364 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
365 }
366
367 #[test]
368 fn test_continue_break_completion() {
369 check_snippet_completion(r"
370 fn quux() -> i32 {
371 loop { <|> }
372 }
373 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
374 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
375 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
376 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
377 CompletionItem { label: "continue", lookup: None, snippet: Some("continue") },
378 CompletionItem { label: "break", lookup: None, snippet: Some("break") },
379 CompletionItem { label: "return", lookup: None, snippet: Some("return $0") },
380 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
381 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
382 check_snippet_completion(r"
383 fn quux() -> i32 {
384 loop { || { <|> } }
385 }
386 ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") },
387 CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") },
388 CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") },
389 CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") },
390 CompletionItem { label: "return", lookup: None, snippet: Some("return $0") },
391 CompletionItem { label: "pd", lookup: None, snippet: Some("eprintln!(\"$0 = {:?}\", $0);") },
392 CompletionItem { label: "ppd", lookup: None, snippet: Some("eprintln!(\"$0 = {:#?}\", $0);") }]"#);
393 }
394
395 #[test]
396 fn test_param_completion_last_param() {
397 check_scope_completion(r"
398 fn foo(file_id: FileId) {}
399 fn bar(file_id: FileId) {}
400 fn baz(file<|>) {}
401 ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
402 }
403
404 #[test]
405 fn test_param_completion_nth_param() {
406 check_scope_completion(r"
407 fn foo(file_id: FileId) {}
408 fn bar(file_id: FileId) {}
409 fn baz(file<|>, x: i32) {}
410 ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
411 }
412
413 #[test]
414 fn test_param_completion_trait_param() {
415 check_scope_completion(r"
416 pub(crate) trait SourceRoot {
417 pub fn contains(&self, file_id: FileId) -> bool;
418 pub fn module_map(&self) -> &ModuleMap;
419 pub fn lines(&self, file_id: FileId) -> &LineIndex;
420 pub fn syntax(&self, file<|>)
421 }
422 ", r#"[CompletionItem { label: "self", lookup: None, snippet: None },
423 CompletionItem { label: "SourceRoot", lookup: None, snippet: None },
424 CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#);
425 }
426
427 #[test]
428 fn test_item_snippets() {
429 // check_snippet_completion(r"
430 // <|>
431 // ",
432 // r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##,
433 // );
434 check_snippet_completion(r"
435 #[cfg(test)]
436 mod tests {
437 <|>
438 }
439 ",
440 r##"[CompletionItem { label: "Test function", lookup: Some("tfn"), snippet: Some("#[test]\nfn ${1:feature}() {\n$0\n}") },
441 CompletionItem { label: "pub(crate)", lookup: None, snippet: Some("pub(crate) $0") }]"##,
442 );
443 }
444} 60}
diff --git a/crates/ra_analysis/src/completion/complete_fn_param.rs b/crates/ra_analysis/src/completion/complete_fn_param.rs
new file mode 100644
index 000000000..bb5fdfda0
--- /dev/null
+++ b/crates/ra_analysis/src/completion/complete_fn_param.rs
@@ -0,0 +1,102 @@
1use ra_syntax::{
2 algo::visit::{visitor_ctx, VisitorCtx},
3 ast,
4 AstNode,
5};
6use rustc_hash::FxHashMap;
7
8use crate::completion::{CompletionContext, Completions, CompletionKind, CompletionItem};
9
10/// Complete repeated parametes, both name and type. For example, if all
11/// functions in a file have a `spam: &mut Spam` parameter, a completion with
12/// `spam: &mut Spam` insert text/label and `spam` lookup string will be
13/// suggested.
14pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) {
15 if !ctx.is_param {
16 return;
17 }
18
19 let mut params = FxHashMap::default();
20 for node in ctx.leaf.ancestors() {
21 let _ = visitor_ctx(&mut params)
22 .visit::<ast::SourceFile, _>(process)
23 .visit::<ast::ItemList, _>(process)
24 .accept(node);
25 }
26 params
27 .into_iter()
28 .filter_map(|(label, (count, param))| {
29 let lookup = param.pat()?.syntax().text().to_string();
30 if count < 2 {
31 None
32 } else {
33 Some((label, lookup))
34 }
35 })
36 .for_each(|(label, lookup)| {
37 CompletionItem::new(CompletionKind::Magic, label)
38 .lookup_by(lookup)
39 .add_to(acc)
40 });
41
42 fn process<'a, N: ast::FnDefOwner<'a>>(
43 node: N,
44 params: &mut FxHashMap<String, (u32, ast::Param<'a>)>,
45 ) {
46 node.functions()
47 .filter_map(|it| it.param_list())
48 .flat_map(|it| it.params())
49 .for_each(|param| {
50 let text = param.syntax().text().to_string();
51 params.entry(text).or_insert((0, param)).0 += 1;
52 })
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use crate::completion::*;
59
60 fn check_magic_completion(code: &str, expected_completions: &str) {
61 check_completion(code, expected_completions, CompletionKind::Magic);
62 }
63
64 #[test]
65 fn test_param_completion_last_param() {
66 check_magic_completion(
67 r"
68 fn foo(file_id: FileId) {}
69 fn bar(file_id: FileId) {}
70 fn baz(file<|>) {}
71 ",
72 r#"file_id "file_id: FileId""#,
73 );
74 }
75
76 #[test]
77 fn test_param_completion_nth_param() {
78 check_magic_completion(
79 r"
80 fn foo(file_id: FileId) {}
81 fn bar(file_id: FileId) {}
82 fn baz(file<|>, x: i32) {}
83 ",
84 r#"file_id "file_id: FileId""#,
85 );
86 }
87
88 #[test]
89 fn test_param_completion_trait_param() {
90 check_magic_completion(
91 r"
92 pub(crate) trait SourceRoot {
93 pub fn contains(&self, file_id: FileId) -> bool;
94 pub fn module_map(&self) -> &ModuleMap;
95 pub fn lines(&self, file_id: FileId) -> &LineIndex;
96 pub fn syntax(&self, file<|>)
97 }
98 ",
99 r#"file_id "file_id: FileId""#,
100 );
101 }
102}
diff --git a/crates/ra_analysis/src/completion/complete_keyword.rs b/crates/ra_analysis/src/completion/complete_keyword.rs
new file mode 100644
index 000000000..5427fcb11
--- /dev/null
+++ b/crates/ra_analysis/src/completion/complete_keyword.rs
@@ -0,0 +1,204 @@
1use ra_syntax::{
2 algo::visit::{visitor, Visitor},
3 AstNode,
4 ast::{self, LoopBodyOwner},
5 SyntaxKind::*, SyntaxNodeRef,
6};
7
8use crate::completion::{CompletionContext, CompletionItem, Completions, CompletionKind, CompletionItemKind};
9
10fn keyword(kw: &str, snippet: &str) -> CompletionItem {
11 CompletionItem::new(CompletionKind::Keyword, kw)
12 .kind(CompletionItemKind::Keyword)
13 .snippet(snippet)
14 .build()
15}
16
17pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
18 if !ctx.is_trivial_path {
19 return;
20 }
21 let fn_def = match ctx.enclosing_fn {
22 Some(it) => it,
23 None => return,
24 };
25 acc.add(keyword("if", "if $0 {}"));
26 acc.add(keyword("match", "match $0 {}"));
27 acc.add(keyword("while", "while $0 {}"));
28 acc.add(keyword("loop", "loop {$0}"));
29
30 if ctx.after_if {
31 acc.add(keyword("else", "else {$0}"));
32 acc.add(keyword("else if", "else if $0 {}"));
33 }
34 if is_in_loop_body(ctx.leaf) {
35 acc.add(keyword("continue", "continue"));
36 acc.add(keyword("break", "break"));
37 }
38 acc.add_all(complete_return(fn_def, ctx.is_stmt));
39}
40
41fn is_in_loop_body(leaf: SyntaxNodeRef) -> bool {
42 for node in leaf.ancestors() {
43 if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
44 break;
45 }
46 let loop_body = visitor()
47 .visit::<ast::ForExpr, _>(LoopBodyOwner::loop_body)
48 .visit::<ast::WhileExpr, _>(LoopBodyOwner::loop_body)
49 .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
50 .accept(node);
51 if let Some(Some(body)) = loop_body {
52 if leaf.range().is_subrange(&body.syntax().range()) {
53 return true;
54 }
55 }
56 }
57 false
58}
59
60fn complete_return(fn_def: ast::FnDef, is_stmt: bool) -> Option<CompletionItem> {
61 let snip = match (is_stmt, fn_def.ret_type().is_some()) {
62 (true, true) => "return $0;",
63 (true, false) => "return;",
64 (false, true) => "return $0",
65 (false, false) => "return",
66 };
67 Some(keyword("return", snip))
68}
69
70#[cfg(test)]
71mod tests {
72 use crate::completion::{CompletionKind, check_completion};
73 fn check_keyword_completion(code: &str, expected_completions: &str) {
74 check_completion(code, expected_completions, CompletionKind::Keyword);
75 }
76
77 #[test]
78 fn test_completion_kewords() {
79 check_keyword_completion(
80 r"
81 fn quux() {
82 <|>
83 }
84 ",
85 r#"
86 if "if $0 {}"
87 match "match $0 {}"
88 while "while $0 {}"
89 loop "loop {$0}"
90 return "return"
91 "#,
92 );
93 }
94
95 #[test]
96 fn test_completion_else() {
97 check_keyword_completion(
98 r"
99 fn quux() {
100 if true {
101 ()
102 } <|>
103 }
104 ",
105 r#"
106 if "if $0 {}"
107 match "match $0 {}"
108 while "while $0 {}"
109 loop "loop {$0}"
110 else "else {$0}"
111 else if "else if $0 {}"
112 return "return"
113 "#,
114 );
115 }
116
117 #[test]
118 fn test_completion_return_value() {
119 check_keyword_completion(
120 r"
121 fn quux() -> i32 {
122 <|>
123 92
124 }
125 ",
126 r#"
127 if "if $0 {}"
128 match "match $0 {}"
129 while "while $0 {}"
130 loop "loop {$0}"
131 return "return $0;"
132 "#,
133 );
134 check_keyword_completion(
135 r"
136 fn quux() {
137 <|>
138 92
139 }
140 ",
141 r#"
142 if "if $0 {}"
143 match "match $0 {}"
144 while "while $0 {}"
145 loop "loop {$0}"
146 return "return;"
147 "#,
148 );
149 }
150
151 #[test]
152 fn test_completion_return_no_stmt() {
153 check_keyword_completion(
154 r"
155 fn quux() -> i32 {
156 match () {
157 () => <|>
158 }
159 }
160 ",
161 r#"
162 if "if $0 {}"
163 match "match $0 {}"
164 while "while $0 {}"
165 loop "loop {$0}"
166 return "return $0"
167 "#,
168 );
169 }
170
171 #[test]
172 fn test_continue_break_completion() {
173 check_keyword_completion(
174 r"
175 fn quux() -> i32 {
176 loop { <|> }
177 }
178 ",
179 r#"
180 if "if $0 {}"
181 match "match $0 {}"
182 while "while $0 {}"
183 loop "loop {$0}"
184 continue "continue"
185 break "break"
186 return "return $0"
187 "#,
188 );
189 check_keyword_completion(
190 r"
191 fn quux() -> i32 {
192 loop { || { <|> } }
193 }
194 ",
195 r#"
196 if "if $0 {}"
197 match "match $0 {}"
198 while "while $0 {}"
199 loop "loop {$0}"
200 return "return $0"
201 "#,
202 );
203 }
204}
diff --git a/crates/ra_analysis/src/completion/complete_path.rs b/crates/ra_analysis/src/completion/complete_path.rs
new file mode 100644
index 000000000..ad4d68a33
--- /dev/null
+++ b/crates/ra_analysis/src/completion/complete_path.rs
@@ -0,0 +1,95 @@
1use crate::{
2 Cancelable,
3 completion::{CompletionItem, Completions, CompletionKind, CompletionContext},
4};
5
6pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> {
7 let (path, module) = match (&ctx.path_prefix, &ctx.module) {
8 (Some(path), Some(module)) => (path.clone(), module),
9 _ => return Ok(()),
10 };
11 let def_id = match module.resolve_path(ctx.db, path)? {
12 Some(it) => it,
13 None => return Ok(()),
14 };
15 let target_module = match def_id.resolve(ctx.db)? {
16 hir::Def::Module(it) => it,
17 _ => return Ok(()),
18 };
19 let module_scope = target_module.scope(ctx.db)?;
20 module_scope.entries().for_each(|(name, res)| {
21 CompletionItem::new(CompletionKind::Reference, name.to_string())
22 .from_resolution(ctx.db, res)
23 .add_to(acc)
24 });
25 Ok(())
26}
27
28#[cfg(test)]
29mod tests {
30 use crate::completion::{CompletionKind, check_completion};
31
32 fn check_reference_completion(code: &str, expected_completions: &str) {
33 check_completion(code, expected_completions, CompletionKind::Reference);
34 }
35
36 #[test]
37 fn completes_use_item_starting_with_self() {
38 check_reference_completion(
39 r"
40 use self::m::<|>;
41
42 mod m {
43 struct Bar;
44 }
45 ",
46 "Bar",
47 );
48 }
49
50 #[test]
51 fn completes_use_item_starting_with_crate() {
52 check_reference_completion(
53 "
54 //- /lib.rs
55 mod foo;
56 struct Spam;
57 //- /foo.rs
58 use crate::Sp<|>
59 ",
60 "Spam;foo",
61 );
62 }
63
64 #[test]
65 fn completes_nested_use_tree() {
66 check_reference_completion(
67 "
68 //- /lib.rs
69 mod foo;
70 struct Spam;
71 //- /foo.rs
72 use crate::{Sp<|>};
73 ",
74 "Spam;foo",
75 );
76 }
77
78 #[test]
79 fn completes_deeply_nested_use_tree() {
80 check_reference_completion(
81 "
82 //- /lib.rs
83 mod foo;
84 pub mod bar {
85 pub mod baz {
86 pub struct Spam;
87 }
88 }
89 //- /foo.rs
90 use crate::{bar::{baz::Sp<|>}};
91 ",
92 "Spam",
93 );
94 }
95}
diff --git a/crates/ra_analysis/src/completion/complete_scope.rs b/crates/ra_analysis/src/completion/complete_scope.rs
new file mode 100644
index 000000000..a57670e3b
--- /dev/null
+++ b/crates/ra_analysis/src/completion/complete_scope.rs
@@ -0,0 +1,173 @@
1use rustc_hash::FxHashSet;
2use ra_syntax::TextUnit;
3
4use crate::{
5 Cancelable,
6 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
7};
8
9pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> {
10 if !ctx.is_trivial_path {
11 return Ok(());
12 }
13 let module = match &ctx.module {
14 Some(it) => it,
15 None => return Ok(()),
16 };
17 if let Some(fn_def) = ctx.enclosing_fn {
18 let function = hir::source_binder::function_from_module(ctx.db, module, fn_def);
19 let scopes = function.scopes(ctx.db);
20 complete_fn(acc, &scopes, ctx.offset);
21 }
22
23 let module_scope = module.scope(ctx.db)?;
24 module_scope
25 .entries()
26 .filter(|(_name, res)| {
27 // Don't expose this item
28 match res.import {
29 None => true,
30 Some(import) => {
31 let range = import.range(ctx.db, module.source().file_id());
32 !range.is_subrange(&ctx.leaf.range())
33 }
34 }
35 })
36 .for_each(|(name, res)| {
37 CompletionItem::new(CompletionKind::Reference, name.to_string())
38 .from_resolution(ctx.db, res)
39 .add_to(acc)
40 });
41 Ok(())
42}
43
44fn complete_fn(acc: &mut Completions, scopes: &hir::FnScopes, offset: TextUnit) {
45 let mut shadowed = FxHashSet::default();
46 scopes
47 .scope_chain_for_offset(offset)
48 .flat_map(|scope| scopes.entries(scope).iter())
49 .filter(|entry| shadowed.insert(entry.name()))
50 .for_each(|entry| {
51 CompletionItem::new(CompletionKind::Reference, entry.name().to_string())
52 .kind(CompletionItemKind::Binding)
53 .add_to(acc)
54 });
55 if scopes.self_param.is_some() {
56 CompletionItem::new(CompletionKind::Reference, "self").add_to(acc);
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::completion::{CompletionKind, check_completion};
63
64 fn check_reference_completion(code: &str, expected_completions: &str) {
65 check_completion(code, expected_completions, CompletionKind::Reference);
66 }
67
68 #[test]
69 fn completes_bindings_from_let() {
70 check_reference_completion(
71 r"
72 fn quux(x: i32) {
73 let y = 92;
74 1 + <|>;
75 let z = ();
76 }
77 ",
78 "y;x;quux",
79 );
80 }
81
82 #[test]
83 fn completes_bindings_from_if_let() {
84 check_reference_completion(
85 r"
86 fn quux() {
87 if let Some(x) = foo() {
88 let y = 92;
89 };
90 if let Some(a) = bar() {
91 let b = 62;
92 1 + <|>
93 }
94 }
95 ",
96 "b;a;quux",
97 );
98 }
99
100 #[test]
101 fn completes_bindings_from_for() {
102 check_reference_completion(
103 r"
104 fn quux() {
105 for x in &[1, 2, 3] {
106 <|>
107 }
108 }
109 ",
110 "x;quux",
111 );
112 }
113
114 #[test]
115 fn completes_module_items() {
116 check_reference_completion(
117 r"
118 struct Foo;
119 enum Baz {}
120 fn quux() {
121 <|>
122 }
123 ",
124 "quux;Foo;Baz",
125 );
126 }
127
128 #[test]
129 fn completes_module_items_in_nested_modules() {
130 check_reference_completion(
131 r"
132 struct Foo;
133 mod m {
134 struct Bar;
135 fn quux() { <|> }
136 }
137 ",
138 "quux;Bar",
139 );
140 }
141
142 #[test]
143 fn completes_return_type() {
144 check_reference_completion(
145 r"
146 struct Foo;
147 fn x() -> <|>
148 ",
149 "Foo;x",
150 )
151 }
152
153 #[test]
154 fn dont_show_to_completions_for_shadowing() {
155 check_reference_completion(
156 r"
157 fn foo() -> {
158 let bar = 92;
159 {
160 let bar = 62;
161 <|>
162 }
163 }
164 ",
165 "bar;foo",
166 )
167 }
168
169 #[test]
170 fn completes_self_in_methods() {
171 check_reference_completion(r"impl S { fn foo(&self) { <|> } }", "self")
172 }
173}
diff --git a/crates/ra_analysis/src/completion/complete_snippet.rs b/crates/ra_analysis/src/completion/complete_snippet.rs
new file mode 100644
index 000000000..fb9da0a4f
--- /dev/null
+++ b/crates/ra_analysis/src/completion/complete_snippet.rs
@@ -0,0 +1,73 @@
1use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionItemKind, CompletionContext, completion_item::Builder};
2
3fn snippet(label: &str, snippet: &str) -> Builder {
4 CompletionItem::new(CompletionKind::Snippet, label)
5 .snippet(snippet)
6 .kind(CompletionItemKind::Snippet)
7}
8
9pub(super) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
10 if !(ctx.is_trivial_path && ctx.enclosing_fn.is_some()) {
11 return;
12 }
13 snippet("pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
14 snippet("ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
15}
16
17pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) {
18 if !ctx.is_new_item {
19 return;
20 }
21 snippet(
22 "Test function",
23 "\
24#[test]
25fn ${1:feature}() {
26 $0
27}",
28 )
29 .lookup_by("tfn")
30 .add_to(acc);
31
32 snippet("pub(crate)", "pub(crate) $0").add_to(acc);
33}
34
35#[cfg(test)]
36mod tests {
37 use crate::completion::{CompletionKind, check_completion};
38 fn check_snippet_completion(code: &str, expected_completions: &str) {
39 check_completion(code, expected_completions, CompletionKind::Snippet);
40 }
41
42 #[test]
43 fn completes_snippets_in_expressions() {
44 check_snippet_completion(
45 r"fn foo(x: i32) { <|> }",
46 r##"
47 pd "eprintln!(\"$0 = {:?}\", $0);"
48 ppd "eprintln!(\"$0 = {:#?}\", $0);"
49 "##,
50 );
51 }
52
53 #[test]
54 fn completes_snippets_in_items() {
55 // check_snippet_completion(r"
56 // <|>
57 // ",
58 // r##"[CompletionItem { label: "Test function", lookup: None, snippet: Some("#[test]\nfn test_${1:feature}() {\n$0\n}"##,
59 // );
60 check_snippet_completion(
61 r"
62 #[cfg(test)]
63 mod tests {
64 <|>
65 }
66 ",
67 r##"
68 tfn "Test function" "#[test]\nfn ${1:feature}() {\n $0\n}"
69 pub(crate) "pub(crate) $0"
70 "##,
71 );
72 }
73}
diff --git a/crates/ra_analysis/src/completion/completion_context.rs b/crates/ra_analysis/src/completion/completion_context.rs
new file mode 100644
index 000000000..064fbc6f7
--- /dev/null
+++ b/crates/ra_analysis/src/completion/completion_context.rs
@@ -0,0 +1,156 @@
1use ra_editor::find_node_at_offset;
2use ra_text_edit::AtomTextEdit;
3use ra_syntax::{
4 algo::find_leaf_at_offset,
5 ast,
6 AstNode,
7 SyntaxNodeRef,
8 SourceFileNode,
9 TextUnit,
10 SyntaxKind::*,
11};
12use hir::source_binder;
13
14use crate::{db, FilePosition, Cancelable};
15
16/// `CompletionContext` is created early during completion to figure out, where
17/// exactly is the cursor, syntax-wise.
18#[derive(Debug)]
19pub(super) struct CompletionContext<'a> {
20 pub(super) db: &'a db::RootDatabase,
21 pub(super) offset: TextUnit,
22 pub(super) leaf: SyntaxNodeRef<'a>,
23 pub(super) module: Option<hir::Module>,
24 pub(super) enclosing_fn: Option<ast::FnDef<'a>>,
25 pub(super) is_param: bool,
26 /// A single-indent path, like `foo`.
27 pub(super) is_trivial_path: bool,
28 /// If not a trivial, path, the prefix (qualifier).
29 pub(super) path_prefix: Option<hir::Path>,
30 pub(super) after_if: bool,
31 pub(super) is_stmt: bool,
32 /// Something is typed at the "top" level, in module or impl/trait.
33 pub(super) is_new_item: bool,
34}
35
36impl<'a> CompletionContext<'a> {
37 pub(super) fn new(
38 db: &'a db::RootDatabase,
39 original_file: &'a SourceFileNode,
40 position: FilePosition,
41 ) -> Cancelable<Option<CompletionContext<'a>>> {
42 let module = source_binder::module_from_position(db, position)?;
43 let leaf =
44 ctry!(find_leaf_at_offset(original_file.syntax(), position.offset).left_biased());
45 let mut ctx = CompletionContext {
46 db,
47 leaf,
48 offset: position.offset,
49 module,
50 enclosing_fn: None,
51 is_param: false,
52 is_trivial_path: false,
53 path_prefix: None,
54 after_if: false,
55 is_stmt: false,
56 is_new_item: false,
57 };
58 ctx.fill(original_file, position.offset);
59 Ok(Some(ctx))
60 }
61
62 fn fill(&mut self, original_file: &SourceFileNode, offset: TextUnit) {
63 // Insert a fake ident to get a valid parse tree. We will use this file
64 // to determine context, though the original_file will be used for
65 // actual completion.
66 let file = {
67 let edit = AtomTextEdit::insert(offset, "intellijRulezz".to_string());
68 original_file.reparse(&edit)
69 };
70
71 // First, let's try to complete a reference to some declaration.
72 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), offset) {
73 // Special case, `trait T { fn foo(i_am_a_name_ref) {} }`.
74 // See RFC#1685.
75 if is_node::<ast::Param>(name_ref.syntax()) {
76 self.is_param = true;
77 return;
78 }
79 self.classify_name_ref(&file, name_ref);
80 }
81
82 // Otherwise, see if this is a declaration. We can use heuristics to
83 // suggest declaration names, see `CompletionKind::Magic`.
84 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), offset) {
85 if is_node::<ast::Param>(name.syntax()) {
86 self.is_param = true;
87 return;
88 }
89 }
90 }
91 fn classify_name_ref(&mut self, file: &SourceFileNode, name_ref: ast::NameRef) {
92 let name_range = name_ref.syntax().range();
93 let top_node = name_ref
94 .syntax()
95 .ancestors()
96 .take_while(|it| it.range() == name_range)
97 .last()
98 .unwrap();
99
100 match top_node.parent().map(|it| it.kind()) {
101 Some(SOURCE_FILE) | Some(ITEM_LIST) => {
102 self.is_new_item = true;
103 return;
104 }
105 _ => (),
106 }
107
108 let parent = match name_ref.syntax().parent() {
109 Some(it) => it,
110 None => return,
111 };
112 if let Some(segment) = ast::PathSegment::cast(parent) {
113 let path = segment.parent_path();
114 if let Some(mut path) = hir::Path::from_ast(path) {
115 if !path.is_ident() {
116 path.segments.pop().unwrap();
117 self.path_prefix = Some(path);
118 return;
119 }
120 }
121 if path.qualifier().is_none() {
122 self.is_trivial_path = true;
123 self.enclosing_fn = self
124 .leaf
125 .ancestors()
126 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
127 .find_map(ast::FnDef::cast);
128
129 self.is_stmt = match name_ref
130 .syntax()
131 .ancestors()
132 .filter_map(ast::ExprStmt::cast)
133 .next()
134 {
135 None => false,
136 Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range(),
137 };
138
139 if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
140 if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
141 if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
142 self.after_if = true;
143 }
144 }
145 }
146 }
147 }
148 }
149}
150
151fn is_node<'a, N: AstNode<'a>>(node: SyntaxNodeRef<'a>) -> bool {
152 match node.ancestors().filter_map(N::cast).next() {
153 None => false,
154 Some(n) => n.syntax().range() == node.range(),
155 }
156}
diff --git a/crates/ra_analysis/src/completion/completion_item.rs b/crates/ra_analysis/src/completion/completion_item.rs
new file mode 100644
index 000000000..911f08468
--- /dev/null
+++ b/crates/ra_analysis/src/completion/completion_item.rs
@@ -0,0 +1,214 @@
1use crate::db;
2
3/// `CompletionItem` describes a single completion variant in the editor pop-up.
4/// It is basically a POD with various properties. To construct a
5/// `CompletionItem`, use `new` method and the `Builder` struct.
6#[derive(Debug)]
7pub struct CompletionItem {
8 /// Used only internally in tests, to check only specific kind of
9 /// completion.
10 completion_kind: CompletionKind,
11 label: String,
12 lookup: Option<String>,
13 snippet: Option<String>,
14 kind: Option<CompletionItemKind>,
15}
16
17pub enum InsertText {
18 PlainText { text: String },
19 Snippet { text: String },
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum CompletionItemKind {
24 Snippet,
25 Keyword,
26 Module,
27 Function,
28 Binding,
29}
30
31#[derive(Debug, PartialEq, Eq)]
32pub(crate) enum CompletionKind {
33 /// Parser-based keyword completion.
34 Keyword,
35 /// Your usual "complete all valid identifiers".
36 Reference,
37 /// "Secret sauce" completions.
38 Magic,
39 Snippet,
40}
41
42impl CompletionItem {
43 pub(crate) fn new(completion_kind: CompletionKind, label: impl Into<String>) -> Builder {
44 let label = label.into();
45 Builder {
46 completion_kind,
47 label,
48 lookup: None,
49 snippet: None,
50 kind: None,
51 }
52 }
53 /// What user sees in pop-up in the UI.
54 pub fn label(&self) -> &str {
55 &self.label
56 }
57 /// What string is used for filtering.
58 pub fn lookup(&self) -> &str {
59 self.lookup
60 .as_ref()
61 .map(|it| it.as_str())
62 .unwrap_or(self.label())
63 }
64 /// What is inserted.
65 pub fn insert_text(&self) -> InsertText {
66 match &self.snippet {
67 None => InsertText::PlainText {
68 text: self.label.clone(),
69 },
70 Some(it) => InsertText::Snippet { text: it.clone() },
71 }
72 }
73
74 pub fn kind(&self) -> Option<CompletionItemKind> {
75 self.kind
76 }
77}
78
79/// A helper to make `CompletionItem`s.
80#[must_use]
81pub(crate) struct Builder {
82 completion_kind: CompletionKind,
83 label: String,
84 lookup: Option<String>,
85 snippet: Option<String>,
86 kind: Option<CompletionItemKind>,
87}
88
89impl Builder {
90 pub(crate) fn add_to(self, acc: &mut Completions) {
91 acc.add(self.build())
92 }
93
94 pub(crate) fn build(self) -> CompletionItem {
95 CompletionItem {
96 label: self.label,
97 lookup: self.lookup,
98 snippet: self.snippet,
99 kind: self.kind,
100 completion_kind: self.completion_kind,
101 }
102 }
103 pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder {
104 self.lookup = Some(lookup.into());
105 self
106 }
107 pub(crate) fn snippet(mut self, snippet: impl Into<String>) -> Builder {
108 self.snippet = Some(snippet.into());
109 self
110 }
111 pub(crate) fn kind(mut self, kind: CompletionItemKind) -> Builder {
112 self.kind = Some(kind);
113 self
114 }
115 pub(crate) fn from_resolution(
116 mut self,
117 db: &db::RootDatabase,
118 resolution: &hir::Resolution,
119 ) -> Builder {
120 if let Some(def_id) = resolution.def_id {
121 if let Ok(def) = def_id.resolve(db) {
122 let kind = match def {
123 hir::Def::Module(..) => CompletionItemKind::Module,
124 hir::Def::Function(..) => CompletionItemKind::Function,
125 _ => return self,
126 };
127 self.kind = Some(kind);
128 }
129 }
130 self
131 }
132}
133
134impl Into<CompletionItem> for Builder {
135 fn into(self) -> CompletionItem {
136 self.build()
137 }
138}
139
140/// Represents an in-progress set of completions being built.
141#[derive(Debug, Default)]
142pub(crate) struct Completions {
143 buf: Vec<CompletionItem>,
144}
145
146impl Completions {
147 pub(crate) fn add(&mut self, item: impl Into<CompletionItem>) {
148 self.buf.push(item.into())
149 }
150 pub(crate) fn add_all<I>(&mut self, items: I)
151 where
152 I: IntoIterator,
153 I::Item: Into<CompletionItem>,
154 {
155 items.into_iter().for_each(|item| self.add(item.into()))
156 }
157
158 #[cfg(test)]
159 pub(crate) fn assert_match(&self, expected: &str, kind: CompletionKind) {
160 let expected = normalize(expected);
161 let actual = self.debug_render(kind);
162 test_utils::assert_eq_text!(expected.as_str(), actual.as_str(),);
163
164 /// Normalize the textual representation of `Completions`:
165 /// replace `;` with newlines, normalize whitespace
166 fn normalize(expected: &str) -> String {
167 use ra_syntax::{tokenize, TextUnit, TextRange, SyntaxKind::SEMI};
168 let mut res = String::new();
169 for line in expected.trim().lines() {
170 let line = line.trim();
171 let mut start_offset: TextUnit = 0.into();
172 // Yep, we use rust tokenize in completion tests :-)
173 for token in tokenize(line) {
174 let range = TextRange::offset_len(start_offset, token.len);
175 start_offset += token.len;
176 if token.kind == SEMI {
177 res.push('\n');
178 } else {
179 res.push_str(&line[range]);
180 }
181 }
182
183 res.push('\n');
184 }
185 res
186 }
187 }
188
189 #[cfg(test)]
190 fn debug_render(&self, kind: CompletionKind) -> String {
191 let mut res = String::new();
192 for c in self.buf.iter() {
193 if c.completion_kind == kind {
194 if let Some(lookup) = &c.lookup {
195 res.push_str(lookup);
196 res.push_str(&format!(" {:?}", c.label));
197 } else {
198 res.push_str(&c.label);
199 }
200 if let Some(snippet) = &c.snippet {
201 res.push_str(&format!(" {:?}", snippet));
202 }
203 res.push('\n');
204 }
205 }
206 res
207 }
208}
209
210impl Into<Vec<CompletionItem>> for Completions {
211 fn into(self) -> Vec<CompletionItem> {
212 self.buf
213 }
214}
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
deleted file mode 100644
index f483ed045..000000000
--- a/crates/ra_analysis/src/completion/reference_completion.rs
+++ /dev/null
@@ -1,294 +0,0 @@
1use rustc_hash::{FxHashSet};
2use ra_editor::find_node_at_offset;
3use ra_syntax::{
4 algo::visit::{visitor, Visitor},
5 SourceFileNode, AstNode,
6 ast::{self, LoopBodyOwner},
7 SyntaxKind::*,
8};
9use hir::{
10 self,
11 FnScopes,
12 Def,
13 Path,
14};
15
16use crate::{
17 db::RootDatabase,
18 completion::CompletionItem,
19 Cancelable
20};
21
22pub(super) fn completions(
23 acc: &mut Vec<CompletionItem>,
24 db: &RootDatabase,
25 module: &hir::Module,
26 file: &SourceFileNode,
27 name_ref: ast::NameRef,
28) -> Cancelable<()> {
29 let kind = match classify_name_ref(name_ref) {
30 Some(it) => it,
31 None => return Ok(()),
32 };
33
34 match kind {
35 NameRefKind::LocalRef { enclosing_fn } => {
36 if let Some(fn_def) = enclosing_fn {
37 let scopes = FnScopes::new(fn_def);
38 complete_fn(name_ref, &scopes, acc);
39 complete_expr_keywords(&file, fn_def, name_ref, acc);
40 complete_expr_snippets(acc);
41 }
42
43 let module_scope = module.scope(db)?;
44 acc.extend(
45 module_scope
46 .entries()
47 .filter(|(_name, res)| {
48 // Don't expose this item
49 match res.import {
50 None => true,
51 Some(import) => {
52 let range = import.range(db, module.source().file_id());
53 !range.is_subrange(&name_ref.syntax().range())
54 }
55 }
56 })
57 .map(|(name, _res)| CompletionItem {
58 label: name.to_string(),
59 lookup: None,
60 snippet: None,
61 }),
62 );
63 }
64 NameRefKind::Path(path) => complete_path(acc, db, module, path)?,
65 NameRefKind::BareIdentInMod => {
66 let name_range = name_ref.syntax().range();
67 let top_node = name_ref
68 .syntax()
69 .ancestors()
70 .take_while(|it| it.range() == name_range)
71 .last()
72 .unwrap();
73 match top_node.parent().map(|it| it.kind()) {
74 Some(SOURCE_FILE) | Some(ITEM_LIST) => complete_mod_item_snippets(acc),
75 _ => (),
76 }
77 }
78 }
79 Ok(())
80}
81
82enum NameRefKind<'a> {
83 /// NameRef is a part of single-segment path, for example, a refernece to a
84 /// local variable.
85 LocalRef {
86 enclosing_fn: Option<ast::FnDef<'a>>,
87 },
88 /// NameRef is the last segment in some path
89 Path(Path),
90 /// NameRef is bare identifier at the module's root.
91 /// Used for keyword completion
92 BareIdentInMod,
93}
94
95fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
96 let name_range = name_ref.syntax().range();
97 let top_node = name_ref
98 .syntax()
99 .ancestors()
100 .take_while(|it| it.range() == name_range)
101 .last()
102 .unwrap();
103 match top_node.parent().map(|it| it.kind()) {
104 Some(SOURCE_FILE) | Some(ITEM_LIST) => return Some(NameRefKind::BareIdentInMod),
105 _ => (),
106 }
107
108 let parent = name_ref.syntax().parent()?;
109 if let Some(segment) = ast::PathSegment::cast(parent) {
110 let path = segment.parent_path();
111 if let Some(path) = Path::from_ast(path) {
112 if !path.is_ident() {
113 return Some(NameRefKind::Path(path));
114 }
115 }
116 if path.qualifier().is_none() {
117 let enclosing_fn = name_ref
118 .syntax()
119 .ancestors()
120 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
121 .find_map(ast::FnDef::cast);
122 return Some(NameRefKind::LocalRef { enclosing_fn });
123 }
124 }
125 None
126}
127
128fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
129 let mut shadowed = FxHashSet::default();
130 acc.extend(
131 scopes
132 .scope_chain(name_ref.syntax())
133 .flat_map(|scope| scopes.entries(scope).iter())
134 .filter(|entry| shadowed.insert(entry.name()))
135 .map(|entry| CompletionItem {
136 label: entry.name().to_string(),
137 lookup: None,
138 snippet: None,
139 }),
140 );
141 if scopes.self_param.is_some() {
142 acc.push(CompletionItem {
143 label: "self".to_string(),
144 lookup: None,
145 snippet: None,
146 })
147 }
148}
149
150fn complete_path(
151 acc: &mut Vec<CompletionItem>,
152 db: &RootDatabase,
153 module: &hir::Module,
154 mut path: Path,
155) -> Cancelable<()> {
156 if path.segments.is_empty() {
157 return Ok(());
158 }
159 path.segments.pop();
160 let def_id = match module.resolve_path(db, path)? {
161 None => return Ok(()),
162 Some(it) => it,
163 };
164 let target_module = match def_id.resolve(db)? {
165 Def::Module(it) => it,
166 _ => return Ok(()),
167 };
168 let module_scope = target_module.scope(db)?;
169 let completions = module_scope.entries().map(|(name, _res)| CompletionItem {
170 label: name.to_string(),
171 lookup: None,
172 snippet: None,
173 });
174 acc.extend(completions);
175 Ok(())
176}
177
178fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) {
179 acc.push(CompletionItem {
180 label: "Test function".to_string(),
181 lookup: Some("tfn".to_string()),
182 snippet: Some(
183 "#[test]\n\
184 fn ${1:feature}() {\n\
185 $0\n\
186 }"
187 .to_string(),
188 ),
189 });
190 acc.push(CompletionItem {
191 label: "pub(crate)".to_string(),
192 lookup: None,
193 snippet: Some("pub(crate) $0".to_string()),
194 })
195}
196
197fn complete_expr_keywords(
198 file: &SourceFileNode,
199 fn_def: ast::FnDef,
200 name_ref: ast::NameRef,
201 acc: &mut Vec<CompletionItem>,
202) {
203 acc.push(keyword("if", "if $0 {}"));
204 acc.push(keyword("match", "match $0 {}"));
205 acc.push(keyword("while", "while $0 {}"));
206 acc.push(keyword("loop", "loop {$0}"));
207
208 if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
209 if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
210 if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
211 acc.push(keyword("else", "else {$0}"));
212 acc.push(keyword("else if", "else if $0 {}"));
213 }
214 }
215 }
216 if is_in_loop_body(name_ref) {
217 acc.push(keyword("continue", "continue"));
218 acc.push(keyword("break", "break"));
219 }
220 acc.extend(complete_return(fn_def, name_ref));
221}
222
223fn is_in_loop_body(name_ref: ast::NameRef) -> bool {
224 for node in name_ref.syntax().ancestors() {
225 if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
226 break;
227 }
228 let loop_body = visitor()
229 .visit::<ast::ForExpr, _>(LoopBodyOwner::loop_body)
230 .visit::<ast::WhileExpr, _>(LoopBodyOwner::loop_body)
231 .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
232 .accept(node);
233 if let Some(Some(body)) = loop_body {
234 if name_ref
235 .syntax()
236 .range()
237 .is_subrange(&body.syntax().range())
238 {
239 return true;
240 }
241 }
242 }
243 false
244}
245
246fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option<CompletionItem> {
247 // let is_last_in_block = name_ref.syntax().ancestors().filter_map(ast::Expr::cast)
248 // .next()
249 // .and_then(|it| it.syntax().parent())
250 // .and_then(ast::Block::cast)
251 // .is_some();
252
253 // if is_last_in_block {
254 // return None;
255 // }
256
257 let is_stmt = match name_ref
258 .syntax()
259 .ancestors()
260 .filter_map(ast::ExprStmt::cast)
261 .next()
262 {
263 None => false,
264 Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range(),
265 };
266 let snip = match (is_stmt, fn_def.ret_type().is_some()) {
267 (true, true) => "return $0;",
268 (true, false) => "return;",
269 (false, true) => "return $0",
270 (false, false) => "return",
271 };
272 Some(keyword("return", snip))
273}
274
275fn keyword(kw: &str, snip: &str) -> CompletionItem {
276 CompletionItem {
277 label: kw.to_string(),
278 lookup: None,
279 snippet: Some(snip.to_string()),
280 }
281}
282
283fn complete_expr_snippets(acc: &mut Vec<CompletionItem>) {
284 acc.push(CompletionItem {
285 label: "pd".to_string(),
286 lookup: None,
287 snippet: Some("eprintln!(\"$0 = {:?}\", $0);".to_string()),
288 });
289 acc.push(CompletionItem {
290 label: "ppd".to_string(),
291 lookup: None,
292 snippet: Some("eprintln!(\"$0 = {:#?}\", $0);".to_string()),
293 });
294}
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index 3d0f13f34..94729d296 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,4 +1,4 @@
1use std::sync::Arc; 1use std::{fmt, sync::Arc};
2use salsa::{self, Database}; 2use salsa::{self, Database};
3use ra_db::{LocationIntener, BaseDatabase}; 3use ra_db::{LocationIntener, BaseDatabase};
4use hir::{self, DefId, DefLoc}; 4use hir::{self, DefId, DefLoc};
@@ -13,11 +13,19 @@ pub(crate) struct RootDatabase {
13 id_maps: Arc<IdMaps>, 13 id_maps: Arc<IdMaps>,
14} 14}
15 15
16#[derive(Debug, Default)] 16#[derive(Default)]
17struct IdMaps { 17struct IdMaps {
18 defs: LocationIntener<DefLoc, DefId>, 18 defs: LocationIntener<DefLoc, DefId>,
19} 19}
20 20
21impl fmt::Debug for IdMaps {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 f.debug_struct("IdMaps")
24 .field("n_defs", &self.defs.len())
25 .finish()
26 }
27}
28
21impl salsa::Database for RootDatabase { 29impl salsa::Database for RootDatabase {
22 fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> { 30 fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> {
23 &self.runtime 31 &self.runtime
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index b44d9297a..b01382808 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -25,7 +25,7 @@ use crate::{
25 db, 25 db,
26 symbol_index::{SymbolIndex, SymbolsDatabase, LibrarySymbolsQuery}, 26 symbol_index::{SymbolIndex, SymbolsDatabase, LibrarySymbolsQuery},
27 AnalysisChange, RootChange, Cancelable, CrateId, Diagnostic, FileId, 27 AnalysisChange, RootChange, Cancelable, CrateId, Diagnostic, FileId,
28 FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, 28 FileSystemEdit, FilePosition, Query, SourceChange, SourceFileEdit,
29 ReferenceResolution, 29 ReferenceResolution,
30}; 30};
31 31
@@ -219,7 +219,8 @@ impl AnalysisImpl {
219 self.db.crate_graph().crate_root(crate_id) 219 self.db.crate_graph().crate_root(crate_id)
220 } 220 }
221 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { 221 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
222 completions(&self.db, position) 222 let completions = completions(&self.db, position)?;
223 Ok(completions.map(|it| it.into()))
223 } 224 }
224 pub fn approximately_resolve_symbol( 225 pub fn approximately_resolve_symbol(
225 &self, 226 &self,
@@ -234,7 +235,7 @@ impl AnalysisImpl {
234 position.file_id, 235 position.file_id,
235 name_ref.syntax(), 236 name_ref.syntax(),
236 )? { 237 )? {
237 let scope = fn_descr.scope(&*self.db); 238 let scope = fn_descr.scopes(&*self.db);
238 // First try to resolve the symbol locally 239 // First try to resolve the symbol locally
239 if let Some(entry) = scope.resolve_local_name(name_ref) { 240 if let Some(entry) = scope.resolve_local_name(name_ref) {
240 rr.add_resolution( 241 rr.add_resolution(
@@ -293,7 +294,7 @@ impl AnalysisImpl {
293 let mut ret = vec![(position.file_id, binding.syntax().range())]; 294 let mut ret = vec![(position.file_id, binding.syntax().range())];
294 ret.extend( 295 ret.extend(
295 descr 296 descr
296 .scope(&*self.db) 297 .scopes(&*self.db)
297 .find_all_refs(binding) 298 .find_all_refs(binding)
298 .into_iter() 299 .into_iter()
299 .map(|ref_desc| (position.file_id, ref_desc.range)), 300 .map(|ref_desc| (position.file_id, ref_desc.range)),
@@ -321,7 +322,7 @@ impl AnalysisImpl {
321 position.file_id, 322 position.file_id,
322 name_ref.syntax(), 323 name_ref.syntax(),
323 )?); 324 )?);
324 let scope = descr.scope(db); 325 let scope = descr.scopes(db);
325 let resolved = ctry!(scope.resolve_local_name(name_ref)); 326 let resolved = ctry!(scope.resolve_local_name(name_ref));
326 let resolved = resolved.ptr().resolve(source_file); 327 let resolved = resolved.ptr().resolve(source_file);
327 let binding = ctry!(find_node_at_offset::<ast::BindPat>( 328 let binding = ctry!(find_node_at_offset::<ast::BindPat>(
@@ -368,10 +369,11 @@ impl AnalysisImpl {
368 .collect::<Vec<_>>(); 369 .collect::<Vec<_>>();
369 if let Some(m) = source_binder::module_from_file_id(&*self.db, file_id)? { 370 if let Some(m) = source_binder::module_from_file_id(&*self.db, file_id)? {
370 for (name_node, problem) in m.problems(&*self.db) { 371 for (name_node, problem) in m.problems(&*self.db) {
372 let source_root = self.db.file_source_root(file_id);
371 let diag = match problem { 373 let diag = match problem {
372 Problem::UnresolvedModule { candidate } => { 374 Problem::UnresolvedModule { candidate } => {
373 let create_file = FileSystemEdit::CreateFile { 375 let create_file = FileSystemEdit::CreateFile {
374 anchor: file_id, 376 source_root,
375 path: candidate.clone(), 377 path: candidate.clone(),
376 }; 378 };
377 let fix = SourceChange { 379 let fix = SourceChange {
@@ -388,11 +390,12 @@ impl AnalysisImpl {
388 } 390 }
389 Problem::NotDirOwner { move_to, candidate } => { 391 Problem::NotDirOwner { move_to, candidate } => {
390 let move_file = FileSystemEdit::MoveFile { 392 let move_file = FileSystemEdit::MoveFile {
391 file: file_id, 393 src: file_id,
392 path: move_to.clone(), 394 dst_source_root: source_root,
395 dst_path: move_to.clone(),
393 }; 396 };
394 let create_file = FileSystemEdit::CreateFile { 397 let create_file = FileSystemEdit::CreateFile {
395 anchor: file_id, 398 source_root,
396 path: move_to.join(candidate), 399 path: move_to.join(candidate),
397 }; 400 };
398 let fix = SourceChange { 401 let fix = SourceChange {
@@ -518,9 +521,9 @@ impl AnalysisImpl {
518 521
519impl SourceChange { 522impl SourceChange {
520 pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange { 523 pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange {
521 let file_edit = SourceFileNodeEdit { 524 let file_edit = SourceFileEdit {
522 file_id, 525 file_id,
523 edits: edit.edit.into_atoms(), 526 edit: edit.edit,
524 }; 527 };
525 SourceChange { 528 SourceChange {
526 label: label.to_string(), 529 label: label.to_string(),
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index a1d462528..85df9c089 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -20,7 +20,7 @@ use std::{fmt, sync::Arc};
20 20
21use rustc_hash::FxHashMap; 21use rustc_hash::FxHashMap;
22use ra_syntax::{SourceFileNode, TextRange, TextUnit}; 22use ra_syntax::{SourceFileNode, TextRange, TextUnit};
23use ra_text_edit::AtomTextEdit; 23use ra_text_edit::TextEdit;
24use rayon::prelude::*; 24use rayon::prelude::*;
25use relative_path::RelativePathBuf; 25use relative_path::RelativePathBuf;
26 26
@@ -30,7 +30,7 @@ use crate::{
30}; 30};
31 31
32pub use crate::{ 32pub use crate::{
33 completion::CompletionItem, 33 completion::{CompletionItem, CompletionItemKind, InsertText},
34}; 34};
35pub use ra_editor::{ 35pub use ra_editor::{
36 FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode, 36 FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode,
@@ -72,13 +72,23 @@ struct RemoveFile {
72 72
73impl fmt::Debug for AnalysisChange { 73impl fmt::Debug for AnalysisChange {
74 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 74 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
75 fmt.debug_struct("AnalysisChange") 75 let mut d = fmt.debug_struct("AnalysisChange");
76 .field("new_roots", &self.new_roots) 76 if !self.new_roots.is_empty() {
77 .field("roots_changed", &self.roots_changed) 77 d.field("new_roots", &self.new_roots);
78 .field("files_changed", &self.files_changed.len()) 78 }
79 .field("libraries_added", &self.libraries_added.len()) 79 if !self.roots_changed.is_empty() {
80 .field("crate_graph", &self.crate_graph) 80 d.field("roots_changed", &self.roots_changed);
81 .finish() 81 }
82 if !self.files_changed.is_empty() {
83 d.field("files_changed", &self.files_changed.len());
84 }
85 if !self.libraries_added.is_empty() {
86 d.field("libraries_added", &self.libraries_added.len());
87 }
88 if !self.crate_graph.is_some() {
89 d.field("crate_graph", &self.crate_graph);
90 }
91 d.finish()
82 } 92 }
83} 93}
84 94
@@ -159,26 +169,27 @@ impl AnalysisHost {
159#[derive(Debug)] 169#[derive(Debug)]
160pub struct SourceChange { 170pub struct SourceChange {
161 pub label: String, 171 pub label: String,
162 pub source_file_edits: Vec<SourceFileNodeEdit>, 172 pub source_file_edits: Vec<SourceFileEdit>,
163 pub file_system_edits: Vec<FileSystemEdit>, 173 pub file_system_edits: Vec<FileSystemEdit>,
164 pub cursor_position: Option<FilePosition>, 174 pub cursor_position: Option<FilePosition>,
165} 175}
166 176
167#[derive(Debug)] 177#[derive(Debug)]
168pub struct SourceFileNodeEdit { 178pub struct SourceFileEdit {
169 pub file_id: FileId, 179 pub file_id: FileId,
170 pub edits: Vec<AtomTextEdit>, 180 pub edit: TextEdit,
171} 181}
172 182
173#[derive(Debug)] 183#[derive(Debug)]
174pub enum FileSystemEdit { 184pub enum FileSystemEdit {
175 CreateFile { 185 CreateFile {
176 anchor: FileId, 186 source_root: SourceRootId,
177 path: RelativePathBuf, 187 path: RelativePathBuf,
178 }, 188 },
179 MoveFile { 189 MoveFile {
180 file: FileId, 190 src: FileId,
181 path: RelativePathBuf, 191 dst_source_root: SourceRootId,
192 dst_path: RelativePathBuf,
182 }, 193 },
183} 194}
184 195
@@ -357,13 +368,22 @@ impl Analysis {
357 } 368 }
358} 369}
359 370
360#[derive(Debug)]
361pub struct LibraryData { 371pub struct LibraryData {
362 root_id: SourceRootId, 372 root_id: SourceRootId,
363 root_change: RootChange, 373 root_change: RootChange,
364 symbol_index: SymbolIndex, 374 symbol_index: SymbolIndex,
365} 375}
366 376
377impl fmt::Debug for LibraryData {
378 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
379 f.debug_struct("LibraryData")
380 .field("root_id", &self.root_id)
381 .field("root_change", &self.root_change)
382 .field("n_symbols", &self.symbol_index.len())
383 .finish()
384 }
385}
386
367impl LibraryData { 387impl LibraryData {
368 pub fn prepare( 388 pub fn prepare(
369 root_id: SourceRootId, 389 root_id: SourceRootId,
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs
index b48a37229..e5bdf0aa1 100644
--- a/crates/ra_analysis/src/symbol_index.rs
+++ b/crates/ra_analysis/src/symbol_index.rs
@@ -56,6 +56,10 @@ impl Hash for SymbolIndex {
56} 56}
57 57
58impl SymbolIndex { 58impl SymbolIndex {
59 pub(crate) fn len(&self) -> usize {
60 self.symbols.len()
61 }
62
59 pub(crate) fn for_files( 63 pub(crate) fn for_files(
60 files: impl ParallelIterator<Item = (FileId, SourceFileNode)>, 64 files: impl ParallelIterator<Item = (FileId, SourceFileNode)>,
61 ) -> SymbolIndex { 65 ) -> SymbolIndex {
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs
index 889b568b9..938ca797a 100644
--- a/crates/ra_analysis/tests/tests.rs
+++ b/crates/ra_analysis/tests/tests.rs
@@ -81,7 +81,7 @@ fn test_unresolved_module_diagnostic() {
81 fix: Some(SourceChange { 81 fix: Some(SourceChange {
82 label: "create module", 82 label: "create module",
83 source_file_edits: [], 83 source_file_edits: [],
84 file_system_edits: [CreateFile { anchor: FileId(1), path: "../foo.rs" }], 84 file_system_edits: [CreateFile { source_root: SourceRootId(0), path: "foo.rs" }],
85 cursor_position: None }) }]"#, 85 cursor_position: None }) }]"#,
86 &diagnostics, 86 &diagnostics,
87 ); 87 );
@@ -452,63 +452,3 @@ fn test_find_all_refs_for_fn_param() {
452 let refs = get_all_refs(code); 452 let refs = get_all_refs(code);
453 assert_eq!(refs.len(), 2); 453 assert_eq!(refs.len(), 2);
454} 454}
455
456#[test]
457fn test_complete_crate_path() {
458 let (analysis, position) = analysis_and_position(
459 "
460 //- /lib.rs
461 mod foo;
462 struct Spam;
463 //- /foo.rs
464 use crate::Sp<|>
465 ",
466 );
467 let completions = analysis.completions(position).unwrap().unwrap();
468 assert_eq_dbg(
469 r#"[CompletionItem { label: "Spam", lookup: None, snippet: None },
470 CompletionItem { label: "foo", lookup: None, snippet: None }]"#,
471 &completions,
472 );
473}
474
475#[test]
476fn test_complete_crate_path_with_braces() {
477 let (analysis, position) = analysis_and_position(
478 "
479 //- /lib.rs
480 mod foo;
481 struct Spam;
482 //- /foo.rs
483 use crate::{Sp<|>};
484 ",
485 );
486 let completions = analysis.completions(position).unwrap().unwrap();
487 assert_eq_dbg(
488 r#"[CompletionItem { label: "Spam", lookup: None, snippet: None },
489 CompletionItem { label: "foo", lookup: None, snippet: None }]"#,
490 &completions,
491 );
492}
493
494#[test]
495fn test_complete_crate_path_in_nested_tree() {
496 let (analysis, position) = analysis_and_position(
497 "
498 //- /lib.rs
499 mod foo;
500 pub mod bar {
501 pub mod baz {
502 pub struct Spam;
503 }
504 }
505 //- /foo.rs
506 use crate::{bar::{baz::Sp<|>}};
507 ",
508 );
509 let completions = analysis.completions(position).unwrap().unwrap();
510 assert_eq_dbg(
511 r#"[CompletionItem { label: "Spam", lookup: None, snippet: None }]"#,
512 &completions,
513 );
514}
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index f12dd9345..7c3dd9296 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -7,11 +7,13 @@
7/// actual IO is done and lowered to input. 7/// actual IO is done and lowered to input.
8use std::sync::Arc; 8use std::sync::Arc;
9 9
10use rustc_hash::{FxHashMap};
11use relative_path::RelativePathBuf; 10use relative_path::RelativePathBuf;
12use ra_syntax::SmolStr; 11use rustc_hash::FxHashMap;
13use salsa; 12use salsa;
14 13
14use ra_syntax::SmolStr;
15use rustc_hash::FxHashSet;
16
15/// `FileId` is an integer which uniquely identifies a file. File paths are 17/// `FileId` is an integer which uniquely identifies a file. File paths are
16/// messy and system-dependent, so most of the code should work directly with 18/// messy and system-dependent, so most of the code should work directly with
17/// `FileId`, without inspecting the path. The mapping between `FileId` and path 19/// `FileId`, without inspecting the path. The mapping between `FileId` and path
@@ -92,12 +94,16 @@ impl CrateGraph {
92 assert!(prev.is_none()); 94 assert!(prev.is_none());
93 crate_id 95 crate_id
94 } 96 }
95 // FIXME: check that we don't have cycles here.
96 // Just a simple depth first search from `to` should work,
97 // the graph is small.
98 pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) { 97 pub fn add_dep(&mut self, from: CrateId, name: SmolStr, to: CrateId) {
98 let mut visited = FxHashSet::default();
99 if self.dfs_find(from, to, &mut visited) {
100 panic!("Cycle dependencies found.")
101 }
99 self.arena.get_mut(&from).unwrap().add_dep(name, to) 102 self.arena.get_mut(&from).unwrap().add_dep(name, to)
100 } 103 }
104 pub fn is_empty(&self) -> bool {
105 self.arena.is_empty()
106 }
101 pub fn crate_root(&self, crate_id: CrateId) -> FileId { 107 pub fn crate_root(&self, crate_id: CrateId) -> FileId {
102 self.arena[&crate_id].file_id 108 self.arena[&crate_id].file_id
103 } 109 }
@@ -114,6 +120,52 @@ impl CrateGraph {
114 ) -> impl Iterator<Item = &'a Dependency> + 'a { 120 ) -> impl Iterator<Item = &'a Dependency> + 'a {
115 self.arena[&crate_id].dependencies.iter() 121 self.arena[&crate_id].dependencies.iter()
116 } 122 }
123 fn dfs_find(&self, target: CrateId, from: CrateId, visited: &mut FxHashSet<CrateId>) -> bool {
124 if !visited.insert(from) {
125 return false;
126 }
127
128 for dep in self.dependencies(from) {
129 let crate_id = dep.crate_id();
130 if crate_id == target {
131 return true;
132 }
133
134 if self.dfs_find(target, crate_id, visited) {
135 return true;
136 }
137 }
138 return false;
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::{CrateGraph, FxHashMap, FileId, SmolStr};
145
146 #[test]
147 #[should_panic]
148 fn it_should_painc_because_of_cycle_dependencies() {
149 let mut graph = CrateGraph::default();
150 let crate1 = graph.add_crate_root(FileId(1u32));
151 let crate2 = graph.add_crate_root(FileId(2u32));
152 let crate3 = graph.add_crate_root(FileId(3u32));
153 graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
154 graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
155 graph.add_dep(crate3, SmolStr::new("crate1"), crate1);
156 }
157
158 #[test]
159 fn it_works() {
160 let mut graph = CrateGraph {
161 arena: FxHashMap::default(),
162 };
163 let crate1 = graph.add_crate_root(FileId(1u32));
164 let crate2 = graph.add_crate_root(FileId(2u32));
165 let crate3 = graph.add_crate_root(FileId(3u32));
166 graph.add_dep(crate1, SmolStr::new("crate2"), crate2);
167 graph.add_dep(crate2, SmolStr::new("crate3"), crate3);
168 }
117} 169}
118 170
119salsa::query_group! { 171salsa::query_group! {
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 65fa3cbfa..0aca6f343 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -15,7 +15,7 @@ pub type Cancelable<T> = Result<T, Canceled>;
15 15
16impl std::fmt::Display for Canceled { 16impl std::fmt::Display for Canceled {
17 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 17 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 fmt.write_str("Canceled") 18 fmt.write_str("canceled")
19 } 19 }
20} 20}
21 21
diff --git a/crates/ra_db/src/loc2id.rs b/crates/ra_db/src/loc2id.rs
index 69ba43d0f..2dc7930d8 100644
--- a/crates/ra_db/src/loc2id.rs
+++ b/crates/ra_db/src/loc2id.rs
@@ -42,6 +42,10 @@ where
42 ID: NumericId, 42 ID: NumericId,
43 LOC: Clone + Eq + Hash, 43 LOC: Clone + Eq + Hash,
44{ 44{
45 pub fn len(&self) -> usize {
46 self.loc2id.len()
47 }
48
45 pub fn loc2id(&mut self, loc: &LOC) -> ID { 49 pub fn loc2id(&mut self, loc: &LOC) -> ID {
46 match self.loc2id.get(loc) { 50 match self.loc2id.get(loc) {
47 Some(id) => return id.clone(), 51 Some(id) => return id.clone(),
@@ -91,6 +95,9 @@ where
91 ID: NumericId, 95 ID: NumericId,
92 LOC: Clone + Eq + Hash, 96 LOC: Clone + Eq + Hash,
93{ 97{
98 pub fn len(&self) -> usize {
99 self.map.lock().len()
100 }
94 pub fn loc2id(&self, loc: &LOC) -> ID { 101 pub fn loc2id(&self, loc: &LOC) -> ID {
95 self.map.lock().loc2id(loc) 102 self.map.lock().loc2id(loc)
96 } 103 }
diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs
index 2a8fa3cda..da542ecf0 100644
--- a/crates/ra_editor/src/folding_ranges.rs
+++ b/crates/ra_editor/src/folding_ranges.rs
@@ -10,6 +10,7 @@ use ra_syntax::{
10pub enum FoldKind { 10pub enum FoldKind {
11 Comment, 11 Comment,
12 Imports, 12 Imports,
13 Block,
13} 14}
14 15
15#[derive(Debug)] 16#[derive(Debug)]
@@ -62,6 +63,8 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
62 match kind { 63 match kind {
63 COMMENT => Some(FoldKind::Comment), 64 COMMENT => Some(FoldKind::Comment),
64 USE_ITEM => Some(FoldKind::Imports), 65 USE_ITEM => Some(FoldKind::Imports),
66 NAMED_FIELD_DEF_LIST | FIELD_PAT_LIST | ITEM_LIST | EXTERN_ITEM_LIST | USE_TREE_LIST
67 | BLOCK | ENUM_VARIANT_LIST => Some(FoldKind::Block),
65 _ => None, 68 _ => None,
66 } 69 }
67} 70}
@@ -170,7 +173,7 @@ mod tests {
170 use test_utils::extract_ranges; 173 use test_utils::extract_ranges;
171 174
172 fn do_check(text: &str, fold_kinds: &[FoldKind]) { 175 fn do_check(text: &str, fold_kinds: &[FoldKind]) {
173 let (ranges, text) = extract_ranges(text); 176 let (ranges, text) = extract_ranges(text, "fold");
174 let file = SourceFileNode::parse(&text); 177 let file = SourceFileNode::parse(&text);
175 let folds = folding_ranges(&file); 178 let folds = folding_ranges(&file);
176 179
@@ -198,26 +201,27 @@ mod tests {
198 #[test] 201 #[test]
199 fn test_fold_comments() { 202 fn test_fold_comments() {
200 let text = r#" 203 let text = r#"
201<|>// Hello 204<fold>// Hello
202// this is a multiline 205// this is a multiline
203// comment 206// comment
204//<|> 207//</fold>
205 208
206// But this is not 209// But this is not
207 210
208fn main() { 211fn main() <fold>{
209 <|>// We should 212 <fold>// We should
210 // also 213 // also
211 // fold 214 // fold
212 // this one.<|> 215 // this one.</fold>
213 <|>//! But this one is different 216 <fold>//! But this one is different
214 //! because it has another flavor<|> 217 //! because it has another flavor</fold>
215 <|>/* As does this 218 <fold>/* As does this
216 multiline comment */<|> 219 multiline comment */</fold>
217}"#; 220}</fold>"#;
218 221
219 let fold_kinds = &[ 222 let fold_kinds = &[
220 FoldKind::Comment, 223 FoldKind::Comment,
224 FoldKind::Block,
221 FoldKind::Comment, 225 FoldKind::Comment,
222 FoldKind::Comment, 226 FoldKind::Comment,
223 FoldKind::Comment, 227 FoldKind::Comment,
@@ -228,60 +232,66 @@ fn main() {
228 #[test] 232 #[test]
229 fn test_fold_imports() { 233 fn test_fold_imports() {
230 let text = r#" 234 let text = r#"
231<|>use std::{ 235<fold>use std::<fold>{
232 str, 236 str,
233 vec, 237 vec,
234 io as iop 238 io as iop
235};<|> 239}</fold>;</fold>
236 240
237fn main() { 241fn main() <fold>{
238}"#; 242}</fold>"#;
239 243
240 let folds = &[FoldKind::Imports]; 244 let folds = &[FoldKind::Imports, FoldKind::Block, FoldKind::Block];
241 do_check(text, folds); 245 do_check(text, folds);
242 } 246 }
243 247
244 #[test] 248 #[test]
245 fn test_fold_import_groups() { 249 fn test_fold_import_groups() {
246 let text = r#" 250 let text = r#"
247<|>use std::str; 251<fold>use std::str;
248use std::vec; 252use std::vec;
249use std::io as iop;<|> 253use std::io as iop;</fold>
250 254
251<|>use std::mem; 255<fold>use std::mem;
252use std::f64;<|> 256use std::f64;</fold>
253 257
254use std::collections::HashMap; 258use std::collections::HashMap;
255// Some random comment 259// Some random comment
256use std::collections::VecDeque; 260use std::collections::VecDeque;
257 261
258fn main() { 262fn main() <fold>{
259}"#; 263}</fold>"#;
260 264
261 let folds = &[FoldKind::Imports, FoldKind::Imports]; 265 let folds = &[FoldKind::Imports, FoldKind::Imports, FoldKind::Block];
262 do_check(text, folds); 266 do_check(text, folds);
263 } 267 }
264 268
265 #[test] 269 #[test]
266 fn test_fold_import_and_groups() { 270 fn test_fold_import_and_groups() {
267 let text = r#" 271 let text = r#"
268<|>use std::str; 272<fold>use std::str;
269use std::vec; 273use std::vec;
270use std::io as iop;<|> 274use std::io as iop;</fold>
271 275
272<|>use std::mem; 276<fold>use std::mem;
273use std::f64;<|> 277use std::f64;</fold>
274 278
275<|>use std::collections::{ 279<fold>use std::collections::<fold>{
276 HashMap, 280 HashMap,
277 VecDeque, 281 VecDeque,
278};<|> 282}</fold>;</fold>
279// Some random comment 283// Some random comment
280 284
281fn main() { 285fn main() <fold>{
282}"#; 286}</fold>"#;
283 287
284 let folds = &[FoldKind::Imports, FoldKind::Imports, FoldKind::Imports]; 288 let folds = &[
289 FoldKind::Imports,
290 FoldKind::Imports,
291 FoldKind::Imports,
292 FoldKind::Block,
293 FoldKind::Block,
294 ];
285 do_check(text, folds); 295 do_check(text, folds);
286 } 296 }
287 297
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 46a6e2d62..5e412bcfa 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -164,6 +164,16 @@ fn remove_newline(
164 if join_single_expr_block(edit, node).is_some() { 164 if join_single_expr_block(edit, node).is_some() {
165 return; 165 return;
166 } 166 }
167 // ditto for
168 //
169 // ```
170 // use foo::{<|>
171 // bar
172 // };
173 // ```
174 if join_single_use_tree(edit, node).is_some() {
175 return;
176 }
167 177
168 // The node is between two other nodes 178 // The node is between two other nodes
169 let prev = node.prev_sibling().unwrap(); 179 let prev = node.prev_sibling().unwrap();
@@ -228,6 +238,36 @@ fn single_expr(block: ast::Block) -> Option<ast::Expr> {
228 res 238 res
229} 239}
230 240
241fn join_single_use_tree(edit: &mut TextEditBuilder, node: SyntaxNodeRef) -> Option<()> {
242 let use_tree_list = ast::UseTreeList::cast(node.parent()?)?;
243 let tree = single_use_tree(use_tree_list)?;
244 edit.replace(
245 use_tree_list.syntax().range(),
246 tree.syntax().text().to_string(),
247 );
248 Some(())
249}
250
251fn single_use_tree(tree_list: ast::UseTreeList) -> Option<ast::UseTree> {
252 let mut res = None;
253 for child in tree_list.syntax().children() {
254 if let Some(tree) = ast::UseTree::cast(child) {
255 if tree.syntax().text().contains('\n') {
256 return None;
257 }
258 if mem::replace(&mut res, Some(tree)).is_some() {
259 return None;
260 }
261 } else {
262 match child.kind() {
263 WHITESPACE | L_CURLY | R_CURLY | COMMA => (),
264 _ => return None,
265 }
266 }
267 }
268 res
269}
270
231fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str { 271fn compute_ws(left: SyntaxNodeRef, right: SyntaxNodeRef) -> &'static str {
232 match left.kind() { 272 match left.kind() {
233 L_PAREN | L_BRACK => return "", 273 L_PAREN | L_BRACK => return "",
@@ -306,6 +346,24 @@ fn foo() {
306 } 346 }
307 347
308 #[test] 348 #[test]
349 fn test_join_lines_use_tree() {
350 check_join_lines(
351 r"
352use ra_syntax::{
353 algo::<|>{
354 find_leaf_at_offset,
355 },
356 ast,
357};",
358 r"
359use ra_syntax::{
360 algo::<|>find_leaf_at_offset,
361 ast,
362};",
363 );
364 }
365
366 #[test]
309 fn test_join_lines_normal_comments() { 367 fn test_join_lines_normal_comments() {
310 check_join_lines( 368 check_join_lines(
311 r" 369 r"
diff --git a/crates/ra_hir/src/function.rs b/crates/ra_hir/src/function.rs
index 5187dc051..2925beb16 100644
--- a/crates/ra_hir/src/function.rs
+++ b/crates/ra_hir/src/function.rs
@@ -27,7 +27,7 @@ impl Function {
27 Function { fn_id } 27 Function { fn_id }
28 } 28 }
29 29
30 pub fn scope(&self, db: &impl HirDatabase) -> Arc<FnScopes> { 30 pub fn scopes(&self, db: &impl HirDatabase) -> Arc<FnScopes> {
31 db.fn_scopes(self.fn_id) 31 db.fn_scopes(self.fn_id)
32 } 32 }
33 33
diff --git a/crates/ra_hir/src/function/scope.rs b/crates/ra_hir/src/function/scope.rs
index 863453291..a1a580979 100644
--- a/crates/ra_hir/src/function/scope.rs
+++ b/crates/ra_hir/src/function/scope.rs
@@ -1,7 +1,7 @@
1use rustc_hash::{FxHashMap, FxHashSet}; 1use rustc_hash::{FxHashMap, FxHashSet};
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 AstNode, SmolStr, SyntaxNodeRef, TextRange, 4 AstNode, SmolStr, SyntaxNodeRef, TextUnit, TextRange,
5 algo::generate, 5 algo::generate,
6 ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, 6 ast::{self, ArgListOwner, LoopBodyOwner, NameOwner},
7}; 7};
@@ -33,7 +33,7 @@ pub struct ScopeData {
33} 33}
34 34
35impl FnScopes { 35impl FnScopes {
36 pub fn new(fn_def: ast::FnDef) -> FnScopes { 36 pub(crate) fn new(fn_def: ast::FnDef) -> FnScopes {
37 let mut scopes = FnScopes { 37 let mut scopes = FnScopes {
38 self_param: fn_def 38 self_param: fn_def
39 .param_list() 39 .param_list()
@@ -57,6 +57,48 @@ impl FnScopes {
57 self.scopes[scope].parent 57 self.scopes[scope].parent
58 }) 58 })
59 } 59 }
60 pub fn scope_chain_for_offset<'a>(
61 &'a self,
62 offset: TextUnit,
63 ) -> impl Iterator<Item = ScopeId> + 'a {
64 let scope = self
65 .scope_for
66 .iter()
67 // find containin scope
68 .min_by_key(|(ptr, _scope)| {
69 (
70 !(ptr.range().start() <= offset && offset <= ptr.range().end()),
71 ptr.range().len(),
72 )
73 })
74 .map(|(ptr, scope)| self.adjust(*ptr, *scope, offset));
75
76 generate(scope, move |&scope| self.scopes[scope].parent)
77 }
78 // XXX: during completion, cursor might be outside of any particular
79 // expression. Try to figure out the correct scope...
80 fn adjust(&self, ptr: LocalSyntaxPtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId {
81 let r = ptr.range();
82 let child_scopes = self
83 .scope_for
84 .iter()
85 .map(|(ptr, scope)| (ptr.range(), scope))
86 .filter(|(range, _)| range.start() <= offset && range.is_subrange(&r) && *range != r);
87
88 child_scopes
89 .max_by(|(r1, _), (r2, _)| {
90 if r2.is_subrange(&r1) {
91 std::cmp::Ordering::Greater
92 } else if r1.is_subrange(&r2) {
93 std::cmp::Ordering::Less
94 } else {
95 r1.start().cmp(&r2.start())
96 }
97 })
98 .map(|(_ptr, scope)| *scope)
99 .unwrap_or(original_scope)
100 }
101
60 pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> { 102 pub fn resolve_local_name<'a>(&'a self, name_ref: ast::NameRef) -> Option<&'a ScopeEntry> {
61 let mut shadowed = FxHashSet::default(); 103 let mut shadowed = FxHashSet::default();
62 let ret = self 104 let ret = self
@@ -144,6 +186,8 @@ impl ScopeEntry {
144} 186}
145 187
146fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: ScopeId) { 188fn compute_block_scopes(block: ast::Block, scopes: &mut FnScopes, mut scope: ScopeId) {
189 // A hack for completion :(
190 scopes.set_scope(block.syntax(), scope);
147 for stmt in block.statements() { 191 for stmt in block.statements() {
148 match stmt { 192 match stmt {
149 ast::Stmt::LetStmt(stmt) => { 193 ast::Stmt::LetStmt(stmt) => {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 5941a9ea3..f56214b47 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -39,7 +39,7 @@ use crate::{
39pub use self::{ 39pub use self::{
40 path::{Path, PathKind}, 40 path::{Path, PathKind},
41 krate::Crate, 41 krate::Crate,
42 module::{Module, ModuleId, Problem, nameres::ItemMap}, 42 module::{Module, ModuleId, Problem, nameres::ItemMap, ModuleScope, Resolution},
43 function::{Function, FnScopes}, 43 function::{Function, FnScopes},
44}; 44};
45 45
diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs
index d5866f6ef..cd31e8cfe 100644
--- a/crates/ra_hir/src/module.rs
+++ b/crates/ra_hir/src/module.rs
@@ -16,7 +16,7 @@ use crate::{
16 arena::{Arena, Id}, 16 arena::{Arena, Id},
17}; 17};
18 18
19pub use self::nameres::ModuleScope; 19pub use self::nameres::{ModuleScope, Resolution};
20 20
21/// `Module` is API entry point to get all the information 21/// `Module` is API entry point to get all the information
22/// about a particular module. 22/// about a particular module.
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs
index f3a346152..748fdb64e 100644
--- a/crates/ra_hir/src/module/imp.rs
+++ b/crates/ra_hir/src/module/imp.rs
@@ -4,7 +4,7 @@ use ra_syntax::{
4 ast::{self, NameOwner}, 4 ast::{self, NameOwner},
5 SmolStr, 5 SmolStr,
6}; 6};
7use relative_path::{RelativePathBuf, RelativePath}; 7use relative_path::RelativePathBuf;
8use rustc_hash::{FxHashMap, FxHashSet}; 8use rustc_hash::{FxHashMap, FxHashSet};
9use arrayvec::ArrayVec; 9use arrayvec::ArrayVec;
10use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId}; 10use ra_db::{SourceRoot, SourceRootId, Cancelable, FileId};
@@ -184,11 +184,7 @@ fn resolve_submodule(
184 .collect::<Vec<_>>(); 184 .collect::<Vec<_>>();
185 let problem = if points_to.is_empty() { 185 let problem = if points_to.is_empty() {
186 Some(Problem::UnresolvedModule { 186 Some(Problem::UnresolvedModule {
187 candidate: RelativePath::new("../").join(&if is_dir_owner { 187 candidate: if is_dir_owner { file_mod } else { file_dir_mod },
188 file_mod
189 } else {
190 file_dir_mod
191 }),
192 }) 188 })
193 } else { 189 } else {
194 None 190 None
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs
index f44abc730..39e891cda 100644
--- a/crates/ra_hir/src/module/nameres.rs
+++ b/crates/ra_hir/src/module/nameres.rs
@@ -49,7 +49,7 @@ pub struct ModuleScope {
49} 49}
50 50
51impl ModuleScope { 51impl ModuleScope {
52 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &Resolution)> + 'a { 52 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a SmolStr, &'a Resolution)> + 'a {
53 self.items.iter() 53 self.items.iter()
54 } 54 }
55 pub fn get(&self, name: &SmolStr) -> Option<&Resolution> { 55 pub fn get(&self, name: &SmolStr) -> Option<&Resolution> {
diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/module/nameres/tests.rs
index 9fa9146e3..3e29c3954 100644
--- a/crates/ra_hir/src/module/nameres/tests.rs
+++ b/crates/ra_hir/src/module/nameres/tests.rs
@@ -44,6 +44,25 @@ fn item_map_smoke_test() {
44} 44}
45 45
46#[test] 46#[test]
47fn test_self() {
48 let (item_map, module_id) = item_map(
49 "
50 //- /lib.rs
51 mod foo;
52 use crate::foo::bar::Baz::{self};
53 <|>
54 //- /foo/mod.rs
55 pub mod bar;
56 //- /foo/bar.rs
57 pub struct Baz;
58 ",
59 );
60 let name = SmolStr::from("Baz");
61 let resolution = &item_map.per_module[&module_id].items[&name];
62 assert!(resolution.def_id.is_some());
63}
64
65#[test]
47fn item_map_across_crates() { 66fn item_map_across_crates() {
48 let (mut db, sr) = MockDatabase::with_files( 67 let (mut db, sr) = MockDatabase::with_files(
49 " 68 "
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 4a2e427cd..e04d00900 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -76,17 +76,32 @@ fn expand_use_tree(
76) { 76) {
77 if let Some(use_tree_list) = tree.use_tree_list() { 77 if let Some(use_tree_list) = tree.use_tree_list() {
78 let prefix = match tree.path() { 78 let prefix = match tree.path() {
79 // E.g. use something::{{{inner}}};
79 None => prefix, 80 None => prefix,
81 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
82 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
80 Some(path) => match convert_path(prefix, path) { 83 Some(path) => match convert_path(prefix, path) {
81 Some(it) => Some(it), 84 Some(it) => Some(it),
82 None => return, // TODO: report errors somewhere 85 None => return, // TODO: report errors somewhere
83 }, 86 },
84 }; 87 };
85 for tree in use_tree_list.use_trees() { 88 for child_tree in use_tree_list.use_trees() {
86 expand_use_tree(prefix.clone(), tree, cb); 89 expand_use_tree(prefix.clone(), child_tree, cb);
87 } 90 }
88 } else { 91 } else {
89 if let Some(ast_path) = tree.path() { 92 if let Some(ast_path) = tree.path() {
93 // Handle self in a path.
94 // E.g. `use something::{self, <...>}`
95 if ast_path.qualifier().is_none() {
96 if let Some(segment) = ast_path.segment() {
97 if segment.kind() == Some(ast::PathSegmentKind::SelfKw) {
98 if let Some(prefix) = prefix {
99 cb(prefix, Some(segment.syntax().range()));
100 return;
101 }
102 }
103 }
104 }
90 if let Some(path) = convert_path(prefix, ast_path) { 105 if let Some(path) = convert_path(prefix, ast_path) {
91 let range = if tree.has_star() { 106 let range = if tree.has_star() {
92 None 107 None
@@ -96,6 +111,8 @@ fn expand_use_tree(
96 }; 111 };
97 cb(path, range) 112 cb(path, range)
98 } 113 }
114 // TODO: report errors somewhere
115 // We get here if we do
99 } 116 }
100 } 117 }
101} 118}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index ce2a0f2e8..a0165aef2 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -74,6 +74,16 @@ pub fn function_from_source(
74 fn_def: ast::FnDef, 74 fn_def: ast::FnDef,
75) -> Cancelable<Option<Function>> { 75) -> Cancelable<Option<Function>> {
76 let module = ctry!(module_from_child_node(db, file_id, fn_def.syntax())?); 76 let module = ctry!(module_from_child_node(db, file_id, fn_def.syntax())?);
77 let res = function_from_module(db, &module, fn_def);
78 Ok(Some(res))
79}
80
81pub fn function_from_module(
82 db: &impl HirDatabase,
83 module: &Module,
84 fn_def: ast::FnDef,
85) -> Function {
86 let file_id = module.source().file_id();
77 let file_items = db.file_items(file_id); 87 let file_items = db.file_items(file_id);
78 let item_id = file_items.id_of(file_id, fn_def.syntax()); 88 let item_id = file_items.id_of(file_id, fn_def.syntax());
79 let source_item_id = SourceItemId { 89 let source_item_id = SourceItemId {
@@ -86,7 +96,7 @@ pub fn function_from_source(
86 module_id: module.module_id, 96 module_id: module.module_id,
87 source_item_id, 97 source_item_id,
88 }; 98 };
89 Ok(Some(Function::new(def_loc.id(db)))) 99 Function::new(def_loc.id(db))
90} 100}
91 101
92pub fn function_from_child_node( 102pub fn function_from_child_node(
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index fc10096e5..3c8c240cd 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -12,7 +12,6 @@ failure = "0.1.2"
12failure_derive = "0.1.2" 12failure_derive = "0.1.2"
13serde_json = "1.0.24" 13serde_json = "1.0.24"
14serde = "1.0.71" 14serde = "1.0.71"
15serde_derive = "1.0.71"
16drop_bomb = "0.1.0" 15drop_bomb = "0.1.0"
17crossbeam-channel = "0.2.4" 16crossbeam-channel = "0.2.4"
18flexi_logger = "0.10.0" 17flexi_logger = "0.10.0"
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 7467f472c..051f1f995 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -1,8 +1,8 @@
1use languageserver_types::{ 1use languageserver_types::{
2 self, Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, 2 self, Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
3 TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, 3 TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, InsertTextFormat,
4}; 4};
5use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition}; 5use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit, FilePosition, CompletionItem, CompletionItemKind, InsertText};
6use ra_editor::{LineCol, LineIndex}; 6use ra_editor::{LineCol, LineIndex};
7use ra_text_edit::{AtomTextEdit, TextEdit}; 7use ra_text_edit::{AtomTextEdit, TextEdit};
8use ra_syntax::{SyntaxKind, TextRange, TextUnit}; 8use ra_syntax::{SyntaxKind, TextRange, TextUnit};
@@ -45,6 +45,46 @@ impl Conv for SyntaxKind {
45 } 45 }
46} 46}
47 47
48impl Conv for CompletionItemKind {
49 type Output = ::languageserver_types::CompletionItemKind;
50
51 fn conv(self) -> <Self as Conv>::Output {
52 use ::languageserver_types::CompletionItemKind::*;
53 match self {
54 CompletionItemKind::Keyword => Keyword,
55 CompletionItemKind::Snippet => Snippet,
56 CompletionItemKind::Module => Module,
57 CompletionItemKind::Function => Function,
58 CompletionItemKind::Binding => Variable,
59 }
60 }
61}
62
63impl Conv for CompletionItem {
64 type Output = ::languageserver_types::CompletionItem;
65
66 fn conv(self) -> <Self as Conv>::Output {
67 let mut res = ::languageserver_types::CompletionItem {
68 label: self.label().to_string(),
69 filter_text: Some(self.lookup().to_string()),
70 kind: self.kind().map(|it| it.conv()),
71 ..Default::default()
72 };
73 match self.insert_text() {
74 InsertText::PlainText { text } => {
75 res.insert_text = Some(text);
76 res.insert_text_format = Some(InsertTextFormat::PlainText);
77 }
78 InsertText::Snippet { text } => {
79 res.insert_text = Some(text);
80 res.insert_text_format = Some(InsertTextFormat::Snippet);
81 res.kind = Some(languageserver_types::CompletionItemKind::Keyword);
82 }
83 }
84 res
85 }
86}
87
48impl ConvWith for Position { 88impl ConvWith for Position {
49 type Ctx = LineIndex; 89 type Ctx = LineIndex;
50 type Output = TextUnit; 90 type Output = TextUnit;
@@ -97,21 +137,21 @@ impl ConvWith for TextEdit {
97 type Output = Vec<languageserver_types::TextEdit>; 137 type Output = Vec<languageserver_types::TextEdit>;
98 138
99 fn conv_with(self, line_index: &LineIndex) -> Vec<languageserver_types::TextEdit> { 139 fn conv_with(self, line_index: &LineIndex) -> Vec<languageserver_types::TextEdit> {
100 self.into_atoms() 140 self.as_atoms()
101 .into_iter() 141 .into_iter()
102 .map_conv_with(line_index) 142 .map_conv_with(line_index)
103 .collect() 143 .collect()
104 } 144 }
105} 145}
106 146
107impl ConvWith for AtomTextEdit { 147impl<'a> ConvWith for &'a AtomTextEdit {
108 type Ctx = LineIndex; 148 type Ctx = LineIndex;
109 type Output = languageserver_types::TextEdit; 149 type Output = languageserver_types::TextEdit;
110 150
111 fn conv_with(self, line_index: &LineIndex) -> languageserver_types::TextEdit { 151 fn conv_with(self, line_index: &LineIndex) -> languageserver_types::TextEdit {
112 languageserver_types::TextEdit { 152 languageserver_types::TextEdit {
113 range: self.delete.conv_with(line_index), 153 range: self.delete.conv_with(line_index),
114 new_text: self.insert, 154 new_text: self.insert.clone(),
115 } 155 }
116 } 156 }
117} 157}
@@ -199,7 +239,7 @@ impl TryConvWith for SourceChange {
199 .source_file_edits 239 .source_file_edits
200 .iter() 240 .iter()
201 .find(|it| it.file_id == pos.file_id) 241 .find(|it| it.file_id == pos.file_id)
202 .map(|it| it.edits.as_slice()) 242 .map(|it| it.edit.as_atoms())
203 .unwrap_or(&[]); 243 .unwrap_or(&[]);
204 let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits); 244 let line_col = translate_offset_with_edit(&*line_index, pos.offset, edits);
205 let position = 245 let position =
@@ -256,7 +296,7 @@ fn translate_offset_with_edit(
256 } 296 }
257} 297}
258 298
259impl TryConvWith for SourceFileNodeEdit { 299impl TryConvWith for SourceFileEdit {
260 type Ctx = ServerWorld; 300 type Ctx = ServerWorld;
261 type Output = TextDocumentEdit; 301 type Output = TextDocumentEdit;
262 fn try_conv_with(self, world: &ServerWorld) -> Result<TextDocumentEdit> { 302 fn try_conv_with(self, world: &ServerWorld) -> Result<TextDocumentEdit> {
@@ -265,7 +305,12 @@ impl TryConvWith for SourceFileNodeEdit {
265 version: None, 305 version: None,
266 }; 306 };
267 let line_index = world.analysis().file_line_index(self.file_id); 307 let line_index = world.analysis().file_line_index(self.file_id);
268 let edits = self.edits.into_iter().map_conv_with(&line_index).collect(); 308 let edits = self
309 .edit
310 .as_atoms()
311 .iter()
312 .map_conv_with(&line_index)
313 .collect();
269 Ok(TextDocumentEdit { 314 Ok(TextDocumentEdit {
270 text_document, 315 text_document,
271 edits, 316 edits,
@@ -278,16 +323,17 @@ impl TryConvWith for FileSystemEdit {
278 type Output = req::FileSystemEdit; 323 type Output = req::FileSystemEdit;
279 fn try_conv_with(self, world: &ServerWorld) -> Result<req::FileSystemEdit> { 324 fn try_conv_with(self, world: &ServerWorld) -> Result<req::FileSystemEdit> {
280 let res = match self { 325 let res = match self {
281 FileSystemEdit::CreateFile { anchor, path } => { 326 FileSystemEdit::CreateFile { source_root, path } => {
282 let uri = world.file_id_to_uri(anchor)?; 327 let uri = world.path_to_uri(source_root, &path)?;
283 let path = &path.as_str()[3..]; // strip `../` b/c url is weird
284 let uri = uri.join(path)?;
285 req::FileSystemEdit::CreateFile { uri } 328 req::FileSystemEdit::CreateFile { uri }
286 } 329 }
287 FileSystemEdit::MoveFile { file, path } => { 330 FileSystemEdit::MoveFile {
288 let src = world.file_id_to_uri(file)?; 331 src,
289 let path = &path.as_str()[3..]; // strip `../` b/c url is weird 332 dst_source_root,
290 let dst = src.join(path)?; 333 dst_path,
334 } => {
335 let src = world.file_id_to_uri(src)?;
336 let dst = world.path_to_uri(dst_source_root, &dst_path)?;
291 req::FileSystemEdit::MoveFile { src, dst } 337 req::FileSystemEdit::MoveFile { src, dst }
292 } 338 }
293 }; 339 };
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index 721665eed..33aa30d70 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -1,7 +1,7 @@
1use serde_derive::Deserialize; 1use serde::Deserialize;
2use serde::Deserialize as _D;
3use flexi_logger::{Duplicate, Logger}; 2use flexi_logger::{Duplicate, Logger};
4use gen_lsp_server::{run_server, stdio_transport}; 3use gen_lsp_server::{run_server, stdio_transport};
4
5use ra_lsp_server::Result; 5use ra_lsp_server::Result;
6 6
7fn main() -> Result<()> { 7fn main() -> Result<()> {
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 8b787c329..a5a2b5eec 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -2,6 +2,7 @@ mod handlers;
2mod subscriptions; 2mod subscriptions;
3 3
4use std::{ 4use std::{
5 fmt,
5 path::PathBuf, 6 path::PathBuf,
6 sync::Arc, 7 sync::Arc,
7}; 8};
@@ -109,6 +110,50 @@ pub fn main_loop(
109 Ok(()) 110 Ok(())
110} 111}
111 112
113enum Event {
114 Msg(RawMessage),
115 Task(Task),
116 Vfs(VfsTask),
117 Lib(LibraryData),
118}
119
120impl fmt::Debug for Event {
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 let debug_verbose_not = |not: &RawNotification, f: &mut fmt::Formatter| {
123 f.debug_struct("RawNotification")
124 .field("method", &not.method)
125 .finish()
126 };
127
128 match self {
129 Event::Msg(RawMessage::Notification(not)) => {
130 if not.is::<req::DidOpenTextDocument>() || not.is::<req::DidChangeTextDocument>() {
131 return debug_verbose_not(not, f);
132 }
133 }
134 Event::Task(Task::Notify(not)) => {
135 if not.is::<req::PublishDecorations>() || not.is::<req::PublishDiagnostics>() {
136 return debug_verbose_not(not, f);
137 }
138 }
139 Event::Task(Task::Respond(resp)) => {
140 return f
141 .debug_struct("RawResponse")
142 .field("id", &resp.id)
143 .field("error", &resp.error)
144 .finish();
145 }
146 _ => (),
147 }
148 match self {
149 Event::Msg(it) => fmt::Debug::fmt(it, f),
150 Event::Task(it) => fmt::Debug::fmt(it, f),
151 Event::Vfs(it) => fmt::Debug::fmt(it, f),
152 Event::Lib(it) => fmt::Debug::fmt(it, f),
153 }
154 }
155}
156
112fn main_loop_inner( 157fn main_loop_inner(
113 internal_mode: bool, 158 internal_mode: bool,
114 supports_decorations: bool, 159 supports_decorations: bool,
@@ -123,13 +168,6 @@ fn main_loop_inner(
123) -> Result<()> { 168) -> Result<()> {
124 let (libdata_sender, libdata_receiver) = unbounded(); 169 let (libdata_sender, libdata_receiver) = unbounded();
125 loop { 170 loop {
126 #[derive(Debug)]
127 enum Event {
128 Msg(RawMessage),
129 Task(Task),
130 Vfs(VfsTask),
131 Lib(LibraryData),
132 }
133 log::trace!("selecting"); 171 log::trace!("selecting");
134 let event = select! { 172 let event = select! {
135 recv(msg_receiver, msg) => match msg { 173 recv(msg_receiver, msg) => match msg {
@@ -143,7 +181,8 @@ fn main_loop_inner(
143 } 181 }
144 recv(libdata_receiver, data) => Event::Lib(data.unwrap()) 182 recv(libdata_receiver, data) => Event::Lib(data.unwrap())
145 }; 183 };
146 log::info!("{:?}", event); 184 log::info!("loop_turn = {:?}", event);
185 let start = std::time::Instant::now();
147 let mut state_changed = false; 186 let mut state_changed = false;
148 match event { 187 match event {
149 Event::Task(task) => on_task(task, msg_sender, pending_requests), 188 Event::Task(task) => on_task(task, msg_sender, pending_requests),
@@ -206,6 +245,7 @@ fn main_loop_inner(
206 subs.subscriptions(), 245 subs.subscriptions(),
207 ) 246 )
208 } 247 }
248 log::info!("loop_turn = {:?}", start.elapsed());
209 } 249 }
210} 250}
211 251
@@ -387,7 +427,7 @@ impl<'a> PoolDispatcher<'a> {
387 RawResponse::err( 427 RawResponse::err(
388 id, 428 id,
389 ErrorCode::ContentModified as i32, 429 ErrorCode::ContentModified as i32,
390 e.to_string(), 430 format!("content modified: {}", e),
391 ) 431 )
392 } else { 432 } else {
393 RawResponse::err( 433 RawResponse::err(
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 572ae7fb5..252d1ba3e 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -2,9 +2,9 @@ use std::collections::HashMap;
2 2
3use gen_lsp_server::ErrorCode; 3use gen_lsp_server::ErrorCode;
4use languageserver_types::{ 4use languageserver_types::{
5 CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, 5 CodeActionResponse, Command, Diagnostic,
6 DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, 6 DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind,
7 FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, MarkedString, Position, 7 FoldingRangeParams, Location, MarkupContent, MarkupKind, MarkedString, Position,
8 PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, 8 PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit,
9 WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover, HoverContents, 9 WorkspaceEdit, ParameterInformation, ParameterLabel, SignatureInformation, Hover, HoverContents,
10}; 10};
@@ -107,9 +107,16 @@ pub fn handle_on_type_formatting(
107 }; 107 };
108 let edits = match world.analysis().on_eq_typed(position) { 108 let edits = match world.analysis().on_eq_typed(position) {
109 None => return Ok(None), 109 None => return Ok(None),
110 Some(mut action) => action.source_file_edits.pop().unwrap().edits, 110 Some(mut action) => action
111 .source_file_edits
112 .pop()
113 .unwrap()
114 .edit
115 .as_atoms()
116 .iter()
117 .map_conv_with(&line_index)
118 .collect(),
111 }; 119 };
112 let edits = edits.into_iter().map_conv_with(&line_index).collect();
113 Ok(Some(edits)) 120 Ok(Some(edits))
114} 121}
115 122
@@ -412,22 +419,7 @@ pub fn handle_completion(
412 None => return Ok(None), 419 None => return Ok(None),
413 Some(items) => items, 420 Some(items) => items,
414 }; 421 };
415 let items = items 422 let items = items.into_iter().map(|item| item.conv()).collect();
416 .into_iter()
417 .map(|item| {
418 let mut res = CompletionItem {
419 label: item.label,
420 filter_text: item.lookup,
421 ..Default::default()
422 };
423 if let Some(snip) = item.snippet {
424 res.insert_text = Some(snip);
425 res.insert_text_format = Some(InsertTextFormat::Snippet);
426 res.kind = Some(CompletionItemKind::Keyword);
427 };
428 res
429 })
430 .collect();
431 423
432 Ok(Some(req::CompletionResponse::Array(items))) 424 Ok(Some(req::CompletionResponse::Array(items)))
433} 425}
@@ -446,8 +438,9 @@ pub fn handle_folding_range(
446 .into_iter() 438 .into_iter()
447 .map(|fold| { 439 .map(|fold| {
448 let kind = match fold.kind { 440 let kind = match fold.kind {
449 FoldKind::Comment => FoldingRangeKind::Comment, 441 FoldKind::Comment => Some(FoldingRangeKind::Comment),
450 FoldKind::Imports => FoldingRangeKind::Imports, 442 FoldKind::Imports => Some(FoldingRangeKind::Imports),
443 FoldKind::Block => None,
451 }; 444 };
452 let range = fold.range.conv_with(&line_index); 445 let range = fold.range.conv_with(&line_index);
453 FoldingRange { 446 FoldingRange {
@@ -455,7 +448,7 @@ pub fn handle_folding_range(
455 start_character: Some(range.start.character), 448 start_character: Some(range.start.character),
456 end_line: range.end.line, 449 end_line: range.end.line,
457 end_character: Some(range.start.character), 450 end_character: Some(range.start.character),
458 kind: Some(kind), 451 kind,
459 } 452 }
460 }) 453 })
461 .collect(), 454 .collect(),
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs
index 999792ecb..747ab8a8c 100644
--- a/crates/ra_lsp_server/src/req.rs
+++ b/crates/ra_lsp_server/src/req.rs
@@ -1,4 +1,4 @@
1use serde_derive::{Serialize, Deserialize}; 1use serde::{Serialize, Deserialize};
2use languageserver_types::{Location, Position, Range, TextDocumentIdentifier, Url}; 2use languageserver_types::{Location, Position, Range, TextDocumentIdentifier, Url};
3use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
4use url_serde; 4use url_serde;
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
index 785877c4b..c183c25af 100644
--- a/crates/ra_lsp_server/src/server_world.rs
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -8,7 +8,7 @@ use ra_analysis::{
8 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, 8 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData,
9 SourceRootId 9 SourceRootId
10}; 10};
11use ra_vfs::{Vfs, VfsChange, VfsFile}; 11use ra_vfs::{Vfs, VfsChange, VfsFile, VfsRoot};
12use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
13use relative_path::RelativePathBuf; 13use relative_path::RelativePathBuf;
14use parking_lot::RwLock; 14use parking_lot::RwLock;
@@ -107,7 +107,6 @@ impl ServerWorldState {
107 let mut libs = Vec::new(); 107 let mut libs = Vec::new();
108 let mut change = AnalysisChange::new(); 108 let mut change = AnalysisChange::new();
109 for c in changes { 109 for c in changes {
110 log::info!("vfs change {:?}", c);
111 match c { 110 match c {
112 VfsChange::AddRoot { root, files } => { 111 VfsChange::AddRoot { root, files } => {
113 let root_path = self.vfs.read().root2path(root); 112 let root_path = self.vfs.read().root2path(root);
@@ -183,4 +182,12 @@ impl ServerWorld {
183 .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?; 182 .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
184 Ok(url) 183 Ok(url)
185 } 184 }
185
186 pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> {
187 let base = self.vfs.read().root2path(VfsRoot(root.0));
188 let path = path.to_path(base);
189 let url = Url::from_file_path(&path)
190 .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
191 Ok(url)
192 }
186} 193}
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 91c67119f..f12479fb4 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -284,7 +284,7 @@ impl<'a> IfExpr<'a> {
284 } 284 }
285} 285}
286 286
287#[derive(Debug, Clone, Copy)] 287#[derive(Debug, Clone, Copy, PartialEq, Eq)]
288pub enum PathSegmentKind<'a> { 288pub enum PathSegmentKind<'a> {
289 Name(NameRef<'a>), 289 Name(NameRef<'a>),
290 SelfKw, 290 SelfKw,
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index 4f8c46ab3..da78d85a2 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -42,9 +42,15 @@ pub(crate) fn block(p: &mut Parser) {
42 } 42 }
43 let m = p.start(); 43 let m = p.start();
44 p.bump(); 44 p.bump();
45
45 while !p.at(EOF) && !p.at(R_CURLY) { 46 while !p.at(EOF) && !p.at(R_CURLY) {
46 match p.current() { 47 match p.current() {
47 LET_KW => let_stmt(p), 48 LET_KW => let_stmt(p),
49 // test nocontentexpr
50 // fn foo(){
51 // ;;;some_expr();;;;{;;;};;;;Ok(())
52 // }
53 SEMI => p.bump(),
48 _ => { 54 _ => {
49 // test block_items 55 // test block_items
50 // fn a() { fn b() {} } 56 // fn a() { fn b() {} }
@@ -206,7 +212,7 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> BlockLike {
206} 212}
207 213
208const LHS_FIRST: TokenSet = token_set_union![ 214const LHS_FIRST: TokenSet = token_set_union![
209 token_set![AMP, STAR, EXCL, DOTDOT, MINUS], 215 token_set![AMP, STAR, EXCL, DOTDOT, DOTDOTEQ, MINUS],
210 atom::ATOM_EXPR_FIRST, 216 atom::ATOM_EXPR_FIRST,
211]; 217];
212 218
@@ -237,7 +243,7 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
237 } 243 }
238 // test full_range_expr 244 // test full_range_expr
239 // fn foo() { xs[..]; } 245 // fn foo() { xs[..]; }
240 DOTDOT => { 246 DOTDOT | DOTDOTEQ => {
241 m = p.start(); 247 m = p.start();
242 p.bump(); 248 p.bump();
243 if p.at_ts(EXPR_FIRST) { 249 if p.at_ts(EXPR_FIRST) {
@@ -287,7 +293,7 @@ fn postfix_expr(
287 DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs), 293 DOT if p.nth(1) == INT_NUMBER => field_expr(p, lhs),
288 // test postfix_range 294 // test postfix_range
289 // fn foo() { let x = 1..; } 295 // fn foo() { let x = 1..; }
290 DOTDOT if !EXPR_FIRST.contains(p.nth(1)) => { 296 DOTDOT | DOTDOTEQ if !EXPR_FIRST.contains(p.nth(1)) => {
291 let m = lhs.precede(p); 297 let m = lhs.precede(p);
292 p.bump(); 298 p.bump();
293 m.complete(p, RANGE_EXPR) 299 m.complete(p, RANGE_EXPR)
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
index cd7d62aff..31b09ac5b 100644
--- a/crates/ra_syntax/src/grammar/expressions/atom.rs
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -35,11 +35,12 @@ pub(crate) fn literal(p: &mut Parser) -> Option<CompletedMarker> {
35 Some(m.complete(p, LITERAL)) 35 Some(m.complete(p, LITERAL))
36} 36}
37 37
38// E.g. for after the break in `if break {}`, this should not match
38pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![ 39pub(super) const ATOM_EXPR_FIRST: TokenSet = token_set_union![
39 LITERAL_FIRST, 40 LITERAL_FIRST,
40 token_set![ 41 token_set![
41 L_CURLY,
42 L_PAREN, 42 L_PAREN,
43 L_CURLY,
43 L_BRACK, 44 L_BRACK,
44 PIPE, 45 PIPE,
45 MOVE_KW, 46 MOVE_KW,
@@ -88,7 +89,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
88 WHILE_KW => while_expr(p, Some(m)), 89 WHILE_KW => while_expr(p, Some(m)),
89 L_CURLY => block_expr(p, Some(m)), 90 L_CURLY => block_expr(p, Some(m)),
90 _ => { 91 _ => {
91 // test misplaced_label_err 92 // test_err misplaced_label_err
92 // fn main() { 93 // fn main() {
93 // 'loop: impl 94 // 'loop: impl
94 // } 95 // }
@@ -108,7 +109,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
108 L_CURLY => block_expr(p, None), 109 L_CURLY => block_expr(p, None),
109 RETURN_KW => return_expr(p), 110 RETURN_KW => return_expr(p),
110 CONTINUE_KW => continue_expr(p), 111 CONTINUE_KW => continue_expr(p),
111 BREAK_KW => break_expr(p), 112 BREAK_KW => break_expr(p, r),
112 _ => { 113 _ => {
113 p.err_recover("expected expression", EXPR_RECOVERY_SET); 114 p.err_recover("expected expression", EXPR_RECOVERY_SET);
114 return None; 115 return None;
@@ -353,7 +354,7 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
353// fn foo() { 354// fn foo() {
354// match () { 355// match () {
355// _ => (), 356// _ => (),
356// _ if Test>{field: 0} => (), 357// _ if Test > Test{field: 0} => (),
357// X | Y if Z => (), 358// X | Y if Z => (),
358// | X | Y if Z => (), 359// | X | Y if Z => (),
359// | X => (), 360// | X => (),
@@ -427,12 +428,19 @@ fn continue_expr(p: &mut Parser) -> CompletedMarker {
427// break 'l 92; 428// break 'l 92;
428// } 429// }
429// } 430// }
430fn break_expr(p: &mut Parser) -> CompletedMarker { 431fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
431 assert!(p.at(BREAK_KW)); 432 assert!(p.at(BREAK_KW));
432 let m = p.start(); 433 let m = p.start();
433 p.bump(); 434 p.bump();
434 p.eat(LIFETIME); 435 p.eat(LIFETIME);
435 if p.at_ts(EXPR_FIRST) { 436 // test break_ambiguity
437 // fn foo(){
438 // if break {}
439 // while break {}
440 // for i in break {}
441 // match break {}
442 // }
443 if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(L_CURLY)) {
436 expr(p); 444 expr(p);
437 } 445 }
438 m.complete(p, BREAK_EXPR) 446 m.complete(p, BREAK_EXPR)
diff --git a/crates/ra_syntax/src/grammar/items.rs b/crates/ra_syntax/src/grammar/items.rs
index 4473c2fab..aa5fe0777 100644
--- a/crates/ra_syntax/src/grammar/items.rs
+++ b/crates/ra_syntax/src/grammar/items.rs
@@ -89,7 +89,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
89 // modifiers 89 // modifiers
90 has_mods |= p.eat(CONST_KW); 90 has_mods |= p.eat(CONST_KW);
91 91
92 // test unsafe_block_in_mod 92 // test_err unsafe_block_in_mod
93 // fn foo(){} unsafe { } fn bar(){} 93 // fn foo(){} unsafe { } fn bar(){}
94 if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY { 94 if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY {
95 p.eat(UNSAFE_KW); 95 p.eat(UNSAFE_KW);
@@ -202,7 +202,7 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
202 } 202 }
203 STRUCT_DEF 203 STRUCT_DEF
204 } 204 }
205 IDENT if p.at_contextual_kw("union") => { 205 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
206 // test union_items 206 // test union_items
207 // union Foo {} 207 // union Foo {}
208 // union Foo { 208 // union Foo {
diff --git a/crates/ra_syntax/src/grammar/items/traits.rs b/crates/ra_syntax/src/grammar/items/traits.rs
index 31258c253..d4da8b2f7 100644
--- a/crates/ra_syntax/src/grammar/items/traits.rs
+++ b/crates/ra_syntax/src/grammar/items/traits.rs
@@ -116,7 +116,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool {
116 && (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ) 116 && (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ)
117} 117}
118 118
119// test impl_type 119// test_err impl_type
120// impl Type {} 120// impl Type {}
121// impl Trait1 for T {} 121// impl Trait1 for T {}
122// impl impl NotType {} 122// impl impl NotType {}
diff --git a/crates/ra_syntax/src/grammar/items/use_item.rs b/crates/ra_syntax/src/grammar/items/use_item.rs
index b3c78f351..5111d37eb 100644
--- a/crates/ra_syntax/src/grammar/items/use_item.rs
+++ b/crates/ra_syntax/src/grammar/items/use_item.rs
@@ -74,7 +74,7 @@ fn use_tree(p: &mut Parser) {
74 // other::path as some_other_name, 74 // other::path as some_other_name,
75 // different::path as different_name, 75 // different::path as different_name,
76 // yet::another::path, 76 // yet::another::path,
77 // running::out::of::synonyms::for::different::* 77 // running::out::of::synonyms::for_::different::*
78 // }; 78 // };
79 opt_alias(p); 79 opt_alias(p);
80 } 80 }
diff --git a/crates/ra_syntax/src/grammar/type_args.rs b/crates/ra_syntax/src/grammar/type_args.rs
index 29ff6e534..f889419c5 100644
--- a/crates/ra_syntax/src/grammar/type_args.rs
+++ b/crates/ra_syntax/src/grammar/type_args.rs
@@ -26,7 +26,7 @@ pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) {
26} 26}
27 27
28// test type_arg 28// test type_arg
29// type A = B<'static, i32, Item=u64> 29// type A = B<'static, i32, Item=u64>;
30fn type_arg(p: &mut Parser) { 30fn type_arg(p: &mut Parser) {
31 let m = p.start(); 31 let m = p.start();
32 match p.current() { 32 match p.current() {
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs
index f4c98675c..7db25beba 100644
--- a/crates/ra_syntax/src/grammar/type_params.rs
+++ b/crates/ra_syntax/src/grammar/type_params.rs
@@ -96,6 +96,7 @@ pub(super) fn bounds_without_colon(p: &mut Parser) {
96// 'a: 'b + 'c, 96// 'a: 'b + 'c,
97// T: Clone + Copy + 'static, 97// T: Clone + Copy + 'static,
98// Iterator::Item: 'a, 98// Iterator::Item: 'a,
99// <T as Iterator>::Item: 'a
99// {} 100// {}
100pub(super) fn opt_where_clause(p: &mut Parser) { 101pub(super) fn opt_where_clause(p: &mut Parser) {
101 if !p.at(WHERE_KW) { 102 if !p.at(WHERE_KW) {
@@ -104,11 +105,15 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
104 let m = p.start(); 105 let m = p.start();
105 p.bump(); 106 p.bump();
106 loop { 107 loop {
107 if !(paths::is_path_start(p) || p.current() == LIFETIME || p.current() == FOR_KW) { 108 if !(paths::is_path_start(p)
109 || p.current() == LIFETIME
110 || p.current() == FOR_KW
111 || p.current() == L_ANGLE)
112 {
108 break; 113 break;
109 } 114 }
110 where_predicate(p); 115 where_predicate(p);
111 if p.current() != L_CURLY && p.current() != SEMI { 116 if p.current() != L_CURLY && p.current() != SEMI && p.current() != EQ {
112 p.expect(COMMA); 117 p.expect(COMMA);
113 } 118 }
114 } 119 }
diff --git a/crates/ra_syntax/src/grammar/types.rs b/crates/ra_syntax/src/grammar/types.rs
index 811d399d4..a933b986b 100644
--- a/crates/ra_syntax/src/grammar/types.rs
+++ b/crates/ra_syntax/src/grammar/types.rs
@@ -97,7 +97,7 @@ fn pointer_type(p: &mut Parser) {
97 // type C = *mut (); 97 // type C = *mut ();
98 MUT_KW | CONST_KW => p.bump(), 98 MUT_KW | CONST_KW => p.bump(),
99 _ => { 99 _ => {
100 // test pointer_type_no_mutability 100 // test_err pointer_type_no_mutability
101 // type T = *(); 101 // type T = *();
102 p.error( 102 p.error(
103 "expected mut or const in raw pointer type \ 103 "expected mut or const in raw pointer type \
@@ -132,7 +132,7 @@ fn array_or_slice_type(p: &mut Parser) {
132 p.expect(R_BRACK); 132 p.expect(R_BRACK);
133 ARRAY_TYPE 133 ARRAY_TYPE
134 } 134 }
135 // test array_type_missing_semi 135 // test_err array_type_missing_semi
136 // type T = [() 92]; 136 // type T = [() 92];
137 _ => { 137 _ => {
138 p.error("expected `;` or `]`"); 138 p.error("expected `;` or `]`");
@@ -175,7 +175,7 @@ fn fn_pointer_type(p: &mut Parser) {
175 if p.at(EXTERN_KW) { 175 if p.at(EXTERN_KW) {
176 abi(p); 176 abi(p);
177 } 177 }
178 // test fn_pointer_type_missing_fn 178 // test_err fn_pointer_type_missing_fn
179 // type F = unsafe (); 179 // type F = unsafe ();
180 if !p.eat(FN_KW) { 180 if !p.eat(FN_KW) {
181 m.abandon(p); 181 m.abandon(p);
diff --git a/crates/ra_syntax/src/lexer.rs b/crates/ra_syntax/src/lexer.rs
index f388da273..c6acd095e 100644
--- a/crates/ra_syntax/src/lexer.rs
+++ b/crates/ra_syntax/src/lexer.rs
@@ -160,7 +160,7 @@ fn next_token_inner(c: char, ptr: &mut Ptr) -> SyntaxKind {
160 // if we find one, then this is an invalid character literal 160 // if we find one, then this is an invalid character literal
161 if ptr.at('\'') { 161 if ptr.at('\'') {
162 ptr.bump(); 162 ptr.bump();
163 return CHAR; // TODO: error reporting 163 return CHAR;
164 } 164 }
165 LIFETIME 165 LIFETIME
166 } else { 166 } else {
diff --git a/crates/ra_syntax/src/string_lexing/byte.rs b/crates/ra_syntax/src/string_lexing/byte.rs
index 24424349c..b3228d6ca 100644
--- a/crates/ra_syntax/src/string_lexing/byte.rs
+++ b/crates/ra_syntax/src/string_lexing/byte.rs
@@ -40,7 +40,7 @@ impl<'a> Iterator for ByteComponentIterator<'a> {
40 40
41 assert!( 41 assert!(
42 self.parser.peek() == None, 42 self.parser.peek() == None,
43 "byte literal should leave no unparsed input: src = {}, pos = {}, length = {}", 43 "byte literal should leave no unparsed input: src = {:?}, pos = {}, length = {}",
44 self.parser.src, 44 self.parser.src,
45 self.parser.pos, 45 self.parser.pos,
46 self.parser.src.len() 46 self.parser.src.len()
diff --git a/crates/ra_syntax/src/string_lexing/byte_string.rs b/crates/ra_syntax/src/string_lexing/byte_string.rs
index 5b6dda760..a6056159b 100644
--- a/crates/ra_syntax/src/string_lexing/byte_string.rs
+++ b/crates/ra_syntax/src/string_lexing/byte_string.rs
@@ -40,7 +40,7 @@ impl<'a> Iterator for ByteStringComponentIterator<'a> {
40 40
41 assert!( 41 assert!(
42 self.parser.peek() == None, 42 self.parser.peek() == None,
43 "byte string literal should leave no unparsed input: src = {}, pos = {}, length = {}", 43 "byte string literal should leave no unparsed input: src = {:?}, pos = {}, length = {}",
44 self.parser.src, 44 self.parser.src,
45 self.parser.pos, 45 self.parser.pos,
46 self.parser.src.len() 46 self.parser.src.len()
diff --git a/crates/ra_syntax/src/string_lexing/char.rs b/crates/ra_syntax/src/string_lexing/char.rs
index 885c03b14..e01813176 100644
--- a/crates/ra_syntax/src/string_lexing/char.rs
+++ b/crates/ra_syntax/src/string_lexing/char.rs
@@ -35,7 +35,7 @@ impl<'a> Iterator for CharComponentIterator<'a> {
35 35
36 assert!( 36 assert!(
37 self.parser.peek() == None, 37 self.parser.peek() == None,
38 "char literal should leave no unparsed input: src = {}, pos = {}, length = {}", 38 "char literal should leave no unparsed input: src = {:?}, pos = {}, length = {}",
39 self.parser.src, 39 self.parser.src,
40 self.parser.pos, 40 self.parser.pos,
41 self.parser.src.len() 41 self.parser.src.len()
diff --git a/crates/ra_syntax/src/string_lexing/string.rs b/crates/ra_syntax/src/string_lexing/string.rs
index 1b23029c6..d8351e9af 100644
--- a/crates/ra_syntax/src/string_lexing/string.rs
+++ b/crates/ra_syntax/src/string_lexing/string.rs
@@ -35,7 +35,7 @@ impl<'a> Iterator for StringComponentIterator<'a> {
35 35
36 assert!( 36 assert!(
37 self.parser.peek() == None, 37 self.parser.peek() == None,
38 "string literal should leave no unparsed input: src = {}, pos = {}, length = {}", 38 "string literal should leave no unparsed input: src = {:?}, pos = {}, length = {}",
39 self.parser.src, 39 self.parser.src,
40 self.parser.pos, 40 self.parser.pos,
41 self.parser.src.len() 41 self.parser.src.len()
diff --git a/crates/ra_syntax/tests/data/parser/ok/0034_macro_2.0.rs b/crates/ra_syntax/tests/data/parser/err/0028_macro_2.0.rs
index 2a70ee83a..781047ba1 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0034_macro_2.0.rs
+++ b/crates/ra_syntax/tests/data/parser/err/0028_macro_2.0.rs
@@ -13,4 +13,3 @@ fn test_use_tree_merge() {
13 ); 13 );
14 } 14 }
15} 15}
16
diff --git a/crates/ra_syntax/tests/data/parser/ok/0034_macro_2.0.txt b/crates/ra_syntax/tests/data/parser/err/0028_macro_2.0.txt
index caff8df76..12919fab7 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0034_macro_2.0.txt
+++ b/crates/ra_syntax/tests/data/parser/err/0028_macro_2.0.txt
@@ -1,4 +1,4 @@
1SOURCE_FILE@[0; 350) 1SOURCE_FILE@[0; 349)
2 MACRO_CALL@[0; 41) 2 MACRO_CALL@[0; 41)
3 PATH@[0; 5) 3 PATH@[0; 5)
4 PATH_SEGMENT@[0; 5) 4 PATH_SEGMENT@[0; 5)
@@ -314,4 +314,4 @@ SOURCE_FILE@[0; 350)
314 R_CURLY@[345; 346) 314 R_CURLY@[345; 346)
315 WHITESPACE@[346; 347) 315 WHITESPACE@[346; 347)
316 R_CURLY@[347; 348) 316 R_CURLY@[347; 348)
317 WHITESPACE@[348; 350) 317 WHITESPACE@[348; 349)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0058_type_arg.rs b/crates/ra_syntax/tests/data/parser/inline/0058_type_arg.rs
deleted file mode 100644
index f0c8cc3a8..000000000
--- a/crates/ra_syntax/tests/data/parser/inline/0058_type_arg.rs
+++ /dev/null
@@ -1 +0,0 @@
1type A = B<'static, i32, Item=u64>
diff --git a/crates/ra_syntax/tests/data/parser/inline/0063_lambda_expr.txt b/crates/ra_syntax/tests/data/parser/inline/0063_lambda_expr.txt
deleted file mode 100644
index 8c1340c4a..000000000
--- a/crates/ra_syntax/tests/data/parser/inline/0063_lambda_expr.txt
+++ /dev/null
@@ -1,91 +0,0 @@
1SOURCE_FILE@[0; 74)
2 FN_DEF@[0; 74)
3 FN_KW@[0; 2)
4 NAME@[2; 6)
5 WHITESPACE@[2; 3)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 9)
8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9)
11 BLOCK_EXPR@[9; 74)
12 L_CURLY@[9; 10)
13 EXPR_STMT@[10; 26)
14 LAMBDA_EXPR@[10; 20)
15 PARAM_LIST@[10; 18)
16 WHITESPACE@[10; 15)
17 PIPE@[15; 16)
18 PIPE@[16; 17)
19 WHITESPACE@[17; 18)
20 TUPLE_EXPR@[18; 20)
21 L_PAREN@[18; 19)
22 R_PAREN@[19; 20)
23 SEMI@[20; 21)
24 WHITESPACE@[21; 26)
25 EXPR_STMT@[26; 48)
26 LAMBDA_EXPR@[26; 42)
27 PARAM_LIST@[26; 29)
28 PIPE@[26; 27)
29 PIPE@[27; 28)
30 WHITESPACE@[28; 29)
31 THIN_ARROW@[29; 31)
32 PATH_TYPE@[31; 36)
33 PATH@[31; 36)
34 PATH_SEGMENT@[31; 36)
35 NAME_REF@[31; 36)
36 WHITESPACE@[31; 32)
37 IDENT@[32; 35) "i32"
38 WHITESPACE@[35; 36)
39 BLOCK_EXPR@[36; 42)
40 L_CURLY@[36; 37)
41 LITERAL@[37; 41)
42 WHITESPACE@[37; 38)
43 INT_NUMBER@[38; 40) "92"
44 WHITESPACE@[40; 41)
45 R_CURLY@[41; 42)
46 SEMI@[42; 43)
47 WHITESPACE@[43; 48)
48 EXPR_STMT@[48; 59)
49 LAMBDA_EXPR@[48; 53)
50 PARAM_LIST@[48; 52)
51 PIPE@[48; 49)
52 PARAM@[49; 50)
53 BIND_PAT@[49; 50)
54 NAME@[49; 50)
55 IDENT@[49; 50) "x"
56 PIPE@[50; 51)
57 WHITESPACE@[51; 52)
58 PATH_EXPR@[52; 53)
59 PATH@[52; 53)
60 PATH_SEGMENT@[52; 53)
61 NAME_REF@[52; 53)
62 IDENT@[52; 53) "x"
63 SEMI@[53; 54)
64 WHITESPACE@[54; 59)
65 EXPR_STMT@[59; 72)
66 LAMBDA_EXPR@[59; 70)
67 PARAM_LIST@[59; 69)
68 PIPE@[59; 60)
69 PARAM@[60; 66)
70 BIND_PAT@[60; 61)
71 NAME@[60; 61)
72 IDENT@[60; 61) "x"
73 COLON@[61; 62)
74 PATH_TYPE@[62; 66)
75 PATH@[62; 66)
76 PATH_SEGMENT@[62; 66)
77 NAME_REF@[62; 66)
78 WHITESPACE@[62; 63)
79 IDENT@[63; 66) "i32"
80 COMMA@[66; 67)
81 PIPE@[67; 68)
82 WHITESPACE@[68; 69)
83 PATH_EXPR@[69; 70)
84 PATH@[69; 70)
85 PATH_SEGMENT@[69; 70)
86 NAME_REF@[69; 70)
87 IDENT@[69; 70) "x"
88 SEMI@[70; 71)
89 WHITESPACE@[71; 72)
90 R_CURLY@[72; 73)
91 WHITESPACE@[73; 74)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt b/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt
deleted file mode 100644
index e5647765c..000000000
--- a/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt
+++ /dev/null
@@ -1,148 +0,0 @@
1SOURCE_FILE@[0; 161)
2 FN_DEF@[0; 160)
3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3)
5 NAME@[3; 6)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 8)
8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9)
11 BLOCK@[9; 160)
12 L_CURLY@[9; 10)
13 WHITESPACE@[10; 15)
14 EXPR_STMT@[15; 158)
15 MATCH_EXPR@[15; 157)
16 MATCH_KW@[15; 20)
17 WHITESPACE@[20; 21)
18 TUPLE_EXPR@[21; 23)
19 L_PAREN@[21; 22)
20 R_PAREN@[22; 23)
21 WHITESPACE@[23; 24)
22 MATCH_ARM_LIST@[24; 157)
23 L_CURLY@[24; 25)
24 WHITESPACE@[25; 34)
25 MATCH_ARM@[34; 41)
26 PLACEHOLDER_PAT@[34; 35)
27 UNDERSCORE@[34; 35)
28 WHITESPACE@[35; 36)
29 FAT_ARROW@[36; 38)
30 WHITESPACE@[38; 39)
31 TUPLE_EXPR@[39; 41)
32 L_PAREN@[39; 40)
33 R_PAREN@[40; 41)
34 COMMA@[41; 42)
35 WHITESPACE@[42; 51)
36 MATCH_ARM@[51; 77)
37 PLACEHOLDER_PAT@[51; 52)
38 UNDERSCORE@[51; 52)
39 WHITESPACE@[52; 53)
40 IF_KW@[53; 55)
41 WHITESPACE@[55; 56)
42 BIN_EXPR@[56; 71)
43 PATH_EXPR@[56; 60)
44 PATH@[56; 60)
45 PATH_SEGMENT@[56; 60)
46 NAME_REF@[56; 60)
47 IDENT@[56; 60) "Test"
48 R_ANGLE@[60; 61)
49 BLOCK_EXPR@[61; 71)
50 BLOCK@[61; 71)
51 L_CURLY@[61; 62)
52 EXPR_STMT@[62; 67)
53 PATH_EXPR@[62; 67)
54 PATH@[62; 67)
55 PATH_SEGMENT@[62; 67)
56 NAME_REF@[62; 67)
57 IDENT@[62; 67) "field"
58 err: `expected SEMI`
59 err: `expected expression`
60 EXPR_STMT@[67; 68)
61 ERROR@[67; 68)
62 COLON@[67; 68)
63 err: `expected SEMI`
64 WHITESPACE@[68; 69)
65 LITERAL@[69; 70)
66 INT_NUMBER@[69; 70) "0"
67 R_CURLY@[70; 71)
68 WHITESPACE@[71; 72)
69 FAT_ARROW@[72; 74)
70 WHITESPACE@[74; 75)
71 TUPLE_EXPR@[75; 77)
72 L_PAREN@[75; 76)
73 R_PAREN@[76; 77)
74 COMMA@[77; 78)
75 WHITESPACE@[78; 87)
76 MATCH_ARM@[87; 103)
77 BIND_PAT@[87; 88)
78 NAME@[87; 88)
79 IDENT@[87; 88) "X"
80 WHITESPACE@[88; 89)
81 PIPE@[89; 90)
82 WHITESPACE@[90; 91)
83 BIND_PAT@[91; 92)
84 NAME@[91; 92)
85 IDENT@[91; 92) "Y"
86 WHITESPACE@[92; 93)
87 IF_KW@[93; 95)
88 WHITESPACE@[95; 96)
89 PATH_EXPR@[96; 97)
90 PATH@[96; 97)
91 PATH_SEGMENT@[96; 97)
92 NAME_REF@[96; 97)
93 IDENT@[96; 97) "Z"
94 WHITESPACE@[97; 98)
95 FAT_ARROW@[98; 100)
96 WHITESPACE@[100; 101)
97 TUPLE_EXPR@[101; 103)
98 L_PAREN@[101; 102)
99 R_PAREN@[102; 103)
100 COMMA@[103; 104)
101 WHITESPACE@[104; 113)
102 MATCH_ARM@[113; 131)
103 PIPE@[113; 114)
104 WHITESPACE@[114; 115)
105 BIND_PAT@[115; 116)
106 NAME@[115; 116)
107 IDENT@[115; 116) "X"
108 WHITESPACE@[116; 117)
109 PIPE@[117; 118)
110 WHITESPACE@[118; 119)
111 BIND_PAT@[119; 120)
112 NAME@[119; 120)
113 IDENT@[119; 120) "Y"
114 WHITESPACE@[120; 121)
115 IF_KW@[121; 123)
116 WHITESPACE@[123; 124)
117 PATH_EXPR@[124; 125)
118 PATH@[124; 125)
119 PATH_SEGMENT@[124; 125)
120 NAME_REF@[124; 125)
121 IDENT@[124; 125) "Z"
122 WHITESPACE@[125; 126)
123 FAT_ARROW@[126; 128)
124 WHITESPACE@[128; 129)
125 TUPLE_EXPR@[129; 131)
126 L_PAREN@[129; 130)
127 R_PAREN@[130; 131)
128 COMMA@[131; 132)
129 WHITESPACE@[132; 141)
130 MATCH_ARM@[141; 150)
131 PIPE@[141; 142)
132 WHITESPACE@[142; 143)
133 BIND_PAT@[143; 144)
134 NAME@[143; 144)
135 IDENT@[143; 144) "X"
136 WHITESPACE@[144; 145)
137 FAT_ARROW@[145; 147)
138 WHITESPACE@[147; 148)
139 TUPLE_EXPR@[148; 150)
140 L_PAREN@[148; 149)
141 R_PAREN@[149; 150)
142 COMMA@[150; 151)
143 WHITESPACE@[151; 156)
144 R_CURLY@[156; 157)
145 SEMI@[157; 158)
146 WHITESPACE@[158; 159)
147 R_CURLY@[159; 160)
148 WHITESPACE@[160; 161)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0023_array_type_missing_semi.rs b/crates/ra_syntax/tests/data/parser/inline/err/0001_array_type_missing_semi.rs
index a94851443..a94851443 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0023_array_type_missing_semi.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0001_array_type_missing_semi.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0023_array_type_missing_semi.txt b/crates/ra_syntax/tests/data/parser/inline/err/0001_array_type_missing_semi.txt
index 036363587..036363587 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0023_array_type_missing_semi.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0001_array_type_missing_semi.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0108_misplaced_label_err.rs b/crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.rs
index a2164c510..a2164c510 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0108_misplaced_label_err.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0108_misplaced_label_err.txt b/crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt
index 75533ecc1..75533ecc1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0108_misplaced_label_err.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0002_misplaced_label_err.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0021_pointer_type_no_mutability.rs b/crates/ra_syntax/tests/data/parser/inline/err/0003_pointer_type_no_mutability.rs
index fae705131..fae705131 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0021_pointer_type_no_mutability.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0003_pointer_type_no_mutability.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0021_pointer_type_no_mutability.txt b/crates/ra_syntax/tests/data/parser/inline/err/0003_pointer_type_no_mutability.txt
index 189aa563e..189aa563e 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0021_pointer_type_no_mutability.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0003_pointer_type_no_mutability.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0111_impl_type.rs b/crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.rs
index b8c7b65e3..b8c7b65e3 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0111_impl_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0111_impl_type.txt b/crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt
index 7279d5cae..7279d5cae 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0111_impl_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0004_impl_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.rs b/crates/ra_syntax/tests/data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs
index f014914ff..f014914ff 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0005_fn_pointer_type_missing_fn.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.txt b/crates/ra_syntax/tests/data/parser/inline/err/0005_fn_pointer_type_missing_fn.txt
index f97db4bff..f97db4bff 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0005_fn_pointer_type_missing_fn.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0013_unsafe_block_in_mod.rs b/crates/ra_syntax/tests/data/parser/inline/err/0006_unsafe_block_in_mod.rs
index 26141e904..26141e904 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0013_unsafe_block_in_mod.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0006_unsafe_block_in_mod.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0013_unsafe_block_in_mod.txt b/crates/ra_syntax/tests/data/parser/inline/err/0006_unsafe_block_in_mod.txt
index d2da2bad7..d2da2bad7 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0013_unsafe_block_in_mod.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/err/0006_unsafe_block_in_mod.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0049_trait_item_list.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.rs
index a5ec3239f..a5ec3239f 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0049_trait_item_list.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0049_trait_item_list.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt
index 998ac3da9..998ac3da9 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0049_trait_item_list.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0001_trait_item_list.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0118_use_tree_list.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0002_use_tree_list.rs
index 06c387cee..06c387cee 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0118_use_tree_list.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0002_use_tree_list.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0118_use_tree_list.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0002_use_tree_list.txt
index 89a0b9f2a..89a0b9f2a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0118_use_tree_list.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0002_use_tree_list.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.rs
index b448c6178..b448c6178 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt
index 921bdacf4..921bdacf4 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0096_value_parameters_no_patterns.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0004_value_parameters_no_patterns.rs
index d8c23c76a..d8c23c76a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0096_value_parameters_no_patterns.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0004_value_parameters_no_patterns.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0096_value_parameters_no_patterns.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0004_value_parameters_no_patterns.txt
index f2d7e866b..f2d7e866b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0096_value_parameters_no_patterns.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0004_value_parameters_no_patterns.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0060_function_type_params.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.rs
index 9df40ed39..9df40ed39 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0060_function_type_params.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0060_function_type_params.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.txt
index b20f13267..b20f13267 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0060_function_type_params.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0005_function_type_params.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0055_self_param.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.rs
index 80c0a43f5..80c0a43f5 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0055_self_param.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0055_self_param.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt
index 53027c852..53027c852 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0055_self_param.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0006_self_param.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0041_type_param_bounds.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.rs
index 919bde0ee..919bde0ee 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0041_type_param_bounds.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0041_type_param_bounds.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.txt
index 745cf8798..745cf8798 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0041_type_param_bounds.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0007_type_param_bounds.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0072_path_part.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0008_path_part.rs
index f6e32c7c1..f6e32c7c1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0072_path_part.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0008_path_part.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0072_path_part.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0008_path_part.txt
index 0020cfb4d..0020cfb4d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0072_path_part.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0008_path_part.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0084_loop_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0009_loop_expr.rs
index 9f078fa48..9f078fa48 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0084_loop_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0009_loop_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0084_loop_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0009_loop_expr.txt
index c3c64c322..c3c64c322 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0084_loop_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0009_loop_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0003_extern_block.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0010_extern_block.rs
index 26a9ccd1e..26a9ccd1e 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0003_extern_block.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0010_extern_block.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0003_extern_block.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0010_extern_block.txt
index 7e79c2280..7e79c2280 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0003_extern_block.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0010_extern_block.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0052_field_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0011_field_expr.rs
index 3e69538e5..3e69538e5 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0052_field_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0011_field_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0052_field_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0011_field_expr.txt
index 03fbf092b..03fbf092b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0052_field_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0011_field_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0016_type_item_where_clause.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.rs
index a602d07f0..a602d07f0 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0016_type_item_where_clause.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0016_type_item_where_clause.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.txt
index f38b2f79a..dbb705acf 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0016_type_item_where_clause.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0012_type_item_where_clause.txt
@@ -21,7 +21,6 @@ SOURCE_FILE@[0; 31)
21 PATH_SEGMENT@[20; 24) 21 PATH_SEGMENT@[20; 24)
22 NAME_REF@[20; 24) 22 NAME_REF@[20; 24)
23 IDENT@[20; 24) "Copy" 23 IDENT@[20; 24) "Copy"
24 err: `expected COMMA`
25 WHITESPACE@[24; 25) 24 WHITESPACE@[24; 25)
26 EQ@[25; 26) 25 EQ@[25; 26)
27 WHITESPACE@[26; 27) 26 WHITESPACE@[26; 27)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0022_pointer_type_mut.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0013_pointer_type_mut.rs
index 04b2bb9ba..04b2bb9ba 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0022_pointer_type_mut.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0013_pointer_type_mut.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0022_pointer_type_mut.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0013_pointer_type_mut.txt
index 149cd571d..149cd571d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0022_pointer_type_mut.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0013_pointer_type_mut.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0020_never_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0014_never_type.rs
index de399fcf4..de399fcf4 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0020_never_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0014_never_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0020_never_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0014_never_type.txt
index e0cae644d..e0cae644d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0020_never_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0014_never_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0105_continue_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0015_continue_expr.rs
index 474cc3f0e..474cc3f0e 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0105_continue_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0015_continue_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0105_continue_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0015_continue_expr.txt
index 39be5b2c8..39be5b2c8 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0105_continue_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0015_continue_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0007_unsafe_trait.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0016_unsafe_trait.rs
index 04e021550..04e021550 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0007_unsafe_trait.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0016_unsafe_trait.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0007_unsafe_trait.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0016_unsafe_trait.txt
index 3669c93a8..3669c93a8 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0007_unsafe_trait.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0016_unsafe_trait.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0024_array_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0017_array_type.rs
index 27eb22f22..27eb22f22 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0024_array_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0017_array_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0024_array_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0017_array_type.txt
index 2c2b615fc..2c2b615fc 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0024_array_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0017_array_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0104_arb_self_types.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.rs
index 6a170d5ac..6a170d5ac 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0104_arb_self_types.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0104_arb_self_types.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt
index b2f04ea7b..b2f04ea7b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0104_arb_self_types.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0018_arb_self_types.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0074_unary_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0019_unary_expr.rs
index f1c3f7118..f1c3f7118 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0074_unary_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0019_unary_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0074_unary_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0019_unary_expr.txt
index 72d7d8bfb..72d7d8bfb 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0074_unary_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0019_unary_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0116_use_star.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0020_use_star.rs
index 6f15769a8..6f15769a8 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0116_use_star.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0020_use_star.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0116_use_star.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0020_use_star.txt
index 2db3cbf9e..2db3cbf9e 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0116_use_star.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0020_use_star.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0073_impl_item_list.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.rs
index f10851487..f10851487 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0073_impl_item_list.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0073_impl_item_list.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt
index b15f93cd2..b15f93cd2 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0073_impl_item_list.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0021_impl_item_list.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0037_crate_visibility.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0022_crate_visibility.rs
index faeefde94..faeefde94 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0037_crate_visibility.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0022_crate_visibility.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0037_crate_visibility.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0022_crate_visibility.txt
index 7d137cfe9..7d137cfe9 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0037_crate_visibility.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0022_crate_visibility.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0027_placeholder_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0023_placeholder_type.rs
index 7952dbd57..7952dbd57 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0027_placeholder_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0023_placeholder_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0027_placeholder_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0023_placeholder_type.txt
index 43ada95d4..43ada95d4 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0027_placeholder_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0023_placeholder_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0089_slice_pat.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0024_slice_pat.rs
index 7955973b9..7955973b9 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0089_slice_pat.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0024_slice_pat.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0089_slice_pat.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0024_slice_pat.txt
index 72987308d..72987308d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0089_slice_pat.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0024_slice_pat.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0025_slice_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0025_slice_type.rs
index 4da1af827..4da1af827 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0025_slice_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0025_slice_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0025_slice_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0025_slice_type.txt
index db18c7139..db18c7139 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0025_slice_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0025_slice_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0071_tuple_pat_fields.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0026_tuple_pat_fields.rs
index 0dfe63629..0dfe63629 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0071_tuple_pat_fields.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0026_tuple_pat_fields.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0071_tuple_pat_fields.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0026_tuple_pat_fields.txt
index 737fbec22..737fbec22 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0071_tuple_pat_fields.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0026_tuple_pat_fields.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0035_ref_pat.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0027_ref_pat.rs
index de41f5cae..de41f5cae 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0035_ref_pat.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0027_ref_pat.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0035_ref_pat.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0027_ref_pat.txt
index 008f4f159..008f4f159 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0035_ref_pat.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0027_ref_pat.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0063_impl_trait_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.rs
index 54c5a7c46..54c5a7c46 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0063_impl_trait_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0063_impl_trait_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.txt
index efd4dd42a..efd4dd42a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0063_impl_trait_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0028_impl_trait_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0079_cast_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.rs
index b571a5860..b571a5860 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0079_cast_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0079_cast_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.txt
index cb56aef0b..cb56aef0b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0079_cast_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0029_cast_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0076_cond.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0030_cond.rs
index fdb37ee6f..fdb37ee6f 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0076_cond.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0030_cond.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0076_cond.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0030_cond.txt
index 641a09fff..641a09fff 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0076_cond.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0030_cond.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0077_while_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0031_while_expr.rs
index 293046a04..293046a04 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0077_while_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0031_while_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0077_while_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0031_while_expr.txt
index f9b074e82..f9b074e82 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0077_while_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0031_while_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0028_fn_pointer_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0032_fn_pointer_type.rs
index c9bf3bdb4..c9bf3bdb4 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0028_fn_pointer_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0032_fn_pointer_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0028_fn_pointer_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0032_fn_pointer_type.txt
index 0c508ec27..0c508ec27 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0028_fn_pointer_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0032_fn_pointer_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0026_reference_type;.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0033_reference_type;.rs
index 3ac0badab..3ac0badab 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0026_reference_type;.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0033_reference_type;.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0026_reference_type;.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0033_reference_type;.txt
index 7f35254d1..7f35254d1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0026_reference_type;.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0033_reference_type;.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0106_break_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0034_break_expr.rs
index 1b4094636..1b4094636 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0106_break_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0034_break_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0106_break_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0034_break_expr.txt
index 1877311e8..1877311e8 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0106_break_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0034_break_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0068_pub_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.rs
index d9d99d2d3..d9d99d2d3 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0068_pub_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0068_pub_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.txt
index de20eee7a..de20eee7a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0068_pub_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0035_pub_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0012_unsafe_extern_fn.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0036_unsafe_extern_fn.rs
index 1295c2cd2..1295c2cd2 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0012_unsafe_extern_fn.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0036_unsafe_extern_fn.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0012_unsafe_extern_fn.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0036_unsafe_extern_fn.txt
index 0cde40595..0cde40595 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0012_unsafe_extern_fn.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0036_unsafe_extern_fn.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0101_qual_paths.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0037_qual_paths.rs
index d140692e2..d140692e2 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0101_qual_paths.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0037_qual_paths.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0101_qual_paths.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0037_qual_paths.txt
index 394fc7f5b..394fc7f5b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0101_qual_paths.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0037_qual_paths.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0102_full_range_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0038_full_range_expr.rs
index ae21ad94c..ae21ad94c 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0102_full_range_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0038_full_range_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0102_full_range_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0038_full_range_expr.txt
index caef145ce..caef145ce 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0102_full_range_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0038_full_range_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0039_type_arg.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0039_type_arg.rs
new file mode 100644
index 000000000..385c43131
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0039_type_arg.rs
@@ -0,0 +1 @@
type A = B<'static, i32, Item=u64>;
diff --git a/crates/ra_syntax/tests/data/parser/inline/0058_type_arg.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0039_type_arg.txt
index 086a74bdb..ccef7188f 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0058_type_arg.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0039_type_arg.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 35) 1SOURCE_FILE@[0; 36)
2 TYPE_DEF@[0; 34) 2 TYPE_DEF@[0; 35)
3 TYPE_KW@[0; 4) 3 TYPE_KW@[0; 4)
4 WHITESPACE@[4; 5) 4 WHITESPACE@[4; 5)
5 NAME@[5; 6) 5 NAME@[5; 6)
@@ -36,5 +36,5 @@ SOURCE_FILE@[0; 35)
36 NAME_REF@[30; 33) 36 NAME_REF@[30; 33)
37 IDENT@[30; 33) "u64" 37 IDENT@[30; 33) "u64"
38 R_ANGLE@[33; 34) 38 R_ANGLE@[33; 34)
39 err: `expected SEMI` 39 SEMI@[34; 35)
40 WHITESPACE@[34; 35) 40 WHITESPACE@[35; 36)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0099_crate_keyword_vis.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.rs
index 660d927cf..660d927cf 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0099_crate_keyword_vis.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0099_crate_keyword_vis.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.txt
index ff5add838..ff5add838 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0099_crate_keyword_vis.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0040_crate_keyword_vis.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0056_trait_item.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.rs
index 4385afca9..4385afca9 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0056_trait_item.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0056_trait_item.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.txt
index 333a737ec..333a737ec 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0056_trait_item.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0041_trait_item.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0043_call_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.rs
index 0c9a20718..0c9a20718 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0043_call_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0043_call_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.txt
index 6364dc73c..6364dc73c 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0043_call_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0042_call_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0115_use_alias.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0043_use_alias.rs
index c7a141bbd..544caa020 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0115_use_alias.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0043_use_alias.rs
@@ -3,5 +3,5 @@ use some::{
3 other::path as some_other_name, 3 other::path as some_other_name,
4 different::path as different_name, 4 different::path as different_name,
5 yet::another::path, 5 yet::another::path,
6 running::out::of::synonyms::for::different::* 6 running::out::of::synonyms::for_::different::*
7}; 7};
diff --git a/crates/ra_syntax/tests/data/parser/inline/0115_use_alias.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0043_use_alias.txt
index f7b599476..8ef0ecbc6 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0115_use_alias.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0043_use_alias.txt
@@ -1,4 +1,4 @@
1SOURCE_FILE@[0; 181) 1SOURCE_FILE@[0; 182)
2 USE_ITEM@[0; 28) 2 USE_ITEM@[0; 28)
3 USE_KW@[0; 3) 3 USE_KW@[0; 3)
4 WHITESPACE@[3; 4) 4 WHITESPACE@[3; 4)
@@ -20,16 +20,16 @@ SOURCE_FILE@[0; 181)
20 IDENT@[18; 27) "some_name" 20 IDENT@[18; 27) "some_name"
21 SEMI@[27; 28) 21 SEMI@[27; 28)
22 WHITESPACE@[28; 29) 22 WHITESPACE@[28; 29)
23 USE_ITEM@[29; 180) 23 USE_ITEM@[29; 181)
24 USE_KW@[29; 32) 24 USE_KW@[29; 32)
25 WHITESPACE@[32; 33) 25 WHITESPACE@[32; 33)
26 USE_TREE@[33; 179) 26 USE_TREE@[33; 180)
27 PATH@[33; 37) 27 PATH@[33; 37)
28 PATH_SEGMENT@[33; 37) 28 PATH_SEGMENT@[33; 37)
29 NAME_REF@[33; 37) 29 NAME_REF@[33; 37)
30 IDENT@[33; 37) "some" 30 IDENT@[33; 37) "some"
31 COLONCOLON@[37; 39) 31 COLONCOLON@[37; 39)
32 USE_TREE_LIST@[39; 179) 32 USE_TREE_LIST@[39; 180)
33 L_CURLY@[39; 40) 33 L_CURLY@[39; 40)
34 WHITESPACE@[40; 42) 34 WHITESPACE@[40; 42)
35 USE_TREE@[42; 72) 35 USE_TREE@[42; 72)
@@ -85,9 +85,9 @@ SOURCE_FILE@[0; 181)
85 IDENT@[125; 129) "path" 85 IDENT@[125; 129) "path"
86 COMMA@[129; 130) 86 COMMA@[129; 130)
87 WHITESPACE@[130; 132) 87 WHITESPACE@[130; 132)
88 USE_TREE@[132; 177) 88 USE_TREE@[132; 178)
89 PATH@[132; 174) 89 PATH@[132; 175)
90 PATH@[132; 163) 90 PATH@[132; 164)
91 PATH@[132; 158) 91 PATH@[132; 158)
92 PATH@[132; 148) 92 PATH@[132; 148)
93 PATH@[132; 144) 93 PATH@[132; 144)
@@ -108,17 +108,16 @@ SOURCE_FILE@[0; 181)
108 NAME_REF@[150; 158) 108 NAME_REF@[150; 158)
109 IDENT@[150; 158) "synonyms" 109 IDENT@[150; 158) "synonyms"
110 COLONCOLON@[158; 160) 110 COLONCOLON@[158; 160)
111 err: `expected identifier` 111 PATH_SEGMENT@[160; 164)
112 PATH_SEGMENT@[160; 163) 112 NAME_REF@[160; 164)
113 ERROR@[160; 163) 113 IDENT@[160; 164) "for_"
114 FOR_KW@[160; 163) 114 COLONCOLON@[164; 166)
115 COLONCOLON@[163; 165) 115 PATH_SEGMENT@[166; 175)
116 PATH_SEGMENT@[165; 174) 116 NAME_REF@[166; 175)
117 NAME_REF@[165; 174) 117 IDENT@[166; 175) "different"
118 IDENT@[165; 174) "different" 118 COLONCOLON@[175; 177)
119 COLONCOLON@[174; 176) 119 STAR@[177; 178)
120 STAR@[176; 177) 120 WHITESPACE@[178; 179)
121 WHITESPACE@[177; 178) 121 R_CURLY@[179; 180)
122 R_CURLY@[178; 179) 122 SEMI@[180; 181)
123 SEMI@[179; 180) 123 WHITESPACE@[181; 182)
124 WHITESPACE@[180; 181)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0053_block_items.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0044_block_items.rs
index d9868718c..d9868718c 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0053_block_items.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0044_block_items.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0053_block_items.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0044_block_items.txt
index dd1843ee5..dd1843ee5 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0053_block_items.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0044_block_items.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0097_param_list_opt_patterns.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.rs
index 9b93442c0..9b93442c0 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0097_param_list_opt_patterns.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0097_param_list_opt_patterns.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.txt
index 2ce7a6714..2ce7a6714 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0097_param_list_opt_patterns.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0045_param_list_opt_patterns.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0019_singleton_tuple_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0046_singleton_tuple_type.rs
index cb66bad24..cb66bad24 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0019_singleton_tuple_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0046_singleton_tuple_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0019_singleton_tuple_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0046_singleton_tuple_type.txt
index 173c325d0..173c325d0 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0019_singleton_tuple_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0046_singleton_tuple_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0010_unsafe_default_impl.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.rs
index 9cd6c57bd..9cd6c57bd 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0010_unsafe_default_impl.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0010_unsafe_default_impl.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt
index 6003ba645..6003ba645 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0010_unsafe_default_impl.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0047_unsafe_default_impl.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0095_path_type_with_bounds.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.rs
index 215210e27..215210e27 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0095_path_type_with_bounds.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0095_path_type_with_bounds.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.txt
index 911a27ea1..911a27ea1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0095_path_type_with_bounds.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0048_path_type_with_bounds.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0050_let_stmt;.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0049_let_stmt;.rs
index 0a9af907f..0a9af907f 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0050_let_stmt;.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0049_let_stmt;.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0050_let_stmt;.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0049_let_stmt;.txt
index 9c2aad7e0..9c2aad7e0 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0050_let_stmt;.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0049_let_stmt;.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0091_fn_decl.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0050_fn_decl.rs
index c9f74f7f5..c9f74f7f5 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0091_fn_decl.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0050_fn_decl.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0091_fn_decl.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0050_fn_decl.txt
index bb87e1d06..bb87e1d06 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0091_fn_decl.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0050_fn_decl.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0018_unit_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0051_unit_type.rs
index c039cf7d3..c039cf7d3 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0018_unit_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0051_unit_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0018_unit_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0051_unit_type.txt
index 9fd19ba4a..9fd19ba4a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0018_unit_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0051_unit_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0032_path_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0052_path_type.rs
index bf94f32e1..bf94f32e1 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0032_path_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0052_path_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0032_path_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0052_path_type.txt
index b72b96e95..b72b96e95 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0032_path_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0052_path_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0039_path_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0053_path_expr.rs
index 333ebabef..333ebabef 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0039_path_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0053_path_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0039_path_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0053_path_expr.txt
index 673ea1d3d..673ea1d3d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0039_path_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0053_path_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0103_field_attrs.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0054_field_attrs.rs
index 4744d8ac0..4744d8ac0 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0103_field_attrs.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0054_field_attrs.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0103_field_attrs.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0054_field_attrs.txt
index e02ebf400..e02ebf400 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0103_field_attrs.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0054_field_attrs.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0092_literal_pattern.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.rs
index 16f674d9d..16f674d9d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0092_literal_pattern.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0092_literal_pattern.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt
index 99b289d56..99b289d56 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0092_literal_pattern.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0098_where_clause.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.rs
index 592a005f9..19d7e571b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0098_where_clause.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.rs
@@ -3,4 +3,5 @@ where
3 'a: 'b + 'c, 3 'a: 'b + 'c,
4 T: Clone + Copy + 'static, 4 T: Clone + Copy + 'static,
5 Iterator::Item: 'a, 5 Iterator::Item: 'a,
6 <T as Iterator>::Item: 'a
6{} 7{}
diff --git a/crates/ra_syntax/tests/data/parser/inline/0098_where_clause.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt
index 54c3d64f1..68485dc0b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0098_where_clause.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0056_where_clause.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 87) 1SOURCE_FILE@[0; 116)
2 FN_DEF@[0; 86) 2 FN_DEF@[0; 115)
3 FN_KW@[0; 2) 3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3) 4 WHITESPACE@[2; 3)
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,7 +8,7 @@ SOURCE_FILE@[0; 87)
8 L_PAREN@[6; 7) 8 L_PAREN@[6; 7)
9 R_PAREN@[7; 8) 9 R_PAREN@[7; 8)
10 WHITESPACE@[8; 9) 10 WHITESPACE@[8; 9)
11 WHERE_CLAUSE@[9; 83) 11 WHERE_CLAUSE@[9; 112)
12 WHERE_KW@[9; 14) 12 WHERE_KW@[9; 14)
13 WHITESPACE@[14; 18) 13 WHITESPACE@[14; 18)
14 WHERE_PRED@[18; 29) 14 WHERE_PRED@[18; 29)
@@ -64,8 +64,36 @@ SOURCE_FILE@[0; 87)
64 WHITESPACE@[79; 80) 64 WHITESPACE@[79; 80)
65 LIFETIME@[80; 82) "'a" 65 LIFETIME@[80; 82) "'a"
66 COMMA@[82; 83) 66 COMMA@[82; 83)
67 WHITESPACE@[83; 84) 67 WHITESPACE@[83; 87)
68 BLOCK@[84; 86) 68 WHERE_PRED@[87; 112)
69 L_CURLY@[84; 85) 69 PATH_TYPE@[87; 108)
70 R_CURLY@[85; 86) 70 PATH@[87; 108)
71 WHITESPACE@[86; 87) 71 PATH@[87; 102)
72 PATH_SEGMENT@[87; 102)
73 L_ANGLE@[87; 88)
74 PATH_TYPE@[88; 89)
75 PATH@[88; 89)
76 PATH_SEGMENT@[88; 89)
77 NAME_REF@[88; 89)
78 IDENT@[88; 89) "T"
79 WHITESPACE@[89; 90)
80 AS_KW@[90; 92)
81 WHITESPACE@[92; 93)
82 PATH_TYPE@[93; 101)
83 PATH@[93; 101)
84 PATH_SEGMENT@[93; 101)
85 NAME_REF@[93; 101)
86 IDENT@[93; 101) "Iterator"
87 R_ANGLE@[101; 102)
88 COLONCOLON@[102; 104)
89 PATH_SEGMENT@[104; 108)
90 NAME_REF@[104; 108)
91 IDENT@[104; 108) "Item"
92 COLON@[108; 109)
93 WHITESPACE@[109; 110)
94 LIFETIME@[110; 112) "'a"
95 WHITESPACE@[112; 113)
96 BLOCK@[113; 115)
97 L_CURLY@[113; 114)
98 R_CURLY@[114; 115)
99 WHITESPACE@[115; 116)
diff --git a/crates/ra_syntax/tests/data/parser/inline/0002_const_fn.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0057_const_fn.rs
index 8c84d9cd7..8c84d9cd7 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0002_const_fn.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0057_const_fn.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0002_const_fn.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0057_const_fn.txt
index 8206d973b..8206d973b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0002_const_fn.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0057_const_fn.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.rs
index c12ab6fce..c12ab6fce 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt
index d47f38903..d47f38903 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0085_match_arms_commas.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0059_match_arms_commas.rs
index 1f25d577a..1f25d577a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0085_match_arms_commas.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0059_match_arms_commas.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0085_match_arms_commas.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0059_match_arms_commas.txt
index 1034846c8..1034846c8 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0085_match_arms_commas.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0059_match_arms_commas.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0005_extern_crate.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.rs
index 49af74e1b..49af74e1b 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0005_extern_crate.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0005_extern_crate.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.txt
index 7ffdc7fbd..7ffdc7fbd 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0005_extern_crate.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0060_extern_crate.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0061_struct_lit.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0061_struct_lit.rs
index eb711f68a..eb711f68a 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0061_struct_lit.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0061_struct_lit.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0061_struct_lit.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0061_struct_lit.txt
index aec25403d..aec25403d 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0061_struct_lit.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0061_struct_lit.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0078_mod_contents.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0062_mod_contents.rs
index 24a15c5c5..24a15c5c5 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0078_mod_contents.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0062_mod_contents.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0078_mod_contents.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0062_mod_contents.txt
index 62528ca47..62528ca47 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0078_mod_contents.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0062_mod_contents.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0048_impl_item_neg.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.rs
index b7527c870..b7527c870 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0048_impl_item_neg.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0048_impl_item_neg.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.txt
index b83db380e..b83db380e 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0048_impl_item_neg.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0063_impl_item_neg.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0065_if_expr.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0064_if_expr.rs
index 4b0d9af89..4b0d9af89 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0065_if_expr.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0064_if_expr.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0065_if_expr.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0064_if_expr.txt
index 637d23d9e..637d23d9e 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0065_if_expr.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0064_if_expr.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0100_dyn_trait_type.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.rs
index c3ecabb99..c3ecabb99 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0100_dyn_trait_type.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.rs
diff --git a/crates/ra_syntax/tests/data/parser/inline/0100_dyn_trait_type.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.txt
index d07fe70b2..d07fe70b2 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0100_dyn_trait_type.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0065_dyn_trait_type.txt
diff --git a/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.rs
index 3380fa4ca..9e009e24f 100644
--- a/crates/ra_syntax/tests/data/parser/inline/0069_match_arm.rs
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.rs
@@ -1,7 +1,7 @@
1fn foo() { 1fn foo() {
2 match () { 2 match () {
3 _ => (), 3 _ => (),
4 _ if Test>{field: 0} => (), 4 _ if Test > Test{field: 0} => (),
5 X | Y if Z => (), 5 X | Y if Z => (),
6 | X | Y if Z => (), 6 | X | Y if Z => (),
7 | X => (), 7 | X => (),
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt
new file mode 100644
index 000000000..98e7535a3
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt
@@ -0,0 +1,146 @@