aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml4
-rw-r--r--ARCHITECTURE.md20
-rw-r--r--Cargo.lock20
-rw-r--r--Cargo.toml7
-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
-rw-r--r--editors/code/src/extension.ts30
313 files changed, 4614 insertions, 1607 deletions
diff --git a/.travis.yml b/.travis.yml
index ece7425fe..5e11cbd2f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,7 @@
1cache: cargo 1cache: cargo
2before_cache: 2before_cache:
3 - find ./target/debug -type f -maxdepth 1 -delete 3 - find ./target/debug -type f -maxdepth 1 -delete
4 - rm -fr ./target/debug/{deps,.fingerprint}/{*ra_*,*test*,*tools*,*gen_lsp*} 4 - rm -fr ./target/debug/{deps,.fingerprint}/{*ra_*,*test*,*tools*,*gen_lsp*,*thread_worker*}
5 - rm -f ./target/.rustc_info.json 5 - rm -f ./target/.rustc_info.json
6 6
7env: 7env:
@@ -9,7 +9,7 @@ env:
9 9
10build: &rust_build 10build: &rust_build
11 language: rust 11 language: rust
12 rust: 1.31.0 12 rust: 1.31.1
13 script: 13 script:
14 - cargo gen-tests --verify 14 - cargo gen-tests --verify
15 - cargo gen-syntax --verify 15 - cargo gen-syntax --verify
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index 823db0034..b326f9c71 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -20,7 +20,7 @@ memory and never does any IO. Because the input data is source code, which
20typically measures in tens of megabytes at most, keeping all input data in 20typically measures in tens of megabytes at most, keeping all input data in
21memory is OK. 21memory is OK.
22 22
23A "structured semantic model" is basically an object-oriented representations of 23A "structured semantic model" is basically an object-oriented representation of
24modules, functions and types which appear in the source code. This representation 24modules, functions and types which appear in the source code. This representation
25is fully "resolved": all expressions have types, all references are bound to 25is fully "resolved": all expressions have types, all references are bound to
26declarations, etc. 26declarations, etc.
@@ -90,29 +90,29 @@ fixes a bug in the grammar.
90We use [salsa][https://github.com/salsa-rs/salsa] crate for incremental and 90We use [salsa][https://github.com/salsa-rs/salsa] crate for incremental and
91on-demand computation. Roughly, you can think of salsa as a key-value store, but 91on-demand computation. Roughly, you can think of salsa as a key-value store, but
92it also can compute derived values using specified functions. The `ra_db` crate 92it also can compute derived values using specified functions. The `ra_db` crate
93provides a basic infrastructure for interracting with salsa. Crucially, it 93provides a basic infrastructure for interacting with salsa. Crucially, it
94defines most of the "input" queries: facts supplied by the client of the 94defines most of the "input" queries: facts supplied by the client of the
95analyzer. Reading the docs of the `ra_db::input` module should be useful: 95analyzer. Reading the docs of the `ra_db::input` module should be useful:
96everithing else is strictly derived from thouse inputs. 96everything else is strictly derived from those inputs.
97 97
98### `crates/ra_hir` 98### `crates/ra_hir`
99 99
100HIR provides a high-level "object oriented" acess to Rust code. 100HIR provides high-level "object oriented" access to Rust code.
101 101
102The principal difference between HIR and syntax trees is that HIR is bound to a 102The principal difference between HIR and syntax trees is that HIR is bound to a
103particular crate instance. That is, it has cfg flags and features applied (in 103particular crate instance. That is, it has cfg flags and features applied (in
104theory, in practice this is to be implemented). So, there relation between 104theory, in practice this is to be implemented). So, the relation between
105syntax and HIR is many-to-one. The `source_binder` modules is responsible for 105syntax and HIR is many-to-one. The `source_binder` modules is responsible for
106guessing a hir for a particular source position. 106guessing a HIR for a particular source position.
107 107
108Underneath, hir works on top of salsa, using a `HirDatabase` trait. 108Underneath, HIR works on top of salsa, using a `HirDatabase` trait.
109 109
110### `crates/ra_analysis` 110### `crates/ra_analysis`
111 111
112A stateful library for analyzing many Rust files as they change. 112A stateful library for analyzing many Rust files as they change.
113`AnalysisHost` is a mutable entity (clojure's atom) which holds 113`AnalysisHost` is a mutable entity (clojure's atom) which holds the
114current state, incorporates changes and handles out `Analysis` --- an 114current state, incorporates changes and handles out `Analysis` --- an
115immutable consistent snapshot of world state at a point in time, which 115immutable and consistent snapshot of world state at a point in time, which
116actually powers analysis. 116actually powers analysis.
117 117
118One interesting aspect of analysis is its support for cancellation. When a change 118One interesting aspect of analysis is its support for cancellation. When a change
@@ -137,7 +137,7 @@ without the need to fiddle with build-systems, file
137synchronization and such. 137synchronization and such.
138 138
139In a sense, `ra_editor` is just a bunch of pure functions which take a 139In a sense, `ra_editor` is just a bunch of pure functions which take a
140syntax tree as an input. 140syntax tree as input.
141 141
142The tests for `ra_editor` are `#[cfg(test)] mod tests` unit-tests spread 142The tests for `ra_editor` are `#[cfg(test)] mod tests` unit-tests spread
143throughout its modules. 143throughout its modules.
diff --git a/Cargo.lock b/Cargo.lock
index 5e5db84c3..5bf946b34 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -334,7 +334,6 @@ dependencies = [
334 "languageserver-types 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)", 334 "languageserver-types 0.53.0 (registry+https://github.com/rust-lang/crates.io-index)",
335 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 335 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
336 "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", 336 "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
337 "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
338 "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", 337 "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
339] 338]
340 339
@@ -649,7 +648,7 @@ dependencies = [
649 "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 648 "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
650 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 649 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
651 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 650 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
652 "salsa 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 651 "salsa 0.8.0 (git+https://github.com/matklad/salsa?branch=no-upgrade)",
653 "test_utils 0.1.0", 652 "test_utils 0.1.0",
654] 653]
655 654
@@ -674,7 +673,7 @@ dependencies = [
674 "ra_syntax 0.1.0", 673 "ra_syntax 0.1.0",
675 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 674 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
676 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 675 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
677 "salsa 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 676 "salsa 0.8.0 (git+https://github.com/matklad/salsa?branch=no-upgrade)",
678 "test_utils 0.1.0", 677 "test_utils 0.1.0",
679] 678]
680 679
@@ -704,7 +703,7 @@ dependencies = [
704 "ra_syntax 0.1.0", 703 "ra_syntax 0.1.0",
705 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 704 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
706 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 705 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
707 "salsa 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 706 "salsa 0.8.0 (git+https://github.com/matklad/salsa?branch=no-upgrade)",
708 "test_utils 0.1.0", 707 "test_utils 0.1.0",
709] 708]
710 709
@@ -732,9 +731,8 @@ dependencies = [
732 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 731 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
733 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 732 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
734 "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", 733 "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
735 "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
736 "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", 734 "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
737 "smol_str 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 735 "smol_str 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
738 "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 736 "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
739 "test_utils 0.1.0", 737 "test_utils 0.1.0",
740 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 738 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -959,7 +957,7 @@ version = "0.1.3"
959source = "registry+https://github.com/rust-lang/crates.io-index" 957source = "registry+https://github.com/rust-lang/crates.io-index"
960dependencies = [ 958dependencies = [
961 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 959 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
962 "smol_str 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 960 "smol_str 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
963 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 961 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
964] 962]
965 963
@@ -997,7 +995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
997[[package]] 995[[package]]
998name = "salsa" 996name = "salsa"
999version = "0.8.0" 997version = "0.8.0"
1000source = "registry+https://github.com/rust-lang/crates.io-index" 998source = "git+https://github.com/matklad/salsa?branch=no-upgrade#1a7ae719af1601fda81186fb48bd100edd9cfb7f"
1001dependencies = [ 999dependencies = [
1002 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", 1000 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1003 "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1001 "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1092,7 +1090,7 @@ dependencies = [
1092 1090
1093[[package]] 1091[[package]]
1094name = "smol_str" 1092name = "smol_str"
1095version = "0.1.7" 1093version = "0.1.8"
1096source = "registry+https://github.com/rust-lang/crates.io-index" 1094source = "registry+https://github.com/rust-lang/crates.io-index"
1097dependencies = [ 1095dependencies = [
1098 "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", 1096 "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1554,7 +1552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1554"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1552"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1555"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" 1553"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
1556"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" 1554"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
1557"checksum salsa 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e56b13ce9b2bfaa1c89863d76880838c0734de85beeaef437fd70d4fa7e253d3" 1555"checksum salsa 0.8.0 (git+https://github.com/matklad/salsa?branch=no-upgrade)" = "<none>"
1558"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" 1556"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
1559"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" 1557"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
1560"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1558"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
@@ -1565,7 +1563,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1565"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded" 1563"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
1566"checksum slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" 1564"checksum slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373"
1567"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" 1565"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
1568"checksum smol_str 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ed6f19b800d76574926e458d5f8e2dbea86c2b58c08d33a982448f09ac8d0c" 1566"checksum smol_str 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "486a74e9b9fc53373808f7a17e10fc728adcb1fbe272292271d8bea61175e181"
1569"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" 1567"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
1570"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" 1568"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
1571"checksum superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50b13d42370e0f5fc62eafdd5c2d20065eaf5458dab215ff3e20e63eea96b30" 1569"checksum superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50b13d42370e0f5fc62eafdd5c2d20065eaf5458dab215ff3e20e63eea96b30"
diff --git a/Cargo.toml b/Cargo.toml
index 95830561d..cbb9a09d5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,3 +4,10 @@ members = [ "crates/*" ]
4[profile.release] 4[profile.release]
5incremental = true 5incremental = true
6debug = true 6debug = true
7
8
9[patch.'crates-io']
10# https://github.com/salsa-rs/salsa/pull/75
11# and
12# https://github.com/salsa-rs/salsa/issues/99
13salsa = { git = "https://github.com/matklad/salsa", branch = "no-upgrade" }
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 636