aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--Cargo.lock84
-rw-r--r--crates/gen_lsp_server/src/lib.rs2
-rw-r--r--crates/ra_analysis/src/completion/mod.rs (renamed from crates/ra_analysis/src/completion.rs)328
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs316
-rw-r--r--crates/ra_analysis/src/db.rs8
-rw-r--r--crates/ra_analysis/src/descriptors/function/imp.rs4
-rw-r--r--crates/ra_analysis/src/descriptors/function/scope.rs6
-rw-r--r--crates/ra_analysis/src/descriptors/module/imp.rs18
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs49
-rw-r--r--crates/ra_analysis/src/descriptors/module/scope.rs6
-rw-r--r--crates/ra_analysis/src/imp.rs43
-rw-r--r--crates/ra_analysis/src/lib.rs23
-rw-r--r--crates/ra_analysis/src/symbol_index.rs8
-rw-r--r--crates/ra_analysis/src/syntax_ptr.rs11
-rw-r--r--crates/ra_analysis/tests/tests.rs41
-rw-r--r--crates/ra_cli/src/main.rs10
-rw-r--r--crates/ra_editor/src/code_actions.rs19
-rw-r--r--crates/ra_editor/src/extend_selection.rs6
-rw-r--r--crates/ra_editor/src/folding_ranges.rs6
-rw-r--r--crates/ra_editor/src/lib.rs18
-rw-r--r--crates/ra_editor/src/symbols.rs40
-rw-r--r--crates/ra_editor/src/test_utils.rs14
-rw-r--r--crates/ra_editor/src/typing.rs16
-rw-r--r--crates/ra_lsp_server/Cargo.toml2
-rw-r--r--crates/ra_lsp_server/src/caps.rs2
-rw-r--r--crates/ra_lsp_server/src/conv.rs4
-rw-r--r--crates/ra_lsp_server/src/main.rs41
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs28
-rw-r--r--crates/ra_lsp_server/src/main_loop/mod.rs24
-rw-r--r--crates/ra_lsp_server/tests/heavy_tests/support.rs2
-rw-r--r--crates/ra_syntax/Cargo.toml3
-rw-r--r--crates/ra_syntax/src/algo/mod.rs113
-rw-r--r--crates/ra_syntax/src/ast/generated.rs3535
-rw-r--r--crates/ra_syntax/src/ast/generated.rs.tera52
-rw-r--r--crates/ra_syntax/src/ast/mod.rs34
-rw-r--r--crates/ra_syntax/src/grammar.ron16
-rw-r--r--crates/ra_syntax/src/grammar/mod.rs2
-rw-r--r--crates/ra_syntax/src/grammar/type_params.rs6
-rw-r--r--crates/ra_syntax/src/lexer/ptr.rs3
-rw-r--r--crates/ra_syntax/src/lib.rs37
-rw-r--r--crates/ra_syntax/src/parser_impl/event.rs2
-rw-r--r--crates/ra_syntax/src/reparsing.rs8
-rw-r--r--crates/ra_syntax/src/string_lexing/byte.rs51
-rw-r--r--crates/ra_syntax/src/string_lexing/byte_string.rs51
-rw-r--r--crates/ra_syntax/src/string_lexing/char.rs176
-rw-r--r--crates/ra_syntax/src/string_lexing/mod.rs314
-rw-r--r--crates/ra_syntax/src/string_lexing/parser.rs201
-rw-r--r--crates/ra_syntax/src/string_lexing/string.rs46
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs4
-rw-r--r--crates/ra_syntax/src/utils.rs5
-rw-r--r--crates/ra_syntax/src/validation.rs78
-rw-r--r--crates/ra_syntax/src/validation/byte.rs211
-rw-r--r--crates/ra_syntax/src/validation/byte_string.rs178
-rw-r--r--crates/ra_syntax/src/validation/char.rs276
-rw-r--r--crates/ra_syntax/src/validation/mod.rs24
-rw-r--r--crates/ra_syntax/src/validation/string.rs168
-rw-r--r--crates/ra_syntax/src/yellow/mod.rs2
-rw-r--r--crates/ra_syntax/src/yellow/syntax_error.rs55
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0000_struct_field_missing_comma.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0001_item_recovery_in_file.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0002_duplicate_shebang.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0003_C++_semicolon.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0004_use_path_bad_segment.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0005_attribute_recover.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0006_named_field_recovery.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0007_stray_curly_in_file.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0008_item_block_recovery.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0009_broken_struct_type_parameter.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0010_unsafe_lambda_block.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0011_extern_struct.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0012_broken_lambda.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0013_invalid_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0014_where_no_bounds.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0015_curly_in_params.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0016_missing_semi.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0017_incomplete_binexpr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0018_incomplete_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0019_let_recover.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0020_fn_recover.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0021_incomplete_param.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0022_bad_exprs.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0023_mismatched_paren.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0024_many_type_parens.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0025_nope.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0026_imp_recovery.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.rs3
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt27
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0001_const_unsafe_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0002_const_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0003_extern_block.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0004_extern_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0005_extern_crate.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0007_unsafe_trait.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0008_unsafe_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0009_unsafe_auto_trait.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0010_unsafe_default_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0011_unsafe_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0012_unsafe_extern_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0013_unsafe_block_in_mod.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0014_type_item_type_params.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0015_type_item.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0016_type_item_where_clause.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0017_paren_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0018_unit_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0019_singleton_tuple_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0020_never_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0021_pointer_type_no_mutability.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0022_pointer_type_mut.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0023_array_type_missing_semi.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0024_array_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0025_slice_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0026_reference_type;.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0027_placeholder_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0028_fn_pointer_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0030_fn_pointer_type_with_ret.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0031_for_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0032_path_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0034_bind_pat.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0035_ref_pat.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0036_placeholder_pat.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0037_crate_visibility.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0038_function_ret_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0039_path_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0040_expr_literals.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0041_type_param_bounds.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0042_type_param_default.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0043_call_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0044_ref_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0045_block.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0046_default_impl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0047_impl_item.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0048_impl_item_neg.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0049_trait_item_list.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0050_let_stmt;.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0051_method_call_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0052_field_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0053_block_items.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0054_field_pat_list.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0055_self_param.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0056_trait_item.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0057_auto_trait.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0058_type_arg.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0059_function_where_clause.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0060_function_type_params.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0061_struct_lit.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0063_impl_trait_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0063_lambda_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0064_param_list.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0065_if_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0066_lambda_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0067_block_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0068_pub_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0068_return_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0069_match_arm.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0070_match_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0071_tuple_pat_fields.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0072_path_part.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0073_impl_item_list.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0074_unary_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0075_try_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0076_cond.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0077_while_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0078_mod_contents.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0079_cast_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0080_tuple_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0081_index_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0082_tuple_pat.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0083_postfix_range.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0084_loop_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0085_for_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0085_match_arms_commas.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0086_array_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0086_no_semi_after_block.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0087_stmt_postfix_expr_ambiguity.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0088_stmt_bin_expr_ambiguity.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0089_slice_pat.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0091_fn_decl.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0092_literal_pattern.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0093_path_fn_trait_args.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0094_range_pat.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0095_path_type_with_bounds.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0096_value_parameters_no_patterns.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0097_param_list_opt_patterns.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0098_where_clause.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0099_crate_keyword_vis.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0100_dyn_trait_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0101_qual_paths.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0102_full_range_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0103_field_attrs.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0104_arb_self_types.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0105_continue_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0106_break_expr.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0107_label.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0108_misplaced_label_err.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0109_struct_items.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0110_union_items.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0111_impl_type.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0112_crate_path.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/0113_where_pred_for.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0000_empty.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0001_struct_item.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0002_struct_item_field.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0004_file_shebang.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0005_fn_item.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0006_inner_attributes.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0007_extern_crate.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0008_mod_item.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0009_use_item.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0010_use_path_segments.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0011_outer_attribute.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0012_visibility.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0013_use_path_self_super.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0014_use_tree.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0015_use_tree.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0016_struct_flavors.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0017_attr_trailing_comma.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0018_struct_type_params.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0019_enums.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0020_type_param_bounds.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0021_extern_fn.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0022_empty_extern_block.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0023_static_items.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0024_const_item.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0025_extern_fn_in_block.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0026_const_fn_in_block.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0027_unsafe_fn_in_block.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0028_operator_binding_power.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0029_range_forms.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0030_traits.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0031_extern.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0032_where_for.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0034_macro_2.0.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0034_macro_stuck.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0035_crate_path_in_call.txt2
-rw-r--r--crates/ra_syntax/tests/test.rs4
-rw-r--r--editors/code/src/server.ts5
-rw-r--r--editors/emacs/ra.el41
240 files changed, 4464 insertions, 2801 deletions
diff --git a/.travis.yml b/.travis.yml
index 5252f20e2..ecb3b76f4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,8 @@
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 -f ./target/debug/deps/*ra_* 4 - rm -fr ./target/debug/{deps,.fingerprint}/{*ra_*,*test*,*tools*,*gen_lsp*}
5 - rm -f ./target/.rustc_info.json
5 6
6env: 7env:
7 - CARGO_INCREMENTAL=0 8 - CARGO_INCREMENTAL=0
diff --git a/Cargo.lock b/Cargo.lock
index fd1fb5ea5..18aac79ab 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -174,7 +174,7 @@ dependencies = [
174 "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", 174 "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
175 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 175 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
176 "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 176 "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
177 "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 177 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
178 "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 178 "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
179 "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 179 "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
180 "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 180 "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -188,7 +188,7 @@ dependencies = [
188 "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", 188 "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
189 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 189 "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
190 "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 190 "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
191 "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 191 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
192 "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 192 "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
193 "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 193 "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
194] 194]
@@ -208,12 +208,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
208 208
209[[package]] 209[[package]]
210name = "derive-new" 210name = "derive-new"
211version = "0.5.5" 211version = "0.5.6"
212source = "registry+https://github.com/rust-lang/crates.io-index" 212source = "registry+https://github.com/rust-lang/crates.io-index"
213dependencies = [ 213dependencies = [
214 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 214 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
215 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 215 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
216 "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", 216 "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)",
217] 217]
218 218
219[[package]] 219[[package]]
@@ -268,7 +268,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
268dependencies = [ 268dependencies = [
269 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 269 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
270 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 270 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
271 "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", 271 "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)",
272 "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", 272 "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
273] 273]
274 274
@@ -279,13 +279,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
279 279
280[[package]] 280[[package]]
281name = "flexi_logger" 281name = "flexi_logger"
282version = "0.9.3" 282version = "0.10.0"
283source = "registry+https://github.com/rust-lang/crates.io-index" 283source = "registry+https://github.com/rust-lang/crates.io-index"
284dependencies = [ 284dependencies = [
285 "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 285 "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
286 "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 286 "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
287 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 287 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
288 "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 288 "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
289] 289]
290 290
291[[package]] 291[[package]]
@@ -317,7 +317,7 @@ version = "0.1.0"
317dependencies = [ 317dependencies = [
318 "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 318 "crossbeam-channel 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
319 "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 319 "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
320 "languageserver-types 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)", 320 "languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
321 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 321 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
322 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 322 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
323 "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 323 "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -394,7 +394,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
394 394
395[[package]] 395[[package]]
396name = "languageserver-types" 396name = "languageserver-types"
397version = "0.51.0" 397version = "0.51.1"
398source = "registry+https://github.com/rust-lang/crates.io-index" 398source = "registry+https://github.com/rust-lang/crates.io-index"
399dependencies = [ 399dependencies = [
400 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 400 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -403,17 +403,14 @@ dependencies = [
403 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 403 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
404 "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 404 "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
405 "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", 405 "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
406 "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 406 "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
407 "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 407 "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
408] 408]
409 409
410[[package]] 410[[package]]
411name = "lazy_static" 411name = "lazy_static"
412version = "1.1.0" 412version = "1.2.0"
413source = "registry+https://github.com/rust-lang/crates.io-index" 413source = "registry+https://github.com/rust-lang/crates.io-index"
414dependencies = [
415 "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
416]
417 414
418[[package]] 415[[package]]
419name = "libc" 416name = "libc"
@@ -484,7 +481,7 @@ dependencies = [
484 "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 481 "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
485 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 482 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
486 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 483 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
487 "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", 484 "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)",
488] 485]
489 486
490[[package]] 487[[package]]
@@ -605,7 +602,7 @@ dependencies = [
605 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 602 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
606 "ra_editor 0.1.0", 603 "ra_editor 0.1.0",
607 "ra_syntax 0.1.0", 604 "ra_syntax 0.1.0",
608 "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 605 "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
609 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 606 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
610 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 607 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
611 "salsa 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 608 "salsa 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -645,15 +642,15 @@ dependencies = [
645 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 642 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
646 "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 643 "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
647 "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 644 "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
648 "flexi_logger 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", 645 "flexi_logger 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
649 "gen_lsp_server 0.1.0", 646 "gen_lsp_server 0.1.0",
650 "im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 647 "im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
651 "languageserver-types 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)", 648 "languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
652 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 649 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
653 "ra_analysis 0.1.0", 650 "ra_analysis 0.1.0",
654 "ra_editor 0.1.0", 651 "ra_editor 0.1.0",
655 "ra_syntax 0.1.0", 652 "ra_syntax 0.1.0",
656 "rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 653 "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
657 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 654 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
658 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 655 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
659 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 656 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -671,10 +668,11 @@ dependencies = [
671name = "ra_syntax" 668name = "ra_syntax"
672version = "0.1.0" 669version = "0.1.0"
673dependencies = [ 670dependencies = [
671 "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
674 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 672 "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
675 "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", 673 "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
676 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 674 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
677 "rowan 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 675 "rowan 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
678 "test_utils 0.1.0", 676 "test_utils 0.1.0",
679 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 677 "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
680 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 678 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -718,7 +716,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
718 716
719[[package]] 717[[package]]
720name = "rayon" 718name = "rayon"
721version = "1.0.2" 719version = "1.0.3"
722source = "registry+https://github.com/rust-lang/crates.io-index" 720source = "registry+https://github.com/rust-lang/crates.io-index"
723dependencies = [ 721dependencies = [
724 "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 722 "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -732,7 +730,7 @@ version = "1.4.1"
732source = "registry+https://github.com/rust-lang/crates.io-index" 730source = "registry+https://github.com/rust-lang/crates.io-index"
733dependencies = [ 731dependencies = [
734 "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 732 "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
735 "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 733 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
736 "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", 734 "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
737 "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 735 "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
738] 736]
@@ -752,7 +750,7 @@ dependencies = [
752 750
753[[package]] 751[[package]]
754name = "regex" 752name = "regex"
755version = "1.0.5" 753version = "1.0.6"
756source = "registry+https://github.com/rust-lang/crates.io-index" 754source = "registry+https://github.com/rust-lang/crates.io-index"
757dependencies = [ 755dependencies = [
758 "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 756 "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -795,7 +793,7 @@ dependencies = [
795 793
796[[package]] 794[[package]]
797name = "rowan" 795name = "rowan"
798version = "0.1.1" 796version = "0.1.2"
799source = "registry+https://github.com/rust-lang/crates.io-index" 797source = "registry+https://github.com/rust-lang/crates.io-index"
800dependencies = [ 798dependencies = [
801 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", 799 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -839,7 +837,7 @@ name = "salsa"
839version = "0.8.0" 837version = "0.8.0"
840source = "registry+https://github.com/rust-lang/crates.io-index" 838source = "registry+https://github.com/rust-lang/crates.io-index"
841dependencies = [ 839dependencies = [
842 "derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", 840 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
843 "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 841 "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
844 "lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 842 "lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
845 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 843 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -890,7 +888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
890dependencies = [ 888dependencies = [
891 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 889 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
892 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 890 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
893 "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", 891 "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)",
894] 892]
895 893
896[[package]] 894[[package]]
@@ -965,7 +963,7 @@ dependencies = [
965 963
966[[package]] 964[[package]]
967name = "syn" 965name = "syn"
968version = "0.15.17" 966version = "0.15.18"
969source = "registry+https://github.com/rust-lang/crates.io-index" 967source = "registry+https://github.com/rust-lang/crates.io-index"
970dependencies = [ 968dependencies = [
971 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 969 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -980,7 +978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
980dependencies = [ 978dependencies = [
981 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", 979 "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
982 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", 980 "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
983 "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", 981 "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)",
984 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 982 "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
985] 983]
986 984
@@ -1002,15 +1000,15 @@ dependencies = [
1002 "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 1000 "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
1003 "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 1001 "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
1004 "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1002 "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1005 "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1003 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1006 "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1004 "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1007 "pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1005 "pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1008 "regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1006 "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
1009 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 1007 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
1010 "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", 1008 "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
1011 "slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 1009 "slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
1012 "unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1010 "unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1013 "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1011 "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1014] 1012]
1015 1013
1016[[package]] 1014[[package]]
@@ -1064,7 +1062,7 @@ name = "thread_local"
1064version = "0.3.6" 1062version = "0.3.6"
1065source = "registry+https://github.com/rust-lang/crates.io-index" 1063source = "registry+https://github.com/rust-lang/crates.io-index"
1066dependencies = [ 1064dependencies = [
1067 "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1065 "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1068] 1066]
1069 1067
1070[[package]] 1068[[package]]
@@ -1185,7 +1183,7 @@ dependencies = [
1185 1183
1186[[package]] 1184[[package]]
1187name = "url" 1185name = "url"
1188version = "1.7.1" 1186version = "1.7.2"
1189source = "registry+https://github.com/rust-lang/crates.io-index" 1187source = "registry+https://github.com/rust-lang/crates.io-index"
1190dependencies = [ 1188dependencies = [
1191 "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 1189 "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1199,7 +1197,7 @@ version = "0.2.0"
1199source = "registry+https://github.com/rust-lang/crates.io-index" 1197source = "registry+https://github.com/rust-lang/crates.io-index"
1200dependencies = [ 1198dependencies = [
1201 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", 1199 "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
1202 "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1200 "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1203] 1201]
1204 1202
1205[[package]] 1203[[package]]
@@ -1284,7 +1282,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1284"checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416" 1282"checksum crossbeam-epoch 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c90f1474584f38e270b5b613e898c8c328aa4f3dea85e0a27ac2e642f009416"
1285"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" 1283"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
1286"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" 1284"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
1287"checksum derive-new 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "899ec79626c14e00ccc9729b4d750bbe67fe76a8f436824c16e0233bbd9d7daa" 1285"checksum derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c"
1288"checksum deunicode 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" 1286"checksum deunicode 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690"
1289"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" 1287"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
1290"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" 1288"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
@@ -1294,7 +1292,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1294"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" 1292"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
1295"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" 1293"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
1296"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 1294"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
1297"checksum flexi_logger 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7992096ba2290bd35b86b282e72edae518a25aa9a067ff417bc017ae63ac5e22" 1295"checksum flexi_logger 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "553854ebfebeae44ba699a9dc7d53a4036ccc01cd1e144aea0e3054c54383733"
1298"checksum fst 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9b0408ab57c1bf7c634b2ac6a165d14f642dc3335a43203090a7f8c78b54577b" 1296"checksum fst 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9b0408ab57c1bf7c634b2ac6a165d14f642dc3335a43203090a7f8c78b54577b"
1299"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 1297"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
1300"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 1298"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
@@ -1308,8 +1306,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1308"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450" 1306"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
1309"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" 1307"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
1310"checksum join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7bddc885f3fd69dd4b5d747c2efe6dd2c36d795ea9938281ed50910e32c95e31" 1308"checksum join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7bddc885f3fd69dd4b5d747c2efe6dd2c36d795ea9938281ed50910e32c95e31"
1311"checksum languageserver-types 0.51.0 (registry+https://github.com/rust-lang/crates.io-index)" = "caecadd973c43c93f5ce96fa457da310113d867af28808a8ed74023e9887a39e" 1309"checksum languageserver-types 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "68de833188ada4e175d04a028f03f244f6370eedbcc75a05604d47d925933f69"
1312"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" 1310"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
1313"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" 1311"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
1314"checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a" 1312"checksum lock_api 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775751a3e69bde4df9b38dd00a1b5d6ac13791e4223d4a0506577f0dd27cfb7a"
1315"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" 1313"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
@@ -1337,16 +1335,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1337"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" 1335"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
1338"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" 1336"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
1339"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" 1337"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
1340"checksum rayon 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df7a791f788cb4c516f0e091301a29c2b71ef680db5e644a7d68835c8ae6dbfa" 1338"checksum rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373814f27745b2686b350dd261bfd24576a6fb0e2c5919b3a2b6005f820b0473"
1341"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" 1339"checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356"
1342"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" 1340"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
1343"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" 1341"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
1344"checksum regex 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2069749032ea3ec200ca51e4a31df41759190a88edca0d2d86ee8bedf7073341" 1342"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467"
1345"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" 1343"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
1346"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c" 1344"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c"
1347"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" 1345"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
1348"checksum ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48677d8a9247a4e0d1f3f9cb4b0a8e29167fdc3c04f383a5e669cd7a960ae0f" 1346"checksum ron 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48677d8a9247a4e0d1f3f9cb4b0a8e29167fdc3c04f383a5e669cd7a960ae0f"
1349"checksum rowan 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bb1f952404091f61bfea7cd09c564090a0fcee3d22223f98084e8756e01c04d" 1347"checksum rowan 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "795b1c830f5335e89f93415315518e9727307308c44c1e5adebe8a38f856c334"
1350"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" 1348"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
1351"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" 1349"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
1352"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1350"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
@@ -1368,7 +1366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1368"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" 1366"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
1369"checksum superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50b13d42370e0f5fc62eafdd5c2d20065eaf5458dab215ff3e20e63eea96b30" 1367"checksum superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50b13d42370e0f5fc62eafdd5c2d20065eaf5458dab215ff3e20e63eea96b30"
1370"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" 1368"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
1371"checksum syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)" = "3391038ebc3e4ab24eb028cb0ef2f2dc4ba0cbf72ee895ed6a6fad730640b5bc" 1369"checksum syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)" = "90c39a061e2f412a9f869540471ab679e85e50c6b05604daf28bc3060f75c430"
1372"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" 1370"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
1373"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" 1371"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
1374"checksum tera 0.11.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac6d8ad623a7efcfb4367ce2a36f84ef849d5aa3c7bcf2e0324c4cbcc57ebaf" 1372"checksum tera 0.11.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac6d8ad623a7efcfb4367ce2a36f84ef849d5aa3c7bcf2e0324c4cbcc57ebaf"
@@ -1393,7 +1391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1393"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" 1391"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
1394"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 1392"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
1395"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 1393"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
1396"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" 1394"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
1397"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea" 1395"checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
1398"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" 1396"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
1399"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 1397"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
diff --git a/crates/gen_lsp_server/src/lib.rs b/crates/gen_lsp_server/src/lib.rs
index e45a6b5e2..5dab8f408 100644
--- a/crates/gen_lsp_server/src/lib.rs
+++ b/crates/gen_lsp_server/src/lib.rs
@@ -1,4 +1,4 @@
1//! A language server scaffold, exposing synchroneous crossbeam-channel based API. 1//! A language server scaffold, exposing a synchronous crossbeam-channel based API.
2//! This crate handles protocol handshaking and parsing messages, while you 2//! This crate handles protocol handshaking and parsing messages, while you
3//! control the message dispatch loop yourself. 3//! control the message dispatch loop yourself.
4//! 4//!
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion/mod.rs
index 7c3476e5c..2e082705e 100644
--- a/crates/ra_analysis/src/completion.rs
+++ b/crates/ra_analysis/src/completion/mod.rs
@@ -1,20 +1,20 @@
1mod reference_completion;
2
1use ra_editor::find_node_at_offset; 3use ra_editor::find_node_at_offset;
2use ra_syntax::{ 4use ra_syntax::{
3 algo::visit::{visitor, visitor_ctx, Visitor, VisitorCtx}, 5 algo::find_leaf_at_offset,
4 ast::{self, AstChildren, LoopBodyOwner, ModuleItemOwner}, 6 algo::visit::{visitor_ctx, VisitorCtx},
5 AstNode, AtomEdit, File, 7 ast,
6 SyntaxKind::*, 8 AstNode, AtomEdit,
7 SyntaxNodeRef, TextUnit, 9 SyntaxNodeRef,
8}; 10};
9use rustc_hash::{FxHashMap, FxHashSet}; 11use rustc_hash::{FxHashMap};
10 12
11use crate::{ 13use crate::{
12 db::{self, SyntaxDatabase}, 14 db::{self, SyntaxDatabase},
13 descriptors::function::FnScopes, 15 descriptors::{DescriptorDatabase, module::ModuleSource},
14 descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource}, 16 input::{FilesDatabase},
15 descriptors::DescriptorDatabase, 17 Cancelable, FilePosition
16 input::FilesDatabase,
17 Cancelable, FilePosition,
18}; 18};
19 19
20#[derive(Debug)] 20#[derive(Debug)]
@@ -27,175 +27,65 @@ pub struct CompletionItem {
27 pub snippet: Option<String>, 27 pub snippet: Option<String>,
28} 28}
29 29
30pub(crate) fn resolve_based_completion( 30pub(crate) fn completions(
31 db: &db::RootDatabase, 31 db: &db::RootDatabase,
32 position: FilePosition, 32 position: FilePosition,
33) -> Cancelable<Option<Vec<CompletionItem>>> { 33) -> Cancelable<Option<Vec<CompletionItem>>> {
34 let source_root_id = db.file_source_root(position.file_id); 34 let original_file = db.file_syntax(position.file_id);
35 let file = db.file_syntax(position.file_id); 35 // Insert a fake ident to get a valid parse tree
36 let module_tree = db.module_tree(source_root_id)?;
37 let module_id = match module_tree.any_module_for_source(ModuleSource::File(position.file_id)) {
38 None => return Ok(None),
39 Some(it) => it,
40 };
41 let file = { 36 let file = {
42 let edit = AtomEdit::insert(position.offset, "intellijRulezz".to_string()); 37 let edit = AtomEdit::insert(position.offset, "intellijRulezz".to_string());
43 file.reparse(&edit) 38 original_file.reparse(&edit)
39 };
40
41 let leaf = match find_leaf_at_offset(original_file.syntax(), position.offset).left_biased() {
42 None => return Ok(None),
43 Some(it) => it,
44 }; 44 };
45 let target_module_id = match find_target_module(&module_tree, module_id, &file, position.offset) 45 let source_root_id = db.file_source_root(position.file_id);
46 { 46 let module_tree = db.module_tree(source_root_id)?;
47 let module_source = ModuleSource::for_node(position.file_id, leaf);
48 let module_id = match module_tree.any_module_for_source(module_source) {
47 None => return Ok(None), 49 None => return Ok(None),
48 Some(it) => it, 50 Some(it) => it,
49 }; 51 };
50 let module_scope = db.module_scope(source_root_id, target_module_id)?;
51 let res: Vec<_> = module_scope
52 .entries()
53 .iter()
54 .map(|entry| CompletionItem {
55 label: entry.name().to_string(),
56 lookup: None,
57 snippet: None,
58 })
59 .collect();
60 Ok(Some(res))
61}
62
63pub(crate) fn find_target_module(
64 module_tree: &ModuleTree,
65 module_id: ModuleId,
66 file: &File,
67 offset: TextUnit,
68) -> Option<ModuleId> {
69 let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), offset)?;
70 let mut crate_path = crate_path(name_ref)?;
71
72 crate_path.pop();
73 let mut target_module = module_id.root(&module_tree);
74 for name in crate_path {
75 target_module = target_module.child(module_tree, name.text().as_str())?;
76 }
77 Some(target_module)
78}
79 52
80fn crate_path(name_ref: ast::NameRef) -> Option<Vec<ast::NameRef>> {
81 let mut path = name_ref
82 .syntax()
83 .parent()
84 .and_then(ast::PathSegment::cast)?
85 .parent_path();
86 let mut res = Vec::new(); 53 let mut res = Vec::new();
87 loop {
88 let segment = path.segment()?;
89 match segment.kind()? {
90 ast::PathSegmentKind::Name(name) => res.push(name),
91 ast::PathSegmentKind::CrateKw => break,
92 ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None,
93 }
94 path = path.qualifier()?;
95 }
96 res.reverse();
97 Some(res)
98}
99
100pub(crate) fn scope_completion(
101 db: &db::RootDatabase,
102 position: FilePosition,
103) -> Option<Vec<CompletionItem>> {
104 let original_file = db.file_syntax(position.file_id);
105 // Insert a fake ident to get a valid parse tree
106 let file = {
107 let edit = AtomEdit::insert(position.offset, "intellijRulezz".to_string());
108 original_file.reparse(&edit)
109 };
110 let mut has_completions = false; 54 let mut has_completions = false;
111 let mut res = Vec::new(); 55 // First, let's try to complete a reference to some declaration.
112 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { 56 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
113 has_completions = true; 57 has_completions = true;
114 complete_name_ref(&file, name_ref, &mut res); 58 reference_completion::completions(
59 &mut res,
60 db,
61 source_root_id,
62 &module_tree,
63 module_id,
64 &file,
65 name_ref,
66 )?;
115 // special case, `trait T { fn foo(i_am_a_name_ref) {} }` 67 // special case, `trait T { fn foo(i_am_a_name_ref) {} }`
116 if is_node::<ast::Param>(name_ref.syntax()) { 68 if is_node::<ast::Param>(name_ref.syntax()) {
117 param_completions(name_ref.syntax(), &mut res); 69 param_completions(name_ref.syntax(), &mut res);
118 } 70 }
119 let name_range = name_ref.syntax().range();
120 let top_node = name_ref
121 .syntax()
122 .ancestors()
123 .take_while(|it| it.range() == name_range)
124 .last()
125 .unwrap();
126 match top_node.parent().map(|it| it.kind()) {
127 Some(ROOT) | Some(ITEM_LIST) => complete_mod_item_snippets(&mut res),
128 _ => (),
129 }
130 } 71 }
72
73 // Otherwise, if this is a declaration, use heuristics to suggest a name.
131 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { 74 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
132 if is_node::<ast::Param>(name.syntax()) { 75 if is_node::<ast::Param>(name.syntax()) {
133 has_completions = true; 76 has_completions = true;
134 param_completions(name.syntax(), &mut res); 77 param_completions(name.syntax(), &mut res);
135 } 78 }
136 } 79 }
137 if has_completions { 80 let res = if has_completions { Some(res) } else { None };
138 Some(res) 81 Ok(res)
139 } else {
140 None
141 }
142}
143
144fn complete_module_items(
145 file: &File,
146 items: AstChildren<ast::ModuleItem>,
147 this_item: Option<ast::NameRef>,
148 acc: &mut Vec<CompletionItem>,
149) {
150 let scope = ModuleScope::new(items); // FIXME
151 acc.extend(
152 scope
153 .entries()
154 .iter()
155 .filter(|entry| {
156 let syntax = entry.ptr().resolve(file);
157 Some(syntax.borrowed()) != this_item.map(|it| it.syntax())
158 })
159 .map(|entry| CompletionItem {
160 label: entry.name().to_string(),
161 lookup: None,
162 snippet: None,
163 }),
164 );
165}
166
167fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) {
168 if !is_node::<ast::Path>(name_ref.syntax()) {
169 return;
170 }
171 let mut visited_fn = false;
172 for node in name_ref.syntax().ancestors() {
173 if let Some(items) = visitor()
174 .visit::<ast::Root, _>(|it| Some(it.items()))
175 .visit::<ast::Module, _>(|it| Some(it.item_list()?.items()))
176 .accept(node)
177 {
178 if let Some(items) = items {
179 complete_module_items(file, items, Some(name_ref), acc);
180 }
181 break;
182 } else if !visited_fn {
183 if let Some(fn_def) = ast::FnDef::cast(node) {
184 visited_fn = true;
185 complete_expr_keywords(&file, fn_def, name_ref, acc);
186 complete_expr_snippets(acc);
187 let scopes = FnScopes::new(fn_def);
188 complete_fn(name_ref, &scopes, acc);
189 }
190 }
191 }
192} 82}
193 83
194fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec<CompletionItem>) { 84fn param_completions(ctx: SyntaxNodeRef, acc: &mut Vec<CompletionItem>) {
195 let mut params = FxHashMap::default(); 85 let mut params = FxHashMap::default();
196 for node in ctx.ancestors() { 86 for node in ctx.ancestors() {
197 let _ = visitor_ctx(&mut params) 87 let _ = visitor_ctx(&mut params)
198 .visit::<ast::Root, _>(process) 88 .visit::<ast::SourceFile, _>(process)
199 .visit::<ast::ItemList, _>(process) 89 .visit::<ast::ItemList, _>(process)
200 .accept(node); 90 .accept(node);
201 } 91 }
@@ -238,140 +128,6 @@ fn is_node<'a, N: AstNode<'a>>(node: SyntaxNodeRef<'a>) -> bool {
238 } 128 }
239} 129}
240 130
241fn complete_expr_keywords(
242 file: &File,
243 fn_def: ast::FnDef,
244 name_ref: ast::NameRef,
245 acc: &mut Vec<CompletionItem>,
246) {
247 acc.push(keyword("if", "if $0 {}"));
248 acc.push(keyword("match", "match $0 {}"));
249 acc.push(keyword("while", "while $0 {}"));
250 acc.push(keyword("loop", "loop {$0}"));
251
252 if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
253 if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
254 if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
255 acc.push(keyword("else", "else {$0}"));
256 acc.push(keyword("else if", "else if $0 {}"));
257 }
258 }
259 }
260 if is_in_loop_body(name_ref) {
261 acc.push(keyword("continue", "continue"));
262 acc.push(keyword("break", "break"));
263 }
264 acc.extend(complete_return(fn_def, name_ref));
265}
266
267fn is_in_loop_body(name_ref: ast::NameRef) -> bool {
268 for node in name_ref.syntax().ancestors() {
269 if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
270 break;
271 }
272 let loop_body = visitor()
273 .visit::<ast::ForExpr, _>(LoopBodyOwner::loop_body)
274 .visit::<ast::WhileExpr, _>(LoopBodyOwner::loop_body)
275 .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
276 .accept(node);
277 if let Some(Some(body)) = loop_body {
278 if name_ref
279 .syntax()
280 .range()
281 .is_subrange(&body.syntax().range())
282 {
283 return true;
284 }
285 }
286 }
287 false
288}
289
290fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option<CompletionItem> {
291 // let is_last_in_block = name_ref.syntax().ancestors().filter_map(ast::Expr::cast)
292 // .next()
293 // .and_then(|it| it.syntax().parent())
294 // .and_then(ast::Block::cast)
295 // .is_some();
296
297 // if is_last_in_block {
298 // return None;
299 // }
300
301 let is_stmt = match name_ref
302 .syntax()
303 .ancestors()
304 .filter_map(ast::ExprStmt::cast)
305 .next()
306 {
307 None => false,
308 Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range(),
309 };
310 let snip = match (is_stmt, fn_def.ret_type().is_some()) {
311 (true, true) => "return $0;",
312 (true, false) => "return;",
313 (false, true) => "return $0",
314 (false, false) => "return",
315 };
316 Some(keyword("return", snip))
317}
318
319fn keyword(kw: &str, snip: &str) -> CompletionItem {
320 CompletionItem {
321 label: kw.to_string(),
322 lookup: None,
323 snippet: Some(snip.to_string()),
324 }
325}
326
327fn complete_expr_snippets(acc: &mut Vec<CompletionItem>) {
328 acc.push(CompletionItem {
329 label: "pd".to_string(),
330 lookup: None,
331 snippet: Some("eprintln!(\"$0 = {:?}\", $0);".to_string()),
332 });
333 acc.push(CompletionItem {
334 label: "ppd".to_string(),
335 lookup: None,
336 snippet: Some("eprintln!(\"$0 = {:#?}\", $0);".to_string()),
337 });
338}
339
340fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) {
341 acc.push(CompletionItem {
342 label: "tfn".to_string(),
343 lookup: None,
344 snippet: Some("#[test]\nfn $1() {\n $0\n}".to_string()),
345 });
346 acc.push(CompletionItem {
347 label: "pub(crate)".to_string(),
348 lookup: None,
349 snippet: Some("pub(crate) $0".to_string()),
350 })
351}
352
353fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
354 let mut shadowed = FxHashSet::default();
355 acc.extend(
356 scopes
357 .scope_chain(name_ref.syntax())
358 .flat_map(|scope| scopes.entries(scope).iter())
359 .filter(|entry| shadowed.insert(entry.name()))
360 .map(|entry| CompletionItem {
361 label: entry.name().to_string(),
362 lookup: None,
363 snippet: None,
364 }),
365 );
366 if scopes.self_param.is_some() {
367 acc.push(CompletionItem {
368 label: "self".to_string(),
369 lookup: None,
370 snippet: None,
371 })
372 }
373}
374
375#[cfg(test)] 131#[cfg(test)]
376mod tests { 132mod tests {
377 use test_utils::assert_eq_dbg; 133 use test_utils::assert_eq_dbg;
@@ -382,7 +138,8 @@ mod tests {
382 138
383 fn check_scope_completion(code: &str, expected_completions: &str) { 139 fn check_scope_completion(code: &str, expected_completions: &str) {
384 let (analysis, position) = single_file_with_position(code); 140 let (analysis, position) = single_file_with_position(code);
385 let completions = scope_completion(&analysis.imp.db, position) 141 let completions = completions(&analysis.imp.db, position)
142 .unwrap()
386 .unwrap() 143 .unwrap()
387 .into_iter() 144 .into_iter()
388 .filter(|c| c.snippet.is_none()) 145 .filter(|c| c.snippet.is_none())
@@ -392,7 +149,8 @@ mod tests {
392 149
393 fn check_snippet_completion(code: &str, expected_completions: &str) { 150 fn check_snippet_completion(code: &str, expected_completions: &str) {
394 let (analysis, position) = single_file_with_position(code); 151 let (analysis, position) = single_file_with_position(code);
395 let completions = scope_completion(&analysis.imp.db, position) 152 let completions = completions(&analysis.imp.db, position)
153 .unwrap()
396 .unwrap() 154 .unwrap()
397 .into_iter() 155 .into_iter()
398 .filter(|c| c.snippet.is_some()) 156 .filter(|c| c.snippet.is_some())
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
new file mode 100644
index 000000000..6c5fd0be6
--- /dev/null
+++ b/crates/ra_analysis/src/completion/reference_completion.rs
@@ -0,0 +1,316 @@
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};
9
10use crate::{
11 db::RootDatabase,
12 input::{SourceRootId},
13 completion::CompletionItem,
14 descriptors::module::{ModuleId, ModuleTree},
15 descriptors::function::FnScopes,
16 descriptors::DescriptorDatabase,
17 Cancelable
18};
19
20pub(super) fn completions(
21 acc: &mut Vec<CompletionItem>,
22 db: &RootDatabase,
23 source_root_id: SourceRootId,
24 module_tree: &ModuleTree,
25 module_id: ModuleId,
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 = db.module_scope(source_root_id, module_id)?;
44 acc.extend(
45 module_scope
46 .entries()
47 .iter()
48 .filter(|entry| {
49 // Don't expose this item
50 !entry.ptr().range().is_subrange(&name_ref.syntax().range())
51 })
52 .map(|entry| CompletionItem {
53 label: entry.name().to_string(),
54 lookup: None,
55 snippet: None,
56 }),
57 );
58 }
59 NameRefKind::CratePath(path) => {
60 complete_path(acc, db, source_root_id, module_tree, module_id, path)?
61 }
62 NameRefKind::BareIdentInMod => {
63 let name_range = name_ref.syntax().range();
64 let top_node = name_ref
65 .syntax()
66 .ancestors()
67 .take_while(|it| it.range() == name_range)
68 .last()
69 .unwrap();
70 match top_node.parent().map(|it| it.kind()) {
71 Some(SOURCE_FILE) | Some(ITEM_LIST) => complete_mod_item_snippets(acc),
72 _ => (),
73 }
74 }
75 }
76 Ok(())
77}
78
79enum NameRefKind<'a> {
80 /// NameRef is a part of single-segment path, for example, a refernece to a
81 /// local variable.
82 LocalRef {
83 enclosing_fn: Option<ast::FnDef<'a>>,
84 },
85 /// NameRef is the last segment in crate:: path
86 CratePath(Vec<ast::NameRef<'a>>),
87 /// NameRef is bare identifier at the module's root.
88 /// Used for keyword completion
89 BareIdentInMod,
90}
91
92fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
93 let name_range = name_ref.syntax().range();
94 let top_node = name_ref
95 .syntax()
96 .ancestors()
97 .take_while(|it| it.range() == name_range)
98 .last()
99 .unwrap();
100 match top_node.parent().map(|it| it.kind()) {
101 Some(SOURCE_FILE) | Some(ITEM_LIST) => return Some(NameRefKind::BareIdentInMod),
102 _ => (),
103 }
104
105 let parent = name_ref.syntax().parent()?;
106 if let Some(segment) = ast::PathSegment::cast(parent) {
107 let path = segment.parent_path();
108 if let Some(crate_path) = crate_path(path) {
109 return Some(NameRefKind::CratePath(crate_path));
110 }
111 if path.qualifier().is_none() {
112 let enclosing_fn = name_ref
113 .syntax()
114 .ancestors()
115 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
116 .find_map(ast::FnDef::cast);
117 return Some(NameRefKind::LocalRef { enclosing_fn });
118 }
119 }
120 None
121}
122
123fn crate_path(mut path: ast::Path) -> Option<Vec<ast::NameRef>> {
124 let mut res = Vec::new();
125 loop {
126 let segment = path.segment()?;
127 match segment.kind()? {
128 ast::PathSegmentKind::Name(name) => res.push(name),
129 ast::PathSegmentKind::CrateKw => break,
130 ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None,
131 }
132 path = qualifier(path)?;
133 }
134 res.reverse();
135 return Some(res);
136
137 fn qualifier(path: ast::Path) -> Option<ast::Path> {
138 if let Some(q) = path.qualifier() {
139 return Some(q);
140 }
141 // TODO: this bottom up traversal is not too precise.
142 // Should we handle do a top-down analysiss, recording results?
143 let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
144 let use_tree = use_tree_list.parent_use_tree();
145 use_tree.path()
146 }
147}
148
149fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
150 let mut shadowed = FxHashSet::default();
151 acc.extend(
152 scopes
153 .scope_chain(name_ref.syntax())
154 .flat_map(|scope| scopes.entries(scope).iter())
155 .filter(|entry| shadowed.insert(entry.name()))
156 .map(|entry| CompletionItem {
157 label: entry.name().to_string(),
158 lookup: None,
159 snippet: None,
160 }),
161 );
162 if scopes.self_param.is_some() {
163 acc.push(CompletionItem {
164 label: "self".to_string(),
165 lookup: None,
166 snippet: None,
167 })
168 }
169}
170
171fn complete_path(
172 acc: &mut Vec<CompletionItem>,
173 db: &RootDatabase,
174 source_root_id: SourceRootId,
175 module_tree: &ModuleTree,
176 module_id: ModuleId,
177 crate_path: Vec<ast::NameRef>,
178) -> Cancelable<()> {
179 let target_module_id = match find_target_module(module_tree, module_id, crate_path) {
180 None => return Ok(()),
181 Some(it) => it,
182 };
183 let module_scope = db.module_scope(source_root_id, target_module_id)?;
184 let completions = module_scope.entries().iter().map(|entry| CompletionItem {
185 label: entry.name().to_string(),
186 lookup: None,
187 snippet: None,
188 });
189 acc.extend(completions);
190 Ok(())
191}
192
193fn find_target_module(
194 module_tree: &ModuleTree,
195 module_id: ModuleId,
196 mut crate_path: Vec<ast::NameRef>,
197) -> Option<ModuleId> {
198 crate_path.pop();
199 let mut target_module = module_id.root(&module_tree);
200 for name in crate_path {
201 target_module = target_module.child(module_tree, name.text().as_str())?;
202 }
203 Some(target_module)
204}
205
206fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) {
207 acc.push(CompletionItem {
208 label: "tfn".to_string(),
209 lookup: None,
210 snippet: Some("#[test]\nfn $1() {\n $0\n}".to_string()),
211 });
212 acc.push(CompletionItem {
213 label: "pub(crate)".to_string(),
214 lookup: None,
215 snippet: Some("pub(crate) $0".to_string()),
216 })
217}
218
219fn complete_expr_keywords(
220 file: &SourceFileNode,
221 fn_def: ast::FnDef,
222 name_ref: ast::NameRef,
223 acc: &mut Vec<CompletionItem>,
224) {
225 acc.push(keyword("if", "if $0 {}"));
226 acc.push(keyword("match", "match $0 {}"));
227 acc.push(keyword("while", "while $0 {}"));
228 acc.push(keyword("loop", "loop {$0}"));
229
230 if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
231 if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
232 if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
233 acc.push(keyword("else", "else {$0}"));
234 acc.push(keyword("else if", "else if $0 {}"));
235 }
236 }
237 }
238 if is_in_loop_body(name_ref) {
239 acc.push(keyword("continue", "continue"));
240 acc.push(keyword("break", "break"));
241 }
242 acc.extend(complete_return(fn_def, name_ref));
243}
244
245fn is_in_loop_body(name_ref: ast::NameRef) -> bool {
246 for node in name_ref.syntax().ancestors() {
247 if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
248 break;
249 }
250 let loop_body = visitor()
251 .visit::<ast::ForExpr, _>(LoopBodyOwner::loop_body)
252 .visit::<ast::WhileExpr, _>(LoopBodyOwner::loop_body)
253 .visit::<ast::LoopExpr, _>(LoopBodyOwner::loop_body)
254 .accept(node);
255 if let Some(Some(body)) = loop_body {
256 if name_ref
257 .syntax()
258 .range()
259 .is_subrange(&body.syntax().range())
260 {
261 return true;
262 }
263 }
264 }
265 false
266}
267
268fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option<CompletionItem> {
269 // let is_last_in_block = name_ref.syntax().ancestors().filter_map(ast::Expr::cast)
270 // .next()
271 // .and_then(|it| it.syntax().parent())
272 // .and_then(ast::Block::cast)
273 // .is_some();
274
275 // if is_last_in_block {
276 // return None;
277 // }
278
279 let is_stmt = match name_ref
280 .syntax()
281 .ancestors()
282 .filter_map(ast::ExprStmt::cast)
283 .next()
284 {
285 None => false,
286 Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range(),
287 };
288 let snip = match (is_stmt, fn_def.ret_type().is_some()) {
289 (true, true) => "return $0;",
290 (true, false) => "return;",
291 (false, true) => "return $0",
292 (false, false) => "return",
293 };
294 Some(keyword("return", snip))
295}
296
297fn keyword(kw: &str, snip: &str) -> CompletionItem {
298 CompletionItem {
299 label: kw.to_string(),
300 lookup: None,
301 snippet: Some(snip.to_string()),
302 }
303}
304
305fn complete_expr_snippets(acc: &mut Vec<CompletionItem>) {
306 acc.push(CompletionItem {
307 label: "pd".to_string(),
308 lookup: None,
309 snippet: Some("eprintln!(\"$0 = {:?}\", $0);".to_string()),
310 });
311 acc.push(CompletionItem {
312 label: "ppd".to_string(),
313 lookup: None,
314 snippet: Some("eprintln!(\"$0 = {:#?}\", $0);".to_string()),
315 });
316}
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index 627512553..194f1a6b0 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,7 +1,7 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_editor::LineIndex; 3use ra_editor::LineIndex;
4use ra_syntax::{File, SyntaxNode}; 4use ra_syntax::{SourceFileNode, SyntaxNode};
5use salsa::{self, Database}; 5use salsa::{self, Database};
6 6
7use crate::{ 7use crate::{
@@ -85,7 +85,7 @@ salsa::database_storage! {
85 85
86salsa::query_group! { 86salsa::query_group! {
87 pub(crate) trait SyntaxDatabase: crate::input::FilesDatabase { 87 pub(crate) trait SyntaxDatabase: crate::input::FilesDatabase {
88 fn file_syntax(file_id: FileId) -> File { 88 fn file_syntax(file_id: FileId) -> SourceFileNode {
89 type FileSyntaxQuery; 89 type FileSyntaxQuery;
90 } 90 }
91 fn file_lines(file_id: FileId) -> Arc<LineIndex> { 91 fn file_lines(file_id: FileId) -> Arc<LineIndex> {
@@ -103,9 +103,9 @@ salsa::query_group! {
103 } 103 }
104} 104}
105 105
106fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> File { 106fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> SourceFileNode {
107 let text = db.file_text(file_id); 107 let text = db.file_text(file_id);
108 File::parse(&*text) 108 SourceFileNode::parse(&*text)
109} 109}
110fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> { 110fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> {
111 let text = db.file_text(file_id); 111 let text = db.file_text(file_id);
diff --git a/crates/ra_analysis/src/descriptors/function/imp.rs b/crates/ra_analysis/src/descriptors/function/imp.rs
index 755e05819..a989a04cd 100644
--- a/crates/ra_analysis/src/descriptors/function/imp.rs
+++ b/crates/ra_analysis/src/descriptors/function/imp.rs
@@ -11,11 +11,11 @@ use crate::descriptors::{
11/// TODO: this should return something more type-safe then `SyntaxNode` 11/// TODO: this should return something more type-safe then `SyntaxNode`
12pub(crate) fn fn_syntax(db: &impl DescriptorDatabase, fn_id: FnId) -> FnDefNode { 12pub(crate) fn fn_syntax(db: &impl DescriptorDatabase, fn_id: FnId) -> FnDefNode {
13 let syntax = db.resolve_syntax_ptr(fn_id.0); 13 let syntax = db.resolve_syntax_ptr(fn_id.0);
14 FnDef::cast(syntax.borrowed()).unwrap().into() 14 FnDef::cast(syntax.borrowed()).unwrap().owned()
15} 15}
16 16
17pub(crate) fn fn_scopes(db: &impl DescriptorDatabase, fn_id: FnId) -> Arc<FnScopes> { 17pub(crate) fn fn_scopes(db: &impl DescriptorDatabase, fn_id: FnId) -> Arc<FnScopes> {
18 let syntax = db.fn_syntax(fn_id); 18 let syntax = db.fn_syntax(fn_id);
19 let res = FnScopes::new(syntax.ast()); 19 let res = FnScopes::new(syntax.borrowed());
20 Arc::new(res) 20 Arc::new(res)
21} 21}
diff --git a/crates/ra_analysis/src/descriptors/function/scope.rs b/crates/ra_analysis/src/descriptors/function/scope.rs
index 62b46ffba..bbe16947c 100644
--- a/crates/ra_analysis/src/descriptors/function/scope.rs
+++ b/crates/ra_analysis/src/descriptors/function/scope.rs
@@ -272,7 +272,7 @@ pub fn resolve_local_name<'a>(
272#[cfg(test)] 272#[cfg(test)]
273mod tests { 273mod tests {
274 use ra_editor::find_node_at_offset; 274 use ra_editor::find_node_at_offset;
275 use ra_syntax::File; 275 use ra_syntax::SourceFileNode;
276 use test_utils::extract_offset; 276 use test_utils::extract_offset;
277 277
278 use super::*; 278 use super::*;
@@ -287,7 +287,7 @@ mod tests {
287 buf.push_str(&code[off..]); 287 buf.push_str(&code[off..]);
288 buf 288 buf
289 }; 289 };
290 let file = File::parse(&code); 290 let file = SourceFileNode::parse(&code);
291 let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); 291 let marker: ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap();
292 let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 292 let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
293 let scopes = FnScopes::new(fn_def); 293 let scopes = FnScopes::new(fn_def);
@@ -376,7 +376,7 @@ mod tests {
376 376
377 fn do_check_local_name(code: &str, expected_offset: u32) { 377 fn do_check_local_name(code: &str, expected_offset: u32) {
378 let (off, code) = extract_offset(code); 378 let (off, code) = extract_offset(code);
379 let file = File::parse(&code); 379 let file = SourceFileNode::parse(&code);
380 let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); 380 let fn_def: ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap();
381 let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); 381 let name_ref: ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap();
382 382
diff --git a/crates/ra_analysis/src/descriptors/module/imp.rs b/crates/ra_analysis/src/descriptors/module/imp.rs
index b3b1f1f21..ade96ddc0 100644
--- a/crates/ra_analysis/src/descriptors/module/imp.rs
+++ b/crates/ra_analysis/src/descriptors/module/imp.rs
@@ -41,9 +41,9 @@ pub(crate) fn submodules(
41 db::check_canceled(db)?; 41 db::check_canceled(db)?;
42 let file_id = source.file_id(); 42 let file_id = source.file_id();
43 let submodules = match source.resolve(db) { 43 let submodules = match source.resolve(db) {
44 ModuleSourceNode::Root(it) => collect_submodules(file_id, it.ast()), 44 ModuleSourceNode::SourceFile(it) => collect_submodules(file_id, it.borrowed()),
45 ModuleSourceNode::Inline(it) => it 45 ModuleSourceNode::Module(it) => it
46 .ast() 46 .borrowed()
47 .item_list() 47 .item_list()
48 .map(|it| collect_submodules(file_id, it)) 48 .map(|it| collect_submodules(file_id, it))
49 .unwrap_or_else(Vec::new), 49 .unwrap_or_else(Vec::new),
@@ -89,8 +89,8 @@ pub(crate) fn module_scope(
89 let tree = db.module_tree(source_root_id)?; 89 let tree = db.module_tree(source_root_id)?;
90 let source = module_id.source(&tree).resolve(db); 90 let source = module_id.source(&tree).resolve(db);
91 let res = match source { 91 let res = match source {
92 ModuleSourceNode::Root(root) => ModuleScope::new(root.ast().items()), 92 ModuleSourceNode::SourceFile(it) => ModuleScope::new(it.borrowed().items()),
93 ModuleSourceNode::Inline(inline) => match inline.ast().item_list() { 93 ModuleSourceNode::Module(it) => match it.borrowed().item_list() {
94 Some(items) => ModuleScope::new(items.items()), 94 Some(items) => ModuleScope::new(items.items()),
95 None => ModuleScope::new(std::iter::empty()), 95 None => ModuleScope::new(std::iter::empty()),
96 }, 96 },
@@ -121,7 +121,7 @@ fn create_module_tree<'a>(
121 121
122 let source_root = db.source_root(source_root); 122 let source_root = db.source_root(source_root);
123 for &file_id in source_root.files.iter() { 123 for &file_id in source_root.files.iter() {
124 let source = ModuleSource::File(file_id); 124 let source = ModuleSource::SourceFile(file_id);
125 if visited.contains(&source) { 125 if visited.contains(&source) {
126 continue; // TODO: use explicit crate_roots here 126 continue; // TODO: use explicit crate_roots here
127 } 127 }
@@ -181,7 +181,7 @@ fn build_subtree(
181 visited, 181 visited,
182 roots, 182 roots,
183 Some(link), 183 Some(link),
184 ModuleSource::File(file_id), 184 ModuleSource::SourceFile(file_id),
185 ), 185 ),
186 }) 186 })
187 .collect::<Cancelable<Vec<_>>>()?; 187 .collect::<Cancelable<Vec<_>>>()?;
@@ -213,8 +213,8 @@ fn resolve_submodule(
213 file_resolver: &FileResolverImp, 213 file_resolver: &FileResolverImp,
214) -> (Vec<FileId>, Option<Problem>) { 214) -> (Vec<FileId>, Option<Problem>) {
215 let file_id = match source { 215 let file_id = match source {
216 ModuleSource::File(it) => it, 216 ModuleSource::SourceFile(it) => it,
217 ModuleSource::Inline(..) => { 217 ModuleSource::Module(..) => {
218 // TODO 218 // TODO
219 return (Vec::new(), None); 219 return (Vec::new(), None);
220 } 220 }
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs
index 3d799ba05..bc1148b22 100644
--- a/crates/ra_analysis/src/descriptors/module/mod.rs
+++ b/crates/ra_analysis/src/descriptors/module/mod.rs
@@ -3,7 +3,7 @@ pub(crate) mod scope;
3 3
4use ra_syntax::{ 4use ra_syntax::{
5 ast::{self, AstNode, NameOwner}, 5 ast::{self, AstNode, NameOwner},
6 SmolStr, SyntaxNode, 6 SmolStr, SyntaxNode, SyntaxNodeRef,
7}; 7};
8use relative_path::RelativePathBuf; 8use relative_path::RelativePathBuf;
9 9
@@ -41,19 +41,18 @@ impl ModuleTree {
41 41
42/// `ModuleSource` is the syntax tree element that produced this module: 42/// `ModuleSource` is the syntax tree element that produced this module:
43/// either a file, or an inlinde module. 43/// either a file, or an inlinde module.
44/// TODO: we don't produce Inline modules yet
45#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 44#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
46pub(crate) enum ModuleSource { 45pub(crate) enum ModuleSource {
47 File(FileId), 46 SourceFile(FileId),
48 #[allow(dead_code)] 47 #[allow(dead_code)]
49 Inline(SyntaxPtr), 48 Module(SyntaxPtr),
50} 49}
51 50
52/// An owned syntax node for a module. Unlike `ModuleSource`, 51/// An owned syntax node for a module. Unlike `ModuleSource`,
53/// this holds onto the AST for the whole file. 52/// this holds onto the AST for the whole file.
54enum ModuleSourceNode { 53enum ModuleSourceNode {
55 Root(ast::RootNode), 54 SourceFile(ast::SourceFileNode),
56 Inline(ast::ModuleNode), 55 Module(ast::ModuleNode),
57} 56}
58 57
59#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] 58#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
@@ -117,7 +116,7 @@ impl ModuleId {
117 .filter_map(|&it| { 116 .filter_map(|&it| {
118 let p = tree.link(it).problem.clone()?; 117 let p = tree.link(it).problem.clone()?;
119 let s = it.bind_source(tree, db); 118 let s = it.bind_source(tree, db);
120 let s = s.ast().name().unwrap().syntax().owned(); 119 let s = s.borrowed().name().unwrap().syntax().owned();
121 Some((s, p)) 120 Some((s, p))
122 }) 121 })
123 .collect() 122 .collect()
@@ -135,14 +134,14 @@ impl LinkId {
135 ) -> ast::ModuleNode { 134 ) -> ast::ModuleNode {
136 let owner = self.owner(tree); 135 let owner = self.owner(tree);
137 match owner.source(tree).resolve(db) { 136 match owner.source(tree).resolve(db) {
138 ModuleSourceNode::Root(root) => { 137 ModuleSourceNode::SourceFile(root) => {
139 let ast = imp::modules(root.ast()) 138 let ast = imp::modules(root.borrowed())
140 .find(|(name, _)| name == &tree.link(self).name) 139 .find(|(name, _)| name == &tree.link(self).name)
141 .unwrap() 140 .unwrap()
142 .1; 141 .1;
143 ast.into() 142 ast.owned()
144 } 143 }
145 ModuleSourceNode::Inline(it) => it, 144 ModuleSourceNode::Module(it) => it,
146 } 145 }
147 } 146 }
148} 147}
@@ -155,37 +154,47 @@ struct ModuleData {
155} 154}
156 155
157impl ModuleSource { 156impl ModuleSource {
157 pub(crate) fn for_node(file_id: FileId, node: SyntaxNodeRef) -> ModuleSource {
158 for node in node.ancestors() {
159 if let Some(m) = ast::Module::cast(node) {
160 if !m.has_semi() {
161 return ModuleSource::new_inline(file_id, m);
162 }
163 }
164 }
165 ModuleSource::SourceFile(file_id)
166 }
158 pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource { 167 pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource {
159 assert!(!module.has_semi()); 168 assert!(!module.has_semi());
160 let ptr = SyntaxPtr::new(file_id, module.syntax()); 169 let ptr = SyntaxPtr::new(file_id, module.syntax());
161 ModuleSource::Inline(ptr) 170 ModuleSource::Module(ptr)
162 } 171 }
163 172
164 pub(crate) fn as_file(self) -> Option<FileId> { 173 pub(crate) fn as_file(self) -> Option<FileId> {
165 match self { 174 match self {
166 ModuleSource::File(f) => Some(f), 175 ModuleSource::SourceFile(f) => Some(f),
167 ModuleSource::Inline(..) => None, 176 ModuleSource::Module(..) => None,
168 } 177 }
169 } 178 }
170 179
171 pub(crate) fn file_id(self) -> FileId { 180 pub(crate) fn file_id(self) -> FileId {
172 match self { 181 match self {
173 ModuleSource::File(f) => f, 182 ModuleSource::SourceFile(f) => f,
174 ModuleSource::Inline(ptr) => ptr.file_id(), 183 ModuleSource::Module(ptr) => ptr.file_id(),
175 } 184 }
176 } 185 }
177 186
178 fn resolve(self, db: &impl SyntaxDatabase) -> ModuleSourceNode { 187 fn resolve(self, db: &impl SyntaxDatabase) -> ModuleSourceNode {
179 match self { 188 match self {
180 ModuleSource::File(file_id) => { 189 ModuleSource::SourceFile(file_id) => {
181 let syntax = db.file_syntax(file_id); 190 let syntax = db.file_syntax(file_id);
182 ModuleSourceNode::Root(syntax.ast().into()) 191 ModuleSourceNode::SourceFile(syntax.ast().owned())
183 } 192 }
184 ModuleSource::Inline(ptr) => { 193 ModuleSource::Module(ptr) => {
185 let syntax = db.resolve_syntax_ptr(ptr); 194 let syntax = db.resolve_syntax_ptr(ptr);
186 let syntax = syntax.borrowed(); 195 let syntax = syntax.borrowed();
187 let module = ast::Module::cast(syntax).unwrap(); 196 let module = ast::Module::cast(syntax).unwrap();
188 ModuleSourceNode::Inline(module.into()) 197 ModuleSourceNode::Module(module.owned())
189 } 198 }
190 } 199 }
191 } 200 }
diff --git a/crates/ra_analysis/src/descriptors/module/scope.rs b/crates/ra_analysis/src/descriptors/module/scope.rs
index 215b31f8e..4490228e4 100644
--- a/crates/ra_analysis/src/descriptors/module/scope.rs
+++ b/crates/ra_analysis/src/descriptors/module/scope.rs
@@ -25,7 +25,7 @@ enum EntryKind {
25} 25}
26 26
27impl ModuleScope { 27impl ModuleScope {
28 pub(crate) fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> ModuleScope { 28 pub(super) fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> ModuleScope {
29 let mut entries = Vec::new(); 29 let mut entries = Vec::new();
30 for item in items { 30 for item in items {
31 let entry = match item { 31 let entry = match item {
@@ -95,10 +95,10 @@ fn collect_imports(tree: ast::UseTree, acc: &mut Vec<Entry>) {
95#[cfg(test)] 95#[cfg(test)]
96mod tests { 96mod tests {
97 use super::*; 97 use super::*;
98 use ra_syntax::{ast::ModuleItemOwner, File}; 98 use ra_syntax::{ast::ModuleItemOwner, SourceFileNode};
99 99
100 fn do_check(code: &str, expected: &[&str]) { 100 fn do_check(code: &str, expected: &[&str]) {
101 let file = File::parse(&code); 101 let file = SourceFileNode::parse(&code);
102 let scope = ModuleScope::new(file.ast().items()); 102 let scope = ModuleScope::new(file.ast().items());
103 let actual = scope.entries.iter().map(|it| it.name()).collect::<Vec<_>>(); 103 let actual = scope.entries.iter().map(|it| it.name()).collect::<Vec<_>>();
104 assert_eq!(expected, actual.as_slice()); 104 assert_eq!(expected, actual.as_slice());
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index f2482559f..74c248a96 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -7,7 +7,7 @@ use std::{
7use ra_editor::{self, find_node_at_offset, FileSymbol, LineIndex, LocalEdit}; 7use ra_editor::{self, find_node_at_offset, FileSymbol, LineIndex, LocalEdit};
8use ra_syntax::{ 8use ra_syntax::{
9 ast::{self, ArgListOwner, Expr, NameOwner}, 9 ast::{self, ArgListOwner, Expr, NameOwner},
10 AstNode, File, SmolStr, 10 AstNode, SourceFileNode, SmolStr,
11 SyntaxKind::*, 11 SyntaxKind::*,
12 SyntaxNodeRef, TextRange, TextUnit, 12 SyntaxNodeRef, TextRange, TextUnit,
13}; 13};
@@ -17,7 +17,7 @@ use rustc_hash::FxHashSet;
17use salsa::{Database, ParallelDatabase}; 17use salsa::{Database, ParallelDatabase};
18 18
19use crate::{ 19use crate::{
20 completion::{resolve_based_completion, scope_completion, CompletionItem}, 20 completion::{completions, CompletionItem},
21 db::{self, FileSyntaxQuery, SyntaxDatabase}, 21 db::{self, FileSyntaxQuery, SyntaxDatabase},
22 descriptors::{ 22 descriptors::{
23 function::{FnDescriptor, FnId}, 23 function::{FnDescriptor, FnId},
@@ -27,7 +27,7 @@ use crate::{
27 input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, 27 input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE},
28 symbol_index::SymbolIndex, 28 symbol_index::SymbolIndex,
29 AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver, 29 AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver,
30 FileSystemEdit, FilePosition, Query, SourceChange, SourceFileEdit, 30 FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit,
31}; 31};
32 32
33#[derive(Clone, Debug)] 33#[derive(Clone, Debug)]
@@ -180,7 +180,7 @@ impl fmt::Debug for AnalysisImpl {
180} 180}
181 181
182impl AnalysisImpl { 182impl AnalysisImpl {
183 pub fn file_syntax(&self, file_id: FileId) -> File { 183 pub fn file_syntax(&self, file_id: FileId) -> SourceFileNode {
184 self.db.file_syntax(file_id) 184 self.db.file_syntax(file_id)
185 } 185 }
186 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { 186 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
@@ -226,7 +226,7 @@ impl AnalysisImpl {
226 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) 226 let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset)
227 { 227 {
228 Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m), 228 Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m),
229 _ => ModuleSource::File(position.file_id), 229 _ => ModuleSource::SourceFile(position.file_id),
230 }; 230 };
231 231
232 let res = module_tree 232 let res = module_tree
@@ -236,7 +236,7 @@ impl AnalysisImpl {
236 let link = module_id.parent_link(&module_tree)?; 236 let link = module_id.parent_link(&module_tree)?;
237 let file_id = link.owner(&module_tree).source(&module_tree).file_id(); 237 let file_id = link.owner(&module_tree).source(&module_tree).file_id();
238 let decl = link.bind_source(&module_tree, &*self.db); 238 let decl = link.bind_source(&module_tree, &*self.db);
239 let decl = decl.ast(); 239 let decl = decl.borrowed();
240 240
241 let decl_name = decl.name().unwrap(); 241 let decl_name = decl.name().unwrap();
242 242
@@ -254,7 +254,7 @@ impl AnalysisImpl {
254 let module_tree = self.module_tree(file_id)?; 254 let module_tree = self.module_tree(file_id)?;
255 let crate_graph = self.db.crate_graph(); 255 let crate_graph = self.db.crate_graph();
256 let res = module_tree 256 let res = module_tree
257 .modules_for_source(ModuleSource::File(file_id)) 257 .modules_for_source(ModuleSource::SourceFile(file_id))
258 .into_iter() 258 .into_iter()
259 .map(|it| it.root(&module_tree)) 259 .map(|it| it.root(&module_tree))
260 .filter_map(|it| it.source(&module_tree).as_file()) 260 .filter_map(|it| it.source(&module_tree).as_file())
@@ -267,18 +267,7 @@ impl AnalysisImpl {
267 self.db.crate_graph().crate_roots[&crate_id] 267 self.db.crate_graph().crate_roots[&crate_id]
268 } 268 }
269 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { 269 pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
270 let mut res = Vec::new(); 270 completions(&self.db, position)
271 let mut has_completions = false;
272 if let Some(scope_based) = scope_completion(&self.db, position) {
273 res.extend(scope_based);
274 has_completions = true;
275 }
276 if let Some(scope_based) = resolve_based_completion(&self.db, position)? {
277 res.extend(scope_based);
278 has_completions = true;
279 }
280 let res = if has_completions { Some(res) } else { None };
281 Ok(res)
282 } 271 }
283 pub fn approximately_resolve_symbol( 272 pub fn approximately_resolve_symbol(
284 &self, 273 &self,
@@ -364,6 +353,16 @@ impl AnalysisImpl {
364 ret 353 ret
365 } 354 }
366 355
356 pub fn doc_comment_for(
357 &self,
358 file_id: FileId,
359 symbol: FileSymbol,
360 ) -> Cancelable<Option<String>> {
361 let file = self.db.file_syntax(file_id);
362
363 Ok(symbol.docs(&file))
364 }
365
367 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { 366 pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
368 let module_tree = self.module_tree(file_id)?; 367 let module_tree = self.module_tree(file_id)?;
369 let syntax = self.db.file_syntax(file_id); 368 let syntax = self.db.file_syntax(file_id);
@@ -376,7 +375,7 @@ impl AnalysisImpl {
376 fix: None, 375 fix: None,
377 }) 376 })
378 .collect::<Vec<_>>(); 377 .collect::<Vec<_>>();
379 if let Some(m) = module_tree.any_module_for_source(ModuleSource::File(file_id)) { 378 if let Some(m) = module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) {
380 for (name_node, problem) in m.problems(&module_tree, &*self.db) { 379 for (name_node, problem) in m.problems(&module_tree, &*self.db) {
381 let diag = match problem { 380 let diag = match problem {
382 Problem::UnresolvedModule { candidate } => { 381 Problem::UnresolvedModule { candidate } => {
@@ -538,7 +537,7 @@ impl AnalysisImpl {
538 Some(name) => name.text(), 537 Some(name) => name.text(),
539 None => return Vec::new(), 538 None => return Vec::new(),
540 }; 539 };
541 let module_id = match module_tree.any_module_for_source(ModuleSource::File(file_id)) { 540 let module_id = match module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) {
542 Some(id) => id, 541 Some(id) => id,
543 None => return Vec::new(), 542 None => return Vec::new(),
544 }; 543 };
@@ -552,7 +551,7 @@ impl AnalysisImpl {
552 551
553impl SourceChange { 552impl SourceChange {
554 pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange { 553 pub(crate) fn from_local_edit(file_id: FileId, label: &str, edit: LocalEdit) -> SourceChange {
555 let file_edit = SourceFileEdit { 554 let file_edit = SourceFileNodeEdit {
556 file_id, 555 file_id,
557 edits: edit.edit.into_atoms(), 556 edits: edit.edit.into_atoms(),
558 }; 557 };
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index 0ea9ebee7..ab0e3cb0c 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -1,5 +1,5 @@
1//! ra_analyzer crate is the brain of Rust analyzer. It relies on the `salsa` 1//! ra_analyzer crate is the brain of Rust analyzer. It relies on the `salsa`
2//! crate, which provides and incremental on-deman database of facts. 2//! crate, which provides and incremental on-demand database of facts.
3 3
4extern crate fst; 4extern crate fst;
5extern crate ra_editor; 5extern crate ra_editor;
@@ -20,7 +20,7 @@ pub mod mock_analysis;
20 20
21use std::{fmt, sync::Arc}; 21use std::{fmt, sync::Arc};
22 22
23use ra_syntax::{AtomEdit, File, TextRange, TextUnit}; 23use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit};
24use rayon::prelude::*; 24use rayon::prelude::*;
25use relative_path::RelativePathBuf; 25use relative_path::RelativePathBuf;
26 26
@@ -128,13 +128,13 @@ pub struct FilePosition {
128#[derive(Debug)] 128#[derive(Debug)]
129pub struct SourceChange { 129pub struct SourceChange {
130 pub label: String, 130 pub label: String,
131 pub source_file_edits: Vec<SourceFileEdit>, 131 pub source_file_edits: Vec<SourceFileNodeEdit>,
132 pub file_system_edits: Vec<FileSystemEdit>, 132 pub file_system_edits: Vec<FileSystemEdit>,
133 pub cursor_position: Option<FilePosition>, 133 pub cursor_position: Option<FilePosition>,
134} 134}
135 135
136#[derive(Debug)] 136#[derive(Debug)]
137pub struct SourceFileEdit { 137pub struct SourceFileNodeEdit {
138 pub file_id: FileId, 138 pub file_id: FileId,
139 pub edits: Vec<AtomEdit>, 139 pub edits: Vec<AtomEdit>,
140} 140}
@@ -204,16 +204,16 @@ pub struct Analysis {
204} 204}
205 205
206impl Analysis { 206impl Analysis {
207 pub fn file_syntax(&self, file_id: FileId) -> File { 207 pub fn file_syntax(&self, file_id: FileId) -> SourceFileNode {
208 self.imp.file_syntax(file_id).clone() 208 self.imp.file_syntax(file_id).clone()
209 } 209 }
210 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { 210 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
211 self.imp.file_line_index(file_id) 211 self.imp.file_line_index(file_id)
212 } 212 }
213 pub fn extend_selection(&self, file: &File, range: TextRange) -> TextRange { 213 pub fn extend_selection(&self, file: &SourceFileNode, range: TextRange) -> TextRange {
214 ra_editor::extend_selection(file, range).unwrap_or(range) 214 ra_editor::extend_selection(file, range).unwrap_or(range)
215 } 215 }
216 pub fn matching_brace(&self, file: &File, offset: TextUnit) -> Option<TextUnit> { 216 pub fn matching_brace(&self, file: &SourceFileNode, offset: TextUnit) -> Option<TextUnit> {
217 ra_editor::matching_brace(file, offset) 217 ra_editor::matching_brace(file, offset)
218 } 218 }
219 pub fn syntax_tree(&self, file_id: FileId) -> String { 219 pub fn syntax_tree(&self, file_id: FileId) -> String {
@@ -258,6 +258,13 @@ impl Analysis {
258 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> { 258 pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
259 Ok(self.imp.find_all_refs(position)) 259 Ok(self.imp.find_all_refs(position))
260 } 260 }
261 pub fn doc_comment_for(
262 &self,
263 file_id: FileId,
264 symbol: FileSymbol,
265 ) -> Cancelable<Option<String>> {
266 self.imp.doc_comment_for(file_id, symbol)
267 }
261 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { 268 pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> {
262 self.imp.parent_module(position) 269 self.imp.parent_module(position)
263 } 270 }
@@ -302,7 +309,7 @@ pub struct LibraryData {
302impl LibraryData { 309impl LibraryData {
303 pub fn prepare(files: Vec<(FileId, String)>, file_resolver: Arc<FileResolver>) -> LibraryData { 310 pub fn prepare(files: Vec<(FileId, String)>, file_resolver: Arc<FileResolver>) -> LibraryData {
304 let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, text)| { 311 let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, text)| {
305 let file = File::parse(text); 312 let file = SourceFileNode::parse(text);
306 (*file_id, file) 313 (*file_id, file)
307 })); 314 }));
308 LibraryData { 315 LibraryData {
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs
index b57ad5d33..3a0667ecd 100644
--- a/crates/ra_analysis/src/symbol_index.rs
+++ b/crates/ra_analysis/src/symbol_index.rs
@@ -6,7 +6,7 @@ use std::{
6use fst::{self, Streamer}; 6use fst::{self, Streamer};
7use ra_editor::{file_symbols, FileSymbol}; 7use ra_editor::{file_symbols, FileSymbol};
8use ra_syntax::{ 8use ra_syntax::{
9 File, 9 SourceFileNode,
10 SyntaxKind::{self, *}, 10 SyntaxKind::{self, *},
11}; 11};
12use rayon::prelude::*; 12use rayon::prelude::*;
@@ -34,7 +34,9 @@ impl Hash for SymbolIndex {
34} 34}
35 35
36impl SymbolIndex { 36impl SymbolIndex {
37 pub(crate) fn for_files(files: impl ParallelIterator<Item = (FileId, File)>) -> SymbolIndex { 37 pub(crate) fn for_files(
38 files: impl ParallelIterator<Item = (FileId, SourceFileNode)>,
39 ) -> SymbolIndex {
38 let mut symbols = files 40 let mut symbols = files
39 .flat_map(|(file_id, file)| { 41 .flat_map(|(file_id, file)| {
40 file_symbols(&file) 42 file_symbols(&file)
@@ -51,7 +53,7 @@ impl SymbolIndex {
51 SymbolIndex { symbols, map } 53 SymbolIndex { symbols, map }
52 } 54 }
53 55
54 pub(crate) fn for_file(file_id: FileId, file: File) -> SymbolIndex { 56 pub(crate) fn for_file(file_id: FileId, file: SourceFileNode) -> SymbolIndex {
55 SymbolIndex::for_files(rayon::iter::once((file_id, file))) 57 SymbolIndex::for_files(rayon::iter::once((file_id, file)))
56 } 58 }
57} 59}
diff --git a/crates/ra_analysis/src/syntax_ptr.rs b/crates/ra_analysis/src/syntax_ptr.rs
index 4afb1fc93..194b94584 100644
--- a/crates/ra_analysis/src/syntax_ptr.rs
+++ b/crates/ra_analysis/src/syntax_ptr.rs
@@ -1,4 +1,4 @@
1use ra_syntax::{File, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange}; 1use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange};
2 2
3use crate::db::SyntaxDatabase; 3use crate::db::SyntaxDatabase;
4use crate::FileId; 4use crate::FileId;
@@ -43,7 +43,7 @@ impl LocalSyntaxPtr {
43 } 43 }
44 } 44 }
45 45
46 pub(crate) fn resolve(self, file: &File) -> SyntaxNode { 46 pub(crate) fn resolve(self, file: &SourceFileNode) -> SyntaxNode {
47 let mut curr = file.syntax(); 47 let mut curr = file.syntax();
48 loop { 48 loop {
49 if curr.range() == self.range && curr.kind() == self.kind { 49 if curr.range() == self.range && curr.kind() == self.kind {
@@ -62,12 +62,17 @@ impl LocalSyntaxPtr {
62 local: self, 62 local: self,
63 } 63 }
64 } 64 }
65
66 // Seems unfortunate to expose
67 pub(crate) fn range(self) -> TextRange {
68 self.range
69 }
65} 70}
66 71
67#[test] 72#[test]
68fn test_local_syntax_ptr() { 73fn test_local_syntax_ptr() {
69 use ra_syntax::{ast, AstNode}; 74 use ra_syntax::{ast, AstNode};
70 let file = File::parse("struct Foo { f: u32, }"); 75 let file = SourceFileNode::parse("struct Foo { f: u32, }");
71 let field = file 76 let field = file
72 .syntax() 77 .syntax()
73 .descendants() 78 .descendants()
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs
index c605d34f0..719c166b5 100644
--- a/crates/ra_analysis/tests/tests.rs
+++ b/crates/ra_analysis/tests/tests.rs
@@ -452,3 +452,44 @@ fn test_complete_crate_path() {
452 &completions, 452 &completions,
453 ); 453 );
454} 454}
455
456#[test]
457fn test_complete_crate_path_with_braces() {
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: "foo", lookup: None, snippet: None },
470 CompletionItem { label: "Spam", lookup: None, snippet: None }]"#,
471 &completions,
472 );
473}
474
475#[test]
476fn test_complete_crate_path_in_nested_tree() {
477 let (analysis, position) = analysis_and_position(
478 "
479 //- /lib.rs
480 mod foo;
481 pub mod bar {
482 pub mod baz {
483 pub struct Spam;
484 }
485 }
486 //- /foo.rs
487 use crate::{bar::{baz::Sp<|>}};
488 ",
489 );
490 let completions = analysis.completions(position).unwrap().unwrap();
491 assert_eq_dbg(
492 r#"[CompletionItem { label: "Spam", lookup: None, snippet: None }]"#,
493 &completions,
494 );
495}
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 239d846b3..5ca86df4d 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -11,7 +11,7 @@ use std::{fs, io::Read, path::Path, time::Instant};
11use clap::{App, Arg, SubCommand}; 11use clap::{App, Arg, SubCommand};
12use join_to_string::join; 12use join_to_string::join;
13use ra_editor::{extend_selection, file_structure, syntax_tree}; 13use ra_editor::{extend_selection, file_structure, syntax_tree};
14use ra_syntax::{File, TextRange}; 14use ra_syntax::{SourceFileNode, TextRange};
15use tools::collect_tests; 15use tools::collect_tests;
16 16
17type Result<T> = ::std::result::Result<T, failure::Error>; 17type Result<T> = ::std::result::Result<T, failure::Error>;
@@ -79,9 +79,9 @@ fn main() -> Result<()> {
79 Ok(()) 79 Ok(())
80} 80}
81 81
82fn file() -> Result<File> { 82fn file() -> Result<SourceFileNode> {
83 let text = read_stdin()?; 83 let text = read_stdin()?;
84 Ok(File::parse(&text)) 84 Ok(SourceFileNode::parse(&text))
85} 85}
86 86
87fn read_stdin() -> Result<String> { 87fn read_stdin() -> Result<String> {
@@ -100,12 +100,12 @@ fn render_test(file: &Path, line: usize) -> Result<(String, String)> {
100 None => bail!("No test found at line {} at {}", line, file.display()), 100 None => bail!("No test found at line {} at {}", line, file.display()),
101 Some((_start_line, test)) => test, 101 Some((_start_line, test)) => test,
102 }; 102 };
103 let file = File::parse(&test.text); 103 let file = SourceFileNode::parse(&test.text);
104 let tree = syntax_tree(&file); 104 let tree = syntax_tree(&file);
105 Ok((test.text, tree)) 105 Ok((test.text, tree))
106} 106}
107 107
108fn selections(file: &File, start: u32, end: u32) -> String { 108fn selections(file: &SourceFileNode, start: u32, end: u32) -> String {
109 let mut ranges = Vec::new(); 109 let mut ranges = Vec::new();
110 let mut cur = Some(TextRange::from_to((start - 1).into(), (end - 1).into())); 110 let mut cur = Some(TextRange::from_to((start - 1).into(), (end - 1).into()));
111 while let Some(r) = cur { 111 while let Some(r) = cur {
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs
index ef6df0d53..0139b19d3 100644
--- a/crates/ra_editor/src/code_actions.rs
+++ b/crates/ra_editor/src/code_actions.rs
@@ -3,7 +3,7 @@ use join_to_string::join;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{find_covering_node, find_leaf_at_offset}, 4 algo::{find_covering_node, find_leaf_at_offset},
5 ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, 5 ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
6 Direction, File, 6 Direction, SourceFileNode,
7 SyntaxKind::{COMMA, WHITESPACE}, 7 SyntaxKind::{COMMA, WHITESPACE},
8 SyntaxNodeRef, TextRange, TextUnit, 8 SyntaxNodeRef, TextRange, TextUnit,
9}; 9};
@@ -16,7 +16,10 @@ pub struct LocalEdit {
16 pub cursor_position: Option<TextUnit>, 16 pub cursor_position: Option<TextUnit>,
17} 17}
18 18
19pub fn flip_comma<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> LocalEdit + 'a> { 19pub fn flip_comma<'a>(
20 file: &'a SourceFileNode,
21 offset: TextUnit,
22) -> Option<impl FnOnce() -> LocalEdit + 'a> {
20 let syntax = file.syntax(); 23 let syntax = file.syntax();
21 24
22 let comma = find_leaf_at_offset(syntax, offset).find(|leaf| leaf.kind() == COMMA)?; 25 let comma = find_leaf_at_offset(syntax, offset).find(|leaf| leaf.kind() == COMMA)?;
@@ -33,7 +36,10 @@ pub fn flip_comma<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce()
33 }) 36 })
34} 37}
35 38
36pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> LocalEdit + 'a> { 39pub fn add_derive<'a>(
40 file: &'a SourceFileNode,
41 offset: TextUnit,
42) -> Option<impl FnOnce() -> LocalEdit + 'a> {
37 let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?; 43 let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?;
38 Some(move || { 44 Some(move || {
39 let derive_attr = nominal 45 let derive_attr = nominal
@@ -58,7 +64,10 @@ pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce()
58 }) 64 })
59} 65}
60 66
61pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> LocalEdit + 'a> { 67pub fn add_impl<'a>(
68 file: &'a SourceFileNode,
69 offset: TextUnit,
70) -> Option<impl FnOnce() -> LocalEdit + 'a> {
62 let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?; 71 let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?;
63 let name = nominal.name()?; 72 let name = nominal.name()?;
64 73
@@ -98,7 +107,7 @@ pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() ->
98} 107}
99 108
100pub fn introduce_variable<'a>( 109pub fn introduce_variable<'a>(
101 file: &'a File, 110 file: &'a SourceFileNode,
102 range: TextRange, 111 range: TextRange,
103) -> Option<impl FnOnce() -> LocalEdit + 'a> { 112) -> Option<impl FnOnce() -> LocalEdit + 'a> {
104 let node = find_covering_node(file.syntax(), range); 113 let node = find_covering_node(file.syntax(), range);
diff --git a/crates/ra_editor/src/extend_selection.rs b/crates/ra_editor/src/extend_selection.rs
index 9d8df25c3..8f11d5364 100644
--- a/crates/ra_editor/src/extend_selection.rs
+++ b/crates/ra_editor/src/extend_selection.rs
@@ -1,11 +1,11 @@
1use ra_syntax::{ 1use ra_syntax::{
2 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, 2 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
3 Direction, File, 3 Direction, SourceFileNode,
4 SyntaxKind::*, 4 SyntaxKind::*,
5 SyntaxNodeRef, TextRange, TextUnit, 5 SyntaxNodeRef, TextRange, TextUnit,
6}; 6};
7 7
8pub fn extend_selection(file: &File, range: TextRange) -> Option<TextRange> { 8pub fn extend_selection(file: &SourceFileNode, range: TextRange) -> Option<TextRange> {
9 let syntax = file.syntax(); 9 let syntax = file.syntax();
10 extend(syntax.borrowed(), range) 10 extend(syntax.borrowed(), range)
11} 11}
@@ -120,7 +120,7 @@ mod tests {
120 120
121 fn do_check(before: &str, afters: &[&str]) { 121 fn do_check(before: &str, afters: &[&str]) {
122 let (cursor, before) = extract_offset(before); 122 let (cursor, before) = extract_offset(before);
123 let file = File::parse(&before); 123 let file = SourceFileNode::parse(&before);
124 let mut range = TextRange::offset_len(cursor, 0.into()); 124 let mut range = TextRange::offset_len(cursor, 0.into());
125 for &after in afters { 125 for &after in afters {
126 range = extend_selection(&file, range).unwrap(); 126 range = extend_selection(&file, range).unwrap();
diff --git a/crates/ra_editor/src/folding_ranges.rs b/crates/ra_editor/src/folding_ranges.rs
index 0803c8891..2a8fa3cda 100644
--- a/crates/ra_editor/src/folding_ranges.rs
+++ b/crates/ra_editor/src/folding_ranges.rs
@@ -1,7 +1,7 @@
1use rustc_hash::FxHashSet; 1use rustc_hash::FxHashSet;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast, AstNode, Direction, File, 4 ast, AstNode, Direction, SourceFileNode,
5 SyntaxKind::{self, *}, 5 SyntaxKind::{self, *},
6 SyntaxNodeRef, TextRange, 6 SyntaxNodeRef, TextRange,
7}; 7};
@@ -18,7 +18,7 @@ pub struct Fold {
18 pub kind: FoldKind, 18 pub kind: FoldKind,
19} 19}
20 20
21pub fn folding_ranges(file: &File) -> Vec<Fold> { 21pub fn folding_ranges(file: &SourceFileNode) -> Vec<Fold> {
22 let mut res = vec![]; 22 let mut res = vec![];
23 let mut visited_comments = FxHashSet::default(); 23 let mut visited_comments = FxHashSet::default();
24 let mut visited_imports = FxHashSet::default(); 24 let mut visited_imports = FxHashSet::default();
@@ -171,7 +171,7 @@ mod tests {
171 171
172 fn do_check(text: &str, fold_kinds: &[FoldKind]) { 172 fn do_check(text: &str, fold_kinds: &[FoldKind]) {
173 let (ranges, text) = extract_ranges(text); 173 let (ranges, text) = extract_ranges(text);
174 let file = File::parse(&text); 174 let file = SourceFileNode::parse(&text);
175 let folds = folding_ranges(&file); 175 let folds = folding_ranges(&file);
176 176
177 assert_eq!( 177 assert_eq!(
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index f92181b86..ff4e8303d 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -30,7 +30,7 @@ pub use ra_syntax::AtomEdit;
30use ra_syntax::{ 30use ra_syntax::{
31 algo::find_leaf_at_offset, 31 algo::find_leaf_at_offset,
32 ast::{self, AstNode, NameOwner}, 32 ast::{self, AstNode, NameOwner},
33 File, 33 SourceFileNode,
34 Location, 34 Location,
35 SyntaxKind::{self, *}, 35 SyntaxKind::{self, *},
36 SyntaxNodeRef, TextRange, TextUnit, 36 SyntaxNodeRef, TextRange, TextUnit,
@@ -60,7 +60,7 @@ pub enum RunnableKind {
60 Bin, 60 Bin,
61} 61}
62 62
63pub fn matching_brace(file: &File, offset: TextUnit) -> Option<TextUnit> { 63pub fn matching_brace(file: &SourceFileNode, offset: TextUnit) -> Option<TextUnit> {
64 const BRACES: &[SyntaxKind] = &[ 64 const BRACES: &[SyntaxKind] = &[
65 L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE, 65 L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE,
66 ]; 66 ];
@@ -78,7 +78,7 @@ pub fn matching_brace(file: &File, offset: TextUnit) -> Option<TextUnit> {
78 Some(matching_node.range().start()) 78 Some(matching_node.range().start())
79} 79}
80 80
81pub fn highlight(file: &File) -> Vec<HighlightedRange> { 81pub fn highlight(file: &SourceFileNode) -> Vec<HighlightedRange> {
82 let mut res = Vec::new(); 82 let mut res = Vec::new();
83 for node in file.syntax().descendants() { 83 for node in file.syntax().descendants() {
84 let tag = match node.kind() { 84 let tag = match node.kind() {
@@ -100,7 +100,7 @@ pub fn highlight(file: &File) -> Vec<HighlightedRange> {
100 res 100 res
101} 101}
102 102
103pub fn diagnostics(file: &File) -> Vec<Diagnostic> { 103pub fn diagnostics(file: &SourceFileNode) -> Vec<Diagnostic> {
104 fn location_to_range(location: Location) -> TextRange { 104 fn location_to_range(location: Location) -> TextRange {
105 match location { 105 match location {
106 Location::Offset(offset) => TextRange::offset_len(offset, 1.into()), 106 Location::Offset(offset) => TextRange::offset_len(offset, 1.into()),
@@ -117,11 +117,11 @@ pub fn diagnostics(file: &File) -> Vec<Diagnostic> {
117 .collect() 117 .collect()
118} 118}
119 119
120pub fn syntax_tree(file: &File) -> String { 120pub fn syntax_tree(file: &SourceFileNode) -> String {
121 ::ra_syntax::utils::dump_tree(file.syntax()) 121 ::ra_syntax::utils::dump_tree(file.syntax())
122} 122}
123 123
124pub fn runnables(file: &File) -> Vec<Runnable> { 124pub fn runnables(file: &SourceFileNode) -> Vec<Runnable> {
125 file.syntax() 125 file.syntax()
126 .descendants() 126 .descendants()
127 .filter_map(ast::FnDef::cast) 127 .filter_map(ast::FnDef::cast)
@@ -163,7 +163,7 @@ mod tests {
163 163
164 #[test] 164 #[test]
165 fn test_highlighting() { 165 fn test_highlighting() {
166 let file = File::parse( 166 let file = SourceFileNode::parse(
167 r#" 167 r#"
168// comment 168// comment
169fn main() {} 169fn main() {}
@@ -184,7 +184,7 @@ fn main() {}
184 184
185 #[test] 185 #[test]
186 fn test_runnables() { 186 fn test_runnables() {
187 let file = File::parse( 187 let file = SourceFileNode::parse(
188 r#" 188 r#"
189fn main() {} 189fn main() {}
190 190
@@ -209,7 +209,7 @@ fn test_foo() {}
209 fn test_matching_brace() { 209 fn test_matching_brace() {
210 fn do_check(before: &str, after: &str) { 210 fn do_check(before: &str, after: &str) {
211 let (pos, before) = extract_offset(before); 211 let (pos, before) = extract_offset(before);
212 let file = File::parse(&before); 212 let file = SourceFileNode::parse(&before);
213 let new_pos = match matching_brace(&file, pos) { 213 let new_pos = match matching_brace(&file, pos) {
214 None => pos, 214 None => pos,
215 Some(pos) => pos, 215 Some(pos) => pos,
diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs
index 4e602d0e3..6d3b0514a 100644
--- a/crates/ra_editor/src/symbols.rs
+++ b/crates/ra_editor/src/symbols.rs
@@ -2,8 +2,8 @@ use crate::TextRange;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 algo::visit::{visitor, Visitor}, 4 algo::visit::{visitor, Visitor},
5 ast::{self, NameOwner}, 5 ast::{self, DocCommentsOwner, NameOwner},
6 AstNode, File, SmolStr, SyntaxKind, SyntaxNodeRef, WalkEvent, 6 AstNode, SourceFileNode, SmolStr, SyntaxKind, SyntaxNodeRef, WalkEvent,
7}; 7};
8 8
9#[derive(Debug, Clone)] 9#[derive(Debug, Clone)]
@@ -22,7 +22,37 @@ pub struct FileSymbol {
22 pub kind: SyntaxKind, 22 pub kind: SyntaxKind,
23} 23}
24 24
25pub fn file_symbols(file: &File) -> Vec<FileSymbol> { 25impl FileSymbol {
26 pub fn docs(&self, file: &SourceFileNode) -> Option<String> {
27 file.syntax()
28 .descendants()
29 .filter(|node| node.kind() == self.kind && node.range() == self.node_range)
30 .filter_map(|node: SyntaxNodeRef| {
31 fn doc_comments<'a, N: DocCommentsOwner<'a>>(node: N) -> Option<String> {
32 let comments = node.doc_comment_text();
33 if comments.is_empty() {
34 None
35 } else {
36 Some(comments)
37 }
38 }
39
40 visitor()
41 .visit(doc_comments::<ast::FnDef>)
42 .visit(doc_comments::<ast::StructDef>)
43 .visit(doc_comments::<ast::EnumDef>)
44 .visit(doc_comments::<ast::TraitDef>)
45 .visit(doc_comments::<ast::Module>)
46 .visit(doc_comments::<ast::TypeDef>)
47 .visit(doc_comments::<ast::ConstDef>)
48 .visit(doc_comments::<ast::StaticDef>)
49 .accept(node)?
50 })
51 .nth(0)
52 }
53}
54
55pub fn file_symbols(file: &SourceFileNode) -> Vec<FileSymbol> {
26 file.syntax().descendants().filter_map(to_symbol).collect() 56 file.syntax().descendants().filter_map(to_symbol).collect()
27} 57}
28 58
@@ -47,7 +77,7 @@ fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
47 .accept(node)? 77 .accept(node)?
48} 78}
49 79
50pub fn file_structure(file: &File) -> Vec<StructureNode> { 80pub fn file_structure(file: &SourceFileNode) -> Vec<StructureNode> {
51 let mut res = Vec::new(); 81 let mut res = Vec::new();
52 let mut stack = Vec::new(); 82 let mut stack = Vec::new();
53 83
@@ -123,7 +153,7 @@ mod tests {
123 153
124 #[test] 154 #[test]
125 fn test_file_structure() { 155 fn test_file_structure() {
126 let file = File::parse( 156 let file = SourceFileNode::parse(
127 r#" 157 r#"
128struct Foo { 158struct Foo {
129 x: i32 159 x: i32
diff --git a/crates/ra_editor/src/test_utils.rs b/crates/ra_editor/src/test_utils.rs
index bc3d700f6..cbeb6433b 100644
--- a/crates/ra_editor/src/test_utils.rs
+++ b/crates/ra_editor/src/test_utils.rs
@@ -1,10 +1,14 @@
1use crate::LocalEdit; 1use crate::LocalEdit;
2pub use crate::_test_utils::*; 2pub use crate::_test_utils::*;
3use ra_syntax::{File, TextRange, TextUnit}; 3use ra_syntax::{SourceFileNode, TextRange, TextUnit};
4 4
5pub fn check_action<F: Fn(&File, TextUnit) -> Option<LocalEdit>>(before: &str, after: &str, f: F) { 5pub fn check_action<F: Fn(&SourceFileNode, TextUnit) -> Option<LocalEdit>>(
6 before: &str,
7 after: &str,
8 f: F,
9) {
6 let (before_cursor_pos, before) = extract_offset(before); 10 let (before_cursor_pos, before) = extract_offset(before);
7 let file = File::parse(&before); 11 let file = SourceFileNode::parse(&before);
8 let result = f(&file, before_cursor_pos).expect("code action is not applicable"); 12 let result = f(&file, before_cursor_pos).expect("code action is not applicable");
9 let actual = result.edit.apply(&before); 13 let actual = result.edit.apply(&before);
10 let actual_cursor_pos = match result.cursor_position { 14 let actual_cursor_pos = match result.cursor_position {
@@ -15,13 +19,13 @@ pub fn check_action<F: Fn(&File, TextUnit) -> Option<LocalEdit>>(before: &str, a
15 assert_eq_text!(after, &actual); 19 assert_eq_text!(after, &actual);
16} 20}
17 21
18pub fn check_action_range<F: Fn(&File, TextRange) -> Option<LocalEdit>>( 22pub fn check_action_range<F: Fn(&SourceFileNode, TextRange) -> Option<LocalEdit>>(
19 before: &str, 23 before: &str,
20 after: &str, 24 after: &str,
21 f: F, 25 f: F,
22) { 26) {
23 let (range, before) = extract_range(before); 27 let (range, before) = extract_range(before);
24 let file = File::parse(&before); 28 let file = SourceFileNode::parse(&before);
25 let result = f(&file, range).expect("code action is not applicable"); 29 let result = f(&file, range).expect("code action is not applicable");
26 let actual = result.edit.apply(&before); 30 let actual = result.edit.apply(&before);
27 let actual_cursor_pos = match result.cursor_position { 31 let actual_cursor_pos = match result.cursor_position {
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 5a457d148..f894d8392 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -4,14 +4,14 @@ use ra_syntax::{
4 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, 4 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
5 ast, 5 ast,
6 text_utils::{contains_offset_nonstrict, intersect}, 6 text_utils::{contains_offset_nonstrict, intersect},
7 AstNode, File, SyntaxKind, 7 AstNode, SourceFileNode, SyntaxKind,
8 SyntaxKind::*, 8 SyntaxKind::*,
9 SyntaxNodeRef, TextRange, TextUnit, 9 SyntaxNodeRef, TextRange, TextUnit,
10}; 10};
11 11
12use crate::{find_node_at_offset, EditBuilder, LocalEdit}; 12use crate::{find_node_at_offset, EditBuilder, LocalEdit};
13 13
14pub fn join_lines(file: &File, range: TextRange) -> LocalEdit { 14pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
15 let range = if range.is_empty() { 15 let range = if range.is_empty() {
16 let syntax = file.syntax(); 16 let syntax = file.syntax();
17 let text = syntax.text().slice(range.start()..); 17 let text = syntax.text().slice(range.start()..);
@@ -55,7 +55,7 @@ pub fn join_lines(file: &File, range: TextRange) -> LocalEdit {
55 } 55 }
56} 56}
57 57
58pub fn on_enter(file: &File, offset: TextUnit) -> Option<LocalEdit> { 58pub fn on_enter(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> {
59 let comment = find_leaf_at_offset(file.syntax(), offset) 59 let comment = find_leaf_at_offset(file.syntax(), offset)
60 .left_biased() 60 .left_biased()
61 .and_then(ast::Comment::cast)?; 61 .and_then(ast::Comment::cast)?;
@@ -80,7 +80,7 @@ pub fn on_enter(file: &File, offset: TextUnit) -> Option<LocalEdit> {
80 }) 80 })
81} 81}
82 82
83fn node_indent<'a>(file: &'a File, node: SyntaxNodeRef) -> Option<&'a str> { 83fn node_indent<'a>(file: &'a SourceFileNode, node: SyntaxNodeRef) -> Option<&'a str> {
84 let ws = match find_leaf_at_offset(file.syntax(), node.range().start()) { 84 let ws = match find_leaf_at_offset(file.syntax(), node.range().start()) {
85 LeafAtOffset::Between(l, r) => { 85 LeafAtOffset::Between(l, r) => {
86 assert!(r == node); 86 assert!(r == node);
@@ -100,7 +100,7 @@ fn node_indent<'a>(file: &'a File, node: SyntaxNodeRef) -> Option<&'a str> {
100 Some(&text[pos..]) 100 Some(&text[pos..])
101} 101}
102 102
103pub fn on_eq_typed(file: &File, offset: TextUnit) -> Option<LocalEdit> { 103pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> {
104 let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?; 104 let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?;
105 if let_stmt.has_semi() { 105 if let_stmt.has_semi() {
106 return None; 106 return None;
@@ -390,7 +390,7 @@ fn foo() {
390 390
391 fn check_join_lines_sel(before: &str, after: &str) { 391 fn check_join_lines_sel(before: &str, after: &str) {
392 let (sel, before) = extract_range(before); 392 let (sel, before) = extract_range(before);
393 let file = File::parse(&before); 393 let file = SourceFileNode::parse(&before);
394 let result = join_lines(&file, sel); 394 let result = join_lines(&file, sel);
395 let actual = result.edit.apply(&before); 395 let actual = result.edit.apply(&before);
396 assert_eq_text!(after, &actual); 396 assert_eq_text!(after, &actual);
@@ -469,7 +469,7 @@ pub fn handle_find_matching_brace() {
469 fn test_on_eq_typed() { 469 fn test_on_eq_typed() {
470 fn do_check(before: &str, after: &str) { 470 fn do_check(before: &str, after: &str) {
471 let (offset, before) = extract_offset(before); 471 let (offset, before) = extract_offset(before);
472 let file = File::parse(&before); 472 let file = SourceFileNode::parse(&before);
473 let result = on_eq_typed(&file, offset).unwrap(); 473 let result = on_eq_typed(&file, offset).unwrap();
474 let actual = result.edit.apply(&before); 474 let actual = result.edit.apply(&before);
475 assert_eq_text!(after, &actual); 475 assert_eq_text!(after, &actual);
@@ -513,7 +513,7 @@ fn foo() {
513 fn test_on_enter() { 513 fn test_on_enter() {
514 fn apply_on_enter(before: &str) -> Option<String> { 514 fn apply_on_enter(before: &str) -> Option<String> {
515 let (offset, before) = extract_offset(before); 515 let (offset, before) = extract_offset(before);
516 let file = File::parse(&before); 516 let file = SourceFileNode::parse(&before);
517 let result = on_enter(&file, offset)?; 517 let result = on_enter(&file, offset)?;
518 let actual = result.edit.apply(&before); 518 let actual = result.edit.apply(&before);
519 let actual = add_cursor(&actual, result.cursor_position.unwrap()); 519 let actual = add_cursor(&actual, result.cursor_position.unwrap());
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index f29dafc17..79d86f9b2 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -14,7 +14,7 @@ serde = "1.0.71"
14serde_derive = "1.0.71" 14serde_derive = "1.0.71"
15drop_bomb = "0.1.0" 15drop_bomb = "0.1.0"
16crossbeam-channel = "0.2.4" 16crossbeam-channel = "0.2.4"
17flexi_logger = "0.9.1" 17flexi_logger = "0.10.0"
18log = "0.4.3" 18log = "0.4.3"
19url_serde = "0.2.0" 19url_serde = "0.2.0"
20languageserver-types = "0.51.0" 20languageserver-types = "0.51.0"
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index 0d02c8073..bcf857fce 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -16,7 +16,7 @@ pub fn server_capabilities() -> ServerCapabilities {
16 save: None, 16 save: None,
17 }, 17 },
18 )), 18 )),
19 hover_provider: None, 19 hover_provider: Some(true),
20 completion_provider: Some(CompletionOptions { 20 completion_provider: Some(CompletionOptions {
21 resolve_provider: None, 21 resolve_provider: None,
22 trigger_characters: None, 22 trigger_characters: None,
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index fa04f4b00..e5a2449c2 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -2,7 +2,7 @@ use languageserver_types::{
2 Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, 2 Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
3 TextDocumentItem, TextDocumentPositionParams, TextEdit, Url, VersionedTextDocumentIdentifier, 3 TextDocumentItem, TextDocumentPositionParams, TextEdit, Url, VersionedTextDocumentIdentifier,
4}; 4};
5use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileEdit, FilePosition}; 5use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition};
6use ra_editor::{AtomEdit, Edit, LineCol, LineIndex}; 6use ra_editor::{AtomEdit, Edit, LineCol, LineIndex};
7use ra_syntax::{SyntaxKind, TextRange, TextUnit}; 7use ra_syntax::{SyntaxKind, TextRange, TextUnit};
8 8
@@ -257,7 +257,7 @@ fn translate_offset_with_edit(
257 } 257 }
258} 258}
259 259
260impl TryConvWith for SourceFileEdit { 260impl TryConvWith for SourceFileNodeEdit {
261 type Ctx = ServerWorld; 261 type Ctx = ServerWorld;
262 type Output = TextDocumentEdit; 262 type Output = TextDocumentEdit;
263 fn try_conv_with(self, world: &ServerWorld) -> Result<TextDocumentEdit> { 263 fn try_conv_with(self, world: &ServerWorld) -> Result<TextDocumentEdit> {
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index c07eb0140..26bcddd8e 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -2,10 +2,14 @@
2extern crate log; 2extern crate log;
3#[macro_use] 3#[macro_use]
4extern crate failure; 4extern crate failure;
5#[macro_use]
6extern crate serde_derive;
7extern crate serde;
5extern crate flexi_logger; 8extern crate flexi_logger;
6extern crate gen_lsp_server; 9extern crate gen_lsp_server;
7extern crate ra_lsp_server; 10extern crate ra_lsp_server;
8 11
12use serde::Deserialize;
9use flexi_logger::{Duplicate, Logger}; 13use flexi_logger::{Duplicate, Logger};
10use gen_lsp_server::{run_server, stdio_transport}; 14use gen_lsp_server::{run_server, stdio_transport};
11use ra_lsp_server::Result; 15use ra_lsp_server::Result;
@@ -30,6 +34,12 @@ fn main() -> Result<()> {
30 } 34 }
31} 35}
32 36
37#[derive(Deserialize)]
38#[serde(rename_all = "camelCase")]
39struct InitializationOptions {
40 publish_decorations: bool,
41}
42
33fn main_inner() -> Result<()> { 43fn main_inner() -> Result<()> {
34 let (receiver, sender, threads) = stdio_transport(); 44 let (receiver, sender, threads) = stdio_transport();
35 let cwd = ::std::env::current_dir()?; 45 let cwd = ::std::env::current_dir()?;
@@ -42,7 +52,12 @@ fn main_inner() -> Result<()> {
42 .root_uri 52 .root_uri
43 .and_then(|it| it.to_file_path().ok()) 53 .and_then(|it| it.to_file_path().ok())
44 .unwrap_or(cwd); 54 .unwrap_or(cwd);
45 ra_lsp_server::main_loop(false, root, r, s) 55 let publish_decorations = params
56 .initialization_options
57 .and_then(|v| InitializationOptions::deserialize(v).ok())
58 .map(|it| it.publish_decorations)
59 == Some(true);
60 ra_lsp_server::main_loop(false, root, publish_decorations, r, s)
46 }, 61 },
47 )?; 62 )?;
48 info!("shutting down IO..."); 63 info!("shutting down IO...");
@@ -50,3 +65,27 @@ fn main_inner() -> Result<()> {
50 info!("... IO is down"); 65 info!("... IO is down");
51 Ok(()) 66 Ok(())
52} 67}
68
69/*
70 (let ((backend (eglot-xref-backend)))
71 (mapcar
72 (lambda (xref)
73 (let ((loc (xref-item-location xref)))
74 (propertize
75 (concat
76 (when (xref-file-location-p loc)
77 (with-slots (file line column) loc
78 (format "%s:%s:%s:"
79 (propertize (file-relative-name file)
80 'face 'compilation-info)
81 (propertize (format "%s" line)
82 'face 'compilation-line
83 )
84 column)))
85 (xref-item-summary xref))
86 'xref xref)))
87 (xref-backend-apropos backend "Analysis"))
88 )
89
90
91*/
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 5314a333e..c872b0dc4 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -4,9 +4,9 @@ use gen_lsp_server::ErrorCode;
4use languageserver_types::{ 4use languageserver_types::{
5 CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, 5 CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic,
6 DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, 6 DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind,
7 FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, Position, 7 FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, MarkedString, Position,
8 PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, 8 PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit,
9 WorkspaceEdit, ParameterInformation, SignatureInformation, 9 WorkspaceEdit, ParameterInformation, SignatureInformation, Hover, HoverContents,
10}; 10};
11use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition}; 11use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition};
12use ra_syntax::text_utils::contains_offset_nonstrict; 12use ra_syntax::text_utils::contains_offset_nonstrict;
@@ -478,6 +478,30 @@ pub fn handle_signature_help(
478 } 478 }
479} 479}
480 480
481pub fn handle_hover(
482 world: ServerWorld,
483 params: req::TextDocumentPositionParams,
484) -> Result<Option<Hover>> {
485 let position = params.try_conv_with(&world)?;
486 let line_index = world.analysis().file_line_index(position.file_id);
487
488 for (file_id, symbol) in world.analysis().approximately_resolve_symbol(position)? {
489 let range = symbol.node_range.conv_with(&line_index);
490 let comment = world.analysis.doc_comment_for(file_id, symbol)?;
491
492 if comment.is_some() {
493 let contents = HoverContents::Scalar(MarkedString::String(comment.unwrap()));
494
495 return Ok(Some(Hover {
496 contents,
497 range: Some(range),
498 }));
499 }
500 }
501
502 Ok(None)
503}
504
481pub fn handle_prepare_rename( 505pub fn handle_prepare_rename(
482 world: ServerWorld, 506 world: ServerWorld,
483 params: req::TextDocumentPositionParams, 507 params: req::TextDocumentPositionParams,
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs
index 229d1b0f7..78d93741a 100644
--- a/crates/ra_lsp_server/src/main_loop/mod.rs
+++ b/crates/ra_lsp_server/src/main_loop/mod.rs
@@ -48,6 +48,7 @@ enum Task {
48pub fn main_loop( 48pub fn main_loop(
49 internal_mode: bool, 49 internal_mode: bool,
50 root: PathBuf, 50 root: PathBuf,
51 publish_decorations: bool,
51 msg_receiver: &Receiver<RawMessage>, 52 msg_receiver: &Receiver<RawMessage>,
52 msg_sender: &Sender<RawMessage>, 53 msg_sender: &Sender<RawMessage>,
53) -> Result<()> { 54) -> Result<()> {
@@ -67,6 +68,7 @@ pub fn main_loop(
67 let mut subs = Subscriptions::new(); 68 let mut subs = Subscriptions::new();
68 let main_res = main_loop_inner( 69 let main_res = main_loop_inner(
69 internal_mode, 70 internal_mode,
71 publish_decorations,
70 root, 72 root,
71 &pool, 73 &pool,
72 msg_sender, 74 msg_sender,
@@ -99,6 +101,7 @@ pub fn main_loop(
99 101
100fn main_loop_inner( 102fn main_loop_inner(
101 internal_mode: bool, 103 internal_mode: bool,
104 publish_decorations: bool,
102 ws_root: PathBuf, 105 ws_root: PathBuf,
103 pool: &ThreadPool, 106 pool: &ThreadPool,
104 msg_sender: &Sender<RawMessage>, 107 msg_sender: &Sender<RawMessage>,
@@ -210,6 +213,7 @@ fn main_loop_inner(
210 update_file_notifications_on_threadpool( 213 update_file_notifications_on_threadpool(
211 pool, 214 pool,
212 state.snapshot(), 215 state.snapshot(),
216 publish_decorations,
213 task_sender.clone(), 217 task_sender.clone(),
214 subs.subscriptions(), 218 subs.subscriptions(),
215 ) 219 )
@@ -259,6 +263,7 @@ fn on_request(
259 .on::<req::CodeActionRequest>(handlers::handle_code_action)? 263 .on::<req::CodeActionRequest>(handlers::handle_code_action)?
260 .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)? 264 .on::<req::FoldingRangeRequest>(handlers::handle_folding_range)?
261 .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)? 265 .on::<req::SignatureHelpRequest>(handlers::handle_signature_help)?
266 .on::<req::HoverRequest>(handlers::handle_hover)?
262 .on::<req::PrepareRenameRequest>(handlers::handle_prepare_rename)? 267 .on::<req::PrepareRenameRequest>(handlers::handle_prepare_rename)?
263 .on::<req::Rename>(handlers::handle_rename)? 268 .on::<req::Rename>(handlers::handle_rename)?
264 .on::<req::References>(handlers::handle_references)? 269 .on::<req::References>(handlers::handle_references)?
@@ -415,6 +420,7 @@ impl<'a> PoolDispatcher<'a> {
415fn update_file_notifications_on_threadpool( 420fn update_file_notifications_on_threadpool(
416 pool: &ThreadPool, 421 pool: &ThreadPool,
417 world: ServerWorld, 422 world: ServerWorld,
423 publish_decorations: bool,
418 sender: Sender<Task>, 424 sender: Sender<Task>,
419 subscriptions: Vec<FileId>, 425 subscriptions: Vec<FileId>,
420) { 426) {
@@ -431,15 +437,17 @@ fn update_file_notifications_on_threadpool(
431 sender.send(Task::Notify(not)); 437 sender.send(Task::Notify(not));
432 } 438 }
433 } 439 }
434 match handlers::publish_decorations(&world, file_id) { 440 if publish_decorations {
435 Err(e) => { 441 match handlers::publish_decorations(&world, file_id) {
436 if !is_canceled(&e) { 442 Err(e) => {
437 error!("failed to compute decorations: {:?}", e); 443 if !is_canceled(&e) {
444 error!("failed to compute decorations: {:?}", e);
445 }
446 }
447 Ok(params) => {
448 let not = RawNotification::new::<req::PublishDecorations>(&params);
449 sender.send(Task::Notify(not))
438 } 450 }
439 }
440 Ok(params) => {
441 let not = RawNotification::new::<req::PublishDecorations>(&params);
442 sender.send(Task::Notify(not))
443 } 451 }
444 } 452 }
445 } 453 }
diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs
index b90d21135..88d379bfa 100644
--- a/crates/ra_lsp_server/tests/heavy_tests/support.rs
+++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs
@@ -55,7 +55,7 @@ impl Server {
55 "test server", 55 "test server",
56 128, 56 128,
57 move |mut msg_receiver, mut msg_sender| { 57 move |mut msg_receiver, mut msg_sender| {
58 main_loop(true, path, &mut msg_receiver, &mut msg_sender).unwrap() 58 main_loop(true, path, true, &mut msg_receiver, &mut msg_sender).unwrap()
59 }, 59 },
60 ); 60 );
61 let res = Server { 61 let res = Server {
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml
index de4b25e67..54ee72386 100644
--- a/crates/ra_syntax/Cargo.toml
+++ b/crates/ra_syntax/Cargo.toml
@@ -8,11 +8,12 @@ description = "Comment and whitespace preserving parser for the Rust langauge"
8repository = "https://github.com/rust-analyzer/rust-analyzer" 8repository = "https://github.com/rust-analyzer/rust-analyzer"
9 9
10[dependencies] 10[dependencies]
11arrayvec = "0.4.7"
11unicode-xid = "0.1.0" 12unicode-xid = "0.1.0"
12itertools = "0.7.8" 13itertools = "0.7.8"
13drop_bomb = "0.1.4" 14drop_bomb = "0.1.4"
14parking_lot = "0.6.0" 15parking_lot = "0.6.0"
15rowan = "0.1.1" 16rowan = "0.1.2"
16text_unit = "0.1.5" 17text_unit = "0.1.5"
17 18
18[dev-dependencies] 19[dev-dependencies]
diff --git a/crates/ra_syntax/src/algo/mod.rs b/crates/ra_syntax/src/algo/mod.rs
index faf5a6211..4b3548ea9 100644
--- a/crates/ra_syntax/src/algo/mod.rs
+++ b/crates/ra_syntax/src/algo/mod.rs
@@ -1,116 +1,19 @@
1pub mod visit; 1pub mod visit;
2// pub mod walk;
3 2
4use crate::{text_utils::contains_offset_nonstrict, SyntaxNodeRef, TextRange, TextUnit}; 3use crate::{SyntaxNode, SyntaxNodeRef, TextRange, TextUnit};
5 4
6pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset { 5pub use rowan::LeafAtOffset;
7 let range = node.range();
8 assert!(
9 contains_offset_nonstrict(range, offset),
10 "Bad offset: range {:?} offset {:?}",
11 range,
12 offset
13 );
14 if range.is_empty() {
15 return LeafAtOffset::None;
16 }
17
18 if node.is_leaf() {
19 return LeafAtOffset::Single(node);
20 }
21
22 let mut children = node.children().filter(|child| {
23 let child_range = child.range();
24 !child_range.is_empty() && contains_offset_nonstrict(child_range, offset)
25 });
26
27 let left = children.next().unwrap();
28 let right = children.next();
29 assert!(children.next().is_none());
30
31 if let Some(right) = right {
32 match (
33 find_leaf_at_offset(left, offset),
34 find_leaf_at_offset(right, offset),
35 ) {
36 (LeafAtOffset::Single(left), LeafAtOffset::Single(right)) => {
37 LeafAtOffset::Between(left, right)
38 }
39 _ => unreachable!(),
40 }
41 } else {
42 find_leaf_at_offset(left, offset)
43 }
44}
45
46#[derive(Clone, Debug)]
47pub enum LeafAtOffset<'a> {
48 None,
49 Single(SyntaxNodeRef<'a>),
50 Between(SyntaxNodeRef<'a>, SyntaxNodeRef<'a>),
51}
52 6
53impl<'a> LeafAtOffset<'a> { 7pub fn find_leaf_at_offset(node: SyntaxNodeRef, offset: TextUnit) -> LeafAtOffset<SyntaxNodeRef> {
54 pub fn right_biased(self) -> Option<SyntaxNodeRef<'a>> { 8 match node.0.leaf_at_offset(offset) {
55 match self { 9 LeafAtOffset::None => LeafAtOffset::None,
56 LeafAtOffset::None => None, 10 LeafAtOffset::Single(n) => LeafAtOffset::Single(SyntaxNode(n)),
57 LeafAtOffset::Single(node) => Some(node), 11 LeafAtOffset::Between(l, r) => LeafAtOffset::Between(SyntaxNode(l), SyntaxNode(r)),
58 LeafAtOffset::Between(_, right) => Some(right),
59 }
60 }
61
62 pub fn left_biased(self) -> Option<SyntaxNodeRef<'a>> {
63 match self {
64 LeafAtOffset::None => None,
65 LeafAtOffset::Single(node) => Some(node),
66 LeafAtOffset::Between(left, _) => Some(left),
67 }
68 }
69}
70
71impl<'f> Iterator for LeafAtOffset<'f> {
72 type Item = SyntaxNodeRef<'f>;
73
74 fn next(&mut self) -> Option<SyntaxNodeRef<'f>> {
75 match *self {
76 LeafAtOffset::None => None,
77 LeafAtOffset::Single(node) => {
78 *self = LeafAtOffset::None;
79 Some(node)
80 }
81 LeafAtOffset::Between(left, right) => {
82 *self = LeafAtOffset::Single(right);
83 Some(left)
84 }
85 }
86 } 12 }
87} 13}
88 14
89pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef { 15pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef {
90 assert!( 16 SyntaxNode(root.0.covering_node(range))
91 range.is_subrange(&root.range()),
92 "node range: {:?}, target range: {:?}",
93 root.range(),
94 range,
95 );
96 let (left, right) = match (
97 find_leaf_at_offset(root, range.start()).right_biased(),
98 find_leaf_at_offset(root, range.end()).left_biased(),
99 ) {
100 (Some(l), Some(r)) => (l, r),
101 _ => return root,
102 };
103
104 common_ancestor(left, right)
105}
106
107fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> {
108 for p in n1.ancestors() {
109 if n2.ancestors().any(|a| a == p) {
110 return p;
111 }
112 }
113 panic!("Can't find common ancestor of {:?} and {:?}", n1, n2)
114} 17}
115 18
116pub fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item = T> { 19pub fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item = T> {
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 75769a4e9..bf056131e 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1,34 +1,36 @@
1// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-syntax` is run 1// This file is automatically generated based on the file `./generated.rs.tera` when `cargo gen-syntax` is run
2// Do not edit manually 2// Do not edit manually
3 3
4//! This module contains auto-generated Rust AST. Like `SyntaxNode`s, AST nodes
5//! are generic over ownership: `X<'a>` things are `Copy` references, `XNode`
6//! are Arc-based. You can switch between the two variants using `.owned` and
7//! `.borrowed` functions. Most of the code works with borowed mode, and only
8//! this mode has all AST accessors.
9
4#![cfg_attr(rustfmt, rustfmt_skip)] 10#![cfg_attr(rustfmt, rustfmt_skip)]
5 11
12use std::hash::{Hash, Hasher};
13
6use crate::{ 14use crate::{
7 ast, 15 ast,
8 SyntaxNode, SyntaxNodeRef, AstNode, 16 SyntaxNode, SyntaxNodeRef, AstNode,
17 yellow::{TreeRoot, RaTypes, OwnedRoot, RefRoot},
9 SyntaxKind::*, 18 SyntaxKind::*,
10}; 19};
11 20
12// ArgList 21// ArgList
13 22#[derive(Debug, Clone, Copy,)]
14#[derive(Debug, Clone)] 23pub struct ArgListNode<R: TreeRoot<RaTypes> = OwnedRoot> {
15pub struct ArgListNode(SyntaxNode); 24 pub(crate) syntax: SyntaxNode<R>,
16
17impl ArgListNode {
18 pub fn ast(&self) -> ArgList {
19 ArgList::cast(self.0.borrowed()).unwrap()
20 }
21} 25}
26pub type ArgList<'a> = ArgListNode<RefRoot<'a>>;
22 27
23impl<'a> From<ArgList<'a>> for ArgListNode { 28impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<ArgListNode<R1>> for ArgListNode<R2> {
24 fn from(ast: ArgList<'a>) -> ArgListNode { 29 fn eq(&self, other: &ArgListNode<R1>) -> bool { self.syntax == other.syntax }
25 let syntax = ast.syntax().owned();
26 ArgListNode(syntax)
27 }
28} 30}
29#[derive(Debug, Clone, Copy)] 31impl<R: TreeRoot<RaTypes>> Eq for ArgListNode<R> {}
30pub struct ArgList<'a> { 32impl<R: TreeRoot<RaTypes>> Hash for ArgListNode<R> {
31 syntax: SyntaxNodeRef<'a>, 33 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
32} 34}
33 35
34impl<'a> AstNode<'a> for ArgList<'a> { 36impl<'a> AstNode<'a> for ArgList<'a> {
@@ -41,6 +43,16 @@ impl<'a> AstNode<'a> for ArgList<'a> {
41 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 43 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
42} 44}
43 45
46impl<R: TreeRoot<RaTypes>> ArgListNode<R> {
47 pub fn borrowed(&self) -> ArgList {
48 ArgListNode { syntax: self.syntax.borrowed() }
49 }
50 pub fn owned(&self) -> ArgListNode {
51 ArgListNode { syntax: self.syntax.owned() }
52 }
53}
54
55
44impl<'a> ArgList<'a> { 56impl<'a> ArgList<'a> {
45 pub fn args(self) -> impl Iterator<Item = Expr<'a>> + 'a { 57 pub fn args(self) -> impl Iterator<Item = Expr<'a>> + 'a {
46 super::children(self) 58 super::children(self)
@@ -48,25 +60,18 @@ impl<'a> ArgList<'a> {
48} 60}
49 61
50// ArrayExpr 62// ArrayExpr
51 63#[derive(Debug, Clone, Copy,)]
52#[derive(Debug, Clone)] 64pub struct ArrayExprNode<R: TreeRoot<RaTypes> = OwnedRoot> {
53pub struct ArrayExprNode(SyntaxNode); 65 pub(crate) syntax: SyntaxNode<R>,
54
55impl ArrayExprNode {
56 pub fn ast(&self) -> ArrayExpr {
57 ArrayExpr::cast(self.0.borrowed()).unwrap()
58 }
59} 66}
67pub type ArrayExpr<'a> = ArrayExprNode<RefRoot<'a>>;
60 68
61impl<'a> From<ArrayExpr<'a>> for ArrayExprNode { 69impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<ArrayExprNode<R1>> for ArrayExprNode<R2> {
62 fn from(ast: ArrayExpr<'a>) -> ArrayExprNode { 70 fn eq(&self, other: &ArrayExprNode<R1>) -> bool { self.syntax == other.syntax }
63 let syntax = ast.syntax().owned();
64 ArrayExprNode(syntax)
65 }
66} 71}
67#[derive(Debug, Clone, Copy)] 72impl<R: TreeRoot<RaTypes>> Eq for ArrayExprNode<R> {}
68pub struct ArrayExpr<'a> { 73impl<R: TreeRoot<RaTypes>> Hash for ArrayExprNode<R> {
69 syntax: SyntaxNodeRef<'a>, 74 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
70} 75}
71 76
72impl<'a> AstNode<'a> for ArrayExpr<'a> { 77impl<'a> AstNode<'a> for ArrayExpr<'a> {
@@ -79,28 +84,31 @@ impl<'a> AstNode<'a> for ArrayExpr<'a> {
79 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 84 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
80} 85}
81 86
82impl<'a> ArrayExpr<'a> {} 87impl<R: TreeRoot<RaTypes>> ArrayExprNode<R> {
88 pub fn borrowed(&self) -> ArrayExpr {
89 ArrayExprNode { syntax: self.syntax.borrowed() }
90 }
91 pub fn owned(&self) -> ArrayExprNode {
92 ArrayExprNode { syntax: self.syntax.owned() }
93 }
94}
83 95
84// ArrayType
85 96
86#[derive(Debug, Clone)] 97impl<'a> ArrayExpr<'a> {}
87pub struct ArrayTypeNode(SyntaxNode);
88 98
89impl ArrayTypeNode { 99// ArrayType
90 pub fn ast(&self) -> ArrayType { 100#[derive(Debug, Clone, Copy,)]
91 ArrayType::cast(self.0.borrowed()).unwrap() 101pub struct ArrayTypeNode<R: TreeRoot<RaTypes> = OwnedRoot> {
92 } 102 pub(crate) syntax: SyntaxNode<R>,
93} 103}
104pub type ArrayType<'a> = ArrayTypeNode<RefRoot<'a>>;
94 105
95impl<'a> From<ArrayType<'a>> for ArrayTypeNode { 106impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<ArrayTypeNode<R1>> for ArrayTypeNode<R2> {
96 fn from(ast: ArrayType<'a>) -> ArrayTypeNode { 107 fn eq(&self, other: &ArrayTypeNode<R1>) -> bool { self.syntax == other.syntax }
97 let syntax = ast.syntax().owned();
98 ArrayTypeNode(syntax)
99 }
100} 108}
101#[derive(Debug, Clone, Copy)] 109impl<R: TreeRoot<RaTypes>> Eq for ArrayTypeNode<R> {}
102pub struct ArrayType<'a> { 110impl<R: TreeRoot<RaTypes>> Hash for ArrayTypeNode<R> {
103 syntax: SyntaxNodeRef<'a>, 111 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
104} 112}
105 113
106impl<'a> AstNode<'a> for ArrayType<'a> { 114impl<'a> AstNode<'a> for ArrayType<'a> {
@@ -113,28 +121,31 @@ impl<'a> AstNode<'a> for ArrayType<'a> {
113 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 121 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
114} 122}
115 123
116impl<'a> ArrayType<'a> {} 124impl<R: TreeRoot<RaTypes>> ArrayTypeNode<R> {
125 pub fn borrowed(&self) -> ArrayType {
126 ArrayTypeNode { syntax: self.syntax.borrowed() }
127 }
128 pub fn owned(&self) -> ArrayTypeNode {
129 ArrayTypeNode { syntax: self.syntax.owned() }
130 }
131}
117 132
118// Attr
119 133
120#[derive(Debug, Clone)] 134impl<'a> ArrayType<'a> {}
121pub struct AttrNode(SyntaxNode);
122 135
123impl AttrNode { 136// Attr
124 pub fn ast(&self) -> Attr { 137#[derive(Debug, Clone, Copy,)]
125 Attr::cast(self.0.borrowed()).unwrap() 138pub struct AttrNode<R: TreeRoot<RaTypes> = OwnedRoot> {
126 } 139 pub(crate) syntax: SyntaxNode<R>,
127} 140}
141pub type Attr<'a> = AttrNode<RefRoot<'a>>;
128 142
129impl<'a> From<Attr<'a>> for AttrNode { 143impl<R1: TreeRoot<RaTypes>, R2: TreeRoot<RaTypes>> PartialEq<AttrNode<R1>> for AttrNode<R2> {
130 fn from(ast: Attr<'a>) -> AttrNode { 144 fn eq(&self, other: &AttrNode<R1>) -> bool { self.syntax == other.syntax }
131 let syntax = ast.syntax().owned();
132 AttrNode(syntax)
133 }
134} 145}
135#[derive(Debug, Clone, Copy)] 146impl<R: TreeRoot<RaTypes>> Eq for AttrNode<R> {}
136pub struct Attr<'a> { 147impl<R: TreeRoot<RaTypes>> Hash for AttrNode<R> {
137 syntax: SyntaxNodeRef<'a>, 148 fn hash<H: Hasher>(&self, state: &mut H) { self.syntax.hash(state) }
138} 149}
139 150
140impl<'a> AstNode<'a> for Attr<'a> { 151impl<'a> AstNode<'a> for Attr<'a> {
@@ -147,6 +158,16 @@ impl<'a> AstNode<'a> for Attr<'a> {
147 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 158 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
148}