aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/release.yaml16
-rw-r--r--Cargo.lock94
-rw-r--r--crates/ra_assists/src/ast_transform.rs24
-rw-r--r--crates/ra_assists/src/handlers/add_custom_impl.rs2
-rw-r--r--crates/ra_assists/src/handlers/add_explicit_type.rs4
-rw-r--r--crates/ra_assists/src/handlers/add_missing_impl_members.rs50
-rw-r--r--crates/ra_assists/src/handlers/unwrap_block.rs221
-rw-r--r--crates/ra_assists/src/utils.rs4
-rw-r--r--crates/ra_flycheck/Cargo.toml2
-rw-r--r--crates/ra_flycheck/src/lib.rs4
-rw-r--r--crates/ra_hir/src/code_model.rs35
-rw-r--r--crates/ra_hir_def/src/data.rs31
-rw-r--r--crates/ra_hir_def/src/db.rs6
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs4
-rw-r--r--crates/ra_hir_ty/src/display.rs63
-rw-r--r--crates/ra_hir_ty/src/infer.rs8
-rw-r--r--crates/ra_hir_ty/src/lib.rs5
-rw-r--r--crates/ra_hir_ty/src/op.rs3
-rw-r--r--crates/ra_hir_ty/src/tests/display_source_code.rs27
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs29
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs256
-rw-r--r--crates/ra_ide/src/completion/complete_snippet.rs26
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs2
-rw-r--r--crates/ra_ide/src/completion/presentation.rs58
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs9
-rw-r--r--crates/ra_ide/src/lib.rs8
-rw-r--r--crates/ra_ide/src/references.rs25
-rw-r--r--crates/ra_ide/src/snapshots/highlight_strings.html4
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html23
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs33
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tests.rs21
-rw-r--r--crates/ra_ide_db/src/defs.rs12
-rw-r--r--crates/ra_proc_macro_srv/Cargo.toml4
-rw-r--r--crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt21
-rw-r--r--crates/ra_proc_macro_srv/src/tests/mod.rs6
-rw-r--r--crates/ra_proc_macro_srv/src/tests/utils.rs4
-rw-r--r--crates/ra_project_model/Cargo.toml2
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs14
-rw-r--r--crates/ra_project_model/src/lib.rs2
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs1504
-rw-r--r--crates/ra_syntax/src/ast/make.rs11
-rw-r--r--crates/ra_syntax/src/validation.rs2
-rw-r--r--crates/ra_text_edit/src/lib.rs3
-rw-r--r--crates/ra_toolchain/src/lib.rs7
-rw-r--r--crates/rust-analyzer/src/bin/main.rs7
-rw-r--r--crates/rust-analyzer/src/cli.rs1
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs60
-rw-r--r--crates/rust-analyzer/src/conv.rs726
-rw-r--r--crates/rust-analyzer/src/from_proto.rs42
-rw-r--r--crates/rust-analyzer/src/lib.rs5
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs (renamed from crates/rust-analyzer/src/req.rs)29
-rw-r--r--crates/rust-analyzer/src/main_loop.rs198
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs523
-rw-r--r--crates/rust-analyzer/src/to_proto.rs592
-rw-r--r--crates/rust-analyzer/src/world.rs38
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs17
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/support.rs7
-rw-r--r--docs/dev/README.md2
-rw-r--r--docs/user/features.md14
-rw-r--r--docs/user/readme.adoc2
-rw-r--r--editors/code/.vscodeignore1
-rw-r--r--editors/code/package-lock.json92
-rw-r--r--editors/code/package.json50
-rw-r--r--editors/code/rust.tmGrammar.json681
-rw-r--r--editors/code/src/commands/ssr.ts2
-rw-r--r--editors/code/src/commands/syntax_tree.ts4
-rw-r--r--xtask/src/ast_src.rs1499
-rw-r--r--xtask/src/codegen/gen_syntax.rs25
69 files changed, 5695 insertions, 1613 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 3f52f31f8..29ac89549 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -20,7 +20,7 @@ jobs:
20 runs-on: ${{ matrix.os }} 20 runs-on: ${{ matrix.os }}
21 strategy: 21 strategy:
22 matrix: 22 matrix:
23 os: [ubuntu-latest, windows-latest, macos-latest] 23 os: [ubuntu-16.04, windows-latest, macos-latest]
24 24
25 steps: 25 steps:
26 - name: Checkout repository 26 - name: Checkout repository
@@ -42,25 +42,25 @@ jobs:
42 override: true 42 override: true
43 43
44 - name: Install Nodejs 44 - name: Install Nodejs
45 if: matrix.os == 'ubuntu-latest' 45 if: matrix.os == 'ubuntu-16.04'
46 uses: actions/setup-node@v1 46 uses: actions/setup-node@v1
47 with: 47 with:
48 node-version: 12.x 48 node-version: 12.x
49 49
50 - name: Dist 50 - name: Dist
51 if: matrix.os == 'ubuntu-latest' && github.ref == 'refs/heads/release' 51 if: matrix.os == 'ubuntu-16.04' && github.ref == 'refs/heads/release'
52 run: cargo xtask dist --client 0.2.$GITHUB_RUN_NUMBER 52 run: cargo xtask dist --client 0.2.$GITHUB_RUN_NUMBER
53 53
54 - name: Dist 54 - name: Dist
55 if: matrix.os == 'ubuntu-latest' && github.ref != 'refs/heads/release' 55 if: matrix.os == 'ubuntu-16.04' && github.ref != 'refs/heads/release'
56 run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly 56 run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly
57 57
58 - name: Dist 58 - name: Dist
59 if: matrix.os != 'ubuntu-latest' 59 if: matrix.os != 'ubuntu-16.04'
60 run: cargo xtask dist 60 run: cargo xtask dist
61 61
62 - name: Nightly analysis-stats check 62 - name: Nightly analysis-stats check
63 if: matrix.os == 'ubuntu-latest' && github.ref != 'refs/heads/release' 63 if: matrix.os == 'ubuntu-16.04' && github.ref != 'refs/heads/release'
64 run: ./dist/rust-analyzer-linux analysis-stats . 64 run: ./dist/rust-analyzer-linux analysis-stats .
65 65
66 - name: Upload artifacts 66 - name: Upload artifacts
@@ -71,7 +71,7 @@ jobs:
71 71
72 publish: 72 publish:
73 name: publish 73 name: publish
74 runs-on: ubuntu-latest 74 runs-on: ubuntu-16.04
75 needs: ['dist'] 75 needs: ['dist']
76 steps: 76 steps:
77 - name: Install Nodejs 77 - name: Install Nodejs
@@ -94,7 +94,7 @@ jobs:
94 path: dist 94 path: dist
95 - uses: actions/download-artifact@v1 95 - uses: actions/download-artifact@v1
96 with: 96 with:
97 name: dist-ubuntu-latest 97 name: dist-ubuntu-16.04
98 path: dist 98 path: dist
99 - uses: actions/download-artifact@v1 99 - uses: actions/download-artifact@v1
100 with: 100 with:
diff --git a/Cargo.lock b/Cargo.lock
index 41855f22e..3a34978b1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,15 @@
1# This file is automatically @generated by Cargo. 1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing. 2# It is not intended for manual editing.
3[[package]] 3[[package]]
4name = "addr2line"
5version = "0.12.0"
6source = "registry+https://github.com/rust-lang/crates.io-index"
7checksum = "456d75cbb82da1ad150c8a9d97285ffcd21c9931dcb11e995903e7d75141b38b"
8dependencies = [
9 "gimli",
10]
11
12[[package]]
4name = "aho-corasick" 13name = "aho-corasick"
5version = "0.7.10" 14version = "0.7.10"
6source = "registry+https://github.com/rust-lang/crates.io-index" 15source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -11,9 +20,9 @@ dependencies = [
11 20
12[[package]] 21[[package]]
13name = "anyhow" 22name = "anyhow"
14version = "1.0.28" 23version = "1.0.29"
15source = "registry+https://github.com/rust-lang/crates.io-index" 24source = "registry+https://github.com/rust-lang/crates.io-index"
16checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff" 25checksum = "dc98824304f5513bb8f862f9e5985219003de4d730689e59d8f28818283a6fe4"
17 26
18[[package]] 27[[package]]
19name = "anymap" 28name = "anymap"
@@ -46,27 +55,18 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
46 55
47[[package]] 56[[package]]
48name = "backtrace" 57name = "backtrace"
49version = "0.3.46" 58version = "0.3.47"
50source = "registry+https://github.com/rust-lang/crates.io-index" 59source = "registry+https://github.com/rust-lang/crates.io-index"
51checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" 60checksum = "a5393cb2f40a6fae0014c9af00018e95846f3b241b331a6b7733c326d3e58108"
52dependencies = [ 61dependencies = [
53 "backtrace-sys", 62 "addr2line",
54 "cfg-if", 63 "cfg-if",
55 "libc", 64 "libc",
65 "object",
56 "rustc-demangle", 66 "rustc-demangle",
57] 67]
58 68
59[[package]] 69[[package]]
60name = "backtrace-sys"
61version = "0.1.37"
62source = "registry+https://github.com/rust-lang/crates.io-index"
63checksum = "18fbebbe1c9d1f383a9cc7e8ccdb471b91c8d024ee9c2ca5b5346121fe8b4399"
64dependencies = [
65 "cc",
66 "libc",
67]
68
69[[package]]
70name = "base64" 70name = "base64"
71version = "0.12.1" 71version = "0.12.1"
72source = "registry+https://github.com/rust-lang/crates.io-index" 72source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -80,18 +80,18 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
80 80
81[[package]] 81[[package]]
82name = "bstr" 82name = "bstr"
83version = "0.2.12" 83version = "0.2.13"
84source = "registry+https://github.com/rust-lang/crates.io-index" 84source = "registry+https://github.com/rust-lang/crates.io-index"
85checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" 85checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931"
86dependencies = [ 86dependencies = [
87 "memchr", 87 "memchr",
88] 88]
89 89
90[[package]] 90[[package]]
91name = "cargo_metadata" 91name = "cargo_metadata"
92version = "0.9.1" 92version = "0.10.0"
93source = "registry+https://github.com/rust-lang/crates.io-index" 93source = "registry+https://github.com/rust-lang/crates.io-index"
94checksum = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" 94checksum = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf"
95dependencies = [ 95dependencies = [
96 "semver", 96 "semver",
97 "serde", 97 "serde",
@@ -423,6 +423,12 @@ dependencies = [
423] 423]
424 424
425[[package]] 425[[package]]
426name = "gimli"
427version = "0.21.0"
428source = "registry+https://github.com/rust-lang/crates.io-index"
429checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c"
430
431[[package]]
426name = "globset" 432name = "globset"
427version = "0.4.5" 433version = "0.4.5"
428source = "registry+https://github.com/rust-lang/crates.io-index" 434source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -437,9 +443,9 @@ dependencies = [
437 443
438[[package]] 444[[package]]
439name = "goblin" 445name = "goblin"
440version = "0.2.1" 446version = "0.2.3"
441source = "registry+https://github.com/rust-lang/crates.io-index" 447source = "registry+https://github.com/rust-lang/crates.io-index"
442checksum = "ddd5e3132801a1ac34ac53b97acde50c4685414dd2f291b9ea52afa6f07468c8" 448checksum = "d20fd25aa456527ce4f544271ae4fea65d2eda4a6561ea56f39fb3ee4f7e3884"
443dependencies = [ 449dependencies = [
444 "log", 450 "log",
445 "plain", 451 "plain",
@@ -613,9 +619,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
613 619
614[[package]] 620[[package]]
615name = "libc" 621name = "libc"
616version = "0.2.69" 622version = "0.2.70"
617source = "registry+https://github.com/rust-lang/crates.io-index" 623source = "registry+https://github.com/rust-lang/crates.io-index"
618checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005" 624checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f"
619 625
620[[package]] 626[[package]]
621name = "libloading" 627name = "libloading"
@@ -796,6 +802,12 @@ dependencies = [
796] 802]
797 803
798[[package]] 804[[package]]
805name = "object"
806version = "0.19.0"
807source = "registry+https://github.com/rust-lang/crates.io-index"
808checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2"
809
810[[package]]
799name = "once_cell" 811name = "once_cell"
800version = "1.3.1" 812version = "1.3.1"
801source = "registry+https://github.com/rust-lang/crates.io-index" 813source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -904,9 +916,9 @@ dependencies = [
904 916
905[[package]] 917[[package]]
906name = "quote" 918name = "quote"
907version = "1.0.4" 919version = "1.0.5"
908source = "registry+https://github.com/rust-lang/crates.io-index" 920source = "registry+https://github.com/rust-lang/crates.io-index"
909checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" 921checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e"
910dependencies = [ 922dependencies = [
911 "proc-macro2", 923 "proc-macro2",
912] 924]
@@ -1221,9 +1233,9 @@ dependencies = [
1221 1233
1222[[package]] 1234[[package]]
1223name = "ra_vfs" 1235name = "ra_vfs"
1224version = "0.6.0" 1236version = "0.6.1"
1225source = "registry+https://github.com/rust-lang/crates.io-index" 1237source = "registry+https://github.com/rust-lang/crates.io-index"
1226checksum = "fcaa5615f420134aea7667253db101d03a5c5f300eac607872dc2a36407b2ac9" 1238checksum = "cbf31a173fc77ec59c27cf39af6baa137b40f4dbd45a8b3eccb1b2e4cfc922c1"
1227dependencies = [ 1239dependencies = [
1228 "crossbeam-channel", 1240 "crossbeam-channel",
1229 "jod-thread", 1241 "jod-thread",
@@ -1487,9 +1499,9 @@ dependencies = [
1487 1499
1488[[package]] 1500[[package]]
1489name = "scroll_derive" 1501name = "scroll_derive"
1490version = "0.10.1" 1502version = "0.10.2"
1491source = "registry+https://github.com/rust-lang/crates.io-index" 1503source = "registry+https://github.com/rust-lang/crates.io-index"
1492checksum = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28" 1504checksum = "e367622f934864ffa1c704ba2b82280aab856e3d8213c84c5720257eb34b15b9"
1493dependencies = [ 1505dependencies = [
1494 "proc-macro2", 1506 "proc-macro2",
1495 "quote", 1507 "quote",
@@ -1514,18 +1526,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
1514 1526
1515[[package]] 1527[[package]]
1516name = "serde" 1528name = "serde"
1517version = "1.0.106" 1529version = "1.0.110"
1518source = "registry+https://github.com/rust-lang/crates.io-index" 1530source = "registry+https://github.com/rust-lang/crates.io-index"
1519checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" 1531checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c"
1520dependencies = [ 1532dependencies = [
1521 "serde_derive", 1533 "serde_derive",
1522] 1534]
1523 1535
1524[[package]] 1536[[package]]
1525name = "serde_derive" 1537name = "serde_derive"
1526version = "1.0.106" 1538version = "1.0.110"
1527source = "registry+https://github.com/rust-lang/crates.io-index" 1539source = "registry+https://github.com/rust-lang/crates.io-index"
1528checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" 1540checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
1529dependencies = [ 1541dependencies = [
1530 "proc-macro2", 1542 "proc-macro2",
1531 "quote", 1543 "quote",
@@ -1534,9 +1546,9 @@ dependencies = [
1534 1546
1535[[package]] 1547[[package]]
1536name = "serde_json" 1548name = "serde_json"
1537version = "1.0.52" 1549version = "1.0.53"
1538source = "registry+https://github.com/rust-lang/crates.io-index" 1550source = "registry+https://github.com/rust-lang/crates.io-index"
1539checksum = "a7894c8ed05b7a3a279aeb79025fdec1d3158080b75b98a08faf2806bb799edd" 1551checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2"
1540dependencies = [ 1552dependencies = [
1541 "itoa", 1553 "itoa",
1542 "ryu", 1554 "ryu",
@@ -1556,9 +1568,9 @@ dependencies = [
1556 1568
1557[[package]] 1569[[package]]
1558name = "serde_yaml" 1570name = "serde_yaml"
1559version = "0.8.11" 1571version = "0.8.12"
1560source = "registry+https://github.com/rust-lang/crates.io-index" 1572source = "registry+https://github.com/rust-lang/crates.io-index"
1561checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" 1573checksum = "16c7a592a1ec97c9c1c68d75b6e537dcbf60c7618e038e7841e00af1d9ccf0c4"
1562dependencies = [ 1574dependencies = [
1563 "dtoa", 1575 "dtoa",
1564 "linked-hash-map", 1576 "linked-hash-map",
@@ -1599,9 +1611,9 @@ checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f"
1599 1611
1600[[package]] 1612[[package]]
1601name = "syn" 1613name = "syn"
1602version = "1.0.19" 1614version = "1.0.21"
1603source = "registry+https://github.com/rust-lang/crates.io-index" 1615source = "registry+https://github.com/rust-lang/crates.io-index"
1604checksum = "e8e5aa70697bb26ee62214ae3288465ecec0000f05182f039b477001f08f5ae7" 1616checksum = "4696caa4048ac7ce2bcd2e484b3cef88c1004e41b8e945a277e2c25dc0b72060"
1605dependencies = [ 1617dependencies = [
1606 "proc-macro2", 1618 "proc-macro2",
1607 "quote", 1619 "quote",
@@ -1685,9 +1697,9 @@ dependencies = [
1685 1697
1686[[package]] 1698[[package]]
1687name = "threadpool" 1699name = "threadpool"
1688version = "1.8.0" 1700version = "1.8.1"
1689source = "registry+https://github.com/rust-lang/crates.io-index" 1701source = "registry+https://github.com/rust-lang/crates.io-index"
1690checksum = "e8dae184447c15d5a6916d973c642aec485105a13cd238192a6927ae3e077d66" 1702checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
1691dependencies = [ 1703dependencies = [
1692 "num_cpus", 1704 "num_cpus",
1693] 1705]
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs
index 9ac65ab39..3079a02a2 100644
--- a/crates/ra_assists/src/ast_transform.rs
+++ b/crates/ra_assists/src/ast_transform.rs
@@ -1,7 +1,7 @@
1//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined. 1//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
2use rustc_hash::FxHashMap; 2use rustc_hash::FxHashMap;
3 3
4use hir::{PathResolution, SemanticsScope}; 4use hir::{HirDisplay, PathResolution, SemanticsScope};
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{ 6use ra_syntax::{
7 algo::SyntaxRewriter, 7 algo::SyntaxRewriter,
@@ -51,7 +51,27 @@ impl<'a> SubstituteTypeParams<'a> {
51 .into_iter() 51 .into_iter()
52 // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky 52 // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
53 .skip(1) 53 .skip(1)
54 .zip(substs.into_iter()) 54 // The actual list of trait type parameters may be longer than the one
55 // used in the `impl` block due to trailing default type parametrs.
56 // For that case we extend the `substs` with an empty iterator so we
57 // can still hit those trailing values and check if they actually have
58 // a default type. If they do, go for that type from `hir` to `ast` so
59 // the resulting change can be applied correctly.
60 .zip(substs.into_iter().map(Some).chain(std::iter::repeat(None)))
61 .filter_map(|(k, v)| match v {
62 Some(v) => Some((k, v)),
63 None => {
64 let default = k.default(source_scope.db)?;
65 Some((
66 k,
67 ast::make::type_ref(
68 &default
69 .display_source_code(source_scope.db, source_scope.module()?.into())
70 .ok()?,
71 ),
72 ))
73 }
74 })
55 .collect(); 75 .collect();
56 return SubstituteTypeParams { 76 return SubstituteTypeParams {
57 source_scope, 77 source_scope,
diff --git a/crates/ra_assists/src/handlers/add_custom_impl.rs b/crates/ra_assists/src/handlers/add_custom_impl.rs
index 795a225a4..2baeb8607 100644
--- a/crates/ra_assists/src/handlers/add_custom_impl.rs
+++ b/crates/ra_assists/src/handlers/add_custom_impl.rs
@@ -49,7 +49,7 @@ pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<
49 let start_offset = annotated.syntax().parent()?.text_range().end(); 49 let start_offset = annotated.syntax().parent()?.text_range().end();
50 50
51 let label = 51 let label =
52 format!("Add custom impl '{}' for '{}'", trait_token.text().as_str(), annotated_name); 52 format!("Add custom impl `{}` for `{}`", trait_token.text().as_str(), annotated_name);
53 53
54 let target = attr.syntax().text_range(); 54 let target = attr.syntax().text_range();
55 acc.add(AssistId("add_custom_impl"), label, target, |edit| { 55 acc.add(AssistId("add_custom_impl"), label, target, |edit| {
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs
index 146cc75df..0c7d5e355 100644
--- a/crates/ra_assists/src/handlers/add_explicit_type.rs
+++ b/crates/ra_assists/src/handlers/add_explicit_type.rs
@@ -61,7 +61,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
61 let inferred_type = ty.display_source_code(ctx.db, module.into()).ok()?; 61 let inferred_type = ty.display_source_code(ctx.db, module.into()).ok()?;
62 acc.add( 62 acc.add(
63 AssistId("add_explicit_type"), 63 AssistId("add_explicit_type"),
64 format!("Insert explicit type '{}'", inferred_type), 64 format!("Insert explicit type `{}`", inferred_type),
65 pat_range, 65 pat_range,
66 |builder| match ascribed_ty { 66 |builder| match ascribed_ty {
67 Some(ascribed_ty) => { 67 Some(ascribed_ty) => {
@@ -209,7 +209,7 @@ struct Test<K, T = u8> {
209} 209}
210 210
211fn main() { 211fn main() {
212 let test<|>: Test<i32, u8> = Test { t: 23, k: 33 }; 212 let test<|>: Test<i32> = Test { t: 23, k: 33 };
213}"#, 213}"#,
214 ); 214 );
215 } 215 }
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
index c1ce87914..22e1156d2 100644
--- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
@@ -618,4 +618,54 @@ impl Foo for S {
618}"#, 618}"#,
619 ) 619 )
620 } 620 }
621
622 #[test]
623 fn test_generic_single_default_parameter() {
624 check_assist(
625 add_missing_impl_members,
626 r#"
627trait Foo<T = Self> {
628 fn bar(&self, other: &T);
629}
630
631struct S;
632impl Foo for S { <|> }"#,
633 r#"
634trait Foo<T = Self> {
635 fn bar(&self, other: &T);
636}
637
638struct S;
639impl Foo for S {
640 <|>fn bar(&self, other: &Self) {
641 todo!()
642 }
643}"#,
644 )
645 }
646
647 #[test]
648 fn test_generic_default_parameter_is_second() {
649 check_assist(
650 add_missing_impl_members,
651 r#"
652trait Foo<T1, T2 = Self> {
653 fn bar(&self, this: &T1, that: &T2);
654}
655
656struct S<T>;
657impl Foo<T> for S<T> { <|> }"#,
658 r#"
659trait Foo<T1, T2 = Self> {
660 fn bar(&self, this: &T1, that: &T2);
661}
662
663struct S<T>;
664impl Foo<T> for S<T> {
665 <|>fn bar(&self, this: &T, that: &Self) {
666 todo!()
667 }
668}"#,
669 )
670 }
621} 671}
diff --git a/crates/ra_assists/src/handlers/unwrap_block.rs b/crates/ra_assists/src/handlers/unwrap_block.rs
index eba0631a4..e52ec557e 100644
--- a/crates/ra_assists/src/handlers/unwrap_block.rs
+++ b/crates/ra_assists/src/handlers/unwrap_block.rs
@@ -1,6 +1,6 @@
1use crate::{AssistContext, AssistId, Assists}; 1use crate::{AssistContext, AssistId, Assists};
2 2
3use ast::LoopBodyOwner; 3use ast::{ElseBranch, Expr, LoopBodyOwner};
4use ra_fmt::unwrap_trivial_block; 4use ra_fmt::unwrap_trivial_block;
5use ra_syntax::{ast, match_ast, AstNode, TextRange, T}; 5use ra_syntax::{ast, match_ast, AstNode, TextRange, T};
6 6
@@ -25,19 +25,11 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
25 let l_curly_token = ctx.find_token_at_offset(T!['{'])?; 25 let l_curly_token = ctx.find_token_at_offset(T!['{'])?;
26 let block = ast::BlockExpr::cast(l_curly_token.parent())?; 26 let block = ast::BlockExpr::cast(l_curly_token.parent())?;
27 let parent = block.syntax().parent()?; 27 let parent = block.syntax().parent()?;
28 let assist_id = AssistId("unwrap_block");
29 let assist_label = "Unwrap block";
30
28 let (expr, expr_to_unwrap) = match_ast! { 31 let (expr, expr_to_unwrap) = match_ast! {
29 match parent { 32 match parent {
30 ast::IfExpr(if_expr) => {
31 let expr_to_unwrap = if_expr.blocks().find_map(|expr| extract_expr(ctx.frange.range, expr));
32 let expr_to_unwrap = expr_to_unwrap?;
33 // Find if we are in a else if block
34 let ancestor = if_expr.syntax().parent().and_then(ast::IfExpr::cast);
35
36 match ancestor {
37 None => (ast::Expr::IfExpr(if_expr), expr_to_unwrap),
38 Some(ancestor) => (ast::Expr::IfExpr(ancestor), expr_to_unwrap),
39 }
40 },
41 ast::ForExpr(for_expr) => { 33 ast::ForExpr(for_expr) => {
42 let block_expr = for_expr.loop_body()?; 34 let block_expr = for_expr.loop_body()?;
43 let expr_to_unwrap = extract_expr(ctx.frange.range, block_expr)?; 35 let expr_to_unwrap = extract_expr(ctx.frange.range, block_expr)?;
@@ -53,27 +45,62 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
53 let expr_to_unwrap = extract_expr(ctx.frange.range, block_expr)?; 45 let expr_to_unwrap = extract_expr(ctx.frange.range, block_expr)?;
54 (ast::Expr::LoopExpr(loop_expr), expr_to_unwrap) 46 (ast::Expr::LoopExpr(loop_expr), expr_to_unwrap)
55 }, 47 },
48 ast::IfExpr(if_expr) => {
49 let mut resp = None;
50
51 let then_branch = if_expr.then_branch()?;
52 if then_branch.l_curly_token()?.text_range().contains_range(ctx.frange.range) {
53 if let Some(ancestor) = if_expr.syntax().parent().and_then(ast::IfExpr::cast) {
54 // For `else if` blocks
55 let ancestor_then_branch = ancestor.then_branch()?;
56 let l_curly_token = then_branch.l_curly_token()?;
57
58 let target = then_branch.syntax().text_range();
59 return acc.add(assist_id, assist_label, target, |edit| {
60 let range_to_del_else_if = TextRange::new(ancestor_then_branch.syntax().text_range().end(), l_curly_token.text_range().start());
61 let range_to_del_rest = TextRange::new(then_branch.syntax().text_range().end(), if_expr.syntax().text_range().end());
62
63 edit.set_cursor(ancestor_then_branch.syntax().text_range().end());
64 edit.delete(range_to_del_rest);
65 edit.delete(range_to_del_else_if);
66 edit.replace(target, update_expr_string(then_branch.to_string(), &[' ', '{']));
67 });
68 } else {
69 resp = Some((ast::Expr::IfExpr(if_expr.clone()), Expr::BlockExpr(then_branch)));
70 }
71 } else if let Some(else_branch) = if_expr.else_branch() {
72 match else_branch {
73 ElseBranch::Block(else_block) => {
74 let l_curly_token = else_block.l_curly_token()?;
75 if l_curly_token.text_range().contains_range(ctx.frange.range) {
76 let target = else_block.syntax().text_range();
77 return acc.add(assist_id, assist_label, target, |edit| {
78 let range_to_del = TextRange::new(then_branch.syntax().text_range().end(), l_curly_token.text_range().start());
79
80 edit.set_cursor(then_branch.syntax().text_range().end());
81 edit.delete(range_to_del);
82 edit.replace(target, update_expr_string(else_block.to_string(), &[' ', '{']));
83 });
84 }
85 },
86 ElseBranch::IfExpr(_) => {},
87 }
88 }
89
90 resp?
91 },
56 _ => return None, 92 _ => return None,
57 } 93 }
58 }; 94 };
59 95
60 let target = expr_to_unwrap.syntax().text_range(); 96 let target = expr_to_unwrap.syntax().text_range();
61 acc.add(AssistId("unwrap_block"), "Unwrap block", target, |edit| { 97 acc.add(assist_id, assist_label, target, |edit| {
62 edit.set_cursor(expr.syntax().text_range().start()); 98 edit.set_cursor(expr.syntax().text_range().start());
63 99
64 let pat_start: &[_] = &[' ', '{', '\n']; 100 edit.replace(
65 let expr_to_unwrap = expr_to_unwrap.to_string(); 101 expr.syntax().text_range(),
66 let expr_string = expr_to_unwrap.trim_start_matches(pat_start); 102 update_expr_string(expr_to_unwrap.to_string(), &[' ', '{', '\n']),
67 let mut expr_string_lines: Vec<&str> = expr_string.lines().collect(); 103 );
68 expr_string_lines.pop(); // Delete last line
69
70 let expr_string = expr_string_lines
71 .into_iter()
72 .map(|line| line.replacen(" ", "", 1)) // Delete indentation
73 .collect::<Vec<String>>()
74 .join("\n");
75
76 edit.replace(expr.syntax().text_range(), expr_string);
77 }) 104 })
78} 105}
79 106
@@ -87,6 +114,18 @@ fn extract_expr(cursor_range: TextRange, block: ast::BlockExpr) -> Option<ast::E
87 } 114 }
88} 115}
89 116
117fn update_expr_string(expr_str: String, trim_start_pat: &[char]) -> String {
118 let expr_string = expr_str.trim_start_matches(trim_start_pat);
119 let mut expr_string_lines: Vec<&str> = expr_string.lines().collect();
120 expr_string_lines.pop(); // Delete last line
121
122 expr_string_lines
123 .into_iter()
124 .map(|line| line.replacen(" ", "", 1)) // Delete indentation
125 .collect::<Vec<String>>()
126 .join("\n")
127}
128
90#[cfg(test)] 129#[cfg(test)]
91mod tests { 130mod tests {
92 use crate::tests::{check_assist, check_assist_not_applicable}; 131 use crate::tests::{check_assist, check_assist_not_applicable};
@@ -142,7 +181,13 @@ mod tests {
142 r#" 181 r#"
143 fn main() { 182 fn main() {
144 bar(); 183 bar();
145 <|>println!("bar"); 184 if true {
185 foo();
186
187 //comment
188 bar();
189 }<|>
190 println!("bar");
146 } 191 }
147 "#, 192 "#,
148 ); 193 );
@@ -170,7 +215,127 @@ mod tests {
170 r#" 215 r#"
171 fn main() { 216 fn main() {
172 //bar(); 217 //bar();
173 <|>println!("bar"); 218 if true {
219 println!("true");
220
221 //comment
222 //bar();
223 }<|>
224 println!("bar");
225 }
226 "#,
227 );
228 }
229
230 #[test]
231 fn simple_if_else_if_nested() {
232 check_assist(
233 unwrap_block,
234 r#"
235 fn main() {
236 //bar();
237 if true {
238 println!("true");
239
240 //comment
241 //bar();
242 } else if false {
243 println!("bar");
244 } else if true {<|>
245 println!("foo");
246 }
247 }
248 "#,
249 r#"
250 fn main() {
251 //bar();
252 if true {
253 println!("true");
254
255 //comment
256 //bar();
257 } else if false {
258 println!("bar");
259 }<|>
260 println!("foo");
261 }
262 "#,
263 );
264 }
265
266 #[test]
267 fn simple_if_else_if_nested_else() {
268 check_assist(
269 unwrap_block,
270 r#"
271 fn main() {
272 //bar();
273 if true {
274 println!("true");
275
276 //comment
277 //bar();
278 } else if false {
279 println!("bar");
280 } else if true {
281 println!("foo");
282 } else {<|>
283 println!("else");
284 }
285 }
286 "#,
287 r#"
288 fn main() {
289 //bar();
290 if true {
291 println!("true");
292
293 //comment
294 //bar();
295 } else if false {
296 println!("bar");
297 } else if true {
298 println!("foo");
299 }<|>
300 println!("else");
301 }
302 "#,
303 );
304 }
305
306 #[test]
307 fn simple_if_else_if_nested_middle() {
308 check_assist(
309 unwrap_block,
310 r#"
311 fn main() {
312 //bar();
313 if true {
314 println!("true");
315
316 //comment
317 //bar();
318 } else if false {
319 println!("bar");
320 } else if true {<|>
321 println!("foo");
322 } else {
323 println!("else");
324 }
325 }
326 "#,
327 r#"
328 fn main() {
329 //bar();
330 if true {
331 println!("true");
332
333 //comment
334 //bar();
335 } else if false {
336 println!("bar");
337 }<|>
338 println!("foo");
174 } 339 }
175 "#, 340 "#,
176 ); 341 );
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 2f15a3f15..f3fc92ebf 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -103,7 +103,7 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
103} 103}
104 104
105#[derive(Clone, Copy)] 105#[derive(Clone, Copy)]
106pub(crate) enum TryEnum { 106pub enum TryEnum {
107 Result, 107 Result,
108 Option, 108 Option,
109} 109}
@@ -111,7 +111,7 @@ pub(crate) enum TryEnum {
111impl TryEnum { 111impl TryEnum {
112 const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result]; 112 const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result];
113 113
114 pub(crate) fn from_ty(sema: &Semantics<RootDatabase>, ty: &Type) -> Option<TryEnum> { 114 pub fn from_ty(sema: &Semantics<RootDatabase>, ty: &Type) -> Option<TryEnum> {
115 let enum_ = match ty.as_adt() { 115 let enum_ = match ty.as_adt() {
116 Some(Adt::Enum(it)) => it, 116 Some(Adt::Enum(it)) => it,
117 _ => return None, 117 _ => return None,
diff --git a/crates/ra_flycheck/Cargo.toml b/crates/ra_flycheck/Cargo.toml
index 03e557148..eac502da5 100644
--- a/crates/ra_flycheck/Cargo.toml
+++ b/crates/ra_flycheck/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
11crossbeam-channel = "0.4.0" 11crossbeam-channel = "0.4.0"
12lsp-types = { version = "0.74.0", features = ["proposed"] } 12lsp-types = { version = "0.74.0", features = ["proposed"] }
13log = "0.4.8" 13log = "0.4.8"
14cargo_metadata = "0.9.1" 14cargo_metadata = "0.10.0"
15serde_json = "1.0.48" 15serde_json = "1.0.48"
16jod-thread = "0.1.1" 16jod-thread = "0.1.1"
17ra_toolchain = { path = "../ra_toolchain" } 17ra_toolchain = { path = "../ra_toolchain" }
diff --git a/crates/ra_flycheck/src/lib.rs b/crates/ra_flycheck/src/lib.rs
index 68dcee285..d5efb6ab3 100644
--- a/crates/ra_flycheck/src/lib.rs
+++ b/crates/ra_flycheck/src/lib.rs
@@ -157,7 +157,7 @@ impl FlycheckThread {
157 CheckEvent::Begin => { 157 CheckEvent::Begin => {
158 task_send 158 task_send
159 .send(CheckTask::Status(WorkDoneProgress::Begin(WorkDoneProgressBegin { 159 .send(CheckTask::Status(WorkDoneProgress::Begin(WorkDoneProgressBegin {
160 title: "Running 'cargo check'".to_string(), 160 title: "Running `cargo check`".to_string(),
161 cancellable: Some(false), 161 cancellable: Some(false),
162 message: None, 162 message: None,
163 percentage: None, 163 percentage: None,
@@ -204,6 +204,8 @@ impl FlycheckThread {
204 } 204 }
205 205
206 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} 206 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {}
207 CheckEvent::Msg(Message::BuildFinished(_)) => {}
208 CheckEvent::Msg(Message::TextLine(_)) => {}
207 CheckEvent::Msg(Message::Unknown) => {} 209 CheckEvent::Msg(Message::Unknown) => {}
208 } 210 }
209 } 211 }
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index be18c845c..840cfdfc8 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -148,6 +148,26 @@ impl ModuleDef {
148 ModuleDef::BuiltinType(_) => None, 148 ModuleDef::BuiltinType(_) => None,
149 } 149 }
150 } 150 }
151
152 pub fn definition_visibility(&self, db: &dyn HirDatabase) -> Option<Visibility> {
153 let module = match self {
154 ModuleDef::Module(it) => it.parent(db)?,
155 ModuleDef::Function(it) => return Some(it.visibility(db)),
156 ModuleDef::Adt(it) => it.module(db),
157 ModuleDef::EnumVariant(it) => {
158 let parent = it.parent_enum(db);
159 let module = it.module(db);
160 return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent)));
161 }
162 ModuleDef::Const(it) => return Some(it.visibility(db)),
163 ModuleDef::Static(it) => it.module(db),
164 ModuleDef::Trait(it) => it.module(db),
165 ModuleDef::TypeAlias(it) => return Some(it.visibility(db)),
166 ModuleDef::BuiltinType(_) => return None,
167 };
168
169 module.visibility_of(db, self)
170 }
151} 171}
152 172
153pub use hir_def::{ 173pub use hir_def::{
@@ -678,6 +698,10 @@ impl Static {
678 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 698 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
679 db.static_data(self.id).name.clone() 699 db.static_data(self.id).name.clone()
680 } 700 }
701
702 pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
703 db.static_data(self.id).mutable
704 }
681} 705}
682 706
683#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 707#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -965,6 +989,17 @@ impl TypeParam {
965 ty: InEnvironment { value: ty, environment }, 989 ty: InEnvironment { value: ty, environment },
966 } 990 }
967 } 991 }
992
993 pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
994 let params = db.generic_defaults(self.id.parent);
995 let local_idx = hir_ty::param_idx(db, self.id)?;
996 let resolver = self.id.parent.resolver(db.upcast());
997 let environment = TraitEnvironment::lower(db, &resolver);
998 params.get(local_idx).cloned().map(|ty| Type {
999 krate: self.id.parent.module(db.upcast()).krate,
1000 ty: InEnvironment { value: ty, environment },
1001 })
1002 }
968} 1003}
969 1004
970// FIXME: rename from `ImplDef` to `Impl` 1005// FIXME: rename from `ImplDef` to `Impl`
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index e7eb2bb11..e2130d931 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -251,11 +251,6 @@ impl ConstData {
251 Arc::new(ConstData::new(db, vis_default, node)) 251 Arc::new(ConstData::new(db, vis_default, node))
252 } 252 }
253 253
254 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<ConstData> {
255 let node = konst.lookup(db).source(db);
256 Arc::new(ConstData::new(db, RawVisibility::private(), node))
257 }
258
259 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>( 254 fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(
260 db: &dyn DefDatabase, 255 db: &dyn DefDatabase,
261 vis_default: RawVisibility, 256 vis_default: RawVisibility,
@@ -270,6 +265,32 @@ impl ConstData {
270 } 265 }
271} 266}
272 267
268#[derive(Debug, Clone, PartialEq, Eq)]
269pub struct StaticData {
270 pub name: Option<Name>,
271 pub type_ref: TypeRef,
272 pub visibility: RawVisibility,
273 pub mutable: bool,
274}
275
276impl StaticData {
277 pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
278 let node = konst.lookup(db).source(db);
279 let ctx = LowerCtx::new(db, node.file_id);
280
281 let name = node.value.name().map(|n| n.as_name());
282 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
283 let mutable = node.value.mut_token().is_some();
284 let visibility = RawVisibility::from_ast_with_default(
285 db,
286 RawVisibility::private(),
287 node.map(|n| n.visibility()),
288 );
289
290 Arc::new(StaticData { name, type_ref, visibility, mutable })
291 }
292}
293
273fn collect_items_in_macros( 294fn collect_items_in_macros(
274 db: &dyn DefDatabase, 295 db: &dyn DefDatabase,
275 expander: &mut Expander, 296 expander: &mut Expander,
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 5dc7395f5..e665ab45d 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -10,7 +10,7 @@ use crate::{
10 adt::{EnumData, StructData}, 10 adt::{EnumData, StructData},
11 attr::Attrs, 11 attr::Attrs,
12 body::{scope::ExprScopes, Body, BodySourceMap}, 12 body::{scope::ExprScopes, Body, BodySourceMap},
13 data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData}, 13 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData},
14 docs::Documentation, 14 docs::Documentation,
15 generics::GenericParams, 15 generics::GenericParams,
16 lang_item::{LangItemTarget, LangItems}, 16 lang_item::{LangItemTarget, LangItems},
@@ -77,8 +77,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
77 #[salsa::invoke(ConstData::const_data_query)] 77 #[salsa::invoke(ConstData::const_data_query)]
78 fn const_data(&self, konst: ConstId) -> Arc<ConstData>; 78 fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
79 79
80 #[salsa::invoke(ConstData::static_data_query)] 80 #[salsa::invoke(StaticData::static_data_query)]
81 fn static_data(&self, konst: StaticId) -> Arc<ConstData>; 81 fn static_data(&self, konst: StaticId) -> Arc<StaticData>;
82 82
83 #[salsa::invoke(Body::body_with_source_map_query)] 83 #[salsa::invoke(Body::body_with_source_map_query)]
84 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 84 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
index d8b3d342c..3bce8f673 100644
--- a/crates/ra_hir_expand/src/builtin_macro.rs
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -360,7 +360,7 @@ fn env_expand(
360 // However, we cannot use an empty string here, because for 360 // However, we cannot use an empty string here, because for
361 // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become 361 // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become
362 // `include!("foo.rs"), which might go to infinite loop 362 // `include!("foo.rs"), which might go to infinite loop
363 let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTATED__".to_string()); 363 let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTED__".to_string());
364 let expanded = quote! { #s }; 364 let expanded = quote! { #s };
365 365
366 Ok((expanded, FragmentKind::Expr)) 366 Ok((expanded, FragmentKind::Expr))
@@ -508,7 +508,7 @@ mod tests {
508 "#, 508 "#,
509 ); 509 );
510 510
511 assert_eq!(expanded, "\"__RA_UNIMPLEMENTATED__\""); 511 assert_eq!(expanded, "\"__RA_UNIMPLEMENTED__\"");
512 } 512 }
513 513
514 #[test] 514 #[test]
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index f5edaea8c..b9c4d2e89 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -136,6 +136,12 @@ enum DisplayTarget {
136 SourceCode { module_id: ModuleId }, 136 SourceCode { module_id: ModuleId },
137} 137}
138 138
139impl DisplayTarget {
140 fn is_source_code(&self) -> bool {
141 matches!(self, Self::SourceCode {..})
142 }
143}
144
139#[derive(Debug)] 145#[derive(Debug)]
140pub enum DisplaySourceCodeError { 146pub enum DisplaySourceCodeError {
141 PathNotFound, 147 PathNotFound,
@@ -303,37 +309,40 @@ impl HirDisplay for ApplicationTy {
303 309
304 if self.parameters.len() > 0 { 310 if self.parameters.len() > 0 {
305 let mut non_default_parameters = Vec::with_capacity(self.parameters.len()); 311 let mut non_default_parameters = Vec::with_capacity(self.parameters.len());
306 let parameters_to_write = if f.omit_verbose_types() { 312 let parameters_to_write =
307 match self 313 if f.display_target.is_source_code() || f.omit_verbose_types() {
308 .ctor 314 match self
309 .as_generic_def() 315 .ctor
310 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 316 .as_generic_def()
311 .filter(|defaults| !defaults.is_empty()) 317 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
312 { 318 .filter(|defaults| !defaults.is_empty())
313 None => self.parameters.0.as_ref(), 319 {
314 Some(default_parameters) => { 320 None => self.parameters.0.as_ref(),
315 for (i, parameter) in self.parameters.iter().enumerate() { 321 Some(default_parameters) => {
316 match (parameter, default_parameters.get(i)) { 322 for (i, parameter) in self.parameters.iter().enumerate() {
317 (&Ty::Unknown, _) | (_, None) => { 323 match (parameter, default_parameters.get(i)) {
318 non_default_parameters.push(parameter.clone()) 324 (&Ty::Unknown, _) | (_, None) => {
319 } 325 non_default_parameters.push(parameter.clone())
320 (_, Some(default_parameter)) 326 }
321 if parameter != default_parameter => 327 (_, Some(default_parameter))
322 { 328 if parameter != default_parameter =>
323 non_default_parameters.push(parameter.clone()) 329 {
330 non_default_parameters.push(parameter.clone())
331 }
332 _ => (),
324 } 333 }
325 _ => (),
326 } 334 }
335 &non_default_parameters
327 } 336 }
328 &non_default_parameters
329 } 337 }
330 } 338 } else {
331 } else { 339 self.parameters.0.as_ref()
332 self.parameters.0.as_ref() 340 };
333 }; 341 if !parameters_to_write.is_empty() {
334 write!(f, "<")?; 342 write!(f, "<")?;
335 f.write_joined(parameters_to_write, ", ")?; 343 f.write_joined(parameters_to_write, ", ")?;
336 write!(f, ">")?; 344 write!(f, ">")?;
345 }
337 } 346 }
338 } 347 }
339 TypeCtor::AssociatedType(type_alias) => { 348 TypeCtor::AssociatedType(type_alias) => {
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index a21ad8d86..fb7c6cd8c 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -22,7 +22,7 @@ use rustc_hash::FxHashMap;
22 22
23use hir_def::{ 23use hir_def::{
24 body::Body, 24 body::Body,
25 data::{ConstData, FunctionData}, 25 data::{ConstData, FunctionData, StaticData},
26 expr::{BindingAnnotation, ExprId, PatId}, 26 expr::{BindingAnnotation, ExprId, PatId},
27 lang_item::LangItemTarget, 27 lang_item::LangItemTarget,
28 path::{path, Path}, 28 path::{path, Path},
@@ -71,7 +71,7 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
71 match def { 71 match def {
72 DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)), 72 DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
73 DefWithBodyId::FunctionId(f) => ctx.collect_fn(&db.function_data(f)), 73 DefWithBodyId::FunctionId(f) => ctx.collect_fn(&db.function_data(f)),
74 DefWithBodyId::StaticId(s) => ctx.collect_const(&db.static_data(s)), 74 DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
75 } 75 }
76 76
77 ctx.infer_body(); 77 ctx.infer_body();
@@ -485,6 +485,10 @@ impl<'a> InferenceContext<'a> {
485 self.return_ty = self.make_ty(&data.type_ref); 485 self.return_ty = self.make_ty(&data.type_ref);
486 } 486 }
487 487
488 fn collect_static(&mut self, data: &StaticData) {
489 self.return_ty = self.make_ty(&data.type_ref);
490 }
491
488 fn collect_fn(&mut self, data: &FunctionData) { 492 fn collect_fn(&mut self, data: &FunctionData) {
489 let body = Arc::clone(&self.body); // avoid borrow checker problem 493 let body = Arc::clone(&self.body); // avoid borrow checker problem
490 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver) 494 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index e8f3482fe..ccc4348f4 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -427,6 +427,11 @@ impl Substs {
427 } 427 }
428} 428}
429 429
430/// Return an index of a parameter in the generic type parameter list by it's id.
431pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
432 generics(db.upcast(), id.parent).param_idx(id)
433}
434
430#[derive(Debug, Clone)] 435#[derive(Debug, Clone)]
431pub struct SubstsBuilder { 436pub struct SubstsBuilder {
432 vec: Vec<Ty>, 437 vec: Vec<Ty>,
diff --git a/crates/ra_hir_ty/src/op.rs b/crates/ra_hir_ty/src/op.rs
index 54e2bd05a..0870874fc 100644
--- a/crates/ra_hir_ty/src/op.rs
+++ b/crates/ra_hir_ty/src/op.rs
@@ -30,7 +30,8 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
30pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { 30pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
31 match op { 31 match op {
32 BinaryOp::LogicOp(..) => Ty::simple(TypeCtor::Bool), 32 BinaryOp::LogicOp(..) => Ty::simple(TypeCtor::Bool),
33 BinaryOp::Assignment { op: None } | BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty { 33 BinaryOp::Assignment { op: None } => lhs_ty,
34 BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty {
34 Ty::Apply(ApplicationTy { ctor, .. }) => match ctor { 35 Ty::Apply(ApplicationTy { ctor, .. }) => match ctor {
35 TypeCtor::Int(..) 36 TypeCtor::Int(..)
36 | TypeCtor::Float(..) 37 | TypeCtor::Float(..)
diff --git a/crates/ra_hir_ty/src/tests/display_source_code.rs b/crates/ra_hir_ty/src/tests/display_source_code.rs
index ca1748615..4088b1d22 100644
--- a/crates/ra_hir_ty/src/tests/display_source_code.rs
+++ b/crates/ra_hir_ty/src/tests/display_source_code.rs
@@ -21,3 +21,30 @@ fn bar() {
21 ); 21 );
22 assert_eq!("foo::Foo", displayed_source_at_pos(&db, pos)); 22 assert_eq!("foo::Foo", displayed_source_at_pos(&db, pos));
23} 23}
24
25#[test]
26fn omit_default_type_parameters() {
27 let (db, pos) = TestDB::with_position(
28 r"
29 //- /main.rs
30 struct Foo<T = u8> { t: T }
31 fn main() {
32 let foo = Foo { t: 5 };
33 foo<|>;
34 }
35 ",
36 );
37 assert_eq!("Foo", displayed_source_at_pos(&db, pos));
38
39 let (db, pos) = TestDB::with_position(
40 r"
41 //- /main.rs
42 struct Foo<K, T = u8> { k: K, t: T }
43 fn main() {
44 let foo = Foo { k: 400, t: 5 };
45 foo<|>;
46 }
47 ",
48 );
49 assert_eq!("Foo<i32>", displayed_source_at_pos(&db, pos));
50}
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index 3820175f6..322838f02 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -1787,3 +1787,32 @@ fn main() {
1787 "### 1787 "###
1788 ) 1788 )
1789} 1789}
1790
1791#[test]
1792fn infer_generic_from_later_assignment() {
1793 assert_snapshot!(
1794 infer(r#"
1795enum Option<T> { Some(T), None }
1796use Option::*;
1797
1798fn test() {
1799 let mut end = None;
1800 loop {
1801 end = Some(true);
1802 }
1803}
1804"#),
1805 @r###"
1806 60..130 '{ ... } }': ()
1807 70..77 'mut end': Option<bool>
1808 80..84 'None': Option<bool>
1809 90..128 'loop {... }': !
1810 95..128 '{ ... }': ()
1811 105..108 'end': Option<bool>
1812 105..121 'end = ...(true)': ()
1813 111..115 'Some': Some<bool>(bool) -> Option<bool>
1814 111..121 'Some(true)': Option<bool>
1815 116..120 'true': bool
1816 "###
1817 );
1818}
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs
index 6a0f0c72e..f2a52a407 100644
--- a/crates/ra_ide/src/completion/complete_postfix.rs
+++ b/crates/ra_ide/src/completion/complete_postfix.rs
@@ -14,6 +14,7 @@ use crate::{
14 }, 14 },
15 CompletionItem, 15 CompletionItem,
16}; 16};
17use ra_assists::utils::TryEnum;
17 18
18pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { 19pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
19 if !ctx.config.enable_postfix_completions { 20 if !ctx.config.enable_postfix_completions {
@@ -37,8 +38,53 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
37 Some(it) => it, 38 Some(it) => it,
38 None => return, 39 None => return,
39 }; 40 };
41 let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty);
42 if let Some(try_enum) = &try_enum {
43 match try_enum {
44 TryEnum::Result => {
45 postfix_snippet(
46 ctx,
47 cap,
48 &dot_receiver,
49 "ifl",
50 "if let Ok {}",
51 &format!("if let Ok($1) = {} {{\n $0\n}}", receiver_text),
52 )
53 .add_to(acc);
40 54
41 if receiver_ty.is_bool() || receiver_ty.is_unknown() { 55 postfix_snippet(
56 ctx,
57 cap,
58 &dot_receiver,
59 "while",
60 "while let Ok {}",
61 &format!("while let Ok($1) = {} {{\n $0\n}}", receiver_text),
62 )
63 .add_to(acc);
64 }
65 TryEnum::Option => {
66 postfix_snippet(
67 ctx,
68 cap,
69 &dot_receiver,
70 "ifl",
71 "if let Some {}",
72 &format!("if let Some($1) = {} {{\n $0\n}}", receiver_text),
73 )
74 .add_to(acc);
75
76 postfix_snippet(
77 ctx,
78 cap,
79 &dot_receiver,
80 "while",
81 "while let Some {}",
82 &format!("while let Some($1) = {} {{\n $0\n}}", receiver_text),
83 )
84 .add_to(acc);
85 }
86 }
87 } else if receiver_ty.is_bool() || receiver_ty.is_unknown() {
42 postfix_snippet( 88 postfix_snippet(
43 ctx, 89 ctx,
44 cap, 90 cap,
@@ -58,7 +104,6 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
58 ) 104 )
59 .add_to(acc); 105 .add_to(acc);
60 } 106 }
61
62 // !&&&42 is a compiler error, ergo process it before considering the references 107 // !&&&42 is a compiler error, ergo process it before considering the references
63 postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text)) 108 postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text))
64 .add_to(acc); 109 .add_to(acc);
@@ -80,16 +125,45 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
80 let dot_receiver = include_references(dot_receiver); 125 let dot_receiver = include_references(dot_receiver);
81 let receiver_text = 126 let receiver_text =
82 get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal); 127 get_receiver_text(&dot_receiver, ctx.dot_receiver_is_ambiguous_float_literal);
83 128 match try_enum {
84 postfix_snippet( 129 Some(try_enum) => {
85 ctx, 130 match try_enum {
86 cap, 131 TryEnum::Result => {
87 &dot_receiver, 132 postfix_snippet(
88 "match", 133 ctx,
89 "match expr {}", 134 cap,
90 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text), 135 &dot_receiver,
91 ) 136 "match",
92 .add_to(acc); 137 "match expr {}",
138 &format!("match {} {{\n Ok(${{1:_}}) => {{$2\\}},\n Err(${{3:_}}) => {{$0\\}},\n}}", receiver_text),
139 )
140 .add_to(acc);
141 }
142 TryEnum::Option => {
143 postfix_snippet(
144 ctx,
145 cap,
146 &dot_receiver,
147 "match",
148 "match expr {}",
149 &format!("match {} {{\n Some(${{1:_}}) => {{$2\\}},\n None => {{$0\\}},\n}}", receiver_text),
150 )
151 .add_to(acc);
152 }
153 }
154 }
155 None => {
156 postfix_snippet(
157 ctx,
158 cap,
159 &dot_receiver,
160 "match",
161 "match expr {}",
162 &format!("match {} {{\n ${{1:_}} => {{$0\\}},\n}}", receiver_text),
163 )
164 .add_to(acc);
165 }
166 }
93 167
94 postfix_snippet( 168 postfix_snippet(
95 ctx, 169 ctx,
@@ -236,6 +310,164 @@ mod tests {
236 } 310 }
237 311
238 #[test] 312 #[test]
313 fn postfix_completion_works_for_option() {
314 assert_debug_snapshot!(
315 do_postfix_completion(
316 r#"
317 enum Option<T> {
318 Some(T),
319 None,
320 }
321
322 fn main() {
323 let bar = Option::Some(true);
324 bar.<|>
325 }
326 "#,
327 ),
328 @r###"
329 [
330 CompletionItem {
331 label: "box",
332 source_range: 210..210,
333 delete: 206..210,
334 insert: "Box::new(bar)",
335 detail: "Box::new(expr)",
336 },
337 CompletionItem {
338 label: "dbg",
339 source_range: 210..210,
340 delete: 206..210,
341 insert: "dbg!(bar)",
342 detail: "dbg!(expr)",
343 },
344 CompletionItem {
345 label: "ifl",
346 source_range: 210..210,
347 delete: 206..210,
348 insert: "if let Some($1) = bar {\n $0\n}",
349 detail: "if let Some {}",
350 },
351 CompletionItem {
352 label: "match",
353 source_range: 210..210,
354 delete: 206..210,
355 insert: "match bar {\n Some(${1:_}) => {$2\\},\n None => {$0\\},\n}",
356 detail: "match expr {}",
357 },
358 CompletionItem {
359 label: "not",
360 source_range: 210..210,
361 delete: 206..210,
362 insert: "!bar",
363 detail: "!expr",
364 },
365 CompletionItem {
366 label: "ref",
367 source_range: 210..210,
368 delete: 206..210,
369 insert: "&bar",
370 detail: "&expr",
371 },
372 CompletionItem {
373 label: "refm",
374 source_range: 210..210,
375 delete: 206..210,
376 insert: "&mut bar",
377 detail: "&mut expr",
378 },
379 CompletionItem {
380 label: "while",
381 source_range: 210..210,
382 delete: 206..210,
383 insert: "while let Some($1) = bar {\n $0\n}",
384 detail: "while let Some {}",
385 },
386 ]
387 "###
388 );
389 }
390
391 #[test]
392 fn postfix_completion_works_for_result() {
393 assert_debug_snapshot!(
394 do_postfix_completion(
395 r#"
396 enum Result<T, E> {
397 Ok(T),
398 Err(E),
399 }
400
401 fn main() {
402 let bar = Result::Ok(true);
403 bar.<|>
404 }
405 "#,
406 ),
407 @r###"
408 [
409 CompletionItem {
410 label: "box",
411 source_range: 211..211,
412 delete: 207..211,
413 insert: "Box::new(bar)",
414 detail: "Box::new(expr)",
415 },
416 CompletionItem {
417 label: "dbg",
418 source_range: 211..211,
419 delete: 207..211,
420 insert: "dbg!(bar)",
421 detail: "dbg!(expr)",
422 },
423 CompletionItem {
424 label: "ifl",
425 source_range: 211..211,
426 delete: 207..211,
427 insert: "if let Ok($1) = bar {\n $0\n}",
428 detail: "if let Ok {}",
429 },
430 CompletionItem {
431 label: "match",
432 source_range: 211..211,
433 delete: 207..211,
434 insert: "match bar {\n Ok(${1:_}) => {$2\\},\n Err(${3:_}) => {$0\\},\n}",
435 detail: "match expr {}",
436 },
437 CompletionItem {
438 label: "not",
439 source_range: 211..211,
440 delete: 207..211,
441 insert: "!bar",
442 detail: "!expr",
443 },
444 CompletionItem {
445 label: "ref",
446 source_range: 211..211,
447 delete: 207..211,
448 insert: "&bar",
449 detail: "&expr",
450 },
451 CompletionItem {
452 label: "refm",
453 source_range: 211..211,
454 delete: 207..211,
455 insert: "&mut bar",
456 detail: "&mut expr",
457 },
458 CompletionItem {
459 label: "while",
460 source_range: 211..211,
461 delete: 207..211,
462 insert: "while let Ok($1) = bar {\n $0\n}",
463 detail: "while let Ok {}",
464 },
465 ]
466 "###
467 );
468 }
469
470 #[test]
239 fn some_postfix_completions_ignored() { 471 fn some_postfix_completions_ignored() {
240 assert_debug_snapshot!( 472 assert_debug_snapshot!(
241 do_postfix_completion( 473 do_postfix_completion(
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs
index a3f5d1b6a..0568d9ccf 100644
--- a/crates/ra_ide/src/completion/complete_snippet.rs
+++ b/crates/ra_ide/src/completion/complete_snippet.rs
@@ -36,6 +36,24 @@ pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionConte
36 snippet( 36 snippet(
37 ctx, 37 ctx,
38 cap, 38 cap,
39 "Test module",
40 "\
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn ${1:test_name}() {
47 $0
48 }
49}",
50 )
51 .lookup_by("tmod")
52 .add_to(acc);
53
54 snippet(
55 ctx,
56 cap,
39 "Test function", 57 "Test function",
40 "\ 58 "\
41#[test] 59#[test]
@@ -118,6 +136,14 @@ mod tests {
118 lookup: "tfn", 136 lookup: "tfn",
119 }, 137 },
120 CompletionItem { 138 CompletionItem {
139 label: "Test module",
140 source_range: 78..78,
141 delete: 78..78,
142 insert: "#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn ${1:test_name}() {\n $0\n }\n}",
143 kind: Snippet,
144 lookup: "tmod",
145 },
146 CompletionItem {
121 label: "macro_rules", 147 label: "macro_rules",
122 source_range: 78..78, 148 source_range: 78..78,
123 delete: 78..78, 149 delete: 78..78,
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index b6b9627de..da336973c 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -34,7 +34,7 @@ pub(crate) struct CompletionContext<'a> {
34 pub(super) record_pat_syntax: Option<ast::RecordPat>, 34 pub(super) record_pat_syntax: Option<ast::RecordPat>,
35 pub(super) record_field_syntax: Option<ast::RecordField>, 35 pub(super) record_field_syntax: Option<ast::RecordField>,
36 pub(super) impl_def: Option<ast::ImplDef>, 36 pub(super) impl_def: Option<ast::ImplDef>,
37 /// FIXME: `ActiveParameter` is string-based, which is very wrong 37 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
38 pub(super) active_parameter: Option<ActiveParameter>, 38 pub(super) active_parameter: Option<ActiveParameter>,
39 pub(super) is_param: bool, 39 pub(super) is_param: bool,
40 /// If a name-binding or reference to a const in a pattern. 40 /// If a name-binding or reference to a const in a pattern.
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 2edb130cf..077cf9647 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -17,12 +17,11 @@ use crate::{
17impl Completions { 17impl Completions {
18 pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) { 18 pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) {
19 let is_deprecated = is_deprecated(field, ctx.db); 19 let is_deprecated = is_deprecated(field, ctx.db);
20 let ty = ty.display(ctx.db).to_string();
21 let name = field.name(ctx.db); 20 let name = field.name(ctx.db);
22 let mut completion_item = 21 let mut completion_item =
23 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) 22 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
24 .kind(CompletionItemKind::Field) 23 .kind(CompletionItemKind::Field)
25 .detail(ty.clone()) 24 .detail(ty.display(ctx.db).to_string())
26 .set_documentation(field.docs(ctx.db)) 25 .set_documentation(field.docs(ctx.db))
27 .set_deprecated(is_deprecated); 26 .set_deprecated(is_deprecated);
28 27
@@ -107,6 +106,12 @@ impl Completions {
107 } 106 }
108 }; 107 };
109 108
109 if let ScopeDef::Local(local) = resolution {
110 if let Some(score) = compute_score(ctx, &local.ty(ctx.db), &local_name) {
111 completion_item = completion_item.set_score(score);
112 }
113 }
114
110 // Add `<>` for generic types 115 // Add `<>` for generic types
111 if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis { 116 if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis {
112 if let Some(cap) = ctx.config.snippet_cap { 117 if let Some(cap) = ctx.config.snippet_cap {
@@ -319,10 +324,11 @@ impl Completions {
319 324
320pub(crate) fn compute_score( 325pub(crate) fn compute_score(
321 ctx: &CompletionContext, 326 ctx: &CompletionContext,
322 // FIXME: this definitely should be a `Type` 327 ty: &Type,
323 ty: &str,
324 name: &str, 328 name: &str,
325) -> Option<CompletionScore> { 329) -> Option<CompletionScore> {
330 // FIXME: this should not fall back to string equality.
331 let ty = &ty.display(ctx.db).to_string();
326 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { 332 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
327 tested_by!(test_struct_field_completion_in_record_lit); 333 tested_by!(test_struct_field_completion_in_record_lit);
328 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; 334 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?;
@@ -1405,4 +1411,48 @@ mod tests {
1405 "### 1411 "###
1406 ); 1412 );
1407 } 1413 }
1414
1415 #[test]
1416 fn prioritize_exact_ref_match() {
1417 assert_debug_snapshot!(
1418 do_reference_completion(
1419 r"
1420 struct WorldSnapshot { _f: () };
1421 fn go(world: &WorldSnapshot) {
1422 go(w<|>)
1423 }
1424 ",
1425 ),
1426 @r###"
1427 [
1428 CompletionItem {
1429 label: "WorldSnapshot",
1430 source_range: 132..133,
1431 delete: 132..133,
1432 insert: "WorldSnapshot",
1433 kind: Struct,
1434 },
1435 CompletionItem {
1436 label: "go(…)",
1437 source_range: 132..133,
1438 delete: 132..133,
1439 insert: "go(${1:world})$0",
1440 kind: Function,
1441 lookup: "go",
1442 detail: "fn go(world: &WorldSnapshot)",
1443 trigger_call_info: true,
1444 },
1445 CompletionItem {
1446 label: "world",
1447 source_range: 132..133,
1448 delete: 132..133,
1449 insert: "world",
1450 kind: Binding,
1451 detail: "&WorldSnapshot",
1452 score: TypeAndNameMatch,
1453 },
1454 ]
1455 "###
1456 );
1457 }
1408} 1458}
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index de35c6711..5da28edd2 100644
--- a/crates/ra_ide/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11 TextRange, 11 TextRange,
12}; 12};
13 13
14use crate::FileSymbol; 14use crate::{FileRange, FileSymbol};
15 15
16use super::short_label::ShortLabel; 16use super::short_label::ShortLabel;
17 17
@@ -22,10 +22,11 @@ use super::short_label::ShortLabel;
22/// code, like a function or a struct, but this is not strictly required. 22/// code, like a function or a struct, but this is not strictly required.
23#[derive(Debug, Clone, PartialEq, Eq, Hash)] 23#[derive(Debug, Clone, PartialEq, Eq, Hash)]
24pub struct NavigationTarget { 24pub struct NavigationTarget {
25 // FIXME: use FileRange?
25 file_id: FileId, 26 file_id: FileId,
27 full_range: TextRange,
26 name: SmolStr, 28 name: SmolStr,
27 kind: SyntaxKind, 29 kind: SyntaxKind,
28 full_range: TextRange,
29 focus_range: Option<TextRange>, 30 focus_range: Option<TextRange>,
30 container_name: Option<SmolStr>, 31 container_name: Option<SmolStr>,
31 description: Option<String>, 32 description: Option<String>,
@@ -63,6 +64,10 @@ impl NavigationTarget {
63 self.file_id 64 self.file_id
64 } 65 }
65 66
67 pub fn file_range(&self) -> FileRange {
68 FileRange { file_id: self.file_id, range: self.full_range }
69 }
70
66 pub fn full_range(&self) -> TextRange { 71 pub fn full_range(&self) -> TextRange {
67 self.full_range 72 self.full_range
68 } 73 }
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 915199bd8..78149ddfc 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -176,14 +176,10 @@ impl AnalysisHost {
176 pub fn request_cancellation(&mut self) { 176 pub fn request_cancellation(&mut self) {
177 self.db.request_cancellation(); 177 self.db.request_cancellation();
178 } 178 }
179 pub fn raw_database( 179 pub fn raw_database(&self) -> &RootDatabase {
180 &self,
181 ) -> &(impl hir::db::HirDatabase + salsa::Database + ra_db::SourceDatabaseExt) {
182 &self.db 180 &self.db
183 } 181 }
184 pub fn raw_database_mut( 182 pub fn raw_database_mut(&mut self) -> &mut RootDatabase {
185 &mut self,
186 ) -> &mut (impl hir::db::HirDatabase + salsa::Database + ra_db::SourceDatabaseExt) {
187 &mut self.db 183 &mut self.db
188 } 184 }
189} 185}
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs
index 555ccf295..074284b42 100644
--- a/crates/ra_ide/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -593,6 +593,31 @@ mod tests {
593 check_result(refs, "i BIND_PAT FileId(1) 36..37 Other", &["FileId(1) 51..52 Other Write"]); 593 check_result(refs, "i BIND_PAT FileId(1) 36..37 Other", &["FileId(1) 51..52 Other Write"]);
594 } 594 }
595 595
596 #[test]
597 fn test_find_struct_function_refs_outside_module() {
598 let code = r#"
599 mod foo {
600 pub struct Foo;
601
602 impl Foo {
603 pub fn new<|>() -> Foo {
604 Foo
605 }
606 }
607 }
608
609 fn main() {
610 let _f = foo::Foo::new();
611 }"#;
612
613 let refs = get_all_refs(code);
614 check_result(
615 refs,
616 "new FN_DEF FileId(1) 87..150 94..97 Other",
617 &["FileId(1) 227..230 StructLiteral"],
618 );
619 }
620
596 fn get_all_refs(text: &str) -> ReferenceSearchResult { 621 fn get_all_refs(text: &str) -> ReferenceSearchResult {
597 let (analysis, position) = single_file_with_position(text); 622 let (analysis, position) = single_file_with_position(text);
598 analysis.find_all_refs(position, None).unwrap().unwrap() 623 analysis.find_all_refs(position, None).unwrap().unwrap()
diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/src/snapshots/highlight_strings.html
index de06daf72..752b487e8 100644
--- a/crates/ra_ide/src/snapshots/highlight_strings.html
+++ b/crates/ra_ide/src/snapshots/highlight_strings.html
@@ -27,13 +27,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
27.keyword.unsafe { color: #BC8383; font-weight: bold; } 27.keyword.unsafe { color: #BC8383; font-weight: bold; }
28.control { font-style: italic; } 28.control { font-style: italic; }
29</style> 29</style>
30<pre><code><span class="macro">macro_rules!</span> println { 30<pre><code><span class="macro">macro_rules!</span> <span class="macro declaration">println</span> {
31 ($($arg:tt)*) =&gt; ({ 31 ($($arg:tt)*) =&gt; ({
32 $<span class="keyword">crate</span>::io::_print($<span class="keyword">crate</span>::format_args_nl!($($arg)*)); 32 $<span class="keyword">crate</span>::io::_print($<span class="keyword">crate</span>::format_args_nl!($($arg)*));
33 }) 33 })
34} 34}
35#[rustc_builtin_macro] 35#[rustc_builtin_macro]
36<span class="macro">macro_rules!</span> format_args_nl { 36<span class="macro">macro_rules!</span> <span class="macro declaration">format_args_nl</span> {
37 ($fmt:expr) =&gt; {{ <span class="comment">/* compiler built-in */</span> }}; 37 ($fmt:expr) =&gt; {{ <span class="comment">/* compiler built-in */</span> }};
38 ($fmt:expr, $($args:tt)*) =&gt; {{ <span class="comment">/* compiler built-in */</span> }}; 38 ($fmt:expr, $($args:tt)*) =&gt; {{ <span class="comment">/* compiler built-in */</span> }};
39} 39}
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html
index 4b12fe823..635fe5cf9 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/src/snapshots/highlighting.html
@@ -33,11 +33,23 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
33 <span class="keyword">pub</span> <span class="field declaration">y</span>: <span class="builtin_type">i32</span>, 33 <span class="keyword">pub</span> <span class="field declaration">y</span>: <span class="builtin_type">i32</span>,
34} 34}
35 35
36<span class="keyword">trait</span> <span class="trait declaration">Bar</span> {
37 <span class="keyword">fn</span> <span class="function declaration">bar</span>(&<span class="keyword">self</span>) -&gt; <span class="builtin_type">i32</span>;
38}
39
40<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> {
41 <span class="keyword">fn</span> <span class="function declaration">bar</span>(&<span class="keyword">self</span>) -&gt; <span class="builtin_type">i32</span> {
42 <span class="keyword">self</span>.<span class="field">x</span>
43 }
44}
45
46<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable">STATIC_MUT</span>: <span class="builtin_type">i32</span> = <span class="numeric_literal">0</span>;
47
36<span class="keyword">fn</span> <span class="function declaration">foo</span>&lt;<span class="lifetime declaration">'a</span>, <span class="type_param declaration">T</span>&gt;() -&gt; <span class="type_param">T</span> { 48<span class="keyword">fn</span> <span class="function declaration">foo</span>&lt;<span class="lifetime declaration">'a</span>, <span class="type_param declaration">T</span>&gt;() -&gt; <span class="type_param">T</span> {
37 <span class="function">foo</span>::&lt;<span class="lifetime">'a</span>, <span class="builtin_type">i32</span>&gt;() 49 <span class="function">foo</span>::&lt;<span class="lifetime">'a</span>, <span class="builtin_type">i32</span>&gt;()
38} 50}
39 51
40<span class="macro">macro_rules!</span> def_fn { 52<span class="macro">macro_rules!</span> <span class="macro declaration">def_fn</span> {
41 ($($tt:tt)*) =&gt; {$($tt)*} 53 ($($tt:tt)*) =&gt; {$($tt)*}
42} 54}
43 55
@@ -56,7 +68,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
56 <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>; 68 <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>;
57 <span class="variable mutable">vec</span>.<span class="unresolved_reference">push</span>(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> }); 69 <span class="variable mutable">vec</span>.<span class="unresolved_reference">push</span>(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> });
58 } 70 }
59 <span class="keyword unsafe">unsafe</span> { <span class="variable mutable">vec</span>.<span class="unresolved_reference">set_len</span>(<span class="numeric_literal">0</span>); } 71 <span class="keyword unsafe">unsafe</span> {
72 <span class="variable mutable">vec</span>.<span class="unresolved_reference">set_len</span>(<span class="numeric_literal">0</span>);
73 <span class="static mutable">STATIC_MUT</span> = <span class="numeric_literal">1</span>;
74 }
75
76 <span class="keyword control">for</span> <span class="variable declaration">e</span> <span class="keyword control">in</span> <span class="variable mutable">vec</span> {
77 <span class="comment">// Do nothing</span>
78 }
60 79
61 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; 80 <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>;
62 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; 81 <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>;
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 6658c7bb2..be57eeb0a 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -167,6 +167,19 @@ pub(crate) fn highlight(
167 binding_hash: None, 167 binding_hash: None,
168 }); 168 });
169 } 169 }
170 if let Some(name) = mc.is_macro_rules() {
171 if let Some((highlight, binding_hash)) = highlight_element(
172 &sema,
173 &mut bindings_shadow_count,
174 name.syntax().clone().into(),
175 ) {
176 stack.add(HighlightedRange {
177 range: name.syntax().text_range(),
178 highlight,
179 binding_hash,
180 });
181 }
182 }
170 continue; 183 continue;
171 } 184 }
172 WalkEvent::Leave(Some(mc)) => { 185 WalkEvent::Leave(Some(mc)) => {
@@ -390,12 +403,13 @@ fn highlight_element(
390 T![break] 403 T![break]
391 | T![continue] 404 | T![continue]
392 | T![else] 405 | T![else]
393 | T![for]
394 | T![if] 406 | T![if]
395 | T![loop] 407 | T![loop]
396 | T![match] 408 | T![match]
397 | T![return] 409 | T![return]
398 | T![while] => h | HighlightModifier::ControlFlow, 410 | T![while]
411 | T![in] => h | HighlightModifier::ControlFlow,
412 T![for] if !is_child_of_impl(element) => h | HighlightModifier::ControlFlow,
399 T![unsafe] => h | HighlightModifier::Unsafe, 413 T![unsafe] => h | HighlightModifier::Unsafe,
400 _ => h, 414 _ => h,
401 } 415 }
@@ -419,6 +433,13 @@ fn highlight_element(
419 } 433 }
420} 434}
421 435
436fn is_child_of_impl(element: SyntaxElement) -> bool {
437 match element.parent() {
438 Some(e) => e.kind() == IMPL_DEF,
439 _ => false,
440 }
441}
442
422fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { 443fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
423 match def { 444 match def {
424 Definition::Macro(_) => HighlightTag::Macro, 445 Definition::Macro(_) => HighlightTag::Macro,
@@ -431,10 +452,16 @@ fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight {
431 hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union, 452 hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union,
432 hir::ModuleDef::EnumVariant(_) => HighlightTag::EnumVariant, 453 hir::ModuleDef::EnumVariant(_) => HighlightTag::EnumVariant,
433 hir::ModuleDef::Const(_) => HighlightTag::Constant, 454 hir::ModuleDef::Const(_) => HighlightTag::Constant,
434 hir::ModuleDef::Static(_) => HighlightTag::Static,
435 hir::ModuleDef::Trait(_) => HighlightTag::Trait, 455 hir::ModuleDef::Trait(_) => HighlightTag::Trait,
436 hir::ModuleDef::TypeAlias(_) => HighlightTag::TypeAlias, 456 hir::ModuleDef::TypeAlias(_) => HighlightTag::TypeAlias,
437 hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType, 457 hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType,
458 hir::ModuleDef::Static(s) => {
459 let mut h = Highlight::new(HighlightTag::Static);
460 if s.is_mut(db) {
461 h |= HighlightModifier::Mutable;
462 }
463 return h;
464 }
438 }, 465 },
439 Definition::SelfType(_) => HighlightTag::SelfType, 466 Definition::SelfType(_) => HighlightTag::SelfType,
440 Definition::TypeParam(_) => HighlightTag::TypeParam, 467 Definition::TypeParam(_) => HighlightTag::TypeParam,
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs
index d2926ba78..eb43a23da 100644
--- a/crates/ra_ide/src/syntax_highlighting/tests.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tests.rs
@@ -17,6 +17,18 @@ struct Foo {
17 pub y: i32, 17 pub y: i32,
18} 18}
19 19
20trait Bar {
21 fn bar(&self) -> i32;
22}
23
24impl Bar for Foo {
25 fn bar(&self) -> i32 {
26 self.x
27 }
28}
29
30static mut STATIC_MUT: i32 = 0;
31
20fn foo<'a, T>() -> T { 32fn foo<'a, T>() -> T {
21 foo::<'a, i32>() 33 foo::<'a, i32>()
22} 34}
@@ -40,7 +52,14 @@ fn main() {
40 let x = 92; 52 let x = 92;
41 vec.push(Foo { x, y: 1 }); 53 vec.push(Foo { x, y: 1 });
42 } 54 }
43 unsafe { vec.set_len(0); } 55 unsafe {
56 vec.set_len(0);
57 STATIC_MUT = 1;
58 }
59
60 for e in vec {
61 // Do nothing
62 }
44 63
45 let mut x = 42; 64 let mut x = 42;
46 let y = &mut x; 65 let y = &mut x;
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index f990e3bb9..60c11178e 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -6,7 +6,7 @@
6// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). 6// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
7 7
8use hir::{ 8use hir::{
9 Adt, Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution, 9 Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution,
10 Semantics, TypeParam, Visibility, 10 Semantics, TypeParam, Visibility,
11}; 11};
12use ra_prof::profile; 12use ra_prof::profile;
@@ -42,18 +42,10 @@ impl Definition {
42 } 42 }
43 43
44 pub fn visibility(&self, db: &RootDatabase) -> Option<Visibility> { 44 pub fn visibility(&self, db: &RootDatabase) -> Option<Visibility> {
45 let module = self.module(db);
46
47 match self { 45 match self {
48 Definition::Macro(_) => None, 46 Definition::Macro(_) => None,
49 Definition::Field(sf) => Some(sf.visibility(db)), 47 Definition::Field(sf) => Some(sf.visibility(db)),
50 Definition::ModuleDef(def) => match def { 48 Definition::ModuleDef(def) => def.definition_visibility(db),
51 ModuleDef::EnumVariant(id) => {
52 let parent = id.parent_enum(db);
53 module?.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent)))
54 }
55 _ => module?.visibility_of(db, def),
56 },
57 Definition::SelfType(_) => None, 49 Definition::SelfType(_) => None,
58 Definition::Local(_) => None, 50 Definition::Local(_) => None,
59 Definition::TypeParam(_) => None, 51 Definition::TypeParam(_) => None,
diff --git a/crates/ra_proc_macro_srv/Cargo.toml b/crates/ra_proc_macro_srv/Cargo.toml
index 886e14870..bb3003278 100644
--- a/crates/ra_proc_macro_srv/Cargo.toml
+++ b/crates/ra_proc_macro_srv/Cargo.toml
@@ -18,7 +18,7 @@ memmap = "0.7"
18test_utils = { path = "../test_utils" } 18test_utils = { path = "../test_utils" }
19 19
20[dev-dependencies] 20[dev-dependencies]
21cargo_metadata = "0.9.1" 21cargo_metadata = "0.10.0"
22difference = "2.0.0" 22difference = "2.0.0"
23# used as proc macro test target 23# used as proc macro test target
24serde_derive = "=1.0.106" 24serde_derive = "1.0.106"
diff --git a/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt b/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
index 6776f5231..bc010cfe9 100644
--- a/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
+++ b/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt
@@ -23,23 +23,12 @@ SUBTREE $
23 SUBTREE [] 4294967295 23 SUBTREE [] 4294967295
24 IDENT allow 4294967295 24 IDENT allow 4294967295
25 SUBTREE () 4294967295 25 SUBTREE () 4294967295
26 IDENT unknown_lints 4294967295
27 PUNCH # [alone] 4294967295
28 SUBTREE [] 4294967295
29 IDENT cfg_attr 4294967295
30 SUBTREE () 4294967295
31 IDENT feature 4294967295
32 PUNCH = [alone] 4294967295
33 LITERAL "cargo-clippy" 0
34 PUNCH , [alone] 4294967295
35 IDENT allow 4294967295
36 SUBTREE () 4294967295
37 IDENT useless_attribute 4294967295
38 PUNCH # [alone] 4294967295
39 SUBTREE [] 4294967295
40 IDENT allow 4294967295
41 SUBTREE () 4294967295
42 IDENT rust_2018_idioms 4294967295 26 IDENT rust_2018_idioms 4294967295
27 PUNCH , [alone] 4294967295
28 IDENT clippy 4294967295
29 PUNCH : [joint] 4294967295
30 PUNCH : [alone] 4294967295
31 IDENT useless_attribute 4294967295
43 IDENT extern 4294967295 32 IDENT extern 4294967295
44 IDENT crate 4294967295 33 IDENT crate 4294967295
45 IDENT serde 4294967295 34 IDENT serde 4294967295
diff --git a/crates/ra_proc_macro_srv/src/tests/mod.rs b/crates/ra_proc_macro_srv/src/tests/mod.rs
index 9cf58511c..82cefbb29 100644
--- a/crates/ra_proc_macro_srv/src/tests/mod.rs
+++ b/crates/ra_proc_macro_srv/src/tests/mod.rs
@@ -10,7 +10,7 @@ fn test_derive_serialize_proc_macro() {
10 assert_expand( 10 assert_expand(
11 "serde_derive", 11 "serde_derive",
12 "Serialize", 12 "Serialize",
13 "1.0.106", 13 "1.0",
14 r##"struct Foo {}"##, 14 r##"struct Foo {}"##,
15 include_str!("fixtures/test_serialize_proc_macro.txt"), 15 include_str!("fixtures/test_serialize_proc_macro.txt"),
16 ); 16 );
@@ -21,7 +21,7 @@ fn test_derive_serialize_proc_macro_failed() {
21 assert_expand( 21 assert_expand(
22 "serde_derive", 22 "serde_derive",
23 "Serialize", 23 "Serialize",
24 "1.0.106", 24 "1.0",
25 r##" 25 r##"
26 struct {} 26 struct {}
27"##, 27"##,
@@ -37,7 +37,7 @@ SUBTREE $
37 37
38#[test] 38#[test]
39fn test_derive_proc_macro_list() { 39fn test_derive_proc_macro_list() {
40 let res = list("serde_derive", "1.0.106").join("\n"); 40 let res = list("serde_derive", "1.0").join("\n");
41 41
42 assert_eq_text!( 42 assert_eq_text!(
43 &res, 43 &res,
diff --git a/crates/ra_proc_macro_srv/src/tests/utils.rs b/crates/ra_proc_macro_srv/src/tests/utils.rs
index 646a427c5..84348b5de 100644
--- a/crates/ra_proc_macro_srv/src/tests/utils.rs
+++ b/crates/ra_proc_macro_srv/src/tests/utils.rs
@@ -8,7 +8,7 @@ use std::str::FromStr;
8use test_utils::assert_eq_text; 8use test_utils::assert_eq_text;
9 9
10mod fixtures { 10mod fixtures {
11 use cargo_metadata::{parse_messages, Message}; 11 use cargo_metadata::Message;
12 use std::process::Command; 12 use std::process::Command;
13 13
14 // Use current project metadata to get the proc-macro dylib path 14 // Use current project metadata to get the proc-macro dylib path
@@ -19,7 +19,7 @@ mod fixtures {
19 .unwrap() 19 .unwrap()
20 .stdout; 20 .stdout;
21 21
22 for message in parse_messages(command.as_slice()) { 22 for message in Message::parse_stream(command.as_slice()) {
23 match message.unwrap() { 23 match message.unwrap() {
24 Message::CompilerArtifact(artifact) => { 24 Message::CompilerArtifact(artifact) => {
25 if artifact.target.kind.contains(&"proc-macro".to_string()) { 25 if artifact.target.kind.contains(&"proc-macro".to_string()) {
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml
index a32a5daab..e4a60f4c0 100644
--- a/crates/ra_project_model/Cargo.toml
+++ b/crates/ra_project_model/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
11log = "0.4.8" 11log = "0.4.8"
12rustc-hash = "1.1.0" 12rustc-hash = "1.1.0"
13 13
14cargo_metadata = "0.9.1" 14cargo_metadata = "0.10.0"
15 15
16ra_arena = { path = "../ra_arena" } 16ra_arena = { path = "../ra_arena" }
17ra_cfg = { path = "../ra_cfg" } 17ra_cfg = { path = "../ra_cfg" }
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 082af4f96..a306ce95f 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -161,7 +161,7 @@ impl CargoWorkspace {
161 meta.current_dir(parent); 161 meta.current_dir(parent);
162 } 162 }
163 if let Some(target) = cargo_features.target.as_ref() { 163 if let Some(target) = cargo_features.target.as_ref() {
164 meta.other_options(&[String::from("--filter-platform"), target.clone()]); 164 meta.other_options(vec![String::from("--filter-platform"), target.clone()]);
165 } 165 }
166 let meta = meta.exec().with_context(|| { 166 let meta = meta.exec().with_context(|| {
167 format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) 167 format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display())
@@ -304,19 +304,13 @@ pub fn load_extern_resources(
304 304
305 let mut res = ExternResources::default(); 305 let mut res = ExternResources::default();
306 306
307 for message in cargo_metadata::parse_messages(output.stdout.as_slice()) { 307 for message in cargo_metadata::Message::parse_stream(output.stdout.as_slice()) {
308 if let Ok(message) = message { 308 if let Ok(message) = message {
309 match message { 309 match message {
310 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => { 310 Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => {
311 res.out_dirs.insert(package_id.clone(), out_dir); 311 res.out_dirs.insert(package_id.clone(), out_dir);
312 res.cfgs.insert( 312 res.cfgs.insert(package_id, cfgs);
313 package_id,
314 // FIXME: Current `cargo_metadata` uses `PathBuf` instead of `String`,
315 // change when https://github.com/oli-obk/cargo_metadata/pulls/112 reaches crates.io
316 cfgs.iter().filter_map(|c| c.to_str().map(|s| s.to_owned())).collect(),
317 );
318 } 313 }
319
320 Message::CompilerArtifact(message) => { 314 Message::CompilerArtifact(message) => {
321 if message.target.kind.contains(&"proc-macro".to_string()) { 315 if message.target.kind.contains(&"proc-macro".to_string()) {
322 let package_id = message.package_id; 316 let package_id = message.package_id;
@@ -329,6 +323,8 @@ pub fn load_extern_resources(
329 } 323 }
330 Message::CompilerMessage(_) => (), 324 Message::CompilerMessage(_) => (),
331 Message::Unknown => (), 325 Message::Unknown => (),
326 Message::BuildFinished(_) => {}
327 Message::TextLine(_) => {}
332 } 328 }
333 } 329 }
334 } 330 }
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 4f098b706..a2e9f65ef 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -35,7 +35,7 @@ pub enum ProjectWorkspace {
35/// `PackageRoot` describes a package root folder. 35/// `PackageRoot` describes a package root folder.
36/// Which may be an external dependency, or a member of 36/// Which may be an external dependency, or a member of
37/// the current workspace. 37/// the current workspace.
38#[derive(Clone)] 38#[derive(Debug, Clone)]
39pub struct PackageRoot { 39pub struct PackageRoot {
40 /// Path to the root folder 40 /// Path to the root folder
41 path: PathBuf, 41 path: PathBuf,
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs
index b00c15608..cf6067e57 100644
--- a/crates/ra_syntax/src/ast/generated/nodes.rs
+++ b/crates/ra_syntax/src/ast/generated/nodes.rs
@@ -5,7 +5,9 @@ use crate::{
5 SyntaxKind::{self, *}, 5 SyntaxKind::{self, *},
6 SyntaxNode, SyntaxToken, T, 6 SyntaxNode, SyntaxToken, T,
7}; 7};
8 8/// The entire Rust source file. Includes all top-level inner attributes and module items.
9///
10/// [Reference](https://doc.rust-lang.org/reference/crates-and-source-files.html)
9#[derive(Debug, Clone, PartialEq, Eq, Hash)] 11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct SourceFile { 12pub struct SourceFile {
11 pub(crate) syntax: SyntaxNode, 13 pub(crate) syntax: SyntaxNode,
@@ -16,7 +18,28 @@ impl ast::DocCommentsOwner for SourceFile {}
16impl SourceFile { 18impl SourceFile {
17 pub fn modules(&self) -> AstChildren<Module> { support::children(&self.syntax) } 19 pub fn modules(&self) -> AstChildren<Module> { support::children(&self.syntax) }
18} 20}
19 21/// Function definition either with body or not.
22/// Includes all of its attributes and doc comments.
23///
24/// ```
25/// ❰
26/// /// Docs
27/// #[attr]
28/// pub extern "C" fn foo<T>(#[attr] Patern {p}: Pattern) -> u32
29/// where
30/// T: Debug
31/// {
32/// 42
33/// }
34/// ❱
35///
36/// extern "C" {
37/// ❰ fn fn_decl(also_variadic_ffi: u32, ...) -> u32; ❱
38/// }
39/// ```
40///
41/// - [Reference](https://doc.rust-lang.org/reference/items/functions.html)
42/// - [Nomicon](https://doc.rust-lang.org/nomicon/ffi.html#variadic-functions)
20#[derive(Debug, Clone, PartialEq, Eq, Hash)] 43#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21pub struct FnDef { 44pub struct FnDef {
22 pub(crate) syntax: SyntaxNode, 45 pub(crate) syntax: SyntaxNode,
@@ -38,7 +61,13 @@ impl FnDef {
38 pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) } 61 pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
39 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 62 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
40} 63}
41 64/// Return type annotation.
65///
66/// ```
67/// fn foo(a: u32) ❰ -> Option<u32> ❱ { Some(a) }
68/// ```
69///
70/// [Reference](https://doc.rust-lang.org/reference/items/functions.html)
42#[derive(Debug, Clone, PartialEq, Eq, Hash)] 71#[derive(Debug, Clone, PartialEq, Eq, Hash)]
43pub struct RetType { 72pub struct RetType {
44 pub(crate) syntax: SyntaxNode, 73 pub(crate) syntax: SyntaxNode,
@@ -47,7 +76,26 @@ impl RetType {
47 pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) } 76 pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) }
48 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 77 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
49} 78}
50 79/// Struct definition.
80/// Includes all of its attributes and doc comments.
81///
82/// ```
83/// ❰
84/// /// Docs
85/// #[attr]
86/// struct Foo<T> where T: Debug {
87/// /// Docs
88/// #[attr]
89/// pub a: u32,
90/// b: T,
91/// }
92/// ❱
93///
94/// ❰ struct Foo; ❱
95/// ❰ struct Foo<T>(#[attr] T) where T: Debug; ❱
96/// ```
97///
98/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
51#[derive(Debug, Clone, PartialEq, Eq, Hash)] 99#[derive(Debug, Clone, PartialEq, Eq, Hash)]
52pub struct StructDef { 100pub struct StructDef {
53 pub(crate) syntax: SyntaxNode, 101 pub(crate) syntax: SyntaxNode,
@@ -62,7 +110,23 @@ impl StructDef {
62 pub fn field_def_list(&self) -> Option<FieldDefList> { support::child(&self.syntax) } 110 pub fn field_def_list(&self) -> Option<FieldDefList> { support::child(&self.syntax) }
63 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 111 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
64} 112}
65 113/// Union definition.
114/// Includes all of its attributes and doc comments.
115///
116/// ```
117/// ❰
118/// /// Docs
119/// #[attr]
120/// pub union Foo<T> where T: Debug {
121/// /// Docs
122/// #[attr]
123/// a: T,
124/// b: u32,
125/// }
126/// ❱
127/// ```
128///
129/// [Reference](https://doc.rust-lang.org/reference/items/unions.html)
66#[derive(Debug, Clone, PartialEq, Eq, Hash)] 130#[derive(Debug, Clone, PartialEq, Eq, Hash)]
67pub struct UnionDef { 131pub struct UnionDef {
68 pub(crate) syntax: SyntaxNode, 132 pub(crate) syntax: SyntaxNode,
@@ -78,7 +142,19 @@ impl UnionDef {
78 support::child(&self.syntax) 142 support::child(&self.syntax)
79 } 143 }
80} 144}
81 145/// Record field definition list including enclosing curly braces.
146///
147/// ```
148/// struct Foo // same for union
149/// ❰
150/// {
151/// a: u32,
152/// b: bool,
153/// }
154/// ❱
155/// ```
156///
157/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
82#[derive(Debug, Clone, PartialEq, Eq, Hash)] 158#[derive(Debug, Clone, PartialEq, Eq, Hash)]
83pub struct RecordFieldDefList { 159pub struct RecordFieldDefList {
84 pub(crate) syntax: SyntaxNode, 160 pub(crate) syntax: SyntaxNode,
@@ -88,7 +164,22 @@ impl RecordFieldDefList {
88 pub fn fields(&self) -> AstChildren<RecordFieldDef> { support::children(&self.syntax) } 164 pub fn fields(&self) -> AstChildren<RecordFieldDef> { support::children(&self.syntax) }
89 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 165 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
90} 166}
91 167/// Record field definition including its attributes and doc comments.
168///
169/// ` ``
170/// same for union
171/// struct Foo {
172/// ❰
173/// /// Docs
174/// #[attr]
175/// pub a: u32
176/// ❱
177///
178/// ❰ b: bool ❱
179/// }
180/// ```
181///
182/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
92#[derive(Debug, Clone, PartialEq, Eq, Hash)] 183#[derive(Debug, Clone, PartialEq, Eq, Hash)]
93pub struct RecordFieldDef { 184pub struct RecordFieldDef {
94 pub(crate) syntax: SyntaxNode, 185 pub(crate) syntax: SyntaxNode,
@@ -99,7 +190,13 @@ impl ast::AttrsOwner for RecordFieldDef {}
99impl ast::DocCommentsOwner for RecordFieldDef {} 190impl ast::DocCommentsOwner for RecordFieldDef {}
100impl ast::TypeAscriptionOwner for RecordFieldDef {} 191impl ast::TypeAscriptionOwner for RecordFieldDef {}
101impl RecordFieldDef {} 192impl RecordFieldDef {}
102 193/// Tuple field definition list including enclosing parens.
194///
195/// ```
196/// struct Foo ❰ (u32, String, Vec<u32>) ❱;
197/// ```
198///
199/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
103#[derive(Debug, Clone, PartialEq, Eq, Hash)] 200#[derive(Debug, Clone, PartialEq, Eq, Hash)]
104pub struct TupleFieldDefList { 201pub struct TupleFieldDefList {
105 pub(crate) syntax: SyntaxNode, 202 pub(crate) syntax: SyntaxNode,
@@ -109,7 +206,13 @@ impl TupleFieldDefList {
109 pub fn fields(&self) -> AstChildren<TupleFieldDef> { support::children(&self.syntax) } 206 pub fn fields(&self) -> AstChildren<TupleFieldDef> { support::children(&self.syntax) }
110 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 207 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
111} 208}
112 209/// Tuple field definition including its attributes.
210///
211/// ```
212/// struct Foo(❰ #[attr] u32 ❱);
213/// ```
214///
215/// [Reference](https://doc.rust-lang.org/reference/items/structs.html)
113#[derive(Debug, Clone, PartialEq, Eq, Hash)] 216#[derive(Debug, Clone, PartialEq, Eq, Hash)]
114pub struct TupleFieldDef { 217pub struct TupleFieldDef {
115 pub(crate) syntax: SyntaxNode, 218 pub(crate) syntax: SyntaxNode,
@@ -119,7 +222,29 @@ impl ast::AttrsOwner for TupleFieldDef {}
119impl TupleFieldDef { 222impl TupleFieldDef {
120 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 223 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
121} 224}
122 225/// Enum definition.
226/// Includes all of its attributes and doc comments.
227///
228/// ```
229/// ❰
230/// /// Docs
231/// #[attr]
232/// pub enum Foo<T> where T: Debug {
233/// /// Docs
234/// #[attr]
235/// Bar,
236/// Baz(#[attr] u32),
237/// Bruh {
238/// a: u32,
239/// /// Docs
240/// #[attr]
241/// b: T,
242/// }
243/// }
244/// ❱
245/// ```
246///
247/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
123#[derive(Debug, Clone, PartialEq, Eq, Hash)] 248#[derive(Debug, Clone, PartialEq, Eq, Hash)]
124pub struct EnumDef { 249pub struct EnumDef {
125 pub(crate) syntax: SyntaxNode, 250 pub(crate) syntax: SyntaxNode,
@@ -133,7 +258,22 @@ impl EnumDef {
133 pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) } 258 pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
134 pub fn variant_list(&self) -> Option<EnumVariantList> { support::child(&self.syntax) } 259 pub fn variant_list(&self) -> Option<EnumVariantList> { support::child(&self.syntax) }
135} 260}
136 261/// Enum variant definition list including enclosing curly braces.
262///
263/// ```
264/// enum Foo
265/// ❰
266/// {
267/// Bar,
268/// Baz(u32),
269/// Bruh {
270/// a: u32
271/// }
272/// }
273/// ❱
274/// ```
275///
276/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
137#[derive(Debug, Clone, PartialEq, Eq, Hash)] 277#[derive(Debug, Clone, PartialEq, Eq, Hash)]
138pub struct EnumVariantList { 278pub struct EnumVariantList {
139 pub(crate) syntax: SyntaxNode, 279 pub(crate) syntax: SyntaxNode,
@@ -143,7 +283,21 @@ impl EnumVariantList {
143 pub fn variants(&self) -> AstChildren<EnumVariant> { support::children(&self.syntax) } 283 pub fn variants(&self) -> AstChildren<EnumVariant> { support::children(&self.syntax) }
144 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 284 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
145} 285}
146 286/// Enum variant definition including its attributes and discriminant value definition.
287///
288/// ```
289/// enum Foo {
290/// ❰
291/// /// Docs
292/// #[attr]
293/// Bar
294/// ❱
295///
296/// // same for tuple and record variants
297/// }
298/// ```
299///
300/// [Reference](https://doc.rust-lang.org/reference/items/enumerations.html)
147#[derive(Debug, Clone, PartialEq, Eq, Hash)] 301#[derive(Debug, Clone, PartialEq, Eq, Hash)]
148pub struct EnumVariant { 302pub struct EnumVariant {
149 pub(crate) syntax: SyntaxNode, 303 pub(crate) syntax: SyntaxNode,
@@ -157,7 +311,20 @@ impl EnumVariant {
157 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } 311 pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
158 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 312 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
159} 313}
160 314/// Trait definition.
315/// Includes all of its attributes and doc comments.
316///
317/// ```
318/// ❰
319/// /// Docs
320/// #[attr]
321/// pub unsafe trait Foo<T>: Debug where T: Debug {
322/// // ...
323/// }
324/// ❱
325/// ```
326///
327/// [Reference](https://doc.rust-lang.org/reference/items/traits.html)
161#[derive(Debug, Clone, PartialEq, Eq, Hash)] 328#[derive(Debug, Clone, PartialEq, Eq, Hash)]
162pub struct TraitDef { 329pub struct TraitDef {
163 pub(crate) syntax: SyntaxNode, 330 pub(crate) syntax: SyntaxNode,
@@ -174,7 +341,27 @@ impl TraitDef {
174 pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) } 341 pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
175 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) } 342 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
176} 343}
177 344/// Module definition either with body or not.
345/// Includes all of its inner and outer attributes, module items, doc comments.
346///
347/// ```
348/// ❰
349/// /// Docs
350/// #[attr]
351/// pub mod foo;
352/// ❱
353///
354/// ❰
355/// /// Docs
356/// #[attr]
357/// pub mod bar {
358/// //! Inner docs
359/// #![inner_attr]
360/// }
361/// ❱
362/// ```
363///
364/// [Reference](https://doc.rust-lang.org/reference/items/modules.html)
178#[derive(Debug, Clone, PartialEq, Eq, Hash)] 365#[derive(Debug, Clone, PartialEq, Eq, Hash)]
179pub struct Module { 366pub struct Module {
180 pub(crate) syntax: SyntaxNode, 367 pub(crate) syntax: SyntaxNode,
@@ -188,7 +375,28 @@ impl Module {
188 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) } 375 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
189 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 376 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
190} 377}
191 378/// Item defintion list.
379/// This is used for both top-level items and impl block items.
380///
381/// ```
382/// ❰
383/// fn foo {}
384/// struct Bar;
385/// enum Baz;
386/// trait Bruh;
387/// const BRUUH: u32 = 42;
388/// ❱
389///
390/// impl Foo
391/// ❰
392/// {
393/// fn bar() {}
394/// const BAZ: u32 = 42;
395/// }
396/// ❱
397/// ```
398///
399/// [Reference](https://doc.rust-lang.org/reference/items.html)
192#[derive(Debug, Clone, PartialEq, Eq, Hash)] 400#[derive(Debug, Clone, PartialEq, Eq, Hash)]
193pub struct ItemList { 401pub struct ItemList {
194 pub(crate) syntax: SyntaxNode, 402 pub(crate) syntax: SyntaxNode,
@@ -199,7 +407,18 @@ impl ItemList {
199 pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) } 407 pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) }
200 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 408 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
201} 409}
202 410/// Constant variable definition.
411/// Includes all of its attributes and doc comments.
412///
413/// ```
414/// ❰
415/// /// Docs
416/// #[attr]
417/// pub const FOO: u32 = 42;
418/// ❱
419/// ```
420///
421/// [Reference](https://doc.rust-lang.org/reference/items/constant-items.html)
203#[derive(Debug, Clone, PartialEq, Eq, Hash)] 422#[derive(Debug, Clone, PartialEq, Eq, Hash)]
204pub struct ConstDef { 423pub struct ConstDef {
205 pub(crate) syntax: SyntaxNode, 424 pub(crate) syntax: SyntaxNode,
@@ -217,7 +436,18 @@ impl ConstDef {
217 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } 436 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
218 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 437 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
219} 438}
220 439/// Static variable definition.
440/// Includes all of its attributes and doc comments.
441///
442/// ```
443/// ❰
444/// /// Docs
445/// #[attr]
446/// pub static mut FOO: u32 = 42;
447/// ❱
448/// ```
449///
450/// [Reference](https://doc.rust-lang.org/reference/items/static-items.html)
221#[derive(Debug, Clone, PartialEq, Eq, Hash)] 451#[derive(Debug, Clone, PartialEq, Eq, Hash)]
222pub struct StaticDef { 452pub struct StaticDef {
223 pub(crate) syntax: SyntaxNode, 453 pub(crate) syntax: SyntaxNode,
@@ -235,7 +465,24 @@ impl StaticDef {
235 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } 465 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
236 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 466 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
237} 467}
238 468/// Type alias definition.
469/// Includes associated type clauses with type bounds.
470///
471/// ```
472/// ❰
473/// /// Docs
474/// #[attr]
475/// pub type Foo<T> where T: Debug = T;
476/// ❱
477///
478/// trait Bar {
479/// ❰ type Baz: Debug; ❱
480/// ❰ type Bruh = String; ❱
481/// ❰ type Bruuh: Debug = u32; ❱
482/// }
483/// ```
484///
485/// [Reference](https://doc.rust-lang.org/reference/items/type-aliases.html)
239#[derive(Debug, Clone, PartialEq, Eq, Hash)] 486#[derive(Debug, Clone, PartialEq, Eq, Hash)]
240pub struct TypeAliasDef { 487pub struct TypeAliasDef {
241 pub(crate) syntax: SyntaxNode, 488 pub(crate) syntax: SyntaxNode,
@@ -253,7 +500,20 @@ impl TypeAliasDef {
253 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 500 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
254 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 501 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
255} 502}
256 503/// Inherent and trait impl definition.
504/// Includes all of its inner and outer attributes.
505///
506/// ```
507/// ❰
508/// #[attr]
509/// unsafe impl<T> const !Foo for Bar where T: Debug {
510/// #![inner_attr]
511/// // ...
512/// }
513/// ❱
514/// ```
515///
516/// [Reference](https://doc.rust-lang.org/reference/items/implementations.html)
257#[derive(Debug, Clone, PartialEq, Eq, Hash)] 517#[derive(Debug, Clone, PartialEq, Eq, Hash)]
258pub struct ImplDef { 518pub struct ImplDef {
259 pub(crate) syntax: SyntaxNode, 519 pub(crate) syntax: SyntaxNode,
@@ -270,7 +530,16 @@ impl ImplDef {
270 pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } 530 pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
271 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) } 531 pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
272} 532}
273 533/// Parenthesized type reference.
534/// Note: parens are only used for grouping, this is not a tuple type.
535///
536/// ```
537/// // This is effectively just `u32`.
538/// // Single-item tuple must be defined with a trailing comma: `(u32,)`
539/// type Foo = ❰ (u32) ❱;
540///
541/// let bar: &'static ❰ (dyn Debug) ❱ = "bruh";
542/// ```
274#[derive(Debug, Clone, PartialEq, Eq, Hash)] 543#[derive(Debug, Clone, PartialEq, Eq, Hash)]
275pub struct ParenType { 544pub struct ParenType {
276 pub(crate) syntax: SyntaxNode, 545 pub(crate) syntax: SyntaxNode,
@@ -280,7 +549,13 @@ impl ParenType {
280 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 549 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
281 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 550 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
282} 551}
283 552/// Unnamed tuple type.
553///
554/// ```
555/// let foo: ❰ (u32, bool) ❱ = (42, true);
556/// ```
557///
558/// [Reference](https://doc.rust-lang.org/reference/types/tuple.html)
284#[derive(Debug, Clone, PartialEq, Eq, Hash)] 559#[derive(Debug, Clone, PartialEq, Eq, Hash)]
285pub struct TupleType { 560pub struct TupleType {
286 pub(crate) syntax: SyntaxNode, 561 pub(crate) syntax: SyntaxNode,
@@ -290,7 +565,17 @@ impl TupleType {
290 pub fn fields(&self) -> AstChildren<TypeRef> { support::children(&self.syntax) } 565 pub fn fields(&self) -> AstChildren<TypeRef> { support::children(&self.syntax) }
291 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 566 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
292} 567}
293 568/// The never type (i.e. the exclamation point).
569///
570/// ```
571/// type T = ❰ ! ❱;
572///
573/// fn no_return() -> ❰ ! ❱ {
574/// loop {}
575/// }
576/// ```
577///
578/// [Reference](https://doc.rust-lang.org/reference/types/never.html)
294#[derive(Debug, Clone, PartialEq, Eq, Hash)] 579#[derive(Debug, Clone, PartialEq, Eq, Hash)]
295pub struct NeverType { 580pub struct NeverType {
296 pub(crate) syntax: SyntaxNode, 581 pub(crate) syntax: SyntaxNode,
@@ -298,7 +583,17 @@ pub struct NeverType {
298impl NeverType { 583impl NeverType {
299 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } 584 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
300} 585}
301 586/// Path to a type.
587/// Includes single identifier type names and elaborate paths with
588/// generic parameters.
589///
590/// ```
591/// type Foo = ❰ String ❱;
592/// type Bar = ❰ std::vec::Vec<T> ❱;
593/// type Baz = ❰ ::bruh::<Bruuh as Iterator>::Item ❱;
594/// ```
595///
596/// [Reference](https://doc.rust-lang.org/reference/paths.html)
302#[derive(Debug, Clone, PartialEq, Eq, Hash)] 597#[derive(Debug, Clone, PartialEq, Eq, Hash)]
303pub struct PathType { 598pub struct PathType {
304 pub(crate) syntax: SyntaxNode, 599 pub(crate) syntax: SyntaxNode,
@@ -306,7 +601,14 @@ pub struct PathType {
306impl PathType { 601impl PathType {
307 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 602 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
308} 603}
309 604/// Raw pointer type.
605///
606/// ```
607/// type Foo = ❰ *const u32 ❱;
608/// type Bar = ❰ *mut u32 ❱;
609/// ```
610///
611/// [Reference](https://doc.rust-lang.org/reference/types/pointer.html#raw-pointers-const-and-mut)
310#[derive(Debug, Clone, PartialEq, Eq, Hash)] 612#[derive(Debug, Clone, PartialEq, Eq, Hash)]
311pub struct PointerType { 613pub struct PointerType {
312 pub(crate) syntax: SyntaxNode, 614 pub(crate) syntax: SyntaxNode,
@@ -317,7 +619,13 @@ impl PointerType {
317 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } 619 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
318 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 620 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
319} 621}
320 622/// Array type.
623///
624/// ```
625/// type Foo = ❰ [u32; 24 - 3] ❱;
626/// ```
627///
628/// [Reference](https://doc.rust-lang.org/reference/types/array.html)
321#[derive(Debug, Clone, PartialEq, Eq, Hash)] 629#[derive(Debug, Clone, PartialEq, Eq, Hash)]
322pub struct ArrayType { 630pub struct ArrayType {
323 pub(crate) syntax: SyntaxNode, 631 pub(crate) syntax: SyntaxNode,
@@ -329,7 +637,13 @@ impl ArrayType {
329 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 637 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
330 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 638 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
331} 639}
332 640/// Slice type.
641///
642/// ```
643/// type Foo = ❰ [u8] ❱;
644/// ```
645///
646/// [Reference](https://doc.rust-lang.org/reference/types/slice.html)
333#[derive(Debug, Clone, PartialEq, Eq, Hash)] 647#[derive(Debug, Clone, PartialEq, Eq, Hash)]
334pub struct SliceType { 648pub struct SliceType {
335 pub(crate) syntax: SyntaxNode, 649 pub(crate) syntax: SyntaxNode,
@@ -339,7 +653,13 @@ impl SliceType {
339 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 653 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
340 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 654 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
341} 655}
342 656/// Reference type.
657///
658/// ```
659/// type Foo = ❰ &'static str ❱;
660/// ```
661///
662/// [Reference](https://doc.rust-lang.org/reference/types/pointer.html)
343#[derive(Debug, Clone, PartialEq, Eq, Hash)] 663#[derive(Debug, Clone, PartialEq, Eq, Hash)]
344pub struct ReferenceType { 664pub struct ReferenceType {
345 pub(crate) syntax: SyntaxNode, 665 pub(crate) syntax: SyntaxNode,
@@ -352,7 +672,13 @@ impl ReferenceType {
352 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } 672 pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
353 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 673 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
354} 674}
355 675/// Placeholder type (i.e. the underscore).
676///
677/// ```
678/// let foo: ❰ _ ❱ = 42_u32;
679/// ```
680///
681/// [Reference](https://doc.rust-lang.org/reference/types/inferred.html)
356#[derive(Debug, Clone, PartialEq, Eq, Hash)] 682#[derive(Debug, Clone, PartialEq, Eq, Hash)]
357pub struct PlaceholderType { 683pub struct PlaceholderType {
358 pub(crate) syntax: SyntaxNode, 684 pub(crate) syntax: SyntaxNode,
@@ -360,7 +686,15 @@ pub struct PlaceholderType {
360impl PlaceholderType { 686impl PlaceholderType {
361 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } 687 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
362} 688}
363 689/// Function pointer type (not to be confused with `Fn*` family of traits).
690///
691/// ```
692/// type Foo = ❰ async fn(#[attr] u32, named: bool) -> u32 ❱;
693///
694/// type Bar = ❰ extern "C" fn(variadic: u32, #[attr] ...) ❱;
695/// ```
696///
697/// [Reference](https://doc.rust-lang.org/reference/types/function-pointer.html)
364#[derive(Debug, Clone, PartialEq, Eq, Hash)] 698#[derive(Debug, Clone, PartialEq, Eq, Hash)]
365pub struct FnPointerType { 699pub struct FnPointerType {
366 pub(crate) syntax: SyntaxNode, 700 pub(crate) syntax: SyntaxNode,
@@ -372,7 +706,13 @@ impl FnPointerType {
372 pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } 706 pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
373 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } 707 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
374} 708}
375 709/// Higher order type.
710///
711/// ```
712/// type Foo = ❰ for<'a> fn(&'a str) ❱;
713/// ```
714///
715/// [Reference](https://doc.rust-lang.org/nomicon/hrtb.html)
376#[derive(Debug, Clone, PartialEq, Eq, Hash)] 716#[derive(Debug, Clone, PartialEq, Eq, Hash)]
377pub struct ForType { 717pub struct ForType {
378 pub(crate) syntax: SyntaxNode, 718 pub(crate) syntax: SyntaxNode,
@@ -382,7 +722,13 @@ impl ForType {
382 pub fn type_param_list(&self) -> Option<TypeParamList> { support::child(&self.syntax) } 722 pub fn type_param_list(&self) -> Option<TypeParamList> { support::child(&self.syntax) }
383 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } 723 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
384} 724}
385 725/// Opaque `impl Trait` type.
726///
727/// ```
728/// fn foo(bar: ❰ impl Debug + Eq ❱) {}
729/// ```
730///
731/// [Reference](https://doc.rust-lang.org/reference/types/impl-trait.html)
386#[derive(Debug, Clone, PartialEq, Eq, Hash)] 732#[derive(Debug, Clone, PartialEq, Eq, Hash)]
387pub struct ImplTraitType { 733pub struct ImplTraitType {
388 pub(crate) syntax: SyntaxNode, 734 pub(crate) syntax: SyntaxNode,
@@ -391,7 +737,13 @@ impl ast::TypeBoundsOwner for ImplTraitType {}
391impl ImplTraitType { 737impl ImplTraitType {
392 pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) } 738 pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
393} 739}
394 740/// Trait object type.
741///
742/// ```
743/// type Foo = ❰ dyn Debug ❱;
744/// ```
745///
746/// [Reference](https://doc.rust-lang.org/reference/types/trait-object.html)
395#[derive(Debug, Clone, PartialEq, Eq, Hash)] 747#[derive(Debug, Clone, PartialEq, Eq, Hash)]
396pub struct DynTraitType { 748pub struct DynTraitType {
397 pub(crate) syntax: SyntaxNode, 749 pub(crate) syntax: SyntaxNode,
@@ -400,7 +752,13 @@ impl ast::TypeBoundsOwner for DynTraitType {}
400impl DynTraitType { 752impl DynTraitType {
401 pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) } 753 pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
402} 754}
403 755/// Tuple literal.
756///
757/// ```
758/// ❰ (42, true) ❱;
759/// ```
760///
761/// [Reference](https://doc.rust-lang.org/reference/expressions/tuple-expr.html)
404#[derive(Debug, Clone, PartialEq, Eq, Hash)] 762#[derive(Debug, Clone, PartialEq, Eq, Hash)]
405pub struct TupleExpr { 763pub struct TupleExpr {
406 pub(crate) syntax: SyntaxNode, 764 pub(crate) syntax: SyntaxNode,
@@ -411,7 +769,15 @@ impl TupleExpr {
411 pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) } 769 pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
412 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 770 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
413} 771}
414 772/// Array literal.
773///
774/// ```
775/// ❰ [#![inner_attr] true, false, true] ❱;
776///
777/// ❰ ["baz"; 24] ❱;
778/// ```
779///
780/// [Reference](https://doc.rust-lang.org/reference/expressions/array-expr.html)
415#[derive(Debug, Clone, PartialEq, Eq, Hash)] 781#[derive(Debug, Clone, PartialEq, Eq, Hash)]
416pub struct ArrayExpr { 782pub struct ArrayExpr {
417 pub(crate) syntax: SyntaxNode, 783 pub(crate) syntax: SyntaxNode,
@@ -423,7 +789,14 @@ impl ArrayExpr {
423 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } 789 pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
424 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } 790 pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
425} 791}
426 792/// Parenthesized expression.
793/// Note: parens are only used for grouping, this is not a tuple literal.
794///
795/// ```
796/// ❰ (#![inner_attr] 2 + 2) ❱ * 2;
797/// ```
798///
799/// [Reference](https://doc.rust-lang.org/reference/expressions/grouped-expr.html)
427#[derive(Debug, Clone, PartialEq, Eq, Hash)] 800#[derive(Debug, Clone, PartialEq, Eq, Hash)]
428pub struct ParenExpr { 801pub struct ParenExpr {
429 pub(crate) syntax: SyntaxNode, 802 pub(crate) syntax: SyntaxNode,
@@ -434,7 +807,19 @@ impl ParenExpr {
434 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 807 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
435 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } 808 pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
436} 809}
437 810/// Path to a symbol in expression context.
811/// Includes single identifier variable names and elaborate paths with
812/// generic parameters.
813///
814/// ```
815/// ❰ Some::<i32> ❱;
816/// ❰ foo ❱ + 42;
817/// ❰ Vec::<i32>::push ❱;
818/// ❰ <[i32]>::reverse ❱;
819/// ❰ <String as std::borrow::Borrow<str>>::borrow ❱;
820/// ```
821///
822/// [Reference](https://doc.rust-lang.org/reference/expressions/path-expr.html)
438#[derive(Debug, Clone, PartialEq, Eq, Hash)] 823#[derive(Debug, Clone, PartialEq, Eq, Hash)]
439pub struct PathExpr { 824pub struct PathExpr {
440 pub(crate) syntax: SyntaxNode, 825 pub(crate) syntax: SyntaxNode,
@@ -442,7 +827,17 @@ pub struct PathExpr {
442impl PathExpr { 827impl PathExpr {
443 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } 828 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
444} 829}
445 830/// Anonymous callable object literal a.k.a. closure, lambda or functor.
831///
832/// ```
833/// ❰ || 42 ❱;
834/// ❰ |a: u32| val + 1 ❱;
835/// ❰ async |#[attr] Pattern(_): Pattern| { bar } ❱;
836/// ❰ move || baz ❱;
837/// ❰ || -> u32 { closure_with_ret_type_annotation_requires_block_expr } ❱
838/// ```
839///
840/// [Reference](https://doc.rust-lang.org/reference/expressions/closure-expr.html)
446#[derive(Debug, Clone, PartialEq, Eq, Hash)] 841#[derive(Debug, Clone, PartialEq, Eq, Hash)]
447pub struct LambdaExpr { 842pub struct LambdaExpr {
448 pub(crate) syntax: SyntaxNode, 843 pub(crate) syntax: SyntaxNode,
@@ -456,7 +851,25 @@ impl LambdaExpr {
456 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } 851 pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
457 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } 852 pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
458} 853}
459 854/// If expression. Includes both regular `if` and `if let` forms.
855/// Beware that `else if` is a special case syntax sugar, because in general
856/// there has to be block expression after `else`.
857///
858/// ```
859/// ❰ if bool_cond { 42 } ❱
860/// ❰ if bool_cond { 42 } else { 24 } ❱
861/// ❰ if bool_cond { 42 } else if bool_cond2 { 42 } ❱
862///
863/// ❰
864/// if let Pattern(foo) = bar {
865/// foo
866/// } else {
867/// panic!();
868/// }
869/// ❱
870/// ```
871///
872/// [Reference](https://doc.rust-lang.org/reference/expressions/if-expr.html)
460#[derive(Debug, Clone, PartialEq, Eq, Hash)] 873#[derive(Debug, Clone, PartialEq, Eq, Hash)]
461pub struct IfExpr { 874pub struct IfExpr {
462 pub(crate) syntax: SyntaxNode, 875 pub(crate) syntax: SyntaxNode,
@@ -466,7 +879,17 @@ impl IfExpr {
466 pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) } 879 pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
467 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } 880 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
468} 881}
469 882/// Unconditional loop expression.
883///
884/// ```
885/// ❰
886/// loop {
887/// // yeah, it's that simple...
888/// }
889/// ❱
890/// ```
891///
892/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html)
470#[derive(Debug, Clone, PartialEq, Eq, Hash)] 893#[derive(Debug, Clone, PartialEq, Eq, Hash)]
471pub struct LoopExpr { 894pub struct LoopExpr {
472 pub(crate) syntax: SyntaxNode, 895 pub(crate) syntax: SyntaxNode,
@@ -476,7 +899,20 @@ impl ast::LoopBodyOwner for LoopExpr {}
476impl LoopExpr { 899impl LoopExpr {
477 pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) } 900 pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
478} 901}
479 902/// Block expression with an optional prefix (label, try ketword,
903/// unsafe keyword, async keyword...).
904///
905/// ```
906/// ❰
907/// 'label: try {
908/// None?
909/// }
910/// ❱
911/// ```
912///
913/// - [try block](https://doc.rust-lang.org/unstable-book/language-features/try-blocks.html)
914/// - [unsafe block](https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks)
915/// - [async block](https://doc.rust-lang.org/reference/expressions/block-expr.html#async-blocks)
480#[derive(Debug, Clone, PartialEq, Eq, Hash)] 916#[derive(Debug, Clone, PartialEq, Eq, Hash)]
481pub struct EffectExpr { 917pub struct EffectExpr {
482 pub(crate) syntax: SyntaxNode, 918 pub(crate) syntax: SyntaxNode,
@@ -489,7 +925,19 @@ impl EffectExpr {
489 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } 925 pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
490 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } 926 pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
491} 927}
492 928/// For loop expression.
929/// Note: record struct literals are not valid as iterable expression
930/// due to ambiguity.
931///
932/// ```
933/// ❰
934/// for i in (0..4) {
935/// dbg!(i);
936/// }
937/// ❱
938/// ```
939///
940/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops)
493#[derive(Debug, Clone, PartialEq, Eq, Hash)] 941#[derive(Debug, Clone, PartialEq, Eq, Hash)]
494pub struct ForExpr { 942pub struct ForExpr {
495 pub(crate) syntax: SyntaxNode, 943 pub(crate) syntax: SyntaxNode,
@@ -502,7 +950,22 @@ impl ForExpr {
502 pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) } 950 pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
503 pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) } 951 pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) }
504} 952}
505 953/// While loop expression. Includes both regular `while` and `while let` forms.
954///
955/// ```
956/// ❰
957/// while bool_cond {
958/// 42;
959/// }
960/// ❱
961/// ❰
962/// while let Pattern(foo) = bar {
963/// bar += 1;
964/// }
965/// ❱
966/// ```
967///
968/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#predicate-loops)
506#[derive(Debug, Clone, PartialEq, Eq, Hash)] 969#[derive(Debug, Clone, PartialEq, Eq, Hash)]
507pub struct WhileExpr { 970pub struct WhileExpr {
508 pub(crate) syntax: SyntaxNode, 971 pub(crate) syntax: SyntaxNode,
@@ -513,7 +976,22 @@ impl WhileExpr {
513 pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) } 976 pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) }
514 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } 977 pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) }
515} 978}
516 979/// Continue expression.
980///
981/// ```
982/// while bool_cond {
983/// ❰ continue ❱;
984/// }
985///
986/// 'outer: loop {
987/// loop {
988/// ❰ continue 'outer ❱;
989/// }
990/// }
991///
992/// ```
993///
994/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html#continue-expressions)
517#[derive(Debug, Clone, PartialEq, Eq, Hash)] 995#[derive(Debug, Clone, PartialEq, Eq, Hash)]
518pub struct ContinueExpr { 996pub struct ContinueExpr {
519 pub(crate) syntax: SyntaxNode, 997 pub(crate) syntax: SyntaxNode,
@@ -527,7 +1005,25 @@ impl ContinueExpr {
527 support::token(&self.syntax, T![lifetime]) 1005 support::token(&self.syntax, T![lifetime])
528 } 1006 }
529} 1007}
530 1008/// Break expression.
1009///
1010/// ```
1011/// while bool_cond {
1012/// ❰ break ❱;
1013/// }
1014/// 'outer: loop {
1015/// for foo in bar {
1016/// ❰ break 'outer ❱;
1017/// }
1018/// }
1019/// 'outer: loop {
1020/// loop {
1021/// ❰ break 'outer 42 ❱;
1022/// }
1023/// }
1024/// ```
1025///
1026/// [Refernce](https://doc.rust-lang.org/reference/expressions/loop-expr.html#break-expressions)
531#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1027#[derive(Debug, Clone, PartialEq, Eq, Hash)]
532pub struct BreakExpr { 1028pub struct BreakExpr {
533 pub(crate) syntax: SyntaxNode, 1029 pub(crate) syntax: SyntaxNode,
@@ -540,7 +1036,20 @@ impl BreakExpr {
540 } 1036 }
541 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1037 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
542} 1038}
543 1039/// Label.
1040///
1041/// ```
1042/// ❰ 'outer: ❱ loop {}
1043///
1044/// let foo = ❰ 'bar: ❱ loop {}
1045///
1046/// ❰ 'baz: ❱ {
1047/// break 'baz;
1048/// }
1049/// ```
1050///
1051/// [Reference](https://doc.rust-lang.org/reference/expressions/loop-expr.html?highlight=label#loop-labels)
1052/// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
544#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1053#[derive(Debug, Clone, PartialEq, Eq, Hash)]
545pub struct Label { 1054pub struct Label {
546 pub(crate) syntax: SyntaxNode, 1055 pub(crate) syntax: SyntaxNode,
@@ -550,7 +1059,21 @@ impl Label {
550 support::token(&self.syntax, T![lifetime]) 1059 support::token(&self.syntax, T![lifetime])
551 } 1060 }
552} 1061}
553 1062/// Block expression. Includes unsafe blocks and block labels.
1063///
1064/// ```
1065/// let foo = ❰
1066/// {
1067/// #![inner_attr]
1068/// ❰ { } ❱
1069///
1070/// ❰ 'label: { break 'label } ❱
1071/// }
1072/// ❱;
1073/// ```
1074///
1075/// [Reference](https://doc.rust-lang.org/reference/expressions/block-expr.html)
1076/// [Labels for blocks RFC](https://github.com/rust-lang/rfcs/blob/master/text/2046-label-break-value.md)
554#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1077#[derive(Debug, Clone, PartialEq, Eq, Hash)]
555pub struct BlockExpr { 1078pub struct BlockExpr {
556 pub(crate) syntax: SyntaxNode, 1079 pub(crate) syntax: SyntaxNode,
@@ -563,7 +1086,17 @@ impl BlockExpr {
563 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1086 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
564 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } 1087 pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
565} 1088}
566 1089/// Return expression.
1090///
1091/// ```
1092/// || ❰ return 42 ❱;
1093///
1094/// fn bar() {
1095/// ❰ return ❱;
1096/// }
1097/// ```
1098///
1099/// [Reference](https://doc.rust-lang.org/reference/expressions/return-expr.html)
567#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1100#[derive(Debug, Clone, PartialEq, Eq, Hash)]
568pub struct ReturnExpr { 1101pub struct ReturnExpr {
569 pub(crate) syntax: SyntaxNode, 1102 pub(crate) syntax: SyntaxNode,
@@ -572,7 +1105,16 @@ impl ast::AttrsOwner for ReturnExpr {}
572impl ReturnExpr { 1105impl ReturnExpr {
573 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1106 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
574} 1107}
575 1108/// Call expression (not to be confused with method call expression, it is
1109/// a separate ast node).
1110///
1111/// ```
1112/// ❰ foo() ❱;
1113/// ❰ &str::len("bar") ❱;
1114/// ❰ <&str as PartialEq<&str>>::eq(&"", &"") ❱;
1115/// ```
1116///
1117/// [Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html)
576#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1118#[derive(Debug, Clone, PartialEq, Eq, Hash)]
577pub struct CallExpr { 1119pub struct CallExpr {
578 pub(crate) syntax: SyntaxNode, 1120 pub(crate) syntax: SyntaxNode,
@@ -581,7 +1123,16 @@ impl ast::ArgListOwner for CallExpr {}
581impl CallExpr { 1123impl CallExpr {
582 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } 1124 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
583} 1125}
584 1126/// Method call expression.
1127///
1128/// ```
1129/// ❰ receiver_expr.method() ❱;
1130/// ❰ receiver_expr.method::<T>(42, true) ❱;
1131///
1132/// ❰ ❰ ❰ foo.bar() ❱ .baz() ❱ .bruh() ❱;
1133/// ```
1134///