aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--Cargo.lock221
-rw-r--r--crates/ra_assists/src/assist_ctx.rs8
-rw-r--r--crates/ra_assists/src/assists/add_derive.rs4
-rw-r--r--crates/ra_assists/src/assists/add_explicit_type.rs2
-rw-r--r--crates/ra_assists/src/assists/add_impl.rs2
-rw-r--r--crates/ra_assists/src/assists/add_missing_impl_members.rs46
-rw-r--r--crates/ra_assists/src/assists/apply_demorgan.rs102
-rw-r--r--crates/ra_assists/src/assists/auto_import.rs5
-rw-r--r--crates/ra_assists/src/assists/change_visibility.rs2
-rw-r--r--crates/ra_assists/src/assists/fill_match_arms.rs2
-rw-r--r--crates/ra_assists/src/assists/flip_binexpr.rs2
-rw-r--r--crates/ra_assists/src/assists/flip_comma.rs2
-rw-r--r--crates/ra_assists/src/assists/inline_local_variable.rs2
-rw-r--r--crates/ra_assists/src/assists/introduce_variable.rs2
-rw-r--r--crates/ra_assists/src/assists/merge_match_arms.rs2
-rw-r--r--crates/ra_assists/src/assists/move_bounds.rs14
-rw-r--r--crates/ra_assists/src/assists/move_guard.rs2
-rw-r--r--crates/ra_assists/src/assists/raw_string.rs2
-rw-r--r--crates/ra_assists/src/assists/remove_dbg.rs2
-rw-r--r--crates/ra_assists/src/assists/replace_if_let_with_match.rs2
-rw-r--r--crates/ra_assists/src/assists/split_import.rs8
-rw-r--r--crates/ra_assists/src/ast_editor.rs315
-rw-r--r--crates/ra_assists/src/lib.rs3
-rw-r--r--crates/ra_assists/src/marks.rs2
-rw-r--r--crates/ra_batch/src/lib.rs20
-rw-r--r--crates/ra_cfg/Cargo.toml14
-rw-r--r--crates/ra_cfg/src/cfg_expr.rs132
-rw-r--r--crates/ra_cfg/src/lib.rs61
-rw-r--r--crates/ra_cli/Cargo.toml2
-rw-r--r--crates/ra_cli/src/analysis_bench.rs2
-rw-r--r--crates/ra_cli/src/analysis_stats.rs2
-rw-r--r--crates/ra_cli/src/help.rs2
-rw-r--r--crates/ra_cli/src/main.rs10
-rw-r--r--crates/ra_db/Cargo.toml1
-rw-r--r--crates/ra_db/src/input.rs48
-rw-r--r--crates/ra_db/src/lib.rs5
-rw-r--r--crates/ra_hir/Cargo.toml1
-rw-r--r--crates/ra_hir/src/adt.rs2
-rw-r--r--crates/ra_hir/src/attr.rs80
-rw-r--r--crates/ra_hir/src/code_model.rs16
-rw-r--r--crates/ra_hir/src/code_model/docs.rs2
-rw-r--r--crates/ra_hir/src/code_model/src.rs4
-rw-r--r--crates/ra_hir/src/db.rs2
-rw-r--r--crates/ra_hir/src/diagnostics.rs2
-rw-r--r--crates/ra_hir/src/either.rs2
-rw-r--r--crates/ra_hir/src/expr.rs2
-rw-r--r--crates/ra_hir/src/expr/lower.rs23
-rw-r--r--crates/ra_hir/src/expr/scope.rs2
-rw-r--r--crates/ra_hir/src/expr/validation.rs2
-rw-r--r--crates/ra_hir/src/from_source.rs2
-rw-r--r--crates/ra_hir/src/generics.rs1
-rw-r--r--crates/ra_hir/src/ids.rs22
-rw-r--r--crates/ra_hir/src/impl_block.rs41
-rw-r--r--crates/ra_hir/src/lang_item.rs4
-rw-r--r--crates/ra_hir/src/lib.rs5
-rw-r--r--crates/ra_hir/src/marks.rs5
-rw-r--r--crates/ra_hir/src/mock.rs25
-rw-r--r--crates/ra_hir/src/name.rs159
-rw-r--r--crates/ra_hir/src/nameres.rs14
-rw-r--r--crates/ra_hir/src/nameres/collector.rs60
-rw-r--r--crates/ra_hir/src/nameres/per_ns.rs2
-rw-r--r--crates/ra_hir/src/nameres/raw.rs102
-rw-r--r--crates/ra_hir/src/nameres/tests.rs70
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs105
-rw-r--r--crates/ra_hir/src/path.rs66
-rw-r--r--crates/ra_hir/src/source_binder.rs16
-rw-r--r--crates/ra_hir/src/source_id.rs2
-rw-r--r--crates/ra_hir/src/ty.rs141
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs14
-rw-r--r--crates/ra_hir/src/ty/display.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs36
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs10
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs24
-rw-r--r--crates/ra_hir/src/ty/lower.rs20
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs18
-rw-r--r--crates/ra_hir/src/ty/op.rs2
-rw-r--r--crates/ra_hir/src/ty/primitive.rs2
-rw-r--r--crates/ra_hir/src/ty/tests.rs142
-rw-r--r--crates/ra_hir/src/ty/traits.rs12
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs80
-rw-r--r--crates/ra_hir/src/type_ref.rs2
-rw-r--r--crates/ra_ide_api/Cargo.toml1
-rw-r--r--crates/ra_ide_api/src/assists.rs2
-rw-r--r--crates/ra_ide_api/src/call_info.rs2
-rw-r--r--crates/ra_ide_api/src/change.rs2
-rw-r--r--crates/ra_ide_api/src/completion.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_fn_param.rs18
-rw-r--r--crates/ra_ide_api/src/completion/complete_keyword.rs20
-rw-r--r--crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_pattern.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_record_literal.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_record_pattern.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_snippet.rs2
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs2
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs2
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs1
-rw-r--r--crates/ra_ide_api/src/db.rs2
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs12
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs2
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs61
-rw-r--r--crates/ra_ide_api/src/display/short_label.rs2
-rw-r--r--crates/ra_ide_api/src/display/structure.rs120
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs2
-rw-r--r--crates/ra_ide_api/src/feature_flags.rs2
-rw-r--r--crates/ra_ide_api/src/folding_ranges.rs2
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs187
-rw-r--r--crates/ra_ide_api/src/goto_type_definition.rs2
-rw-r--r--crates/ra_ide_api/src/hover.rs79
-rw-r--r--crates/ra_ide_api/src/impls.rs2
-rw-r--r--crates/ra_ide_api/src/inlay_hints.rs106
-rw-r--r--crates/ra_ide_api/src/join_lines.rs2
-rw-r--r--crates/ra_ide_api/src/lib.rs6
-rw-r--r--crates/ra_ide_api/src/line_index.rs3
-rw-r--r--crates/ra_ide_api/src/line_index_utils.rs2
-rw-r--r--crates/ra_ide_api/src/marks.rs2
-rw-r--r--crates/ra_ide_api/src/matching_brace.rs2
-rw-r--r--crates/ra_ide_api/src/mock_analysis.rs8
-rw-r--r--crates/ra_ide_api/src/name_ref_kind.rs2
-rw-r--r--crates/ra_ide_api/src/parent_module.rs5
-rw-r--r--crates/ra_ide_api/src/references.rs2
-rw-r--r--crates/ra_ide_api/src/runnables.rs3
-rw-r--r--crates/ra_ide_api/src/snapshots/highlighting.html2
-rw-r--r--crates/ra_ide_api/src/status.rs2
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs26
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs2
-rw-r--r--crates/ra_ide_api/src/syntax_tree.rs2
-rw-r--r--crates/ra_ide_api/src/test_utils.rs2
-rw-r--r--crates/ra_ide_api/src/typing.rs2
-rw-r--r--crates/ra_ide_api/src/wasm_shims.rs2
-rw-r--r--crates/ra_lsp_server/Cargo.toml1
-rw-r--r--crates/ra_lsp_server/src/caps.rs2
-rw-r--r--crates/ra_lsp_server/src/cargo_target_spec.rs2
-rw-r--r--crates/ra_lsp_server/src/config.rs2
-rw-r--r--crates/ra_lsp_server/src/conv.rs2
-rw-r--r--crates/ra_lsp_server/src/lib.rs2
-rw-r--r--crates/ra_lsp_server/src/main.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop/pending_requests.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop/subscriptions.rs2
-rw-r--r--crates/ra_lsp_server/src/markdown.rs3
-rw-r--r--crates/ra_lsp_server/src/req.rs2
-rw-r--r--crates/ra_lsp_server/src/world.rs10
-rw-r--r--crates/ra_lsp_server/tests/heavy_tests/main.rs8
-rw-r--r--crates/ra_mbe/src/lib.rs8
-rw-r--r--crates/ra_mbe/src/mbe_expander/matcher.rs2
-rw-r--r--crates/ra_mbe/src/mbe_expander/transcriber.rs2
-rw-r--r--crates/ra_mbe/src/subtree_source.rs2
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs2
-rw-r--r--crates/ra_mbe/src/tt_iter.rs2
-rw-r--r--crates/ra_parser/src/grammar.rs1
-rw-r--r--crates/ra_parser/src/grammar/attributes.rs21
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs38
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs12
-rw-r--r--crates/ra_parser/src/grammar/items.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/consts.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/nominal.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/traits.rs2
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs2
-rw-r--r--crates/ra_parser/src/grammar/params.rs2
-rw-r--r--crates/ra_parser/src/grammar/paths.rs2
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs2
-rw-r--r--crates/ra_parser/src/grammar/type_args.rs2
-rw-r--r--crates/ra_parser/src/grammar/type_params.rs2
-rw-r--r--crates/ra_parser/src/grammar/types.rs2
-rw-r--r--crates/ra_parser/src/parser.rs2
-rw-r--r--crates/ra_parser/src/syntax_kind.rs2
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs2
-rw-r--r--crates/ra_parser/src/token_set.rs2
-rw-r--r--crates/ra_prof/src/lib.rs2
-rw-r--r--crates/ra_prof/src/memory_usage.rs2
-rw-r--r--crates/ra_project_model/Cargo.toml1
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs8
-rw-r--r--crates/ra_project_model/src/json_project.rs5
-rw-r--r--crates/ra_project_model/src/lib.rs57
-rw-r--r--crates/ra_project_model/src/sysroot.rs2
-rw-r--r--crates/ra_syntax/Cargo.toml2
-rw-r--r--crates/ra_syntax/fuzz/fuzz_targets/parser.rs2
-rw-r--r--crates/ra_syntax/fuzz/fuzz_targets/reparse.rs2
-rw-r--r--crates/ra_syntax/src/algo.rs19
-rw-r--r--crates/ra_syntax/src/algo/visit.rs110
-rw-r--r--crates/ra_syntax/src/ast.rs1
-rw-r--r--crates/ra_syntax/src/ast/edit.rs271
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs93
-rw-r--r--crates/ra_syntax/src/ast/generated.rs46
-rw-r--r--crates/ra_syntax/src/ast/make.rs48
-rw-r--r--crates/ra_syntax/src/ast/traits.rs2
-rw-r--r--crates/ra_syntax/src/fuzz.rs2
-rw-r--r--crates/ra_syntax/src/grammar.ron8
-rw-r--r--crates/ra_syntax/src/lib.rs31
-rw-r--r--crates/ra_syntax/src/parsing/lexer.rs2
-rw-r--r--crates/ra_syntax/src/parsing/text_token_source.rs2
-rw-r--r--crates/ra_syntax/src/parsing/text_tree_sink.rs2
-rw-r--r--crates/ra_syntax/src/ptr.rs2
-rw-r--r--crates/ra_syntax/src/syntax_error.rs2
-rw-r--r--crates/ra_syntax/src/validation.rs20
-rw-r--r--crates/ra_syntax/src/validation/block.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/err/0005_attribute_recover.txt68
-rw-r--r--crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt10
-rw-r--r--crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.txt72
-rw-r--r--crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.txt18
-rw-r--r--crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.txt18
-rw-r--r--crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.txt20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt34
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt26
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt43
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt65
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs6
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt107
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt26
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.txt18
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.txt54
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.txt130
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.txt36
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt18
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.txt50
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.txt20
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt18
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt18
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.txt10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.txt10
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rs3
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.txt43
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0006_inner_attributes.txt268
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt10
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rs3
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.txt53
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.txt20
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt89
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0044_let_attrs.txt26
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.txt90
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0046_extern_inner_attributes.txt18
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt150
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.txt10
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rs7
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.txt97
-rw-r--r--crates/ra_text_edit/src/lib.rs2
-rw-r--r--crates/ra_text_edit/src/test_utils.rs2
-rw-r--r--crates/ra_text_edit/src/text_edit.rs2
-rw-r--r--crates/ra_tools/Cargo.toml2
-rw-r--r--crates/ra_tools/src/bin/pre-commit.rs2
-rw-r--r--crates/ra_tools/src/boilerplate_gen.rs4
-rw-r--r--crates/ra_tools/src/help.rs2
-rw-r--r--crates/ra_tools/src/lib.rs2
-rw-r--r--crates/ra_tools/src/main.rs2
-rw-r--r--crates/ra_tools/tests/cli.rs5
-rw-r--r--crates/ra_tools/tests/docs.rs63
-rw-r--r--crates/ra_tools/tests/main.rs2
-rw-r--r--crates/ra_tt/src/buffer.rs2
-rw-r--r--crates/ra_tt/src/lib.rs6
-rw-r--r--crates/test_utils/src/lib.rs2
-rw-r--r--docs/dev/architecture.md4
-rw-r--r--docs/user/README.md18
-rw-r--r--docs/user/features.md18
-rw-r--r--editors/code/src/test/utils/diagnotics/rust.test.ts8
-rw-r--r--editors/code/src/utils/diagnostics/rust.ts18
264 files changed, 4018 insertions, 1973 deletions
diff --git a/.travis.yml b/.travis.yml
index c198cc5f7..d4cf71ab5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -58,7 +58,7 @@ deploy:
58 provider: pages 58 provider: pages
59 skip-cleanup: true 59 skip-cleanup: true
60 github-token: $DOCS_TOKEN # Set in the settings page of your repository, as a secure variable 60 github-token: $DOCS_TOKEN # Set in the settings page of your repository, as a secure variable
61 keep-history: true 61 keep-history: false
62 local-dir: target/website/ 62 local-dir: target/website/
63 on: 63 on:
64 branch: master 64 branch: master
diff --git a/Cargo.lock b/Cargo.lock
index dad9b1df1..e9383a89a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,11 +32,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
32 32
33[[package]] 33[[package]]
34name = "backtrace" 34name = "backtrace"
35version = "0.3.37" 35version = "0.3.38"
36source = "registry+https://github.com/rust-lang/crates.io-index" 36source = "registry+https://github.com/rust-lang/crates.io-index"
37dependencies = [ 37dependencies = [
38 "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", 38 "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
39 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 39 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
40 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 40 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
41 "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 41 "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
42] 42]
@@ -46,7 +46,7 @@ name = "backtrace-sys"
46version = "0.1.31" 46version = "0.1.31"
47source = "registry+https://github.com/rust-lang/crates.io-index" 47source = "registry+https://github.com/rust-lang/crates.io-index"
48dependencies = [ 48dependencies = [
49 "cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 49 "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
50 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 50 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
51] 51]
52 52
@@ -73,7 +73,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
73 73
74[[package]] 74[[package]]
75name = "bitflags" 75name = "bitflags"
76version = "1.1.0" 76version = "1.2.0"
77source = "registry+https://github.com/rust-lang/crates.io-index" 77source = "registry+https://github.com/rust-lang/crates.io-index"
78 78
79[[package]] 79[[package]]
@@ -104,19 +104,19 @@ version = "0.8.2"
104source = "registry+https://github.com/rust-lang/crates.io-index" 104source = "registry+https://github.com/rust-lang/crates.io-index"
105dependencies = [ 105dependencies = [
106 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 106 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
107 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 107 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
108 "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 108 "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
109 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", 109 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
110] 110]
111 111
112[[package]] 112[[package]]
113name = "cc" 113name = "cc"
114version = "1.0.42" 114version = "1.0.45"
115source = "registry+https://github.com/rust-lang/crates.io-index" 115source = "registry+https://github.com/rust-lang/crates.io-index"
116 116
117[[package]] 117[[package]]
118name = "cfg-if" 118name = "cfg-if"
119version = "0.1.9" 119version = "0.1.10"
120source = "registry+https://github.com/rust-lang/crates.io-index" 120source = "registry+https://github.com/rust-lang/crates.io-index"
121 121
122[[package]] 122[[package]]
@@ -200,7 +200,7 @@ name = "cloudabi"
200version = "0.0.3" 200version = "0.0.3"
201source = "registry+https://github.com/rust-lang/crates.io-index" 201source = "registry+https://github.com/rust-lang/crates.io-index"
202dependencies = [ 202dependencies = [
203 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 203 "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
204] 204]
205 205
206[[package]] 206[[package]]
@@ -223,7 +223,7 @@ name = "crossbeam"
223version = "0.7.2" 223version = "0.7.2"
224source = "registry+https://github.com/rust-lang/crates.io-index" 224source = "registry+https://github.com/rust-lang/crates.io-index"
225dependencies = [ 225dependencies = [
226 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 226 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
227 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 227 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
228 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 228 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
229 "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 229 "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -254,7 +254,7 @@ version = "0.7.2"
254source = "registry+https://github.com/rust-lang/crates.io-index" 254source = "registry+https://github.com/rust-lang/crates.io-index"
255dependencies = [ 255dependencies = [
256 "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", 256 "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
257 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 257 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
258 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", 258 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
259 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 259 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
260 "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 260 "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -274,7 +274,7 @@ name = "crossbeam-utils"
274version = "0.6.6" 274version = "0.6.6"
275source = "registry+https://github.com/rust-lang/crates.io-index" 275source = "registry+https://github.com/rust-lang/crates.io-index"
276dependencies = [ 276dependencies = [
277 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 277 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
278 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 278 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
279] 279]
280 280
@@ -283,7 +283,7 @@ name = "derive-new"
283version = "0.5.8" 283version = "0.5.8"
284source = "registry+https://github.com/rust-lang/crates.io-index" 284source = "registry+https://github.com/rust-lang/crates.io-index"
285dependencies = [ 285dependencies = [
286 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 286 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
287 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 287 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
288 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 288 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
289] 289]
@@ -305,7 +305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
305 305
306[[package]] 306[[package]]
307name = "either" 307name = "either"
308version = "1.5.2" 308version = "1.5.3"
309source = "registry+https://github.com/rust-lang/crates.io-index" 309source = "registry+https://github.com/rust-lang/crates.io-index"
310 310
311[[package]] 311[[package]]
@@ -326,7 +326,7 @@ name = "filetime"
326version = "0.2.7" 326version = "0.2.7"
327source = "registry+https://github.com/rust-lang/crates.io-index" 327source = "registry+https://github.com/rust-lang/crates.io-index"
328dependencies = [ 328dependencies = [
329 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 329 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
330 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 330 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
331 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 331 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
332 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 332 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -339,7 +339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
339 339
340[[package]] 340[[package]]
341name = "flexi_logger" 341name = "flexi_logger"
342version = "0.14.3" 342version = "0.14.4"
343source = "registry+https://github.com/rust-lang/crates.io-index" 343source = "registry+https://github.com/rust-lang/crates.io-index"
344dependencies = [ 344dependencies = [
345 "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", 345 "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -369,7 +369,7 @@ name = "fsevent"
369version = "0.4.0" 369version = "0.4.0"
370source = "registry+https://github.com/rust-lang/crates.io-index" 370source = "registry+https://github.com/rust-lang/crates.io-index"
371dependencies = [ 371dependencies = [
372 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 372 "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
373 "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 373 "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
374] 374]
375 375
@@ -399,7 +399,7 @@ name = "fuchsia-zircon"
399version = "0.3.3" 399version = "0.3.3"
400source = "registry+https://github.com/rust-lang/crates.io-index" 400source = "registry+https://github.com/rust-lang/crates.io-index"
401dependencies = [ 401dependencies = [
402 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 402 "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
403 "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 403 "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
404] 404]
405 405
@@ -410,12 +410,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
410 410
411[[package]] 411[[package]]
412name = "getrandom" 412name = "getrandom"
413version = "0.1.11" 413version = "0.1.12"
414source = "registry+https://github.com/rust-lang/crates.io-index" 414source = "registry+https://github.com/rust-lang/crates.io-index"
415dependencies = [ 415dependencies = [
416 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 416 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
417 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 417 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
418 "wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 418 "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
419] 419]
420 420
421[[package]] 421[[package]]
@@ -455,7 +455,7 @@ dependencies = [
455 455
456[[package]] 456[[package]]
457name = "indexmap" 457name = "indexmap"
458version = "1.1.0" 458version = "1.2.0"
459source = "registry+https://github.com/rust-lang/crates.io-index" 459source = "registry+https://github.com/rust-lang/crates.io-index"
460 460
461[[package]] 461[[package]]
@@ -475,7 +475,7 @@ name = "inotify"
475version = "0.6.1" 475version = "0.6.1"
476source = "registry+https://github.com/rust-lang/crates.io-index" 476source = "registry+https://github.com/rust-lang/crates.io-index"
477dependencies = [ 477dependencies = [
478 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 478 "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
479 "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 479 "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
480 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 480 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
481] 481]
@@ -496,7 +496,7 @@ dependencies = [
496 "console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 496 "console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
497 "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 497 "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
498 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 498 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
499 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 499 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
500 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", 500 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
501 "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", 501 "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
502 "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", 502 "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -516,7 +516,7 @@ name = "itertools"
516version = "0.8.0" 516version = "0.8.0"
517source = "registry+https://github.com/rust-lang/crates.io-index" 517source = "registry+https://github.com/rust-lang/crates.io-index"
518dependencies = [ 518dependencies = [
519 "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 519 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
520] 520]
521 521
522[[package]] 522[[package]]
@@ -539,7 +539,7 @@ name = "jemalloc-sys"
539version = "0.3.2" 539version = "0.3.2"
540source = "registry+https://github.com/rust-lang/crates.io-index" 540source = "registry+https://github.com/rust-lang/crates.io-index"
541dependencies = [ 541dependencies = [
542 "cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 542 "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
543 "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 543 "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
544 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 544 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
545] 545]
@@ -610,7 +610,7 @@ name = "log"
610version = "0.4.8" 610version = "0.4.8"
611source = "registry+https://github.com/rust-lang/crates.io-index" 611source = "registry+https://github.com/rust-lang/crates.io-index"
612dependencies = [ 612dependencies = [
613 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 613 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
614] 614]
615 615
616[[package]] 616[[package]]
@@ -620,7 +620,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
620dependencies = [ 620dependencies = [
621 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 621 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
622 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 622 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
623 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 623 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
624 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", 624 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
625] 625]
626 626
@@ -629,8 +629,8 @@ name = "lsp-types"
629version = "0.61.0" 629version = "0.61.0"
630source = "registry+https://github.com/rust-lang/crates.io-index" 630source = "registry+https://github.com/rust-lang/crates.io-index"
631dependencies = [ 631dependencies = [
632 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 632 "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
633 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 633 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
634 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", 634 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
635 "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 635 "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
636 "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 636 "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -698,7 +698,7 @@ name = "net2"
698version = "0.2.33" 698version = "0.2.33"
699source = "registry+https://github.com/rust-lang/crates.io-index" 699source = "registry+https://github.com/rust-lang/crates.io-index"
700dependencies = [ 700dependencies = [
701 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 701 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
702 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 702 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
703 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 703 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
704] 704]
@@ -713,7 +713,7 @@ name = "notify"
713version = "4.0.13" 713version = "4.0.13"
714source = "registry+https://github.com/rust-lang/crates.io-index" 714source = "registry+https://github.com/rust-lang/crates.io-index"
715dependencies = [ 715dependencies = [
716 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 716 "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
717 "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", 717 "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
718 "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 718 "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
719 "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 719 "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -761,7 +761,7 @@ dependencies = [
761 761
762[[package]] 762[[package]]
763name = "once_cell" 763name = "once_cell"
764version = "1.0.2" 764version = "1.2.0"
765source = "registry+https://github.com/rust-lang/crates.io-index" 765source = "registry+https://github.com/rust-lang/crates.io-index"
766 766
767[[package]] 767[[package]]
@@ -784,7 +784,7 @@ name = "parking_lot_core"
784version = "0.6.2" 784version = "0.6.2"
785source = "registry+https://github.com/rust-lang/crates.io-index" 785source = "registry+https://github.com/rust-lang/crates.io-index"
786dependencies = [ 786dependencies = [
787 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 787 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
788 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 788 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
789 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 789 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
790 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 790 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -808,7 +808,7 @@ version = "0.1.6"
808source = "registry+https://github.com/rust-lang/crates.io-index" 808source = "registry+https://github.com/rust-lang/crates.io-index"
809dependencies = [ 809dependencies = [
810 "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", 810 "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
811 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 811 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
812 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 812 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
813 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 813 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
814] 814]
@@ -829,7 +829,7 @@ dependencies = [
829 829
830[[package]] 830[[package]]
831name = "pico-args" 831name = "pico-args"
832version = "0.2.0" 832version = "0.3.0"
833source = "registry+https://github.com/rust-lang/crates.io-index" 833source = "registry+https://github.com/rust-lang/crates.io-index"
834 834
835[[package]] 835[[package]]
@@ -842,14 +842,14 @@ name = "proc-macro-hack"
842version = "0.5.9" 842version = "0.5.9"
843source = "registry+https://github.com/rust-lang/crates.io-index" 843source = "registry+https://github.com/rust-lang/crates.io-index"
844dependencies = [ 844dependencies = [
845 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 845 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
846 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 846 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
847 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 847 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
848] 848]
849 849
850[[package]] 850[[package]]
851name = "proc-macro2" 851name = "proc-macro2"
852version = "1.0.2" 852version = "1.0.5"
853source = "registry+https://github.com/rust-lang/crates.io-index" 853source = "registry+https://github.com/rust-lang/crates.io-index"
854dependencies = [ 854dependencies = [
855 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 855 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -861,7 +861,7 @@ version = "0.9.4"
861source = "registry+https://github.com/rust-lang/crates.io-index" 861source = "registry+https://github.com/rust-lang/crates.io-index"
862dependencies = [ 862dependencies = [
863 "bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 863 "bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
864 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 864 "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
865 "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 865 "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
866 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 866 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
867 "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 867 "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -882,7 +882,7 @@ name = "quote"
882version = "1.0.2" 882version = "1.0.2"
883source = "registry+https://github.com/rust-lang/crates.io-index" 883source = "registry+https://github.com/rust-lang/crates.io-index"
884dependencies = [ 884dependencies = [
885 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 885 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
886] 886]
887 887
888[[package]] 888[[package]]
@@ -897,7 +897,7 @@ dependencies = [
897 "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 897 "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
898 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 898 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
899 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 899 "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
900 "once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 900 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
901 "ra_db 0.1.0", 901 "ra_db 0.1.0",
902 "ra_fmt 0.1.0", 902 "ra_fmt 0.1.0",
903 "ra_hir 0.1.0", 903 "ra_hir 0.1.0",
@@ -924,12 +924,22 @@ dependencies = [
924] 924]
925 925
926[[package]] 926[[package]]
927name = "ra_cfg"
928version = "0.1.0"
929dependencies = [
930 "ra_mbe 0.1.0",
931 "ra_syntax 0.1.0",
932 "ra_tt 0.1.0",
933 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
934]
935
936[[package]]
927name = "ra_cli" 937name = "ra_cli"
928version = "0.1.0" 938version = "0.1.0"
929dependencies = [ 939dependencies = [
930 "flexi_logger 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", 940 "flexi_logger 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
931 "indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 941 "indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
932 "pico-args 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 942 "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
933 "ra_batch 0.1.0", 943 "ra_batch 0.1.0",
934 "ra_db 0.1.0", 944 "ra_db 0.1.0",
935 "ra_hir 0.1.0", 945 "ra_hir 0.1.0",
@@ -942,11 +952,12 @@ dependencies = [
942name = "ra_db" 952name = "ra_db"
943version = "0.1.0" 953version = "0.1.0"
944dependencies = [ 954dependencies = [
955 "ra_cfg 0.1.0",
945 "ra_prof 0.1.0", 956 "ra_prof 0.1.0",
946 "ra_syntax 0.1.0", 957 "ra_syntax 0.1.0",
947 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 958 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
948 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 959 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
949 "salsa 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", 960 "salsa 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
950] 961]
951 962
952[[package]] 963[[package]]
@@ -969,9 +980,10 @@ dependencies = [
969 "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 980 "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
970 "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", 981 "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
971 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 982 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
972 "once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 983 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
973 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 984 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
974 "ra_arena 0.1.0", 985 "ra_arena 0.1.0",
986 "ra_cfg 0.1.0",
975 "ra_db 0.1.0", 987 "ra_db 0.1.0",
976 "ra_mbe 0.1.0", 988 "ra_mbe 0.1.0",
977 "ra_prof 0.1.0", 989 "ra_prof 0.1.0",
@@ -994,13 +1006,14 @@ dependencies = [
994 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1006 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
995 "proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)", 1007 "proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
996 "ra_assists 0.1.0", 1008 "ra_assists 0.1.0",
1009 "ra_cfg 0.1.0",
997 "ra_db 0.1.0", 1010 "ra_db 0.1.0",
998 "ra_fmt 0.1.0", 1011 "ra_fmt 0.1.0",
999 "ra_hir 0.1.0", 1012 "ra_hir 0.1.0",
1000 "ra_prof 0.1.0", 1013 "ra_prof 0.1.0",
1001 "ra_syntax 0.1.0", 1014 "ra_syntax 0.1.0",
1002 "ra_text_edit 0.1.0", 1015 "ra_text_edit 0.1.0",
1003 "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1016 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1004 "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1017 "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1005 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1018 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1006 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1019 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1014,12 +1027,13 @@ name = "ra_lsp_server"
1014version = "0.1.0" 1027version = "0.1.0"
1015dependencies = [ 1028dependencies = [
1016 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 1029 "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1017 "flexi_logger 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)", 1030 "flexi_logger 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
1018 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1031 "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1019 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1032 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1020 "lsp-server 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1033 "lsp-server 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1021 "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", 1034 "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)",
1022 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 1035 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
1036 "ra_cfg 0.1.0",
1023 "ra_db 0.1.0", 1037 "ra_db 0.1.0",
1024 "ra_ide_api 0.1.0", 1038 "ra_ide_api 0.1.0",
1025 "ra_prof 0.1.0", 1039 "ra_prof 0.1.0",
@@ -1030,7 +1044,7 @@ dependencies = [
1030 "ra_vfs_glob 0.1.0", 1044 "ra_vfs_glob 0.1.0",
1031 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1045 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1032 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1046 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1033 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1047 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1034 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", 1048 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1035 "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1049 "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1036 "test_utils 0.1.0", 1050 "test_utils 0.1.0",
@@ -1062,11 +1076,11 @@ dependencies = [
1062name = "ra_prof" 1076name = "ra_prof"
1063version = "0.1.0" 1077version = "0.1.0"
1064dependencies = [ 1078dependencies = [
1065 "backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", 1079 "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
1066 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1080 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1067 "jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 1081 "jemalloc-ctl 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
1068 "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 1082 "jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
1069 "once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1083 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1070] 1084]
1071 1085
1072[[package]] 1086[[package]]
@@ -1076,9 +1090,10 @@ dependencies = [
1076 "cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", 1090 "cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
1077 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1091 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1078 "ra_arena 0.1.0", 1092 "ra_arena 0.1.0",
1093 "ra_cfg 0.1.0",
1079 "ra_db 0.1.0", 1094 "ra_db 0.1.0",
1080 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1095 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1081 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1096 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1082 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", 1097 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1083] 1098]
1084 1099
@@ -1086,13 +1101,15 @@ dependencies = [
1086name = "ra_syntax" 1101name = "ra_syntax"
1087version = "0.1.0" 1102version = "0.1.0"
1088dependencies = [ 1103dependencies = [
1104 "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1089 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1105 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1106 "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1090 "ra_parser 0.1.0", 1107 "ra_parser 0.1.0",
1091 "ra_text_edit 0.1.0", 1108 "ra_text_edit 0.1.0",
1092 "rowan 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 1109 "rowan 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
1093 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1110 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1094 "rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1111 "rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1095 "smol_str 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1112 "smol_str 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1096 "test_utils 0.1.0", 1113 "test_utils 0.1.0",
1097 "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", 1114 "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
1098] 1115]
@@ -1111,11 +1128,11 @@ name = "ra_tools"
1111version = "0.1.0" 1128version = "0.1.0"
1112dependencies = [ 1129dependencies = [
1113 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1130 "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1114 "pico-args 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1131 "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1115 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1132 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1116 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1133 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1117 "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1134 "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1118 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1135 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1119 "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", 1136 "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
1120] 1137]
1121 1138
@@ -1123,7 +1140,7 @@ dependencies = [
1123name = "ra_tt" 1140name = "ra_tt"
1124version = "0.1.0" 1141version = "0.1.0"
1125dependencies = [ 1142dependencies = [
1126 "smol_str 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1143 "smol_str 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1127] 1144]
1128 1145
1129[[package]] 1146[[package]]
@@ -1169,10 +1186,10 @@ dependencies = [
1169 1186
1170[[package]] 1187[[package]]
1171name = "rand" 1188name = "rand"
1172version = "0.7.0" 1189version = "0.7.2"
1173source = "registry+https://github.com/rust-lang/crates.io-index" 1190source = "registry+https://github.com/rust-lang/crates.io-index"
1174dependencies = [ 1191dependencies = [
1175 "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 1192 "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1176 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 1193 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
1177 "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 1194 "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1178 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 1195 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1216,7 +1233,7 @@ name = "rand_core"
1216version = "0.5.1" 1233version = "0.5.1"
1217source = "registry+https://github.com/rust-lang/crates.io-index" 1234source = "registry+https://github.com/rust-lang/crates.io-index"
1218dependencies = [ 1235dependencies = [
1219 "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", 1236 "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1220] 1237]
1221 1238
1222[[package]] 1239[[package]]
@@ -1298,7 +1315,7 @@ version = "1.2.0"
1298source = "registry+https://github.com/rust-lang/crates.io-index" 1315source = "registry+https://github.com/rust-lang/crates.io-index"
1299dependencies = [ 1316dependencies = [
1300 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", 1317 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1301 "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 1318 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
1302 "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 1319 "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
1303] 1320]
1304 1321
@@ -1362,8 +1379,8 @@ version = "0.5.1"
1362source = "registry+https://github.com/rust-lang/crates.io-index" 1379source = "registry+https://github.com/rust-lang/crates.io-index"
1363dependencies = [ 1380dependencies = [
1364 "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", 1381 "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
1365 "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1382 "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1366 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1383 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1367] 1384]
1368 1385
1369[[package]] 1386[[package]]
@@ -1372,7 +1389,7 @@ version = "0.6.2"
1372source = "registry+https://github.com/rust-lang/crates.io-index" 1389source = "registry+https://github.com/rust-lang/crates.io-index"
1373dependencies = [ 1390dependencies = [
1374 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1391 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1375 "smol_str 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 1392 "smol_str 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1376 "text_unit 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 1393 "text_unit 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
1377] 1394]
1378 1395
@@ -1412,15 +1429,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1412 1429
1413[[package]] 1430[[package]]
1414name = "salsa" 1431name = "salsa"
1415version = "0.13.0" 1432version = "0.13.1"
1416source = "registry+https://github.com/rust-lang/crates.io-index" 1433source = "registry+https://github.com/rust-lang/crates.io-index"
1417dependencies = [ 1434dependencies = [
1418 "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 1435 "crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1419 "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", 1436 "derive-new 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
1420 "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1437 "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1421 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 1438 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1422 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 1439 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
1423 "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1440 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1424 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1441 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1425 "salsa-macros 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", 1442 "salsa-macros 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
1426 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", 1443 "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1432,7 +1449,7 @@ version = "0.13.1"
1432source = "registry+https://github.com/rust-lang/crates.io-index" 1449source = "registry+https://github.com/rust-lang/crates.io-index"
1433dependencies = [ 1450dependencies = [
1434 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 1451 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1435 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1452 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1436 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1453 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1437 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1454 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1438] 1455]
@@ -1456,7 +1473,7 @@ version = "0.9.0"
1456source = "registry+https://github.com/rust-lang/crates.io-index" 1473source = "registry+https://github.com/rust-lang/crates.io-index"
1457dependencies = [ 1474dependencies = [
1458 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1475 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1459 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1476 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1460] 1477]
1461 1478
1462[[package]] 1479[[package]]
@@ -1466,18 +1483,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1466 1483
1467[[package]] 1484[[package]]
1468name = "serde" 1485name = "serde"
1469version = "1.0.99" 1486version = "1.0.101"
1470source = "registry+https://github.com/rust-lang/crates.io-index" 1487source = "registry+https://github.com/rust-lang/crates.io-index"
1471dependencies = [ 1488dependencies = [
1472 "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1489 "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1473] 1490]
1474 1491
1475[[package]] 1492[[package]]
1476name = "serde_derive" 1493name = "serde_derive"
1477version = "1.0.99" 1494version = "1.0.101"
1478source = "registry+https://github.com/rust-lang/crates.io-index" 1495source = "registry+https://github.com/rust-lang/crates.io-index"
1479dependencies = [ 1496dependencies = [
1480 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1497 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1481 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1498 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1482 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1499 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1483] 1500]
@@ -1489,7 +1506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1489dependencies = [ 1506dependencies = [
1490 "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 1507 "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
1491 "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 1508 "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
1492 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1509 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1493] 1510]
1494 1511
1495[[package]] 1512[[package]]
@@ -1497,7 +1514,7 @@ name = "serde_repr"
1497version = "0.1.5" 1514version = "0.1.5"
1498source = "registry+https://github.com/rust-lang/crates.io-index" 1515source = "registry+https://github.com/rust-lang/crates.io-index"
1499dependencies = [ 1516dependencies = [
1500 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1517 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1501 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1518 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1502 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 1519 "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1503] 1520]
@@ -1509,7 +1526,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1509dependencies = [ 1526dependencies = [
1510 "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 1527 "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
1511 "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 1528 "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
1512 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1529 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1513 "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 1530 "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
1514] 1531]
1515 1532
@@ -1525,10 +1542,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1525 1542
1526[[package]] 1543[[package]]
1527name = "smol_str" 1544name = "smol_str"
1528version = "0.1.12" 1545version = "0.1.13"
1529source = "registry+https://github.com/rust-lang/crates.io-index" 1546source = "registry+https://github.com/rust-lang/crates.io-index"
1530dependencies = [ 1547dependencies = [
1531 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1548 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1532] 1549]
1533 1550
1534[[package]] 1551[[package]]
@@ -1536,8 +1553,8 @@ name = "stacker"
1536version = "0.1.5" 1553version = "0.1.5"
1537source = "registry+https://github.com/rust-lang/crates.io-index" 1554source = "registry+https://github.com/rust-lang/crates.io-index"
1538dependencies = [ 1555dependencies = [
1539 "cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", 1556 "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
1540 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 1557 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1541 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 1558 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
1542 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1559 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
1543] 1560]
@@ -1552,7 +1569,7 @@ name = "syn"
1552version = "1.0.5" 1569version = "1.0.5"
1553source = "registry+https://github.com/rust-lang/crates.io-index" 1570source = "registry+https://github.com/rust-lang/crates.io-index"
1554dependencies = [ 1571dependencies = [
1555 "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1572 "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1556 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1573 "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1557 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1574 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1558] 1575]
@@ -1562,9 +1579,9 @@ name = "tempfile"
1562version = "3.1.0" 1579version = "3.1.0"
1563source = "registry+https://github.com/rust-lang/crates.io-index" 1580source = "registry+https://github.com/rust-lang/crates.io-index"
1564dependencies = [ 1581dependencies = [
1565 "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 1582 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1566 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", 1583 "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
1567 "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 1584 "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1568 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", 1585 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
1569 "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 1586 "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
1570 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 1587 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1665,7 +1682,7 @@ dependencies = [
1665 "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1682 "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1666 "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 1683 "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
1667 "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1684 "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1668 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1685 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1669] 1686]
1670 1687
1671[[package]] 1688[[package]]
@@ -1674,7 +1691,7 @@ version = "0.7.4"
1674source = "registry+https://github.com/rust-lang/crates.io-index" 1691source = "registry+https://github.com/rust-lang/crates.io-index"
1675dependencies = [ 1692dependencies = [
1676 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1693 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
1677 "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", 1694 "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
1678] 1695]
1679 1696
1680[[package]] 1697[[package]]
@@ -1694,7 +1711,7 @@ dependencies = [
1694 1711
1695[[package]] 1712[[package]]
1696name = "wasi" 1713name = "wasi"
1697version = "0.5.0" 1714version = "0.7.0"
1698source = "registry+https://github.com/rust-lang/crates.io-index" 1715source = "registry+https://github.com/rust-lang/crates.io-index"
1699 1716
1700[[package]] 1717[[package]]
@@ -1768,18 +1785,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1768"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" 1785"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
1769"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" 1786"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
1770"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" 1787"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
1771"checksum backtrace 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" 1788"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5"
1772"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" 1789"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
1773"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" 1790"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
1774"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" 1791"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80"
1775"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" 1792"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
1776"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" 1793"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
1777"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" 1794"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245"
1778"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 1795"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
1779"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" 1796"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
1780"checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426" 1797"checksum cargo_metadata 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "700b3731fd7d357223d0000f4dbf1808401b694609035c3c411fbc0cd375c426"
1781"checksum cc 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "a61c7bce55cd2fae6ec8cb935ebd76256c2959a1f95790f6118a441c2cd5b406" 1798"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be"
1782"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" 1799"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
1783"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1800"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>"
1784"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1801"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git)" = "<none>"
1785"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)" = "<none>" 1802"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git)" = "<none>"
@@ -1799,12 +1816,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1799"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" 1816"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
1800"checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f" 1817"checksum drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f"
1801"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" 1818"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
1802"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" 1819"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
1803"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" 1820"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87"
1804"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 1821"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
1805"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" 1822"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469"
1806"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" 1823"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
1807"checksum flexi_logger 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66473c1b6a0d2a72f6ed983d33021a4c744a1d179e6f4265867b7d0a9dd679c5" 1824"checksum flexi_logger 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d20d127f22dd09495f5a5de83dc9f51cf90932735b642910062c577082dd3b36"
1808"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 1825"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
1809"checksum format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aea5a5909a74969507051a3b17adc84737e31a5f910559892aedce026f4d53" 1826"checksum format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aea5a5909a74969507051a3b17adc84737e31a5f910559892aedce026f4d53"
1810"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" 1827"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
@@ -1814,12 +1831,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1814"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 1831"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
1815"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 1832"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
1816"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 1833"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
1817"checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872" 1834"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"
1818"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" 1835"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
1819"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" 1836"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2"
1820"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 1837"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
1821"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" 1838"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
1822"checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356" 1839"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3"
1823"checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c" 1840"checksum indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c60da1c9abea75996b70a931bba6c750730399005b61ccd853cee50ef3d0d0c"
1824"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" 1841"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
1825"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" 1842"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
@@ -1855,7 +1872,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1855"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" 1872"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
1856"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" 1873"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
1857"checksum number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf9993e59c894e3c08aa1c2712914e9e6bf1fcbfc6bef283e2183df345a4fee" 1874"checksum number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dbf9993e59c894e3c08aa1c2712914e9e6bf1fcbfc6bef283e2183df345a4fee"
1858"checksum once_cell 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd38c1bb51148ca239ec38ef1bb4f7570d432861f03e91774d53b01c2ba2132f" 1875"checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed"
1859"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" 1876"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
1860"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" 1877"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
1861"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" 1878"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
@@ -1863,16 +1880,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1863"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" 1880"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5"
1864"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1881"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
1865"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" 1882"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
1866"checksum pico-args 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2fce25154205cf4360b456fd7d48994afe20663b77e3bd3d0a353a2fccf7f22c" 1883"checksum pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22e32b0f3771287ebb436130477eabf0f11f934ed036099ad548bc885e708667"
1867"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" 1884"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
1868"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" 1885"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8"
1869"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95" 1886"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0"
1870"checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f" 1887"checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f"
1871"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" 1888"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
1872"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 1889"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
1873"checksum ra_vfs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdf6a0926414eb0c00866eb9274894182302f879cd06b5459c1d8ee7f1234aed" 1890"checksum ra_vfs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdf6a0926414eb0c00866eb9274894182302f879cd06b5459c1d8ee7f1234aed"
1874"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" 1891"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
1875"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" 1892"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412"
1876"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" 1893"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
1877"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" 1894"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
1878"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 1895"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
@@ -1901,20 +1918,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1901"checksum rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86aae0c77166108c01305ee1a36a1e77289d7dc6ca0a3cd91ff4992de2d16a5" 1918"checksum rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86aae0c77166108c01305ee1a36a1e77289d7dc6ca0a3cd91ff4992de2d16a5"
1902"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1919"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
1903"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" 1920"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
1904"checksum salsa 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3265a2a9bbd384bd2a9f9511c2c18fb41f62c412516052e8934517dc8ff64f1" 1921"checksum salsa 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "df34c3a66ef408c3219c11dee2c928d52e679390d3ee6e0b87e96cc758d85377"
1905"checksum salsa-macros 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c15f36e5c85b3f40b84283321f97ef2ceafa6f9996cffad06793a9e096ab695" 1922"checksum salsa-macros 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c15f36e5c85b3f40b84283321f97ef2ceafa6f9996cffad06793a9e096ab695"
1906"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" 1923"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
1907"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 1924"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
1908"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1925"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
1909"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 1926"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1910"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" 1927"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
1911"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" 1928"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e"
1912"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" 1929"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
1913"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" 1930"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573"
1914"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" 1931"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582"
1915"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1932"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
1916"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" 1933"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
1917"checksum smol_str 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "590700be3630457c56f8c73c0ea39881476ad7076cd84057d44f4f38f79914fb" 1934"checksum smol_str 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "378286eaa0fa9e6bbc351c9bfcc2320391c347e014f10cb177c26be18142e596"
1918"checksum stacker 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fb79482f57cf598af52094ec4cc3b3c42499d3ce5bd426f2ac41515b7e57404b" 1935"checksum stacker 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fb79482f57cf598af52094ec4cc3b3c42499d3ce5bd426f2ac41515b7e57404b"
1919"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" 1936"checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
1920"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" 1937"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
@@ -1934,7 +1951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1934"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" 1951"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
1935"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" 1952"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
1936"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" 1953"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
1937"checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" 1954"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
1938"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 1955"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
1939"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 1956"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
1940"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 1957"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index c45262efa..189cad7d0 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -1,8 +1,10 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_db::FileRange; 4use ra_db::FileRange;
3use ra_fmt::{leading_indent, reindent}; 5use ra_fmt::{leading_indent, reindent};
4use ra_syntax::{ 6use ra_syntax::{
5 algo::{find_covering_element, find_node_at_offset}, 7 algo::{self, find_covering_element, find_node_at_offset},
6 AstNode, SourceFile, SyntaxElement, SyntaxNode, SyntaxToken, TextRange, TextUnit, 8 AstNode, SourceFile, SyntaxElement, SyntaxNode, SyntaxToken, TextRange, TextUnit,
7 TokenAtOffset, 9 TokenAtOffset,
8}; 10};
@@ -177,6 +179,10 @@ impl AssistBuilder {
177 &mut self.edit 179 &mut self.edit
178 } 180 }
179 181
182 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) {
183 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit)
184 }
185
180 fn build(self) -> AssistAction { 186 fn build(self) -> AssistAction {
181 AssistAction { 187 AssistAction {
182 edit: self.edit.finish(), 188 edit: self.edit.finish(),
diff --git a/crates/ra_assists/src/assists/add_derive.rs b/crates/ra_assists/src/assists/add_derive.rs
index 9c88644df..77ecc33c9 100644
--- a/crates/ra_assists/src/assists/add_derive.rs
+++ b/crates/ra_assists/src/assists/add_derive.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::{ 4use ra_syntax::{
3 ast::{self, AstNode, AttrsOwner}, 5 ast::{self, AstNode, AttrsOwner},
@@ -13,7 +15,7 @@ pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
13 ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| { 15 ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| {
14 let derive_attr = nominal 16 let derive_attr = nominal
15 .attrs() 17 .attrs()
16 .filter_map(|x| x.as_call()) 18 .filter_map(|x| x.as_simple_call())
17 .filter(|(name, _arg)| name == "derive") 19 .filter(|(name, _arg)| name == "derive")
18 .map(|(_name, arg)| arg) 20 .map(|(_name, arg)| arg)
19 .next(); 21 .next();
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs
index 78f0f7f28..8c83dc987 100644
--- a/crates/ra_assists/src/assists/add_explicit_type.rs
+++ b/crates/ra_assists/src/assists/add_explicit_type.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::{db::HirDatabase, HirDisplay, Ty}; 3use hir::{db::HirDatabase, HirDisplay, Ty};
2use ra_syntax::{ 4use ra_syntax::{
3 ast::{self, AstNode, LetStmt, NameOwner}, 5 ast::{self, AstNode, LetStmt, NameOwner},
diff --git a/crates/ra_assists/src/assists/add_impl.rs b/crates/ra_assists/src/assists/add_impl.rs
index 4b61f4031..94801fbc9 100644
--- a/crates/ra_assists/src/assists/add_impl.rs
+++ b/crates/ra_assists/src/assists/add_impl.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use format_buf::format; 3use format_buf::format;
2use hir::db::HirDatabase; 4use hir::db::HirDatabase;
3use join_to_string::join; 5use join_to_string::join;
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs
index 23da1e65f..565b96fb5 100644
--- a/crates/ra_assists/src/assists/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs
@@ -1,10 +1,12 @@
1//! FIXME: write short doc here
2
1use hir::{db::HirDatabase, HasSource}; 3use hir::{db::HirDatabase, HasSource};
2use ra_syntax::{ 4use ra_syntax::{
3 ast::{self, make, AstNode, NameOwner}, 5 ast::{self, edit, make, AstNode, NameOwner},
4 SmolStr, 6 SmolStr,
5}; 7};
6 8
7use crate::{ast_editor::AstEditor, Assist, AssistCtx, AssistId}; 9use crate::{Assist, AssistCtx, AssistId};
8 10
9#[derive(PartialEq)] 11#[derive(PartialEq)]
10enum AddMissingImplMembersMode { 12enum AddMissingImplMembersMode {
@@ -75,37 +77,32 @@ fn add_missing_impl_members_inner(
75 77
76 ctx.add_action(AssistId(assist_id), label, |edit| { 78 ctx.add_action(AssistId(assist_id), label, |edit| {
77 let n_existing_items = impl_item_list.impl_items().count(); 79 let n_existing_items = impl_item_list.impl_items().count();
78 let items = missing_items.into_iter().map(|it| match it { 80 let items = missing_items
79 ast::ImplItem::FnDef(def) => strip_docstring(add_body(def).into()), 81 .into_iter()
80 _ => strip_docstring(it), 82 .map(|it| match it {
81 }); 83 ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)),
82 let mut ast_editor = AstEditor::new(impl_item_list); 84 _ => it,
83 85 })
84 ast_editor.append_items(items); 86 .map(|it| edit::strip_attrs_and_docs(&it));
85 87 let new_impl_item_list = impl_item_list.append_items(items);
86 let first_new_item = ast_editor.ast().impl_items().nth(n_existing_items).unwrap(); 88 let cursor_position = {
87 let cursor_position = first_new_item.syntax().text_range().start(); 89 let first_new_item = new_impl_item_list.impl_items().nth(n_existing_items).unwrap();
88 ast_editor.into_text_edit(edit.text_edit_builder()); 90 first_new_item.syntax().text_range().start()
89 91 };
92
93 edit.replace_ast(impl_item_list, new_impl_item_list);
90 edit.set_cursor(cursor_position); 94 edit.set_cursor(cursor_position);
91 }); 95 });
92 96
93 ctx.build() 97 ctx.build()
94} 98}
95 99
96fn strip_docstring(item: ast::ImplItem) -> ast::ImplItem {
97 let mut ast_editor = AstEditor::new(item);
98 ast_editor.strip_attrs_and_docs();
99 ast_editor.ast().to_owned()
100}
101
102fn add_body(fn_def: ast::FnDef) -> ast::FnDef { 100fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
103 let mut ast_editor = AstEditor::new(fn_def.clone());
104 if fn_def.body().is_none() { 101 if fn_def.body().is_none() {
105 let body = make::block_from_expr(make::expr_unimplemented()); 102 fn_def.with_body(make::block_from_expr(make::expr_unimplemented()))
106 ast_editor.set_body(&body); 103 } else {
104 fn_def
107 } 105 }
108 ast_editor.ast().to_owned()
109} 106}
110 107
111/// Given an `ast::ImplBlock`, resolves the target trait (the one being 108/// Given an `ast::ImplBlock`, resolves the target trait (the one being
@@ -332,5 +329,4 @@ impl Foo for S {
332}", 329}",
333 ) 330 )
334 } 331 }
335
336} 332}
diff --git a/crates/ra_assists/src/assists/apply_demorgan.rs b/crates/ra_assists/src/assists/apply_demorgan.rs
new file mode 100644
index 000000000..5f2b0dd18
--- /dev/null
+++ b/crates/ra_assists/src/assists/apply_demorgan.rs
@@ -0,0 +1,102 @@
1//! This contains the functions associated with the demorgan assist.
2//! This assist transforms boolean expressions of the form `!a || !b` into
3//! `!(a && b)`.
4use hir::db::HirDatabase;
5use ra_syntax::ast::{self, AstNode};
6use ra_syntax::SyntaxNode;
7
8use crate::{Assist, AssistCtx, AssistId};
9
10/// Assist for applying demorgan's law
11///
12/// This transforms expressions of the form `!l || !r` into `!(l && r)`.
13/// This also works with `&&`. This assist can only be applied with the cursor
14/// on either `||` or `&&`, with both operands being a negation of some kind.
15/// This means something of the form `!x` or `x != y`.
16pub(crate) fn apply_demorgan(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
17 let expr = ctx.node_at_offset::<ast::BinExpr>()?;
18 let op = expr.op_kind()?;
19 let op_range = expr.op_token()?.text_range();
20 let opposite_op = opposite_logic_op(op)?;
21 let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
22 if !cursor_in_range {
23 return None;
24 }
25 let lhs = expr.lhs()?.syntax().clone();
26 let lhs_range = lhs.text_range();
27 let rhs = expr.rhs()?.syntax().clone();
28 let rhs_range = rhs.text_range();
29 let not_lhs = undo_negation(lhs)?;
30 let not_rhs = undo_negation(rhs)?;
31
32 ctx.add_action(AssistId("apply_demorgan"), "apply demorgan's law", |edit| {
33 edit.target(op_range);
34 edit.replace(op_range, opposite_op);
35 edit.replace(lhs_range, format!("!({}", not_lhs));
36 edit.replace(rhs_range, format!("{})", not_rhs));
37 });
38 ctx.build()
39}
40
41// Return the opposite text for a given logical operator, if it makes sense
42fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> {
43 match kind {
44 ast::BinOp::BooleanOr => Some("&&"),
45 ast::BinOp::BooleanAnd => Some("||"),
46 _ => None,
47 }
48}
49
50// This function tries to undo unary negation, or inequality
51fn undo_negation(node: SyntaxNode) -> Option<String> {
52 match ast::Expr::cast(node)? {
53 ast::Expr::BinExpr(bin) => match bin.op_kind()? {
54 ast::BinOp::NegatedEqualityTest => {
55 let lhs = bin.lhs()?.syntax().text();
56 let rhs = bin.rhs()?.syntax().text();
57 Some(format!("{} == {}", lhs, rhs))
58 }
59 _ => None,
60 },
61 ast::Expr::PrefixExpr(pe) => match pe.op_kind()? {
62 ast::PrefixOp::Not => {
63 let child = pe.expr()?.syntax().text();
64 Some(String::from(child))
65 }
66 _ => None,
67 },
68 _ => None,
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 use crate::helpers::{check_assist, check_assist_not_applicable};
77
78 #[test]
79 fn demorgan_turns_and_into_or() {
80 check_assist(apply_demorgan, "fn f() { !x &&<|> !x }", "fn f() { !(x ||<|> x) }")
81 }
82
83 #[test]
84 fn demorgan_turns_or_into_and() {
85 check_assist(apply_demorgan, "fn f() { !x ||<|> !x }", "fn f() { !(x &&<|> x) }")
86 }
87
88 #[test]
89 fn demorgan_removes_inequality() {
90 check_assist(apply_demorgan, "fn f() { x != x ||<|> !x }", "fn f() { !(x == x &&<|> x) }")
91 }
92
93 #[test]
94 fn demorgan_doesnt_apply_with_cursor_not_on_op() {
95 check_assist_not_applicable(apply_demorgan, "fn f() { <|> !x || !x }")
96 }
97
98 #[test]
99 fn demorgan_doesnt_apply_when_operands_arent_negated_already() {
100 check_assist_not_applicable(apply_demorgan, "fn f() { x ||<|> x }")
101 }
102}
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs
index 5aae98546..02c58e7c6 100644
--- a/crates/ra_assists/src/assists/auto_import.rs
+++ b/crates/ra_assists/src/assists/auto_import.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::{self, db::HirDatabase}; 3use hir::{self, db::HirDatabase};
2use ra_text_edit::TextEditBuilder; 4use ra_text_edit::TextEditBuilder;
3 5
@@ -448,7 +450,6 @@ fn make_assist_add_in_tree_list(
448 fmt_segments_raw(target, &mut buf); 450 fmt_segments_raw(target, &mut buf);
449 edit.insert(offset, buf); 451 edit.insert(offset, buf);
450 } else { 452 } else {
451
452 } 453 }
453} 454}
454 455
@@ -512,7 +513,7 @@ pub fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
512 hir::PathKind::Plain => {} 513 hir::PathKind::Plain => {}
513 hir::PathKind::Self_ => ps.push("self".into()), 514 hir::PathKind::Self_ => ps.push("self".into()),
514 hir::PathKind::Super => ps.push("super".into()), 515 hir::PathKind::Super => ps.push("super".into()),
515 hir::PathKind::Type(_) => return None, 516 hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None,
516 } 517 }
517 for s in path.segments.iter() { 518 for s in path.segments.iter() {
518 ps.push(s.name.to_string().into()); 519 ps.push(s.name.to_string().into());
diff --git a/crates/ra_assists/src/assists/change_visibility.rs b/crates/ra_assists/src/assists/change_visibility.rs
index 60c74debc..df92c6b67 100644
--- a/crates/ra_assists/src/assists/change_visibility.rs
+++ b/crates/ra_assists/src/assists/change_visibility.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::{ 4use ra_syntax::{
3 ast::{self, NameOwner, VisibilityOwner}, 5 ast::{self, NameOwner, VisibilityOwner},
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs
index db82db89a..7335cce09 100644
--- a/crates/ra_assists/src/assists/fill_match_arms.rs
+++ b/crates/ra_assists/src/assists/fill_match_arms.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::iter; 3use std::iter;
2 4
3use hir::{db::HirDatabase, Adt, HasSource}; 5use hir::{db::HirDatabase, Adt, HasSource};
diff --git a/crates/ra_assists/src/assists/flip_binexpr.rs b/crates/ra_assists/src/assists/flip_binexpr.rs
index b55b36a8e..c51035282 100644
--- a/crates/ra_assists/src/assists/flip_binexpr.rs
+++ b/crates/ra_assists/src/assists/flip_binexpr.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::ast::{AstNode, BinExpr, BinOp}; 4use ra_syntax::ast::{AstNode, BinExpr, BinOp};
3 5
diff --git a/crates/ra_assists/src/assists/flip_comma.rs b/crates/ra_assists/src/assists/flip_comma.rs
index 5ee7561bc..e31cc5e7d 100644
--- a/crates/ra_assists/src/assists/flip_comma.rs
+++ b/crates/ra_assists/src/assists/flip_comma.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::{algo::non_trivia_sibling, Direction, T}; 4use ra_syntax::{algo::non_trivia_sibling, Direction, T};
3 5
diff --git a/crates/ra_assists/src/assists/inline_local_variable.rs b/crates/ra_assists/src/assists/inline_local_variable.rs
index eedb29199..9bd64decc 100644
--- a/crates/ra_assists/src/assists/inline_local_variable.rs
+++ b/crates/ra_assists/src/assists/inline_local_variable.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::{ 4use ra_syntax::{
3 ast::{self, AstNode, AstToken}, 5 ast::{self, AstNode, AstToken},
diff --git a/crates/ra_assists/src/assists/introduce_variable.rs b/crates/ra_assists/src/assists/introduce_variable.rs
index 470ffe120..43378c4b0 100644
--- a/crates/ra_assists/src/assists/introduce_variable.rs
+++ b/crates/ra_assists/src/assists/introduce_variable.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use format_buf::format; 3use format_buf::format;
2use hir::db::HirDatabase; 4use hir::db::HirDatabase;
3use ra_syntax::{ 5use ra_syntax::{
diff --git a/crates/ra_assists/src/assists/merge_match_arms.rs b/crates/ra_assists/src/assists/merge_match_arms.rs
index 3b6a99895..17baa98f9 100644
--- a/crates/ra_assists/src/assists/merge_match_arms.rs
+++ b/crates/ra_assists/src/assists/merge_match_arms.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{Assist, AssistCtx, AssistId, TextRange, TextUnit}; 3use crate::{Assist, AssistCtx, AssistId, TextRange, TextUnit};
2use hir::db::HirDatabase; 4use hir::db::HirDatabase;
3use ra_syntax::ast::{AstNode, MatchArm}; 5use ra_syntax::ast::{AstNode, MatchArm};
diff --git a/crates/ra_assists/src/assists/move_bounds.rs b/crates/ra_assists/src/assists/move_bounds.rs
index fd4bdc55c..f791d22b0 100644
--- a/crates/ra_assists/src/assists/move_bounds.rs
+++ b/crates/ra_assists/src/assists/move_bounds.rs
@@ -1,11 +1,13 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::{ 4use ra_syntax::{
3 ast::{self, make, AstNode, NameOwner, TypeBoundsOwner}, 5 ast::{self, edit, make, AstNode, NameOwner, TypeBoundsOwner},
4 SyntaxElement, 6 SyntaxElement,
5 SyntaxKind::*, 7 SyntaxKind::*,
6}; 8};
7 9
8use crate::{ast_editor::AstEditor, Assist, AssistCtx, AssistId}; 10use crate::{Assist, AssistCtx, AssistId};
9 11
10pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 12pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let type_param_list = ctx.node_at_offset::<ast::TypeParamList>()?; 13 let type_param_list = ctx.node_at_offset::<ast::TypeParamList>()?;
@@ -39,14 +41,12 @@ pub(crate) fn move_bounds_to_where_clause(mut ctx: AssistCtx<impl HirDatabase>)
39 .type_params() 41 .type_params()
40 .filter(|it| it.type_bound_list().is_some()) 42 .filter(|it| it.type_bound_list().is_some())
41 .map(|type_param| { 43 .map(|type_param| {
42 let without_bounds = 44 let without_bounds = type_param.remove_bounds();
43 AstEditor::new(type_param.clone()).remove_bounds().ast().clone();
44 (type_param, without_bounds) 45 (type_param, without_bounds)
45 }); 46 });
46 47
47 let mut ast_editor = AstEditor::new(type_param_list.clone()); 48 let new_type_param_list = edit::replace_descendants(&type_param_list, new_params);
48 ast_editor.replace_descendants(new_params); 49 edit.replace_ast(type_param_list.clone(), new_type_param_list);
49 ast_editor.into_text_edit(edit.text_edit_builder());
50 50
51 let where_clause = { 51 let where_clause = {
52 let predicates = type_param_list.type_params().filter_map(build_predicate); 52 let predicates = type_param_list.type_params().filter_map(build_predicate);
diff --git a/crates/ra_assists/src/assists/move_guard.rs b/crates/ra_assists/src/assists/move_guard.rs
index 699221e33..51aea6334 100644
--- a/crates/ra_assists/src/assists/move_guard.rs
+++ b/crates/ra_assists/src/assists/move_guard.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::{ 4use ra_syntax::{
3 ast, 5 ast,
diff --git a/crates/ra_assists/src/assists/raw_string.rs b/crates/ra_assists/src/assists/raw_string.rs
index 200aaa59a..2d2e31e51 100644
--- a/crates/ra_assists/src/assists/raw_string.rs
+++ b/crates/ra_assists/src/assists/raw_string.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::db::HirDatabase; 3use hir::db::HirDatabase;
2use ra_syntax::{ast::AstNode, ast::Literal, TextRange, TextUnit}; 4use ra_syntax::{ast::AstNode, ast::Literal, TextRange, TextUnit};
3use rustc_lexer; 5use rustc_lexer;
diff --git a/crates/ra_assists/src/assists/remove_dbg.rs b/crates/ra_assists/src/assists/remove_dbg.rs
index 870133fda..1a7e2b305 100644
--- a/crates/ra_assists/src/assists/remove_dbg.rs
+++ b/crates/ra_assists/src/assists/remove_dbg.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{Assist, AssistCtx, AssistId}; 3use crate::{Assist, AssistCtx, AssistId};
2use hir::db::HirDatabase; 4use hir::db::HirDatabase;
3use ra_syntax::{ 5use ra_syntax::{
diff --git a/crates/ra_assists/src/assists/replace_if_let_with_match.rs b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
index 401835c57..749ff338a 100644
--- a/crates/ra_assists/src/assists/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use format_buf::format; 3use format_buf::format;
2use hir::db::HirDatabase; 4use hir::db::HirDatabase;
3use ra_fmt::extract_trivial_expression; 5use ra_fmt::extract_trivial_expression;
diff --git a/crates/ra_assists/src/assists/split_import.rs b/crates/ra_assists/src/assists/split_import.rs
index 2c1edddb9..fe3e64af5 100644
--- a/crates/ra_assists/src/assists/split_import.rs
+++ b/crates/ra_assists/src/assists/split_import.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::iter::successors; 3use std::iter::successors;
2 4
3use hir::db::HirDatabase; 5use hir::db::HirDatabase;
@@ -49,13 +51,13 @@ mod tests {
49 fn split_import_works_with_trees() { 51 fn split_import_works_with_trees() {
50 check_assist( 52 check_assist(
51 split_import, 53 split_import,
52 "use algo:<|>:visitor::{Visitor, visit}", 54 "use crate:<|>:db::{RootDatabase, FileSymbol}",
53 "use algo::{<|>visitor::{Visitor, visit}}", 55 "use crate::{<|>db::{RootDatabase, FileSymbol}}",
54 ) 56 )
55 } 57 }
56 58
57 #[test] 59 #[test]
58 fn split_import_target() { 60 fn split_import_target() {
59 check_assist_target(split_import, "use algo::<|>visitor::{Visitor, visit}", "::"); 61 check_assist_target(split_import, "use crate::<|>db::{RootDatabase, FileSymbol}", "::");
60 } 62 }
61} 63}
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs
deleted file mode 100644
index 2a685f26e..000000000
--- a/crates/ra_assists/src/ast_editor.rs
+++ /dev/null
@@ -1,315 +0,0 @@
1use std::{iter, ops::RangeInclusive};
2
3use arrayvec::ArrayVec;
4use rustc_hash::FxHashMap;
5
6use ra_fmt::leading_indent;
7use ra_syntax::{
8 algo,
9 ast::{self, TypeBoundsOwner},
10 AstNode, Direction, InsertPosition, SyntaxElement,
11 SyntaxKind::*,
12 T,
13};
14use ra_text_edit::TextEditBuilder;
15
16pub struct AstEditor<N: AstNode> {
17 original_ast: N,
18 ast: N,
19}
20
21impl<N: AstNode> AstEditor<N> {
22 pub fn new(node: N) -> AstEditor<N>
23 where
24 N: Clone,
25 {
26 AstEditor { original_ast: node.clone(), ast: node }
27 }
28
29 pub fn into_text_edit(self, builder: &mut TextEditBuilder) {
30 for (from, to) in algo::diff(&self.original_ast.syntax(), self.ast().syntax()) {
31 builder.replace(from.text_range(), to.to_string())
32 }
33 }
34
35 pub fn ast(&self) -> &N {
36 &self.ast
37 }
38
39 pub fn replace_descendants<T: AstNode>(
40 &mut self,
41 replacement_map: impl Iterator<Item = (T, T)>,
42 ) -> &mut Self {
43 let map = replacement_map
44 .map(|(from, to)| (from.syntax().clone().into(), to.syntax().clone().into()))
45 .collect::<FxHashMap<_, _>>();
46 let new_syntax = algo::replace_descendants(self.ast.syntax(), &map);
47 self.ast = N::cast(new_syntax).unwrap();
48 self
49 }
50
51 #[must_use]
52 fn insert_children(
53 &self,
54 position: InsertPosition<SyntaxElement>,
55 mut to_insert: impl Iterator<Item = SyntaxElement>,
56 ) -> N {
57 let new_syntax = algo::insert_children(self.ast().syntax(), position, &mut to_insert);
58 N::cast(new_syntax).unwrap()
59 }
60
61 #[must_use]
62 fn replace_children(
63 &self,
64 to_delete: RangeInclusive<SyntaxElement>,
65 mut to_insert: impl Iterator<Item = SyntaxElement>,
66 ) -> N {
67 let new_syntax = algo::replace_children(self.ast().syntax(), to_delete, &mut to_insert);
68 N::cast(new_syntax).unwrap()
69 }
70
71 fn do_make_multiline(&mut self) {
72 let l_curly =
73 match self.ast().syntax().children_with_tokens().find(|it| it.kind() == T!['{']) {
74 Some(it) => it,
75 None => return,
76 };
77 let sibling = match l_curly.next_sibling_or_token() {
78 Some(it) => it,
79 None => return,
80 };
81 let existing_ws = match sibling.as_token() {
82 None => None,
83 Some(tok) if tok.kind() != WHITESPACE => None,
84 Some(ws) => {
85 if ws.text().contains('\n') {
86 return;
87 }
88 Some(ws.clone())
89 }
90 };
91
92 let indent = leading_indent(self.ast().syntax()).unwrap_or("".into());
93 let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
94 let to_insert = iter::once(ws.ws().into());
95 self.ast = match existing_ws {
96 None => self.insert_children(InsertPosition::After(l_curly), to_insert),
97 Some(ws) => {
98 self.replace_children(RangeInclusive::new(ws.clone().into(), ws.into()), to_insert)
99 }
100 };
101 }
102}
103
104impl AstEditor<ast::RecordFieldList> {
105 pub fn append_field(&mut self, field: &ast::RecordField) {
106 self.insert_field(InsertPosition::Last, field)
107 }
108
109 pub fn insert_field(
110 &mut self,
111 position: InsertPosition<&'_ ast::RecordField>,
112 field: &ast::RecordField,
113 ) {
114 let is_multiline = self.ast().syntax().text().contains_char('\n');
115 let ws;
116 let space = if is_multiline {
117 ws = tokens::WsBuilder::new(&format!(
118 "\n{} ",
119 leading_indent(self.ast().syntax()).unwrap_or("".into())
120 ));
121 ws.ws()
122 } else {
123 tokens::single_space()
124 };
125
126 let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new();
127 to_insert.push(space.into());
128 to_insert.push(field.syntax().clone().into());
129 to_insert.push(tokens::comma().into());
130
131 macro_rules! after_l_curly {
132 () => {{
133 let anchor = match self.l_curly() {
134 Some(it) => it,
135 None => return,
136 };
137 InsertPosition::After(anchor)
138 }};
139 }
140
141 macro_rules! after_field {
142 ($anchor:expr) => {
143 if let Some(comma) = $anchor
144 .syntax()
145 .siblings_with_tokens(Direction::Next)
146 .find(|it| it.kind() == T![,])
147 {
148 InsertPosition::After(comma)
149 } else {
150 to_insert.insert(0, tokens::comma().into());
151 InsertPosition::After($anchor.syntax().clone().into())
152 }
153 };
154 };
155
156 let position = match position {
157 InsertPosition::First => after_l_curly!(),
158 InsertPosition::Last => {
159 if !is_multiline {
160 // don't insert comma before curly
161 to_insert.pop();
162 }
163 match self.ast().fields().last() {
164 Some(it) => after_field!(it),
165 None => after_l_curly!(),
166 }
167 }
168 InsertPosition::Before(anchor) => {
169 InsertPosition::Before(anchor.syntax().clone().into())
170 }
171 InsertPosition::After(anchor) => after_field!(anchor),
172 };
173
174 self.ast = self.insert_children(position, to_insert.iter().cloned());
175 }
176
177 fn l_curly(&self) -> Option<SyntaxElement> {
178 self.ast().syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
179 }
180}
181
182impl AstEditor<ast::ItemList> {
183 pub fn append_items(&mut self, items: impl Iterator<Item = ast::ImplItem>) {
184 if !self.ast().syntax().text().contains_char('\n') {
185 self.do_make_multiline();
186 }
187 items.for_each(|it| self.append_item(it));
188 }
189
190 pub fn append_item(&mut self, item: ast::ImplItem) {
191 let (indent, position) = match self.ast().impl_items().last() {
192 Some(it) => (
193 leading_indent(it.syntax()).unwrap_or_default().to_string(),
194 InsertPosition::After(it.syntax().clone().into()),
195 ),
196 None => match self.l_curly() {
197 Some(it) => (
198 " ".to_string() + &leading_indent(self.ast().syntax()).unwrap_or_default(),
199 InsertPosition::After(it),
200 ),
201 None => return,
202 },
203 };
204 let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
205 let to_insert: ArrayVec<[SyntaxElement; 2]> =
206 [ws.ws().into(), item.syntax().clone().into()].into();
207 self.ast = self.insert_children(position, to_insert.into_iter());
208 }
209
210 fn l_curly(&self) -> Option<SyntaxElement> {
211 self.ast().syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
212 }
213}
214
215impl AstEditor<ast::ImplItem> {
216 pub fn strip_attrs_and_docs(&mut self) {
217 while let Some(start) = self
218 .ast()
219 .syntax()
220 .children_with_tokens()
221 .find(|it| it.kind() == ATTR || it.kind() == COMMENT)
222 {
223 let end = match &start.next_sibling_or_token() {
224 Some(el) if el.kind() == WHITESPACE => el.clone(),
225 Some(_) | None => start.clone(),
226 };
227 self.ast = self.replace_children(RangeInclusive::new(start, end), iter::empty());
228 }
229 }
230}
231
232impl AstEditor<ast::FnDef> {
233 pub fn set_body(&mut self, body: &ast::Block) {
234 let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
235 let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.ast().body() {
236 old_body.syntax().clone().into()
237 } else if let Some(semi) = self.ast().semicolon_token() {
238 to_insert.push(tokens::single_space().into());
239 semi.into()
240 } else {
241 to_insert.push(tokens::single_space().into());
242 to_insert.push(body.syntax().clone().into());
243 self.ast = self.insert_children(InsertPosition::Last, to_insert.into_iter());
244 return;
245 };
246 to_insert.push(body.syntax().clone().into());
247 let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi);
248 self.ast = self.replace_children(replace_range, to_insert.into_iter())
249 }
250}
251
252impl AstEditor<ast::TypeParam> {
253 pub fn remove_bounds(&mut self) -> &mut Self {
254 let colon = match self.ast.colon_token() {
255 Some(it) => it,
256 None => return self,
257 };
258 let end = match self.ast.type_bound_list() {
259 Some(it) => it.syntax().clone().into(),
260 None => colon.clone().into(),
261 };
262 self.ast = self.replace_children(RangeInclusive::new(colon.into(), end), iter::empty());
263 self
264 }
265}
266
267mod tokens {
268 use once_cell::sync::Lazy;
269 use ra_syntax::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T};
270
271 static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;"));
272
273 pub(crate) fn comma() -> SyntaxToken {
274 SOURCE_FILE
275 .tree()
276 .syntax()
277 .descendants_with_tokens()
278 .filter_map(|it| it.into_token())
279 .find(|it| it.kind() == T![,])
280 .unwrap()
281 }
282
283 pub(crate) fn single_space() -> SyntaxToken {
284 SOURCE_FILE
285 .tree()
286 .syntax()
287 .descendants_with_tokens()
288 .filter_map(|it| it.into_token())
289 .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ")
290 .unwrap()
291 }
292
293 #[allow(unused)]
294 pub(crate) fn single_newline() -> SyntaxToken {
295 SOURCE_FILE
296 .tree()
297 .syntax()
298 .descendants_with_tokens()
299 .filter_map(|it| it.into_token())
300 .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n")
301 .unwrap()
302 }
303
304 pub(crate) struct WsBuilder(SourceFile);
305
306 impl WsBuilder {
307 pub(crate) fn new(text: &str) -> WsBuilder {
308 WsBuilder(SourceFile::parse(text).ok().unwrap())
309 }
310 pub(crate) fn ws(&self) -> SyntaxToken {
311 self.0.syntax().first_child_or_token().unwrap().into_token().unwrap()
312 }
313 }
314
315}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 3ca3320f7..d2376c475 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -7,7 +7,6 @@
7 7
8mod assist_ctx; 8mod assist_ctx;
9mod marks; 9mod marks;
10pub mod ast_editor;
11 10
12use hir::db::HirDatabase; 11use hir::db::HirDatabase;
13use itertools::Itertools; 12use itertools::Itertools;
@@ -93,6 +92,7 @@ mod assists {
93 mod add_derive; 92 mod add_derive;
94 mod add_explicit_type; 93 mod add_explicit_type;
95 mod add_impl; 94 mod add_impl;
95 mod apply_demorgan;
96 mod flip_comma; 96 mod flip_comma;
97 mod flip_binexpr; 97 mod flip_binexpr;
98 mod change_visibility; 98 mod change_visibility;
@@ -114,6 +114,7 @@ mod assists {
114 add_derive::add_derive, 114 add_derive::add_derive,
115 add_explicit_type::add_explicit_type, 115 add_explicit_type::add_explicit_type,
116 add_impl::add_impl, 116 add_impl::add_impl,
117 apply_demorgan::apply_demorgan,
117 change_visibility::change_visibility, 118 change_visibility::change_visibility,
118 fill_match_arms::fill_match_arms, 119 fill_match_arms::fill_match_arms,
119 merge_match_arms::merge_match_arms, 120 merge_match_arms::merge_match_arms,
diff --git a/crates/ra_assists/src/marks.rs b/crates/ra_assists/src/marks.rs
index a29f9f658..c20e4db9e 100644
--- a/crates/ra_assists/src/marks.rs
+++ b/crates/ra_assists/src/marks.rs
@@ -1,3 +1,5 @@
1//! See test_utils/src/marks.rs
2
1test_utils::marks!( 3test_utils::marks!(
2 introduce_var_in_comment_is_not_applicable 4 introduce_var_in_comment_is_not_applicable
3 test_introduce_var_expr_stmt 5 test_introduce_var_expr_stmt
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index ffc9e16bb..a5fc2a23e 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{collections::HashSet, error::Error, path::Path}; 3use std::{collections::HashSet, error::Error, path::Path};
2 4
3use rustc_hash::FxHashMap; 5use rustc_hash::FxHashMap;
@@ -5,7 +7,7 @@ use rustc_hash::FxHashMap;
5use crossbeam_channel::{unbounded, Receiver}; 7use crossbeam_channel::{unbounded, Receiver};
6use ra_db::{CrateGraph, FileId, SourceRootId}; 8use ra_db::{CrateGraph, FileId, SourceRootId};
7use ra_ide_api::{AnalysisChange, AnalysisHost, FeatureFlags}; 9use ra_ide_api::{AnalysisChange, AnalysisHost, FeatureFlags};
8use ra_project_model::{PackageRoot, ProjectWorkspace}; 10use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace};
9use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; 11use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
10use ra_vfs_glob::RustPackageFilterBuilder; 12use ra_vfs_glob::RustPackageFilterBuilder;
11 13
@@ -39,11 +41,17 @@ pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId,
39 sender, 41 sender,
40 Watch(false), 42 Watch(false),
41 ); 43 );
42 let (crate_graph, _crate_names) = ws.to_crate_graph(&mut |path: &Path| { 44
43 let vfs_file = vfs.load(path); 45 // FIXME: cfg options?
44 log::debug!("vfs file {:?} -> {:?}", path, vfs_file); 46 let default_cfg_options =
45 vfs_file.map(vfs_file_to_id) 47 get_rustc_cfg_options().atom("test".into()).atom("debug_assertion".into());
46 }); 48
49 let (crate_graph, _crate_names) =
50 ws.to_crate_graph(&default_cfg_options, &mut |path: &Path| {
51 let vfs_file = vfs.load(path);
52 log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
53 vfs_file.map(vfs_file_to_id)
54 });
47 log::debug!("crate graph: {:?}", crate_graph); 55 log::debug!("crate graph: {:?}", crate_graph);
48 56
49 let source_roots = roots 57 let source_roots = roots
diff --git a/crates/ra_cfg/Cargo.toml b/crates/ra_cfg/Cargo.toml
new file mode 100644
index 000000000..b28affc3a
--- /dev/null
+++ b/crates/ra_cfg/Cargo.toml
@@ -0,0 +1,14 @@
1[package]
2edition = "2018"
3name = "ra_cfg"
4version = "0.1.0"
5authors = ["rust-analyzer developers"]
6
7[dependencies]
8rustc-hash = "1.0.1"
9
10ra_syntax = { path = "../ra_syntax" }
11tt = { path = "../ra_tt", package = "ra_tt" }
12
13[dev-dependencies]
14mbe = { path = "../ra_mbe", package = "ra_mbe" }
diff --git a/crates/ra_cfg/src/cfg_expr.rs b/crates/ra_cfg/src/cfg_expr.rs
new file mode 100644
index 000000000..39d71851c
--- /dev/null
+++ b/crates/ra_cfg/src/cfg_expr.rs
@@ -0,0 +1,132 @@
1//! The condition expression used in `#[cfg(..)]` attributes.
2//!
3//! See: https://doc.rust-lang.org/reference/conditional-compilation.html#conditional-compilation
4
5use std::slice::Iter as SliceIter;
6
7use ra_syntax::SmolStr;
8use tt::{Leaf, Subtree, TokenTree};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum CfgExpr {
12 Invalid,
13 Atom(SmolStr),
14 KeyValue { key: SmolStr, value: SmolStr },
15 All(Vec<CfgExpr>),
16 Any(Vec<CfgExpr>),
17 Not(Box<CfgExpr>),
18}
19
20impl CfgExpr {
21 /// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates.
22 pub fn fold(&self, query: &dyn Fn(&SmolStr, Option<&SmolStr>) -> bool) -> Option<bool> {
23 match self {
24 CfgExpr::Invalid => None,
25 CfgExpr::Atom(name) => Some(query(name, None)),
26 CfgExpr::KeyValue { key, value } => Some(query(key, Some(value))),
27 CfgExpr::All(preds) => {
28 preds.iter().try_fold(true, |s, pred| Some(s && pred.fold(query)?))
29 }
30 CfgExpr::Any(preds) => {
31 preds.iter().try_fold(false, |s, pred| Some(s || pred.fold(query)?))
32 }
33 CfgExpr::Not(pred) => pred.fold(query).map(|s| !s),
34 }
35 }
36}
37
38pub fn parse_cfg(tt: &Subtree) -> CfgExpr {
39 next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid)
40}
41
42fn next_cfg_expr(it: &mut SliceIter<tt::TokenTree>) -> Option<CfgExpr> {
43 let name = match it.next() {
44 None => return None,
45 Some(TokenTree::Leaf(Leaf::Ident(ident))) => ident.text.clone(),
46 Some(_) => return Some(CfgExpr::Invalid),
47 };
48
49 // Peek
50 let ret = match it.as_slice().first() {
51 Some(TokenTree::Leaf(Leaf::Punct(punct))) if punct.char == '=' => {
52 match it.as_slice().get(1) {
53 Some(TokenTree::Leaf(Leaf::Literal(literal))) => {
54 it.next();
55 it.next();
56 // FIXME: escape? raw string?
57 let value =
58 SmolStr::new(literal.text.trim_start_matches('"').trim_end_matches('"'));
59 CfgExpr::KeyValue { key: name, value }
60 }
61 _ => return Some(CfgExpr::Invalid),
62 }
63 }
64 Some(TokenTree::Subtree(subtree)) => {
65 it.next();
66 let mut sub_it = subtree.token_trees.iter();
67 let mut subs = std::iter::from_fn(|| next_cfg_expr(&mut sub_it)).collect();
68 match name.as_str() {
69 "all" => CfgExpr::All(subs),
70 "any" => CfgExpr::Any(subs),
71 "not" => CfgExpr::Not(Box::new(subs.pop().unwrap_or(CfgExpr::Invalid))),
72 _ => CfgExpr::Invalid,
73 }
74 }
75 _ => CfgExpr::Atom(name),
76 };
77
78 // Eat comma separator
79 if let Some(TokenTree::Leaf(Leaf::Punct(punct))) = it.as_slice().first() {
80 if punct.char == ',' {
81 it.next();
82 }
83 }
84 Some(ret)
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 use mbe::ast_to_token_tree;
92 use ra_syntax::ast::{self, AstNode};
93
94 fn assert_parse_result(input: &str, expected: CfgExpr) {
95 let source_file = ast::SourceFile::parse(input).ok().unwrap();
96 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
97 let (tt, _) = ast_to_token_tree(&tt).unwrap();
98 assert_eq!(parse_cfg(&tt), expected);
99 }
100
101 #[test]
102 fn test_cfg_expr_parser() {
103 assert_parse_result("#![cfg(foo)]", CfgExpr::Atom("foo".into()));
104 assert_parse_result("#![cfg(foo,)]", CfgExpr::Atom("foo".into()));
105 assert_parse_result(
106 "#![cfg(not(foo))]",
107 CfgExpr::Not(Box::new(CfgExpr::Atom("foo".into()))),
108 );
109 assert_parse_result("#![cfg(foo(bar))]", CfgExpr::Invalid);
110
111 // Only take the first
112 assert_parse_result(r#"#![cfg(foo, bar = "baz")]"#, CfgExpr::Atom("foo".into()));
113
114 assert_parse_result(
115 r#"#![cfg(all(foo, bar = "baz"))]"#,
116 CfgExpr::All(vec![
117 CfgExpr::Atom("foo".into()),
118 CfgExpr::KeyValue { key: "bar".into(), value: "baz".into() },
119 ]),
120 );
121
122 assert_parse_result(
123 r#"#![cfg(any(not(), all(), , bar = "baz",))]"#,
124 CfgExpr::Any(vec![
125 CfgExpr::Not(Box::new(CfgExpr::Invalid)),
126 CfgExpr::All(vec![]),
127 CfgExpr::Invalid,
128 CfgExpr::KeyValue { key: "bar".into(), value: "baz".into() },
129 ]),
130 );
131 }
132}
diff --git a/crates/ra_cfg/src/lib.rs b/crates/ra_cfg/src/lib.rs
new file mode 100644
index 000000000..e1c92fbba
--- /dev/null
+++ b/crates/ra_cfg/src/lib.rs
@@ -0,0 +1,61 @@
1//! ra_cfg defines conditional compiling options, `cfg` attibute parser and evaluator
2use std::iter::IntoIterator;
3
4use ra_syntax::SmolStr;
5use rustc_hash::FxHashSet;
6
7mod cfg_expr;
8
9pub use cfg_expr::{parse_cfg, CfgExpr};
10
11/// Configuration options used for conditional compilition on items with `cfg` attributes.
12/// We have two kind of options in different namespaces: atomic options like `unix`, and
13/// key-value options like `target_arch="x86"`.
14///
15/// Note that for key-value options, one key can have multiple values (but not none).
16/// `feature` is an example. We have both `feature="foo"` and `feature="bar"` if features
17/// `foo` and `bar` are both enabled. And here, we store key-value options as a set of tuple
18/// of key and value in `key_values`.
19///
20/// See: https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options
21#[derive(Debug, Clone, PartialEq, Eq, Default)]
22pub struct CfgOptions {
23 atoms: FxHashSet<SmolStr>,
24 key_values: FxHashSet<(SmolStr, SmolStr)>,
25}
26
27impl CfgOptions {
28 pub fn check(&self, cfg: &CfgExpr) -> Option<bool> {
29 cfg.fold(&|key, value| match value {
30 None => self.atoms.contains(key),
31 Some(value) => self.key_values.contains(&(key.clone(), value.clone())),
32 })
33 }
34
35 pub fn is_cfg_enabled(&self, attr: &tt::Subtree) -> Option<bool> {
36 self.check(&parse_cfg(attr))
37 }
38
39 pub fn atom(mut self, name: SmolStr) -> CfgOptions {
40 self.atoms.insert(name);
41 self
42 }
43
44 pub fn key_value(mut self, key: SmolStr, value: SmolStr) -> CfgOptions {
45 self.key_values.insert((key, value));
46 self
47 }
48
49 /// Shortcut to set features
50 pub fn features(mut self, iter: impl IntoIterator<Item = SmolStr>) -> CfgOptions {
51 for feat in iter {
52 self = self.key_value("feature".into(), feat);
53 }
54 self
55 }
56
57 pub fn remove_atom(mut self, name: &SmolStr) -> CfgOptions {
58 self.atoms.remove(name);
59 self
60 }
61}
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml
index d42ac3ad4..67e727a88 100644
--- a/crates/ra_cli/Cargo.toml
+++ b/crates/ra_cli/Cargo.toml
@@ -6,7 +6,7 @@ authors = ["rust-analyzer developers"]
6publish = false 6publish = false
7 7
8[dependencies] 8[dependencies]
9pico-args = "0.2.0" 9pico-args = "0.3.0"
10flexi_logger = "0.14.0" 10flexi_logger = "0.14.0"
11indicatif = "0.11.0" 11indicatif = "0.11.0"
12 12
diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs
index 01b96ec58..727f1e62b 100644
--- a/crates/ra_cli/src/analysis_bench.rs
+++ b/crates/ra_cli/src/analysis_bench.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{ 3use std::{
2 path::{Path, PathBuf}, 4 path::{Path, PathBuf},
3 sync::Arc, 5 sync::Arc,
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index 6b1e44a2c..a8a110bd9 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{collections::HashSet, fmt::Write, path::Path, time::Instant}; 3use std::{collections::HashSet, fmt::Write, path::Path, time::Instant};
2 4
3use ra_db::SourceDatabase; 5use ra_db::SourceDatabase;
diff --git a/crates/ra_cli/src/help.rs b/crates/ra_cli/src/help.rs
index 2a74b8733..d3c4c7d0b 100644
--- a/crates/ra_cli/src/help.rs
+++ b/crates/ra_cli/src/help.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1pub const GLOBAL_HELP: &str = "ra-cli 3pub const GLOBAL_HELP: &str = "ra-cli
2 4
3USAGE: 5USAGE:
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index 8b91ba3e9..2405eb4f4 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod analysis_stats; 3mod analysis_stats;
2mod analysis_bench; 4mod analysis_bench;
3mod help; 5mod help;
@@ -93,7 +95,7 @@ fn main() -> Result<()> {
93 (true, true) => Err("Invalid flags: -q conflicts with -v")?, 95 (true, true) => Err("Invalid flags: -q conflicts with -v")?,
94 }; 96 };
95 let memory_usage = matches.contains("--memory-usage"); 97 let memory_usage = matches.contains("--memory-usage");
96 let only: Option<String> = matches.value_from_str(["-o", "--only"])?; 98 let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?;
97 let path = { 99 let path = {
98 let mut trailing = matches.free()?; 100 let mut trailing = matches.free()?;
99 if trailing.len() != 1 { 101 if trailing.len() != 1 {
@@ -115,9 +117,9 @@ fn main() -> Result<()> {
115 return Ok(()); 117 return Ok(());
116 } 118 }
117 let verbose = matches.contains(["-v", "--verbose"]); 119 let verbose = matches.contains(["-v", "--verbose"]);
118 let path: String = matches.value_from_str("--path")?.unwrap_or_default(); 120 let path: String = matches.opt_value_from_str("--path")?.unwrap_or_default();
119 let highlight_path = matches.value_from_str("--highlight")?; 121 let highlight_path = matches.opt_value_from_str("--highlight")?;
120 let complete_path = matches.value_from_str("--complete")?; 122 let complete_path = matches.opt_value_from_str("--complete")?;
121 if highlight_path.is_some() && complete_path.is_some() { 123 if highlight_path.is_some() && complete_path.is_some() {
122 panic!("either --highlight or --complete must be set, not both") 124 panic!("either --highlight or --complete must be set, not both")
123 } 125 }
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index 2fac07bc5..c141f1a88 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -10,4 +10,5 @@ relative-path = "0.4.0"
10rustc-hash = "1.0" 10rustc-hash = "1.0"
11 11
12ra_syntax = { path = "../ra_syntax" } 12ra_syntax = { path = "../ra_syntax" }
13ra_cfg = { path = "../ra_cfg" }
13ra_prof = { path = "../ra_prof" } 14ra_prof = { path = "../ra_prof" }
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index a1ace61b6..23148096c 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -1,13 +1,15 @@
1/// This module specifies the input to rust-analyzer. In some sense, this is 1//! This module specifies the input to rust-analyzer. In some sense, this is
2/// **the** most important module, because all other fancy stuff is strictly 2//! **the** most important module, because all other fancy stuff is strictly
3/// derived from this input. 3//! derived from this input.
4/// 4//!
5/// Note that neither this module, nor any other part of the analyzer's core do 5//! Note that neither this module, nor any other part of the analyzer's core do
6/// actual IO. See `vfs` and `project_model` in the `ra_lsp_server` crate for how 6//! actual IO. See `vfs` and `project_model` in the `ra_lsp_server` crate for how
7/// actual IO is done and lowered to input. 7//! actual IO is done and lowered to input.
8
8use relative_path::{RelativePath, RelativePathBuf}; 9use relative_path::{RelativePath, RelativePathBuf};
9use rustc_hash::FxHashMap; 10use rustc_hash::FxHashMap;
10 11
12use ra_cfg::CfgOptions;
11use ra_syntax::SmolStr; 13use ra_syntax::SmolStr;
12use rustc_hash::FxHashSet; 14use rustc_hash::FxHashSet;
13 15
@@ -108,11 +110,12 @@ struct CrateData {
108 file_id: FileId, 110 file_id: FileId,
109 edition: Edition, 111 edition: Edition,
110 dependencies: Vec<Dependency>, 112 dependencies: Vec<Dependency>,
113 cfg_options: CfgOptions,
111} 114}
112 115
113impl CrateData { 116impl CrateData {
114 fn new(file_id: FileId, edition: Edition) -> CrateData { 117 fn new(file_id: FileId, edition: Edition, cfg_options: CfgOptions) -> CrateData {
115 CrateData { file_id, edition, dependencies: Vec::new() } 118 CrateData { file_id, edition, dependencies: Vec::new(), cfg_options }
116 } 119 }
117 120
118 fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) { 121 fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) {
@@ -133,13 +136,22 @@ impl Dependency {
133} 136}
134 137
135impl CrateGraph { 138impl CrateGraph {
136 pub fn add_crate_root(&mut self, file_id: FileId, edition: Edition) -> CrateId { 139 pub fn add_crate_root(
140 &mut self,
141 file_id: FileId,
142 edition: Edition,
143 cfg_options: CfgOptions,
144 ) -> CrateId {
137 let crate_id = CrateId(self.arena.len() as u32); 145 let crate_id = CrateId(self.arena.len() as u32);
138 let prev = self.arena.insert(crate_id, CrateData::new(file_id, edition)); 146 let prev = self.arena.insert(crate_id, CrateData::new(file_id, edition, cfg_options));
139 assert!(prev.is_none()); 147 assert!(prev.is_none());
140 crate_id 148 crate_id
141 } 149 }
142 150
151 pub fn cfg_options(&self, crate_id: CrateId) -> &CfgOptions {
152 &self.arena[&crate_id].cfg_options
153 }
154
143 pub fn add_dep( 155 pub fn add_dep(
144 &mut self, 156 &mut self,
145 from: CrateId, 157 from: CrateId,
@@ -220,14 +232,14 @@ impl CrateGraph {
220 232
221#[cfg(test)] 233#[cfg(test)]
222mod tests { 234mod tests {
223 use super::{CrateGraph, Edition::Edition2018, FileId, SmolStr}; 235 use super::{CfgOptions, CrateGraph, Edition::Edition2018, FileId, SmolStr};
224 236
225 #[test] 237 #[test]
226 fn it_should_panic_because_of_cycle_dependencies() { 238 fn it_should_panic_because_of_cycle_dependencies() {
227 let mut graph = CrateGraph::default(); 239 let mut graph = CrateGraph::default();
228 let crate1 = graph.add_crate_root(FileId(1u32), Edition2018); 240 let crate1 = graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default());
229 let crate2 = graph.add_crate_root(FileId(2u32), Edition2018); 241 let crate2 = graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default());
230 let crate3 = graph.add_crate_root(FileId(3u32), Edition2018); 242 let crate3 = graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default());
231 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok()); 243 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok());
232 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok()); 244 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok());
233 assert!(graph.add_dep(crate3, SmolStr::new("crate1"), crate1).is_err()); 245 assert!(graph.add_dep(crate3, SmolStr::new("crate1"), crate1).is_err());
@@ -236,9 +248,9 @@ mod tests {
236 #[test] 248 #[test]
237 fn it_works() { 249 fn it_works() {
238 let mut graph = CrateGraph::default(); 250 let mut graph = CrateGraph::default();
239 let crate1 = graph.add_crate_root(FileId(1u32), Edition2018); 251 let crate1 = graph.add_crate_root(FileId(1u32), Edition2018, CfgOptions::default());
240 let crate2 = graph.add_crate_root(FileId(2u32), Edition2018); 252 let crate2 = graph.add_crate_root(FileId(2u32), Edition2018, CfgOptions::default());
241 let crate3 = graph.add_crate_root(FileId(3u32), Edition2018); 253 let crate3 = graph.add_crate_root(FileId(3u32), Edition2018, CfgOptions::default());
242 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok()); 254 assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok());
243 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok()); 255 assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok());
244 } 256 }
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index c54791b7a..603daed37 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -32,11 +32,10 @@ pub trait CheckCanceled {
32 32
33 fn catch_canceled<F, T>(&self, f: F) -> Result<T, Canceled> 33 fn catch_canceled<F, T>(&self, f: F) -> Result<T, Canceled>
34 where 34 where
35 Self: Sized, 35 Self: Sized + panic::RefUnwindSafe,
36 F: FnOnce(&Self) -> T + panic::UnwindSafe, 36 F: FnOnce(&Self) -> T + panic::UnwindSafe,
37 { 37 {
38 let this = panic::AssertUnwindSafe(self); 38 panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() {
39 panic::catch_unwind(|| f(*this)).map_err(|err| match err.downcast::<Canceled>() {
40 Ok(canceled) => *canceled, 39 Ok(canceled) => *canceled,
41 Err(payload) => panic::resume_unwind(payload), 40 Err(payload) => panic::resume_unwind(payload),
42 }) 41 })
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index d9bed4dda..cc117f84d 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -15,6 +15,7 @@ once_cell = "1.0.1"
15 15
16ra_syntax = { path = "../ra_syntax" } 16ra_syntax = { path = "../ra_syntax" }
17ra_arena = { path = "../ra_arena" } 17ra_arena = { path = "../ra_arena" }
18ra_cfg = { path = "../ra_cfg" }
18ra_db = { path = "../ra_db" } 19ra_db = { path = "../ra_db" }
19mbe = { path = "../ra_mbe", package = "ra_mbe" } 20mbe = { path = "../ra_mbe", package = "ra_mbe" }
20tt = { path = "../ra_tt", package = "ra_tt" } 21tt = { path = "../ra_tt", package = "ra_tt" }
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index fbb4ff4d8..99d286215 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -133,7 +133,7 @@ impl VariantData {
133 .fields() 133 .fields()
134 .enumerate() 134 .enumerate()
135 .map(|(i, fd)| StructFieldData { 135 .map(|(i, fd)| StructFieldData {
136 name: Name::tuple_field_name(i), 136 name: Name::new_tuple_field(i),
137 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 137 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
138 }) 138 })
139 .collect(); 139 .collect();
diff --git a/crates/ra_hir/src/attr.rs b/crates/ra_hir/src/attr.rs
new file mode 100644
index 000000000..f67e80bfd
--- /dev/null
+++ b/crates/ra_hir/src/attr.rs
@@ -0,0 +1,80 @@
1//! A higher level attributes based on TokenTree, with also some shortcuts.
2
3use std::sync::Arc;
4
5use mbe::ast_to_token_tree;
6use ra_cfg::CfgOptions;
7use ra_syntax::{
8 ast::{self, AstNode, AttrsOwner},
9 SmolStr,
10};
11use tt::Subtree;
12
13use crate::{db::AstDatabase, path::Path, HirFileId, Source};
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub(crate) struct Attr {
17 pub(crate) path: Path,
18 pub(crate) input: Option<AttrInput>,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub enum AttrInput {
23 Literal(SmolStr),
24 TokenTree(Subtree),
25}
26
27impl Attr {
28 pub(crate) fn from_src(
29 Source { file_id, ast }: Source<ast::Attr>,
30 db: &impl AstDatabase,
31 ) -> Option<Attr> {
32 let path = Path::from_src(Source { file_id, ast: ast.path()? }, db)?;
33 let input = match ast.input() {
34 None => None,
35 Some(ast::AttrInput::Literal(lit)) => {
36 // FIXME: escape? raw string?
37 let value = lit.syntax().first_token()?.text().trim_matches('"').into();
38 Some(AttrInput::Literal(value))
39 }
40 Some(ast::AttrInput::TokenTree(tt)) => {
41 Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0))
42 }
43 };
44
45 Some(Attr { path, input })
46 }
47
48 pub(crate) fn from_attrs_owner(
49 file_id: HirFileId,
50 owner: &dyn AttrsOwner,
51 db: &impl AstDatabase,
52 ) -> Option<Arc<[Attr]>> {
53 let mut attrs = owner.attrs().peekable();
54 if attrs.peek().is_none() {
55 // Avoid heap allocation
56 return None;
57 }
58 Some(attrs.flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect())
59 }
60
61 pub(crate) fn is_simple_atom(&self, name: &str) -> bool {
62 // FIXME: Avoid cloning
63 self.path.as_ident().map_or(false, |s| s.to_string() == name)
64 }
65
66 pub(crate) fn as_cfg(&self) -> Option<&Subtree> {
67 if self.is_simple_atom("cfg") {
68 match &self.input {
69 Some(AttrInput::TokenTree(subtree)) => Some(subtree),
70 _ => None,
71 }
72 } else {
73 None
74 }
75 }
76
77 pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Option<bool> {
78 cfg_options.is_cfg_enabled(self.as_cfg()?)
79 }
80}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 20413cb3d..e3a7e8e3c 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1pub(crate) mod src; 3pub(crate) mod src;
2pub(crate) mod docs; 4pub(crate) mod docs;
3 5
@@ -339,10 +341,14 @@ pub struct Struct {
339} 341}
340 342
341impl Struct { 343impl Struct {
342 pub fn module(self, db: &impl HirDatabase) -> Module { 344 pub fn module(self, db: &impl DefDatabase) -> Module {
343 self.id.module(db) 345 self.id.module(db)
344 } 346 }
345 347
348 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
349 self.module(db).krate(db)
350 }
351
346 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 352 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
347 db.struct_data(self).name.clone() 353 db.struct_data(self).name.clone()
348 } 354 }
@@ -423,10 +429,14 @@ pub struct Enum {
423} 429}
424 430
425impl Enum { 431impl Enum {
426 pub fn module(self, db: &impl HirDatabase) -> Module { 432 pub fn module(self, db: &impl DefDatabase) -> Module {
427 self.id.module(db) 433 self.id.module(db)
428 } 434 }
429 435
436 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
437 self.module(db).krate(db)
438 }
439
430 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 440 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
431 db.enum_data(self).name.clone() 441 db.enum_data(self).name.clone()
432 } 442 }
@@ -514,7 +524,7 @@ impl Adt {
514 } 524 }
515 } 525 }
516 526
517 pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> { 527 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
518 match self { 528 match self {
519 Adt::Struct(s) => s.module(db), 529 Adt::Struct(s) => s.module(db),
520 Adt::Union(s) => s.module(db), 530 Adt::Union(s) => s.module(db),
diff --git a/crates/ra_hir/src/code_model/docs.rs b/crates/ra_hir/src/code_model/docs.rs
index 99edc5814..9675e397f 100644
--- a/crates/ra_hir/src/code_model/docs.rs
+++ b/crates/ra_hir/src/code_model/docs.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::sync::Arc; 3use std::sync::Arc;
2 4
3use ra_syntax::ast; 5use ra_syntax::ast;
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index c0cb27b47..fdae26906 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_syntax::{ 3use ra_syntax::{
2 ast::{self, AstNode}, 4 ast::{self, AstNode},
3 SyntaxNode, 5 SyntaxNode,
@@ -119,7 +121,7 @@ impl HasSource for TypeAlias {
119impl HasSource for MacroDef { 121impl HasSource for MacroDef {
120 type Ast = ast::MacroCall; 122 type Ast = ast::MacroCall;
121 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> { 123 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> {
122 Source { file_id: self.id.0.file_id(), ast: self.id.0.to_node(db) } 124 Source { file_id: self.id.ast_id.file_id(), ast: self.id.ast_id.to_node(db) }
123 } 125 }
124} 126}
125 127
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index deed1c62f..73d7d6fb6 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::sync::Arc; 3use std::sync::Arc;
2 4
3use ra_db::{salsa, SourceDatabase}; 5use ra_db::{salsa, SourceDatabase};
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 60da33695..9acdaf8ed 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{any::Any, fmt}; 3use std::{any::Any, fmt};
2 4
3use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, TextRange}; 5use ra_syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, TextRange};
diff --git a/crates/ra_hir/src/either.rs b/crates/ra_hir/src/either.rs
index 439e6ec87..83583ef8b 100644
--- a/crates/ra_hir/src/either.rs
+++ b/crates/ra_hir/src/either.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 3#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
2pub enum Either<A, B> { 4pub enum Either<A, B> {
3 A(A), 5 A(A),
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index b1bec2a68..d238741ba 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1pub(crate) mod lower; 3pub(crate) mod lower;
2pub(crate) mod scope; 4pub(crate) mod scope;
3pub(crate) mod validation; 5pub(crate) mod validation;
diff --git a/crates/ra_hir/src/expr/lower.rs b/crates/ra_hir/src/expr/lower.rs
index 61535d24f..50ea429ea 100644
--- a/crates/ra_hir/src/expr/lower.rs
+++ b/crates/ra_hir/src/expr/lower.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_arena::Arena; 3use ra_arena::Arena;
2use ra_syntax::{ 4use ra_syntax::{
3 ast::{ 5 ast::{
@@ -272,8 +274,11 @@ where
272 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr) 274 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
273 } 275 }
274 ast::Expr::PathExpr(e) => { 276 ast::Expr::PathExpr(e) => {
275 let path = 277 let path = e
276 e.path().and_then(Path::from_ast).map(Expr::Path).unwrap_or(Expr::Missing); 278 .path()
279 .and_then(|path| self.parse_path(path))
280 .map(Expr::Path)
281 .unwrap_or(Expr::Missing);
277 self.alloc_expr(path, syntax_ptr) 282 self.alloc_expr(path, syntax_ptr)
278 } 283 }
279 ast::Expr::ContinueExpr(_e) => { 284 ast::Expr::ContinueExpr(_e) => {
@@ -295,7 +300,7 @@ where
295 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 300 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
296 } 301 }
297 ast::Expr::RecordLit(e) => { 302 ast::Expr::RecordLit(e) => {
298 let path = e.path().and_then(Path::from_ast); 303 let path = e.path().and_then(|path| self.parse_path(path));
299 let mut field_ptrs = Vec::new(); 304 let mut field_ptrs = Vec::new();
300 let record_lit = if let Some(nfl) = e.record_field_list() { 305 let record_lit = if let Some(nfl) = e.record_field_list() {
301 let fields = nfl 306 let fields = nfl
@@ -459,7 +464,7 @@ where
459 .ast_id(&e) 464 .ast_id(&e)
460 .with_file_id(self.current_file_id); 465 .with_file_id(self.current_file_id);
461 466
462 if let Some(path) = e.path().and_then(Path::from_ast) { 467 if let Some(path) = e.path().and_then(|path| self.parse_path(path)) {
463 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) { 468 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) {
464 let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db); 469 let call_id = MacroCallLoc { def: def.id, ast_id }.id(self.db);
465 let file_id = call_id.as_file(MacroFileKind::Expr); 470 let file_id = call_id.as_file(MacroFileKind::Expr);
@@ -529,7 +534,7 @@ where
529 Pat::Bind { name, mode: annotation, subpat } 534 Pat::Bind { name, mode: annotation, subpat }
530 } 535 }
531 ast::Pat::TupleStructPat(p) => { 536 ast::Pat::TupleStructPat(p) => {
532 let path = p.path().and_then(Path::from_ast); 537 let path = p.path().and_then(|path| self.parse_path(path));
533 let args = p.args().map(|p| self.collect_pat(p)).collect(); 538 let args = p.args().map(|p| self.collect_pat(p)).collect();
534 Pat::TupleStruct { path, args } 539 Pat::TupleStruct { path, args }
535 } 540 }
@@ -539,7 +544,7 @@ where
539 Pat::Ref { pat, mutability } 544 Pat::Ref { pat, mutability }
540 } 545 }
541 ast::Pat::PathPat(p) => { 546 ast::Pat::PathPat(p) => {
542 let path = p.path().and_then(Path::from_ast); 547 let path = p.path().and_then(|path| self.parse_path(path));
543 path.map(Pat::Path).unwrap_or(Pat::Missing) 548 path.map(Pat::Path).unwrap_or(Pat::Missing)
544 } 549 }
545 ast::Pat::TuplePat(p) => { 550 ast::Pat::TuplePat(p) => {
@@ -548,7 +553,7 @@ where
548 } 553 }
549 ast::Pat::PlaceholderPat(_) => Pat::Wild, 554 ast::Pat::PlaceholderPat(_) => Pat::Wild,
550 ast::Pat::RecordPat(p) => { 555 ast::Pat::RecordPat(p) => {
551 let path = p.path().and_then(Path::from_ast); 556 let path = p.path().and_then(|path| self.parse_path(path));
552 let record_field_pat_list = 557 let record_field_pat_list =
553 p.record_field_pat_list().expect("every struct should have a field list"); 558 p.record_field_pat_list().expect("every struct should have a field list");
554 let mut fields: Vec<_> = record_field_pat_list 559 let mut fields: Vec<_> = record_field_pat_list
@@ -589,6 +594,10 @@ where
589 self.missing_pat() 594 self.missing_pat()
590 } 595 }
591 } 596 }
597
598 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
599 Path::from_src(Source { ast: path, file_id: self.current_file_id }, self.db)
600 }
592} 601}
593 602
594impl From<ast::BinOp> for BinaryOp { 603impl From<ast::BinOp> for BinaryOp {
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index de0983a7e..5496822e7 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::sync::Arc; 3use std::sync::Arc;
2 4
3use ra_arena::{impl_arena_id, Arena, RawId}; 5use ra_arena::{impl_arena_id, Arena, RawId};
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index f06e5ec07..1aa853c3e 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::sync::Arc; 3use std::sync::Arc;
2 4
3use ra_syntax::ast; 5use ra_syntax::ast;
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 7b6d9b240..a012f33f7 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_db::{FileId, FilePosition}; 3use ra_db::{FileId, FilePosition};
2use ra_syntax::{ 4use ra_syntax::{
3 algo::find_node_at_offset, 5 algo::find_node_at_offset,
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 6865d34ba..4ce7551c3 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -132,6 +132,7 @@ impl GenericParams {
132 fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { 132 fn fill_params(&mut self, params: ast::TypeParamList, start: u32) {
133 for (idx, type_param) in params.type_params().enumerate() { 133 for (idx, type_param) in params.type_params().enumerate() {
134 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 134 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
135 // FIXME: Use `Path::from_src`
135 let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast); 136 let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast);
136 137
137 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; 138 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default };
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 9ea4e695d..a3b65cc79 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{ 3use std::{
2 hash::{Hash, Hasher}, 4 hash::{Hash, Hasher},
3 sync::Arc, 5 sync::Arc,
@@ -10,7 +12,7 @@ use ra_syntax::{ast, AstNode, Parse, SyntaxNode};
10 12
11use crate::{ 13use crate::{
12 db::{AstDatabase, DefDatabase, InternDatabase}, 14 db::{AstDatabase, DefDatabase, InternDatabase},
13 AstId, FileAstId, Module, Source, 15 AstId, Crate, FileAstId, Module, Source,
14}; 16};
15 17
16/// hir makes heavy use of ids: integer (u32) handlers to various things. You 18/// hir makes heavy use of ids: integer (u32) handlers to various things. You
@@ -58,6 +60,17 @@ impl HirFileId {
58 } 60 }
59 } 61 }
60 62
63 /// Get the crate which the macro lives in, if it is a macro file.
64 pub(crate) fn macro_crate(self, db: &impl AstDatabase) -> Option<Crate> {
65 match self.0 {
66 HirFileIdRepr::File(_) => None,
67 HirFileIdRepr::Macro(macro_file) => {
68 let loc = macro_file.macro_call_id.loc(db);
69 Some(loc.def.krate)
70 }
71 }
72 }
73
61 pub(crate) fn parse_or_expand_query( 74 pub(crate) fn parse_or_expand_query(
62 db: &impl AstDatabase, 75 db: &impl AstDatabase,
63 file_id: HirFileId, 76 file_id: HirFileId,
@@ -121,10 +134,13 @@ impl From<FileId> for HirFileId {
121} 134}
122 135
123#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 136#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
124pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>); 137pub struct MacroDefId {
138 pub(crate) ast_id: AstId<ast::MacroCall>,
139 pub(crate) krate: Crate,
140}
125 141
126pub(crate) fn macro_def_query(db: &impl AstDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> { 142pub(crate) fn macro_def_query(db: &impl AstDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> {
127 let macro_call = id.0.to_node(db); 143 let macro_call = id.ast_id.to_node(db);
128 let arg = macro_call.token_tree()?; 144 let arg = macro_call.token_tree()?;
129 let (tt, _) = mbe::ast_to_token_tree(&arg).or_else(|| { 145 let (tt, _) = mbe::ast_to_token_tree(&arg).or_else(|| {
130 log::warn!("fail on macro_def to token tree: {:#?}", arg); 146 log::warn!("fail on macro_def to token tree: {:#?}", arg);
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index d830202bd..55dfc393b 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -1,13 +1,17 @@
1//! FIXME: write short doc here
2
1use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
2use std::sync::Arc; 4use std::sync::Arc;
3 5
4use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 6use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
7use ra_cfg::CfgOptions;
5use ra_syntax::{ 8use ra_syntax::{
6 ast::{self, AstNode}, 9 ast::{self, AstNode},
7 AstPtr, 10 AstPtr,
8}; 11};
9 12
10use crate::{ 13use crate::{
14 attr::Attr,
11 code_model::{Module, ModuleSource}, 15 code_model::{Module, ModuleSource},
12 db::{AstDatabase, DefDatabase, HirDatabase}, 16 db::{AstDatabase, DefDatabase, HirDatabase},
13 generics::HasGenericParams, 17 generics::HasGenericParams,
@@ -174,6 +178,7 @@ pub struct ModuleImplBlocks {
174impl ModuleImplBlocks { 178impl ModuleImplBlocks {
175 fn collect( 179 fn collect(
176 db: &(impl DefDatabase + AstDatabase), 180 db: &(impl DefDatabase + AstDatabase),
181 cfg_options: &CfgOptions,
177 module: Module, 182 module: Module,
178 source_map: &mut ImplSourceMap, 183 source_map: &mut ImplSourceMap,
179 ) -> Self { 184 ) -> Self {
@@ -186,11 +191,11 @@ impl ModuleImplBlocks {
186 let src = m.module.definition_source(db); 191 let src = m.module.definition_source(db);
187 match &src.ast { 192 match &src.ast {
188 ModuleSource::SourceFile(node) => { 193 ModuleSource::SourceFile(node) => {
189 m.collect_from_item_owner(db, source_map, node, src.file_id) 194 m.collect_from_item_owner(db, cfg_options, source_map, node, src.file_id)
190 } 195 }
191 ModuleSource::Module(node) => { 196 ModuleSource::Module(node) => {
192 let item_list = node.item_list().expect("inline module should have item list"); 197 let item_list = node.item_list().expect("inline module should have item list");
193 m.collect_from_item_owner(db, source_map, &item_list, src.file_id) 198 m.collect_from_item_owner(db, cfg_options, source_map, &item_list, src.file_id)
194 } 199 }
195 }; 200 };
196 m 201 m
@@ -199,6 +204,7 @@ impl ModuleImplBlocks {
199 fn collect_from_item_owner( 204 fn collect_from_item_owner(
200 &mut self, 205 &mut self,
201 db: &(impl DefDatabase + AstDatabase), 206 db: &(impl DefDatabase + AstDatabase),
207 cfg_options: &CfgOptions,
202 source_map: &mut ImplSourceMap, 208 source_map: &mut ImplSourceMap,
203 owner: &dyn ast::ModuleItemOwner, 209 owner: &dyn ast::ModuleItemOwner,
204 file_id: HirFileId, 210 file_id: HirFileId,
@@ -206,6 +212,13 @@ impl ModuleImplBlocks {
206 for item in owner.items_with_macros() { 212 for item in owner.items_with_macros() {
207 match item { 213 match item {
208 ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => { 214 ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => {
215 let attrs = Attr::from_attrs_owner(file_id, &impl_block_ast, db);
216 if attrs.map_or(false, |attrs| {
217 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
218 }) {
219 continue;
220 }
221
209 let impl_block = ImplData::from_ast(db, file_id, self.module, &impl_block_ast); 222 let impl_block = ImplData::from_ast(db, file_id, self.module, &impl_block_ast);
210 let id = self.impls.alloc(impl_block); 223 let id = self.impls.alloc(impl_block);
211 for &impl_item in &self.impls[id].items { 224 for &impl_item in &self.impls[id].items {
@@ -216,9 +229,19 @@ impl ModuleImplBlocks {
216 } 229 }
217 ast::ItemOrMacro::Item(_) => (), 230 ast::ItemOrMacro::Item(_) => (),
218 ast::ItemOrMacro::Macro(macro_call) => { 231 ast::ItemOrMacro::Macro(macro_call) => {
232 let attrs = Attr::from_attrs_owner(file_id, &macro_call, db);
233 if attrs.map_or(false, |attrs| {
234 attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
235 }) {
236 continue;
237 }
238
219 //FIXME: we should really cut down on the boilerplate required to process a macro 239 //FIXME: we should really cut down on the boilerplate required to process a macro
220 let ast_id = db.ast_id_map(file_id).ast_id(&macro_call).with_file_id(file_id); 240 let ast_id = db.ast_id_map(file_id).ast_id(&macro_call).with_file_id(file_id);
221 if let Some(path) = macro_call.path().and_then(Path::from_ast) { 241 if let Some(path) = macro_call
242 .path()
243 .and_then(|path| Path::from_src(Source { ast: path, file_id }, db))
244 {
222 if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path) 245 if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path)
223 { 246 {
224 let call_id = MacroCallLoc { def: def.id, ast_id }.id(db); 247 let call_id = MacroCallLoc { def: def.id, ast_id }.id(db);
@@ -226,7 +249,13 @@ impl ModuleImplBlocks {
226 if let Some(item_list) = 249 if let Some(item_list) =
227 db.parse_or_expand(file_id).and_then(ast::MacroItems::cast) 250 db.parse_or_expand(file_id).and_then(ast::MacroItems::cast)
228 { 251 {
229 self.collect_from_item_owner(db, source_map, &item_list, file_id) 252 self.collect_from_item_owner(
253 db,
254 cfg_options,
255 source_map,
256 &item_list,
257 file_id,
258 )
230 } 259 }
231 } 260 }
232 } 261 }
@@ -241,8 +270,10 @@ pub(crate) fn impls_in_module_with_source_map_query(
241 module: Module, 270 module: Module,
242) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) { 271) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
243 let mut source_map = ImplSourceMap::default(); 272 let mut source_map = ImplSourceMap::default();
273 let crate_graph = db.crate_graph();
274 let cfg_options = crate_graph.cfg_options(module.krate.crate_id());
244 275
245 let result = ModuleImplBlocks::collect(db, module, &mut source_map); 276 let result = ModuleImplBlocks::collect(db, cfg_options, module, &mut source_map);
246 (Arc::new(result), Arc::new(source_map)) 277 (Arc::new(result), Arc::new(source_map))
247} 278}
248 279
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
index bcce314d8..6c4e8ffbd 100644
--- a/crates/ra_hir/src/lang_item.rs
+++ b/crates/ra_hir/src/lang_item.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
2use std::sync::Arc; 4use std::sync::Arc;
3 5
@@ -151,7 +153,7 @@ impl LangItems {
151 153
152fn lang_item_name<T: AttrsOwner>(node: &T) -> Option<SmolStr> { 154fn lang_item_name<T: AttrsOwner>(node: &T) -> Option<SmolStr> {
153 node.attrs() 155 node.attrs()
154 .filter_map(|a| a.as_key_value()) 156 .filter_map(|a| a.as_simple_key_value())
155 .filter(|(key, _)| key == "lang") 157 .filter(|(key, _)| key == "lang")
156 .map(|(_, val)| val) 158 .map(|(_, val)| val)
157 .nth(0) 159 .nth(0)
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index a9de9fb6b..4340e9d34 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -1,5 +1,3 @@
1#![recursion_limit = "512"]
2
3//! HIR (previously known as descriptors) provides a high-level object oriented 1//! HIR (previously known as descriptors) provides a high-level object oriented
4//! access to Rust code. 2//! access to Rust code.
5//! 3//!
@@ -7,6 +5,8 @@
7//! to a particular crate instance. That is, it has cfg flags and features 5//! to a particular crate instance. That is, it has cfg flags and features
8//! applied. So, the relation between syntax and HIR is many-to-one. 6//! applied. So, the relation between syntax and HIR is many-to-one.
9 7
8#![recursion_limit = "512"]
9
10macro_rules! impl_froms { 10macro_rules! impl_froms {
11 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => { 11 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => {
12 $( 12 $(
@@ -44,6 +44,7 @@ mod traits;
44mod type_alias; 44mod type_alias;
45mod type_ref; 45mod type_ref;
46mod ty; 46mod ty;
47mod attr;
47mod impl_block; 48mod impl_block;
48mod expr; 49mod expr;
49mod lang_item; 50mod lang_item;
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index b2111be05..79af24b20 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -1,3 +1,5 @@
1//! See test_utils/src/marks.rs
2
1test_utils::marks!( 3test_utils::marks!(
2 bogus_paths 4 bogus_paths
3 name_res_works_for_broken_modules 5 name_res_works_for_broken_modules
@@ -9,9 +11,10 @@ test_utils::marks!(
9 glob_across_crates 11 glob_across_crates
10 std_prelude 12 std_prelude
11 match_ergonomics_ref 13 match_ergonomics_ref
12 trait_resolution_on_fn_type
13 infer_while_let 14 infer_while_let
14 macro_rules_from_other_crates_are_visible_with_macro_use 15 macro_rules_from_other_crates_are_visible_with_macro_use
15 prelude_is_macro_use 16 prelude_is_macro_use
16 coerce_merge_fail_fallback 17 coerce_merge_fail_fallback
18 macro_dollar_crate_self
19 macro_dollar_crate_other
17); 20);
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index cb405091e..f750986b8 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -1,6 +1,9 @@
1//! FIXME: write short doc here
2
1use std::{panic, sync::Arc}; 3use std::{panic, sync::Arc};
2 4
3use parking_lot::Mutex; 5use parking_lot::Mutex;
6use ra_cfg::CfgOptions;
4use ra_db::{ 7use ra_db::{
5 salsa, CrateGraph, CrateId, Edition, FileId, FilePosition, SourceDatabase, SourceRoot, 8 salsa, CrateGraph, CrateId, Edition, FileId, FilePosition, SourceDatabase, SourceRoot,
6 SourceRootId, 9 SourceRootId,
@@ -72,13 +75,13 @@ impl MockDatabase {
72 pub fn set_crate_graph_from_fixture(&mut self, graph: CrateGraphFixture) { 75 pub fn set_crate_graph_from_fixture(&mut self, graph: CrateGraphFixture) {
73 let mut ids = FxHashMap::default(); 76 let mut ids = FxHashMap::default();
74 let mut crate_graph = CrateGraph::default(); 77 let mut crate_graph = CrateGraph::default();
75 for (crate_name, (crate_root, edition, _)) in graph.0.iter() { 78 for (crate_name, (crate_root, edition, cfg_options, _)) in graph.0.iter() {
76 let crate_root = self.file_id_of(&crate_root); 79 let crate_root = self.file_id_of(&crate_root);
77 let crate_id = crate_graph.add_crate_root(crate_root, *edition); 80 let crate_id = crate_graph.add_crate_root(crate_root, *edition, cfg_options.clone());
78 Arc::make_mut(&mut self.crate_names).insert(crate_id, crate_name.clone()); 81 Arc::make_mut(&mut self.crate_names).insert(crate_id, crate_name.clone());
79 ids.insert(crate_name, crate_id); 82 ids.insert(crate_name, crate_id);
80 } 83 }
81 for (crate_name, (_, _, deps)) in graph.0.iter() { 84 for (crate_name, (_, _, _, deps)) in graph.0.iter() {
82 let from = ids[crate_name]; 85 let from = ids[crate_name];
83 for dep in deps { 86 for dep in deps {
84 let to = ids[dep]; 87 let to = ids[dep];
@@ -182,7 +185,7 @@ impl MockDatabase {
182 185
183 if is_crate_root { 186 if is_crate_root {
184 let mut crate_graph = CrateGraph::default(); 187 let mut crate_graph = CrateGraph::default();
185 crate_graph.add_crate_root(file_id, Edition::Edition2018); 188 crate_graph.add_crate_root(file_id, Edition::Edition2018, CfgOptions::default());
186 self.set_crate_graph(Arc::new(crate_graph)); 189 self.set_crate_graph(Arc::new(crate_graph));
187 } 190 }
188 file_id 191 file_id
@@ -266,19 +269,27 @@ impl MockDatabase {
266} 269}
267 270
268#[derive(Default)] 271#[derive(Default)]
269pub struct CrateGraphFixture(pub Vec<(String, (String, Edition, Vec<String>))>); 272pub struct CrateGraphFixture(pub Vec<(String, (String, Edition, CfgOptions, Vec<String>))>);
270 273
271#[macro_export] 274#[macro_export]
272macro_rules! crate_graph { 275macro_rules! crate_graph {
273 ($($crate_name:literal: ($crate_path:literal, $($edition:literal,)? [$($dep:literal),*]),)*) => {{ 276 ($(
277 $crate_name:literal: (
278 $crate_path:literal,
279 $($edition:literal,)?
280 [$($dep:literal),*]
281 $(,$cfg:expr)?
282 ),
283 )*) => {{
274 let mut res = $crate::mock::CrateGraphFixture::default(); 284 let mut res = $crate::mock::CrateGraphFixture::default();
275 $( 285 $(
276 #[allow(unused_mut, unused_assignments)] 286 #[allow(unused_mut, unused_assignments)]
277 let mut edition = ra_db::Edition::Edition2018; 287 let mut edition = ra_db::Edition::Edition2018;
278 $(edition = ra_db::Edition::from_string($edition);)? 288 $(edition = ra_db::Edition::from_string($edition);)?
289 let cfg_options = { ::ra_cfg::CfgOptions::default() $(; $cfg)? };
279 res.0.push(( 290 res.0.push((
280 $crate_name.to_string(), 291 $crate_name.to_string(),
281 ($crate_path.to_string(), edition, vec![$($dep.to_string()),*]) 292 ($crate_path.to_string(), edition, cfg_options, vec![$($dep.to_string()),*])
282 )); 293 ));
283 )* 294 )*
284 res 295 res
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 1bf993ffb..1e0b8c350 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt; 3use std::fmt;
2 4
3use ra_syntax::{ast, SmolStr}; 5use ra_syntax::{ast, SmolStr};
@@ -5,20 +7,21 @@ use ra_syntax::{ast, SmolStr};
5/// `Name` is a wrapper around string, which is used in hir for both references 7/// `Name` is a wrapper around string, which is used in hir for both references
6/// and declarations. In theory, names should also carry hygiene info, but we are 8/// and declarations. In theory, names should also carry hygiene info, but we are
7/// not there yet! 9/// not there yet!
8#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] 10#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9pub struct Name { 11pub struct Name(Repr);
10 text: SmolStr,
11}
12 12
13impl fmt::Display for Name { 13#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 14enum Repr {
15 fmt::Display::fmt(&self.text, f) 15 Text(SmolStr),
16 } 16 TupleField(usize),
17} 17}
18 18
19impl fmt::Debug for Name { 19impl fmt::Display for Name {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 fmt::Debug::fmt(&self.text, f) 21 match &self.0 {
22 Repr::Text(text) => fmt::Display::fmt(&text, f),
23 Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
24 }
22 } 25 }
23} 26}
24 27
@@ -26,29 +29,38 @@ impl Name {
26 /// Note: this is private to make creating name from random string hard. 29 /// Note: this is private to make creating name from random string hard.
27 /// Hopefully, this should allow us to integrate hygiene cleaner in the 30 /// Hopefully, this should allow us to integrate hygiene cleaner in the
28 /// future, and to switch to interned representation of names. 31 /// future, and to switch to interned representation of names.
29 const fn new(text: SmolStr) -> Name { 32 const fn new_text(text: SmolStr) -> Name {
30 Name { text } 33 Name(Repr::Text(text))
31 } 34 }
32 35
33 pub(crate) fn missing() -> Name { 36 pub(crate) fn new_tuple_field(idx: usize) -> Name {
34 Name::new("[missing name]".into()) 37 Name(Repr::TupleField(idx))
38 }
39
40 /// Shortcut to create inline plain text name
41 const fn new_inline_ascii(len: usize, text: &[u8]) -> Name {
42 Name::new_text(SmolStr::new_inline_from_ascii(len, text))
35 } 43 }
36 44
37 pub(crate) fn tuple_field_name(idx: usize) -> Name { 45 /// Resolve a name from the text of token.
38 Name::new(idx.to_string().into()) 46 fn resolve(raw_text: &SmolStr) -> Name {
47 let raw_start = "r#";
48 if raw_text.as_str().starts_with(raw_start) {
49 Name::new_text(SmolStr::new(&raw_text[raw_start.len()..]))
50 } else {
51 Name::new_text(raw_text.clone())
52 }
39 } 53 }
40 54
41 // There's should be no way to extract a string out of `Name`: `Name` in the 55 pub(crate) fn missing() -> Name {
42 // future, `Name` will include hygiene information, and you can't encode 56 Name::new_text("[missing name]".into())
43 // hygiene into a String. 57 }
44 // 58
45 // If you need to compare something with `Name`, compare `Name`s directly. 59 pub(crate) fn as_tuple_index(&self) -> Option<usize> {
46 // 60 match self.0 {
47 // If you need to render `Name` for the user, use the `Display` impl, but be 61 Repr::TupleField(idx) => Some(idx),
48 // aware that it strips hygiene info. 62 _ => None,
49 #[deprecated(note = "use to_string instead")] 63 }
50 pub fn as_smolstr(&self) -> &SmolStr {
51 &self.text
52 } 64 }
53} 65}
54 66
@@ -58,15 +70,16 @@ pub(crate) trait AsName {
58 70
59impl AsName for ast::NameRef { 71impl AsName for ast::NameRef {
60 fn as_name(&self) -> Name { 72 fn as_name(&self) -> Name {
61 let name = resolve_name(self.text()); 73 match self.as_tuple_field() {
62 Name::new(name) 74 Some(idx) => Name::new_tuple_field(idx),
75 None => Name::resolve(self.text()),
76 }
63 } 77 }
64} 78}
65 79
66impl AsName for ast::Name { 80impl AsName for ast::Name {
67 fn as_name(&self) -> Name { 81 fn as_name(&self) -> Name {
68 let name = resolve_name(self.text()); 82 Name::resolve(self.text())
69 Name::new(name)
70 } 83 }
71} 84}
72 85
@@ -74,66 +87,56 @@ impl AsName for ast::FieldKind {
74 fn as_name(&self) -> Name { 87 fn as_name(&self) -> Name {
75 match self { 88 match self {
76 ast::FieldKind::Name(nr) => nr.as_name(), 89 ast::FieldKind::Name(nr) => nr.as_name(),
77 ast::FieldKind::Index(idx) => Name::new(idx.text().clone()), 90 ast::FieldKind::Index(idx) => Name::new_tuple_field(idx.text().parse().unwrap()),
78 } 91 }
79 } 92 }
80} 93}
81 94
82impl AsName for ra_db::Dependency { 95impl AsName for ra_db::Dependency {
83 fn as_name(&self) -> Name { 96 fn as_name(&self) -> Name {
84 Name::new(self.name.clone()) 97 Name::new_text(self.name.clone())
85 } 98 }
86} 99}
87 100
88// Primitives 101// Primitives
89pub(crate) const ISIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"isize")); 102pub(crate) const ISIZE: Name = Name::new_inline_ascii(5, b"isize");
90pub(crate) const I8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"i8")); 103pub(crate) const I8: Name = Name::new_inline_ascii(2, b"i8");
91pub(crate) const I16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i16")); 104pub(crate) const I16: Name = Name::new_inline_ascii(3, b"i16");
92pub(crate) const I32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i32")); 105pub(crate) const I32: Name = Name::new_inline_ascii(3, b"i32");
93pub(crate) const I64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i64")); 106pub(crate) const I64: Name = Name::new_inline_ascii(3, b"i64");
94pub(crate) const I128: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"i128")); 107pub(crate) const I128: Name = Name::new_inline_ascii(4, b"i128");
95pub(crate) const USIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"usize")); 108pub(crate) const USIZE: Name = Name::new_inline_ascii(5, b"usize");
96pub(crate) const U8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"u8")); 109pub(crate) const U8: Name = Name::new_inline_ascii(2, b"u8");
97pub(crate) const U16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u16")); 110pub(crate) const U16: Name = Name::new_inline_ascii(3, b"u16");
98pub(crate) const U32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u32")); 111pub(crate) const U32: Name = Name::new_inline_ascii(3, b"u32");
99pub(crate) const U64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u64")); 112pub(crate) const U64: Name = Name::new_inline_ascii(3, b"u64");
100pub(crate) const U128: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"u128")); 113pub(crate) const U128: Name = Name::new_inline_ascii(4, b"u128");
101pub(crate) const F32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f32")); 114pub(crate) const F32: Name = Name::new_inline_ascii(3, b"f32");
102pub(crate) const F64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f64")); 115pub(crate) const F64: Name = Name::new_inline_ascii(3, b"f64");
103pub(crate) const BOOL: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"bool")); 116pub(crate) const BOOL: Name = Name::new_inline_ascii(4, b"bool");
104pub(crate) const CHAR: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"char")); 117pub(crate) const CHAR: Name = Name::new_inline_ascii(4, b"char");
105pub(crate) const STR: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"str")); 118pub(crate) const STR: Name = Name::new_inline_ascii(3, b"str");
106 119
107// Special names 120// Special names
108pub(crate) const SELF_PARAM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"self")); 121pub(crate) const SELF_PARAM: Name = Name::new_inline_ascii(4, b"self");
109pub(crate) const SELF_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Self")); 122pub(crate) const SELF_TYPE: Name = Name::new_inline_ascii(4, b"Self");
110pub(crate) const MACRO_RULES: Name = Name::new(SmolStr::new_inline_from_ascii(11, b"macro_rules")); 123pub(crate) const MACRO_RULES: Name = Name::new_inline_ascii(11, b"macro_rules");
111 124
112// Components of known path (value or mod name) 125// Components of known path (value or mod name)
113pub(crate) const STD: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"std")); 126pub(crate) const STD: Name = Name::new_inline_ascii(3, b"std");
114pub(crate) const ITER: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"iter")); 127pub(crate) const ITER: Name = Name::new_inline_ascii(4, b"iter");
115pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops")); 128pub(crate) const OPS: Name = Name::new_inline_ascii(3, b"ops");
116pub(crate) const FUTURE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); 129pub(crate) const FUTURE: Name = Name::new_inline_ascii(6, b"future");
117pub(crate) const RESULT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result")); 130pub(crate) const RESULT: Name = Name::new_inline_ascii(6, b"result");
118pub(crate) const BOXED: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed")); 131pub(crate) const BOXED: Name = Name::new_inline_ascii(5, b"boxed");
119 132
120// Components of known path (type name) 133// Components of known path (type name)
121pub(crate) const INTO_ITERATOR_TYPE: Name = 134pub(crate) const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(12, b"IntoIterator");
122 Name::new(SmolStr::new_inline_from_ascii(12, b"IntoIterator")); 135pub(crate) const ITEM_TYPE: Name = Name::new_inline_ascii(4, b"Item");
123pub(crate) const ITEM_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item")); 136pub(crate) const TRY_TYPE: Name = Name::new_inline_ascii(3, b"Try");
124pub(crate) const TRY_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")); 137pub(crate) const OK_TYPE: Name = Name::new_inline_ascii(2, b"Ok");
125pub(crate) const OK_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); 138pub(crate) const FUTURE_TYPE: Name = Name::new_inline_ascii(6, b"Future");
126pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); 139pub(crate) const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result");
127pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); 140pub(crate) const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output");
128pub(crate) const OUTPUT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); 141pub(crate) const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target");
129pub(crate) const TARGET_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target")); 142pub(crate) const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");
130pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box"));
131
132fn resolve_name(text: &SmolStr) -> SmolStr {
133 let raw_start = "r#";
134 if text.as_str().starts_with(raw_start) {
135 SmolStr::new(&text[raw_start.len()..])
136 } else {
137 text.clone()
138 }
139}
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index b808a0c36..67adcfa28 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -332,6 +332,20 @@ impl CrateDefMap {
332 ) -> ResolvePathResult { 332 ) -> ResolvePathResult {
333 let mut segments = path.segments.iter().enumerate(); 333 let mut segments = path.segments.iter().enumerate();
334 let mut curr_per_ns: PerNs = match path.kind { 334 let mut curr_per_ns: PerNs = match path.kind {
335 PathKind::DollarCrate(krate) => {
336 if krate == self.krate {
337 tested_by!(macro_dollar_crate_self);
338 PerNs::types(Module { krate: self.krate, module_id: self.root }.into())
339 } else {
340 match krate.root_module(db) {
341 Some(module) => {
342 tested_by!(macro_dollar_crate_other);
343 PerNs::types(module.into())
344 }
345 None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
346 }
347 }
348 }
335 PathKind::Crate => { 349 PathKind::Crate => {
336 PerNs::types(Module { krate: self.krate, module_id: self.root }.into()) 350 PerNs::types(Module { krate: self.krate, module_id: self.root }.into())
337 } 351 }
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index ef7dc6ebe..cef2dc9d2 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -1,3 +1,6 @@
1//! FIXME: write short doc here
2
3use ra_cfg::CfgOptions;
1use ra_db::FileId; 4use ra_db::FileId;
2use ra_syntax::{ast, SmolStr}; 5use ra_syntax::{ast, SmolStr};
3use rustc_hash::FxHashMap; 6use rustc_hash::FxHashMap;
@@ -33,6 +36,9 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
33 } 36 }
34 } 37 }
35 38
39 let crate_graph = db.crate_graph();
40 let cfg_options = crate_graph.cfg_options(def_map.krate().crate_id());
41
36 let mut collector = DefCollector { 42 let mut collector = DefCollector {
37 db, 43 db,
38 def_map, 44 def_map,
@@ -40,6 +46,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
40 unresolved_imports: Vec::new(), 46 unresolved_imports: Vec::new(),
41 unexpanded_macros: Vec::new(), 47 unexpanded_macros: Vec::new(),
42 macro_stack_monitor: MacroStackMonitor::default(), 48 macro_stack_monitor: MacroStackMonitor::default(),
49 cfg_options,
43 }; 50 };
44 collector.collect(); 51 collector.collect();
45 collector.finish() 52 collector.finish()
@@ -74,8 +81,8 @@ impl MacroStackMonitor {
74} 81}
75 82
76/// Walks the tree of module recursively 83/// Walks the tree of module recursively
77struct DefCollector<DB> { 84struct DefCollector<'a, DB> {
78 db: DB, 85 db: &'a DB,
79 def_map: CrateDefMap, 86 def_map: CrateDefMap,
80 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, 87 glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
81 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 88 unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>,
@@ -84,9 +91,11 @@ struct DefCollector<DB> {
84 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly 91 /// Some macro use `$tt:tt which mean we have to handle the macro perfectly
85 /// To prevent stack overflow, we add a deep counter here for prevent that. 92 /// To prevent stack overflow, we add a deep counter here for prevent that.
86 macro_stack_monitor: MacroStackMonitor, 93 macro_stack_monitor: MacroStackMonitor,
94
95 cfg_options: &'a CfgOptions,
87} 96}
88 97
89impl<'a, DB> DefCollector<&'a DB> 98impl<DB> DefCollector<'_, DB>
90where 99where
91 DB: DefDatabase, 100 DB: DefDatabase,
92{ 101{
@@ -504,7 +513,7 @@ struct ModCollector<'a, D> {
504 parent_module: Option<ParentModule<'a>>, 513 parent_module: Option<ParentModule<'a>>,
505} 514}
506 515
507impl<DB> ModCollector<'_, &'_ mut DefCollector<&'_ DB>> 516impl<DB> ModCollector<'_, &'_ mut DefCollector<'_, DB>>
508where 517where
509 DB: DefDatabase, 518 DB: DefDatabase,
510{ 519{
@@ -521,24 +530,27 @@ where
521 // `#[macro_use] extern crate` is hoisted to imports macros before collecting 530 // `#[macro_use] extern crate` is hoisted to imports macros before collecting
522 // any other items. 531 // any other items.
523 for item in items { 532 for item in items {
524 if let raw::RawItem::Import(import_id) = *item { 533 if self.is_cfg_enabled(&item.attrs) {
525 let import = self.raw_items[import_id].clone(); 534 if let raw::RawItemKind::Import(import_id) = item.kind {
526 if import.is_extern_crate && import.is_macro_use { 535 let import = self.raw_items[import_id].clone();
527 self.def_collector.import_macros_from_extern_crate(self.module_id, &import); 536 if import.is_extern_crate && import.is_macro_use {
537 self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
538 }
528 } 539 }
529 } 540 }
530 } 541 }
531 542
532 for item in items { 543 for item in items {
533 match *item { 544 if self.is_cfg_enabled(&item.attrs) {
534 raw::RawItem::Module(m) => self.collect_module(&self.raw_items[m]), 545 match item.kind {
535 raw::RawItem::Import(import_id) => self.def_collector.unresolved_imports.push(( 546 raw::RawItemKind::Module(m) => self.collect_module(&self.raw_items[m]),
536 self.module_id, 547 raw::RawItemKind::Import(import_id) => self
537 import_id, 548 .def_collector
538 self.raw_items[import_id].clone(), 549 .unresolved_imports
539 )), 550 .push((self.module_id, import_id, self.raw_items[import_id].clone())),
540 raw::RawItem::Def(def) => self.define_def(&self.raw_items[def]), 551 raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]),
541 raw::RawItem::Macro(mac) => self.collect_macro(&self.raw_items[mac]), 552 raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]),
553 }
542 } 554 }
543 } 555 }
544 } 556 }
@@ -662,7 +674,10 @@ where
662 // Case 1: macro rules, define a macro in crate-global mutable scope 674 // Case 1: macro rules, define a macro in crate-global mutable scope
663 if is_macro_rules(&mac.path) { 675 if is_macro_rules(&mac.path) {
664 if let Some(name) = &mac.name { 676 if let Some(name) = &mac.name {
665 let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id)); 677 let macro_id = MacroDefId {
678 ast_id: mac.ast_id.with_file_id(self.file_id),
679 krate: self.def_collector.def_map.krate,
680 };
666 let macro_ = MacroDef { id: macro_id }; 681 let macro_ = MacroDef { id: macro_id };
667 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export); 682 self.def_collector.define_macro(self.module_id, name.clone(), macro_, mac.export);
668 } 683 }
@@ -698,6 +713,14 @@ where
698 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); 713 self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
699 } 714 }
700 } 715 }
716
717 fn is_cfg_enabled(&self, attrs: &raw::Attrs) -> bool {
718 attrs.as_ref().map_or(true, |attrs| {
719 attrs
720 .iter()
721 .all(|attr| attr.is_cfg_enabled(&self.def_collector.cfg_options) != Some(false))
722 })
723 }
701} 724}
702 725
703fn is_macro_rules(path: &Path) -> bool { 726fn is_macro_rules(path: &Path) -> bool {
@@ -725,6 +748,7 @@ mod tests {
725 unresolved_imports: Vec::new(), 748 unresolved_imports: Vec::new(),
726 unexpanded_macros: Vec::new(), 749 unexpanded_macros: Vec::new(),
727 macro_stack_monitor: monitor, 750 macro_stack_monitor: monitor,
751 cfg_options: &CfgOptions::default(),
728 }; 752 };
729 collector.collect(); 753 collector.collect();
730 collector.finish() 754 collector.finish()
diff --git a/crates/ra_hir/src/nameres/per_ns.rs b/crates/ra_hir/src/nameres/per_ns.rs
index 964da2794..0da6789de 100644
--- a/crates/ra_hir/src/nameres/per_ns.rs
+++ b/crates/ra_hir/src/nameres/per_ns.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{MacroDef, ModuleDef}; 3use crate::{MacroDef, ModuleDef};
2 4
3#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 5#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index 29aaddbf1..623b343c4 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{ops::Index, sync::Arc}; 3use std::{ops::Index, sync::Arc};
2 4
3use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; 5use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
@@ -8,8 +10,9 @@ use ra_syntax::{
8use test_utils::tested_by; 10use test_utils::tested_by;
9 11
10use crate::{ 12use crate::{
13 attr::Attr,
11 db::{AstDatabase, DefDatabase}, 14 db::{AstDatabase, DefDatabase},
12 AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, 15 AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source,
13}; 16};
14 17
15/// `RawItems` is a set of top-level items in a file (except for impls). 18/// `RawItems` is a set of top-level items in a file (except for impls).
@@ -71,6 +74,8 @@ impl RawItems {
71 raw_items: RawItems::default(), 74 raw_items: RawItems::default(),
72 source_ast_id_map: db.ast_id_map(file_id), 75 source_ast_id_map: db.ast_id_map(file_id),
73 source_map: ImportSourceMap::default(), 76 source_map: ImportSourceMap::default(),
77 file_id,
78 db,
74 }; 79 };
75 if let Some(node) = db.parse_or_expand(file_id) { 80 if let Some(node) = db.parse_or_expand(file_id) {
76 if let Some(source_file) = ast::SourceFile::cast(node.clone()) { 81 if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
@@ -115,8 +120,17 @@ impl Index<Macro> for RawItems {
115 } 120 }
116} 121}
117 122
123// Avoid heap allocation on items without attributes.
124pub(super) type Attrs = Option<Arc<[Attr]>>;
125
126#[derive(Debug, PartialEq, Eq, Clone)]
127pub(super) struct RawItem {
128 pub(super) attrs: Attrs,
129 pub(super) kind: RawItemKind,
130}
131
118#[derive(Debug, PartialEq, Eq, Clone, Copy)] 132#[derive(Debug, PartialEq, Eq, Clone, Copy)]
119pub(super) enum RawItem { 133pub(super) enum RawItemKind {
120 Module(Module), 134 Module(Module),
121 Import(ImportId), 135 Import(ImportId),
122 Def(Def), 136 Def(Def),
@@ -192,13 +206,15 @@ pub(super) struct MacroData {
192 pub(super) export: bool, 206 pub(super) export: bool,
193} 207}
194 208
195struct RawItemsCollector { 209struct RawItemsCollector<DB> {
196 raw_items: RawItems, 210 raw_items: RawItems,
197 source_ast_id_map: Arc<AstIdMap>, 211 source_ast_id_map: Arc<AstIdMap>,
198 source_map: ImportSourceMap, 212 source_map: ImportSourceMap,
213 file_id: HirFileId,
214 db: DB,
199} 215}
200 216
201impl RawItemsCollector { 217impl<DB: AstDatabase> RawItemsCollector<&DB> {
202 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { 218 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) {
203 for item_or_macro in body.items_with_macros() { 219 for item_or_macro in body.items_with_macros() {
204 match item_or_macro { 220 match item_or_macro {
@@ -209,6 +225,7 @@ impl RawItemsCollector {
209 } 225 }
210 226
211 fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { 227 fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) {
228 let attrs = self.parse_attrs(&item);
212 let (kind, name) = match item { 229 let (kind, name) = match item {
213 ast::ModuleItem::Module(module) => { 230 ast::ModuleItem::Module(module) => {
214 self.add_module(current_module, module); 231 self.add_module(current_module, module);
@@ -257,7 +274,7 @@ impl RawItemsCollector {
257 if let Some(name) = name { 274 if let Some(name) = name {
258 let name = name.as_name(); 275 let name = name.as_name();
259 let def = self.raw_items.defs.alloc(DefData { name, kind }); 276 let def = self.raw_items.defs.alloc(DefData { name, kind });
260 self.push_item(current_module, RawItem::Def(def)) 277 self.push_item(current_module, attrs, RawItemKind::Def(def));
261 } 278 }
262 } 279 }
263 280
@@ -266,8 +283,10 @@ impl RawItemsCollector {
266 Some(it) => it.as_name(), 283 Some(it) => it.as_name(),
267 None => return, 284 None => return,
268 }; 285 };
286 let attrs = self.parse_attrs(&module);
269 287
270 let ast_id = self.source_ast_id_map.ast_id(&module); 288 let ast_id = self.source_ast_id_map.ast_id(&module);
289 // FIXME: cfg_attr
271 let is_macro_use = module.has_atom_attr("macro_use"); 290 let is_macro_use = module.has_atom_attr("macro_use");
272 if module.has_semi() { 291 if module.has_semi() {
273 let attr_path = extract_mod_path_attribute(&module); 292 let attr_path = extract_mod_path_attribute(&module);
@@ -277,7 +296,7 @@ impl RawItemsCollector {
277 attr_path, 296 attr_path,
278 is_macro_use, 297 is_macro_use,
279 }); 298 });
280 self.push_item(current_module, RawItem::Module(item)); 299 self.push_item(current_module, attrs, RawItemKind::Module(item));
281 return; 300 return;
282 } 301 }
283 302
@@ -291,26 +310,37 @@ impl RawItemsCollector {
291 is_macro_use, 310 is_macro_use,
292 }); 311 });
293 self.process_module(Some(item), item_list); 312 self.process_module(Some(item), item_list);
294 self.push_item(current_module, RawItem::Module(item)); 313 self.push_item(current_module, attrs, RawItemKind::Module(item));
295 return; 314 return;
296 } 315 }
297 tested_by!(name_res_works_for_broken_modules); 316 tested_by!(name_res_works_for_broken_modules);
298 } 317 }
299 318
300 fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { 319 fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) {
320 // FIXME: cfg_attr
301 let is_prelude = use_item.has_atom_attr("prelude_import"); 321 let is_prelude = use_item.has_atom_attr("prelude_import");
302 322 let attrs = self.parse_attrs(&use_item);
303 Path::expand_use_item(&use_item, |path, use_tree, is_glob, alias| { 323
304 let import_data = ImportData { 324 Path::expand_use_item(
305 path, 325 Source { ast: use_item, file_id: self.file_id },
306 alias, 326 self.db,
307 is_glob, 327 |path, use_tree, is_glob, alias| {
308 is_prelude, 328 let import_data = ImportData {
309 is_extern_crate: false, 329 path,
310 is_macro_use: false, 330 alias,
311 }; 331 is_glob,
312 self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree))); 332 is_prelude,
313 }) 333 is_extern_crate: false,
334 is_macro_use: false,
335 };
336 self.push_import(
337 current_module,
338 attrs.clone(),
339 import_data,
340 Either::A(AstPtr::new(use_tree)),
341 );
342 },
343 )
314 } 344 }
315 345
316 fn add_extern_crate_item( 346 fn add_extern_crate_item(
@@ -321,6 +351,8 @@ impl RawItemsCollector {
321 if let Some(name_ref) = extern_crate.name_ref() { 351 if let Some(name_ref) = extern_crate.name_ref() {
322 let path = Path::from_name_ref(&name_ref); 352 let path = Path::from_name_ref(&name_ref);
323 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); 353 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name());
354 let attrs = self.parse_attrs(&extern_crate);
355 // FIXME: cfg_attr
324 let is_macro_use = extern_crate.has_atom_attr("macro_use"); 356 let is_macro_use = extern_crate.has_atom_attr("macro_use");
325 let import_data = ImportData { 357 let import_data = ImportData {
326 path, 358 path,
@@ -330,37 +362,47 @@ impl RawItemsCollector {
330 is_extern_crate: true, 362 is_extern_crate: true,
331 is_macro_use, 363 is_macro_use,
332 }; 364 };
333 self.push_import(current_module, import_data, Either::B(AstPtr::new(&extern_crate))); 365 self.push_import(
366 current_module,
367 attrs,
368 import_data,
369 Either::B(AstPtr::new(&extern_crate)),
370 );
334 } 371 }
335 } 372 }
336 373
337 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { 374 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
338 let path = match m.path().and_then(Path::from_ast) { 375 let attrs = self.parse_attrs(&m);
376 let path = match m
377 .path()
378 .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db))
379 {
339 Some(it) => it, 380 Some(it) => it,
340 _ => return, 381 _ => return,
341 }; 382 };
342 383
343 let name = m.name().map(|it| it.as_name()); 384 let name = m.name().map(|it| it.as_name());
344 let ast_id = self.source_ast_id_map.ast_id(&m); 385 let ast_id = self.source_ast_id_map.ast_id(&m);
345 let export = m.has_atom_attr("macro_export") 386 // FIXME: cfg_attr
346 || m.attrs().filter_map(|x| x.as_call()).any(|(name, _)| name == "macro_export"); 387 let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
347 388
348 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export }); 389 let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
349 self.push_item(current_module, RawItem::Macro(m)); 390 self.push_item(current_module, attrs, RawItemKind::Macro(m));
350 } 391 }
351 392
352 fn push_import( 393 fn push_import(
353 &mut self, 394 &mut self,
354 current_module: Option<Module>, 395 current_module: Option<Module>,
396 attrs: Attrs,
355 data: ImportData, 397 data: ImportData,
356 source: ImportSourcePtr, 398 source: ImportSourcePtr,
357 ) { 399 ) {
358 let import = self.raw_items.imports.alloc(data); 400 let import = self.raw_items.imports.alloc(data);
359 self.source_map.insert(import, source); 401 self.source_map.insert(import, source);
360 self.push_item(current_module, RawItem::Import(import)) 402 self.push_item(current_module, attrs, RawItemKind::Import(import))
361 } 403 }
362 404
363 fn push_item(&mut self, current_module: Option<Module>, item: RawItem) { 405 fn push_item(&mut self, current_module: Option<Module>, attrs: Attrs, kind: RawItemKind) {
364 match current_module { 406 match current_module {
365 Some(module) => match &mut self.raw_items.modules[module] { 407 Some(module) => match &mut self.raw_items.modules[module] {
366 ModuleData::Definition { items, .. } => items, 408 ModuleData::Definition { items, .. } => items,
@@ -368,13 +410,17 @@ impl RawItemsCollector {
368 }, 410 },
369 None => &mut self.raw_items.items, 411 None => &mut self.raw_items.items,
370 } 412 }
371 .push(item) 413 .push(RawItem { attrs, kind })
414 }
415
416 fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
417 Attr::from_attrs_owner(self.file_id, item, self.db)
372 } 418 }
373} 419}
374 420
375fn extract_mod_path_attribute(module: &ast::Module) -> Option<SmolStr> { 421fn extract_mod_path_attribute(module: &ast::Module) -> Option<SmolStr> {
376 module.attrs().into_iter().find_map(|attr| { 422 module.attrs().into_iter().find_map(|attr| {
377 attr.as_key_value().and_then(|(name, value)| { 423 attr.as_simple_key_value().and_then(|(name, value)| {
378 let is_path = name == "path"; 424 let is_path = name == "path";
379 if is_path { 425 if is_path {
380 Some(value) 426 Some(value)
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index bc4b47b70..34dd79574 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -7,6 +7,7 @@ mod mod_resolution;
7use std::sync::Arc; 7use std::sync::Arc;
8 8
9use insta::assert_snapshot; 9use insta::assert_snapshot;
10use ra_cfg::CfgOptions;
10use ra_db::SourceDatabase; 11use ra_db::SourceDatabase;
11use test_utils::covers; 12use test_utils::covers;
12 13
@@ -507,3 +508,72 @@ fn values_dont_shadow_extern_crates() {
507 â‹®foo: v 508 â‹®foo: v
508 "###); 509 "###);
509} 510}
511
512#[test]
513fn cfg_not_test() {
514 let map = def_map_with_crate_graph(
515 r#"
516 //- /main.rs
517 use {Foo, Bar, Baz};
518 //- /lib.rs
519 #[prelude_import]
520 pub use self::prelude::*;
521 mod prelude {
522 #[cfg(test)]
523 pub struct Foo;
524 #[cfg(not(test))]
525 pub struct Bar;
526 #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
527 pub struct Baz;
528 }
529 "#,
530 crate_graph! {
531 "main": ("/main.rs", ["std"]),
532 "std": ("/lib.rs", []),
533 },
534 );
535
536 assert_snapshot!(map, @r###"
537 â‹®crate
538 â‹®Bar: t v
539 â‹®Baz: _
540 â‹®Foo: _
541 "###);
542}
543
544#[test]
545fn cfg_test() {
546 let map = def_map_with_crate_graph(
547 r#"
548 //- /main.rs
549 use {Foo, Bar, Baz};
550 //- /lib.rs
551 #[prelude_import]
552 pub use self::prelude::*;
553 mod prelude {
554 #[cfg(test)]
555 pub struct Foo;
556 #[cfg(not(test))]
557 pub struct Bar;
558 #[cfg(all(not(any()), feature = "foo", feature = "bar", opt = "42"))]
559 pub struct Baz;
560 }
561 "#,
562 crate_graph! {
563 "main": ("/main.rs", ["std"]),
564 "std": ("/lib.rs", [], CfgOptions::default()
565 .atom("test".into())
566 .key_value("feature".into(), "foo".into())
567 .key_value("feature".into(), "bar".into())
568 .key_value("opt".into(), "42".into())
569 ),
570 },
571 );
572
573 assert_snapshot!(map, @r###"
574 â‹®crate
575 â‹®Bar: _
576 â‹®Baz: t v
577 â‹®Foo: t v
578 "###);
579}
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
index bd60f4258..e4b408394 100644
--- a/crates/ra_hir/src/nameres/tests/macros.rs
+++ b/crates/ra_hir/src/nameres/tests/macros.rs
@@ -515,3 +515,108 @@ fn path_qualified_macros() {
515 â‹®not_found: _ 515 â‹®not_found: _
516 "###); 516 "###);
517} 517}
518
519#[test]
520fn macro_dollar_crate_is_correct_in_item() {
521 covers!(macro_dollar_crate_self);
522 covers!(macro_dollar_crate_other);
523 let map = def_map_with_crate_graph(
524 "
525 //- /main.rs
526 #[macro_use]
527 extern crate foo;
528
529 #[macro_use]
530 mod m {
531 macro_rules! current {
532 () => {
533 use $crate::Foo as FooSelf;
534 }
535 }
536 }
537
538 struct Foo;
539
540 current!();
541 not_current1!();
542 foo::not_current2!();
543
544 //- /lib.rs
545 mod m {
546 #[macro_export]
547 macro_rules! not_current1 {
548 () => {
549 use $crate::Bar;
550 }
551 }
552 }
553
554 #[macro_export]
555 macro_rules! not_current2 {
556 () => {
557 use $crate::Baz;
558 }
559 }
560
561 struct Bar;
562 struct Baz;
563 ",
564 crate_graph! {
565 "main": ("/main.rs", ["foo"]),
566 "foo": ("/lib.rs", []),
567 },
568 );
569 assert_snapshot!(map, @r###"
570 â‹®crate
571 â‹®Bar: t v
572 â‹®Baz: t v
573 â‹®Foo: t v
574 â‹®FooSelf: t v
575 â‹®foo: t
576 â‹®m: t
577 â‹®
578 â‹®crate::m
579 "###);
580}
581
582#[test]
583fn macro_dollar_crate_is_correct_in_indirect_deps() {
584 covers!(macro_dollar_crate_other);
585 // From std
586 let map = def_map_with_crate_graph(
587 r#"
588 //- /main.rs
589 foo!();
590
591 //- /std.rs
592 #[prelude_import]
593 use self::prelude::*;
594
595 pub use core::foo;
596
597 mod prelude {}
598
599 #[macro_use]
600 mod std_macros;
601
602 //- /core.rs
603 #[macro_export]
604 macro_rules! foo {
605 () => {
606 use $crate::bar;
607 }
608 }
609
610 pub struct bar;
611 "#,
612 crate_graph! {
613 "main": ("/main.rs", ["std"]),
614 "std": ("/std.rs", ["core"]),
615 "core": ("/core.rs", []),
616 },
617 );
618 assert_snapshot!(map, @r###"
619 â‹®crate
620 â‹®bar: t v
621 "###);
622}
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 39d1b7e46..394617e1a 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{iter, sync::Arc}; 3use std::{iter, sync::Arc};
2 4
3use ra_syntax::{ 5use ra_syntax::{
@@ -5,7 +7,7 @@ use ra_syntax::{
5 AstNode, 7 AstNode,
6}; 8};
7 9
8use crate::{name, type_ref::TypeRef, AsName, Name}; 10use crate::{db::AstDatabase, name, type_ref::TypeRef, AsName, Crate, Name, Source};
9 11
10#[derive(Debug, Clone, PartialEq, Eq, Hash)] 12#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct Path { 13pub struct Path {
@@ -52,16 +54,19 @@ pub enum PathKind {
52 Abs, 54 Abs,
53 // Type based path like `<T>::foo` 55 // Type based path like `<T>::foo`
54 Type(Box<TypeRef>), 56 Type(Box<TypeRef>),
57 // `$crate` from macro expansion
58 DollarCrate(Crate),
55} 59}
56 60
57impl Path { 61impl Path {
58 /// Calls `cb` with all paths, represented by this use item. 62 /// Calls `cb` with all paths, represented by this use item.
59 pub fn expand_use_item( 63 pub fn expand_use_item(
60 item: &ast::UseItem, 64 item_src: Source<ast::UseItem>,
65 db: &impl AstDatabase,
61 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 66 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
62 ) { 67 ) {
63 if let Some(tree) = item.use_tree() { 68 if let Some(tree) = item_src.ast.use_tree() {
64 expand_use_tree(None, tree, &mut cb); 69 expand_use_tree(None, tree, &|| item_src.file_id.macro_crate(db), &mut cb);
65 } 70 }
66 } 71 }
67 72
@@ -76,7 +81,19 @@ impl Path {
76 } 81 }
77 82
78 /// Converts an `ast::Path` to `Path`. Works with use trees. 83 /// Converts an `ast::Path` to `Path`. Works with use trees.
79 pub fn from_ast(mut path: ast::Path) -> Option<Path> { 84 /// DEPRECATED: It does not handle `$crate` from macro call.
85 pub fn from_ast(path: ast::Path) -> Option<Path> {
86 Path::parse(path, &|| None)
87 }
88
89 /// Converts an `ast::Path` to `Path`. Works with use trees.
90 /// It correctly handles `$crate` based path from macro call.
91 pub fn from_src(source: Source<ast::Path>, db: &impl AstDatabase) -> Option<Path> {
92 let file_id = source.file_id;
93 Path::parse(source.ast, &|| file_id.macro_crate(db))
94 }
95
96 fn parse(mut path: ast::Path, macro_crate: &impl Fn() -> Option<Crate>) -> Option<Path> {
80 let mut kind = PathKind::Plain; 97 let mut kind = PathKind::Plain;
81 let mut segments = Vec::new(); 98 let mut segments = Vec::new();
82 loop { 99 loop {
@@ -88,6 +105,13 @@ impl Path {
88 105
89 match segment.kind()? { 106 match segment.kind()? {
90 ast::PathSegmentKind::Name(name) => { 107 ast::PathSegmentKind::Name(name) => {
108 if name.text() == "$crate" {
109 if let Some(macro_crate) = macro_crate() {
110 kind = PathKind::DollarCrate(macro_crate);
111 break;
112 }
113 }
114
91 let args = segment 115 let args = segment
92 .type_arg_list() 116 .type_arg_list()
93 .and_then(GenericArgs::from_ast) 117 .and_then(GenericArgs::from_ast)
@@ -113,7 +137,7 @@ impl Path {
113 } 137 }
114 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo 138 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
115 Some(trait_ref) => { 139 Some(trait_ref) => {
116 let path = Path::from_ast(trait_ref.path()?)?; 140 let path = Path::parse(trait_ref.path()?, macro_crate)?;
117 kind = path.kind; 141 kind = path.kind;
118 let mut prefix_segments = path.segments; 142 let mut prefix_segments = path.segments;
119 prefix_segments.reverse(); 143 prefix_segments.reverse();
@@ -264,6 +288,7 @@ impl From<Name> for Path {
264fn expand_use_tree( 288fn expand_use_tree(
265 prefix: Option<Path>, 289 prefix: Option<Path>,
266 tree: ast::UseTree, 290 tree: ast::UseTree,
291 macro_crate: &impl Fn() -> Option<Crate>,
267 cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 292 cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
268) { 293) {
269 if let Some(use_tree_list) = tree.use_tree_list() { 294 if let Some(use_tree_list) = tree.use_tree_list() {
@@ -272,13 +297,13 @@ fn expand_use_tree(
272 None => prefix, 297 None => prefix,
273 // E.g. `use something::{inner}` (prefix is `None`, path is `something`) 298 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
274 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) 299 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
275 Some(path) => match convert_path(prefix, path) { 300 Some(path) => match convert_path(prefix, path, macro_crate) {
276 Some(it) => Some(it), 301 Some(it) => Some(it),
277 None => return, // FIXME: report errors somewhere 302 None => return, // FIXME: report errors somewhere
278 }, 303 },
279 }; 304 };
280 for child_tree in use_tree_list.use_trees() { 305 for child_tree in use_tree_list.use_trees() {
281 expand_use_tree(prefix.clone(), child_tree, cb); 306 expand_use_tree(prefix.clone(), child_tree, macro_crate, cb);
282 } 307 }
283 } else { 308 } else {
284 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); 309 let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
@@ -295,7 +320,7 @@ fn expand_use_tree(
295 } 320 }
296 } 321 }
297 } 322 }
298 if let Some(path) = convert_path(prefix, ast_path) { 323 if let Some(path) = convert_path(prefix, ast_path, macro_crate) {
299 let is_glob = tree.has_star(); 324 let is_glob = tree.has_star();
300 cb(path, &tree, is_glob, alias) 325 cb(path, &tree, is_glob, alias)
301 } 326 }
@@ -305,12 +330,29 @@ fn expand_use_tree(
305 } 330 }
306} 331}
307 332
308fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> { 333fn convert_path(
309 let prefix = 334 prefix: Option<Path>,
310 if let Some(qual) = path.qualifier() { Some(convert_path(prefix, qual)?) } else { prefix }; 335 path: ast::Path,
336 macro_crate: &impl Fn() -> Option<Crate>,
337) -> Option<Path> {
338 let prefix = if let Some(qual) = path.qualifier() {
339 Some(convert_path(prefix, qual, macro_crate)?)
340 } else {
341 prefix
342 };
343
311 let segment = path.segment()?; 344 let segment = path.segment()?;
312 let res = match segment.kind()? { 345 let res = match segment.kind()? {
313 ast::PathSegmentKind::Name(name) => { 346 ast::PathSegmentKind::Name(name) => {
347 if name.text() == "$crate" {
348 if let Some(krate) = macro_crate() {
349 return Some(Path::from_simple_segments(
350 PathKind::DollarCrate(krate),
351 iter::empty(),
352 ));
353 }
354 }
355
314 // no type args in use 356 // no type args in use
315 let mut res = prefix 357 let mut res = prefix
316 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) }); 358 .unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index bd4be8430..088335e66 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -1,10 +1,10 @@
1/// Lookup hir elements using positions in the source code. This is a lossy 1//! Lookup hir elements using positions in the source code. This is a lossy
2/// transformation: in general, a single source might correspond to several 2//! transformation: in general, a single source might correspond to several
3/// modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on 3//! modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on
4/// modules. 4//! modules.
5/// 5//!
6/// So, this modules should not be used during hir construction, it exists 6//! So, this modules should not be used during hir construction, it exists
7/// purely for "IDE needs". 7//! purely for "IDE needs".
8use std::sync::Arc; 8use std::sync::Arc;
9 9
10use ra_db::FileId; 10use ra_db::FileId;
@@ -203,6 +203,7 @@ impl SourceAnalyzer {
203 db: &impl HirDatabase, 203 db: &impl HirDatabase,
204 macro_call: &ast::MacroCall, 204 macro_call: &ast::MacroCall,
205 ) -> Option<MacroDef> { 205 ) -> Option<MacroDef> {
206 // This must be a normal source file rather than macro file.
206 let path = macro_call.path().and_then(Path::from_ast)?; 207 let path = macro_call.path().and_then(Path::from_ast)?;
207 self.resolver.resolve_path_as_macro(db, &path) 208 self.resolver.resolve_path_as_macro(db, &path)
208 } 209 }
@@ -261,6 +262,7 @@ impl SourceAnalyzer {
261 return Some(PathResolution::AssocItem(assoc)); 262 return Some(PathResolution::AssocItem(assoc));
262 } 263 }
263 } 264 }
265 // This must be a normal source file rather than macro file.
264 let hir_path = crate::Path::from_ast(path.clone())?; 266 let hir_path = crate::Path::from_ast(path.clone())?;
265 self.resolve_hir_path(db, &hir_path) 267 self.resolve_hir_path(db, &hir_path)
266 } 268 }
diff --git a/crates/ra_hir/src/source_id.rs b/crates/ra_hir/src/source_id.rs
index 04574876d..a4dd99598 100644
--- a/crates/ra_hir/src/source_id.rs
+++ b/crates/ra_hir/src/source_id.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{ 3use std::{
2 hash::{Hash, Hasher}, 4 hash::{Hash, Hasher},
3 marker::PhantomData, 5 marker::PhantomData,
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index fae9c1e22..d161735e8 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -14,11 +14,11 @@ pub(crate) mod display;
14 14
15use std::ops::Deref; 15use std::ops::Deref;
16use std::sync::Arc; 16use std::sync::Arc;
17use std::{fmt, mem}; 17use std::{fmt, iter, mem};
18 18
19use crate::{ 19use crate::{
20 db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, DefWithBody, GenericParams, Name, 20 db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, Crate, DefWithBody, GenericParams,
21 Trait, TypeAlias, 21 HasGenericParams, Name, Trait, TypeAlias,
22}; 22};
23use display::{HirDisplay, HirFormatter}; 23use display::{HirDisplay, HirFormatter};
24 24
@@ -111,6 +111,81 @@ pub enum TypeCtor {
111 Closure { def: DefWithBody, expr: ExprId }, 111 Closure { def: DefWithBody, expr: ExprId },
112} 112}
113 113
114impl TypeCtor {
115 pub fn num_ty_params(self, db: &impl HirDatabase) -> usize {
116 match self {
117 TypeCtor::Bool
118 | TypeCtor::Char
119 | TypeCtor::Int(_)
120 | TypeCtor::Float(_)
121 | TypeCtor::Str
122 | TypeCtor::Never => 0,
123 TypeCtor::Slice
124 | TypeCtor::Array
125 | TypeCtor::RawPtr(_)
126 | TypeCtor::Ref(_)
127 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure
128 => 1,
129 TypeCtor::Adt(adt) => {
130 let generic_params = adt.generic_params(db);
131 generic_params.count_params_including_parent()
132 }
133 TypeCtor::FnDef(callable) => {
134 let generic_params = callable.generic_params(db);
135 generic_params.count_params_including_parent()
136 }
137 TypeCtor::AssociatedType(type_alias) => {
138 let generic_params = type_alias.generic_params(db);
139 generic_params.count_params_including_parent()
140 }
141 TypeCtor::FnPtr { num_args } => num_args as usize + 1,
142 TypeCtor::Tuple { cardinality } => cardinality as usize,
143 }
144 }
145
146 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
147 match self {
148 TypeCtor::Bool
149 | TypeCtor::Char
150 | TypeCtor::Int(_)
151 | TypeCtor::Float(_)
152 | TypeCtor::Str
153 | TypeCtor::Never
154 | TypeCtor::Slice
155 | TypeCtor::Array
156 | TypeCtor::RawPtr(_)
157 | TypeCtor::Ref(_)
158 | TypeCtor::FnPtr { .. }
159 | TypeCtor::Tuple { .. } => None,
160 TypeCtor::Closure { def, .. } => def.krate(db),
161 TypeCtor::Adt(adt) => adt.krate(db),
162 TypeCtor::FnDef(callable) => callable.krate(db),
163 TypeCtor::AssociatedType(type_alias) => type_alias.krate(db),
164 }
165 }
166
167 pub fn as_generic_def(self) -> Option<crate::generics::GenericDef> {
168 match self {
169 TypeCtor::Bool
170 | TypeCtor::Char
171 | TypeCtor::Int(_)
172 | TypeCtor::Float(_)
173 | TypeCtor::Str
174 | TypeCtor::Never
175 | TypeCtor::Slice
176 | TypeCtor::Array
177 | TypeCtor::RawPtr(_)
178 | TypeCtor::Ref(_)
179 | TypeCtor::FnPtr { .. }
180 | TypeCtor::Tuple { .. }
181 | TypeCtor::Closure { .. } => None,
182 TypeCtor::Adt(adt) => Some(adt.into()),
183 TypeCtor::FnDef(callable) => Some(callable.into()),
184 TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()),
185 }
186 }
187}
188
114/// A nominal type with (maybe 0) type parameters. This might be a primitive 189/// A nominal type with (maybe 0) type parameters. This might be a primitive
115/// type like `bool`, a struct, tuple, function pointer, reference or 190/// type like `bool`, a struct, tuple, function pointer, reference or
116/// several other things. 191/// several other things.
@@ -271,11 +346,65 @@ impl Substs {
271 .into(), 346 .into(),
272 ) 347 )
273 } 348 }
349
350 pub fn build_for_def(
351 db: &impl HirDatabase,
352 def: impl crate::HasGenericParams,
353 ) -> SubstsBuilder {
354 let params = def.generic_params(db);
355 let param_count = params.count_params_including_parent();
356 Substs::builder(param_count)
357 }
358
359 pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder {
360 Substs::builder(generic_params.count_params_including_parent())
361 }
362
363 pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
364 Substs::builder(type_ctor.num_ty_params(db))
365 }
366
367 fn builder(param_count: usize) -> SubstsBuilder {
368 SubstsBuilder { vec: Vec::with_capacity(param_count), param_count }
369 }
370}
371
372#[derive(Debug, Clone)]
373pub struct SubstsBuilder {
374 vec: Vec<Ty>,
375 param_count: usize,
274} 376}
275 377
276impl From<Vec<Ty>> for Substs { 378impl SubstsBuilder {
277 fn from(v: Vec<Ty>) -> Self { 379 pub fn build(self) -> Substs {
278 Substs(v.into()) 380 assert_eq!(self.vec.len(), self.param_count);
381 Substs(self.vec.into())
382 }
383
384 pub fn push(mut self, ty: Ty) -> Self {
385 self.vec.push(ty);
386 self
387 }
388
389 fn remaining(&self) -> usize {
390 self.param_count - self.vec.len()
391 }
392
393 pub fn fill_with_bound_vars(mut self, starting_from: u32) -> Self {
394 self.vec.extend((starting_from..starting_from + self.remaining() as u32).map(Ty::Bound));
395 self
396 }
397
398 pub fn fill_with_unknown(mut self) -> Self {
399 self.vec.extend(iter::repeat(Ty::Unknown).take(self.remaining()));
400 self
401 }
402
403 pub fn use_parent_substs(mut self, parent_substs: &Substs) -> Self {
404 assert!(self.vec.is_empty());
405 assert!(parent_substs.len() <= self.param_count);
406 self.vec.extend(parent_substs.iter().cloned());
407 self
279 } 408 }
280} 409}
281 410
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 94f8ecdc9..02492ca14 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -7,7 +7,7 @@ use std::iter::successors;
7 7
8use log::{info, warn}; 8use log::{info, warn};
9 9
10use super::{traits::Solution, Canonical, Ty, TypeWalk}; 10use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
11use crate::{db::HirDatabase, name, HasGenericParams, Resolver}; 11use crate::{db::HirDatabase, name, HasGenericParams, Resolver};
12 12
13const AUTODEREF_RECURSION_LIMIT: usize = 10; 13const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -44,7 +44,8 @@ fn deref_by_trait(
44 }; 44 };
45 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; 45 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?;
46 46
47 if target.generic_params(db).count_params_including_parent() != 1 { 47 let generic_params = target.generic_params(db);
48 if generic_params.count_params_including_parent() != 1 {
48 // the Target type + Deref trait should only have one generic parameter, 49 // the Target type + Deref trait should only have one generic parameter,
49 // namely Deref's Self type 50 // namely Deref's Self type
50 return None; 51 return None;
@@ -54,12 +55,13 @@ fn deref_by_trait(
54 55
55 let env = super::lower::trait_env(db, resolver); 56 let env = super::lower::trait_env(db, resolver);
56 57
58 let parameters = Substs::build_for_generics(&generic_params)
59 .push(ty.value.clone().shift_bound_vars(1))
60 .build();
61
57 let projection = super::traits::ProjectionPredicate { 62 let projection = super::traits::ProjectionPredicate {
58 ty: Ty::Bound(0), 63 ty: Ty::Bound(0),
59 projection_ty: super::ProjectionTy { 64 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
60 associated_ty: target,
61 parameters: vec![ty.value.clone().shift_bound_vars(1)].into(),
62 },
63 }; 65 };
64 66
65 let obligation = super::Obligation::Projection(projection); 67 let obligation = super::Obligation::Projection(projection);
diff --git a/crates/ra_hir/src/ty/display.rs b/crates/ra_hir/src/ty/display.rs
index 63ec9d7e1..7910429d7 100644
--- a/crates/ra_hir/src/ty/display.rs
+++ b/crates/ra_hir/src/ty/display.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt; 3use std::fmt;
2 4
3use crate::db::HirDatabase; 5use crate::db::HirDatabase;
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index db3377357..ca9aefc42 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -609,7 +609,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
609 609
610 for (i, &subpat) in subpats.iter().enumerate() { 610 for (i, &subpat) in subpats.iter().enumerate() {
611 let expected_ty = def 611 let expected_ty = def
612 .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) 612 .and_then(|d| d.field(self.db, &Name::new_tuple_field(i)))
613 .map_or(Ty::Unknown, |field| field.ty(self.db)) 613 .map_or(Ty::Unknown, |field| field.ty(self.db))
614 .subst(&substs); 614 .subst(&substs);
615 let expected_ty = self.normalize_associated_types_in(expected_ty); 615 let expected_ty = self.normalize_associated_types_in(expected_ty);
@@ -688,14 +688,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
688 }; 688 };
689 let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); 689 let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown));
690 690
691 let inner_tys: Substs = args 691 let inner_tys = args
692 .iter() 692 .iter()
693 .zip(expectations_iter) 693 .zip(expectations_iter)
694 .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm)) 694 .map(|(&pat, ty)| self.infer_pat(pat, ty, default_bm))
695 .collect::<Vec<_>>() 695 .collect();
696 .into();
697 696
698 Ty::apply(TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, inner_tys) 697 Ty::apply(TypeCtor::Tuple { cardinality: args.len() as u16 }, Substs(inner_tys))
699 } 698 }
700 Pat::Ref { pat, mutability } => { 699 Pat::Ref { pat, mutability } => {
701 let expectation = match expected.as_reference() { 700 let expectation = match expected.as_reference() {
@@ -1229,7 +1228,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1229 ty: pat_ty.clone(), 1228 ty: pat_ty.clone(),
1230 projection_ty: ProjectionTy { 1229 projection_ty: ProjectionTy {
1231 associated_ty: into_iter_item_alias, 1230 associated_ty: into_iter_item_alias,
1232 parameters: vec![iterable_ty].into(), 1231 parameters: Substs::single(iterable_ty),
1233 }, 1232 },
1234 }; 1233 };
1235 self.obligations.push(Obligation::Projection(projection)); 1234 self.obligations.push(Obligation::Projection(projection));
@@ -1262,7 +1261,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1262 sig_tys.push(ret_ty.clone()); 1261 sig_tys.push(ret_ty.clone());
1263 let sig_ty = Ty::apply( 1262 let sig_ty = Ty::apply(
1264 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 1263 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
1265 sig_tys.into(), 1264 Substs(sig_tys.into()),
1266 ); 1265 );
1267 let closure_ty = Ty::apply_one( 1266 let closure_ty = Ty::apply_one(
1268 TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr }, 1267 TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr },
@@ -1375,10 +1374,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1375 ) 1374 )
1376 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { 1375 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) {
1377 Ty::Apply(a_ty) => match a_ty.ctor { 1376 Ty::Apply(a_ty) => match a_ty.ctor {
1378 TypeCtor::Tuple { .. } => { 1377 TypeCtor::Tuple { .. } => name
1379 let i = name.to_string().parse::<usize>().ok(); 1378 .as_tuple_index()
1380 i.and_then(|i| a_ty.parameters.0.get(i).cloned()) 1379 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()),
1381 }
1382 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { 1380 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| {
1383 self.write_field_resolution(tgt_expr, field); 1381 self.write_field_resolution(tgt_expr, field);
1384 field.ty(self.db).subst(&a_ty.parameters) 1382 field.ty(self.db).subst(&a_ty.parameters)
@@ -1400,7 +1398,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1400 ty: ty.clone(), 1398 ty: ty.clone(),
1401 projection_ty: ProjectionTy { 1399 projection_ty: ProjectionTy {
1402 associated_ty: future_future_output_alias, 1400 associated_ty: future_future_output_alias,
1403 parameters: vec![inner_ty].into(), 1401 parameters: Substs::single(inner_ty),
1404 }, 1402 },
1405 }; 1403 };
1406 self.obligations.push(Obligation::Projection(projection)); 1404 self.obligations.push(Obligation::Projection(projection));
@@ -1419,7 +1417,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1419 ty: ty.clone(), 1417 ty: ty.clone(),
1420 projection_ty: ProjectionTy { 1418 projection_ty: ProjectionTy {
1421 associated_ty: ops_try_ok_alias, 1419 associated_ty: ops_try_ok_alias,
1422 parameters: vec![inner_ty].into(), 1420 parameters: Substs::single(inner_ty),
1423 }, 1421 },
1424 }; 1422 };
1425 self.obligations.push(Obligation::Projection(projection)); 1423 self.obligations.push(Obligation::Projection(projection));
@@ -1604,6 +1602,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1604 tail: Option<ExprId>, 1602 tail: Option<ExprId>,
1605 expected: &Expectation, 1603 expected: &Expectation,
1606 ) -> Ty { 1604 ) -> Ty {
1605 let mut diverges = false;
1607 for stmt in statements { 1606 for stmt in statements {
1608 match stmt { 1607 match stmt {
1609 Statement::Let { pat, type_ref, initializer } => { 1608 Statement::Let { pat, type_ref, initializer } => {
@@ -1625,16 +1624,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1625 self.infer_pat(*pat, &ty, BindingMode::default()); 1624 self.infer_pat(*pat, &ty, BindingMode::default());
1626 } 1625 }
1627 Statement::Expr(expr) => { 1626 Statement::Expr(expr) => {
1628 self.infer_expr(*expr, &Expectation::none()); 1627 if let ty_app!(TypeCtor::Never) = self.infer_expr(*expr, &Expectation::none()) {
1628 diverges = true;
1629 }
1629 } 1630 }
1630 } 1631 }
1631 } 1632 }
1632 1633
1633 if let Some(expr) = tail { 1634 let ty = if let Some(expr) = tail {
1634 self.infer_expr_coerce(expr, expected) 1635 self.infer_expr_coerce(expr, expected)
1635 } else { 1636 } else {
1636 self.coerce(&Ty::unit(), &expected.ty); 1637 self.coerce(&Ty::unit(), &expected.ty);
1637 Ty::unit() 1638 Ty::unit()
1639 };
1640 if diverges {
1641 Ty::simple(TypeCtor::Never)
1642 } else {
1643 ty
1638 } 1644 }
1639 } 1645 }
1640 1646
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index feb7481b2..db979353a 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -158,13 +158,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
158 AssocItem::Const(c) => ValueNs::Const(c), 158 AssocItem::Const(c) => ValueNs::Const(c),
159 AssocItem::TypeAlias(_) => unreachable!(), 159 AssocItem::TypeAlias(_) => unreachable!(),
160 }; 160 };
161 let generics = item.generic_params(self.db); 161 let substs = Substs::build_for_def(self.db, item)
162 let mut substs = Vec::with_capacity(generics.count_params_including_parent()); 162 .use_parent_substs(&trait_ref.substs)
163 substs.extend(trait_ref.substs.iter().cloned()); 163 .fill_with_unknown()
164 substs.extend(std::iter::repeat(Ty::Unknown).take(generics.params.len())); 164 .build();
165 165
166 self.write_assoc_resolution(id, item); 166 self.write_assoc_resolution(id, item);
167 Some((def, Some(substs.into()))) 167 Some((def, Some(substs)))
168 } 168 }
169 169
170 fn resolve_ty_assoc_item( 170 fn resolve_ty_assoc_item(
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index b6ebee3b1..d161aa6b3 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -3,7 +3,8 @@
3use super::{InferenceContext, Obligation}; 3use super::{InferenceContext, Obligation};
4use crate::db::HirDatabase; 4use crate::db::HirDatabase;
5use crate::ty::{ 5use crate::ty::{
6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk, 6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty,
7 TypeWalk,
7}; 8};
8 9
9impl<'a, D: HirDatabase> InferenceContext<'a, D> { 10impl<'a, D: HirDatabase> InferenceContext<'a, D> {
@@ -74,12 +75,9 @@ where
74 } 75 }
75 76
76 fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef { 77 fn do_canonicalize_trait_ref(&mut self, trait_ref: TraitRef) -> TraitRef {
77 let substs = trait_ref 78 let substs =
78 .substs 79 trait_ref.substs.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect();
79 .iter() 80 TraitRef { trait_: trait_ref.trait_, substs: Substs(substs) }
80 .map(|ty| self.do_canonicalize_ty(ty.clone()))
81 .collect::<Vec<_>>();
82 TraitRef { trait_: trait_ref.trait_, substs: substs.into() }
83 } 81 }
84 82
85 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 83 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> {
@@ -90,12 +88,9 @@ where
90 } 88 }
91 89
92 fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy { 90 fn do_canonicalize_projection_ty(&mut self, projection_ty: ProjectionTy) -> ProjectionTy {
93 let params = projection_ty 91 let params =
94 .parameters 92 projection_ty.parameters.iter().map(|ty| self.do_canonicalize_ty(ty.clone())).collect();
95 .iter() 93 ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: Substs(params) }
96 .map(|ty| self.do_canonicalize_ty(ty.clone()))
97 .collect::<Vec<_>>();
98 ProjectionTy { associated_ty: projection_ty.associated_ty, parameters: params.into() }
99 } 94 }
100 95
101 fn do_canonicalize_projection_predicate( 96 fn do_canonicalize_projection_predicate(
@@ -153,8 +148,7 @@ impl<T> Canonicalized<T> {
153 solution: Canonical<Vec<Ty>>, 148 solution: Canonical<Vec<Ty>>,
154 ) { 149 ) {
155 // the solution may contain new variables, which we need to convert to new inference vars 150 // the solution may contain new variables, which we need to convert to new inference vars
156 let new_vars = 151 let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect());
157 (0..solution.num_vars).map(|_| ctx.new_type_var()).collect::<Vec<_>>().into();
158 for (i, ty) in solution.value.into_iter().enumerate() { 152 for (i, ty) in solution.value.into_iter().enumerate() {
159 let var = self.free_vars[i]; 153 let var = self.free_vars[i];
160 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); 154 ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars));
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index dd503d771..4b67c82e7 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -239,14 +239,10 @@ impl Ty {
239 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); 239 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db));
240 for t in traits { 240 for t in traits {
241 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { 241 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) {
242 let generics = t.generic_params(db); 242 let substs =
243 let mut substs = Vec::new(); 243 Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build();
244 substs.push(self_ty.clone());
245 substs.extend(
246 iter::repeat(Ty::Unknown).take(generics.count_params_including_parent() - 1),
247 );
248 // FIXME handle type parameters on the segment 244 // FIXME handle type parameters on the segment
249 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs.into() }); 245 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs });
250 } 246 }
251 } 247 }
252 Ty::Unknown 248 Ty::Unknown
@@ -766,6 +762,16 @@ pub enum CallableDef {
766} 762}
767impl_froms!(CallableDef: Function, Struct, EnumVariant); 763impl_froms!(CallableDef: Function, Struct, EnumVariant);
768 764
765impl CallableDef {
766 pub fn krate(self, db: &impl HirDatabase) -> Option<crate::Crate> {
767 match self {
768 CallableDef::Function(f) => f.krate(db),
769 CallableDef::Struct(s) => s.krate(db),
770 CallableDef::EnumVariant(e) => e.parent_enum(db).krate(db),
771 }
772 }
773}
774
769impl From<CallableDef> for GenericDef { 775impl From<CallableDef> for GenericDef {
770 fn from(def: CallableDef) -> GenericDef { 776 fn from(def: CallableDef) -> GenericDef {
771 match def { 777 match def {
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 4b71b376f..ad2ab560d 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -10,7 +10,6 @@ use rustc_hash::FxHashMap;
10use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 10use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
11use crate::{ 11use crate::{
12 db::HirDatabase, 12 db::HirDatabase,
13 generics::HasGenericParams,
14 impl_block::{ImplBlock, ImplId}, 13 impl_block::{ImplBlock, ImplId},
15 nameres::CrateModuleId, 14 nameres::CrateModuleId,
16 resolve::Resolver, 15 resolve::Resolver,
@@ -331,20 +330,13 @@ fn generic_implements_goal(
331 trait_: Trait, 330 trait_: Trait,
332 self_ty: Canonical<Ty>, 331 self_ty: Canonical<Ty>,
333) -> Canonical<InEnvironment<super::Obligation>> { 332) -> Canonical<InEnvironment<super::Obligation>> {
334 let mut substs = Vec::new();
335 let generics = trait_.generic_params(db);
336 let num_vars = self_ty.num_vars; 333 let num_vars = self_ty.num_vars;
337 substs.push(self_ty.value); 334 let substs = super::Substs::build_for_def(db, trait_)
338 substs.extend( 335 .push(self_ty.value)
339 generics 336 .fill_with_bound_vars(num_vars as u32)
340 .params_including_parent() 337 .build();
341 .into_iter()
342 .skip(1)
343 .enumerate()
344 .map(|(i, _p)| Ty::Bound((i + num_vars) as u32)),
345 );
346 let num_vars = substs.len() - 1 + self_ty.num_vars; 338 let num_vars = substs.len() - 1 + self_ty.num_vars;
347 let trait_ref = TraitRef { trait_, substs: substs.into() }; 339 let trait_ref = TraitRef { trait_, substs };
348 let obligation = super::Obligation::Trait(trait_ref); 340 let obligation = super::Obligation::Trait(trait_ref);
349 Canonical { num_vars, value: InEnvironment::new(env, obligation) } 341 Canonical { num_vars, value: InEnvironment::new(env, obligation) }
350} 342}
diff --git a/crates/ra_hir/src/ty/op.rs b/crates/ra_hir/src/ty/op.rs
index 1b30a5b9b..bcfa3a6a2 100644
--- a/crates/ra_hir/src/ty/op.rs
+++ b/crates/ra_hir/src/ty/op.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::{InferTy, Ty, TypeCtor}; 3use super::{InferTy, Ty, TypeCtor};
2use crate::{ 4use crate::{
3 expr::{BinaryOp, CmpOp}, 5 expr::{BinaryOp, CmpOp},
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 2c60fefd6..8966f9d1d 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt; 3use std::fmt;
2 4
3#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] 5#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 4362bb27a..25dad81eb 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3,6 +3,7 @@ use std::sync::Arc;
3 3
4use insta::assert_snapshot; 4use insta::assert_snapshot;
5 5
6use ra_cfg::CfgOptions;
6use ra_db::{salsa::Database, FilePosition, SourceDatabase}; 7use ra_db::{salsa::Database, FilePosition, SourceDatabase};
7use ra_syntax::{ 8use ra_syntax::{
8 algo, 9 algo,
@@ -24,6 +25,50 @@ mod never_type;
24mod coercion; 25mod coercion;
25 26
26#[test] 27#[test]
28fn cfg_impl_block() {
29 let (mut db, pos) = MockDatabase::with_position(
30 r#"
31//- /main.rs
32use foo::S as T;
33struct S;
34
35#[cfg(test)]
36impl S {
37 fn foo1(&self) -> i32 { 0 }
38}
39
40#[cfg(not(test))]
41impl S {
42 fn foo2(&self) -> i32 { 0 }
43}
44
45fn test() {
46 let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4());
47 t<|>;
48}
49
50//- /foo.rs
51struct S;
52
53#[cfg(not(test))]
54impl S {
55 fn foo3(&self) -> i32 { 0 }
56}
57
58#[cfg(test)]
59impl S {
60 fn foo4(&self) -> i32 { 0 }
61}
62"#,
63 );
64 db.set_crate_graph_from_fixture(crate_graph! {
65 "main": ("/main.rs", ["foo"], CfgOptions::default().atom("test".into())),
66 "foo": ("/foo.rs", []),
67 });
68 assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos));
69}
70
71#[test]
27fn infer_await() { 72fn infer_await() {
28 let (mut db, pos) = MockDatabase::with_position( 73 let (mut db, pos) = MockDatabase::with_position(
29 r#" 74 r#"
@@ -218,7 +263,7 @@ fn test(a: u32, b: isize, c: !, d: &str) {
218 [17; 18) 'b': isize 263 [17; 18) 'b': isize
219 [27; 28) 'c': ! 264 [27; 28) 'c': !
220 [33; 34) 'd': &str 265 [33; 34) 'd': &str
221 [42; 121) '{ ...f32; }': () 266 [42; 121) '{ ...f32; }': !
222 [48; 49) 'a': u32 267 [48; 49) 'a': u32
223 [55; 56) 'b': isize 268 [55; 56) 'b': isize
224 [62; 63) 'c': ! 269 [62; 63) 'c': !
@@ -981,6 +1026,67 @@ fn main(foo: Foo) {
981} 1026}
982 1027
983#[test] 1028#[test]
1029fn infer_if_match_with_return() {
1030 assert_snapshot!(
1031 infer(r#"
1032fn foo() {
1033 let _x1 = if true {
1034 1
1035 } else {
1036 return;
1037 };
1038 let _x2 = if true {
1039 2
1040 } else {
1041 return
1042 };
1043 let _x3 = match true {
1044 true => 3,
1045 _ => {
1046 return;
1047 }
1048 };
1049 let _x4 = match true {
1050 true => 4,
1051 _ => return
1052 };
1053}"#),
1054 @r###"
1055 [10; 323) '{ ... }; }': ()
1056 [20; 23) '_x1': i32
1057 [26; 80) 'if tru... }': i32
1058 [29; 33) 'true': bool
1059 [34; 51) '{ ... }': i32
1060 [44; 45) '1': i32
1061 [57; 80) '{ ... }': !
1062 [67; 73) 'return': !
1063 [90; 93) '_x2': i32
1064 [96; 149) 'if tru... }': i32
1065 [99; 103) 'true': bool
1066 [104; 121) '{ ... }': i32
1067 [114; 115) '2': i32
1068 [127; 149) '{ ... }': !
1069 [137; 143) 'return': !
1070 [159; 162) '_x3': i32
1071 [165; 247) 'match ... }': i32
1072 [171; 175) 'true': bool
1073 [186; 190) 'true': bool
1074 [194; 195) '3': i32
1075 [205; 206) '_': bool
1076 [210; 241) '{ ... }': !
1077 [224; 230) 'return': !
1078 [257; 260) '_x4': i32
1079 [263; 320) 'match ... }': i32
1080 [269; 273) 'true': bool
1081 [284; 288) 'true': bool
1082 [292; 293) '4': i32
1083 [303; 304) '_': bool
1084 [308; 314) 'return': !
1085 "###
1086 )
1087}
1088
1089#[test]
984fn infer_inherent_method() { 1090fn infer_inherent_method() {
985 assert_snapshot!( 1091 assert_snapshot!(
986 infer(r#" 1092 infer(r#"
@@ -3130,6 +3236,39 @@ fn test() { S.foo()<|>; }
3130 assert_eq!(t, "u128"); 3236 assert_eq!(t, "u128");
3131} 3237}
3132 3238
3239#[test]
3240fn infer_macro_with_dollar_crate_is_correct_in_expr() {
3241 covers!(macro_dollar_crate_other);
3242 let (mut db, pos) = MockDatabase::with_position(
3243 r#"
3244//- /main.rs
3245fn test() {
3246 let x = (foo::foo!(1), foo::foo!(2));
3247 x<|>;
3248}
3249
3250//- /lib.rs
3251#[macro_export]
3252macro_rules! foo {
3253 (1) => { $crate::bar!() };
3254 (2) => { 1 + $crate::baz() };
3255}
3256
3257#[macro_export]
3258macro_rules! bar {
3259 () => { 42 }
3260}
3261
3262pub fn baz() -> usize { 31usize }
3263"#,
3264 );
3265 db.set_crate_graph_from_fixture(crate_graph! {
3266 "main": ("/main.rs", ["foo"]),
3267 "foo": ("/lib.rs", []),
3268 });
3269 assert_eq!("(i32, usize)", type_at_pos(&db, pos));
3270}
3271
3133#[ignore] 3272#[ignore]
3134#[test] 3273#[test]
3135fn method_resolution_trait_before_autoref() { 3274fn method_resolution_trait_before_autoref() {
@@ -3321,7 +3460,6 @@ fn test() { S2.into()<|>; }
3321 3460
3322#[test] 3461#[test]
3323fn method_resolution_encountering_fn_type() { 3462fn method_resolution_encountering_fn_type() {
3324 covers!(trait_resolution_on_fn_type);
3325 type_at( 3463 type_at(
3326 r#" 3464 r#"
3327//- /main.rs 3465//- /main.rs
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index d11dab294..b0f67ae50 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -1,9 +1,8 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2use std::sync::Arc; 2use std::sync::{Arc, Mutex};
3 3
4use chalk_ir::cast::Cast; 4use chalk_ir::cast::Cast;
5use log::debug; 5use log::debug;
6use parking_lot::Mutex;
7use ra_db::salsa; 6use ra_db::salsa;
8use ra_prof::profile; 7use ra_prof::profile;
9use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
@@ -38,7 +37,14 @@ impl TraitSolver {
38 ) -> Option<chalk_solve::Solution> { 37 ) -> Option<chalk_solve::Solution> {
39 let context = ChalkContext { db, krate: self.krate }; 38 let context = ChalkContext { db, krate: self.krate };
40 debug!("solve goal: {:?}", goal); 39 debug!("solve goal: {:?}", goal);
41 let solution = self.inner.lock().solve(&context, goal); 40 let mut solver = match self.inner.lock() {
41 Ok(it) => it,
42 // Our cancellation works via unwinding, but, as chalk is not
43 // panic-safe, we need to make sure to propagate the cancellation.
44 // Ideally, we should also make chalk panic-safe.
45 Err(_) => ra_db::Canceled::throw(),
46 };
47 let solution = solver.solve(&context, goal);
42 debug!("solve({:?}) => {:?}", goal, solution); 48 debug!("solve({:?}) => {:?}", goal, solution);
43 solution 49 solution
44 } 50 }
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 538b4d3ec..2642a54bf 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -10,17 +10,13 @@ use chalk_ir::{
10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
11 11
12use ra_db::salsa::{InternId, InternKey}; 12use ra_db::salsa::{InternId, InternKey};
13use test_utils::tested_by;
14 13
15use super::{Canonical, ChalkContext, Impl, Obligation}; 14use super::{Canonical, ChalkContext, Impl, Obligation};
16use crate::{ 15use crate::{
17 db::HirDatabase, 16 db::HirDatabase,
18 generics::GenericDef, 17 generics::GenericDef,
19 ty::display::HirDisplay, 18 ty::display::HirDisplay,
20 ty::{ 19 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
22 TypeWalk,
23 },
24 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias, 20 AssocItem, Crate, HasGenericParams, ImplBlock, Trait, TypeAlias,
25}; 21};
26 22
@@ -124,14 +120,15 @@ impl ToChalk for Substs {
124 } 120 }
125 121
126 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs { 122 fn from_chalk(db: &impl HirDatabase, parameters: Vec<chalk_ir::Parameter>) -> Substs {
127 parameters 123 let tys = parameters
128 .into_iter() 124 .into_iter()
129 .map(|p| match p { 125 .map(|p| match p {
130 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), 126 chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty),
131 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), 127 chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(),
132 }) 128 })
133 .collect::<Vec<_>>() 129 .collect::<Vec<_>>()
134 .into() 130 .into();
131 Substs(tys)
135 } 132 }
136} 133}
137 134
@@ -539,60 +536,18 @@ pub(crate) fn struct_datum_query(
539 struct_id: chalk_ir::StructId, 536 struct_id: chalk_ir::StructId,
540) -> Arc<StructDatum> { 537) -> Arc<StructDatum> {
541 debug!("struct_datum {:?}", struct_id); 538 debug!("struct_datum {:?}", struct_id);
542 let type_ctor = from_chalk(db, struct_id); 539 let type_ctor: TypeCtor = from_chalk(db, struct_id);
543 debug!("struct {:?} = {:?}", struct_id, type_ctor); 540 debug!("struct {:?} = {:?}", struct_id, type_ctor);
544 // FIXME might be nicer if we can create a fake GenericParams for the TypeCtor 541 let num_params = type_ctor.num_ty_params(db);
545 // FIXME extract this to a method on Ty 542 let upstream = type_ctor.krate(db) != Some(krate);
546 let (num_params, where_clauses, upstream) = match type_ctor { 543 let where_clauses = type_ctor
547 TypeCtor::Bool 544 .as_generic_def()
548 | TypeCtor::Char 545 .map(|generic_def| {
549 | TypeCtor::Int(_)
550 | TypeCtor::Float(_)
551 | TypeCtor::Never
552 | TypeCtor::Str => (0, vec![], true),
553 TypeCtor::Slice | TypeCtor::Array | TypeCtor::RawPtr(_) | TypeCtor::Ref(_) => {
554 (1, vec![], true)
555 }
556 TypeCtor::FnPtr { num_args } => (num_args as usize + 1, vec![], true),
557 TypeCtor::Tuple { cardinality } => (cardinality as usize, vec![], true),
558 TypeCtor::FnDef(callable) => {
559 tested_by!(trait_resolution_on_fn_type);
560 let upstream = match callable {
561 CallableDef::Function(f) => f.module(db).krate(db),
562 CallableDef::Struct(s) => s.module(db).krate(db),
563 CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db),
564 } != Some(krate);
565 let generic_def: GenericDef = callable.into();
566 let generic_params = generic_def.generic_params(db); 546 let generic_params = generic_def.generic_params(db);
567 let bound_vars = Substs::bound_vars(&generic_params); 547 let bound_vars = Substs::bound_vars(&generic_params);
568 let where_clauses = convert_where_clauses(db, generic_def, &bound_vars); 548 convert_where_clauses(db, generic_def, &bound_vars)
569 (generic_params.count_params_including_parent(), where_clauses, upstream) 549 })
570 } 550 .unwrap_or_else(Vec::new);
571 TypeCtor::Adt(adt) => {
572 let generic_params = adt.generic_params(db);
573 let bound_vars = Substs::bound_vars(&generic_params);
574 let where_clauses = convert_where_clauses(db, adt.into(), &bound_vars);
575 (
576 generic_params.count_params_including_parent(),
577 where_clauses,
578 adt.krate(db) != Some(krate),
579 )
580 }
581 TypeCtor::AssociatedType(type_alias) => {
582 let generic_params = type_alias.generic_params(db);
583 let bound_vars = Substs::bound_vars(&generic_params);
584 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
585 (
586 generic_params.count_params_including_parent(),
587 where_clauses,
588 type_alias.krate(db) != Some(krate),
589 )
590 }
591 TypeCtor::Closure { def, .. } => {
592 let upstream = def.krate(db) != Some(krate);
593 (1, vec![], upstream)
594 }
595 };
596 let flags = chalk_rust_ir::StructFlags { 551 let flags = chalk_rust_ir::StructFlags {
597 upstream, 552 upstream,
598 // FIXME set fundamental flag correctly 553 // FIXME set fundamental flag correctly
@@ -729,17 +684,20 @@ fn closure_fn_trait_impl_datum(
729 684
730 let arg_ty = Ty::apply( 685 let arg_ty = Ty::apply(
731 TypeCtor::Tuple { cardinality: num_args }, 686 TypeCtor::Tuple { cardinality: num_args },
732 (0..num_args).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(), 687 Substs::builder(num_args as usize).fill_with_bound_vars(0).build(),
733 ); 688 );
734 let output_ty = Ty::Bound(num_args.into()); 689 let output_ty = Ty::Bound(num_args.into());
735 let sig_ty = Ty::apply( 690 let sig_ty = Ty::apply(
736 TypeCtor::FnPtr { num_args }, 691 TypeCtor::FnPtr { num_args },
737 (0..num_args + 1).map(|i| Ty::Bound(i.into())).collect::<Vec<_>>().into(), 692 Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(),
738 ); 693 );
739 694
740 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); 695 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
741 696
742 let trait_ref = TraitRef { trait_, substs: vec![self_ty, arg_ty].into() }; 697 let trait_ref = TraitRef {
698 trait_,
699 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
700 };
743 701
744 let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?; 702 let output_ty_id = fn_once_trait.associated_type_by_name(db, &crate::name::OUTPUT_TYPE)?;
745 703
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs
index bc8acc7ee..2cf06b250 100644
--- a/crates/ra_hir/src/type_ref.rs
+++ b/crates/ra_hir/src/type_ref.rs
@@ -72,6 +72,7 @@ impl TypeRef {
72 } 72 }
73 ast::TypeRef::NeverType(..) => TypeRef::Never, 73 ast::TypeRef::NeverType(..) => TypeRef::Never,
74 ast::TypeRef::PathType(inner) => { 74 ast::TypeRef::PathType(inner) => {
75 // FIXME: Use `Path::from_src`
75 inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error) 76 inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error)
76 } 77 }
77 ast::TypeRef::PointerType(inner) => { 78 ast::TypeRef::PointerType(inner) => {
@@ -141,6 +142,7 @@ impl TypeBound {
141 Some(p) => p, 142 Some(p) => p,
142 None => return TypeBound::Error, 143 None => return TypeBound::Error,
143 }; 144 };
145 // FIXME: Use `Path::from_src`
144 let path = match Path::from_ast(path) { 146 let path = match Path::from_ast(path) {
145 Some(p) => p, 147 Some(p) => p,
146 None => return TypeBound::Error, 148 None => return TypeBound::Error,
diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml
index 6bbf9d5dd..f919a2d61 100644
--- a/crates/ra_ide_api/Cargo.toml
+++ b/crates/ra_ide_api/Cargo.toml
@@ -23,6 +23,7 @@ rand = { version = "0.7.0", features = ["small_rng"] }
23ra_syntax = { path = "../ra_syntax" } 23ra_syntax = { path = "../ra_syntax" }
24ra_text_edit = { path = "../ra_text_edit" } 24ra_text_edit = { path = "../ra_text_edit" }
25ra_db = { path = "../ra_db" } 25ra_db = { path = "../ra_db" }
26ra_cfg = { path = "../ra_cfg" }
26ra_fmt = { path = "../ra_fmt" } 27ra_fmt = { path = "../ra_fmt" }
27ra_prof = { path = "../ra_prof" } 28ra_prof = { path = "../ra_prof" }
28hir = { path = "../ra_hir", package = "ra_hir" } 29hir = { path = "../ra_hir", package = "ra_hir" }
diff --git a/crates/ra_ide_api/src/assists.rs b/crates/ra_ide_api/src/assists.rs
index e3d1ac529..e00589733 100644
--- a/crates/ra_ide_api/src/assists.rs
+++ b/crates/ra_ide_api/src/assists.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_db::{FilePosition, FileRange}; 3use ra_db::{FilePosition, FileRange};
2 4
3use crate::{db::RootDatabase, SourceChange, SourceFileEdit}; 5use crate::{db::RootDatabase, SourceChange, SourceFileEdit};
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index d5e116526..7d18be483 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_db::SourceDatabase; 3use ra_db::SourceDatabase;
2use ra_syntax::{ 4use ra_syntax::{
3 algo::find_node_at_offset, 5 algo::find_node_at_offset,
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 981851829..09913787b 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{fmt, sync::Arc, time}; 3use std::{fmt, sync::Arc, time};
2 4
3use ra_db::{ 5use ra_db::{
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide_api/src/completion.rs
index 0ad414831..abe1f36ce 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide_api/src/completion.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod completion_item; 3mod completion_item;
2mod completion_context; 4mod completion_context;
3mod presentation; 5mod presentation;
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 9e64c8659..28c8324d0 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::{Adt, Ty, TypeCtor}; 3use hir::{Adt, Ty, TypeCtor};
2 4
3use crate::completion::completion_item::CompletionKind; 5use crate::completion::completion_item::CompletionKind;
diff --git a/crates/ra_ide_api/src/completion/complete_fn_param.rs b/crates/ra_ide_api/src/completion/complete_fn_param.rs
index 6639b6fff..3e936e3ec 100644
--- a/crates/ra_ide_api/src/completion/complete_fn_param.rs
+++ b/crates/ra_ide_api/src/completion/complete_fn_param.rs
@@ -1,7 +1,6 @@
1use ra_syntax::{ 1//! FIXME: write short doc here
2 algo::visit::{visitor_ctx, VisitorCtx}, 2
3 ast, AstNode, 3use ra_syntax::{ast, match_ast, AstNode};
4};
5use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
6 5
7use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions}; 6use crate::completion::{CompletionContext, CompletionItem, CompletionKind, Completions};
@@ -17,10 +16,13 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
17 16
18 let mut params = FxHashMap::default(); 17 let mut params = FxHashMap::default();
19 for node in ctx.token.parent().ancestors() { 18 for node in ctx.token.parent().ancestors() {
20 let _ = visitor_ctx(&mut params) 19 match_ast! {
21 .visit::<ast::SourceFile, _>(process) 20 match node {
22 .visit::<ast::ItemList, _>(process) 21 ast::SourceFile(it) => { process(it, &mut params) },
23 .accept(&node); 22 ast::ItemList(it) => { process(it, &mut params) },
23 _ => (),
24 }
25 }
24 } 26 }
25 params 27 params
26 .into_iter() 28 .into_iter()
diff --git a/crates/ra_ide_api/src/completion/complete_keyword.rs b/crates/ra_ide_api/src/completion/complete_keyword.rs
index c527a9f63..48c688a08 100644
--- a/crates/ra_ide_api/src/completion/complete_keyword.rs
+++ b/crates/ra_ide_api/src/completion/complete_keyword.rs
@@ -1,7 +1,8 @@
1//! FIXME: write short doc here
2
1use ra_syntax::{ 3use ra_syntax::{
2 algo::visit::{visitor, Visitor},
3 ast::{self, LoopBodyOwner}, 4 ast::{self, LoopBodyOwner},
4 AstNode, 5 match_ast, AstNode,
5 SyntaxKind::*, 6 SyntaxKind::*,
6 SyntaxToken, 7 SyntaxToken,
7}; 8};
@@ -82,12 +83,15 @@ fn is_in_loop_body(leaf: &SyntaxToken) -> bool {
82 if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR { 83 if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
83 break; 84 break;
84 } 85 }
85 let loop_body = visitor() 86 let loop_body = match_ast! {
86 .visit::<ast::ForExpr, _>(|it| it.loop_body()) 87 match node {
87 .visit::<ast::WhileExpr, _>(|it| it.loop_body()) 88 ast::ForExpr(it) => { it.loop_body() },
88 .visit::<ast::LoopExpr, _>(|it| it.loop_body()) 89 ast::WhileExpr(it) => { it.loop_body() },
89 .accept(&node); 90 ast::LoopExpr(it) => { it.loop_body() },
90 if let Some(Some(body)) = loop_body { 91 _ => None,
92 }
93 };
94 if let Some(body) = loop_body {
91 if leaf.text_range().is_subrange(&body.syntax().text_range()) { 95 if leaf.text_range().is_subrange(&body.syntax().text_range()) {
92 return true; 96 return true;
93 } 97 }
diff --git a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs
index 0cbe4abf7..d808b2357 100644
--- a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs
+++ b/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
2 4
3pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) { 5pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &CompletionContext) {
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs
index e9fec54d8..e01197fe4 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide_api/src/completion/complete_path.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::{Adt, Either, PathResolution}; 3use hir::{Adt, Either, PathResolution};
2use ra_syntax::AstNode; 4use ra_syntax::AstNode;
3use test_utils::tested_by; 5use test_utils::tested_by;
diff --git a/crates/ra_ide_api/src/completion/complete_pattern.rs b/crates/ra_ide_api/src/completion/complete_pattern.rs
index c17b5b7ee..513ad6e5f 100644
--- a/crates/ra_ide_api/src/completion/complete_pattern.rs
+++ b/crates/ra_ide_api/src/completion/complete_pattern.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
2 4
3/// Completes constats and paths in patterns. 5/// Completes constats and paths in patterns.
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs
index 3970d1af3..445a02676 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide_api/src/completion/complete_postfix.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{ 3use crate::{
2 completion::{ 4 completion::{
3 completion_context::CompletionContext, 5 completion_context::CompletionContext,
diff --git a/crates/ra_ide_api/src/completion/complete_record_literal.rs b/crates/ra_ide_api/src/completion/complete_record_literal.rs
index ed4029964..4406695d5 100644
--- a/crates/ra_ide_api/src/completion/complete_record_literal.rs
+++ b/crates/ra_ide_api/src/completion/complete_record_literal.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::Substs; 3use hir::Substs;
2 4
3use crate::completion::{CompletionContext, Completions}; 5use crate::completion::{CompletionContext, Completions};
diff --git a/crates/ra_ide_api/src/completion/complete_record_pattern.rs b/crates/ra_ide_api/src/completion/complete_record_pattern.rs
index 70716b3d6..d20fa796c 100644
--- a/crates/ra_ide_api/src/completion/complete_record_pattern.rs
+++ b/crates/ra_ide_api/src/completion/complete_record_pattern.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::Substs; 3use hir::Substs;
2 4
3use crate::completion::{CompletionContext, Completions}; 5use crate::completion::{CompletionContext, Completions};
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index cb70a1f21..515a6285c 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_assists::auto_import_text_edit; 3use ra_assists::auto_import_text_edit;
2use ra_syntax::{ast, AstNode, SmolStr}; 4use ra_syntax::{ast, AstNode, SmolStr};
3use ra_text_edit::TextEditBuilder; 5use ra_text_edit::TextEditBuilder;
diff --git a/crates/ra_ide_api/src/completion/complete_snippet.rs b/crates/ra_ide_api/src/completion/complete_snippet.rs
index b06221c2a..2df79b6c3 100644
--- a/crates/ra_ide_api/src/completion/complete_snippet.rs
+++ b/crates/ra_ide_api/src/completion/complete_snippet.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::completion::{ 3use crate::completion::{
2 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, 4 completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind,
3 CompletionKind, Completions, 5 CompletionKind, Completions,
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 57542152f..e9ad06965 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_syntax::{ 3use ra_syntax::{
2 algo::{find_covering_element, find_node_at_offset}, 4 algo::{find_covering_element, find_node_at_offset},
3 ast, AstNode, Parse, SourceFile, 5 ast, AstNode, Parse, SourceFile,
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs
index d787bb69e..b1f0390ec 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide_api/src/completion/completion_item.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt; 3use std::fmt;
2 4
3use hir::Documentation; 5use hir::Documentation;
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index b8aa433c1..48028a2f9 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -1,4 +1,5 @@
1//! This modules takes care of rendering various definitions as completion items. 1//! This modules takes care of rendering various definitions as completion items.
2
2use hir::{Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; 3use hir::{Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk};
3use join_to_string::join; 4use join_to_string::join;
4use ra_syntax::ast::NameOwner; 5use ra_syntax::ast::NameOwner;
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index afd9022ce..ea0714add 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::sync::Arc; 3use std::sync::Arc;
2 4
3use ra_db::{ 5use ra_db::{
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index 144bc0a70..0435188c8 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -1,11 +1,13 @@
1//! FIXME: write short doc here
2
1use std::cell::RefCell; 3use std::cell::RefCell;
2 4
3use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}; 5use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink};
4use itertools::Itertools; 6use itertools::Itertools;
5use ra_assists::ast_editor::AstEditor;
6use ra_db::SourceDatabase; 7use ra_db::SourceDatabase;
7use ra_prof::profile; 8use ra_prof::profile;
8use ra_syntax::{ 9use ra_syntax::{
10 algo,
9 ast::{self, make, AstNode}, 11 ast::{self, make, AstNode},
10 Location, SyntaxNode, TextRange, T, 12 Location, SyntaxNode, TextRange, T,
11}; 13};
@@ -56,15 +58,15 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
56 }) 58 })
57 }) 59 })
58 .on::<hir::diagnostics::MissingFields, _>(|d| { 60 .on::<hir::diagnostics::MissingFields, _>(|d| {
59 let node = d.ast(db); 61 let mut field_list = d.ast(db);
60 let mut ast_editor = AstEditor::new(node);
61 for f in d.missed_fields.iter() { 62 for f in d.missed_fields.iter() {
62 let field = make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); 63 let field = make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit()));
63 ast_editor.append_field(&field); 64 field_list = field_list.append_field(&field);
64 } 65 }
65 66
66 let mut builder = TextEditBuilder::default(); 67 let mut builder = TextEditBuilder::default();
67 ast_editor.into_text_edit(&mut builder); 68 algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder);
69
68 let fix = 70 let fix =
69 SourceChange::source_file_edit_from("fill struct fields", file_id, builder.finish()); 71 SourceChange::source_file_edit_from("fill struct fields", file_id, builder.finish());
70 res.borrow_mut().push(Diagnostic { 72 res.borrow_mut().push(Diagnostic {
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs
index 644a4532b..43f022ccd 100644
--- a/crates/ra_ide_api/src/display/function_signature.rs
+++ b/crates/ra_ide_api/src/display/function_signature.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt::{self, Display}; 3use std::fmt::{self, Display};
2 4
3use hir::{Docs, Documentation, HasSource}; 5use hir::{Docs, Documentation, HasSource};
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index d3e774bd0..d0b1a8a2a 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -1,9 +1,10 @@
1//! FIXME: write short doc here
2
1use hir::{AssocItem, FieldSource, HasSource, ModuleSource}; 3use hir::{AssocItem, FieldSource, HasSource, ModuleSource};
2use ra_db::{FileId, SourceDatabase}; 4use ra_db::{FileId, SourceDatabase};
3use ra_syntax::{ 5use ra_syntax::{
4 algo::visit::{visitor, Visitor},
5 ast::{self, DocCommentsOwner}, 6 ast::{self, DocCommentsOwner},
6 AstNode, AstPtr, SmolStr, 7 match_ast, AstNode, AstPtr, SmolStr,
7 SyntaxKind::{self, NAME}, 8 SyntaxKind::{self, NAME},
8 SyntaxNode, TextRange, 9 SyntaxNode, TextRange,
9}; 10};
@@ -306,19 +307,22 @@ pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option
306 let parse = db.parse(symbol.file_id); 307 let parse = db.parse(symbol.file_id);
307 let node = symbol.ptr.to_node(parse.tree().syntax()); 308 let node = symbol.ptr.to_node(parse.tree().syntax());
308 309
309 visitor() 310 match_ast! {
310 .visit(|it: ast::FnDef| it.doc_comment_text()) 311 match node {
311 .visit(|it: ast::StructDef| it.doc_comment_text()) 312 ast::FnDef(it) => { it.doc_comment_text() },
312 .visit(|it: ast::EnumDef| it.doc_comment_text()) 313 ast::StructDef(it) => { it.doc_comment_text() },
313 .visit(|it: ast::TraitDef| it.doc_comment_text()) 314 ast::EnumDef(it) => { it.doc_comment_text() },
314 .visit(|it: ast::Module| it.doc_comment_text()) 315 ast::TraitDef(it) => { it.doc_comment_text() },
315 .visit(|it: ast::TypeAliasDef| it.doc_comment_text()) 316 ast::Module(it) => { it.doc_comment_text() },
316 .visit(|it: ast::ConstDef| it.doc_comment_text()) 317 ast::TypeAliasDef(it) => { it.doc_comment_text() },
317 .visit(|it: ast::StaticDef| it.doc_comment_text()) 318 ast::ConstDef(it) => { it.doc_comment_text() },
318 .visit(|it: ast::RecordFieldDef| it.doc_comment_text()) 319 ast::StaticDef(it) => { it.doc_comment_text() },
319 .visit(|it: ast::EnumVariant| it.doc_comment_text()) 320 ast::RecordFieldDef(it) => { it.doc_comment_text() },
320 .visit(|it: ast::MacroCall| it.doc_comment_text()) 321 ast::EnumVariant(it) => { it.doc_comment_text() },
321 .accept(&node)? 322 ast::MacroCall(it) => { it.doc_comment_text() },
323 _ => None,
324 }
325 }
322} 326}
323 327
324/// Get a description of a symbol. 328/// Get a description of a symbol.
@@ -328,16 +332,19 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) ->
328 let parse = db.parse(symbol.file_id); 332 let parse = db.parse(symbol.file_id);
329 let node = symbol.ptr.to_node(parse.tree().syntax()); 333 let node = symbol.ptr.to_node(parse.tree().syntax());
330 334
331 visitor() 335 match_ast! {
332 .visit(|node: ast::FnDef| node.short_label()) 336 match node {
333 .visit(|node: ast::StructDef| node.short_label()) 337 ast::FnDef(it) => { it.short_label() },
334 .visit(|node: ast::EnumDef| node.short_label()) 338 ast::StructDef(it) => { it.short_label() },
335 .visit(|node: ast::TraitDef| node.short_label()) 339 ast::EnumDef(it) => { it.short_label() },
336 .visit(|node: ast::Module| node.short_label()) 340 ast::TraitDef(it) => { it.short_label() },
337 .visit(|node: ast::TypeAliasDef| node.short_label()) 341 ast::Module(it) => { it.short_label() },
338 .visit(|node: ast::ConstDef| node.short_label()) 342 ast::TypeAliasDef(it) => { it.short_label() },
339 .visit(|node: ast::StaticDef| node.short_label()) 343 ast::ConstDef(it) => { it.short_label() },
340 .visit(|node: ast::RecordFieldDef| node.short_label()) 344 ast::StaticDef(it) => { it.short_label() },
341 .visit(|node: ast::EnumVariant| node.short_label()) 345 ast::RecordFieldDef(it) => { it.short_label() },
342 .accept(&node)? 346 ast::EnumVariant(it) => { it.short_label() },
347 _ => None,
348 }
349 }
343} 350}
diff --git a/crates/ra_ide_api/src/display/short_label.rs b/crates/ra_ide_api/src/display/short_label.rs
index b16d504e1..5d2bce3d2 100644
--- a/crates/ra_ide_api/src/display/short_label.rs
+++ b/crates/ra_ide_api/src/display/short_label.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use format_buf::format; 3use format_buf::format;
2use ra_syntax::ast::{self, AstNode, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 4use ra_syntax::ast::{self, AstNode, NameOwner, TypeAscriptionOwner, VisibilityOwner};
3 5
diff --git a/crates/ra_ide_api/src/display/structure.rs b/crates/ra_ide_api/src/display/structure.rs
index be042ed17..ddd8b7b20 100644
--- a/crates/ra_ide_api/src/display/structure.rs
+++ b/crates/ra_ide_api/src/display/structure.rs
@@ -1,9 +1,10 @@
1//! FIXME: write short doc here
2
1use crate::TextRange; 3use crate::TextRange;
2 4
3use ra_syntax::{ 5use ra_syntax::{
4 algo::visit::{visitor, Visitor},
5 ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner}, 6 ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner},
6 AstNode, SourceFile, SyntaxKind, SyntaxNode, WalkEvent, 7 match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, WalkEvent,
7}; 8};
8 9
9#[derive(Debug, Clone)] 10#[derive(Debug, Clone)]
@@ -77,7 +78,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
77 node_range: node.syntax().text_range(), 78 node_range: node.syntax().text_range(),
78 kind: node.syntax().kind(), 79 kind: node.syntax().kind(),
79 detail, 80 detail,
80 deprecated: node.attrs().filter_map(|x| x.as_named()).any(|x| x == "deprecated"), 81 deprecated: node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated"),
81 }) 82 })
82 } 83 }
83 84
@@ -99,63 +100,66 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
99 }) 100 })
100 } 101 }
101 102
102 visitor() 103 match_ast! {
103 .visit(|fn_def: ast::FnDef| { 104 match node {
104 let mut detail = String::from("fn"); 105 ast::FnDef(it) => {
105 if let Some(type_param_list) = fn_def.type_param_list() { 106 let mut detail = String::from("fn");
106 collapse_ws(type_param_list.syntax(), &mut detail); 107 if let Some(type_param_list) = it.type_param_list() {
107 } 108 collapse_ws(type_param_list.syntax(), &mut detail);
108 if let Some(param_list) = fn_def.param_list() { 109 }
109 collapse_ws(param_list.syntax(), &mut detail); 110 if let Some(param_list) = it.param_list() {
110 } 111 collapse_ws(param_list.syntax(), &mut detail);
111 if let Some(ret_type) = fn_def.ret_type() { 112 }
112 detail.push_str(" "); 113 if let Some(ret_type) = it.ret_type() {
113 collapse_ws(ret_type.syntax(), &mut detail); 114 detail.push_str(" ");
114 } 115 collapse_ws(ret_type.syntax(), &mut detail);
115
116 decl_with_detail(fn_def, Some(detail))
117 })
118 .visit(decl::<ast::StructDef>)
119 .visit(decl::<ast::EnumDef>)
120 .visit(decl::<ast::EnumVariant>)
121 .visit(decl::<ast::TraitDef>)
122 .visit(decl::<ast::Module>)
123 .visit(|td: ast::TypeAliasDef| {
124 let ty = td.type_ref();
125 decl_with_type_ref(td, ty)
126 })
127 .visit(decl_with_ascription::<ast::RecordFieldDef>)
128 .visit(decl_with_ascription::<ast::ConstDef>)
129 .visit(decl_with_ascription::<ast::StaticDef>)
130 .visit(|im: ast::ImplBlock| {
131 let target_type = im.target_type()?;
132 let target_trait = im.target_trait();
133 let label = match target_trait {
134 None => format!("impl {}", target_type.syntax().text()),
135 Some(t) => {
136 format!("impl {} for {}", t.syntax().text(), target_type.syntax().text(),)
137 } 116 }
138 };
139 117
140 let node = StructureNode { 118 decl_with_detail(it, Some(detail))
141 parent: None, 119 },
142 label, 120 ast::StructDef(it) => { decl(it) },
143 navigation_range: target_type.syntax().text_range(), 121 ast::EnumDef(it) => { decl(it) },
144 node_range: im.syntax().text_range(), 122 ast::EnumVariant(it) => { decl(it) },
145 kind: im.syntax().kind(), 123 ast::TraitDef(it) => { decl(it) },
146 detail: None, 124 ast::Module(it) => { decl(it) },
147 deprecated: false, 125 ast::TypeAliasDef(it) => {
148 }; 126 let ty = it.type_ref();
149 Some(node) 127 decl_with_type_ref(it, ty)
150 }) 128 },
151 .visit(|mc: ast::MacroCall| { 129 ast::RecordFieldDef(it) => { decl_with_ascription(it) },
152 let first_token = mc.syntax().first_token().unwrap(); 130 ast::ConstDef(it) => { decl_with_ascription(it) },
153 if first_token.text().as_str() != "macro_rules" { 131 ast::StaticDef(it) => { decl_with_ascription(it) },
154 return None; 132 ast::ImplBlock(it) => {
155 } 133 let target_type = it.target_type()?;
156 decl(mc) 134 let target_trait = it.target_trait();
157 }) 135 let label = match target_trait {
158 .accept(&node)? 136 None => format!("impl {}", target_type.syntax().text()),
137 Some(t) => {
138 format!("impl {} for {}", t.syntax().text(), target_type.syntax().text(),)
139 }
140 };
141
142 let node = StructureNode {
143 parent: None,
144 label,
145 navigation_range: target_type.syntax().text_range(),
146 node_range: it.syntax().text_range(),
147 kind: it.syntax().kind(),
148 detail: None,
149 deprecated: false,
150 };
151 Some(node)
152 },
153 ast::MacroCall(it) => {
154 let first_token = it.syntax().first_token().unwrap();
155 if first_token.text().as_str() != "macro_rules" {
156 return None;
157 }
158 decl(it)
159 },
160 _ => None,
161 }
162 }
159} 163}
160 164
161#[cfg(test)] 165#[cfg(test)]
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index e990eb0d1..33fefb541 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_db::SourceDatabase; 3use ra_db::SourceDatabase;
2use ra_syntax::{ 4use ra_syntax::{
3 algo::find_covering_element, 5 algo::find_covering_element,
diff --git a/crates/ra_ide_api/src/feature_flags.rs b/crates/ra_ide_api/src/feature_flags.rs
index 9f82ac71c..d3ca7be03 100644
--- a/crates/ra_ide_api/src/feature_flags.rs
+++ b/crates/ra_ide_api/src/feature_flags.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
2 4
3/// Feature flags hold fine-grained toggles for all *user-visible* features of 5/// Feature flags hold fine-grained toggles for all *user-visible* features of
diff --git a/crates/ra_ide_api/src/folding_ranges.rs b/crates/ra_ide_api/src/folding_ranges.rs
index 79fadcc5d..4eeb76d14 100644
--- a/crates/ra_ide_api/src/folding_ranges.rs
+++ b/crates/ra_ide_api/src/folding_ranges.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use rustc_hash::FxHashSet; 3use rustc_hash::FxHashSet;
2 4
3use ra_syntax::{ 5use ra_syntax::{
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index bc8863dad..41a88314f 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -1,11 +1,10 @@
1//! FIXME: write short doc here
2
1use ra_db::{FileId, SourceDatabase}; 3use ra_db::{FileId, SourceDatabase};
2use ra_syntax::{ 4use ra_syntax::{
3 algo::{ 5 algo::find_node_at_offset,
4 find_node_at_offset,
5 visit::{visitor, Visitor},
6 },
7 ast::{self, DocCommentsOwner}, 6 ast::{self, DocCommentsOwner},
8 AstNode, SyntaxNode, 7 match_ast, AstNode, SyntaxNode,
9}; 8};
10 9
11use crate::{ 10use crate::{
@@ -112,91 +111,99 @@ pub(crate) fn name_definition(
112} 111}
113 112
114fn named_target(file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget> { 113fn named_target(file_id: FileId, node: &SyntaxNode) -> Option<NavigationTarget> {
115 visitor() 114 match_ast! {
116 .visit(|node: ast::StructDef| { 115 match node {
117 NavigationTarget::from_named( 116 ast::StructDef(it) => {
118 file_id, 117 Some(NavigationTarget::from_named(
119 &node, 118 file_id,
120 node.doc_comment_text(), 119 &it,
121 node.short_label(), 120 it.doc_comment_text(),
122 ) 121 it.short_label(),
123 }) 122 ))
124 .visit(|node: ast::EnumDef| { 123 },
125 NavigationTarget::from_named( 124 ast::EnumDef(it) => {
126 file_id, 125 Some(NavigationTarget::from_named(
127 &node, 126 file_id,
128 node.doc_comment_text(), 127 &it,
129 node.short_label(), 128 it.doc_comment_text(),
130 ) 129 it.short_label(),
131 }) 130 ))
132 .visit(|node: ast::EnumVariant| { 131 },
133 NavigationTarget::from_named( 132 ast::EnumVariant(it) => {
134 file_id, 133 Some(NavigationTarget::from_named(
135 &node, 134 file_id,
136 node.doc_comment_text(), 135 &it,
137 node.short_label(), 136 it.doc_comment_text(),
138 ) 137 it.short_label(),
139 }) 138 ))
140 .visit(|node: ast::FnDef| { 139 },
141 NavigationTarget::from_named( 140 ast::FnDef(it) => {
142 file_id, 141 Some(NavigationTarget::from_named(
143 &node, 142 file_id,
144 node.doc_comment_text(), 143 &it,
145 node.short_label(), 144 it.doc_comment_text(),
146 ) 145 it.short_label(),
147 }) 146 ))
148 .visit(|node: ast::TypeAliasDef| { 147 },
149 NavigationTarget::from_named( 148 ast::TypeAliasDef(it) => {
150 file_id, 149 Some(NavigationTarget::from_named(
151 &node, 150 file_id,
152 node.doc_comment_text(), 151 &it,
153 node.short_label(), 152 it.doc_comment_text(),
154 ) 153 it.short_label(),
155 }) 154 ))
156 .visit(|node: ast::ConstDef| { 155 },
157 NavigationTarget::from_named( 156 ast::ConstDef(it) => {
158 file_id, 157 Some(NavigationTarget::from_named(
159 &node, 158 file_id,
160 node.doc_comment_text(), 159 &it,
161 node.short_label(), 160 it.doc_comment_text(),
162 ) 161 it.short_label(),
163 }) 162 ))
164 .visit(|node: ast::StaticDef| { 163 },
165 NavigationTarget::from_named( 164 ast::StaticDef(it) => {
166 file_id, 165 Some(NavigationTarget::from_named(
167 &node, 166 file_id,
168 node.doc_comment_text(), 167 &it,
169 node.short_label(), 168 it.doc_comment_text(),
170 ) 169 it.short_label(),
171 }) 170 ))
172 .visit(|node: ast::TraitDef| { 171 },
173 NavigationTarget::from_named( 172 ast::TraitDef(it) => {
174 file_id, 173 Some(NavigationTarget::from_named(
175 &node, 174 file_id,
176 node.doc_comment_text(), 175 &it,
177 node.short_label(), 176 it.doc_comment_text(),
178 ) 177 it.short_label(),
179 }) 178 ))
180 .visit(|node: ast::RecordFieldDef| { 179 },
181 NavigationTarget::from_named( 180 ast::RecordFieldDef(it) => {
182 file_id, 181 Some(NavigationTarget::from_named(
183 &node, 182 file_id,
184 node.doc_comment_text(), 183 &it,
185 node.short_label(), 184 it.doc_comment_text(),
186 ) 185 it.short_label(),
187 }) 186 ))
188 .visit(|node: ast::Module| { 187 },
189 NavigationTarget::from_named( 188 ast::Module(it) => {
190 file_id, 189 Some(NavigationTarget::from_named(
191 &node, 190 file_id,
192 node.doc_comment_text(), 191 &it,
193 node.short_label(), 192 it.doc_comment_text(),
194 ) 193 it.short_label(),
195 }) 194 ))
196 .visit(|node: ast::MacroCall| { 195 },
197 NavigationTarget::from_named(file_id, &node, node.doc_comment_text(), None) 196 ast::MacroCall(it) => {
198 }) 197 Some(NavigationTarget::from_named(
199 .accept(node) 198 file_id,
199 &it,
200 it.doc_comment_text(),
201 None,
202 ))
203 },
204 _ => None,
205 }
206 }
200} 207}
201 208
202#[cfg(test)] 209#[cfg(test)]
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs
index 72884e5ca..059d80524 100644
--- a/crates/ra_ide_api/src/goto_type_definition.rs
+++ b/crates/ra_ide_api/src/goto_type_definition.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_db::SourceDatabase; 3use ra_db::SourceDatabase;
2use ra_syntax::{ast, AstNode}; 4use ra_syntax::{ast, AstNode};
3 5
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 655bcdb16..24b161c5c 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -1,12 +1,11 @@
1//! FIXME: write short doc here
2
1use hir::{Adt, HasSource, HirDisplay}; 3use hir::{Adt, HasSource, HirDisplay};
2use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
3use ra_syntax::{ 5use ra_syntax::{
4 algo::{ 6 algo::{ancestors_at_offset, find_covering_element, find_node_at_offset},
5 ancestors_at_offset, find_covering_element, find_node_at_offset,
6 visit::{visitor, Visitor},
7 },
8 ast::{self, DocCommentsOwner}, 7 ast::{self, DocCommentsOwner},
9 AstNode, 8 match_ast, AstNode,
10}; 9};
11 10
12use crate::{ 11use crate::{
@@ -176,37 +175,45 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
176 } 175 }
177 } else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { 176 } else if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
178 if let Some(parent) = name.syntax().parent() { 177 if let Some(parent) = name.syntax().parent() {
179 let text = visitor() 178 let text = match_ast! {
180 .visit(|node: ast::StructDef| { 179 match parent {
181 hover_text(node.doc_comment_text(), node.short_label()) 180 ast::StructDef(it) => {
182 }) 181 hover_text(it.doc_comment_text(), it.short_label())
183 .visit(|node: ast::EnumDef| hover_text(node.doc_comment_text(), node.short_label())) 182 },
184 .visit(|node: ast::EnumVariant| { 183 ast::EnumDef(it) => {
185 hover_text(node.doc_comment_text(), node.short_label()) 184 hover_text(it.doc_comment_text(), it.short_label())
186 }) 185 },
187 .visit(|node: ast::FnDef| hover_text(node.doc_comment_text(), node.short_label())) 186 ast::EnumVariant(it) => {
188 .visit(|node: ast::TypeAliasDef| { 187 hover_text(it.doc_comment_text(), it.short_label())
189 hover_text(node.doc_comment_text(), node.short_label()) 188 },
190 }) 189 ast::FnDef(it) => {
191 .visit(|node: ast::ConstDef| { 190 hover_text(it.doc_comment_text(), it.short_label())
192 hover_text(node.doc_comment_text(), node.short_label()) 191 },
193 }) 192 ast::TypeAliasDef(it) => {
194 .visit(|node: ast::StaticDef| { 193 hover_text(it.doc_comment_text(), it.short_label())
195 hover_text(node.doc_comment_text(), node.short_label()) 194 },
196 }) 195 ast::ConstDef(it) => {
197 .visit(|node: ast::TraitDef| { 196 hover_text(it.doc_comment_text(), it.short_label())
198 hover_text(node.doc_comment_text(), node.short_label()) 197 },
199 }) 198 ast::StaticDef(it) => {
200 .visit(|node: ast::RecordFieldDef| { 199 hover_text(it.doc_comment_text(), it.short_label())
201 hover_text(node.doc_comment_text(), node.short_label()) 200 },
202 }) 201 ast::TraitDef(it) => {
203 .visit(|node: ast::Module| hover_text(node.doc_comment_text(), node.short_label())) 202 hover_text(it.doc_comment_text(), it.short_label())
204 .visit(|node: ast::MacroCall| hover_text(node.doc_comment_text(), None)) 203 },
205 .accept(&parent); 204 ast::RecordFieldDef(it) => {
206 205 hover_text(it.doc_comment_text(), it.short_label())
207 if let Some(text) = text { 206 },
208 res.extend(text); 207 ast::Module(it) => {
209 } 208 hover_text(it.doc_comment_text(), it.short_label())
209 },
210 ast::MacroCall(it) => {
211 hover_text(it.doc_comment_text(), None)
212 },
213 _ => None,
214 }
215 };
216 res.extend(text);
210 } 217 }
211 218
212 if !res.is_empty() && range.is_none() { 219 if !res.is_empty() && range.is_none() {
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
index f57f9a21b..7fc1b1efa 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide_api/src/impls.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::{db::HirDatabase, ApplicationTy, FromSource, Ty, TypeCtor}; 3use hir::{db::HirDatabase, ApplicationTy, FromSource, Ty, TypeCtor};
2use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
3use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 5use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs
index 16bdcf9d1..f1c0dc164 100644
--- a/crates/ra_ide_api/src/inlay_hints.rs
+++ b/crates/ra_ide_api/src/inlay_hints.rs
@@ -1,9 +1,10 @@
1//! FIXME: write short doc here
2
1use crate::{db::RootDatabase, FileId}; 3use crate::{db::RootDatabase, FileId};
2use hir::{HirDisplay, SourceAnalyzer, Ty}; 4use hir::{HirDisplay, SourceAnalyzer, Ty};
3use ra_syntax::{ 5use ra_syntax::{
4 algo::visit::{visitor, Visitor},
5 ast::{self, AstNode, TypeAscriptionOwner}, 6 ast::{self, AstNode, TypeAscriptionOwner},
6 SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, 7 match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange,
7}; 8};
8 9
9#[derive(Debug, PartialEq, Eq)] 10#[derive(Debug, PartialEq, Eq)]
@@ -31,55 +32,58 @@ fn get_inlay_hints(
31 file_id: FileId, 32 file_id: FileId,
32 node: &SyntaxNode, 33 node: &SyntaxNode,
33) -> Option<Vec<InlayHint>> { 34) -> Option<Vec<InlayHint>> {
34 visitor() 35 match_ast! {
35 .visit(|let_statement: ast::LetStmt| { 36 match node {
36 if let_statement.ascribed_type().is_some() { 37 ast::LetStmt(it) => {
37 return None; 38 if it.ascribed_type().is_some() {
38 } 39 return None;
39 let pat = let_statement.pat()?; 40 }
40 let analyzer = SourceAnalyzer::new(db, file_id, let_statement.syntax(), None); 41 let pat = it.pat()?;
41 Some(get_pat_type_hints(db, &analyzer, pat, false)) 42 let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None);
42 }) 43 Some(get_pat_type_hints(db, &analyzer, pat, false))
43 .visit(|closure_parameter: ast::LambdaExpr| { 44 },
44 let analyzer = SourceAnalyzer::new(db, file_id, closure_parameter.syntax(), None); 45 ast::LambdaExpr(it) => {
45 closure_parameter.param_list().map(|param_list| { 46 let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None);
46 param_list 47 it.param_list().map(|param_list| {
47 .params() 48 param_list
48 .filter(|closure_param| closure_param.ascribed_type().is_none()) 49 .params()
49 .filter_map(|closure_param| closure_param.pat()) 50 .filter(|closure_param| closure_param.ascribed_type().is_none())
50 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false)) 51 .filter_map(|closure_param| closure_param.pat())
51 .flatten() 52 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false))
52 .collect() 53 .flatten()
53 }) 54 .collect()
54 }) 55 })
55 .visit(|for_expression: ast::ForExpr| { 56 },
56 let pat = for_expression.pat()?; 57 ast::ForExpr(it) => {
57 let analyzer = SourceAnalyzer::new(db, file_id, for_expression.syntax(), None); 58 let pat = it.pat()?;
58 Some(get_pat_type_hints(db, &analyzer, pat, false)) 59 let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None);
59 }) 60 Some(get_pat_type_hints(db, &analyzer, pat, false))
60 .visit(|if_expr: ast::IfExpr| { 61 },
61 let pat = if_expr.condition()?.pat()?; 62 ast::IfExpr(it) => {
62 let analyzer = SourceAnalyzer::new(db, file_id, if_expr.syntax(), None); 63 let pat = it.condition()?.pat()?;
63 Some(get_pat_type_hints(db, &analyzer, pat, true)) 64 let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None);
64 }) 65 Some(get_pat_type_hints(db, &analyzer, pat, true))
65 .visit(|while_expr: ast::WhileExpr| { 66 },
66 let pat = while_expr.condition()?.pat()?; 67 ast::WhileExpr(it) => {
67 let analyzer = SourceAnalyzer::new(db, file_id, while_expr.syntax(), None); 68 let pat = it.condition()?.pat()?;
68 Some(get_pat_type_hints(db, &analyzer, pat, true)) 69 let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None);
69 }) 70 Some(get_pat_type_hints(db, &analyzer, pat, true))
70 .visit(|match_arm_list: ast::MatchArmList| { 71 },
71 let analyzer = SourceAnalyzer::new(db, file_id, match_arm_list.syntax(), None); 72 ast::MatchArmList(it) => {
72 Some( 73 let analyzer = SourceAnalyzer::new(db, file_id, it.syntax(), None);
73 match_arm_list 74 Some(
74 .arms() 75 it
75 .map(|match_arm| match_arm.pats()) 76 .arms()
76 .flatten() 77 .map(|match_arm| match_arm.pats())
77 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true)) 78 .flatten()
78 .flatten() 79 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true))
79 .collect(), 80 .flatten()
80 ) 81 .collect(),
81 }) 82 )
82 .accept(&node)? 83 },
84 _ => None,
85 }
86 }
83} 87}
84 88
85fn get_pat_type_hints( 89fn get_pat_type_hints(
diff --git a/crates/ra_ide_api/src/join_lines.rs b/crates/ra_ide_api/src/join_lines.rs
index a71e4ed7d..6f71b27db 100644
--- a/crates/ra_ide_api/src/join_lines.rs
+++ b/crates/ra_ide_api/src/join_lines.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use itertools::Itertools; 3use itertools::Itertools;
2use ra_fmt::{compute_ws, extract_trivial_expression}; 4use ra_fmt::{compute_ws, extract_trivial_expression};
3use ra_syntax::{ 5use ra_syntax::{
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 44d1ec77b..24f1b91f6 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -49,6 +49,7 @@ mod test_utils;
49 49
50use std::sync::Arc; 50use std::sync::Arc;
51 51
52use ra_cfg::CfgOptions;
52use ra_db::{ 53use ra_db::{
53 salsa::{self, ParallelDatabase}, 54 salsa::{self, ParallelDatabase},
54 CheckCanceled, SourceDatabase, 55 CheckCanceled, SourceDatabase,
@@ -322,7 +323,10 @@ impl Analysis {
322 change.add_root(source_root, true); 323 change.add_root(source_root, true);
323 let mut crate_graph = CrateGraph::default(); 324 let mut crate_graph = CrateGraph::default();
324 let file_id = FileId(0); 325 let file_id = FileId(0);
325 crate_graph.add_crate_root(file_id, Edition::Edition2018); 326 // FIXME: cfg options
327 // Default to enable test for single file.
328 let cfg_options = CfgOptions::default().atom("test".into());
329 crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options);
326 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); 330 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text));
327 change.set_crate_graph(crate_graph); 331 change.set_crate_graph(crate_graph);
328 host.apply_change(change); 332 host.apply_change(change);
diff --git a/crates/ra_ide_api/src/line_index.rs b/crates/ra_ide_api/src/line_index.rs
index 71de8a928..710890d27 100644
--- a/crates/ra_ide_api/src/line_index.rs
+++ b/crates/ra_ide_api/src/line_index.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::TextUnit; 3use crate::TextUnit;
2use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
3use superslice::Ext; 5use superslice::Ext;
@@ -278,5 +280,4 @@ const C: char = \"メ メ\";
278 280
279 assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextUnit::from_usize(15)); 281 assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextUnit::from_usize(15));
280 } 282 }
281
282} 283}
diff --git a/crates/ra_ide_api/src/line_index_utils.rs b/crates/ra_ide_api/src/line_index_utils.rs
index 534009b98..bd1e08feb 100644
--- a/crates/ra_ide_api/src/line_index_utils.rs
+++ b/crates/ra_ide_api/src/line_index_utils.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{line_index::Utf16Char, LineCol, LineIndex}; 3use crate::{line_index::Utf16Char, LineCol, LineIndex};
2use ra_syntax::{TextRange, TextUnit}; 4use ra_syntax::{TextRange, TextUnit};
3use ra_text_edit::{AtomTextEdit, TextEdit}; 5use ra_text_edit::{AtomTextEdit, TextEdit};
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs
index c3752cc54..3f4ba248b 100644
--- a/crates/ra_ide_api/src/marks.rs
+++ b/crates/ra_ide_api/src/marks.rs
@@ -1,3 +1,5 @@
1//! See test_utils/src/marks.rs
2
1test_utils::marks!( 3test_utils::marks!(
2 inserts_parens_for_function_calls 4 inserts_parens_for_function_calls
3 goto_definition_works_for_macros 5 goto_definition_works_for_macros
diff --git a/crates/ra_ide_api/src/matching_brace.rs b/crates/ra_ide_api/src/matching_brace.rs
index e802d01e4..d1204fac0 100644
--- a/crates/ra_ide_api/src/matching_brace.rs
+++ b/crates/ra_ide_api/src/matching_brace.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_syntax::{ast::AstNode, SourceFile, SyntaxKind, TextUnit, T}; 3use ra_syntax::{ast::AstNode, SourceFile, SyntaxKind, TextUnit, T};
2 4
3pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { 5pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs
index 132f6f875..80b71894c 100644
--- a/crates/ra_ide_api/src/mock_analysis.rs
+++ b/crates/ra_ide_api/src/mock_analysis.rs
@@ -1,5 +1,8 @@
1//! FIXME: write short doc here
2
1use std::sync::Arc; 3use std::sync::Arc;
2 4
5use ra_cfg::CfgOptions;
3use relative_path::RelativePathBuf; 6use relative_path::RelativePathBuf;
4use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; 7use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER};
5 8
@@ -91,10 +94,11 @@ impl MockAnalysis {
91 assert!(path.starts_with('/')); 94 assert!(path.starts_with('/'));
92 let path = RelativePathBuf::from_path(&path[1..]).unwrap(); 95 let path = RelativePathBuf::from_path(&path[1..]).unwrap();
93 let file_id = FileId(i as u32 + 1); 96 let file_id = FileId(i as u32 + 1);
97 let cfg_options = CfgOptions::default();
94 if path == "/lib.rs" || path == "/main.rs" { 98 if path == "/lib.rs" || path == "/main.rs" {
95 root_crate = Some(crate_graph.add_crate_root(file_id, Edition2018)); 99 root_crate = Some(crate_graph.add_crate_root(file_id, Edition2018, cfg_options));
96 } else if path.ends_with("/lib.rs") { 100 } else if path.ends_with("/lib.rs") {
97 let other_crate = crate_graph.add_crate_root(file_id, Edition2018); 101 let other_crate = crate_graph.add_crate_root(file_id, Edition2018, cfg_options);
98 let crate_name = path.parent().unwrap().file_name().unwrap(); 102 let crate_name = path.parent().unwrap().file_name().unwrap();
99 if let Some(root_crate) = root_crate { 103 if let Some(root_crate) = root_crate {
100 crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap(); 104 crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap();
diff --git a/crates/ra_ide_api/src/name_ref_kind.rs b/crates/ra_ide_api/src/name_ref_kind.rs
index aff03464a..149585971 100644
--- a/crates/ra_ide_api/src/name_ref_kind.rs
+++ b/crates/ra_ide_api/src/name_ref_kind.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::Either; 3use hir::Either;
2use ra_syntax::{ast, AstNode, AstPtr}; 4use ra_syntax::{ast, AstNode, AstPtr};
3use test_utils::tested_by; 5use test_utils::tested_by;
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs
index 3668da8d7..566509849 100644
--- a/crates/ra_ide_api/src/parent_module.rs
+++ b/crates/ra_ide_api/src/parent_module.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_db::{CrateId, FileId, FilePosition}; 3use ra_db::{CrateId, FileId, FilePosition};
2 4
3use crate::{db::RootDatabase, NavigationTarget}; 5use crate::{db::RootDatabase, NavigationTarget};
@@ -39,6 +41,7 @@ mod tests {
39 AnalysisChange, CrateGraph, 41 AnalysisChange, CrateGraph,
40 Edition::Edition2018, 42 Edition::Edition2018,
41 }; 43 };
44 use ra_cfg::CfgOptions;
42 45
43 #[test] 46 #[test]
44 fn test_resolve_parent_module() { 47 fn test_resolve_parent_module() {
@@ -86,7 +89,7 @@ mod tests {
86 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); 89 assert!(host.analysis().crate_for(mod_file).unwrap().is_empty());
87 90
88 let mut crate_graph = CrateGraph::default(); 91 let mut crate_graph = CrateGraph::default();
89 let crate_id = crate_graph.add_crate_root(root_file, Edition2018); 92 let crate_id = crate_graph.add_crate_root(root_file, Edition2018, CfgOptions::default());
90 let mut change = AnalysisChange::new(); 93 let mut change = AnalysisChange::new();
91 change.set_crate_graph(crate_graph); 94 change.set_crate_graph(crate_graph);
92 host.apply_change(change); 95 host.apply_change(change);
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index acca71f2a..84c2eb793 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use hir::{Either, ModuleSource}; 3use hir::{Either, ModuleSource};
2use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
3use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode}; 5use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode};
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs
index 095ca56c4..910883da7 100644
--- a/crates/ra_ide_api/src/runnables.rs
+++ b/crates/ra_ide_api/src/runnables.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use itertools::Itertools; 3use itertools::Itertools;
2use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
3use ra_syntax::{ 5use ra_syntax::{
@@ -229,5 +231,4 @@ mod tests {
229 let runnables = analysis.runnables(pos.file_id).unwrap(); 231 let runnables = analysis.runnables(pos.file_id).unwrap();
230 assert!(runnables.is_empty()) 232 assert!(runnables.is_empty())
231 } 233 }
232
233} 234}
diff --git a/crates/ra_ide_api/src/snapshots/highlighting.html b/crates/ra_ide_api/src/snapshots/highlighting.html
index b39c4d371..ae30ebba3 100644
--- a/crates/ra_ide_api/src/snapshots/highlighting.html
+++ b/crates/ra_ide_api/src/snapshots/highlighting.html
@@ -19,7 +19,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
19.keyword\.unsafe { color: #DFAF8F; } 19.keyword\.unsafe { color: #DFAF8F; }
20.keyword\.control { color: #F0DFAF; font-weight: bold; } 20.keyword\.control { color: #F0DFAF; font-weight: bold; }
21</style> 21</style>
22<pre><code><span class="attribute">#</span><span class="attribute">[</span><span class="attribute">derive</span><span class="attribute">(</span><span class="attribute">Clone</span><span class="attribute">,</span><span class="attribute"> </span><span class="attribute">Debug</span><span class="attribute">)</span><span class="attribute">]</span> 22<pre><code><span class="attribute">#</span><span class="attribute">[</span><span class="attribute text">derive</span><span class="attribute">(</span><span class="attribute">Clone</span><span class="attribute">,</span><span class="attribute"> </span><span class="attribute">Debug</span><span class="attribute">)</span><span class="attribute">]</span>
23<span class="keyword">struct</span> <span class="type">Foo</span> { 23<span class="keyword">struct</span> <span class="type">Foo</span> {
24 <span class="keyword">pub</span> <span class="field">x</span>: <span class="type">i32</span>, 24 <span class="keyword">pub</span> <span class="field">x</span>: <span class="type">i32</span>,
25 <span class="keyword">pub</span> <span class="field">y</span>: <span class="type">i32</span>, 25 <span class="keyword">pub</span> <span class="field">y</span>: <span class="type">i32</span>,
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs
index dee2ea46a..f91f16c8e 100644
--- a/crates/ra_ide_api/src/status.rs
+++ b/crates/ra_ide_api/src/status.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{fmt, iter::FromIterator, sync::Arc}; 3use std::{fmt, iter::FromIterator, sync::Arc};
2 4
3use hir::MacroFile; 5use hir::MacroFile;
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs
index 02cdfbc60..797e9926f 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide_api/src/symbol_index.rs
@@ -32,9 +32,8 @@ use ra_db::{
32 SourceDatabase, SourceRootId, 32 SourceDatabase, SourceRootId,
33}; 33};
34use ra_syntax::{ 34use ra_syntax::{
35 algo::visit::{visitor, Visitor},
36 ast::{self, NameOwner}, 35 ast::{self, NameOwner},
37 AstNode, Parse, SmolStr, SourceFile, 36 match_ast, AstNode, Parse, SmolStr, SourceFile,
38 SyntaxKind::{self, *}, 37 SyntaxKind::{self, *},
39 SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent, 38 SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent,
40}; 39};
@@ -306,16 +305,19 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> {
306 305
307 Some((name, ptr, name_range)) 306 Some((name, ptr, name_range))
308 } 307 }
309 visitor() 308 match_ast! {
310 .visit(decl::<ast::FnDef>) 309 match node {
311 .visit(decl::<ast::StructDef>) 310 ast::FnDef(it) => { decl(it) },
312 .visit(decl::<ast::EnumDef>) 311 ast::StructDef(it) => { decl(it) },
313 .visit(decl::<ast::TraitDef>) 312 ast::EnumDef(it) => { decl(it) },
314 .visit(decl::<ast::Module>) 313 ast::TraitDef(it) => { decl(it) },
315 .visit(decl::<ast::TypeAliasDef>) 314 ast::Module(it) => { decl(it) },
316 .visit(decl::<ast::ConstDef>) 315 ast::TypeAliasDef(it) => { decl(it) },
317 .visit(decl::<ast::StaticDef>) 316 ast::ConstDef(it) => { decl(it) },
318 .accept(node)? 317 ast::StaticDef(it) => { decl(it) },
318 _ => None,
319 }
320 }
319} 321}
320 322
321fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> { 323fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 3d7f91c1d..9ae2dc061 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
2 4
3use hir::{Mutability, Ty}; 5use hir::{Mutability, Ty};
diff --git a/crates/ra_ide_api/src/syntax_tree.rs b/crates/ra_ide_api/src/syntax_tree.rs
index e2bb120b4..4d0f0fc47 100644
--- a/crates/ra_ide_api/src/syntax_tree.rs
+++ b/crates/ra_ide_api/src/syntax_tree.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::db::RootDatabase; 3use crate::db::RootDatabase;
2use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
3use ra_syntax::{ 5use ra_syntax::{
diff --git a/crates/ra_ide_api/src/test_utils.rs b/crates/ra_ide_api/src/test_utils.rs
index 6e0d883b4..8adb214d4 100644
--- a/crates/ra_ide_api/src/test_utils.rs
+++ b/crates/ra_ide_api/src/test_utils.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_syntax::{SourceFile, TextUnit}; 3use ra_syntax::{SourceFile, TextUnit};
2use ra_text_edit::TextEdit; 4use ra_text_edit::TextEdit;
3 5
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs
index 2d4491442..2f5782012 100644
--- a/crates/ra_ide_api/src/typing.rs
+++ b/crates/ra_ide_api/src/typing.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_db::{FilePosition, SourceDatabase}; 3use ra_db::{FilePosition, SourceDatabase};
2use ra_fmt::leading_indent; 4use ra_fmt::leading_indent;
3use ra_syntax::{ 5use ra_syntax::{
diff --git a/crates/ra_ide_api/src/wasm_shims.rs b/crates/ra_ide_api/src/wasm_shims.rs
index 592dddf44..088cc9be4 100644
--- a/crates/ra_ide_api/src/wasm_shims.rs
+++ b/crates/ra_ide_api/src/wasm_shims.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1#[cfg(not(feature = "wasm"))] 3#[cfg(not(feature = "wasm"))]
2pub use std::time::Instant; 4pub use std::time::Instant;
3 5
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 677d81835..aedc55a95 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -19,6 +19,7 @@ jod-thread = "0.1.0"
19ra_vfs = "0.4.0" 19ra_vfs = "0.4.0"
20ra_syntax = { path = "../ra_syntax" } 20ra_syntax = { path = "../ra_syntax" }
21ra_db = { path = "../ra_db" } 21ra_db = { path = "../ra_db" }
22ra_cfg = { path = "../ra_cfg" }
22ra_text_edit = { path = "../ra_text_edit" } 23ra_text_edit = { path = "../ra_text_edit" }
23ra_ide_api = { path = "../ra_ide_api" } 24ra_ide_api = { path = "../ra_ide_api" }
24lsp-server = "0.2.0" 25lsp-server = "0.2.0"
diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs
index 22fc97a97..30bcbd7a8 100644
--- a/crates/ra_lsp_server/src/caps.rs
+++ b/crates/ra_lsp_server/src/caps.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use lsp_types::{ 3use lsp_types::{
2 CodeActionProviderCapability, CodeLensOptions, CompletionOptions, 4 CodeActionProviderCapability, CodeLensOptions, CompletionOptions,
3 DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability, 5 DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability,
diff --git a/crates/ra_lsp_server/src/cargo_target_spec.rs b/crates/ra_lsp_server/src/cargo_target_spec.rs
index a083bb311..d996b53de 100644
--- a/crates/ra_lsp_server/src/cargo_target_spec.rs
+++ b/crates/ra_lsp_server/src/cargo_target_spec.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_ide_api::{FileId, RunnableKind}; 3use ra_ide_api::{FileId, RunnableKind};
2use ra_project_model::{self, ProjectWorkspace, TargetKind}; 4use ra_project_model::{self, ProjectWorkspace, TargetKind};
3 5
diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs
index cf53e7c4c..579d4c692 100644
--- a/crates/ra_lsp_server/src/config.rs
+++ b/crates/ra_lsp_server/src/config.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use rustc_hash::FxHashMap; 3use rustc_hash::FxHashMap;
2 4
3use serde::{Deserialize, Deserializer}; 5use serde::{Deserialize, Deserializer};
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index d78f77925..1318a1738 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use lsp_types::{ 3use lsp_types::{
2 self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation, 4 self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation,
3 Location, LocationLink, MarkupContent, MarkupKind, Position, Range, RenameFile, ResourceOp, 5 Location, LocationLink, MarkupContent, MarkupKind, Position, Range, RenameFile, ResourceOp,
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs
index fa3d88abd..7a71a90fb 100644
--- a/crates/ra_lsp_server/src/lib.rs
+++ b/crates/ra_lsp_server/src/lib.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1#![recursion_limit = "512"] 3#![recursion_limit = "512"]
2mod caps; 4mod caps;
3mod cargo_target_spec; 5mod cargo_target_spec;
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index 852fae027..7d9a1d054 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use flexi_logger::{Duplicate, Logger}; 3use flexi_logger::{Duplicate, Logger};
2use lsp_server::Connection; 4use lsp_server::Connection;
3 5
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 2059f9800..35c35d32b 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod handlers; 3mod handlers;
2mod subscriptions; 4mod subscriptions;
3pub(crate) mod pending_requests; 5pub(crate) mod pending_requests;
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index ae57e57e9..10e271376 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{fmt::Write as _, io::Write as _}; 3use std::{fmt::Write as _, io::Write as _};
2 4
3use lsp_server::ErrorCode; 5use lsp_server::ErrorCode;
diff --git a/crates/ra_lsp_server/src/main_loop/pending_requests.rs b/crates/ra_lsp_server/src/main_loop/pending_requests.rs
index 7a99fc679..e7ea7aa5b 100644
--- a/crates/ra_lsp_server/src/main_loop/pending_requests.rs
+++ b/crates/ra_lsp_server/src/main_loop/pending_requests.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::time::{Duration, Instant}; 3use std::time::{Duration, Instant};
2 4
3use lsp_server::RequestId; 5use lsp_server::RequestId;
diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
index bbeda723c..3856263b0 100644
--- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs
+++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_ide_api::FileId; 3use ra_ide_api::FileId;
2use rustc_hash::FxHashSet; 4use rustc_hash::FxHashSet;
3 5
diff --git a/crates/ra_lsp_server/src/markdown.rs b/crates/ra_lsp_server/src/markdown.rs
index c1eb0236a..f51fc4ade 100644
--- a/crates/ra_lsp_server/src/markdown.rs
+++ b/crates/ra_lsp_server/src/markdown.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1pub(crate) fn format_docs(src: &str) -> String { 3pub(crate) fn format_docs(src: &str) -> String {
2 let mut processed_lines = Vec::new(); 4 let mut processed_lines = Vec::new();
3 let mut in_code_block = false; 5 let mut in_code_block = false;
@@ -70,5 +72,4 @@ let a = 1;
70 "```rust\nfn main(){}\n```\nSome comment.\n```rust\nlet a = 1;\n```" 72 "```rust\nfn main(){}\n```\nSome comment.\n```rust\nlet a = 1;\n```"
71 ); 73 );
72 } 74 }
73
74} 75}
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs
index 0540f166e..d25fc5726 100644
--- a/crates/ra_lsp_server/src/req.rs
+++ b/crates/ra_lsp_server/src/req.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url}; 3use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url};
2use rustc_hash::FxHashMap; 4use rustc_hash::FxHashMap;
3use serde::{Deserialize, Serialize}; 5use serde::{Deserialize, Serialize};
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 232409c3b..27da751ab 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{ 3use std::{
2 path::{Path, PathBuf}, 4 path::{Path, PathBuf},
3 sync::Arc, 5 sync::Arc,
@@ -11,7 +13,7 @@ use ra_ide_api::{
11 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData, 13 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData,
12 SourceRootId, 14 SourceRootId,
13}; 15};
14use ra_project_model::ProjectWorkspace; 16use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace};
15use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; 17use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
16use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; 18use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
17use relative_path::RelativePathBuf; 19use relative_path::RelativePathBuf;
@@ -95,6 +97,10 @@ impl WorldState {
95 change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string()); 97 change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string());
96 } 98 }
97 99
100 // FIXME: Read default cfgs from config
101 let default_cfg_options =
102 get_rustc_cfg_options().atom("test".into()).atom("debug_assertion".into());
103
98 // Create crate graph from all the workspaces 104 // Create crate graph from all the workspaces
99 let mut crate_graph = CrateGraph::default(); 105 let mut crate_graph = CrateGraph::default();
100 let mut load = |path: &std::path::Path| { 106 let mut load = |path: &std::path::Path| {
@@ -102,7 +108,7 @@ impl WorldState {
102 vfs_file.map(|f| FileId(f.0)) 108 vfs_file.map(|f| FileId(f.0))
103 }; 109 };
104 for ws in workspaces.iter() { 110 for ws in workspaces.iter() {
105 let (graph, crate_names) = ws.to_crate_graph(&mut load); 111 let (graph, crate_names) = ws.to_crate_graph(&default_cfg_options, &mut load);
106 let shift = crate_graph.extend(graph); 112 let shift = crate_graph.extend(graph);
107 for (crate_id, name) in crate_names { 113 for (crate_id, name) in crate_names {
108 change.set_debug_crate_name(crate_id.shift(shift), name) 114 change.set_debug_crate_name(crate_id.shift(shift), name)
diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs
index 152681062..2ba82ab05 100644
--- a/crates/ra_lsp_server/tests/heavy_tests/main.rs
+++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs
@@ -286,7 +286,13 @@ fn test_missing_module_code_action_in_json_project() {
286 286
287 let project = json!({ 287 let project = json!({
288 "roots": [path], 288 "roots": [path],
289 "crates": [ { "root_module": path.join("src/lib.rs"), "deps": [], "edition": "2015" } ] 289 "crates": [ {
290 "root_module": path.join("src/lib.rs"),
291 "deps": [],
292 "edition": "2015",
293 "atom_cfgs": [],
294 "key_value_cfgs": {}
295 } ]
290 }); 296 });
291 297
292 let code = format!( 298 let code = format!(
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index a0904323c..afdbee84e 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -1,7 +1,7 @@
1/// `mbe` (short for Macro By Example) crate contains code for handling 1//! `mbe` (short for Macro By Example) crate contains code for handling
2/// `macro_rules` macros. It uses `TokenTree` (from `ra_tt` package) as the 2//! `macro_rules` macros. It uses `TokenTree` (from `ra_tt` package) as the
3/// interface, although it contains some code to bridge `SyntaxNode`s and 3//! interface, although it contains some code to bridge `SyntaxNode`s and
4/// `TokenTree`s as well! 4//! `TokenTree`s as well!
5 5
6mod parser; 6mod parser;
7mod mbe_expander; 7mod mbe_expander;
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs
index aff953102..0548e8512 100644
--- a/crates/ra_mbe/src/mbe_expander/matcher.rs
+++ b/crates/ra_mbe/src/mbe_expander/matcher.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{ 3use crate::{
2 mbe_expander::{Binding, Bindings, Fragment}, 4 mbe_expander::{Binding, Bindings, Fragment},
3 parser::{parse_pattern, Op, RepeatKind, Separator}, 5 parser::{parse_pattern, Op, RepeatKind, Separator},
diff --git a/crates/ra_mbe/src/mbe_expander/transcriber.rs b/crates/ra_mbe/src/mbe_expander/transcriber.rs
index c22680b93..ed094d5bb 100644
--- a/crates/ra_mbe/src/mbe_expander/transcriber.rs
+++ b/crates/ra_mbe/src/mbe_expander/transcriber.rs
@@ -86,7 +86,7 @@ fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> Result<tt::Sub
86 86
87fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> Result<Fragment, ExpandError> { 87fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> Result<Fragment, ExpandError> {
88 let res = if v == "crate" { 88 let res = if v == "crate" {
89 // FIXME: Properly handle $crate token 89 // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
90 let tt = 90 let tt =
91 tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }) 91 tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() })
92 .into(); 92 .into();
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs
index cf7458905..7ef45f6dc 100644
--- a/crates/ra_mbe/src/subtree_source.rs
+++ b/crates/ra_mbe/src/subtree_source.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_parser::{Token, TokenSource}; 3use ra_parser::{Token, TokenSource};
2use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T}; 4use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T};
3use std::cell::{Cell, Ref, RefCell}; 5use std::cell::{Cell, Ref, RefCell};
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 2d035307b..1b543c84b 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_parser::{ 3use ra_parser::{
2 FragmentKind::{self, *}, 4 FragmentKind::{self, *},
3 ParseError, TreeSink, 5 ParseError, TreeSink,
diff --git a/crates/ra_mbe/src/tt_iter.rs b/crates/ra_mbe/src/tt_iter.rs
index c53f99d1e..319f1ee65 100644
--- a/crates/ra_mbe/src/tt_iter.rs
+++ b/crates/ra_mbe/src/tt_iter.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1#[derive(Debug, Clone)] 3#[derive(Debug, Clone)]
2pub(crate) struct TtIter<'a> { 4pub(crate) struct TtIter<'a> {
3 pub(crate) inner: std::slice::Iter<'a, tt::TokenTree>, 5 pub(crate) inner: std::slice::Iter<'a, tt::TokenTree>,
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index e2355aff9..6e9e212b7 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -135,7 +135,6 @@ pub(crate) mod fragments {
135 135
136 m.complete(p, MACRO_STMTS); 136 m.complete(p, MACRO_STMTS);
137 } 137 }
138
139} 138}
140 139
141pub(crate) fn reparser( 140pub(crate) fn reparser(
diff --git a/crates/ra_parser/src/grammar/attributes.rs b/crates/ra_parser/src/grammar/attributes.rs
index 1cfd301b5..f3158ade3 100644
--- a/crates/ra_parser/src/grammar/attributes.rs
+++ b/crates/ra_parser/src/grammar/attributes.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) fn inner_attributes(p: &mut Parser) { 5pub(super) fn inner_attributes(p: &mut Parser) {
@@ -22,8 +24,23 @@ fn attribute(p: &mut Parser, inner: bool) {
22 p.bump(T![!]); 24 p.bump(T![!]);
23 } 25 }
24 26
25 if p.at(T!['[']) { 27 if p.eat(T!['[']) {
26 items::token_tree(p); 28 paths::use_path(p);
29
30 match p.current() {
31 T![=] => {
32 p.bump(T![=]);
33 if expressions::literal(p).is_none() {
34 p.error("expected literal");
35 }
36 }
37 T!['('] | T!['['] | T!['{'] => items::token_tree(p),
38 _ => {}
39 }
40
41 if !p.eat(T![']']) {
42 p.error("expected `]`");
43 }
27 } else { 44 } else {
28 p.error("expected `[`"); 45 p.error("expected `[`");
29 } 46 }
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 80b085280..45f2e3de4 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod atom; 3mod atom;
2 4
3pub(crate) use self::atom::match_arm_list; 5pub(crate) use self::atom::match_arm_list;
@@ -248,6 +250,7 @@ fn current_op(p: &Parser) -> (u8, SyntaxKind) {
248 T![!] if p.at(T![!=]) => (5, T![!=]), 250 T![!] if p.at(T![!=]) => (5, T![!=]),
249 T![-] if p.at(T![-=]) => (1, T![-=]), 251 T![-] if p.at(T![-=]) => (1, T![-=]),
250 T![-] => (10, T![-]), 252 T![-] => (10, T![-]),
253 T![as] => (12, T![as]),
251 254
252 _ => NOT_AN_OP 255 _ => NOT_AN_OP
253 } 256 }
@@ -276,6 +279,14 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>,
276 if op_bp < bp { 279 if op_bp < bp {
277 break; 280 break;
278 } 281 }
282 // test as_precedence
283 // fn foo() {
284 // let _ = &1 as *const i32;
285 // }
286 if p.at(T![as]) {
287 lhs = cast_expr(p, lhs);
288 continue;
289 }
279 let m = lhs.precede(p); 290 let m = lhs.precede(p);
280 p.bump(op); 291 p.bump(op);
281 292
@@ -333,9 +344,16 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
333 // } 344 // }
334 // 345 //
335 let (lhs, blocklike) = atom::atom_expr(p, r)?; 346 let (lhs, blocklike) = atom::atom_expr(p, r)?;
336 return Some(postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()))); 347 return Some(postfix_expr(
348 p,
349 lhs,
350 blocklike,
351 !(r.prefer_stmt && blocklike.is_block()),
352 r.forbid_structs,
353 ));
337 } 354 }
338 }; 355 };
356 // parse the interior of the unary expression
339 expr_bp(p, r, 255); 357 expr_bp(p, r, 255);
340 Some((m.complete(p, kind), BlockLike::NotBlock)) 358 Some((m.complete(p, kind), BlockLike::NotBlock))
341} 359}
@@ -348,6 +366,7 @@ fn postfix_expr(
348 // `while true {break}; ();` 366 // `while true {break}; ();`
349 mut block_like: BlockLike, 367 mut block_like: BlockLike,
350 mut allow_calls: bool, 368 mut allow_calls: bool,
369 forbid_structs: bool,
351) -> (CompletedMarker, BlockLike) { 370) -> (CompletedMarker, BlockLike) {
352 loop { 371 loop {
353 lhs = match p.current() { 372 lhs = match p.current() {
@@ -361,7 +380,7 @@ fn postfix_expr(
361 // } 380 // }
362 T!['('] if allow_calls => call_expr(p, lhs), 381 T!['('] if allow_calls => call_expr(p, lhs),
363 T!['['] if allow_calls => index_expr(p, lhs), 382 T!['['] if allow_calls => index_expr(p, lhs),
364 T![.] => match postfix_dot_expr(p, lhs) { 383 T![.] => match postfix_dot_expr(p, lhs, forbid_structs) {
365 Ok(it) => it, 384 Ok(it) => it,
366 Err(it) => { 385 Err(it) => {
367 lhs = it; 386 lhs = it;
@@ -369,7 +388,6 @@ fn postfix_expr(
369 } 388 }
370 }, 389 },
371 T![?] => try_expr(p, lhs), 390 T![?] => try_expr(p, lhs),
372 T![as] => cast_expr(p, lhs),
373 _ => break, 391 _ => break,
374 }; 392 };
375 allow_calls = true; 393 allow_calls = true;
@@ -380,6 +398,7 @@ fn postfix_expr(
380 fn postfix_dot_expr( 398 fn postfix_dot_expr(
381 p: &mut Parser, 399 p: &mut Parser,
382 lhs: CompletedMarker, 400 lhs: CompletedMarker,
401 forbid_structs: bool,
383 ) -> Result<CompletedMarker, CompletedMarker> { 402 ) -> Result<CompletedMarker, CompletedMarker> {
384 assert!(p.at(T![.])); 403 assert!(p.at(T![.]));
385 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) { 404 if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])) {
@@ -400,10 +419,17 @@ fn postfix_expr(
400 } 419 }
401 420
402 // test postfix_range 421 // test postfix_range
403 // fn foo() { let x = 1..; } 422 // fn foo() {
404 for &(op, la) in [(T![..=], 3), (T![..], 2)].iter() { 423 // let x = 1..;
424 // match 1.. { _ => () };
425 // match a.b()..S { _ => () };
426 // }
427 for &(op, la) in &[(T![..=], 3), (T![..], 2)] {
405 if p.at(op) { 428 if p.at(op) {
406 return if EXPR_FIRST.contains(p.nth(la)) { 429 let next_token = p.nth(la);
430 let has_trailing_expression =
431 !(forbid_structs && next_token == T!['{']) && EXPR_FIRST.contains(next_token);
432 return if has_trailing_expression {
407 Err(lhs) 433 Err(lhs)
408 } else { 434 } else {
409 let m = lhs.precede(p); 435 let m = lhs.precede(p);
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 457f42a26..7454005c4 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3// test expr_literals 5// test expr_literals
@@ -119,11 +121,7 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
119 // break; 121 // break;
120 // } 122 // }
121 // } 123 // }
122 if r.forbid_structs { 124 block_expr(p, None)
123 return None;
124 } else {
125 block_expr(p, None)
126 }
127 } 125 }
128 T![return] => return_expr(p), 126 T![return] => return_expr(p),
129 T![continue] => continue_expr(p), 127 T![continue] => continue_expr(p),
@@ -259,6 +257,7 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
259// if true {} else {}; 257// if true {} else {};
260// if true {} else if false {} else {}; 258// if true {} else if false {} else {};
261// if S {}; 259// if S {};
260// if { true } { } else { };
262// } 261// }
263fn if_expr(p: &mut Parser) -> CompletedMarker { 262fn if_expr(p: &mut Parser) -> CompletedMarker {
264 assert!(p.at(T![if])); 263 assert!(p.at(T![if]));
@@ -307,6 +306,7 @@ fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
307// fn foo() { 306// fn foo() {
308// while true {}; 307// while true {};
309// while let Some(x) = it.next() {}; 308// while let Some(x) = it.next() {};
309// while { true } {};
310// } 310// }
311fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 311fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
312 assert!(p.at(T![while])); 312 assert!(p.at(T![while]));
@@ -354,6 +354,8 @@ fn cond(p: &mut Parser) {
354// fn foo() { 354// fn foo() {
355// match () { }; 355// match () { };
356// match S {}; 356// match S {};
357// match { } { _ => () };
358// match { S {} } {};
357// } 359// }
358fn match_expr(p: &mut Parser) -> CompletedMarker { 360fn match_expr(p: &mut Parser) -> CompletedMarker {
359 assert!(p.at(T![match])); 361 assert!(p.at(T![match]));
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 4c67a5c2e..85f7eeb00 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod consts; 3mod consts;
2mod nominal; 4mod nominal;
3mod traits; 5mod traits;
diff --git a/crates/ra_parser/src/grammar/items/consts.rs b/crates/ra_parser/src/grammar/items/consts.rs
index 310260689..742a7e056 100644
--- a/crates/ra_parser/src/grammar/items/consts.rs
+++ b/crates/ra_parser/src/grammar/items/consts.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) fn static_def(p: &mut Parser, m: Marker) { 5pub(super) fn static_def(p: &mut Parser, m: Marker) {
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/nominal.rs
index bede3b692..9d8fb8486 100644
--- a/crates/ra_parser/src/grammar/items/nominal.rs
+++ b/crates/ra_parser/src/grammar/items/nominal.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) { 5pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs
index 3742fd197..2c560e824 100644
--- a/crates/ra_parser/src/grammar/items/traits.rs
+++ b/crates/ra_parser/src/grammar/items/traits.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3// test trait_item 5// test trait_item
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
index 63ac37e9e..e3b991c8c 100644
--- a/crates/ra_parser/src/grammar/items/use_item.rs
+++ b/crates/ra_parser/src/grammar/items/use_item.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) fn use_item(p: &mut Parser, m: Marker) { 5pub(super) fn use_item(p: &mut Parser, m: Marker) {
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index efc329243..c10b53316 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3// test param_list 5// test param_list
diff --git a/crates/ra_parser/src/grammar/paths.rs b/crates/ra_parser/src/grammar/paths.rs
index 24b65128e..ca8e075a1 100644
--- a/crates/ra_parser/src/grammar/paths.rs
+++ b/crates/ra_parser/src/grammar/paths.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) const PATH_FIRST: TokenSet = 5pub(super) const PATH_FIRST: TokenSet =
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index aa9a6d18e..f5d12278c 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST 5pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs
index 8e97fe03c..7256c2697 100644
--- a/crates/ra_parser/src/grammar/type_args.rs
+++ b/crates/ra_parser/src/grammar/type_args.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) { 5pub(super) fn opt_type_arg_list(p: &mut Parser, colon_colon_required: bool) {
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs
index 7071c70ea..34406b5bd 100644
--- a/crates/ra_parser/src/grammar/type_params.rs
+++ b/crates/ra_parser/src/grammar/type_params.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) fn opt_type_param_list(p: &mut Parser) { 5pub(super) fn opt_type_param_list(p: &mut Parser) {
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs
index 4e3522d48..d4ca94fca 100644
--- a/crates/ra_parser/src/grammar/types.rs
+++ b/crates/ra_parser/src/grammar/types.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use super::*; 3use super::*;
2 4
3pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![ 5pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(token_set![
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
index f8fba6860..dafd5247b 100644
--- a/crates/ra_parser/src/parser.rs
+++ b/crates/ra_parser/src/parser.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::cell::Cell; 3use std::cell::Cell;
2 4
3use drop_bomb::DropBomb; 5use drop_bomb::DropBomb;
diff --git a/crates/ra_parser/src/syntax_kind.rs b/crates/ra_parser/src/syntax_kind.rs
index 3efcfa403..8d6bd057b 100644
--- a/crates/ra_parser/src/syntax_kind.rs
+++ b/crates/ra_parser/src/syntax_kind.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1#[macro_use] 3#[macro_use]
2mod generated; 4mod generated;
3 5
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 8b43d93fe..96b5bce88 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -1,4 +1,4 @@
1// Generated file, do not edit by hand, see `crate/ra_tools/src/codegen` 1//! Generated file, do not edit by hand, see `crate/ra_tools/src/codegen`
2 2
3#![allow(bad_style, missing_docs, unreachable_pub)] 3#![allow(bad_style, missing_docs, unreachable_pub)]
4#[doc = r" The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`."] 4#[doc = r" The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT_DEF`."]
diff --git a/crates/ra_parser/src/token_set.rs b/crates/ra_parser/src/token_set.rs
index 79121b35f..6dc061889 100644
--- a/crates/ra_parser/src/token_set.rs
+++ b/crates/ra_parser/src/token_set.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::SyntaxKind; 3use crate::SyntaxKind;
2 4
3/// A bit-set of `SyntaxKind`s 5/// A bit-set of `SyntaxKind`s
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs
index d32a289be..885a98750 100644
--- a/crates/ra_prof/src/lib.rs
+++ b/crates/ra_prof/src/lib.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod memory_usage; 3mod memory_usage;
2#[cfg(feature = "cpu_profiler")] 4#[cfg(feature = "cpu_profiler")]
3mod google_cpu_profiler; 5mod google_cpu_profiler;
diff --git a/crates/ra_prof/src/memory_usage.rs b/crates/ra_prof/src/memory_usage.rs
index 8e8cb7299..ad005ea14 100644
--- a/crates/ra_prof/src/memory_usage.rs
+++ b/crates/ra_prof/src/memory_usage.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt; 3use std::fmt;
2 4
3pub struct MemoryUsage { 5pub struct MemoryUsage {
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml
index ae6b91aa6..a65100031 100644
--- a/crates/ra_project_model/Cargo.toml
+++ b/crates/ra_project_model/Cargo.toml
@@ -12,6 +12,7 @@ cargo_metadata = "0.8.2"
12 12
13ra_arena = { path = "../ra_arena" } 13ra_arena = { path = "../ra_arena" }
14ra_db = { path = "../ra_db" } 14ra_db = { path = "../ra_db" }
15ra_cfg = { path = "../ra_cfg" }
15 16
16serde = { version = "1.0.89", features = ["derive"] } 17serde = { version = "1.0.89", features = ["derive"] }
17serde_json = "1.0.39" 18serde_json = "1.0.39"
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 712d8818f..28dadea9d 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::path::{Path, PathBuf}; 3use std::path::{Path, PathBuf};
2 4
3use cargo_metadata::{CargoOpt, MetadataCommand}; 5use cargo_metadata::{CargoOpt, MetadataCommand};
@@ -37,6 +39,7 @@ struct PackageData {
37 is_member: bool, 39 is_member: bool,
38 dependencies: Vec<PackageDependency>, 40 dependencies: Vec<PackageDependency>,
39 edition: Edition, 41 edition: Edition,
42 features: Vec<String>,
40} 43}
41 44
42#[derive(Debug, Clone)] 45#[derive(Debug, Clone)]
@@ -89,6 +92,9 @@ impl Package {
89 pub fn edition(self, ws: &CargoWorkspace) -> Edition { 92 pub fn edition(self, ws: &CargoWorkspace) -> Edition {
90 ws.packages[self].edition 93 ws.packages[self].edition
91 } 94 }
95 pub fn features(self, ws: &CargoWorkspace) -> &[String] {
96 &ws.packages[self].features
97 }
92 pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Target> + 'a { 98 pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Target> + 'a {
93 ws.packages[self].targets.iter().cloned() 99 ws.packages[self].targets.iter().cloned()
94 } 100 }
@@ -142,6 +148,7 @@ impl CargoWorkspace {
142 is_member, 148 is_member,
143 edition: Edition::from_string(&meta_pkg.edition), 149 edition: Edition::from_string(&meta_pkg.edition),
144 dependencies: Vec::new(), 150 dependencies: Vec::new(),
151 features: Vec::new(),
145 }); 152 });
146 let pkg_data = &mut packages[pkg]; 153 let pkg_data = &mut packages[pkg];
147 pkg_by_id.insert(meta_pkg.id.clone(), pkg); 154 pkg_by_id.insert(meta_pkg.id.clone(), pkg);
@@ -162,6 +169,7 @@ impl CargoWorkspace {
162 let dep = PackageDependency { name: dep_node.name, pkg: pkg_by_id[&dep_node.pkg] }; 169 let dep = PackageDependency { name: dep_node.name, pkg: pkg_by_id[&dep_node.pkg] };
163 packages[source].dependencies.push(dep); 170 packages[source].dependencies.push(dep);
164 } 171 }
172 packages[source].features.extend(node.features);
165 } 173 }
166 174
167 Ok(CargoWorkspace { packages, targets, workspace_root: meta.workspace_root }) 175 Ok(CargoWorkspace { packages, targets, workspace_root: meta.workspace_root })
diff --git a/crates/ra_project_model/src/json_project.rs b/crates/ra_project_model/src/json_project.rs
index 9a9eb9e1f..1bacb1d09 100644
--- a/crates/ra_project_model/src/json_project.rs
+++ b/crates/ra_project_model/src/json_project.rs
@@ -1,5 +1,8 @@
1//! FIXME: write short doc here
2
1use std::path::PathBuf; 3use std::path::PathBuf;
2 4
5use rustc_hash::{FxHashMap, FxHashSet};
3use serde::Deserialize; 6use serde::Deserialize;
4 7
5/// A root points to the directory which contains Rust crates. rust-analyzer watches all files in 8/// A root points to the directory which contains Rust crates. rust-analyzer watches all files in
@@ -17,6 +20,8 @@ pub struct Crate {
17 pub(crate) root_module: PathBuf, 20 pub(crate) root_module: PathBuf,
18 pub(crate) edition: Edition, 21 pub(crate) edition: Edition,
19 pub(crate) deps: Vec<Dep>, 22 pub(crate) deps: Vec<Dep>,
23 pub(crate) atom_cfgs: FxHashSet<String>,
24 pub(crate) key_value_cfgs: FxHashMap<String, String>,
20} 25}
21 26
22#[derive(Clone, Copy, Debug, Deserialize)] 27#[derive(Clone, Copy, Debug, Deserialize)]
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 4fa32dc34..640a5ebd3 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod cargo_workspace; 3mod cargo_workspace;
2mod json_project; 4mod json_project;
3mod sysroot; 5mod sysroot;
@@ -7,8 +9,10 @@ use std::{
7 fs::File, 9 fs::File,
8 io::BufReader, 10 io::BufReader,
9 path::{Path, PathBuf}, 11 path::{Path, PathBuf},
12 process::Command,
10}; 13};
11 14
15use ra_cfg::CfgOptions;
12use ra_db::{CrateGraph, CrateId, Edition, FileId}; 16use ra_db::{CrateGraph, CrateId, Edition, FileId};
13use rustc_hash::FxHashMap; 17use rustc_hash::FxHashMap;
14use serde_json::from_reader; 18use serde_json::from_reader;
@@ -115,6 +119,7 @@ impl ProjectWorkspace {
115 119
116 pub fn to_crate_graph( 120 pub fn to_crate_graph(
117 &self, 121 &self,
122 default_cfg_options: &CfgOptions,
118 load: &mut dyn FnMut(&Path) -> Option<FileId>, 123 load: &mut dyn FnMut(&Path) -> Option<FileId>,
119 ) -> (CrateGraph, FxHashMap<CrateId, String>) { 124 ) -> (CrateGraph, FxHashMap<CrateId, String>) {
120 let mut crate_graph = CrateGraph::default(); 125 let mut crate_graph = CrateGraph::default();
@@ -129,7 +134,17 @@ impl ProjectWorkspace {
129 json_project::Edition::Edition2015 => Edition::Edition2015, 134 json_project::Edition::Edition2015 => Edition::Edition2015,
130 json_project::Edition::Edition2018 => Edition::Edition2018, 135 json_project::Edition::Edition2018 => Edition::Edition2018,
131 }; 136 };
132 crates.insert(crate_id, crate_graph.add_crate_root(file_id, edition)); 137 let mut cfg_options = default_cfg_options.clone();
138 for name in &krate.atom_cfgs {
139 cfg_options = cfg_options.atom(name.into());
140 }
141 for (key, value) in &krate.key_value_cfgs {
142 cfg_options = cfg_options.key_value(key.into(), value.into());
143 }
144 crates.insert(
145 crate_id,
146 crate_graph.add_crate_root(file_id, edition, cfg_options),
147 );
133 } 148 }
134 } 149 }
135 150
@@ -155,7 +170,10 @@ impl ProjectWorkspace {
155 let mut sysroot_crates = FxHashMap::default(); 170 let mut sysroot_crates = FxHashMap::default();
156 for krate in sysroot.crates() { 171 for krate in sysroot.crates() {
157 if let Some(file_id) = load(krate.root(&sysroot)) { 172 if let Some(file_id) = load(krate.root(&sysroot)) {
158 let crate_id = crate_graph.add_crate_root(file_id, Edition::Edition2018); 173 // Crates from sysroot have `cfg(test)` disabled
174 let cfg_options = default_cfg_options.clone().remove_atom(&"test".into());
175 let crate_id =
176 crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options);
159 sysroot_crates.insert(krate, crate_id); 177 sysroot_crates.insert(krate, crate_id);
160 names.insert(crate_id, krate.name(&sysroot).to_string()); 178 names.insert(crate_id, krate.name(&sysroot).to_string());
161 } 179 }
@@ -184,7 +202,11 @@ impl ProjectWorkspace {
184 let root = tgt.root(&cargo); 202 let root = tgt.root(&cargo);
185 if let Some(file_id) = load(root) { 203 if let Some(file_id) = load(root) {
186 let edition = pkg.edition(&cargo); 204 let edition = pkg.edition(&cargo);
187 let crate_id = crate_graph.add_crate_root(file_id, edition); 205 let cfg_options = default_cfg_options
206 .clone()
207 .features(pkg.features(&cargo).iter().map(Into::into));
208 let crate_id =
209 crate_graph.add_crate_root(file_id, edition, cfg_options);
188 names.insert(crate_id, pkg.name(&cargo).to_string()); 210 names.insert(crate_id, pkg.name(&cargo).to_string());
189 if tgt.kind(&cargo) == TargetKind::Lib { 211 if tgt.kind(&cargo) == TargetKind::Lib {
190 lib_tgt = Some(crate_id); 212 lib_tgt = Some(crate_id);
@@ -284,3 +306,32 @@ fn find_cargo_toml(path: &Path) -> Result<PathBuf> {
284 } 306 }
285 Err(format!("can't find Cargo.toml at {}", path.display()))? 307 Err(format!("can't find Cargo.toml at {}", path.display()))?
286} 308}
309
310pub fn get_rustc_cfg_options() -> CfgOptions {
311 let mut cfg_options = CfgOptions::default();
312
313 match (|| -> Result<_> {
314 // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here.
315 let output = Command::new("rustc").args(&["--print", "cfg", "-O"]).output()?;
316 if !output.status.success() {
317 Err("failed to get rustc cfgs")?;
318 }
319 Ok(String::from_utf8(output.stdout)?)
320 })() {
321 Ok(rustc_cfgs) => {
322 for line in rustc_cfgs.lines() {
323 match line.find('=') {
324 None => cfg_options = cfg_options.atom(line.into()),
325 Some(pos) => {
326 let key = &line[..pos];
327 let value = line[pos + 1..].trim_matches('"');
328 cfg_options = cfg_options.key_value(key.into(), value.into());
329 }
330 }
331 }
332 }
333 Err(e) => log::error!("failed to get rustc cfgs: {}", e),
334 }
335
336 cfg_options
337}
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index 0c27d4f4b..35d6df5cb 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{ 3use std::{
2 env, 4 env,
3 path::{Path, PathBuf}, 5 path::{Path, PathBuf},
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml
index 724c38e17..9bc85404a 100644
--- a/crates/ra_syntax/Cargo.toml
+++ b/crates/ra_syntax/Cargo.toml
@@ -12,6 +12,8 @@ itertools = "0.8.0"
12rowan = "0.6.1" 12rowan = "0.6.1"
13rustc_lexer = "0.1.0" 13rustc_lexer = "0.1.0"
14rustc-hash = "1.0.1" 14rustc-hash = "1.0.1"
15arrayvec = "0.4.10"
16once_cell = "1.2.0"
15 17
16# ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here 18# ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here
17# to reduce number of compilations 19# to reduce number of compilations
diff --git a/crates/ra_syntax/fuzz/fuzz_targets/parser.rs b/crates/ra_syntax/fuzz/fuzz_targets/parser.rs
index 76a8b08d0..7bc4ef30d 100644
--- a/crates/ra_syntax/fuzz/fuzz_targets/parser.rs
+++ b/crates/ra_syntax/fuzz/fuzz_targets/parser.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1#![no_main] 3#![no_main]
2use libfuzzer_sys::fuzz_target; 4use libfuzzer_sys::fuzz_target;
3use ra_syntax::fuzz::check_parser; 5use ra_syntax::fuzz::check_parser;
diff --git a/crates/ra_syntax/fuzz/fuzz_targets/reparse.rs b/crates/ra_syntax/fuzz/fuzz_targets/reparse.rs
index 45524d4c1..16598f5f1 100644
--- a/crates/ra_syntax/fuzz/fuzz_targets/reparse.rs
+++ b/crates/ra_syntax/fuzz/fuzz_targets/reparse.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1#![no_main] 3#![no_main]
2use libfuzzer_sys::fuzz_target; 4use libfuzzer_sys::fuzz_target;
3use ra_syntax::fuzz::CheckReparse; 5use ra_syntax::fuzz::CheckReparse;
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs
index 46680a08f..7cfea70f9 100644
--- a/crates/ra_syntax/src/algo.rs
+++ b/crates/ra_syntax/src/algo.rs
@@ -1,8 +1,9 @@
1pub mod visit; 1//! FIXME: write short doc here
2 2
3use std::ops::RangeInclusive; 3use std::ops::RangeInclusive;
4 4
5use itertools::Itertools; 5use itertools::Itertools;
6use ra_text_edit::TextEditBuilder;
6use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
7 8
8use crate::{ 9use crate::{
@@ -63,6 +64,18 @@ pub enum InsertPosition<T> {
63 After(T), 64 After(T),
64} 65}
65 66
67pub struct TreeDiff {
68 replacements: FxHashMap<SyntaxElement, SyntaxElement>,
69}
70
71impl TreeDiff {
72 pub fn into_text_edit(&self, builder: &mut TextEditBuilder) {
73 for (from, to) in self.replacements.iter() {
74 builder.replace(from.text_range(), to.to_string())
75 }
76 }
77}
78
66/// Finds minimal the diff, which, applied to `from`, will result in `to`. 79/// Finds minimal the diff, which, applied to `from`, will result in `to`.
67/// 80///
68/// Specifically, returns a map whose keys are descendants of `from` and values 81/// Specifically, returns a map whose keys are descendants of `from` and values
@@ -70,12 +83,12 @@ pub enum InsertPosition<T> {
70/// 83///
71/// A trivial solution is a singletom map `{ from: to }`, but this function 84/// A trivial solution is a singletom map `{ from: to }`, but this function
72/// tries to find a more fine-grained diff. 85/// tries to find a more fine-grained diff.
73pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> FxHashMap<SyntaxElement, SyntaxElement> { 86pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> TreeDiff {
74 let mut buf = FxHashMap::default(); 87 let mut buf = FxHashMap::default();
75 // FIXME: this is both horrible inefficient and gives larger than 88 // FIXME: this is both horrible inefficient and gives larger than
76 // necessary diff. I bet there's a cool algorithm to diff trees properly. 89 // necessary diff. I bet there's a cool algorithm to diff trees properly.
77 go(&mut buf, from.clone().into(), to.clone().into()); 90 go(&mut buf, from.clone().into(), to.clone().into());
78 return buf; 91 return TreeDiff { replacements: buf };
79 92
80 fn go( 93 fn go(
81 buf: &mut FxHashMap<SyntaxElement, SyntaxElement>, 94 buf: &mut FxHashMap<SyntaxElement, SyntaxElement>,
diff --git a/crates/ra_syntax/src/algo/visit.rs b/crates/ra_syntax/src/algo/visit.rs
deleted file mode 100644
index 87bd15cc0..000000000
--- a/crates/ra_syntax/src/algo/visit.rs
+++ /dev/null
@@ -1,110 +0,0 @@
1use crate::{AstNode, SyntaxNode};
2
3use std::marker::PhantomData;
4
5pub fn visitor<'a, T>() -> impl Visitor<'a, Output = T> {
6 EmptyVisitor { ph: PhantomData }
7}
8
9pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output = T, Ctx = C> {
10 EmptyVisitorCtx { ph: PhantomData, ctx }
11}
12
13pub trait Visitor<'a>: Sized {
14 type Output;
15 fn accept(self, node: &'a SyntaxNode) -> Option<Self::Output>;
16 fn visit<N, F>(self, f: F) -> Vis<Self, N, F>
17 where
18 N: AstNode + 'a,
19 F: FnOnce(N) -> Self::Output,
20 {
21 Vis { inner: self, f, ph: PhantomData }
22 }
23}
24
25pub trait VisitorCtx<'a>: Sized {
26 type Output;
27 type Ctx;
28 fn accept(self, node: &'a SyntaxNode) -> Result<Self::Output, Self::Ctx>;
29 fn visit<N, F>(self, f: F) -> VisCtx<Self, N, F>
30 where
31 N: AstNode + 'a,
32 F: FnOnce(N, Self::Ctx) -> Self::Output,
33 {
34 VisCtx { inner: self, f, ph: PhantomData }
35 }
36}
37
38#[derive(Debug)]
39struct EmptyVisitor<T> {
40 ph: PhantomData<fn() -> T>,
41}
42
43impl<'a, T> Visitor<'a> for EmptyVisitor<T> {
44 type Output = T;
45
46 fn accept(self, _node: &'a SyntaxNode) -> Option<T> {
47 None
48 }
49}
50
51#[derive(Debug)]
52struct EmptyVisitorCtx<T, C> {
53 ctx: C,
54 ph: PhantomData<fn() -> T>,
55}
56
57impl<'a, T, C> VisitorCtx<'a> for EmptyVisitorCtx<T, C> {
58 type Output = T;
59 type Ctx = C;
60
61 fn accept(self, _node: &'a SyntaxNode) -> Result<T, C> {
62 Err(self.ctx)
63 }
64}
65
66#[derive(Debug)]
67pub struct Vis<V, N, F> {
68 inner: V,
69 f: F,
70 ph: PhantomData<fn(N)>,
71}
72
73impl<'a, V, N, F> Visitor<'a> for Vis<V, N, F>
74where
75 V: Visitor<'a>,
76 N: AstNode + 'a,
77 F: FnOnce(N) -> <V as Visitor<'a>>::Output,
78{
79 type Output = <V as Visitor<'a>>::Output;
80
81 fn accept(self, node: &'a SyntaxNode) -> Option<Self::Output> {
82 let Vis { inner, f, .. } = self;
83 inner.accept(node).or_else(|| N::cast(node.clone()).map(f))
84 }
85}
86
87#[derive(Debug)]
88pub struct VisCtx<V, N, F> {
89 inner: V,
90 f: F,
91 ph: PhantomData<fn(N)>,
92}
93
94impl<'a, V, N, F> VisitorCtx<'a> for VisCtx<V, N, F>
95where
96 V: VisitorCtx<'a>,
97 N: AstNode + 'a,
98 F: FnOnce(N, <V as VisitorCtx<'a>>::Ctx) -> <V as VisitorCtx<'a>>::Output,
99{
100 type Output = <V as VisitorCtx<'a>>::Output;
101 type Ctx = <V as VisitorCtx<'a>>::Ctx;
102
103 fn accept(self, node: &'a SyntaxNode) -> Result<Self::Output, Self::Ctx> {
104 let VisCtx { inner, f, .. } = self;
105 inner.accept(node).or_else(|ctx| match N::cast(node.clone()) {
106 None => Err(ctx),
107 Some(node) => Ok(f(node, ctx)),
108 })
109 }
110}
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index f464d6534..1b2ce921a 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -5,6 +5,7 @@ mod traits;
5mod tokens; 5mod tokens;
6mod extensions; 6mod extensions;
7mod expr_extensions; 7mod expr_extensions;
8pub mod edit;
8pub mod make; 9pub mod make;
9 10
10use std::marker::PhantomData; 11use std::marker::PhantomData;
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs
new file mode 100644
index 000000000..03f3b5fbb
--- /dev/null
+++ b/crates/ra_syntax/src/ast/edit.rs
@@ -0,0 +1,271 @@
1//! This module contains functions for editing syntax trees. As the trees are
2//! immutable, all function here return a fresh copy of the tree, instead of
3//! doing an in-place modification.
4use std::{iter, ops::RangeInclusive};
5
6use arrayvec::ArrayVec;
7use rustc_hash::FxHashMap;
8
9use crate::{
10 algo,
11 ast::{
12 self,
13 make::{self, tokens},
14 AstNode, TypeBoundsOwner,
15 },
16 AstToken, Direction, InsertPosition, SmolStr, SyntaxElement,
17 SyntaxKind::{ATTR, COMMENT, WHITESPACE},
18 SyntaxNode, T,
19};
20
21impl ast::FnDef {
22 #[must_use]
23 pub fn with_body(&self, body: ast::Block) -> ast::FnDef {
24 let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
25 let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() {
26 old_body.syntax().clone().into()
27 } else if let Some(semi) = self.semicolon_token() {
28 to_insert.push(make::tokens::single_space().into());
29 semi.into()
30 } else {
31 to_insert.push(make::tokens::single_space().into());
32 to_insert.push(body.syntax().clone().into());
33 return insert_children(self, InsertPosition::Last, to_insert.into_iter());
34 };
35 to_insert.push(body.syntax().clone().into());
36 let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi);
37 replace_children(self, replace_range, to_insert.into_iter())
38 }
39}
40
41impl ast::ItemList {
42 #[must_use]
43 pub fn append_items(&self, items: impl Iterator<Item = ast::ImplItem>) -> ast::ItemList {
44 let mut res = self.clone();
45 if !self.syntax().text().contains_char('\n') {
46 res = res.make_multiline();
47 }
48 items.for_each(|it| res = res.append_item(it));
49 res
50 }
51
52 #[must_use]
53 pub fn append_item(&self, item: ast::ImplItem) -> ast::ItemList {
54 let (indent, position) = match self.impl_items().last() {
55 Some(it) => (
56 leading_indent(it.syntax()).unwrap_or_default().to_string(),
57 InsertPosition::After(it.syntax().clone().into()),
58 ),
59 None => match self.l_curly() {
60 Some(it) => (
61 " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
62 InsertPosition::After(it),
63 ),
64 None => return self.clone(),
65 },
66 };
67 let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
68 let to_insert: ArrayVec<[SyntaxElement; 2]> =
69 [ws.ws().into(), item.syntax().clone().into()].into();
70 insert_children(self, position, to_insert.into_iter())
71 }
72
73 fn l_curly(&self) -> Option<SyntaxElement> {
74 self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
75 }
76
77 fn make_multiline(&self) -> ast::ItemList {
78 let l_curly = match self.syntax().children_with_tokens().find(|it| it.kind() == T!['{']) {
79 Some(it) => it,
80 None => return self.clone(),
81 };
82 let sibling = match l_curly.next_sibling_or_token() {
83 Some(it) => it,
84 None => return self.clone(),
85 };
86 let existing_ws = match sibling.as_token() {
87 None => None,
88 Some(tok) if tok.kind() != WHITESPACE => None,
89 Some(ws) => {
90 if ws.text().contains('\n') {
91 return self.clone();
92 }
93 Some(ws.clone())
94 }
95 };
96
97 let indent = leading_indent(self.syntax()).unwrap_or("".into());
98 let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
99 let to_insert = iter::once(ws.ws().into());
100 match existing_ws {
101 None => insert_children(self, InsertPosition::After(l_curly), to_insert),
102 Some(ws) => {
103 replace_children(self, RangeInclusive::new(ws.clone().into(), ws.into()), to_insert)
104 }
105 }
106 }
107}
108
109impl ast::RecordFieldList {
110 #[must_use]
111 pub fn append_field(&self, field: &ast::RecordField) -> ast::RecordFieldList {
112 self.insert_field(InsertPosition::Last, field)
113 }
114
115 #[must_use]
116 pub fn insert_field(
117 &self,
118 position: InsertPosition<&'_ ast::RecordField>,
119 field: &ast::RecordField,
120 ) -> ast::RecordFieldList {
121 let is_multiline = self.syntax().text().contains_char('\n');
122 let ws;
123 let space = if is_multiline {
124 ws = tokens::WsBuilder::new(&format!(
125 "\n{} ",
126 leading_indent(self.syntax()).unwrap_or("".into())
127 ));
128 ws.ws()
129 } else {
130 tokens::single_space()
131 };
132
133 let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new();
134 to_insert.push(space.into());
135 to_insert.push(field.syntax().clone().into());
136 to_insert.push(tokens::comma().into());
137
138 macro_rules! after_l_curly {
139 () => {{
140 let anchor = match self.l_curly() {
141 Some(it) => it,
142 None => return self.clone(),
143 };
144 InsertPosition::After(anchor)
145 }};
146 }
147
148 macro_rules! after_field {
149 ($anchor:expr) => {
150 if let Some(comma) = $anchor
151 .syntax()
152 .siblings_with_tokens(Direction::Next)
153 .find(|it| it.kind() == T![,])
154 {
155 InsertPosition::After(comma)
156 } else {
157 to_insert.insert(0, tokens::comma().into());
158 InsertPosition::After($anchor.syntax().clone().into())
159 }
160 };
161 };
162
163 let position = match position {
164 InsertPosition::First => after_l_curly!(),
165 InsertPosition::Last => {
166 if !is_multiline {
167 // don't insert comma before curly
168 to_insert.pop();
169 }
170 match self.fields().last() {
171 Some(it) => after_field!(it),
172 None => after_l_curly!(),
173 }
174 }
175 InsertPosition::Before(anchor) => {
176 InsertPosition::Before(anchor.syntax().clone().into())
177 }
178 InsertPosition::After(anchor) => after_field!(anchor),
179 };
180
181 insert_children(self, position, to_insert.iter().cloned())
182 }
183
184 fn l_curly(&self) -> Option<SyntaxElement> {
185 self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
186 }
187}
188
189impl ast::TypeParam {
190 #[must_use]
191 pub fn remove_bounds(&self) -> ast::TypeParam {
192 let colon = match self.colon_token() {
193 Some(it) => it,
194 None => return self.clone(),
195 };
196 let end = match self.type_bound_list() {
197 Some(it) => it.syntax().clone().into(),
198 None => colon.clone().into(),
199 };
200 replace_children(self, RangeInclusive::new(colon.into(), end), iter::empty())
201 }
202}
203
204#[must_use]
205pub fn strip_attrs_and_docs<N: ast::AttrsOwner>(node: &N) -> N {
206 N::cast(strip_attrs_and_docs_inner(node.syntax().clone())).unwrap()
207}
208
209fn strip_attrs_and_docs_inner(mut node: SyntaxNode) -> SyntaxNode {
210 while let Some(start) =
211 node.children_with_tokens().find(|it| it.kind() == ATTR || it.kind() == COMMENT)
212 {
213 let end = match &start.next_sibling_or_token() {
214 Some(el) if el.kind() == WHITESPACE => el.clone(),
215 Some(_) | None => start.clone(),
216 };
217 node = algo::replace_children(&node, RangeInclusive::new(start, end), &mut iter::empty());
218 }
219 node
220}
221
222#[must_use]
223pub fn replace_descendants<N: AstNode, D: AstNode>(
224 parent: &N,
225 replacement_map: impl Iterator<Item = (D, D)>,
226) -> N {
227 let map = replacement_map
228 .map(|(from, to)| (from.syntax().clone().into(), to.syntax().clone().into()))
229 .collect::<FxHashMap<_, _>>();
230 let new_syntax = algo::replace_descendants(parent.syntax(), &map);
231 N::cast(new_syntax).unwrap()
232}
233
234// Note this is copy-pasted from fmt. It seems like fmt should be a separate
235// crate, but basic tree building should be this crate. However, tree building
236// might want to call into fmt...
237fn leading_indent(node: &SyntaxNode) -> Option<SmolStr> {
238 let prev_tokens = std::iter::successors(node.first_token(), |token| token.prev_token());
239 for token in prev_tokens {
240 if let Some(ws) = ast::Whitespace::cast(token.clone()) {
241 let ws_text = ws.text();
242 if let Some(pos) = ws_text.rfind('\n') {
243 return Some(ws_text[pos + 1..].into());
244 }
245 }
246 if token.text().contains('\n') {
247 break;
248 }
249 }
250 None
251}
252
253#[must_use]
254fn insert_children<N: AstNode>(
255 parent: &N,
256 position: InsertPosition<SyntaxElement>,
257 mut to_insert: impl Iterator<Item = SyntaxElement>,
258) -> N {
259 let new_syntax = algo::insert_children(parent.syntax(), position, &mut to_insert);
260 N::cast(new_syntax).unwrap()
261}
262
263#[must_use]
264fn replace_children<N: AstNode>(
265 parent: &N,
266 to_replace: RangeInclusive<SyntaxElement>,
267 mut to_insert: impl Iterator<Item = SyntaxElement>,
268) -> N {
269 let new_syntax = algo::replace_children(parent.syntax(), to_replace, &mut to_insert);
270 N::cast(new_syntax).unwrap()
271}
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 5f7e9f5b1..cefc00402 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -1,10 +1,8 @@
1//! Various extension methods to ast Nodes, which are hard to code-generate. 1//! Various extension methods to ast Nodes, which are hard to code-generate.
2//! Extensions for various expressions live in a sibling `expr_extensions` module. 2//! Extensions for various expressions live in a sibling `expr_extensions` module.
3 3
4use itertools::Itertools;
5
6use crate::{ 4use crate::{
7 ast::{self, child_opt, children, AstNode, SyntaxNode}, 5 ast::{self, child_opt, children, AstChildren, AstNode, AttrInput, SyntaxNode},
8 SmolStr, SyntaxElement, 6 SmolStr, SyntaxElement,
9 SyntaxKind::*, 7 SyntaxKind::*,
10 SyntaxToken, T, 8 SyntaxToken, T,
@@ -21,6 +19,16 @@ impl ast::NameRef {
21 pub fn text(&self) -> &SmolStr { 19 pub fn text(&self) -> &SmolStr {
22 text_of_first_token(self.syntax()) 20 text_of_first_token(self.syntax())
23 } 21 }
22
23 pub fn as_tuple_field(&self) -> Option<usize> {
24 self.syntax().children_with_tokens().find_map(|c| {
25 if c.kind() == SyntaxKind::INT_NUMBER {
26 c.as_token().and_then(|tok| tok.text().as_str().parse().ok())
27 } else {
28 None
29 }
30 })
31 }
24} 32}
25 33
26fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { 34fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {
@@ -28,62 +36,37 @@ fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {
28} 36}
29 37
30impl ast::Attr { 38impl ast::Attr {
31 pub fn is_inner(&self) -> bool { 39 pub fn as_simple_atom(&self) -> Option<SmolStr> {
32 let tt = match self.value() { 40 match self.input() {
33 None => return false, 41 None => self.simple_name(),
34 Some(tt) => tt, 42 Some(_) => None,
35 };
36
37 let prev = match tt.syntax().prev_sibling() {
38 None => return false,
39 Some(prev) => prev,
40 };
41
42 prev.kind() == T![!]
43 }
44
45 pub fn as_atom(&self) -> Option<SmolStr> {
46 let tt = self.value()?;
47 let (_bra, attr, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
48 if attr.kind() == IDENT {
49 Some(attr.as_token()?.text().clone())
50 } else {
51 None
52 } 43 }
53 } 44 }
54 45
55 pub fn as_call(&self) -> Option<(SmolStr, ast::TokenTree)> { 46 pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
56 let tt = self.value()?; 47 match self.input() {
57 let (_bra, attr, args, _ket) = tt.syntax().children_with_tokens().collect_tuple()?; 48 Some(AttrInput::TokenTree(tt)) => Some((self.simple_name()?, tt)),
58 let args = ast::TokenTree::cast(args.as_node()?.clone())?; 49 _ => None,
59 if attr.kind() == IDENT {
60 Some((attr.as_token()?.text().clone(), args))
61 } else {
62 None
63 } 50 }
64 } 51 }
65 52
66 pub fn as_named(&self) -> Option<SmolStr> { 53 pub fn as_simple_key_value(&self) -> Option<(SmolStr, SmolStr)> {
67 let tt = self.value()?; 54 match self.input() {
68 let attr = tt.syntax().children_with_tokens().nth(1)?; 55 Some(AttrInput::Literal(lit)) => {
69 if attr.kind() == IDENT { 56 let key = self.simple_name()?;
70 Some(attr.as_token()?.text().clone()) 57 // FIXME: escape? raw string?
71 } else { 58 let value = lit.syntax().first_token()?.text().trim_matches('"').into();
72 None 59 Some((key, value))
60 }
61 _ => None,
73 } 62 }
74 } 63 }
75 64
76 pub fn as_key_value(&self) -> Option<(SmolStr, SmolStr)> { 65 pub fn simple_name(&self) -> Option<SmolStr> {
77 let tt = self.value()?; 66 let path = self.path()?;
78 let tt_node = tt.syntax(); 67 match (path.segment(), path.qualifier()) {
79 let attr = tt_node.children_with_tokens().nth(1)?; 68 (Some(segment), None) => Some(segment.syntax().first_token()?.text().clone()),
80 if attr.kind() == IDENT { 69 _ => None,
81 let key = attr.as_token()?.text().clone();
82 let val_node = tt_node.children_with_tokens().find(|t| t.kind() == STRING)?;
83 let val = val_node.as_token()?.text().trim_start_matches('"').trim_end_matches('"');
84 Some((key, SmolStr::new(val)))
85 } else {
86 None
87 } 70 }
88 } 71 }
89} 72}
@@ -193,6 +176,16 @@ impl ast::ImplBlock {
193 } 176 }
194} 177}
195 178
179impl ast::AttrsOwner for ast::ImplItem {
180 fn attrs(&self) -> AstChildren<ast::Attr> {
181 match self {
182 ast::ImplItem::FnDef(it) => it.attrs(),
183 ast::ImplItem::TypeAliasDef(it) => it.attrs(),
184 ast::ImplItem::ConstDef(it) => it.attrs(),
185 }
186 }
187}
188
196#[derive(Debug, Clone, PartialEq, Eq)] 189#[derive(Debug, Clone, PartialEq, Eq)]
197pub enum StructKind { 190pub enum StructKind {
198 Tuple(ast::TupleFieldDefList), 191 Tuple(ast::TupleFieldDefList),
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index dc1f8c82c..34b22c3e2 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1,4 +1,4 @@
1// Generated file, do not edit by hand, see `crate/ra_tools/src/codegen` 1//! Generated file, do not edit by hand, see `crate/ra_tools/src/codegen`
2 2
3use crate::{ 3use crate::{
4 ast::{self, AstChildren, AstNode}, 4 ast::{self, AstChildren, AstNode},
@@ -166,11 +166,52 @@ impl AstNode for Attr {
166 } 166 }
167} 167}
168impl Attr { 168impl Attr {
169 pub fn value(&self) -> Option<TokenTree> { 169 pub fn path(&self) -> Option<Path> {
170 AstChildren::new(&self.syntax).next()
171 }
172 pub fn input(&self) -> Option<AttrInput> {
170 AstChildren::new(&self.syntax).next() 173 AstChildren::new(&self.syntax).next()
171 } 174 }
172} 175}
173#[derive(Debug, Clone, PartialEq, Eq, Hash)] 176#[derive(Debug, Clone, PartialEq, Eq, Hash)]
177pub enum AttrInput {
178 Literal(Literal),
179 TokenTree(TokenTree),
180}
181impl From<Literal> for AttrInput {
182 fn from(node: Literal) -> AttrInput {
183 AttrInput::Literal(node)
184 }
185}
186impl From<TokenTree> for AttrInput {
187 fn from(node: TokenTree) -> AttrInput {
188 AttrInput::TokenTree(node)
189 }
190}
191impl AstNode for AttrInput {
192 fn can_cast(kind: SyntaxKind) -> bool {
193 match kind {
194 LITERAL | TOKEN_TREE => true,
195 _ => false,
196 }
197 }
198 fn cast(syntax: SyntaxNode) -> Option<Self> {
199 let res = match syntax.kind() {
200 LITERAL => AttrInput::Literal(Literal { syntax }),
201 TOKEN_TREE => AttrInput::TokenTree(TokenTree { syntax }),
202 _ => return None,
203 };
204 Some(res)
205 }
206 fn syntax(&self) -> &SyntaxNode {
207 match self {
208 AttrInput::Literal(it) => &it.syntax,
209 AttrInput::TokenTree(it) => &it.syntax,
210 }
211 }
212}
213impl AttrInput {}
214#[derive(Debug, Clone, PartialEq, Eq, Hash)]
174pub struct AwaitExpr { 215pub struct AwaitExpr {
175 pub(crate) syntax: SyntaxNode, 216 pub(crate) syntax: SyntaxNode,
176} 217}
@@ -1921,6 +1962,7 @@ impl AstNode for ModuleItem {
1921 } 1962 }
1922 } 1963 }
1923} 1964}
1965impl ast::AttrsOwner for ModuleItem {}
1924impl ModuleItem {} 1966impl ModuleItem {}
1925#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1967#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1926pub struct Name { 1968pub struct Name {
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index c06c62b3b..287a40bee 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -133,3 +133,51 @@ fn ast_from_text<N: AstNode>(text: &str) -> N {
133 let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); 133 let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap();
134 res 134 res
135} 135}
136
137pub mod tokens {
138 use crate::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T};
139 use once_cell::sync::Lazy;
140
141 static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;"));
142
143 pub fn comma() -> SyntaxToken {
144 SOURCE_FILE
145 .tree()
146 .syntax()
147 .descendants_with_tokens()
148 .filter_map(|it| it.into_token())
149 .find(|it| it.kind() == T![,])
150 .unwrap()
151 }
152
153 pub fn single_space() -> SyntaxToken {
154 SOURCE_FILE
155 .tree()
156 .syntax()
157 .descendants_with_tokens()
158 .filter_map(|it| it.into_token())
159 .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ")
160 .unwrap()
161 }
162
163 pub fn single_newline() -> SyntaxToken {
164 SOURCE_FILE
165 .tree()
166 .syntax()
167 .descendants_with_tokens()
168 .filter_map(|it| it.into_token())
169 .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n")
170 .unwrap()
171 }
172
173 pub struct WsBuilder(SourceFile);
174
175 impl WsBuilder {
176 pub fn new(text: &str) -> WsBuilder {
177 WsBuilder(SourceFile::parse(text).ok().unwrap())
178 }
179 pub fn ws(&self) -> SyntaxToken {
180 self.0.syntax().first_child_or_token().unwrap().into_token().unwrap()
181 }
182 }
183}
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs
index c3e676d4c..f275a4955 100644
--- a/crates/ra_syntax/src/ast/traits.rs
+++ b/crates/ra_syntax/src/ast/traits.rs
@@ -99,7 +99,7 @@ pub trait AttrsOwner: AstNode {
99 children(self) 99 children(self)
100 } 100 }
101 fn has_atom_attr(&self, atom: &str) -> bool { 101 fn has_atom_attr(&self, atom: &str) -> bool {
102 self.attrs().filter_map(|x| x.as_atom()).any(|x| x == atom) 102 self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)
103 } 103 }
104} 104}
105 105
diff --git a/crates/ra_syntax/src/fuzz.rs b/crates/ra_syntax/src/fuzz.rs
index 698a624ec..7012df7f0 100644
--- a/crates/ra_syntax/src/fuzz.rs
+++ b/crates/ra_syntax/src/fuzz.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{validation, AstNode, SourceFile, TextRange, TextUnit}; 3use crate::{validation, AstNode, SourceFile, TextRange, TextUnit};
2use ra_text_edit::AtomTextEdit; 4use ra_text_edit::AtomTextEdit;
3use std::str::{self, FromStr}; 5use std::str::{self, FromStr};
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 5f395501a..25e6f64ce 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -1,5 +1,5 @@
1// Stores definitions which must be used in multiple places 1// Stores definitions which must be used in multiple places
2// See `cargo gen-syntax` (defined in crates/tools/src/main.rs) 2// See `cargo gen-syntax` (defined in crates/ra_tools/src/main.rs)
3Grammar( 3Grammar(
4 punct: [ 4 punct: [
5 (";", "SEMI"), 5 (";", "SEMI"),
@@ -397,7 +397,8 @@ Grammar(
397 ), 397 ),
398 "ModuleItem": ( 398 "ModuleItem": (
399 enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock", 399 enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
400 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ] 400 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ],
401 traits: ["AttrsOwner"]
401 ), 402 ),
402 "ImplItem": ( 403 "ImplItem": (
403 enum: ["FnDef", "TypeAliasDef", "ConstDef"] 404 enum: ["FnDef", "TypeAliasDef", "ConstDef"]
@@ -576,7 +577,8 @@ Grammar(
576 traits: [ "NameOwner", "AttrsOwner","DocCommentsOwner" ], 577 traits: [ "NameOwner", "AttrsOwner","DocCommentsOwner" ],
577 options: [ "TokenTree", "Path" ], 578 options: [ "TokenTree", "Path" ],
578 ), 579 ),
579 "Attr": ( options: [ ["value", "TokenTree"] ] ), 580 "AttrInput": ( enum: [ "Literal", "TokenTree" ] ),
581 "Attr": ( options: [ "Path", [ "input", "AttrInput" ] ] ),
580 "TokenTree": (), 582 "TokenTree": (),
581 "TypeParamList": ( 583 "TypeParamList": (
582 collections: [ 584 collections: [
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index edb6076bb..c315ba552 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -160,6 +160,17 @@ impl SourceFile {
160 } 160 }
161} 161}
162 162
163#[macro_export]
164macro_rules! match_ast {
165 (match $node:ident {
166 $( ast::$ast:ident($it:ident) => $res:block, )*
167 _ => $catch_all:expr,
168 }) => {{
169 $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )*
170 { $catch_all }
171 }};
172}
173
163/// This test does not assert anything and instead just shows off the crate's 174/// This test does not assert anything and instead just shows off the crate's
164/// API. 175/// API.
165#[test] 176#[test]
@@ -294,7 +305,7 @@ fn api_walkthrough() {
294 // To recursively process the tree, there are three approaches: 305 // To recursively process the tree, there are three approaches:
295 // 1. explicitly call getter methods on AST nodes. 306 // 1. explicitly call getter methods on AST nodes.
296 // 2. use descendants and `AstNode::cast`. 307 // 2. use descendants and `AstNode::cast`.
297 // 3. use descendants and the visitor. 308 // 3. use descendants and `match_ast!`.
298 // 309 //
299 // Here's how the first one looks like: 310 // Here's how the first one looks like:
300 let exprs_cast: Vec<String> = file 311 let exprs_cast: Vec<String> = file
@@ -304,17 +315,17 @@ fn api_walkthrough() {
304 .map(|expr| expr.syntax().text().to_string()) 315 .map(|expr| expr.syntax().text().to_string())
305 .collect(); 316 .collect();
306 317
307 // An alternative is to use a visitor. The visitor does not do traversal 318 // An alternative is to use a macro.
308 // automatically (so it's more akin to a generic lambda) and is constructed
309 // from closures. This seems more flexible than a single generated visitor
310 // trait.
311 use algo::visit::{visitor, Visitor};
312 let mut exprs_visit = Vec::new(); 319 let mut exprs_visit = Vec::new();
313 for node in file.syntax().descendants() { 320 for node in file.syntax().descendants() {
314 if let Some(result) = 321 match_ast! {
315 visitor().visit::<ast::Expr, _>(|expr| expr.syntax().text().to_string()).accept(&node) 322 match node {
316 { 323 ast::Expr(it) => {
317 exprs_visit.push(result); 324 let res = it.syntax().text().to_string();
325 exprs_visit.push(res);
326 },
327 _ => (),
328 }
318 } 329 }
319 } 330 }
320 assert_eq!(exprs_cast, exprs_visit); 331 assert_eq!(exprs_cast, exprs_visit);
diff --git a/crates/ra_syntax/src/parsing/lexer.rs b/crates/ra_syntax/src/parsing/lexer.rs
index bdb01d40b..6d839208d 100644
--- a/crates/ra_syntax/src/parsing/lexer.rs
+++ b/crates/ra_syntax/src/parsing/lexer.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{ 3use crate::{
2 SyntaxKind::{self, *}, 4 SyntaxKind::{self, *},
3 TextUnit, 5 TextUnit,
diff --git a/crates/ra_syntax/src/parsing/text_token_source.rs b/crates/ra_syntax/src/parsing/text_token_source.rs
index 64cb20ae8..e793f93a4 100644
--- a/crates/ra_syntax/src/parsing/text_token_source.rs
+++ b/crates/ra_syntax/src/parsing/text_token_source.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use ra_parser::Token as PToken; 3use ra_parser::Token as PToken;
2use ra_parser::TokenSource; 4use ra_parser::TokenSource;
3 5
diff --git a/crates/ra_syntax/src/parsing/text_tree_sink.rs b/crates/ra_syntax/src/parsing/text_tree_sink.rs
index be6e51780..142164316 100644
--- a/crates/ra_syntax/src/parsing/text_tree_sink.rs
+++ b/crates/ra_syntax/src/parsing/text_tree_sink.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::mem; 3use std::mem;
2 4
3use ra_parser::{ParseError, TreeSink}; 5use ra_parser::{ParseError, TreeSink};
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index 992034ef0..31167cada 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{iter::successors, marker::PhantomData}; 3use std::{iter::successors, marker::PhantomData};
2 4
3use crate::{AstNode, SyntaxKind, SyntaxNode, TextRange}; 5use crate::{AstNode, SyntaxKind, SyntaxNode, TextRange};
diff --git a/crates/ra_syntax/src/syntax_error.rs b/crates/ra_syntax/src/syntax_error.rs
index 5aefec768..d6eca2ad7 100644
--- a/crates/ra_syntax/src/syntax_error.rs
+++ b/crates/ra_syntax/src/syntax_error.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::fmt; 3use std::fmt;
2 4
3use ra_parser::ParseError; 5use ra_parser::ParseError;
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index 16824f3c4..ab4f15908 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -1,10 +1,11 @@
1//! FIXME: write short doc here
2
1mod block; 3mod block;
2 4
3use rustc_lexer::unescape; 5use rustc_lexer::unescape;
4 6
5use crate::{ 7use crate::{
6 algo::visit::{visitor_ctx, VisitorCtx}, 8 ast, match_ast, AstNode, SyntaxError, SyntaxErrorKind,
7 ast, AstNode, SyntaxError, SyntaxErrorKind,
8 SyntaxKind::{BYTE, BYTE_STRING, CHAR, INT_NUMBER, STRING}, 9 SyntaxKind::{BYTE, BYTE_STRING, CHAR, INT_NUMBER, STRING},
9 SyntaxNode, SyntaxToken, TextUnit, T, 10 SyntaxNode, SyntaxToken, TextUnit, T,
10}; 11};
@@ -95,12 +96,15 @@ impl From<rustc_lexer::unescape::EscapeError> for SyntaxErrorKind {
95pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { 96pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
96 let mut errors = Vec::new(); 97 let mut errors = Vec::new();
97 for node in root.descendants() { 98 for node in root.descendants() {
98 let _ = visitor_ctx(&mut errors) 99 match_ast! {
99 .visit::<ast::Literal, _>(validate_literal) 100 match node {
100 .visit::<ast::BlockExpr, _>(block::validate_block_expr) 101 ast::Literal(it) => { validate_literal(it, &mut errors) },
101 .visit::<ast::FieldExpr, _>(|it, errors| validate_numeric_name(it.name_ref(), errors)) 102 ast::BlockExpr(it) => { block::validate_block_expr(it, &mut errors) },
102 .visit::<ast::RecordField, _>(|it, errors| validate_numeric_name(it.name_ref(), errors)) 103 ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) },
103 .accept(&node); 104 ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) },
105 _ => (),
106 }
107 }
104 } 108 }
105 errors 109 errors
106} 110}
diff --git a/crates/ra_syntax/src/validation/block.rs b/crates/ra_syntax/src/validation/block.rs
index 3c9e96eb3..c85bbc1f4 100644
--- a/crates/ra_syntax/src/validation/block.rs
+++ b/crates/ra_syntax/src/validation/block.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{ 3use crate::{
2 ast::{self, AstNode, AttrsOwner}, 4 ast::{self, AstNode, AttrsOwner},
3 SyntaxError, 5 SyntaxError,
diff --git a/crates/ra_syntax/test_data/parser/err/0005_attribute_recover.txt b/crates/ra_syntax/test_data/parser/err/0005_attribute_recover.txt
index 378b92834..7c1a23170 100644
--- a/crates/ra_syntax/test_data/parser/err/0005_attribute_recover.txt
+++ b/crates/ra_syntax/test_data/parser/err/0005_attribute_recover.txt
@@ -2,20 +2,22 @@ SOURCE_FILE@[0; 54)
2 FN_DEF@[0; 31) 2 FN_DEF@[0; 31)
3 ATTR@[0; 18) 3 ATTR@[0; 18)
4 POUND@[0; 1) "#" 4 POUND@[0; 1) "#"
5 TOKEN_TREE@[1; 18) 5 L_BRACK@[1; 2) "["
6 L_BRACK@[1; 2) "[" 6 PATH@[2; 5)
7 IDENT@[2; 5) "foo" 7 PATH_SEGMENT@[2; 5)
8 TOKEN_TREE@[5; 17) 8 NAME_REF@[2; 5)
9 L_PAREN@[5; 6) "(" 9 IDENT@[2; 5) "foo"
10 IDENT@[6; 9) "foo" 10 TOKEN_TREE@[5; 17)
11 COMMA@[9; 10) "," 11 L_PAREN@[5; 6) "("
12 WHITESPACE@[10; 11) " " 12 IDENT@[6; 9) "foo"
13 PLUS@[11; 12) "+" 13 COMMA@[9; 10) ","
14 COMMA@[12; 13) "," 14 WHITESPACE@[10; 11) " "
15 WHITESPACE@[13; 14) " " 15 PLUS@[11; 12) "+"
16 INT_NUMBER@[14; 16) "92" 16 COMMA@[12; 13) ","
17 R_PAREN@[16; 17) ")" 17 WHITESPACE@[13; 14) " "
18 R_BRACK@[17; 18) "]" 18 INT_NUMBER@[14; 16) "92"
19 R_PAREN@[16; 17) ")"
20 R_BRACK@[17; 18) "]"
19 WHITESPACE@[18; 19) "\n" 21 WHITESPACE@[18; 19) "\n"
20 FN_KW@[19; 21) "fn" 22 FN_KW@[19; 21) "fn"
21 WHITESPACE@[21; 22) " " 23 WHITESPACE@[21; 22) " "
@@ -33,24 +35,26 @@ SOURCE_FILE@[0; 54)
33 WHITESPACE@[31; 34) "\n\n\n" 35 WHITESPACE@[31; 34) "\n\n\n"
34 ATTR@[34; 53) 36 ATTR@[34; 53)
35 POUND@[34; 35) "#" 37 POUND@[34; 35) "#"
36 TOKEN_TREE@[35; 53) 38 L_BRACK@[35; 36) "["
37 L_BRACK@[35; 36) "[" 39 PATH@[36; 39)
38 IDENT@[36; 39) "foo" 40 PATH_SEGMENT@[36; 39)
39 TOKEN_TREE@[39; 53) 41 NAME_REF@[36; 39)
40 L_PAREN@[39; 40) "(" 42 IDENT@[36; 39) "foo"
41 WHITESPACE@[40; 41) "\n" 43 TOKEN_TREE@[39; 53)
42 FN_KW@[41; 43) "fn" 44 L_PAREN@[39; 40) "("
43 WHITESPACE@[43; 44) " " 45 WHITESPACE@[40; 41) "\n"
44 IDENT@[44; 47) "foo" 46 FN_KW@[41; 43) "fn"
45 TOKEN_TREE@[47; 49) 47 WHITESPACE@[43; 44) " "
46 L_PAREN@[47; 48) "(" 48 IDENT@[44; 47) "foo"
47 R_PAREN@[48; 49) ")" 49 TOKEN_TREE@[47; 49)
48 WHITESPACE@[49; 50) " " 50 L_PAREN@[47; 48) "("
49 TOKEN_TREE@[50; 53) 51 R_PAREN@[48; 49) ")"
50 L_CURLY@[50; 51) "{" 52 WHITESPACE@[49; 50) " "
51 WHITESPACE@[51; 52) "\n" 53 TOKEN_TREE@[50; 53)
52 R_CURLY@[52; 53) "}" 54 L_CURLY@[50; 51) "{"
55 WHITESPACE@[51; 52) "\n"
56 R_CURLY@[52; 53) "}"
53 WHITESPACE@[53; 54) "\n" 57 WHITESPACE@[53; 54) "\n"
54error 53: expected R_PAREN 58error 53: expected R_PAREN
55error 53: expected R_BRACK 59error 53: expected `]`
56error 53: expected an item 60error 53: expected an item
diff --git a/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt b/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt
index 73d322c48..c5be73a5a 100644
--- a/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt
+++ b/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt
@@ -60,10 +60,12 @@ SOURCE_FILE@[0; 349)
60 FN_DEF@[95; 348) 60 FN_DEF@[95; 348)
61 ATTR@[95; 102) 61 ATTR@[95; 102)
62 POUND@[95; 96) "#" 62 POUND@[95; 96) "#"
63 TOKEN_TREE@[96; 102) 63 L_BRACK@[96; 97) "["
64 L_BRACK@[96; 97) "[" 64 PATH@[97; 101)
65 IDENT@[97; 101) "test" 65 PATH_SEGMENT@[97; 101)
66 R_BRACK@[101; 102) "]" 66 NAME_REF@[97; 101)
67 IDENT@[97; 101) "test"
68 R_BRACK@[101; 102) "]"
67 WHITESPACE@[102; 103) "\n" 69 WHITESPACE@[102; 103) "\n"
68 FN_KW@[103; 105) "fn" 70 FN_KW@[103; 105) "fn"
69 WHITESPACE@[105; 106) " " 71 WHITESPACE@[105; 106) " "
diff --git a/crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.txt b/crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.txt
index f67325b76..522a0d0e0 100644
--- a/crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/err/0031_block_inner_attrs.txt
@@ -28,14 +28,16 @@ SOURCE_FILE@[0; 350)
28 ATTR@[39; 83) 28 ATTR@[39; 83)
29 POUND@[39; 40) "#" 29 POUND@[39; 40) "#"
30 EXCL@[40; 41) "!" 30 EXCL@[40; 41) "!"
31 TOKEN_TREE@[41; 83) 31 L_BRACK@[41; 42) "["
32 L_BRACK@[41; 42) "[" 32 PATH@[42; 45)
33 IDENT@[42; 45) "doc" 33 PATH_SEGMENT@[42; 45)
34 TOKEN_TREE@[45; 82) 34 NAME_REF@[42; 45)
35 L_PAREN@[45; 46) "(" 35 IDENT@[42; 45) "doc"
36 STRING@[46; 81) "\"Inner attributes not ..." 36 TOKEN_TREE@[45; 82)
37 R_PAREN@[81; 82) ")" 37 L_PAREN@[45; 46) "("
38 R_BRACK@[82; 83) "]" 38 STRING@[46; 81) "\"Inner attributes not ..."
39 R_PAREN@[81; 82) ")"
40 R_BRACK@[82; 83) "]"
39 WHITESPACE@[83; 92) "\n " 41 WHITESPACE@[83; 92) "\n "
40 COMMENT@[92; 122) "//! Nor are ModuleDoc ..." 42 COMMENT@[92; 122) "//! Nor are ModuleDoc ..."
41 WHITESPACE@[122; 127) "\n " 43 WHITESPACE@[122; 127) "\n "
@@ -57,26 +59,30 @@ SOURCE_FILE@[0; 350)
57 ATTR@[152; 171) 59 ATTR@[152; 171)
58 POUND@[152; 153) "#" 60 POUND@[152; 153) "#"
59 EXCL@[153; 154) "!" 61 EXCL@[153; 154) "!"
60 TOKEN_TREE@[154; 171) 62 L_BRACK@[154; 155) "["
61 L_BRACK@[154; 155) "[" 63 PATH@[155; 158)
62 IDENT@[155; 158) "doc" 64 PATH_SEGMENT@[155; 158)
63 TOKEN_TREE@[158; 170) 65 NAME_REF@[155; 158)
64 L_PAREN@[158; 159) "(" 66 IDENT@[155; 158) "doc"
65 STRING@[159; 169) "\"Nor here\"" 67 TOKEN_TREE@[158; 170)
66 R_PAREN@[169; 170) ")" 68 L_PAREN@[158; 159) "("
67 R_BRACK@[170; 171) "]" 69 STRING@[159; 169) "\"Nor here\""
70 R_PAREN@[169; 170) ")"
71 R_BRACK@[170; 171) "]"
68 WHITESPACE@[171; 180) "\n " 72 WHITESPACE@[171; 180) "\n "
69 ATTR@[180; 212) 73 ATTR@[180; 212)
70 POUND@[180; 181) "#" 74 POUND@[180; 181) "#"
71 EXCL@[181; 182) "!" 75 EXCL@[181; 182) "!"
72 TOKEN_TREE@[182; 212) 76 L_BRACK@[182; 183) "["
73 L_BRACK@[182; 183) "[" 77 PATH@[183; 186)
74 IDENT@[183; 186) "doc" 78 PATH_SEGMENT@[183; 186)
75 TOKEN_TREE@[186; 211) 79 NAME_REF@[183; 186)
76 L_PAREN@[186; 187) "(" 80 IDENT@[183; 186) "doc"
77 STRING@[187; 210) "\"We error on each attr\"" 81 TOKEN_TREE@[186; 211)
78 R_PAREN@[210; 211) ")" 82 L_PAREN@[186; 187) "("
79 R_BRACK@[211; 212) "]" 83 STRING@[187; 210) "\"We error on each attr\""
84 R_PAREN@[210; 211) ")"
85 R_BRACK@[211; 212) "]"
80 WHITESPACE@[212; 221) "\n " 86 WHITESPACE@[212; 221) "\n "
81 COMMENT@[221; 251) "//! Nor are ModuleDoc ..." 87 COMMENT@[221; 251) "//! Nor are ModuleDoc ..."
82 WHITESPACE@[251; 256) "\n " 88 WHITESPACE@[251; 256) "\n "
@@ -96,14 +102,16 @@ SOURCE_FILE@[0; 350)
96 ATTR@[283; 302) 102 ATTR@[283; 302)
97 POUND@[283; 284) "#" 103 POUND@[283; 284) "#"
98 EXCL@[284; 285) "!" 104 EXCL@[284; 285) "!"
99 TOKEN_TREE@[285; 302) 105 L_BRACK@[285; 286) "["
100 L_BRACK@[285; 286) "[" 106 PATH@[286; 289)
101 IDENT@[286; 289) "doc" 107 PATH_SEGMENT@[286; 289)
102 TOKEN_TREE@[289; 301) 108 NAME_REF@[286; 289)
103 L_PAREN@[289; 290) "(" 109 IDENT@[286; 289) "doc"
104 STRING@[290; 300) "\"Nor here\"" 110 TOKEN_TREE@[289; 301)
105 R_PAREN@[300; 301) ")" 111 L_PAREN@[289; 290) "("
106 R_BRACK@[301; 302) "]" 112 STRING@[290; 300) "\"Nor here\""
113 R_PAREN@[300; 301) ")"
114 R_BRACK@[301; 302) "]"
107 WHITESPACE@[302; 311) "\n " 115 WHITESPACE@[302; 311) "\n "
108 COMMENT@[311; 341) "//! Nor are ModuleDoc ..." 116 COMMENT@[311; 341) "//! Nor are ModuleDoc ..."
109 WHITESPACE@[341; 346) "\n " 117 WHITESPACE@[341; 346) "\n "
diff --git a/crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.txt b/crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.txt
index 1344fcbc2..dbc0081ac 100644
--- a/crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/err/0032_match_arms_inner_attrs.txt
@@ -135,14 +135,16 @@ SOURCE_FILE@[0; 293)
135 MATCH_ARM@[210; 250) 135 MATCH_ARM@[210; 250)
136 ATTR@[210; 222) 136 ATTR@[210; 222)
137 POUND@[210; 211) "#" 137 POUND@[210; 211) "#"
138 TOKEN_TREE@[211; 222) 138 L_BRACK@[211; 212) "["
139 L_BRACK@[211; 212) "[" 139 PATH@[212; 215)
140 IDENT@[212; 215) "cfg" 140 PATH_SEGMENT@[212; 215)
141 TOKEN_TREE@[215; 221) 141 NAME_REF@[212; 215)
142 L_PAREN@[215; 216) "(" 142 IDENT@[212; 215) "cfg"
143 IDENT@[216; 220) "test" 143 TOKEN_TREE@[215; 221)
144 R_PAREN@[220; 221) ")" 144 L_PAREN@[215; 216) "("
145 R_BRACK@[221; 222) "]" 145 IDENT@[216; 220) "test"
146 R_PAREN@[220; 221) ")"
147 R_BRACK@[221; 222) "]"
146 WHITESPACE@[222; 231) "\n " 148 WHITESPACE@[222; 231) "\n "
147 ATTR@[231; 232) 149 ATTR@[231; 232)
148 POUND@[231; 232) "#" 150 POUND@[231; 232) "#"
diff --git a/crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.txt b/crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.txt
index b65cc3de3..fd5ccc3f2 100644
--- a/crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/err/0033_match_arms_outer_attrs.txt
@@ -47,14 +47,16 @@ SOURCE_FILE@[0; 89)
47 MATCH_ARM@[68; 80) 47 MATCH_ARM@[68; 80)
48 ATTR@[68; 80) 48 ATTR@[68; 80)
49 POUND@[68; 69) "#" 49 POUND@[68; 69) "#"
50 TOKEN_TREE@[69; 80) 50 L_BRACK@[69; 70) "["
51 L_BRACK@[69; 70) "[" 51 PATH@[70; 73)
52 IDENT@[70; 73) "cfg" 52 PATH_SEGMENT@[70; 73)
53 TOKEN_TREE@[73; 79) 53 NAME_REF@[70; 73)
54 L_PAREN@[73; 74) "(" 54 IDENT@[70; 73) "cfg"
55 IDENT@[74; 78) "test" 55 TOKEN_TREE@[73; 79)
56 R_PAREN@[78; 79) ")" 56 L_PAREN@[73; 74) "("
57 R_BRACK@[79; 80) "]" 57 IDENT@[74; 78) "test"
58 R_PAREN@[78; 79) ")"
59 R_BRACK@[79; 80) "]"
58 WHITESPACE@[80; 85) "\n " 60 WHITESPACE@[80; 85) "\n "
59 R_CURLY@[85; 86) "}" 61 R_CURLY@[85; 86) "}"
60 WHITESPACE@[86; 87) "\n" 62 WHITESPACE@[86; 87) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.txt b/crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.txt
index eab9f5b91..2ca5b8f32 100644
--- a/crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.txt
+++ b/crates/ra_syntax/test_data/parser/inline/err/0009_attr_on_expr_not_allowed.txt
@@ -15,10 +15,12 @@ SOURCE_FILE@[0; 48)
15 EXPR_STMT@[14; 25) 15 EXPR_STMT@[14; 25)
16 ATTR@[14; 18) 16 ATTR@[14; 18)
17 POUND@[14; 15) "#" 17 POUND@[14; 15) "#"
18 TOKEN_TREE@[15; 18) 18 L_BRACK@[15; 16) "["
19 L_BRACK@[15; 16) "[" 19 PATH@[16; 17)
20 IDENT@[16; 17) "A" 20 PATH_SEGMENT@[16; 17)
21 R_BRACK@[17; 18) "]" 21 NAME_REF@[16; 17)
22 IDENT@[16; 17) "A"
23 R_BRACK@[17; 18) "]"
22 WHITESPACE@[18; 19) " " 24 WHITESPACE@[18; 19) " "
23 BIN_EXPR@[19; 24) 25 BIN_EXPR@[19; 24)
24 LITERAL@[19; 20) 26 LITERAL@[19; 20)
@@ -33,10 +35,12 @@ SOURCE_FILE@[0; 48)
33 EXPR_STMT@[29; 45) 35 EXPR_STMT@[29; 45)
34 ATTR@[29; 33) 36 ATTR@[29; 33)
35 POUND@[29; 30) "#" 37 POUND@[29; 30) "#"
36 TOKEN_TREE@[30; 33) 38 L_BRACK@[30; 31) "["
37 L_BRACK@[30; 31) "[" 39 PATH@[31; 32)
38 IDENT@[31; 32) "B" 40 PATH_SEGMENT@[31; 32)
39 R_BRACK@[32; 33) "]" 41 NAME_REF@[31; 32)
42 IDENT@[31; 32) "B"
43 R_BRACK@[32; 33) "]"
40 WHITESPACE@[33; 34) " " 44 WHITESPACE@[33; 34) " "
41 IF_EXPR@[34; 44) 45 IF_EXPR@[34; 44)
42 IF_KW@[34; 36) "if" 46 IF_KW@[34; 36) "if"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs
index 293046a04..2f8188160 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.rs
@@ -1,4 +1,5 @@
1fn foo() { 1fn foo() {
2 while true {}; 2 while true {};
3 while let Some(x) = it.next() {}; 3 while let Some(x) = it.next() {};
4 while { true } {};
4} 5}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt
index 9b43d624c..a6e14a114 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0031_while_expr.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 70) 1SOURCE_FILE@[0; 93)
2 FN_DEF@[0; 69) 2 FN_DEF@[0; 92)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 70)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 69) 11 BLOCK_EXPR@[9; 92)
12 BLOCK@[9; 69) 12 BLOCK@[9; 92)
13 L_CURLY@[9; 10) "{" 13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n " 14 WHITESPACE@[10; 15) "\n "
15 EXPR_STMT@[15; 29) 15 EXPR_STMT@[15; 29)
@@ -64,6 +64,26 @@ SOURCE_FILE@[0; 70)
64 L_CURLY@[64; 65) "{" 64 L_CURLY@[64; 65) "{"
65 R_CURLY@[65; 66) "}" 65 R_CURLY@[65; 66) "}"
66 SEMI@[66; 67) ";" 66 SEMI@[66; 67) ";"
67 WHITESPACE@[67; 68) "\n" 67 WHITESPACE@[67; 72) "\n "
68 R_CURLY@[68; 69) "}" 68 EXPR_STMT@[72; 90)
69 WHITESPACE@[69; 70) "\n" 69 WHILE_EXPR@[72; 89)
70 WHILE_KW@[72; 77) "while"
71 WHITESPACE@[77; 78) " "
72 CONDITION@[78; 86)
73 BLOCK_EXPR@[78; 86)
74 BLOCK@[78; 86)
75 L_CURLY@[78; 79) "{"
76 WHITESPACE@[79; 80) " "
77 LITERAL@[80; 84)
78 TRUE_KW@[80; 84) "true"
79 WHITESPACE@[84; 85) " "
80 R_CURLY@[85; 86) "}"
81 WHITESPACE@[86; 87) " "
82 BLOCK_EXPR@[87; 89)
83 BLOCK@[87; 89)
84 L_CURLY@[87; 88) "{"
85 R_CURLY@[88; 89) "}"
86 SEMI@[89; 90) ";"
87 WHITESPACE@[90; 91) "\n"
88 R_CURLY@[91; 92) "}"
89 WHITESPACE@[92; 93) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt b/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt
index 56aeba768..731c31f76 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0054_record_field_attrs.txt
@@ -11,18 +11,20 @@ SOURCE_FILE@[0; 64)
11 RECORD_FIELD_DEF@[15; 60) 11 RECORD_FIELD_DEF@[15; 60)
12 ATTR@[15; 43) 12 ATTR@[15; 43)
13 POUND@[15; 16) "#" 13 POUND@[15; 16) "#"
14 TOKEN_TREE@[16; 43) 14 L_BRACK@[16; 17) "["
15 L_BRACK@[16; 17) "[" 15 PATH@[17; 22)
16 IDENT@[17; 22) "serde" 16 PATH_SEGMENT@[17; 22)
17 TOKEN_TREE@[22; 42) 17 NAME_REF@[17; 22)
18 L_PAREN@[22; 23) "(" 18 IDENT@[17; 22) "serde"
19 IDENT@[23; 27) "with" 19 TOKEN_TREE@[22; 42)
20 WHITESPACE@[27; 28) " " 20 L_PAREN@[22; 23) "("
21 EQ@[28; 29) "=" 21 IDENT@[23; 27) "with"
22 WHITESPACE@[29; 30) " " 22 WHITESPACE@[27; 28) " "
23 STRING@[30; 41) "\"url_serde\"" 23 EQ@[28; 29) "="
24 R_PAREN@[41; 42) ")" 24 WHITESPACE@[29; 30) " "
25 R_BRACK@[42; 43) "]" 25 STRING@[30; 41) "\"url_serde\""
26 R_PAREN@[41; 42) ")"
27 R_BRACK@[42; 43) "]"
26 WHITESPACE@[43; 48) "\n " 28 WHITESPACE@[43; 48) "\n "
27 VISIBILITY@[48; 51) 29 VISIBILITY@[48; 51)
28 PUB_KW@[48; 51) "pub" 30 PUB_KW@[48; 51) "pub"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs
index 4b0d9af89..40f227ba3 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.rs
@@ -3,4 +3,5 @@ fn foo() {
3 if true {} else {}; 3 if true {} else {};
4 if true {} else if false {} else {}; 4 if true {} else if false {} else {};
5 if S {}; 5 if S {};
6 if { true } { } else { };
6} 7}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt
index 14ea91fd2..2ace3c8ee 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0064_if_expr.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 107) 1SOURCE_FILE@[0; 137)
2 FN_DEF@[0; 106) 2 FN_DEF@[0; 136)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 107)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 106) 11 BLOCK_EXPR@[9; 136)
12 BLOCK@[9; 106) 12 BLOCK@[9; 136)
13 L_CURLY@[9; 10) "{" 13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n " 14 WHITESPACE@[10; 15) "\n "
15 EXPR_STMT@[15; 26) 15 EXPR_STMT@[15; 26)
@@ -98,6 +98,35 @@ SOURCE_FILE@[0; 107)
98 L_CURLY@[101; 102) "{" 98 L_CURLY@[101; 102) "{"
99 R_CURLY@[102; 103) "}" 99 R_CURLY@[102; 103) "}"
100 SEMI@[103; 104) ";" 100 SEMI@[103; 104) ";"
101 WHITESPACE@[104; 105) "\n" 101 WHITESPACE@[104; 109) "\n "
102 R_CURLY@[105; 106) "}" 102 EXPR_STMT@[109; 134)
103 WHITESPACE@[106; 107) "\n" 103 IF_EXPR@[109; 133)
104 IF_KW@[109; 111) "if"
105 WHITESPACE@[111; 112) " "
106 CONDITION@[112; 120)
107 BLOCK_EXPR@[112; 120)
108 BLOCK@[112; 120)
109 L_CURLY@[112; 113) "{"
110 WHITESPACE@[113; 114) " "
111 LITERAL@[114; 118)
112 TRUE_KW@[114; 118) "true"
113 WHITESPACE@[118; 119) " "
114 R_CURLY@[119; 120) "}"
115 WHITESPACE@[120; 121) " "
116 BLOCK_EXPR@[121; 124)
117 BLOCK@[121; 124)
118 L_CURLY@[121; 122) "{"
119 WHITESPACE@[122; 123) " "
120 R_CURLY@[123; 124) "}"
121 WHITESPACE@[124; 125) " "
122 ELSE_KW@[125; 129) "else"
123 WHITESPACE@[129; 130) " "
124 BLOCK_EXPR@[130; 133)
125 BLOCK@[130; 133)
126 L_CURLY@[130; 131) "{"
127 WHITESPACE@[131; 132) " "
128 R_CURLY@[132; 133) "}"
129 SEMI@[133; 134) ";"
130 WHITESPACE@[134; 135) "\n"
131 R_CURLY@[135; 136) "}"
132 WHITESPACE@[136; 137) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs
index c9205dfa3..c4021dc10 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.rs
@@ -1,4 +1,6 @@
1fn foo() { 1fn foo() {
2 match () { }; 2 match () { };
3 match S {}; 3 match S {};
4 match { } { _ => () };
5 match { S {} } {};
4} 6}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt
index f62b6c6d5..0af668056 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0071_match_expr.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 47) 1SOURCE_FILE@[0; 97)
2 FN_DEF@[0; 46) 2 FN_DEF@[0; 96)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,8 +8,8 @@ SOURCE_FILE@[0; 47)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 46) 11 BLOCK_EXPR@[9; 96)
12 BLOCK@[9; 46) 12 BLOCK@[9; 96)
13 L_CURLY@[9; 10) "{" 13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n " 14 WHITESPACE@[10; 15) "\n "
15 EXPR_STMT@[15; 28) 15 EXPR_STMT@[15; 28)
@@ -40,6 +40,57 @@ SOURCE_FILE@[0; 47)
40 L_CURLY@[41; 42) "{" 40 L_CURLY@[41; 42) "{"
41 R_CURLY@[42; 43) "}" 41 R_CURLY@[42; 43) "}"
42 SEMI@[43; 44) ";" 42 SEMI@[43; 44) ";"
43 WHITESPACE@[44; 45) "\n" 43 WHITESPACE@[44; 49) "\n "
44 R_CURLY@[45; 46) "}" 44 EXPR_STMT@[49; 71)
45 WHITESPACE@[46; 47) "\n" 45 MATCH_EXPR@[49; 70)
46 MATCH_KW@[49; 54) "match"
47 WHITESPACE@[54; 55) " "
48 BLOCK_EXPR@[55; 58)
49 BLOCK@[55; 58)
50 L_CURLY@[55; 56) "{"
51 WHITESPACE@[56; 57) " "
52 R_CURLY@[57; 58) "}"
53 WHITESPACE@[58; 59) " "
54 MATCH_ARM_LIST@[59; 70)
55 L_CURLY@[59; 60) "{"
56 WHITESPACE@[60; 61) " "
57 MATCH_ARM@[61; 68)
58 PLACEHOLDER_PAT@[61; 62)
59 UNDERSCORE@[61; 62) "_"
60 WHITESPACE@[62; 63) " "
61 FAT_ARROW@[63; 65) "=>"
62 WHITESPACE@[65; 66) " "
63 TUPLE_EXPR@[66; 68)
64 L_PAREN@[66; 67) "("
65 R_PAREN@[67; 68) ")"
66 WHITESPACE@[68; 69) " "
67 R_CURLY@[69; 70) "}"
68 SEMI@[70; 71) ";"
69 WHITESPACE@[71; 76) "\n "
70 EXPR_STMT@[76; 94)
71 MATCH_EXPR@[76; 93)
72 MATCH_KW@[76; 81) "match"
73 WHITESPACE@[81; 82) " "
74 BLOCK_EXPR@[82; 90)
75 BLOCK@[82; 90)
76 L_CURLY@[82; 83) "{"
77 WHITESPACE@[83; 84) " "
78 RECORD_LIT@[84; 88)
79 PATH@[84; 85)
80 PATH_SEGMENT@[84; 85)
81 NAME_REF@[84; 85)
82 IDENT@[84; 85) "S"
83 WHITESPACE@[85; 86) " "
84 RECORD_FIELD_LIST@[86; 88)
85 L_CURLY@[86; 87) "{"
86 R_CURLY@[87; 88) "}"
87 WHITESPACE@[88; 89) " "
88 R_CURLY@[89; 90) "}"
89 WHITESPACE@[90; 91) " "
90 MATCH_ARM_LIST@[91; 93)
91 L_CURLY@[91; 92) "{"
92 R_CURLY@[92; 93) "}"
93 SEMI@[93; 94) ";"
94 WHITESPACE@[94; 95) "\n"
95 R_CURLY@[95; 96) "}"
96 WHITESPACE@[96; 97) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs
index c39fe8e68..e7b7cfc6b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.rs
@@ -1 +1,5 @@
1fn foo() { let x = 1..; } 1fn foo() {
2 let x = 1..;
3 match 1.. { _ => () };
4 match a.b()..S { _ => () };
5}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt
index f3c292f5e..9f8a6b0f6 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0080_postfix_range.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 26) 1SOURCE_FILE@[0; 89)
2 FN_DEF@[0; 25) 2 FN_DEF@[0; 88)
3 FN_KW@[0; 2) "fn" 3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " " 4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6) 5 NAME@[3; 6)
@@ -8,24 +8,89 @@ SOURCE_FILE@[0; 26)
8 L_PAREN@[6; 7) "(" 8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")" 9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " " 10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 25) 11 BLOCK_EXPR@[9; 88)
12 BLOCK@[9; 25) 12 BLOCK@[9; 88)
13 L_CURLY@[9; 10) "{" 13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 11) " " 14 WHITESPACE@[10; 15) "\n "
15 LET_STMT@[11; 23) 15 LET_STMT@[15; 27)
16 LET_KW@[11; 14) "let" 16 LET_KW@[15; 18) "let"
17 WHITESPACE@[14; 15) " "
18 BIND_PAT@[15; 16)
19 NAME@[15; 16)
20 IDENT@[15; 16) "x"
21 WHITESPACE@[16; 17) " "
22 EQ@[17; 18) "="
23 WHITESPACE@[18; 19) " " 17 WHITESPACE@[18; 19) " "
24 RANGE_EXPR@[19; 22) 18 BIND_PAT@[19; 20)
25 LITERAL@[19; 20) 19 NAME@[19; 20)
26 INT_NUMBER@[19; 20) "1" 20 IDENT@[19; 20) "x"
27 DOTDOT@[20; 22) ".." 21 WHITESPACE@[20; 21) " "
28 SEMI@[22; 23) ";" 22 EQ@[21; 22) "="
29 WHITESPACE@[23; 24) " " 23 WHITESPACE@[22; 23) " "
30 R_CURLY@[24; 25) "}" 24 RANGE_EXPR@[23; 26)
31 WHITESPACE@[25; 26) "\n" 25 LITERAL@[23; 24)
26 INT_NUMBER@[23; 24) "1"
27 DOTDOT@[24; 26) ".."
28 SEMI@[26; 27) ";"
29 WHITESPACE@[27; 32) "\n "
30 EXPR_STMT@[32; 54)
31 MATCH_EXPR@[32; 53)
32 MATCH_KW@[32; 37) "match"
33 WHITESPACE@[37; 38) " "
34 RANGE_EXPR@[38; 41)
35 LITERAL@[38; 39)
36 INT_NUMBER@[38; 39) "1"
37 DOTDOT@[39; 41) ".."
38 WHITESPACE@[41; 42) " "
39 MATCH_ARM_LIST@[42; 53)
40 L_CURLY@[42; 43) "{"
41 WHITESPACE@[43; 44) " "
42 MATCH_ARM@[44; 51)
43 PLACEHOLDER_PAT@[44; 45)
44 UNDERSCORE@[44; 45) "_"
45 WHITESPACE@[45; 46) " "
46 FAT_ARROW@[46; 48) "=>"
47 WHITESPACE@[48; 49) " "
48 TUPLE_EXPR@[49; 51)
49 L_PAREN@[49; 50) "("
50 R_PAREN@[50; 51) ")"
51 WHITESPACE@[51; 52) " "
52 R_CURLY@[52; 53) "}"
53 SEMI@[53; 54) ";"
54 WHITESPACE@[54; 59) "\n "
55 EXPR_STMT@[59; 86)
56 MATCH_EXPR@[59; 85)
57 MATCH_KW@[59; 64) "match"
58 WHITESPACE@[64; 65) " "
59 RANGE_EXPR@[65; 73)
60 METHOD_CALL_EXPR@[65; 70)
61 PATH_EXPR@[65; 66)
62 PATH@[65; 66)
63 PATH_SEGMENT@[65; 66)
64 NAME_REF@[65; 66)
65 IDENT@[65; 66) "a"
66 DOT@[66; 67) "."
67 NAME_REF@[67; 68)
68 IDENT@[67; 68) "b"
69 ARG_LIST@[68; 70)
70 L_PAREN@[68; 69) "("
71 R_PAREN@[69; 70) ")"
72 DOTDOT@[70; 72) ".."
73 PATH_EXPR@[72; 73)
74 PATH@[72; 73)
75 PATH_SEGMENT@[72; 73)
76 NAME_REF@[72; 73)
77 IDENT@[72; 73) "S"
78 WHITESPACE@[73; 74) " "
79 MATCH_ARM_LIST@[74; 85)
80 L_CURLY@[74; 75) "{"
81 WHITESPACE@[75; 76) " "
82 MATCH_ARM@[76; 83)
83 PLACEHOLDER_PAT@[76; 77)
84 UNDERSCORE@[76; 77) "_"
85 WHITESPACE@[77; 78) " "
86 FAT_ARROW@[78; 80) "=>"
87 WHITESPACE@[80; 81) " "
88 TUPLE_EXPR@[81; 83)
89 L_PAREN@[81; 82) "("
90 R_PAREN@[82; 83) ")"
91 WHITESPACE@[83; 84) " "
92 R_CURLY@[84; 85) "}"
93 SEMI@[85; 86) ";"
94 WHITESPACE@[86; 87) "\n"
95 R_CURLY@[87; 88) "}"
96 WHITESPACE@[88; 89) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt b/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt
index cb6d9f76d..8fe15d8e2 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0115_tuple_field_attrs.txt
@@ -11,18 +11,20 @@ SOURCE_FILE@[0; 60)
11 TUPLE_FIELD_DEF@[15; 55) 11 TUPLE_FIELD_DEF@[15; 55)
12 ATTR@[15; 43) 12 ATTR@[15; 43)
13 POUND@[15; 16) "#" 13 POUND@[15; 16) "#"
14 TOKEN_TREE@[16; 43) 14 L_BRACK@[16; 17) "["
15 L_BRACK@[16; 17) "[" 15 PATH@[17; 22)
16 IDENT@[17; 22) "serde" 16 PATH_SEGMENT@[17; 22)
17 TOKEN_TREE@[22; 42) 17 NAME_REF@[17; 22)
18 L_PAREN@[22; 23) "(" 18 IDENT@[17; 22) "serde"
19 IDENT@[23; 27) "with" 19 TOKEN_TREE@[22; 42)
20 WHITESPACE@[27; 28) " " 20 L_PAREN@[22; 23) "("
21 EQ@[28; 29) "=" 21 IDENT@[23; 27) "with"
22 WHITESPACE@[29; 30) " " 22 WHITESPACE@[27; 28) " "
23 STRING@[30; 41) "\"url_serde\"" 23 EQ@[28; 29) "="
24 R_PAREN@[41; 42) ")" 24 WHITESPACE@[29; 30) " "
25 R_BRACK@[42; 43) "]" 25 STRING@[30; 41) "\"url_serde\""
26 R_PAREN@[41; 42) ")"
27 R_BRACK@[42; 43) "]"
26 WHITESPACE@[43; 48) "\n " 28 WHITESPACE@[43; 48) "\n "
27 VISIBILITY@[48; 51) 29 VISIBILITY@[48; 51)
28 PUB_KW@[48; 51) "pub" 30 PUB_KW@[48; 51) "pub"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.txt b/crates/ra_syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.txt
index 0ef3eeb75..0e9e9b95b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0118_impl_inner_attributes.txt
@@ -25,14 +25,16 @@ SOURCE_FILE@[0; 94)
25 ATTR@[54; 91) 25 ATTR@[54; 91)
26 POUND@[54; 55) "#" 26 POUND@[54; 55) "#"
27 EXCL@[55; 56) "!" 27 EXCL@[55; 56) "!"
28 TOKEN_TREE@[56; 91) 28 L_BRACK@[56; 57) "["
29 L_BRACK@[56; 57) "[" 29 PATH@[57; 60)
30 IDENT@[57; 60) "doc" 30 PATH_SEGMENT@[57; 60)
31 TOKEN_TREE@[60; 90) 31 NAME_REF@[57; 60)
32 L_PAREN@[60; 61) "(" 32 IDENT@[57; 60) "doc"
33 STRING@[61; 89) "\"This is also a doc c ..." 33 TOKEN_TREE@[60; 90)
34 R_PAREN@[89; 90) ")" 34 L_PAREN@[60; 61) "("
35 R_BRACK@[90; 91) "]" 35 STRING@[61; 89) "\"This is also a doc c ..."
36 R_PAREN@[89; 90) ")"
37 R_BRACK@[90; 91) "]"
36 WHITESPACE@[91; 92) "\n" 38 WHITESPACE@[91; 92) "\n"
37 R_CURLY@[92; 93) "}" 39 R_CURLY@[92; 93) "}"
38 WHITESPACE@[93; 94) "\n" 40 WHITESPACE@[93; 94) "\n"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.txt b/crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.txt
index 3bbeb62bc..640e0640f 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0120_match_arms_inner_attribute.txt
@@ -25,38 +25,44 @@ SOURCE_FILE@[0; 139)
25 ATTR@[34; 60) 25 ATTR@[34; 60)
26 POUND@[34; 35) "#" 26 POUND@[34; 35) "#"
27 EXCL@[35; 36) "!" 27 EXCL@[35; 36) "!"
28 TOKEN_TREE@[36; 60) 28 L_BRACK@[36; 37) "["
29 L_BRACK@[36; 37) "[" 29 PATH@[37; 40)
30 IDENT@[37; 40) "doc" 30 PATH_SEGMENT@[37; 40)
31 TOKEN_TREE@[40; 59) 31 NAME_REF@[37; 40)
32 L_PAREN@[40; 41) "(" 32 IDENT@[37; 40) "doc"
33 STRING@[41; 58) "\"Inner attribute\"" 33 TOKEN_TREE@[40; 59)
34 R_PAREN@[58; 59) ")" 34 L_PAREN@[40; 41) "("
35 R_BRACK@[59; 60) "]" 35 STRING@[41; 58) "\"Inner attribute\""
36 R_PAREN@[58; 59) ")"
37 R_BRACK@[59; 60) "]"
36 WHITESPACE@[60; 69) "\n " 38 WHITESPACE@[60; 69) "\n "
37 ATTR@[69; 86) 39 ATTR@[69; 86)
38 POUND@[69; 70) "#" 40 POUND@[69; 70) "#"
39 EXCL@[70; 71) "!" 41 EXCL@[70; 71) "!"
40 TOKEN_TREE@[71; 86) 42 L_BRACK@[71; 72) "["
41 L_BRACK@[71; 72) "[" 43 PATH@[72; 75)
42 IDENT@[72; 75) "doc" 44 PATH_SEGMENT@[72; 75)
43 TOKEN_TREE@[75; 85) 45 NAME_REF@[72; 75)
44 L_PAREN@[75; 76) "(" 46 IDENT@[72; 75) "doc"
45 STRING@[76; 84) "\"Can be\"" 47 TOKEN_TREE@[75; 85)
46 R_PAREN@[84; 85) ")" 48 L_PAREN@[75; 76) "("
47 R_BRACK@[85; 86) "]" 49 STRING@[76; 84) "\"Can be\""
50 R_PAREN@[84; 85) ")"
51 R_BRACK@[85; 86) "]"
48 WHITESPACE@[86; 95) "\n " 52 WHITESPACE@[86; 95) "\n "
49 ATTR@[95; 113) 53 ATTR@[95; 113)
50 POUND@[95; 96) "#" 54 POUND@[95; 96) "#"
51 EXCL@[96; 97) "!" 55 EXCL@[96; 97) "!"
52 TOKEN_TREE@[97; 113) 56 L_BRACK@[97; 98) "["
53 L_BRACK@[97; 98) "[" 57 PATH@[98; 101)
54 IDENT@[98; 101) "doc" 58 PATH_SEGMENT@[98; 101)
55 TOKEN_TREE@[101; 112) 59 NAME_REF@[98; 101)
56 L_PAREN@[101; 102) "(" 60 IDENT@[98; 101) "doc"
57 STRING@[102; 111) "\"Stacked\"" 61 TOKEN_TREE@[101; 112)
58 R_PAREN@[111; 112) ")" 62 L_PAREN@[101; 102) "("
59 R_BRACK@[112; 113) "]" 63 STRING@[102; 111) "\"Stacked\""
64 R_PAREN@[111; 112) ")"
65 R_BRACK@[112; 113) "]"
60 WHITESPACE@[113; 122) "\n " 66 WHITESPACE@[113; 122) "\n "
61 MATCH_ARM@[122; 129) 67 MATCH_ARM@[122; 129)
62 PLACEHOLDER_PAT@[122; 123) 68 PLACEHOLDER_PAT@[122; 123)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.txt b/crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.txt
index 5fd0adfc2..ff380b448 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0121_match_arms_outer_attributes.txt
@@ -25,18 +25,20 @@ SOURCE_FILE@[0; 259)
25 MATCH_ARM@[34; 74) 25 MATCH_ARM@[34; 74)
26 ATTR@[34; 58) 26 ATTR@[34; 58)
27 POUND@[34; 35) "#" 27 POUND@[34; 35) "#"
28 TOKEN_TREE@[35; 58) 28 L_BRACK@[35; 36) "["
29 L_BRACK@[35; 36) "[" 29 PATH@[36; 39)
30 IDENT@[36; 39) "cfg" 30 PATH_SEGMENT@[36; 39)
31 TOKEN_TREE@[39; 57) 31 NAME_REF@[36; 39)
32 L_PAREN@[39; 40) "(" 32 IDENT@[36; 39) "cfg"
33 IDENT@[40; 47) "feature" 33 TOKEN_TREE@[39; 57)
34 WHITESPACE@[47; 48) " " 34 L_PAREN@[39; 40) "("
35 EQ@[48; 49) "=" 35 IDENT@[40; 47) "feature"
36 WHITESPACE@[49; 50) " " 36 WHITESPACE@[47; 48) " "
37 STRING@[50; 56) "\"some\"" 37 EQ@[48; 49) "="
38 R_PAREN@[56; 57) ")" 38 WHITESPACE@[49; 50) " "
39 R_BRACK@[57; 58) "]" 39 STRING@[50; 56) "\"some\""
40 R_PAREN@[56; 57) ")"
41 R_BRACK@[57; 58) "]"
40 WHITESPACE@[58; 67) "\n " 42 WHITESPACE@[58; 67) "\n "
41 PLACEHOLDER_PAT@[67; 68) 43 PLACEHOLDER_PAT@[67; 68)
42 UNDERSCORE@[67; 68) "_" 44 UNDERSCORE@[67; 68) "_"
@@ -51,18 +53,20 @@ SOURCE_FILE@[0; 259)
51 MATCH_ARM@[84; 125) 53 MATCH_ARM@[84; 125)
52 ATTR@[84; 109) 54 ATTR@[84; 109)
53 POUND@[84; 85) "#" 55 POUND@[84; 85) "#"
54 TOKEN_TREE@[85; 109) 56 L_BRACK@[85; 86) "["
55 L_BRACK@[85; 86) "[" 57 PATH@[86; 89)
56 IDENT@[86; 89) "cfg" 58 PATH_SEGMENT@[86; 89)
57 TOKEN_TREE@[89; 108) 59 NAME_REF@[86; 89)
58 L_PAREN@[89; 90) "(" 60 IDENT@[86; 89) "cfg"
59 IDENT@[90; 97) "feature" 61 TOKEN_TREE@[89; 108)
60 WHITESPACE@[97; 98) " " 62 L_PAREN@[89; 90) "("
61 EQ@[98; 99) "=" 63 IDENT@[90; 97) "feature"
62 WHITESPACE@[99; 100) " " 64 WHITESPACE@[97; 98) " "
63 STRING@[100; 107) "\"other\"" 65 EQ@[98; 99) "="
64 R_PAREN@[107; 108) ")" 66 WHITESPACE@[99; 100) " "
65 R_BRACK@[108; 109) "]" 67 STRING@[100; 107) "\"other\""
68 R_PAREN@[107; 108) ")"
69 R_BRACK@[108; 109) "]"
66 WHITESPACE@[109; 118) "\n " 70 WHITESPACE@[109; 118) "\n "
67 PLACEHOLDER_PAT@[118; 119) 71 PLACEHOLDER_PAT@[118; 119)
68 UNDERSCORE@[118; 119) "_" 72 UNDERSCORE@[118; 119) "_"
@@ -77,48 +81,54 @@ SOURCE_FILE@[0; 259)
77 MATCH_ARM@[135; 249) 81 MATCH_ARM@[135; 249)
78 ATTR@[135; 159) 82 ATTR@[135; 159)
79 POUND@[135; 136) "#" 83 POUND@[135; 136) "#"
80 TOKEN_TREE@[136; 159) 84 L_BRACK@[136; 137) "["
81 L_BRACK@[136; 137) "[" 85 PATH@[137; 140)
82 IDENT@[137; 140) "cfg" 86 PATH_SEGMENT@[137; 140)
83 TOKEN_TREE@[140; 158) 87 NAME_REF@[137; 140)
84 L_PAREN@[140; 141) "(" 88 IDENT@[137; 140) "cfg"
85 IDENT@[141; 148) "feature" 89 TOKEN_TREE@[140; 158)
86 WHITESPACE@[148; 149) " " 90 L_PAREN@[140; 141) "("
87 EQ@[149; 150) "=" 91 IDENT@[141; 148) "feature"
88 WHITESPACE@[150; 151) " " 92 WHITESPACE@[148; 149) " "
89 STRING@[151; 157) "\"many\"" 93 EQ@[149; 150) "="
90 R_PAREN@[157; 158) ")" 94 WHITESPACE@[150; 151) " "
91 R_BRACK@[158; 159) "]" 95 STRING@[151; 157) "\"many\""
96 R_PAREN@[157; 158) ")"
97 R_BRACK@[158; 159) "]"
92 WHITESPACE@[159; 168) "\n " 98 WHITESPACE@[159; 168) "\n "
93 ATTR@[168; 198) 99 ATTR@[168; 198)
94 POUND@[168; 169) "#" 100 POUND@[168; 169) "#"
95 TOKEN_TREE@[169; 198) 101 L_BRACK@[169; 170) "["
96 L_BRACK@[169; 170) "[" 102 PATH@[170; 173)
97 IDENT@[170; 173) "cfg" 103 PATH_SEGMENT@[170; 173)
98 TOKEN_TREE@[173; 197) 104 NAME_REF@[170; 173)
99 L_PAREN@[173; 174) "(" 105 IDENT@[170; 173) "cfg"
100 IDENT@[174; 181) "feature" 106 TOKEN_TREE@[173; 197)
101 WHITESPACE@[181; 182) " " 107 L_PAREN@[173; 174) "("
102 EQ@[182; 183) "=" 108 IDENT@[174; 181) "feature"
103 WHITESPACE@[183; 184) " " 109 WHITESPACE@[181; 182) " "
104 STRING@[184; 196) "\"attributes\"" 110 EQ@[182; 183) "="
105 R_PAREN@[196; 197) ")" 111 WHITESPACE@[183; 184) " "
106 R_BRACK@[197; 198) "]" 112 STRING@[184; 196) "\"attributes\""
113 R_PAREN@[196; 197) ")"
114 R_BRACK@[197; 198) "]"
107 WHITESPACE@[198; 207) "\n " 115 WHITESPACE@[198; 207) "\n "
108 ATTR@[207; 233) 116 ATTR@[207; 233)
109 POUND@[207; 208) "#" 117 POUND@[207; 208) "#"
110 TOKEN_TREE@[208; 233) 118 L_BRACK@[208; 209) "["
111 L_BRACK@[208; 209) "[" 119 PATH@[209; 212)
112 IDENT@[209; 212) "cfg" 120 PATH_SEGMENT@[209; 212)
113 TOKEN_TREE@[212; 232) 121 NAME_REF@[209; 212)
114 L_PAREN@[212; 213) "(" 122 IDENT@[209; 212) "cfg"
115 IDENT@[213; 220) "feature" 123 TOKEN_TREE@[212; 232)
116 WHITESPACE@[220; 221) " " 124 L_PAREN@[212; 213) "("
117 EQ@[221; 222) "=" 125 IDENT@[213; 220) "feature"
118 WHITESPACE@[222; 223) " " 126 WHITESPACE@[220; 221) " "
119 STRING@[223; 231) "\"before\"" 127 EQ@[221; 222) "="
120 R_PAREN@[231; 232) ")" 128 WHITESPACE@[222; 223) " "
121 R_BRACK@[232; 233) "]" 129 STRING@[223; 231) "\"before\""
130 R_PAREN@[231; 232) ")"
131 R_BRACK@[232; 233) "]"
122 WHITESPACE@[233; 242) "\n " 132 WHITESPACE@[233; 242) "\n "
123 PLACEHOLDER_PAT@[242; 243) 133 PLACEHOLDER_PAT@[242; 243)
124 UNDERSCORE@[242; 243) "_" 134 UNDERSCORE@[242; 243) "_"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.txt b/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.txt
index bc7b68b90..a73ff9c90 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0122_generic_lifetime_type_attribute.txt
@@ -9,14 +9,16 @@ SOURCE_FILE@[0; 64)
9 LIFETIME_PARAM@[7; 29) 9 LIFETIME_PARAM@[7; 29)
10 ATTR@[7; 26) 10 ATTR@[7; 26)
11 POUND@[7; 8) "#" 11 POUND@[7; 8) "#"
12 TOKEN_TREE@[8; 26) 12 L_BRACK@[8; 9) "["
13 L_BRACK@[8; 9) "[" 13 PATH@[9; 15)
14 IDENT@[9; 15) "derive" 14 PATH_SEGMENT@[9; 15)
15 TOKEN_TREE@[15; 25) 15 NAME_REF@[9; 15)
16 L_PAREN@[15; 16) "(" 16 IDENT@[9; 15) "derive"
17 IDENT@[16; 24) "Lifetime" 17 TOKEN_TREE@[15; 25)
18 R_PAREN@[24; 25) ")" 18 L_PAREN@[15; 16) "("
19 R_BRACK@[25; 26) "]" 19 IDENT@[16; 24) "Lifetime"
20 R_PAREN@[24; 25) ")"
21 R_BRACK@[25; 26) "]"
20 WHITESPACE@[26; 27) " " 22 WHITESPACE@[26; 27) " "
21 LIFETIME@[27; 29) "\'a" 23 LIFETIME@[27; 29) "\'a"
22 COMMA@[29; 30) "," 24 COMMA@[29; 30) ","
@@ -24,14 +26,16 @@ SOURCE_FILE@[0; 64)
24 TYPE_PARAM@[31; 48) 26 TYPE_PARAM@[31; 48)
25 ATTR@[31; 46) 27 ATTR@[31; 46)
26 POUND@[31; 32) "#" 28 POUND@[31; 32) "#"
27 TOKEN_TREE@[32; 46) 29 L_BRACK@[32; 33) "["
28 L_BRACK@[32; 33) "[" 30 PATH@[33; 39)
29 IDENT@[33; 39) "derive" 31 PATH_SEGMENT@[33; 39)
30 TOKEN_TREE@[39; 45) 32 NAME_REF@[33; 39)
31 L_PAREN@[39; 40) "(" 33 IDENT@[33; 39) "derive"
32 IDENT@[40; 44) "Type" 34 TOKEN_TREE@[39; 45)
33 R_PAREN@[44; 45) ")" 35 L_PAREN@[39; 40) "("
34 R_BRACK@[45; 46) "]" 36 IDENT@[40; 44) "Type"
37 R_PAREN@[44; 45) ")"
38 R_BRACK@[45; 46) "]"
35 WHITESPACE@[46; 47) " " 39 WHITESPACE@[46; 47) " "
36 NAME@[47; 48) 40 NAME@[47; 48)
37 IDENT@[47; 48) "T" 41 IDENT@[47; 48) "T"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt
index 37cc438d9..a36c3df0e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0125_record_literal_field_with_attr.txt
@@ -24,14 +24,16 @@ SOURCE_FILE@[0; 46)
24 RECORD_FIELD@[20; 41) 24 RECORD_FIELD@[20; 41)
25 ATTR@[20; 32) 25 ATTR@[20; 32)
26 POUND@[20; 21) "#" 26 POUND@[20; 21) "#"
27 TOKEN_TREE@[21; 32) 27 L_BRACK@[21; 22) "["
28 L_BRACK@[21; 22) "[" 28 PATH@[22; 25)
29 IDENT@[22; 25) "cfg" 29 PATH_SEGMENT@[22; 25)
30 TOKEN_TREE@[25; 31) 30 NAME_REF@[22; 25)
31 L_PAREN@[25; 26) "(" 31 IDENT@[22; 25) "cfg"
32 IDENT@[26; 30) "test" 32 TOKEN_TREE@[25; 31)
33 R_PAREN@[30; 31) ")" 33 L_PAREN@[25; 26) "("
34 R_BRACK@[31; 32) "]" 34 IDENT@[26; 30) "test"
35 R_PAREN@[30; 31) ")"
36 R_BRACK@[31; 32) "]"
35 WHITESPACE@[32; 33) " " 37 WHITESPACE@[32; 33) " "
36 NAME_REF@[33; 38) 38 NAME_REF@[33; 38)
37 IDENT@[33; 38) "field" 39 IDENT@[33; 38) "field"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.txt b/crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.txt
index 6bc0db077..5c311d18a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0126_attr_on_expr_stmt.txt
@@ -15,10 +15,12 @@ SOURCE_FILE@[0; 82)
15 EXPR_STMT@[15; 26) 15 EXPR_STMT@[15; 26)
16 ATTR@[15; 19) 16 ATTR@[15; 19)
17 POUND@[15; 16) "#" 17 POUND@[15; 16) "#"
18 TOKEN_TREE@[16; 19) 18 L_BRACK@[16; 17) "["
19 L_BRACK@[16; 17) "[" 19 PATH@[17; 18)
20 IDENT@[17; 18) "A" 20 PATH_SEGMENT@[17; 18)
21 R_BRACK@[18; 19) "]" 21 NAME_REF@[17; 18)
22 IDENT@[17; 18) "A"
23 R_BRACK@[18; 19) "]"
22 WHITESPACE@[19; 20) " " 24 WHITESPACE@[19; 20) " "
23 CALL_EXPR@[20; 25) 25 CALL_EXPR@[20; 25)
24 PATH_EXPR@[20; 23) 26 PATH_EXPR@[20; 23)
@@ -34,10 +36,12 @@ SOURCE_FILE@[0; 82)
34 EXPR_STMT@[31; 42) 36 EXPR_STMT@[31; 42)
35 ATTR@[31; 35) 37 ATTR@[31; 35)
36 POUND@[31; 32) "#" 38 POUND@[31; 32) "#"
37 TOKEN_TREE@[32; 35) 39 L_BRACK@[32; 33) "["
38 L_BRACK@[32; 33) "[" 40 PATH@[33; 34)
39 IDENT@[33; 34) "B" 41 PATH_SEGMENT@[33; 34)
40 R_BRACK@[34; 35) "]" 42 NAME_REF@[33; 34)
43 IDENT@[33; 34) "B"
44 R_BRACK@[34; 35) "]"
41 WHITESPACE@[35; 36) " " 45 WHITESPACE@[35; 36) " "
42 MACRO_CALL@[36; 42) 46 MACRO_CALL@[36; 42)
43 PATH@[36; 39) 47 PATH@[36; 39)
@@ -52,17 +56,21 @@ SOURCE_FILE@[0; 82)
52 EXPR_STMT@[47; 59) 56 EXPR_STMT@[47; 59)
53 ATTR@[47; 51) 57 ATTR@[47; 51)
54 POUND@[47; 48) "#" 58 POUND@[47; 48) "#"
55 TOKEN_TREE@[48; 51) 59 L_BRACK@[48; 49) "["
56 L_BRACK@[48; 49) "[" 60 PATH@[49; 50)
57 IDENT@[49; 50) "C" 61 PATH_SEGMENT@[49; 50)
58 R_BRACK@[50; 51) "]" 62 NAME_REF@[49; 50)
63 IDENT@[49; 50) "C"
64 R_BRACK@[50; 51) "]"
59 WHITESPACE@[51; 52) " " 65 WHITESPACE@[51; 52) " "
60 ATTR@[52; 56) 66 ATTR@[52; 56)
61 POUND@[52; 53) "#" 67 POUND@[52; 53) "#"
62 TOKEN_TREE@[53; 56) 68 L_BRACK@[53; 54) "["
63 L_BRACK@[53; 54) "[" 69 PATH@[54; 55)
64 IDENT@[54; 55) "D" 70 PATH_SEGMENT@[54; 55)
65 R_BRACK@[55; 56) "]" 71 NAME_REF@[54; 55)
72 IDENT@[54; 55) "D"
73 R_BRACK@[55; 56) "]"
66 WHITESPACE@[56; 57) " " 74 WHITESPACE@[56; 57) " "
67 BLOCK_EXPR@[57; 59) 75 BLOCK_EXPR@[57; 59)
68 BLOCK@[57; 59) 76 BLOCK@[57; 59)
@@ -72,10 +80,12 @@ SOURCE_FILE@[0; 82)
72 EXPR_STMT@[64; 79) 80 EXPR_STMT@[64; 79)
73 ATTR@[64; 68) 81 ATTR@[64; 68)
74 POUND@[64; 65) "#" 82 POUND@[64; 65) "#"
75 TOKEN_TREE@[65; 68) 83 L_BRACK@[65; 66) "["
76 L_BRACK@[65; 66) "[" 84 PATH@[66; 67)
77 IDENT@[66; 67) "D" 85 PATH_SEGMENT@[66; 67)
78 R_BRACK@[67; 68) "]" 86 NAME_REF@[66; 67)
87 IDENT@[66; 67) "D"
88 R_BRACK@[67; 68) "]"
79 WHITESPACE@[68; 69) " " 89 WHITESPACE@[68; 69) " "
80 RETURN_EXPR@[69; 78) 90 RETURN_EXPR@[69; 78)
81 RETURN_KW@[69; 75) "return" 91 RETURN_KW@[69; 75) "return"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.txt b/crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.txt
index c201196ec..21f49690a 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0127_attr_on_last_expr_in_block.txt
@@ -20,10 +20,12 @@ SOURCE_FILE@[0; 47)
20 TRY_EXPR@[17; 29) 20 TRY_EXPR@[17; 29)
21 ATTR@[17; 21) 21 ATTR@[17; 21)
22 POUND@[17; 18) "#" 22 POUND@[17; 18) "#"
23 TOKEN_TREE@[18; 21) 23 L_BRACK@[18; 19) "["
24 L_BRACK@[18; 19) "[" 24 PATH@[19; 20)
25 IDENT@[19; 20) "A" 25 PATH_SEGMENT@[19; 20)
26 R_BRACK@[20; 21) "]" 26 NAME_REF@[19; 20)
27 IDENT@[19; 20) "A"
28 R_BRACK@[20; 21) "]"
27 WHITESPACE@[21; 22) " " 29 WHITESPACE@[21; 22) " "
28 MACRO_CALL@[22; 28) 30 MACRO_CALL@[22; 28)
29 PATH@[22; 25) 31 PATH@[22; 25)
@@ -41,10 +43,12 @@ SOURCE_FILE@[0; 47)
41 REF_EXPR@[36; 44) 43 REF_EXPR@[36; 44)
42 ATTR@[36; 40) 44 ATTR@[36; 40)
43 POUND@[36; 37) "#" 45 POUND@[36; 37) "#"
44 TOKEN_TREE@[37; 40) 46 L_BRACK@[37; 38) "["
45 L_BRACK@[37; 38) "[" 47 PATH@[38; 39)
46 IDENT@[38; 39) "B" 48 PATH_SEGMENT@[38; 39)
47 R_BRACK@[39; 40) "]" 49 NAME_REF@[38; 39)
50 IDENT@[38; 39) "B"
51 R_BRACK@[39; 40) "]"
48 WHITESPACE@[40; 41) " " 52 WHITESPACE@[40; 41) " "
49 AMP@[41; 42) "&" 53 AMP@[41; 42) "&"
50 TUPLE_EXPR@[42; 44) 54 TUPLE_EXPR@[42; 44)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt b/crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt
index eac4f6f30..8f2e91bdf 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0135_first_array_member_attributes.txt
@@ -29,14 +29,16 @@ SOURCE_FILE@[0; 56)
29 WHITESPACE@[24; 28) "\n " 29 WHITESPACE@[24; 28) "\n "
30 ATTR@[28; 40) 30 ATTR@[28; 40)
31 POUND@[28; 29) "#" 31 POUND@[28; 29) "#"
32 TOKEN_TREE@[29; 40) 32 L_BRACK@[29; 30) "["
33 L_BRACK@[29; 30) "[" 33 PATH@[30; 33)
34 IDENT@[30; 33) "cfg" 34 PATH_SEGMENT@[30; 33)
35 TOKEN_TREE@[33; 39) 35 NAME_REF@[30; 33)
36 L_PAREN@[33; 34) "(" 36 IDENT@[30; 33) "cfg"
37 IDENT@[34; 38) "test" 37 TOKEN_TREE@[33; 39)
38 R_PAREN@[38; 39) ")" 38 L_PAREN@[33; 34) "("
39 R_BRACK@[39; 40) "]" 39 IDENT@[34; 38) "test"
40 R_PAREN@[38; 39) ")"
41 R_BRACK@[39; 40) "]"
40 WHITESPACE@[40; 44) "\n " 42 WHITESPACE@[40; 44) "\n "
41 LITERAL@[44; 45) 43 LITERAL@[44; 45)
42 INT_NUMBER@[44; 45) "1" 44 INT_NUMBER@[44; 45) "1"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt b/crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt
index 6fa1b42d9..41914eb8e 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0136_subsequent_array_member_attributes.txt
@@ -33,14 +33,16 @@ SOURCE_FILE@[0; 56)
33 WHITESPACE@[30; 34) "\n " 33 WHITESPACE@[30; 34) "\n "
34 ATTR@[34; 46) 34 ATTR@[34; 46)
35 POUND@[34; 35) "#" 35 POUND@[34; 35) "#"
36 TOKEN_TREE@[35; 46) 36 L_BRACK@[35; 36) "["
37 L_BRACK@[35; 36) "[" 37 PATH@[36; 39)
38 IDENT@[36; 39) "cfg" 38 PATH_SEGMENT@[36; 39)
39 TOKEN_TREE@[39; 45) 39 NAME_REF@[36; 39)
40 L_PAREN@[39; 40) "(" 40 IDENT@[36; 39) "cfg"
41 IDENT@[40; 44) "test" 41 TOKEN_TREE@[39; 45)
42 R_PAREN@[44; 45) ")" 42 L_PAREN@[39; 40) "("
43 R_BRACK@[45; 46) "]" 43 IDENT@[40; 44) "test"
44 R_PAREN@[44; 45) ")"
45 R_BRACK@[45; 46) "]"
44 WHITESPACE@[46; 50) "\n " 46 WHITESPACE@[46; 50) "\n "
45 LITERAL@[50; 51) 47 LITERAL@[50; 51)
46 INT_NUMBER@[50; 51) "2" 48 INT_NUMBER@[50; 51) "2"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.txt b/crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.txt
index 708fa4773..e627b9746 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.txt
@@ -8,10 +8,12 @@ SOURCE_FILE@[0; 26)
8 L_PAREN@[4; 5) "(" 8 L_PAREN@[4; 5) "("
9 ATTR@[5; 16) 9 ATTR@[5; 16)
10 POUND@[5; 6) "#" 10 POUND@[5; 6) "#"
11 TOKEN_TREE@[6; 16) 11 L_BRACK@[6; 7) "["
12 L_BRACK@[6; 7) "[" 12 PATH@[7; 15)
13 IDENT@[7; 15) "must_use" 13 PATH_SEGMENT@[7; 15)
14 R_BRACK@[15; 16) "]" 14 NAME_REF@[7; 15)
15 IDENT@[7; 15) "must_use"
16 R_BRACK@[15; 16) "]"
15 WHITESPACE@[16; 17) " " 17 WHITESPACE@[16; 17) " "
16 SELF_PARAM@[17; 21) 18 SELF_PARAM@[17; 21)
17 SELF_KW@[17; 21) "self" 19 SELF_KW@[17; 21) "self"
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.txt b/crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.txt
index 9c0a0d20b..cf202c94b 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0139_param_outer_arg.txt
@@ -8,10 +8,12 @@ SOURCE_FILE@[0; 28)
8 L_PAREN@[4; 5) "(" 8 L_PAREN@[4; 5) "("
9 ATTR@[5; 13) 9 ATTR@[5; 13)
10 POUND@[5; 6) "#" 10 POUND@[5; 6) "#"
11 TOKEN_TREE@[6; 13) 11 L_BRACK@[6; 7) "["
12 L_BRACK@[6; 7) "[" 12 PATH@[7; 12)
13 IDENT@[7; 12) "attr1" 13 PATH_SEGMENT@[7; 12)
14 R_BRACK@[12; 13) "]" 14 NAME_REF@[7; 12)
15 IDENT@[7; 12) "attr1"
16 R_BRACK@[12; 13) "]"
15 WHITESPACE@[13; 14) " " 17 WHITESPACE@[13; 14) " "
16 PARAM@[14; 23) 18 PARAM@[14; 23)
17 BIND_PAT@[14; 17) 19 BIND_PAT@[14; 17)
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rs b/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rs
new file mode 100644
index 000000000..a06dec1fa
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.rs
@@ -0,0 +1,3 @@
1fn foo() {
2 let _ = &1 as *const i32;
3}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.txt b/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.txt
new file mode 100644
index 000000000..9e3767fb7
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0146_as_precedence.txt
@@ -0,0 +1,43 @@
1SOURCE_FILE@[0; 43)
2 FN_DEF@[0; 42)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 8)
8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 42)
12 BLOCK@[9; 42)
13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n "
15 LET_STMT@[15; 40)
16 LET_KW@[15; 18) "let"
17 WHITESPACE@[18; 19) " "
18 PLACEHOLDER_PAT@[19; 20)
19 UNDERSCORE@[19; 20) "_"
20 WHITESPACE@[20; 21) " "
21 EQ@[21; 22) "="
22 WHITESPACE@[22; 23) " "
23 CAST_EXPR@[23; 39)
24 REF_EXPR@[23; 25)
25 AMP@[23; 24) "&"
26 LITERAL@[24; 25)
27 INT_NUMBER@[24; 25) "1"
28 WHITESPACE@[25; 26) " "
29 AS_KW@[26; 28) "as"
30 WHITESPACE@[28; 29) " "
31 POINTER_TYPE@[29; 39)
32 STAR@[29; 30) "*"
33 CONST_KW@[30; 35) "const"
34 WHITESPACE@[35; 36) " "
35 PATH_TYPE@[36; 39)
36 PATH@[36; 39)
37 PATH_SEGMENT@[36; 39)
38 NAME_REF@[36; 39)
39 IDENT@[36; 39) "i32"
40 SEMI@[39; 40) ";"
41 WHITESPACE@[40; 41) "\n"
42 R_CURLY@[41; 42) "}"
43 WHITESPACE@[42; 43) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0006_inner_attributes.txt b/crates/ra_syntax/test_data/parser/ok/0006_inner_attributes.txt
index d8cabc9af..d72b72561 100644
--- a/crates/ra_syntax/test_data/parser/ok/0006_inner_attributes.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0006_inner_attributes.txt
@@ -2,163 +2,183 @@ SOURCE_FILE@[0; 236)
2 ATTR@[0; 8) 2 ATTR@[0; 8)
3 POUND@[0; 1) "#" 3 POUND@[0; 1) "#"
4 EXCL@[1; 2) "!" 4 EXCL@[1; 2) "!"
5 TOKEN_TREE@[2; 8) 5 L_BRACK@[2; 3) "["
6 L_BRACK@[2; 3) "[" 6 PATH@[3; 7)
7 IDENT@[3; 7) "attr" 7 PATH_SEGMENT@[3; 7)
8 R_BRACK@[7; 8) "]" 8 NAME_REF@[3; 7)
9 IDENT@[3; 7) "attr"
10 R_BRACK@[7; 8) "]"
9 WHITESPACE@[8; 9) "\n" 11 WHITESPACE@[8; 9) "\n"
10 ATTR@[9; 23) 12 ATTR@[9; 23)
11 POUND@[9; 10) "#" 13 POUND@[9; 10) "#"
12 EXCL@[10; 11) "!" 14 EXCL@[10; 11) "!"
13 TOKEN_TREE@[11; 23) 15 L_BRACK@[11; 12) "["
14 L_BRACK@[11; 12) "[" 16 PATH@[12; 16)
15 IDENT@[12; 16) "attr" 17 PATH_SEGMENT@[12; 16)
16 TOKEN_TREE@[16; 22) 18 NAME_REF@[12; 16)
17 L_PAREN@[16; 17) "(" 19 IDENT@[12; 16) "attr"
18 TRUE_KW@[17; 21) "true" 20 TOKEN_TREE@[16; 22)
19 R_PAREN@[21; 22) ")" 21 L_PAREN@[16; 17) "("
20 R_BRACK@[22; 23) "]" 22 TRUE_KW@[17; 21) "true"
23 R_PAREN@[21; 22) ")"
24 R_BRACK@[22; 23) "]"
21 WHITESPACE@[23; 24) "\n" 25 WHITESPACE@[23; 24) "\n"
22 ATTR@[24; 39) 26 ATTR@[24; 39)
23 POUND@[24; 25) "#" 27 POUND@[24; 25) "#"
24 EXCL@[25; 26) "!" 28 EXCL@[25; 26) "!"
25 TOKEN_TREE@[26; 39) 29 L_BRACK@[26; 27) "["
26 L_BRACK@[26; 27) "[" 30 PATH@[27; 31)
27 IDENT@[27; 31) "attr" 31 PATH_SEGMENT@[27; 31)
28 TOKEN_TREE@[31; 38) 32 NAME_REF@[27; 31)
29 L_PAREN@[31; 32) "(" 33 IDENT@[27; 31) "attr"
30 IDENT@[32; 37) "ident" 34 TOKEN_TREE@[31; 38)
31 R_PAREN@[37; 38) ")" 35 L_PAREN@[31; 32) "("
32 R_BRACK@[38; 39) "]" 36 IDENT@[32; 37) "ident"
37 R_PAREN@[37; 38) ")"
38 R_BRACK@[38; 39) "]"
33 WHITESPACE@[39; 40) "\n" 39 WHITESPACE@[39; 40) "\n"
34 ATTR@[40; 116) 40 ATTR@[40; 116)
35 POUND@[40; 41) "#" 41 POUND@[40; 41) "#"
36 EXCL@[41; 42) "!" 42 EXCL@[41; 42) "!"
37 TOKEN_TREE@[42; 116) 43 L_BRACK@[42; 43) "["
38 L_BRACK@[42; 43) "[" 44 PATH@[43; 47)
39 IDENT@[43; 47) "attr" 45 PATH_SEGMENT@[43; 47)
40 TOKEN_TREE@[47; 115) 46 NAME_REF@[43; 47)
41 L_PAREN@[47; 48) "(" 47 IDENT@[43; 47) "attr"
42 IDENT@[48; 53) "ident" 48 TOKEN_TREE@[47; 115)
43 COMMA@[53; 54) "," 49 L_PAREN@[47; 48) "("
44 WHITESPACE@[54; 55) " " 50 IDENT@[48; 53) "ident"
45 INT_NUMBER@[55; 58) "100" 51 COMMA@[53; 54) ","
46 COMMA@[58; 59) "," 52 WHITESPACE@[54; 55) " "
47 WHITESPACE@[59; 60) " " 53 INT_NUMBER@[55; 58) "100"
48 TRUE_KW@[60; 64) "true" 54 COMMA@[58; 59) ","
49 COMMA@[64; 65) "," 55 WHITESPACE@[59; 60) " "
50 WHITESPACE@[65; 66) " " 56 TRUE_KW@[60; 64) "true"
51 STRING@[66; 72) "\"true\"" 57 COMMA@[64; 65) ","
52 COMMA@[72; 73) "," 58 WHITESPACE@[65; 66) " "
53 WHITESPACE@[73; 74) " " 59 STRING@[66; 72) "\"true\""
54 IDENT@[74; 79) "ident" 60 COMMA@[72; 73) ","
55 WHITESPACE@[79; 80) " " 61 WHITESPACE@[73; 74) " "
56 EQ@[80; 81) "=" 62 IDENT@[74; 79) "ident"
57 WHITESPACE@[81; 82) " " 63 WHITESPACE@[79; 80) " "
58 INT_NUMBER@[82; 85) "100" 64 EQ@[80; 81) "="
59 COMMA@[85; 86) "," 65 WHITESPACE@[81; 82) " "
60 WHITESPACE@[86; 87) " " 66 INT_NUMBER@[82; 85) "100"
61 IDENT@[87; 92) "ident" 67 COMMA@[85; 86) ","
62 WHITESPACE@[92; 93) " " 68 WHITESPACE@[86; 87) " "
63 EQ@[93; 94) "=" 69 IDENT@[87; 92) "ident"
64 WHITESPACE@[94; 95) " " 70 WHITESPACE@[92; 93) " "
65 STRING@[95; 102) "\"hello\"" 71 EQ@[93; 94) "="
66 COMMA@[102; 103) "," 72 WHITESPACE@[94; 95) " "
67 WHITESPACE@[103; 104) " " 73 STRING@[95; 102) "\"hello\""
68 IDENT@[104; 109) "ident" 74 COMMA@[102; 103) ","
69 TOKEN_TREE@[109; 114) 75 WHITESPACE@[103; 104) " "
70 L_PAREN@[109; 110) "(" 76 IDENT@[104; 109) "ident"
71 INT_NUMBER@[110; 113) "100" 77 TOKEN_TREE@[109; 114)
72 R_PAREN@[113; 114) ")" 78 L_PAREN@[109; 110) "("
73 R_PAREN@[114; 115) ")" 79 INT_NUMBER@[110; 113) "100"
74 R_BRACK@[115; 116) "]" 80 R_PAREN@[113; 114) ")"
81 R_PAREN@[114; 115) ")"
82 R_BRACK@[115; 116) "]"
75 WHITESPACE@[116; 117) "\n" 83 WHITESPACE@[116; 117) "\n"
76 ATTR@[117; 130) 84 ATTR@[117; 130)
77 POUND@[117; 118) "#" 85 POUND@[117; 118) "#"
78 EXCL@[118; 119) "!" 86 EXCL@[118; 119) "!"
79 TOKEN_TREE@[119; 130) 87 L_BRACK@[119; 120) "["
80 L_BRACK@[119; 120) "[" 88 PATH@[120; 124)
81 IDENT@[120; 124) "attr" 89 PATH_SEGMENT@[120; 124)
82 TOKEN_TREE@[124; 129) 90 NAME_REF@[120; 124)
83 L_PAREN@[124; 125) "(" 91 IDENT@[120; 124) "attr"
84 INT_NUMBER@[125; 128) "100" 92 TOKEN_TREE@[124; 129)
85 R_PAREN@[128; 129) ")" 93 L_PAREN@[124; 125) "("
86 R_BRACK@[129; 130) "]" 94 INT_NUMBER@[125; 128) "100"
95 R_PAREN@[128; 129) ")"
96 R_BRACK@[129; 130) "]"
87 WHITESPACE@[130; 131) "\n" 97 WHITESPACE@[130; 131) "\n"
88 ATTR@[131; 155) 98 ATTR@[131; 155)
89 POUND@[131; 132) "#" 99 POUND@[131; 132) "#"
90 EXCL@[132; 133) "!" 100 EXCL@[132; 133) "!"
91 TOKEN_TREE@[133; 155) 101 L_BRACK@[133; 134) "["
92 L_BRACK@[133; 134) "[" 102 PATH@[134; 138)
93 IDENT@[134; 138) "attr" 103 PATH_SEGMENT@[134; 138)
94 TOKEN_TREE@[138; 154) 104 NAME_REF@[134; 138)
95 L_PAREN@[138; 139) "(" 105 IDENT@[134; 138) "attr"
96 IDENT@[139; 146) "enabled" 106 TOKEN_TREE@[138; 154)
97 WHITESPACE@[146; 147) " " 107 L_PAREN@[138; 139) "("
98 EQ@[147; 148) "=" 108 IDENT@[139; 146) "enabled"
99 WHITESPACE@[148; 149) " " 109 WHITESPACE@[146; 147) " "
100 TRUE_KW@[149; 153) "true" 110 EQ@[147; 148) "="
101 R_PAREN@[153; 154) ")" 111 WHITESPACE@[148; 149) " "
102 R_BRACK@[154; 155) "]" 112 TRUE_KW@[149; 153) "true"
113 R_PAREN@[153; 154) ")"
114 R_BRACK@[154; 155) "]"
103 WHITESPACE@[155; 156) "\n" 115 WHITESPACE@[155; 156) "\n"
104 ATTR@[156; 173) 116 ATTR@[156; 173)
105 POUND@[156; 157) "#" 117 POUND@[156; 157) "#"
106 EXCL@[157; 158) "!" 118 EXCL@[157; 158) "!"
107 TOKEN_TREE@[158; 173) 119 L_BRACK@[158; 159) "["
108 L_BRACK@[158; 159) "[" 120 PATH@[159; 166)
109 IDENT@[159; 166) "enabled" 121 PATH_SEGMENT@[159; 166)
110 TOKEN_TREE@[166; 172) 122 NAME_REF@[159; 166)
111 L_PAREN@[166; 167) "(" 123 IDENT@[159; 166) "enabled"
112 TRUE_KW@[167; 171) "true" 124 TOKEN_TREE@[166; 172)
113 R_PAREN@[171; 172) ")" 125 L_PAREN@[166; 167) "("
114 R_BRACK@[172; 173) "]" 126 TRUE_KW@[167; 171) "true"
127 R_PAREN@[171; 172) ")"
128 R_BRACK@[172; 173) "]"
115 WHITESPACE@[173; 174) "\n" 129 WHITESPACE@[173; 174) "\n"
116 ATTR@[174; 191) 130 ATTR@[174; 191)
117 POUND@[174; 175) "#" 131 POUND@[174; 175) "#"
118 EXCL@[175; 176) "!" 132 EXCL@[175; 176) "!"
119 TOKEN_TREE@[176; 191) 133 L_BRACK@[176; 177) "["
120 L_BRACK@[176; 177) "[" 134 PATH@[177; 181)
121 IDENT@[177; 181) "attr" 135 PATH_SEGMENT@[177; 181)
122 TOKEN_TREE@[181; 190) 136 NAME_REF@[177; 181)
123 L_PAREN@[181; 182) "(" 137 IDENT@[177; 181) "attr"
124 STRING@[182; 189) "\"hello\"" 138 TOKEN_TREE@[181; 190)
125 R_PAREN@[189; 190) ")" 139 L_PAREN@[181; 182) "("
126 R_BRACK@[190; 191) "]" 140 STRING@[182; 189) "\"hello\""
141 R_PAREN@[189; 190) ")"
142 R_BRACK@[190; 191) "]"
127 WHITESPACE@[191; 192) "\n" 143 WHITESPACE@[191; 192) "\n"
128 ATTR@[192; 214) 144 ATTR@[192; 214)
129 POUND@[192; 193) "#" 145 POUND@[192; 193) "#"
130 EXCL@[193; 194) "!" 146 EXCL@[193; 194) "!"
131 TOKEN_TREE@[194; 214) 147 L_BRACK@[194; 195) "["
132 L_BRACK@[194; 195) "[" 148 PATH@[195; 199)
133 IDENT@[195; 199) "repr" 149 PATH_SEGMENT@[195; 199)
134 TOKEN_TREE@[199; 213) 150 NAME_REF@[195; 199)
135 L_PAREN@[199; 200) "(" 151 IDENT@[195; 199) "repr"
136 IDENT@[200; 201) "C" 152 TOKEN_TREE@[199; 213)
137 COMMA@[201; 202) "," 153 L_PAREN@[199; 200) "("
138 WHITESPACE@[202; 203) " " 154 IDENT@[200; 201) "C"
139 IDENT@[203; 208) "align" 155 COMMA@[201; 202) ","
140 WHITESPACE@[208; 209) " " 156 WHITESPACE@[202; 203) " "
141 EQ@[209; 210) "=" 157 IDENT@[203; 208) "align"
142 WHITESPACE@[210; 211) " " 158 WHITESPACE@[208; 209) " "
143 INT_NUMBER@[211; 212) "4" 159 EQ@[209; 210) "="
144 R_PAREN@[212; 213) ")" 160 WHITESPACE@[210; 211) " "
145 R_BRACK@[213; 214) "]" 161 INT_NUMBER@[211; 212) "4"
162 R_PAREN@[212; 213) ")"
163 R_BRACK@[213; 214) "]"
146 WHITESPACE@[214; 215) "\n" 164 WHITESPACE@[214; 215) "\n"
147 ATTR@[215; 236) 165 ATTR@[215; 236)
148 POUND@[215; 216) "#" 166 POUND@[215; 216) "#"
149 EXCL@[216; 217) "!" 167 EXCL@[216; 217) "!"
150 TOKEN_TREE@[217; 236) 168 L_BRACK@[217; 218) "["
151 L_BRACK@[217; 218) "[" 169 PATH@[218; 222)
152 IDENT@[218; 222) "repr" 170 PATH_SEGMENT@[218; 222)
153 TOKEN_TREE@[222; 235) 171 NAME_REF@[218; 222)
154 L_PAREN@[222; 223) "(" 172 IDENT@[218; 222) "repr"
155 IDENT@[223; 224) "C" 173 TOKEN_TREE@[222; 235)
156 COMMA@[224; 225) "," 174 L_PAREN@[222; 223) "("
157 WHITESPACE@[225; 226) " " 175 IDENT@[223; 224) "C"
158 IDENT@[226; 231) "align" 176 COMMA@[224; 225) ","
159 TOKEN_TREE@[231; 234) 177 WHITESPACE@[225; 226) " "
160 L_PAREN@[231; 232) "(" 178 IDENT@[226; 231) "align"
161 INT_NUMBER@[232; 233) "4" 179 TOKEN_TREE@[231; 234)
162 R_PAREN@[233; 234) ")" 180 L_PAREN@[231; 232) "("
163 R_PAREN@[234; 235) ")" 181 INT_NUMBER@[232; 233) "4"
164 R_BRACK@[235; 236) "]" 182 R_PAREN@[233; 234) ")"
183 R_PAREN@[234; 235) ")"
184 R_BRACK@[235; 236) "]"
diff --git a/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt b/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
index 35465632d..061019a73 100644
--- a/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0008_mod_item.txt
@@ -65,10 +65,12 @@ SOURCE_FILE@[0; 118)
65 ATTR@[79; 87) 65 ATTR@[79; 87)
66 POUND@[79; 80) "#" 66 POUND@[79; 80) "#"
67 EXCL@[80; 81) "!" 67 EXCL@[80; 81) "!"
68 TOKEN_TREE@[81; 87) 68 L_BRACK@[81; 82) "["
69 L_BRACK@[81; 82) "[" 69 PATH@[82; 86)
70 IDENT@[82; 86) "attr" 70 PATH_SEGMENT@[82; 86)
71 R_BRACK@[86; 87) "]" 71 NAME_REF@[82; 86)
72 IDENT@[82; 86) "attr"
73 R_BRACK@[86; 87) "]"
72 WHITESPACE@[87; 92) "\n " 74 WHITESPACE@[87; 92) "\n "
73 MODULE@[92; 98) 75 MODULE@[92; 98)
74 MOD_KW@[92; 95) "mod" 76 MOD_KW@[92; 95) "mod"
diff --git a/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rs b/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rs
index 8b80c0d90..3d2e01d5c 100644
--- a/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rs
+++ b/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.rs
@@ -1,3 +1,6 @@
1#[cfg(test)] 1#[cfg(test)]
2#[ignore] 2#[ignore]
3fn foo() {} 3fn foo() {}
4
5#[path = "a.rs"]
6mod b;
diff --git a/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.txt b/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.txt
index a845c5c24..f7aa8afe4 100644
--- a/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0011_outer_attribute.txt
@@ -1,22 +1,26 @@
1SOURCE_FILE@[0; 35) 1SOURCE_FILE@[0; 60)
2 FN_DEF@[0; 34) 2 FN_DEF@[0; 34)
3 ATTR@[0; 12) 3 ATTR@[0; 12)
4 POUND@[0; 1) "#" 4 POUND@[0; 1) "#"
5 TOKEN_TREE@[1; 12) 5 L_BRACK@[1; 2) "["
6 L_BRACK@[1; 2) "[" 6 PATH@[2; 5)
7 IDENT@[2; 5) "cfg" 7 PATH_SEGMENT@[2; 5)
8 TOKEN_TREE@[5; 11) 8 NAME_REF@[2; 5)
9 L_PAREN@[5; 6) "(" 9 IDENT@[2; 5) "cfg"
10 IDENT@[6; 10) "test" 10 TOKEN_TREE@[5; 11)
11 R_PAREN@[10; 11) ")" 11 L_PAREN@[5; 6) "("
12 R_BRACK@[11; 12) "]" 12 IDENT@[6; 10) "test"
13 R_PAREN@[10; 11) ")"
14 R_BRACK@[11; 12) "]"
13 WHITESPACE@[12; 13) "\n" 15 WHITESPACE@[12; 13) "\n"
14 ATTR@[13; 22) 16 ATTR@[13; 22)
15 POUND@[13; 14) "#" 17 POUND@[13; 14) "#"
16 TOKEN_TREE@[14; 22) 18 L_BRACK@[14; 15) "["
17 L_BRACK@[14; 15) "[" 19 PATH@[15; 21)
18 IDENT@[15; 21) "ignore" 20 PATH_SEGMENT@[15; 21)
19 R_BRACK@[21; 22) "]" 21 NAME_REF@[15; 21)
22 IDENT@[15; 21) "ignore"
23 R_BRACK@[21; 22) "]"
20 WHITESPACE@[22; 23) "\n" 24 WHITESPACE@[22; 23) "\n"
21 FN_KW@[23; 25) "fn" 25 FN_KW@[23; 25) "fn"
22 WHITESPACE@[25; 26) " " 26 WHITESPACE@[25; 26) " "
@@ -30,4 +34,25 @@ SOURCE_FILE@[0; 35)
30 BLOCK@[32; 34) 34 BLOCK@[32; 34)
31 L_CURLY@[32; 33) "{" 35 L_CURLY@[32; 33) "{"
32 R_CURLY@[33; 34) "}" 36 R_CURLY@[33; 34) "}"
33 WHITESPACE@[34; 35) "\n" 37 WHITESPACE@[34; 36) "\n\n"
38 MODULE@[36; 59)
39 ATTR@[36; 52)
40 POUND@[36; 37) "#"
41 L_BRACK@[37; 38) "["
42 PATH@[38; 42)
43 PATH_SEGMENT@[38; 42)
44 NAME_REF@[38; 42)
45 IDENT@[38; 42) "path"
46 WHITESPACE@[42; 43) " "
47 EQ@[43; 44) "="
48 WHITESPACE@[44; 45) " "
49 LITERAL@[45; 51)
50 STRING@[45; 51) "\"a.rs\""
51 R_BRACK@[51; 52) "]"
52 WHITESPACE@[52; 53) "\n"
53 MOD_KW@[53; 56) "mod"
54 WHITESPACE@[56; 57) " "
55 NAME@[57; 58)
56 IDENT@[57; 58) "b"
57 SEMI@[58; 59) ";"
58 WHITESPACE@[59; 60) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.txt b/crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.txt
index a1084b221..1d65b0d6e 100644
--- a/crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0017_attr_trailing_comma.txt
@@ -2,15 +2,17 @@ SOURCE_FILE@[0; 23)
2 FN_DEF@[0; 22) 2 FN_DEF@[0; 22)
3 ATTR@[0; 10) 3 ATTR@[0; 10)
4 POUND@[0; 1) "#" 4 POUND@[0; 1) "#"
5 TOKEN_TREE@[1; 10) 5 L_BRACK@[1; 2) "["
6 L_BRACK@[1; 2) "[" 6 PATH@[2; 5)
7 IDENT@[2; 5) "foo" 7 PATH_SEGMENT@[2; 5)
8 TOKEN_TREE@[5; 9) 8 NAME_REF@[2; 5)
9 L_PAREN@[5; 6) "(" 9 IDENT@[2; 5) "foo"
10 IDENT@[6; 7) "a" 10 TOKEN_TREE@[5; 9)
11 COMMA@[7; 8) "," 11 L_PAREN@[5; 6) "("
12 R_PAREN@[8; 9) ")" 12 IDENT@[6; 7) "a"
13 R_BRACK@[9; 10) "]" 13 COMMA@[7; 8) ","
14 R_PAREN@[8; 9) ")"
15 R_BRACK@[9; 10) "]"
14 WHITESPACE@[10; 11) "\n" 16 WHITESPACE@[10; 11) "\n"
15 FN_KW@[11; 13) "fn" 17 FN_KW@[11; 13) "fn"
16 WHITESPACE@[13; 14) " " 18 WHITESPACE@[13; 14) " "
diff --git a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
index 3326ab2ae..3260cc589 100644
--- a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
@@ -10,62 +10,73 @@ SOURCE_FILE@[0; 3813)
10 ATTR@[271; 302) 10 ATTR@[271; 302)
11 POUND@[271; 272) "#" 11 POUND@[271; 272) "#"
12 EXCL@[272; 273) "!" 12 EXCL@[272; 273) "!"
13 TOKEN_TREE@[273; 302) 13 L_BRACK@[273; 274) "["
14 L_BRACK@[273; 274) "[" 14 PATH@[274; 279)
15 IDENT@[274; 279) "allow" 15 PATH_SEGMENT@[274; 279)
16 TOKEN_TREE@[279; 301) 16 NAME_REF@[274; 279)
17 L_PAREN@[279; 280) "(" 17 IDENT@[274; 279) "allow"
18 IDENT@[280; 300) "non_camel_case_types" 18 TOKEN_TREE@[279; 301)
19 R_PAREN@[300; 301) ")" 19 L_PAREN@[279; 280) "("
20 R_BRACK@[301; 302) "]" 20 IDENT@[280; 300) "non_camel_case_types"
21 R_PAREN@[300; 301) ")"
22 R_BRACK@[301; 302) "]"
21 WHITESPACE@[302; 303) "\n" 23 WHITESPACE@[302; 303) "\n"
22 ATTR@[303; 323) 24 ATTR@[303; 323)
23 POUND@[303; 304) "#" 25 POUND@[303; 304) "#"
24 EXCL@[304; 305) "!" 26 EXCL@[304; 305) "!"
25 TOKEN_TREE@[305; 323) 27 L_BRACK@[305; 306) "["
26 L_BRACK@[305; 306) "[" 28 PATH@[306; 311)
27 IDENT@[306; 311) "allow" 29 PATH_SEGMENT@[306; 311)
28 TOKEN_TREE@[311; 322) 30 NAME_REF@[306; 311)
29 L_PAREN@[311; 312) "(" 31 IDENT@[306; 311) "allow"
30 IDENT@[312; 321) "dead_code" 32 TOKEN_TREE@[311; 322)
31 R_PAREN@[321; 322) ")" 33 L_PAREN@[311; 312) "("
32 R_BRACK@[322; 323) "]" 34 IDENT@[312; 321) "dead_code"
35 R_PAREN@[321; 322) ")"
36 R_BRACK@[322; 323) "]"
33 WHITESPACE@[323; 324) "\n" 37 WHITESPACE@[323; 324) "\n"
34 ATTR@[324; 351) 38 ATTR@[324; 351)
35 POUND@[324; 325) "#" 39 POUND@[324; 325) "#"
36 EXCL@[325; 326) "!" 40 EXCL@[325; 326) "!"
37 TOKEN_TREE@[326; 351) 41 L_BRACK@[326; 327) "["
38 L_BRACK@[326; 327) "[" 42 PATH@[327; 332)
39 IDENT@[327; 332) "allow" 43 PATH_SEGMENT@[327; 332)
40 TOKEN_TREE@[332; 350) 44 NAME_REF@[327; 332)
41 L_PAREN@[332; 333) "(" 45 IDENT@[327; 332) "allow"
42 IDENT@[333; 349) "unreachable_code" 46 TOKEN_TREE@[332; 350)
43 R_PAREN@[349; 350) ")" 47 L_PAREN@[332; 333) "("
44 R_BRACK@[350; 351) "]" 48 IDENT@[333; 349) "unreachable_code"
49 R_PAREN@[349; 350) ")"
50 R_BRACK@[350; 351) "]"
45 WHITESPACE@[351; 352) "\n" 51 WHITESPACE@[351; 352) "\n"
46 ATTR@[352; 376) 52 ATTR@[352; 376)
47 POUND@[352; 353) "#" 53 POUND@[352; 353) "#"
48 EXCL@[353; 354) "!" 54 EXCL@[353; 354) "!"
49 TOKEN_TREE@[354; 376) 55 L_BRACK@[354; 355) "["
50 L_BRACK@[354; 355) "[" 56 PATH@[355; 360)
51 IDENT@[355; 360) "allow" 57 PATH_SEGMENT@[355; 360)
52 TOKEN_TREE@[360; 375) 58 NAME_REF@[355; 360)
53 L_PAREN@[360; 361) "(" 59 IDENT@[355; 360) "allow"
54 IDENT@[361; 374) "unused_parens" 60 TOKEN_TREE@[360; 375)
55 R_PAREN@[374; 375) ")" 61 L_PAREN@[360; 361) "("
56 R_BRACK@[375; 376) "]" 62 IDENT@[361; 374) "unused_parens"
63 R_PAREN@[374; 375) ")"
64 R_BRACK@[375; 376) "]"
57 WHITESPACE@[376; 378) "\n\n" 65 WHITESPACE@[376; 378) "\n\n"
58 ATTR@[378; 405) 66 ATTR@[378; 405)
59 POUND@[378; 379) "#" 67 POUND@[378; 379) "#"
60 EXCL@[379; 380) "!" 68 EXCL@[379; 380) "!"
61 TOKEN_TREE@[380; 405) 69 L_BRACK@[380; 381) "["
62 L_BRACK@[380; 381) "[" 70 PATH@[381; 396)
63 IDENT@[381; 396) "recursion_limit" 71 PATH_SEGMENT@[381; 396)
64 WHITESPACE@[396; 397) " " 72 NAME_REF@[381; 396)
65 EQ@[397; 398) "=" 73 IDENT@[381; 396) "recursion_limit"
66 WHITESPACE@[398; 399) " " 74 WHITESPACE@[396; 397) " "
75 EQ@[397; 398) "="
76 WHITESPACE@[398; 399) " "
77 LITERAL@[399; 404)
67 STRING@[399; 404) "\"128\"" 78 STRING@[399; 404) "\"128\""
68 R_BRACK@[404; 405) "]" 79 R_BRACK@[404; 405) "]"
69 WHITESPACE@[405; 407) "\n\n" 80 WHITESPACE@[405; 407) "\n\n"
70 USE_ITEM@[407; 427) 81 USE_ITEM@[407; 427)
71 USE_KW@[407; 410) "use" 82 USE_KW@[407; 410) "use"
diff --git a/crates/ra_syntax/test_data/parser/ok/0044_let_attrs.txt b/crates/ra_syntax/test_data/parser/ok/0044_let_attrs.txt
index 7dabe535f..bfc793dc1 100644
--- a/crates/ra_syntax/test_data/parser/ok/0044_let_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0044_let_attrs.txt
@@ -17,18 +17,20 @@ SOURCE_FILE@[0; 166)
17 LET_STMT@[77; 163) 17 LET_STMT@[77; 163)
18 ATTR@[77; 106) 18 ATTR@[77; 106)
19 POUND@[77; 78) "#" 19 POUND@[77; 78) "#"
20 TOKEN_TREE@[78; 106) 20 L_BRACK@[78; 79) "["
21 L_BRACK@[78; 79) "[" 21 PATH@[79; 82)
22 IDENT@[79; 82) "cfg" 22 PATH_SEGMENT@[79; 82)
23 TOKEN_TREE@[82; 105) 23 NAME_REF@[79; 82)
24 L_PAREN@[82; 83) "(" 24 IDENT@[79; 82) "cfg"
25 IDENT@[83; 90) "feature" 25 TOKEN_TREE@[82; 105)
26 WHITESPACE@[90; 91) " " 26 L_PAREN@[82; 83) "("
27 EQ@[91; 92) "=" 27 IDENT@[83; 90) "feature"
28 WHITESPACE@[92; 93) " " 28 WHITESPACE@[90; 91) " "
29 STRING@[93; 104) "\"backtrace\"" 29 EQ@[91; 92) "="
30 R_PAREN@[104; 105) ")" 30 WHITESPACE@[92; 93) " "
31 R_BRACK@[105; 106) "]" 31 STRING@[93; 104) "\"backtrace\""
32 R_PAREN@[104; 105) ")"
33 R_BRACK@[105; 106) "]"
32 WHITESPACE@[106; 111) "\n " 34 WHITESPACE@[106; 111) "\n "
33 LET_KW@[111; 114) "let" 35 LET_KW@[111; 114) "let"
34 WHITESPACE@[114; 115) " " 36 WHITESPACE@[114; 115) " "
diff --git a/crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.txt b/crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.txt
index e8be8203b..3d9aab500 100644
--- a/crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0045_block_inner_attrs.txt
@@ -15,14 +15,16 @@ SOURCE_FILE@[0; 686)
15 ATTR@[17; 57) 15 ATTR@[17; 57)
16 POUND@[17; 18) "#" 16 POUND@[17; 18) "#"
17 EXCL@[18; 19) "!" 17 EXCL@[18; 19) "!"
18 TOKEN_TREE@[19; 57) 18 L_BRACK@[19; 20) "["
19 L_BRACK@[19; 20) "[" 19 PATH@[20; 23)
20 IDENT@[20; 23) "doc" 20 PATH_SEGMENT@[20; 23)
21 TOKEN_TREE@[23; 56) 21 NAME_REF@[20; 23)
22 L_PAREN@[23; 24) "(" 22 IDENT@[20; 23) "doc"
23 STRING@[24; 55) "\"Inner attributes all ..." 23 TOKEN_TREE@[23; 56)
24 R_PAREN@[55; 56) ")" 24 L_PAREN@[23; 24) "("
25 R_BRACK@[56; 57) "]" 25 STRING@[24; 55) "\"Inner attributes all ..."
26 R_PAREN@[55; 56) ")"
27 R_BRACK@[56; 57) "]"
26 WHITESPACE@[57; 62) "\n " 28 WHITESPACE@[57; 62) "\n "
27 COMMENT@[62; 97) "//! As are ModuleDoc ..." 29 COMMENT@[62; 97) "//! As are ModuleDoc ..."
28 WHITESPACE@[97; 102) "\n " 30 WHITESPACE@[97; 102) "\n "
@@ -34,26 +36,30 @@ SOURCE_FILE@[0; 686)
34 ATTR@[112; 180) 36 ATTR@[112; 180)
35 POUND@[112; 113) "#" 37 POUND@[112; 113) "#"
36 EXCL@[113; 114) "!" 38 EXCL@[113; 114) "!"
37 TOKEN_TREE@[114; 180) 39 L_BRACK@[114; 115) "["
38 L_BRACK@[114; 115) "[" 40 PATH@[115; 118)
39 IDENT@[115; 118) "doc" 41 PATH_SEGMENT@[115; 118)
40 TOKEN_TREE@[118; 179) 42 NAME_REF@[115; 118)
41 L_PAREN@[118; 119) "(" 43 IDENT@[115; 118) "doc"
42 STRING@[119; 178) "\"Inner attributes are ..." 44 TOKEN_TREE@[118; 179)
43 R_PAREN@[178; 179) ")" 45 L_PAREN@[118; 119) "("
44 R_BRACK@[179; 180) "]" 46 STRING@[119; 178) "\"Inner attributes are ..."
47 R_PAREN@[178; 179) ")"
48 R_BRACK@[179; 180) "]"
45 WHITESPACE@[180; 189) "\n " 49 WHITESPACE@[180; 189) "\n "
46 ATTR@[189; 244) 50 ATTR@[189; 244)
47 POUND@[189; 190) "#" 51 POUND@[189; 190) "#"
48 EXCL@[190; 191) "!" 52 EXCL@[190; 191) "!"
49 TOKEN_TREE@[191; 244) 53 L_BRACK@[191; 192) "["
50 L_BRACK@[191; 192) "[" 54 PATH@[192; 195)
51 IDENT@[192; 195) "doc" 55 PATH_SEGMENT@[192; 195)
52 TOKEN_TREE@[195; 243) 56 NAME_REF@[192; 195)
53 L_PAREN@[195; 196) "(" 57 IDENT@[192; 195) "doc"
54 STRING@[196; 242) "\"Being validated is n ..." 58 TOKEN_TREE@[195; 243)
55 R_PAREN@[242; 243) ")" 59 L_PAREN@[195; 196) "("
56 R_BRACK@[243; 244) "]" 60 STRING@[196; 242) "\"Being validated is n ..."
61 R_PAREN@[242; 243) ")"
62 R_BRACK@[243; 244) "]"
57 WHITESPACE@[244; 253) "\n " 63 WHITESPACE@[244; 253) "\n "
58 COMMENT@[253; 288) "//! As are ModuleDoc ..." 64 COMMENT@[253; 288) "//! As are ModuleDoc ..."
59 WHITESPACE@[288; 293) "\n " 65 WHITESPACE@[288; 293) "\n "
@@ -67,14 +73,16 @@ SOURCE_FILE@[0; 686)
67 ATTR@[310; 409) 73 ATTR@[310; 409)
68 POUND@[310; 311) "#" 74 POUND@[310; 311) "#"
69 EXCL@[311; 312) "!" 75 EXCL@[311; 312) "!"
70 TOKEN_TREE@[312; 409) 76 L_BRACK@[312; 313) "["
71 L_BRACK@[312; 313) "[" 77 PATH@[313; 316)
72 IDENT@[313; 316) "doc" 78 PATH_SEGMENT@[313; 316)
73 TOKEN_TREE@[316; 408) 79 NAME_REF@[313; 316)
74 L_PAREN@[316; 317) "(" 80 IDENT@[313; 316) "doc"
75 STRING@[317; 407) "\"Inner attributes are ..." 81 TOKEN_TREE@[316; 408)
76 R_PAREN@[407; 408) ")" 82 L_PAREN@[316; 317) "("
77 R_BRACK@[408; 409) "]" 83 STRING@[317; 407) "\"Inner attributes are ..."
84 R_PAREN@[407; 408) ")"
85 R_BRACK@[408; 409) "]"
78 WHITESPACE@[409; 418) "\n " 86 WHITESPACE@[409; 418) "\n "
79 COMMENT@[418; 453) "//! As are ModuleDoc ..." 87 COMMENT@[418; 453) "//! As are ModuleDoc ..."
80 WHITESPACE@[453; 458) "\n " 88 WHITESPACE@[453; 458) "\n "
@@ -154,14 +162,16 @@ SOURCE_FILE@[0; 686)
154 ATTR@[612; 639) 162 ATTR@[612; 639)
155 POUND@[612; 613) "#" 163 POUND@[612; 613) "#"
156 EXCL@[613; 614) "!" 164 EXCL@[613; 614) "!"
157 TOKEN_TREE@[614; 639) 165 L_BRACK@[614; 615) "["
158 L_BRACK@[614; 615) "[" 166 PATH@[615; 620)
159 IDENT@[615; 620) "allow" 167 PATH_SEGMENT@[615; 620)
160 TOKEN_TREE@[620; 638) 168 NAME_REF@[615; 620)
161 L_PAREN@[620; 621) "(" 169 IDENT@[615; 620) "allow"
162 IDENT@[621; 637) "unused_variables" 170 TOKEN_TREE@[620; 638)
163 R_PAREN@[637; 638) ")" 171 L_PAREN@[620; 621) "("
164 R_BRACK@[638; 639) "]" 172 IDENT@[621; 637) "unused_variables"
173 R_PAREN@[637; 638) ")"
174 R_BRACK@[638; 639) "]"
165 WHITESPACE@[639; 640) " " 175 WHITESPACE@[639; 640) " "
166 COMMENT@[640; 677) "// this is `inner_at ..." 176 COMMENT@[640; 677) "// this is `inner_at ..."
167 WHITESPACE@[677; 682) "\n " 177 WHITESPACE@[677; 682) "\n "
diff --git a/crates/ra_syntax/test_data/parser/ok/0046_extern_inner_attributes.txt b/crates/ra_syntax/test_data/parser/ok/0046_extern_inner_attributes.txt
index 4487a6e2e..8f192124b 100644
--- a/crates/ra_syntax/test_data/parser/ok/0046_extern_inner_attributes.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0046_extern_inner_attributes.txt
@@ -13,14 +13,16 @@ SOURCE_FILE@[0; 87)
13 ATTR@[47; 84) 13 ATTR@[47; 84)
14 POUND@[47; 48) "#" 14 POUND@[47; 48) "#"
15 EXCL@[48; 49) "!" 15 EXCL@[48; 49) "!"
16 TOKEN_TREE@[49; 84) 16 L_BRACK@[49; 50) "["
17 L_BRACK@[49; 50) "[" 17 PATH@[50; 53)
18 IDENT@[50; 53) "doc" 18 PATH_SEGMENT@[50; 53)
19 TOKEN_TREE@[53; 83) 19 NAME_REF@[50; 53)
20 L_PAREN@[53; 54) "(" 20 IDENT@[50; 53) "doc"
21 STRING@[54; 82) "\"This is also a doc c ..." 21 TOKEN_TREE@[53; 83)
22 R_PAREN@[82; 83) ")" 22 L_PAREN@[53; 54) "("
23 R_BRACK@[83; 84) "]" 23 STRING@[54; 82) "\"This is also a doc c ..."
24 R_PAREN@[82; 83) ")"
25 R_BRACK@[83; 84) "]"
24 WHITESPACE@[84; 85) "\n" 26 WHITESPACE@[84; 85) "\n"
25 R_CURLY@[85; 86) "}" 27 R_CURLY@[85; 86) "}"
26 WHITESPACE@[86; 87) "\n" 28 WHITESPACE@[86; 87) "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt b/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt
index e08fb4988..bfd47d2e1 100644
--- a/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0051_parameter_attrs.txt
@@ -8,17 +8,21 @@ SOURCE_FILE@[0; 519)
8 L_PAREN@[5; 6) "(" 8 L_PAREN@[5; 6) "("
9 ATTR@[6; 14) 9 ATTR@[6; 14)
10 POUND@[6; 7) "#" 10 POUND@[6; 7) "#"
11 TOKEN_TREE@[7; 14) 11 L_BRACK@[7; 8) "["
12 L_BRACK@[7; 8) "[" 12 PATH@[8; 13)
13 IDENT@[8; 13) "attr1" 13 PATH_SEGMENT@[8; 13)
14 R_BRACK@[13; 14) "]" 14 NAME_REF@[8; 13)
15 IDENT@[8; 13) "attr1"
16 R_BRACK@[13; 14) "]"
15 WHITESPACE@[14; 15) " " 17 WHITESPACE@[14; 15) " "
16 ATTR@[15; 23) 18 ATTR@[15; 23)
17 POUND@[15; 16) "#" 19 POUND@[15; 16) "#"
18 TOKEN_TREE@[16; 23) 20 L_BRACK@[16; 17) "["
19 L_BRACK@[16; 17) "[" 21 PATH@[17; 22)
20 IDENT@[17; 22) "attr2" 22 PATH_SEGMENT@[17; 22)
21 R_BRACK@[22; 23) "]" 23 NAME_REF@[17; 22)
24 IDENT@[17; 22) "attr2"
25 R_BRACK@[22; 23) "]"
22 WHITESPACE@[23; 24) " " 26 WHITESPACE@[23; 24) " "
23 PARAM@[24; 33) 27 PARAM@[24; 33)
24 BIND_PAT@[24; 27) 28 BIND_PAT@[24; 27)
@@ -47,10 +51,12 @@ SOURCE_FILE@[0; 519)
47 L_PAREN@[43; 44) "(" 51 L_PAREN@[43; 44) "("
48 ATTR@[44; 52) 52 ATTR@[44; 52)
49 POUND@[44; 45) "#" 53 POUND@[44; 45) "#"
50 TOKEN_TREE@[45; 52) 54 L_BRACK@[45; 46) "["
51 L_BRACK@[45; 46) "[" 55 PATH@[46; 51)
52 IDENT@[46; 51) "attr1" 56 PATH_SEGMENT@[46; 51)
53 R_BRACK@[51; 52) "]" 57 NAME_REF@[46; 51)
58 IDENT@[46; 51) "attr1"
59 R_BRACK@[51; 52) "]"
54 WHITESPACE@[52; 53) " " 60 WHITESPACE@[52; 53) " "
55 PARAM@[53; 58) 61 PARAM@[53; 58)
56 BIND_PAT@[53; 54) 62 BIND_PAT@[53; 54)
@@ -105,10 +111,12 @@ SOURCE_FILE@[0; 519)
105 WHITESPACE@[105; 106) " " 111 WHITESPACE@[105; 106) " "
106 ATTR@[106; 113) 112 ATTR@[106; 113)
107 POUND@[106; 107) "#" 113 POUND@[106; 107) "#"
108 TOKEN_TREE@[107; 113) 114 L_BRACK@[107; 108) "["
109 L_BRACK@[107; 108) "[" 115 PATH@[108; 112)
110 IDENT@[108; 112) "attr" 116 PATH_SEGMENT@[108; 112)
111 R_BRACK@[112; 113) "]" 117 NAME_REF@[108; 112)
118 IDENT@[108; 112) "attr"
119 R_BRACK@[112; 113) "]"
112 WHITESPACE@[113; 114) " " 120 WHITESPACE@[113; 114) " "
113 DOTDOTDOT@[114; 117) "..." 121 DOTDOTDOT@[114; 117) "..."
114 R_PAREN@[117; 118) ")" 122 R_PAREN@[117; 118) ")"
@@ -148,10 +156,12 @@ SOURCE_FILE@[0; 519)
148 L_PAREN@[145; 146) "(" 156 L_PAREN@[145; 146) "("
149 ATTR@[146; 153) 157 ATTR@[146; 153)
150 POUND@[146; 147) "#" 158 POUND@[146; 147) "#"
151 TOKEN_TREE@[147; 153) 159 L_BRACK@[147; 148) "["
152 L_BRACK@[147; 148) "[" 160 PATH@[148; 152)
153 IDENT@[148; 152) "attr" 161 PATH_SEGMENT@[148; 152)
154 R_BRACK@[152; 153) "]" 162 NAME_REF@[148; 152)
163 IDENT@[148; 152) "attr"
164 R_BRACK@[152; 153) "]"
155 WHITESPACE@[153; 154) " " 165 WHITESPACE@[153; 154) " "
156 PARAM@[154; 166) 166 PARAM@[154; 166)
157 REFERENCE_TYPE@[154; 166) 167 REFERENCE_TYPE@[154; 166)
@@ -196,10 +206,12 @@ SOURCE_FILE@[0; 519)
196 L_PAREN@[196; 197) "(" 206 L_PAREN@[196; 197) "("
197 ATTR@[197; 204) 207 ATTR@[197; 204)
198 POUND@[197; 198) "#" 208 POUND@[197; 198) "#"
199 TOKEN_TREE@[198; 204) 209 L_BRACK@[198; 199) "["
200 L_BRACK@[198; 199) "[" 210 PATH@[199; 203)
201 IDENT@[199; 203) "attr" 211 PATH_SEGMENT@[199; 203)
202 R_BRACK@[203; 204) "]" 212 NAME_REF@[199; 203)
213 IDENT@[199; 203) "attr"
214 R_BRACK@[203; 204) "]"
203 WHITESPACE@[204; 205) " " 215 WHITESPACE@[204; 205) " "
204 PARAM@[205; 211) 216 PARAM@[205; 211)
205 PLACEHOLDER_PAT@[205; 206) 217 PLACEHOLDER_PAT@[205; 206)
@@ -216,10 +228,12 @@ SOURCE_FILE@[0; 519)
216 ATTR@[213; 221) 228 ATTR@[213; 221)
217 POUND@[213; 214) "#" 229 POUND@[213; 214) "#"
218 WHITESPACE@[214; 215) " " 230 WHITESPACE@[214; 215) " "
219 TOKEN_TREE@[215; 221) 231 L_BRACK@[215; 216) "["
220 L_BRACK@[215; 216) "[" 232 PATH@[216; 220)
221 IDENT@[216; 220) "attr" 233 PATH_SEGMENT@[216; 220)
222 R_BRACK@[220; 221) "]" 234 NAME_REF@[216; 220)
235 IDENT@[216; 220) "attr"
236 R_BRACK@[220; 221) "]"
223 WHITESPACE@[221; 222) " " 237 WHITESPACE@[221; 222) " "
224 PARAM@[222; 232) 238 PARAM@[222; 232)
225 BIND_PAT@[222; 227) 239 BIND_PAT@[222; 227)
@@ -260,10 +274,12 @@ SOURCE_FILE@[0; 519)
260 L_PAREN@[256; 257) "(" 274 L_PAREN@[256; 257) "("
261 ATTR@[257; 268) 275 ATTR@[257; 268)
262 POUND@[257; 258) "#" 276 POUND@[257; 258) "#"
263 TOKEN_TREE@[258; 268) 277 L_BRACK@[258; 259) "["
264 L_BRACK@[258; 259) "[" 278 PATH@[259; 267)
265 IDENT@[259; 267) "must_use" 279 PATH_SEGMENT@[259; 267)
266 R_BRACK@[267; 268) "]" 280 NAME_REF@[259; 267)
281 IDENT@[259; 267) "must_use"
282 R_BRACK@[267; 268) "]"
267 WHITESPACE@[268; 269) " " 283 WHITESPACE@[268; 269) " "
268 SELF_PARAM@[269; 273) 284 SELF_PARAM@[269; 273)
269 SELF_KW@[269; 273) "self" 285 SELF_KW@[269; 273) "self"
@@ -283,10 +299,12 @@ SOURCE_FILE@[0; 519)
283 L_PAREN@[288; 289) "(" 299 L_PAREN@[288; 289) "("
284 ATTR@[289; 296) 300 ATTR@[289; 296)
285 POUND@[289; 290) "#" 301 POUND@[289; 290) "#"
286 TOKEN_TREE@[290; 296) 302 L_BRACK@[290; 291) "["
287 L_BRACK@[290; 291) "[" 303 PATH@[291; 295)
288 IDENT@[291; 295) "attr" 304 PATH_SEGMENT@[291; 295)
289 R_BRACK@[295; 296) "]" 305 NAME_REF@[291; 295)
306 IDENT@[291; 295) "attr"
307 R_BRACK@[295; 296) "]"
290 WHITESPACE@[296; 297) " " 308 WHITESPACE@[296; 297) " "
291 SELF_PARAM@[297; 301) 309 SELF_PARAM@[297; 301)
292 SELF_KW@[297; 301) "self" 310 SELF_KW@[297; 301) "self"
@@ -306,10 +324,12 @@ SOURCE_FILE@[0; 519)
306 L_PAREN@[316; 317) "(" 324 L_PAREN@[316; 317) "("
307 ATTR@[317; 324) 325 ATTR@[317; 324)
308 POUND@[317; 318) "#" 326 POUND@[317; 318) "#"
309 TOKEN_TREE@[318; 324) 327 L_BRACK@[318; 319) "["
310 L_BRACK@[318; 319) "[" 328 PATH@[319; 323)
311 IDENT@[319; 323) "attr" 329 PATH_SEGMENT@[319; 323)
312 R_BRACK@[323; 324) "]" 330 NAME_REF@[319; 323)
331 IDENT@[319; 323) "attr"
332 R_BRACK@[323; 324) "]"
313 WHITESPACE@[324; 325) " " 333 WHITESPACE@[324; 325) " "
314 SELF_PARAM@[325; 330) 334 SELF_PARAM@[325; 330)
315 AMP@[325; 326) "&" 335 AMP@[325; 326) "&"
@@ -335,10 +355,12 @@ SOURCE_FILE@[0; 519)
335 L_PAREN@[349; 350) "(" 355 L_PAREN@[349; 350) "("
336 ATTR@[350; 357) 356 ATTR@[350; 357)
337 POUND@[350; 351) "#" 357 POUND@[350; 351) "#"
338 TOKEN_TREE@[351; 357) 358 L_BRACK@[351; 352) "["
339 L_BRACK@[351; 352) "[" 359 PATH@[352; 356)
340 IDENT@[352; 356) "attr" 360 PATH_SEGMENT@[352; 356)
341 R_BRACK@[356; 357) "]" 361 NAME_REF@[352; 356)
362 IDENT@[352; 356) "attr"
363 R_BRACK@[356; 357) "]"
342 WHITESPACE@[357; 358) " " 364 WHITESPACE@[357; 358) " "
343 SELF_PARAM@[358; 367) 365 SELF_PARAM@[358; 367)
344 AMP@[358; 359) "&" 366 AMP@[358; 359) "&"
@@ -366,10 +388,12 @@ SOURCE_FILE@[0; 519)
366 L_PAREN@[386; 387) "(" 388 L_PAREN@[386; 387) "("
367 ATTR@[387; 394) 389 ATTR@[387; 394)
368 POUND@[387; 388) "#" 390 POUND@[387; 388) "#"
369 TOKEN_TREE@[388; 394) 391 L_BRACK@[388; 389) "["
370 L_BRACK@[388; 389) "[" 392 PATH@[389; 393)
371 IDENT@[389; 393) "attr" 393 PATH_SEGMENT@[389; 393)
372 R_BRACK@[393; 394) "]" 394 NAME_REF@[389; 393)
395 IDENT@[389; 393) "attr"
396 R_BRACK@[393; 394) "]"
373 WHITESPACE@[394; 395) " " 397 WHITESPACE@[394; 395) " "
374 SELF_PARAM@[395; 403) 398 SELF_PARAM@[395; 403)
375 AMP@[395; 396) "&" 399 AMP@[395; 396) "&"
@@ -397,10 +421,12 @@ SOURCE_FILE@[0; 519)
397 L_PAREN@[422; 423) "(" 421 L_PAREN@[422; 423) "("
398 ATTR@[423; 430) 422 ATTR@[423; 430)
399 POUND@[423; 424) "#" 423 POUND@[423; 424) "#"
400 TOKEN_TREE@[424; 430) 424 L_BRACK@[424; 425) "["
401 L_BRACK@[424; 425) "[" 425 PATH@[425; 429)
402 IDENT@[425; 429) "attr" 426 PATH_SEGMENT@[425; 429)
403 R_BRACK@[429; 430) "]" 427 NAME_REF@[425; 429)
428 IDENT@[425; 429) "attr"
429 R_BRACK@[429; 430) "]"
404 WHITESPACE@[430; 431) " " 430 WHITESPACE@[430; 431) " "
405 SELF_PARAM@[431; 443) 431 SELF_PARAM@[431; 443)
406 AMP@[431; 432) "&" 432 AMP@[431; 432) "&"
@@ -425,10 +451,12 @@ SOURCE_FILE@[0; 519)
425 L_PAREN@[457; 458) "(" 451 L_PAREN@[457; 458) "("
426 ATTR@[458; 465) 452 ATTR@[458; 465)
427 POUND@[458; 459) "#" 453 POUND@[458; 459) "#"
428 TOKEN_TREE@[459; 465) 454 L_BRACK@[459; 460) "["
429 L_BRACK@[459; 460) "[" 455 PATH@[460; 464)
430 IDENT@[460; 464) "attr" 456 PATH_SEGMENT@[460; 464)
431 R_BRACK@[464; 465) "]" 457 NAME_REF@[460; 464)
458 IDENT@[460; 464) "attr"
459 R_BRACK@[464; 465) "]"
432 WHITESPACE@[465; 466) " " 460 WHITESPACE@[465; 466) " "
433 SELF_PARAM@[466; 476) 461 SELF_PARAM@[466; 476)
434 SELF_KW@[466; 470) "self" 462 SELF_KW@[466; 470) "self"
@@ -455,10 +483,12 @@ SOURCE_FILE@[0; 519)
455 L_PAREN@[490; 491) "(" 483 L_PAREN@[490; 491) "("
456 ATTR@[491; 498) 484 ATTR@[491; 498)
457 POUND@[491; 492) "#" 485 POUND@[491; 492) "#"
458 TOKEN_TREE@[492; 498) 486 L_BRACK@[492; 493) "["
459 L_BRACK@[492; 493) "[" 487 PATH@[493; 497)
460 IDENT@[493; 497) "attr" 488 PATH_SEGMENT@[493; 497)
461 R_BRACK@[497; 498) "]" 489 NAME_REF@[493; 497)
490 IDENT@[493; 497) "attr"
491 R_BRACK@[497; 498) "]"
462 WHITESPACE@[498; 499) " " 492 WHITESPACE@[498; 499) " "
463 SELF_PARAM@[499; 513) 493 SELF_PARAM@[499; 513)
464 SELF_KW@[499; 503) "self" 494 SELF_KW@[499; 503) "self"
diff --git a/crates/ra_syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.txt b/crates/ra_syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.txt
index f77221f76..04ff0e2ff 100644
--- a/crates/ra_syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0053_outer_attribute_on_macro_rules.txt
@@ -4,10 +4,12 @@ SOURCE_FILE@[0; 65)
4 WHITESPACE@[13; 14) "\n" 4 WHITESPACE@[13; 14) "\n"
5 ATTR@[14; 29) 5 ATTR@[14; 29)
6 POUND@[14; 15) "#" 6 POUND@[14; 15) "#"
7 TOKEN_TREE@[15; 29) 7 L_BRACK@[15; 16) "["
8 L_BRACK@[15; 16) "[" 8 PATH@[16; 28)
9 IDENT@[16; 28) "macro_export" 9 PATH_SEGMENT@[16; 28)
10 R_BRACK@[28; 29) "]" 10 NAME_REF@[16; 28)
11 IDENT@[16; 28) "macro_export"
12 R_BRACK@[28; 29) "]"
11 WHITESPACE@[29; 30) "\n" 13 WHITESPACE@[29; 30) "\n"
12 PATH@[30; 41) 14 PATH@[30; 41)
13 PATH_SEGMENT@[30; 41) 15 PATH_SEGMENT@[30; 41)
diff --git a/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rs b/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rs
new file mode 100644
index 000000000..100fccc64
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.rs
@@ -0,0 +1,7 @@
1fn foo() {
2 1 + *&2 + 3;
3 *&1 as u64;
4 *x(1);
5 &x[1];
6 -1..2;
7}
diff --git a/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.txt b/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.txt
new file mode 100644
index 000000000..d30cb63ff
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0058_unary_expr_precedence.txt
@@ -0,0 +1,97 @@
1SOURCE_FILE@[0; 79)
2 FN_DEF@[0; 78)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 8)
8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 78)
12 BLOCK@[9; 78)
13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n "
15 EXPR_STMT@[15; 27)
16 BIN_EXPR@[15; 26)
17 BIN_EXPR@[15; 22)
18 LITERAL@[15; 16)
19 INT_NUMBER@[15; 16) "1"
20 WHITESPACE@[16; 17) " "
21 PLUS@[17; 18) "+"
22 WHITESPACE@[18; 19) " "
23 PREFIX_EXPR@[19; 22)
24 STAR@[19; 20) "*"
25 REF_EXPR@[20; 22)
26 AMP@[20; 21) "&"
27 LITERAL@[21; 22)
28 INT_NUMBER@[21; 22) "2"
29 WHITESPACE@[22; 23) " "
30 PLUS@[23; 24) "+"
31 WHITESPACE@[24; 25) " "
32 LITERAL@[25; 26)
33 INT_NUMBER@[25; 26) "3"
34 SEMI@[26; 27) ";"
35 WHITESPACE@[27; 32) "\n "
36 EXPR_STMT@[32; 43)
37 CAST_EXPR@[32; 42)
38 PREFIX_EXPR@[32; 35)
39 STAR@[32; 33) "*"
40 REF_EXPR@[33; 35)
41 AMP@[33; 34) "&"
42 LITERAL@[34; 35)
43 INT_NUMBER@[34; 35) "1"
44 WHITESPACE@[35; 36) " "
45 AS_KW@[36; 38) "as"
46 WHITESPACE@[38; 39) " "
47 PATH_TYPE@[39; 42)
48 PATH@[39; 42)
49 PATH_SEGMENT@[39; 42)
50 NAME_REF@[39; 42)
51 IDENT@[39; 42) "u64"
52 SEMI@[42; 43) ";"
53 WHITESPACE@[43; 48) "\n "
54 EXPR_STMT@[48; 54)
55 PREFIX_EXPR@[48; 53)
56 STAR@[48; 49) "*"
57 CALL_EXPR@[49; 53)
58 PATH_EXPR@[49; 50)
59 PATH@[49; 50)
60 PATH_SEGMENT@[49; 50)
61 NAME_REF@[49; 50)
62 IDENT@[49; 50) "x"
63 ARG_LIST@[50; 53)
64 L_PAREN@[50; 51) "("
65 LITERAL@[51; 52)
66 INT_NUMBER@[51; 52) "1"
67 R_PAREN@[52; 53) ")"
68 SEMI@[53; 54) ";"
69 WHITESPACE@[54; 59) "\n "
70 EXPR_STMT@[59; 65)
71 REF_EXPR@[59; 64)
72 AMP@[59; 60) "&"
73 INDEX_EXPR@[60; 64)
74 PATH_EXPR@[60; 61)
75 PATH@[60; 61)
76 PATH_SEGMENT@[60; 61)
77 NAME_REF@[60; 61)
78 IDENT@[60; 61) "x"
79 L_BRACK@[61; 62) "["
80 LITERAL@[62; 63)
81 INT_NUMBER@[62; 63) "1"
82 R_BRACK@[63; 64) "]"
83 SEMI@[64; 65) ";"
84 WHITESPACE@[65; 70) "\n "
85 EXPR_STMT@[70; 76)
86 RANGE_EXPR@[70; 75)
87 PREFIX_EXPR@[70; 72)
88 MINUS@[70; 71) "-"
89 LITERAL@[71; 72)
90 INT_NUMBER@[71; 72) "1"
91 DOTDOT@[72; 74) ".."
92 LITERAL@[74; 75)
93 INT_NUMBER@[74; 75) "2"
94 SEMI@[75; 76) ";"
95 WHITESPACE@[76; 77) "\n"
96 R_CURLY@[77; 78) "}"
97 WHITESPACE@[78; 79) "\n"
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs
index df673ba18..5f1b12222 100644
--- a/crates/ra_text_edit/src/lib.rs
+++ b/crates/ra_text_edit/src/lib.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod text_edit; 3mod text_edit;
2pub mod test_utils; 4pub mod test_utils;
3 5
diff --git a/crates/ra_text_edit/src/test_utils.rs b/crates/ra_text_edit/src/test_utils.rs
index 2d6e7f216..d4c7840ff 100644
--- a/crates/ra_text_edit/src/test_utils.rs
+++ b/crates/ra_text_edit/src/test_utils.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{AtomTextEdit, TextEdit}; 3use crate::{AtomTextEdit, TextEdit};
2use proptest::prelude::*; 4use proptest::prelude::*;
3use text_unit::{TextRange, TextUnit}; 5use text_unit::{TextRange, TextUnit};
diff --git a/crates/ra_text_edit/src/text_edit.rs b/crates/ra_text_edit/src/text_edit.rs
index 8522f99bd..0381ea000 100644
--- a/crates/ra_text_edit/src/text_edit.rs
+++ b/crates/ra_text_edit/src/text_edit.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::AtomTextEdit; 3use crate::AtomTextEdit;
2use text_unit::{TextRange, TextUnit}; 4use text_unit::{TextRange, TextUnit};
3 5
diff --git a/crates/ra_tools/Cargo.toml b/crates/ra_tools/Cargo.toml
index 848ca408d..9cceacee3 100644
--- a/crates/ra_tools/Cargo.toml
+++ b/crates/ra_tools/Cargo.toml
@@ -8,7 +8,7 @@ publish = false
8[dependencies] 8[dependencies]
9walkdir = "2.1.3" 9walkdir = "2.1.3"
10itertools = "0.8.0" 10itertools = "0.8.0"
11pico-args = "0.2.0" 11pico-args = "0.3.0"
12quote = "1.0.2" 12quote = "1.0.2"
13proc-macro2 = "1.0.1" 13proc-macro2 = "1.0.1"
14ron = "0.5.1" 14ron = "0.5.1"
diff --git a/crates/ra_tools/src/bin/pre-commit.rs b/crates/ra_tools/src/bin/pre-commit.rs
index a628f64b2..16bbf9cb2 100644
--- a/crates/ra_tools/src/bin/pre-commit.rs
+++ b/crates/ra_tools/src/bin/pre-commit.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::process::Command; 3use std::process::Command;
2 4
3use ra_tools::{project_root, run, run_rustfmt, Overwrite, Result}; 5use ra_tools::{project_root, run, run_rustfmt, Overwrite, Result};
diff --git a/crates/ra_tools/src/boilerplate_gen.rs b/crates/ra_tools/src/boilerplate_gen.rs
index 1d112c0af..39f1cae66 100644
--- a/crates/ra_tools/src/boilerplate_gen.rs
+++ b/crates/ra_tools/src/boilerplate_gen.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use std::{ 3use std::{
2 collections::BTreeMap, 4 collections::BTreeMap,
3 fs, 5 fs,
@@ -282,7 +284,7 @@ fn reformat(text: impl std::fmt::Display) -> Result<String> {
282 let output = rustfmt.wait_with_output()?; 284 let output = rustfmt.wait_with_output()?;
283 let stdout = String::from_utf8(output.stdout)?; 285 let stdout = String::from_utf8(output.stdout)?;
284 let preamble = "Generated file, do not edit by hand, see `crate/ra_tools/src/codegen`"; 286 let preamble = "Generated file, do not edit by hand, see `crate/ra_tools/src/codegen`";
285 Ok(format!("// {}\n\n{}", preamble, stdout)) 287 Ok(format!("//! {}\n\n{}", preamble, stdout))
286} 288}
287 289
288#[derive(Deserialize, Debug)] 290#[derive(Deserialize, Debug)]
diff --git a/crates/ra_tools/src/help.rs b/crates/ra_tools/src/help.rs
index 9eb4dfbe4..72dfabacd 100644
--- a/crates/ra_tools/src/help.rs
+++ b/crates/ra_tools/src/help.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1pub const GLOBAL_HELP: &str = "tasks 3pub const GLOBAL_HELP: &str = "tasks
2 4
3USAGE: 5USAGE:
diff --git a/crates/ra_tools/src/lib.rs b/crates/ra_tools/src/lib.rs
index 9ba23caaa..aa993a38a 100644
--- a/crates/ra_tools/src/lib.rs
+++ b/crates/ra_tools/src/lib.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod boilerplate_gen; 3mod boilerplate_gen;
2 4
3use std::{ 5use std::{
diff --git a/crates/ra_tools/src/main.rs b/crates/ra_tools/src/main.rs
index a951ce427..161871ccf 100644
--- a/crates/ra_tools/src/main.rs
+++ b/crates/ra_tools/src/main.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1mod help; 3mod help;
2 4
3use core::fmt::Write; 5use core::fmt::Write;
diff --git a/crates/ra_tools/tests/cli.rs b/crates/ra_tools/tests/cli.rs
index 91b19c8f8..609fd4d8b 100644
--- a/crates/ra_tools/tests/cli.rs
+++ b/crates/ra_tools/tests/cli.rs
@@ -1,6 +1,5 @@
1use walkdir::WalkDir;
2
3use ra_tools::{gen_tests, generate_boilerplate, project_root, run_rustfmt, Verify}; 1use ra_tools::{gen_tests, generate_boilerplate, project_root, run_rustfmt, Verify};
2use walkdir::WalkDir;
4 3
5#[test] 4#[test]
6fn generated_grammar_is_fresh() { 5fn generated_grammar_is_fresh() {
@@ -36,7 +35,7 @@ fn no_todo() {
36 let text = std::fs::read_to_string(e.path()).unwrap(); 35 let text = std::fs::read_to_string(e.path()).unwrap();
37 if text.contains("TODO") || text.contains("TOOD") { 36 if text.contains("TODO") || text.contains("TOOD") {
38 panic!( 37 panic!(
39 "\nTODO markers should not be commited to the master branch,\n\ 38 "\nTODO markers should not be committed to the master branch,\n\
40 use FIXME instead\n\ 39 use FIXME instead\n\
41 {}\n", 40 {}\n",
42 e.path().display(), 41 e.path().display(),
diff --git a/crates/ra_tools/tests/docs.rs b/crates/ra_tools/tests/docs.rs
new file mode 100644
index 000000000..ea3330175
--- /dev/null
+++ b/crates/ra_tools/tests/docs.rs
@@ -0,0 +1,63 @@
1use std::fs;
2use std::io::prelude::*;
3use std::io::BufReader;
4use std::path::Path;
5
6use walkdir::{DirEntry, WalkDir};
7
8use ra_tools::project_root;
9
10fn is_exclude_dir(p: &Path) -> bool {
11 let exclude_dirs = ["tests", "test_data"];
12 let mut cur_path = p;
13 while let Some(path) = cur_path.parent() {
14 if exclude_dirs.iter().any(|dir| path.ends_with(dir)) {
15 return true;
16 }
17 cur_path = path;
18 }
19
20 false
21}
22
23fn is_exclude_file(d: &DirEntry) -> bool {
24 let file_names = ["tests.rs"];
25
26 d.file_name().to_str().map(|f_n| file_names.iter().any(|name| *name == f_n)).unwrap_or(false)
27}
28
29fn is_hidden(entry: &DirEntry) -> bool {
30 entry.file_name().to_str().map(|s| s.starts_with(".")).unwrap_or(false)
31}
32
33#[test]
34fn no_docs_comments() {
35 let crates = project_root().join("crates");
36 let iter = WalkDir::new(crates);
37 for f in iter.into_iter().filter_entry(|e| !is_hidden(e)) {
38 let f = f.unwrap();
39 if f.file_type().is_dir() {
40 continue;
41 }
42 if f.path().extension().map(|it| it != "rs").unwrap_or(false) {
43 continue;
44 }
45 if is_exclude_dir(f.path()) {
46 continue;
47 }
48 if is_exclude_file(&f) {
49 continue;
50 }
51 let mut reader = BufReader::new(fs::File::open(f.path()).unwrap());
52 let mut line = String::new();
53 reader.read_line(&mut line).unwrap();
54 if !line.starts_with("//!") {
55 panic!(
56 "\nMissing docs strings\n\
57 module: {}\n\
58 Need add doc for module\n",
59 f.path().display()
60 )
61 }
62 }
63}
diff --git a/crates/ra_tools/tests/main.rs b/crates/ra_tools/tests/main.rs
new file mode 100644
index 000000000..56d1318d6
--- /dev/null
+++ b/crates/ra_tools/tests/main.rs
@@ -0,0 +1,2 @@
1mod cli;
2mod docs;
diff --git a/crates/ra_tt/src/buffer.rs b/crates/ra_tt/src/buffer.rs
index 48c22a2d8..ef3f2323c 100644
--- a/crates/ra_tt/src/buffer.rs
+++ b/crates/ra_tt/src/buffer.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1use crate::{Subtree, TokenTree}; 3use crate::{Subtree, TokenTree};
2 4
3#[derive(Copy, Clone, Debug, Eq, PartialEq)] 5#[derive(Copy, Clone, Debug, Eq, PartialEq)]
diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs
index 2a48c66c4..20c251ff4 100644
--- a/crates/ra_tt/src/lib.rs
+++ b/crates/ra_tt/src/lib.rs
@@ -1,6 +1,6 @@
1/// `tt` crate defines a `TokenTree` data structure: this is the interface (both 1//! `tt` crate defines a `TokenTree` data structure: this is the interface (both
2/// input and output) of macros. It closely mirrors `proc_macro` crate's 2//! input and output) of macros. It closely mirrors `proc_macro` crate's
3/// `TokenTree`. 3//! `TokenTree`.
4 4
5macro_rules! impl_froms { 5macro_rules! impl_froms {
6 ($e:ident: $($v:ident), *) => { 6 ($e:ident: $($v:ident), *) => {
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index 816d01f09..c40943b63 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -1,3 +1,5 @@
1//! FIXME: write short doc here
2
1#[macro_use] 3#[macro_use]
2pub mod marks; 4pub mod marks;
3 5
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index 1201f6e5a..1ffabc6ef 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -79,9 +79,7 @@ Rust syntax tree structure and parser. See
79- `grammar.ron` RON description of the grammar, which is used to 79- `grammar.ron` RON description of the grammar, which is used to
80 generate `syntax_kinds` and `ast` modules, using `cargo gen-syntax` command. 80 generate `syntax_kinds` and `ast` modules, using `cargo gen-syntax` command.
81- `algo`: generic tree algorithms, including `walk` for O(1) stack 81- `algo`: generic tree algorithms, including `walk` for O(1) stack
82 space tree traversal (this is cool) and `visit` for type-driven 82 space tree traversal (this is cool).
83 visiting the nodes (this is double plus cool, if you understand how
84 `Visitor` works, you understand the design of syntax trees).
85 83
86Tests for ra_syntax are mostly data-driven: `test_data/parser` contains subdirectories with a bunch of `.rs` 84Tests for ra_syntax are mostly data-driven: `test_data/parser` contains subdirectories with a bunch of `.rs`
87(test vectors) and `.txt` files with corresponding syntax trees. During testing, we check 85(test vectors) and `.txt` files with corresponding syntax trees. During testing, we check
diff --git a/docs/user/README.md b/docs/user/README.md
index 9d03cad1c..036b51d58 100644
--- a/docs/user/README.md
+++ b/docs/user/README.md
@@ -45,7 +45,7 @@ should adapt these manual installation instructions:
45``` 45```
46$ git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1 46$ git clone https://github.com/rust-analyzer/rust-analyzer.git --depth 1
47$ cd rust-analyzer 47$ cd rust-analyzer
48$ cargo install --path ./crates/ra_lsp_server/ --force 48$ cargo install --path ./crates/ra_lsp_server/ --force --locked
49$ cd ./editors/code 49$ cd ./editors/code
50$ npm install 50$ npm install
51$ ./node_modules/vsce/out/vsce package 51$ ./node_modules/vsce/out/vsce package
@@ -116,6 +116,22 @@ to load path and require it in `init.el`
116[coc-vim-conf]: https://github.com/neoclide/coc.nvim/#example-vim-configuration 116[coc-vim-conf]: https://github.com/neoclide/coc.nvim/#example-vim-configuration
117[coc-rust-analyzer]: https://github.com/fannheyward/coc-rust-analyzer 117[coc-rust-analyzer]: https://github.com/fannheyward/coc-rust-analyzer
118 118
119## Vim and NeoVim Alternative
120
121* Install LanguageClient-neovim by following the instructions [here][lang-client-neovim]
122 - No extra run-time is required as this server is written in Rust
123 - The github project wiki has extra tips on configuration
124
125* Configure by adding this to your vim/neovim config file (replacing the existing rust specific line if it exists):
126
127```
128let g:LanguageClient_serverCommands = {
129\ 'rust': ['ra_lsp_server'],
130\ }
131```
132
133[lang-client-neovim]: https://github.com/autozimu/LanguageClient-neovim
134
119 135
120## Sublime Text 3 136## Sublime Text 3
121 137
diff --git a/docs/user/features.md b/docs/user/features.md
index 23842f409..8b7a8d7fc 100644
--- a/docs/user/features.md
+++ b/docs/user/features.md
@@ -166,6 +166,20 @@ impl Foo for S {
166} 166}
167``` 167```
168 168
169- Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws)
170
171```rust
172// before:
173fn example(x: bool) -> bool {
174 !x || !x
175}
176
177// after:
178fn example(x: bool) -> bool {
179 !(x && x)
180}
181```
182
169- Import path 183- Import path
170 184
171```rust 185```rust
@@ -353,9 +367,9 @@ impl VariantData {
353 367
354```rust 368```rust
355// before: 369// before:
356use algo:<|>:visitor::{Visitor, visit}; 370use crate:<|>:db::{RootDatabase, FileSymbol};
357// after: 371// after:
358use algo::{<|>visitor::{Visitor, visit}}; 372use crate::{<|>db::{RootDatabase, FileSymbol}};
359``` 373```
360 374
361- Flip binary expression 375- Flip binary expression
diff --git a/editors/code/src/test/utils/diagnotics/rust.test.ts b/editors/code/src/test/utils/diagnotics/rust.test.ts
index 7fb003fe2..327d15046 100644
--- a/editors/code/src/test/utils/diagnotics/rust.test.ts
+++ b/editors/code/src/test/utils/diagnotics/rust.test.ts
@@ -50,7 +50,7 @@ describe('mapRustDiagnosticToVsCode', () => {
50 ].join('\n') 50 ].join('\n')
51 ); 51 );
52 assert.strictEqual(diagnostic.code, 'E0053'); 52 assert.strictEqual(diagnostic.code, 'E0053');
53 assert.strictEqual(diagnostic.tags, undefined); 53 assert.deepStrictEqual(diagnostic.tags, []);
54 54
55 // No related information 55 // No related information
56 assert.deepStrictEqual(diagnostic.relatedInformation, []); 56 assert.deepStrictEqual(diagnostic.relatedInformation, []);
@@ -115,7 +115,7 @@ describe('mapRustDiagnosticToVsCode', () => {
115 ); 115 );
116 assert.strictEqual(diagnostic.code, 'E0061'); 116 assert.strictEqual(diagnostic.code, 'E0061');
117 assert.strictEqual(diagnostic.source, 'rustc'); 117 assert.strictEqual(diagnostic.source, 'rustc');
118 assert.strictEqual(diagnostic.tags, undefined); 118 assert.deepStrictEqual(diagnostic.tags, []);
119 119
120 // One related information for the original definition 120 // One related information for the original definition
121 const relatedInformation = diagnostic.relatedInformation; 121 const relatedInformation = diagnostic.relatedInformation;
@@ -149,7 +149,7 @@ describe('mapRustDiagnosticToVsCode', () => {
149 ].join('\n') 149 ].join('\n')
150 ); 150 );
151 assert.strictEqual(diagnostic.code, 'trivially_copy_pass_by_ref'); 151 assert.strictEqual(diagnostic.code, 'trivially_copy_pass_by_ref');
152 assert.strictEqual(diagnostic.tags, undefined); 152 assert.deepStrictEqual(diagnostic.tags, []);
153 153
154 // One related information for the lint definition 154 // One related information for the lint definition
155 const relatedInformation = diagnostic.relatedInformation; 155 const relatedInformation = diagnostic.relatedInformation;
@@ -189,7 +189,7 @@ describe('mapRustDiagnosticToVsCode', () => {
189 ); 189 );
190 assert.strictEqual(diagnostic.code, 'E0308'); 190 assert.strictEqual(diagnostic.code, 'E0308');
191 assert.strictEqual(diagnostic.source, 'rustc'); 191 assert.strictEqual(diagnostic.source, 'rustc');
192 assert.strictEqual(diagnostic.tags, undefined); 192 assert.deepStrictEqual(diagnostic.tags, []);
193 193
194 // No related information 194 // No related information
195 assert.deepStrictEqual(diagnostic.relatedInformation, []); 195 assert.deepStrictEqual(diagnostic.relatedInformation, []);
diff --git a/editors/code/src/utils/diagnostics/rust.ts b/editors/code/src/utils/diagnostics/rust.ts
index 1fb1f7b6d..0550d0372 100644
--- a/editors/code/src/utils/diagnostics/rust.ts
+++ b/editors/code/src/utils/diagnostics/rust.ts
@@ -112,6 +112,17 @@ function isUnusedOrUnnecessary(rd: RustDiagnostic): boolean {
112} 112}
113 113
114/** 114/**
115 * Determines if diagnostic is related to deprecated code
116 */
117function isDeprecated(rd: RustDiagnostic): boolean {
118 if (!rd.code) {
119 return false;
120 }
121
122 return ['deprecated'].includes(rd.code.code);
123}
124
125/**
115 * Converts a Rust child diagnostic to a VsCode related information 126 * Converts a Rust child diagnostic to a VsCode related information
116 * 127 *
117 * This can have three outcomes: 128 * This can have three outcomes:
@@ -200,6 +211,7 @@ export function mapRustDiagnosticToVsCode(
200 vd.source = source; 211 vd.source = source;
201 vd.code = code; 212 vd.code = code;
202 vd.relatedInformation = []; 213 vd.relatedInformation = [];
214 vd.tags = [];
203 215
204 for (const secondarySpan of secondarySpans) { 216 for (const secondarySpan of secondarySpans) {
205 const related = mapSecondarySpanToRelated(secondarySpan); 217 const related = mapSecondarySpanToRelated(secondarySpan);
@@ -234,7 +246,11 @@ export function mapRustDiagnosticToVsCode(
234 } 246 }
235 247
236 if (isUnusedOrUnnecessary(rd)) { 248 if (isUnusedOrUnnecessary(rd)) {
237 vd.tags = [vscode.DiagnosticTag.Unnecessary]; 249 vd.tags.push(vscode.DiagnosticTag.Unnecessary);
250 }
251
252 if (isDeprecated(rd)) {
253 vd.tags.push(vscode.DiagnosticTag.Deprecated);
238 } 254 }
239 255
240 return { 256 return {