mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 20:43:21 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
8068302fef
478 changed files with 9538 additions and 10722 deletions
5
.github/workflows/ci.yaml
vendored
5
.github/workflows/ci.yaml
vendored
|
@ -61,9 +61,6 @@ jobs:
|
|||
override: true
|
||||
components: rustfmt, rust-src
|
||||
|
||||
- if: matrix.os == 'ubuntu-latest'
|
||||
run: sudo chown -R $(whoami):$(id -ng) ~/.cargo/
|
||||
|
||||
- name: Cache cargo directories
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
@ -108,8 +105,6 @@ jobs:
|
|||
override: true
|
||||
target: 'powerpc-unknown-linux-gnu'
|
||||
|
||||
- run: sudo chown -R $(whoami):$(id -ng) ~/.cargo/
|
||||
|
||||
- name: Cache cargo directories
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
|
|
189
Cargo.lock
generated
189
Cargo.lock
generated
|
@ -102,13 +102,12 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
|||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.10.0"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf"
|
||||
checksum = "89fec17b16f1ac67908af82e47d0a90a7afd0e1827b181cd77504323d3263d35"
|
||||
dependencies = [
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
|
@ -126,9 +125,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|||
|
||||
[[package]]
|
||||
name = "chalk-derive"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eea3a22f0c30b2504ac4ab58934dac0d00b92a4d7788df32795cabca24c3f929"
|
||||
checksum = "c1df0dbb57d74b4acd20f20fa66ab2acd09776b79eaeb9d8f947b2f3e01c40bf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -138,9 +137,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-ir"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb617b643e145e3b151502799e91a9625dd5daf1cf05dc2cb821bc75ae0c9cbd"
|
||||
checksum = "44361a25dbdb1dc428f56ad7a3c21ba9ca12f3225c26a47919ff6fcb10a583d4"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"lazy_static",
|
||||
|
@ -148,9 +147,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-recursive"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d280565c8eefbf9b2bc615df49c7dfd971faad37774bf65734e626fd23864bd6"
|
||||
checksum = "dd89556b98de156d5eaf21077d297cd2198628f10f2df140798ea3a5dd84bc86"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
|
@ -161,9 +160,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-solve"
|
||||
version = "0.18.0"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be906fbca3f3077dce0e76d9864771d0f450c946af0d86b569fb9504148a065a"
|
||||
checksum = "a886da37a0dc457057d86f78f026f7a09c6d8088aa13f4f4127fdb8dc80119a3"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
|
@ -280,9 +279,9 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
|||
|
||||
[[package]]
|
||||
name = "drop_bomb"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69b26e475fd29098530e709294e94e661974c851aed42512793f120fed4e199f"
|
||||
checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
|
@ -319,9 +318,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.10"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695"
|
||||
checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
@ -400,17 +399,6 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.22.0"
|
||||
|
@ -565,9 +553,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.73"
|
||||
version = "0.2.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9"
|
||||
checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
|
@ -619,9 +607,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lsp-types"
|
||||
version = "0.78.0"
|
||||
version = "0.79.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2e6cf68e3492cfa2035f0382c1da1b6ab045db0320feca505b86b4f13d66c27"
|
||||
checksum = "7f1f86677fdbe8df5f88b99131b1424e50aad27bbe3e5900d221bc414bd72e9b"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bitflags",
|
||||
|
@ -810,6 +798,12 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.0"
|
||||
|
@ -846,6 +840,25 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "perf-event"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76c42ba5d85a2f4472b99f475fb60cf336d9b4c85b1ea8bb300fef2e3c7c8f89"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"perf-event-open-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "perf-event-open-sys"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95db63e37862bc1b842135d2234ef9418f222cc660c6752f45e7cf9ddfb97f96"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.5.1"
|
||||
|
@ -868,12 +881,6 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.19"
|
||||
|
@ -1046,6 +1053,7 @@ dependencies = [
|
|||
"indexmap",
|
||||
"itertools",
|
||||
"log",
|
||||
"oorandom",
|
||||
"ra_assists",
|
||||
"ra_cfg",
|
||||
"ra_db",
|
||||
|
@ -1056,7 +1064,6 @@ dependencies = [
|
|||
"ra_ssr",
|
||||
"ra_syntax",
|
||||
"ra_text_edit",
|
||||
"rand",
|
||||
"rustc-hash",
|
||||
"stdx",
|
||||
"test_utils",
|
||||
|
@ -1138,6 +1145,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"perf-event",
|
||||
"ra_arena",
|
||||
]
|
||||
|
||||
|
@ -1217,57 +1225,6 @@ dependencies = [
|
|||
"stdx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
"rand_pcg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.3.1"
|
||||
|
@ -1354,6 +1311,7 @@ dependencies = [
|
|||
"lsp-server",
|
||||
"lsp-types",
|
||||
"mimalloc",
|
||||
"oorandom",
|
||||
"parking_lot",
|
||||
"pico-args",
|
||||
"ra_cfg",
|
||||
|
@ -1372,7 +1330,6 @@ dependencies = [
|
|||
"ra_text_edit",
|
||||
"ra_toolchain",
|
||||
"ra_tt",
|
||||
"rand",
|
||||
"rayon",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
|
@ -1387,9 +1344,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_lexer"
|
||||
version = "669.0.0"
|
||||
version = "671.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456af5f09c006cf6c22c1a433ee0232c4bb74bdc6c647a010166a47c94ed2a63"
|
||||
checksum = "22e1221f3bfa2943c942cf8da319ab2346887f8757778c29c7f1822cd27b521f"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
@ -1414,16 +1371,16 @@ checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
|||
|
||||
[[package]]
|
||||
name = "salsa"
|
||||
version = "0.15.0"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "885b4b99dde959decc84e85dd943bd140b4aabd62db2f8206ef5270f77ec20b9"
|
||||
checksum = "9ab29056d4fb4048a5f0d169c9b6e5526160c9ec37aded5a6879c2c9c445a8e4"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"indexmap",
|
||||
"lock_api",
|
||||
"log",
|
||||
"oorandom",
|
||||
"parking_lot",
|
||||
"rand",
|
||||
"rustc-hash",
|
||||
"salsa-macros",
|
||||
"smallvec",
|
||||
|
@ -1431,9 +1388,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "salsa-macros"
|
||||
version = "0.15.0"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c280ac85b15ac214b86ac4b407626a48e6a1c4f90769a582fec74aa57942b9f"
|
||||
checksum = "a1c3aec007c63c4ed4cd7a018529fb0b5575c4562575fc6a40d6cd2ae0b792ef"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
@ -1484,9 +1441,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
checksum = "394cec28fa623e00903caf7ba4fa6fb9a0e260280bb8cdbbba029611108a0190"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
"serde",
|
||||
|
@ -1576,9 +1533,9 @@ version = "0.1.0"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.36"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250"
|
||||
checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1665,9 +1622,9 @@ checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed"
|
|||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.17"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbdf4ccd1652592b01286a5dbe1e2a77d78afaa34beadd9872a5f7396f92aaa9"
|
||||
checksum = "f0aae59226cf195d8e74d4b34beae1859257efb4e5fed3f147d2dc2c7d372178"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"tracing-attributes",
|
||||
|
@ -1687,9 +1644,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.11"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94ae75f0d28ae10786f3b1895c55fe72e79928fd5ccdebb5438c75e93fec178f"
|
||||
checksum = "d593f98af59ebc017c0648f0117525db358745a8894a8d684e185ba3f45954f9"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
@ -1717,9 +1674,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.9"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4f5dd7095c2481b7b3cbed71c8de53085fb3542bc3c2b4c73cba43e8f11c7ba"
|
||||
checksum = "f7b33f8b2ef2ab0c3778c12646d9c42a24f7772bee4cdafc72199644a9f58fdc"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"chrono",
|
||||
|
@ -1749,6 +1706,12 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ungrammar"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4e20e58a08ee1bcf8a4695cf74550cf054d6c489105f594beacb2c684210aad"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.4"
|
||||
|
@ -1825,12 +1788,6 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
@ -1874,6 +1831,12 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "write-json"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3"
|
||||
|
||||
[[package]]
|
||||
name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
|
@ -1893,5 +1856,7 @@ dependencies = [
|
|||
"pico-args",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"ungrammar",
|
||||
"walkdir",
|
||||
"write-json",
|
||||
]
|
||||
|
|
|
@ -11,7 +11,7 @@ doctest = false
|
|||
[dependencies]
|
||||
crossbeam-channel = "0.4.0"
|
||||
log = "0.4.8"
|
||||
cargo_metadata = "0.10.0"
|
||||
cargo_metadata = "0.11.1"
|
||||
serde_json = "1.0.48"
|
||||
jod-thread = "0.1.1"
|
||||
ra_toolchain = { path = "../ra_toolchain" }
|
||||
|
|
|
@ -24,6 +24,7 @@ pub enum FlycheckConfig {
|
|||
command: String,
|
||||
target_triple: Option<String>,
|
||||
all_targets: bool,
|
||||
no_default_features: bool,
|
||||
all_features: bool,
|
||||
features: Vec<String>,
|
||||
extra_args: Vec<String>,
|
||||
|
@ -180,6 +181,7 @@ impl FlycheckActor {
|
|||
FlycheckConfig::CargoCommand {
|
||||
command,
|
||||
target_triple,
|
||||
no_default_features,
|
||||
all_targets,
|
||||
all_features,
|
||||
extra_args,
|
||||
|
@ -198,9 +200,14 @@ impl FlycheckActor {
|
|||
}
|
||||
if *all_features {
|
||||
cmd.arg("--all-features");
|
||||
} else if !features.is_empty() {
|
||||
cmd.arg("--features");
|
||||
cmd.arg(features.join(" "));
|
||||
} else {
|
||||
if *no_default_features {
|
||||
cmd.arg("--no-default-features");
|
||||
}
|
||||
if !features.is_empty() {
|
||||
cmd.arg("--features");
|
||||
cmd.arg(features.join(" "));
|
||||
}
|
||||
}
|
||||
cmd.args(extra_args);
|
||||
cmd
|
||||
|
|
|
@ -73,6 +73,10 @@ impl<'a> AssistContext<'a> {
|
|||
self.sema.db
|
||||
}
|
||||
|
||||
pub(crate) fn source_file(&self) -> &SourceFile {
|
||||
&self.source_file
|
||||
}
|
||||
|
||||
// NB, this ignores active selection.
|
||||
pub(crate) fn offset(&self) -> TextSize {
|
||||
self.frange.range.start()
|
||||
|
|
|
@ -32,7 +32,7 @@ impl<'a> AstTransform<'a> for NullTransformer {
|
|||
|
||||
pub struct SubstituteTypeParams<'a> {
|
||||
source_scope: &'a SemanticsScope<'a>,
|
||||
substs: FxHashMap<hir::TypeParam, ast::TypeRef>,
|
||||
substs: FxHashMap<hir::TypeParam, ast::Type>,
|
||||
previous: Box<dyn AstTransform<'a> + 'a>,
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ impl<'a> SubstituteTypeParams<'a> {
|
|||
source_scope: &'a SemanticsScope<'a>,
|
||||
// FIXME: there's implicit invariant that `trait_` and `source_scope` match...
|
||||
trait_: hir::Trait,
|
||||
impl_def: ast::ImplDef,
|
||||
impl_def: ast::Impl,
|
||||
) -> SubstituteTypeParams<'a> {
|
||||
let substs = get_syntactic_substs(impl_def).unwrap_or_default();
|
||||
let generic_def: hir::GenericDef = trait_.into();
|
||||
|
@ -63,7 +63,7 @@ impl<'a> SubstituteTypeParams<'a> {
|
|||
let default = k.default(source_scope.db)?;
|
||||
Some((
|
||||
k,
|
||||
ast::make::type_ref(
|
||||
ast::make::ty(
|
||||
&default
|
||||
.display_source_code(source_scope.db, source_scope.module()?.into())
|
||||
.ok()?,
|
||||
|
@ -79,19 +79,25 @@ impl<'a> SubstituteTypeParams<'a> {
|
|||
};
|
||||
|
||||
// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
|
||||
// trait ref, and then go from the types in the substs back to the syntax)
|
||||
fn get_syntactic_substs(impl_def: ast::ImplDef) -> Option<Vec<ast::TypeRef>> {
|
||||
let target_trait = impl_def.target_trait()?;
|
||||
// trait ref, and then go from the types in the substs back to the syntax).
|
||||
fn get_syntactic_substs(impl_def: ast::Impl) -> Option<Vec<ast::Type>> {
|
||||
let target_trait = impl_def.trait_()?;
|
||||
let path_type = match target_trait {
|
||||
ast::TypeRef::PathType(path) => path,
|
||||
ast::Type::PathType(path) => path,
|
||||
_ => return None,
|
||||
};
|
||||
let type_arg_list = path_type.path()?.segment()?.type_arg_list()?;
|
||||
let generic_arg_list = path_type.path()?.segment()?.generic_arg_list()?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
for type_arg in type_arg_list.type_args() {
|
||||
let type_arg: ast::TypeArg = type_arg;
|
||||
result.push(type_arg.type_ref()?);
|
||||
for generic_arg in generic_arg_list.generic_args() {
|
||||
match generic_arg {
|
||||
ast::GenericArg::TypeArg(type_arg) => result.push(type_arg.ty()?),
|
||||
ast::GenericArg::AssocTypeArg(_)
|
||||
| ast::GenericArg::LifetimeArg(_)
|
||||
| ast::GenericArg::ConstArg(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
Some(result)
|
||||
}
|
||||
}
|
||||
|
@ -99,9 +105,9 @@ impl<'a> SubstituteTypeParams<'a> {
|
|||
&self,
|
||||
node: &ra_syntax::SyntaxNode,
|
||||
) -> Option<ra_syntax::SyntaxNode> {
|
||||
let type_ref = ast::TypeRef::cast(node.clone())?;
|
||||
let type_ref = ast::Type::cast(node.clone())?;
|
||||
let path = match &type_ref {
|
||||
ast::TypeRef::PathType(path_type) => path_type.path()?,
|
||||
ast::Type::PathType(path_type) => path_type.path()?,
|
||||
_ => return None,
|
||||
};
|
||||
// FIXME: use `hir::Path::from_src` instead.
|
||||
|
@ -157,7 +163,7 @@ impl<'a> QualifyPaths<'a> {
|
|||
|
||||
let type_args = p
|
||||
.segment()
|
||||
.and_then(|s| s.type_arg_list())
|
||||
.and_then(|s| s.generic_arg_list())
|
||||
.map(|arg_list| apply(self, arg_list));
|
||||
if let Some(type_args) = type_args {
|
||||
let last_segment = path.segment().unwrap();
|
||||
|
|
|
@ -29,8 +29,8 @@ use crate::{
|
|||
// }
|
||||
// ```
|
||||
pub(crate) fn add_custom_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let input = ctx.find_node_at_offset::<ast::AttrInput>()?;
|
||||
let attr = input.syntax().parent().and_then(ast::Attr::cast)?;
|
||||
let attr = ctx.find_node_at_offset::<ast::Attr>()?;
|
||||
let input = attr.token_tree()?;
|
||||
|
||||
let attr_name = attr
|
||||
.syntax()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use hir::HirDisplay;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner},
|
||||
ast::{self, AstNode, LetStmt, NameOwner},
|
||||
TextRange,
|
||||
};
|
||||
|
||||
|
@ -22,20 +22,20 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
|
|||
// }
|
||||
// ```
|
||||
pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let stmt = ctx.find_node_at_offset::<LetStmt>()?;
|
||||
let module = ctx.sema.scope(stmt.syntax()).module()?;
|
||||
let expr = stmt.initializer()?;
|
||||
let let_stmt = ctx.find_node_at_offset::<LetStmt>()?;
|
||||
let module = ctx.sema.scope(let_stmt.syntax()).module()?;
|
||||
let expr = let_stmt.initializer()?;
|
||||
// Must be a binding
|
||||
let pat = match stmt.pat()? {
|
||||
ast::Pat::BindPat(bind_pat) => bind_pat,
|
||||
let pat = match let_stmt.pat()? {
|
||||
ast::Pat::IdentPat(bind_pat) => bind_pat,
|
||||
_ => return None,
|
||||
};
|
||||
let pat_range = pat.syntax().text_range();
|
||||
// The binding must have a name
|
||||
let name = pat.name()?;
|
||||
let name_range = name.syntax().text_range();
|
||||
let stmt_range = stmt.syntax().text_range();
|
||||
let eq_range = stmt.eq_token()?.text_range();
|
||||
let stmt_range = let_stmt.syntax().text_range();
|
||||
let eq_range = let_stmt.eq_token()?.text_range();
|
||||
// Assist should only be applicable if cursor is between 'let' and '='
|
||||
let let_range = TextRange::new(stmt_range.start(), eq_range.start());
|
||||
let cursor_in_range = let_range.contains_range(ctx.frange.range);
|
||||
|
@ -44,9 +44,9 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
|
|||
}
|
||||
// Assist not applicable if the type has already been specified
|
||||
// and it has no placeholders
|
||||
let ascribed_ty = stmt.ascribed_type();
|
||||
let ascribed_ty = let_stmt.ty();
|
||||
if let Some(ty) = &ascribed_ty {
|
||||
if ty.syntax().descendants().find_map(ast::PlaceholderType::cast).is_none() {
|
||||
if ty.syntax().descendants().find_map(ast::InferType::cast).is_none() {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,16 +111,17 @@ fn add_missing_impl_members_inner(
|
|||
label: &'static str,
|
||||
) -> Option<()> {
|
||||
let _p = ra_prof::profile("add_missing_impl_members_inner");
|
||||
let impl_def = ctx.find_node_at_offset::<ast::ImplDef>()?;
|
||||
let impl_item_list = impl_def.item_list()?;
|
||||
let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;
|
||||
let impl_item_list = impl_def.assoc_item_list()?;
|
||||
|
||||
let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
|
||||
|
||||
let def_name = |item: &ast::AssocItem| -> Option<SmolStr> {
|
||||
match item {
|
||||
ast::AssocItem::FnDef(def) => def.name(),
|
||||
ast::AssocItem::TypeAliasDef(def) => def.name(),
|
||||
ast::AssocItem::ConstDef(def) => def.name(),
|
||||
ast::AssocItem::Fn(def) => def.name(),
|
||||
ast::AssocItem::TypeAlias(def) => def.name(),
|
||||
ast::AssocItem::Const(def) => def.name(),
|
||||
ast::AssocItem::MacroCall(_) => None,
|
||||
}
|
||||
.map(|it| it.text().clone())
|
||||
};
|
||||
|
@ -128,13 +129,13 @@ fn add_missing_impl_members_inner(
|
|||
let missing_items = get_missing_assoc_items(&ctx.sema, &impl_def)
|
||||
.iter()
|
||||
.map(|i| match i {
|
||||
hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db()).value),
|
||||
hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAliasDef(i.source(ctx.db()).value),
|
||||
hir::AssocItem::Const(i) => ast::AssocItem::ConstDef(i.source(ctx.db()).value),
|
||||
hir::AssocItem::Function(i) => ast::AssocItem::Fn(i.source(ctx.db()).value),
|
||||
hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAlias(i.source(ctx.db()).value),
|
||||
hir::AssocItem::Const(i) => ast::AssocItem::Const(i.source(ctx.db()).value),
|
||||
})
|
||||
.filter(|t| def_name(&t).is_some())
|
||||
.filter(|t| match t {
|
||||
ast::AssocItem::FnDef(def) => match mode {
|
||||
ast::AssocItem::Fn(def) => match mode {
|
||||
AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(),
|
||||
AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(),
|
||||
},
|
||||
|
@ -157,10 +158,8 @@ fn add_missing_impl_members_inner(
|
|||
.into_iter()
|
||||
.map(|it| ast_transform::apply(&*ast_transform, it))
|
||||
.map(|it| match it {
|
||||
ast::AssocItem::FnDef(def) => ast::AssocItem::FnDef(add_body(def)),
|
||||
ast::AssocItem::TypeAliasDef(def) => {
|
||||
ast::AssocItem::TypeAliasDef(def.remove_bounds())
|
||||
}
|
||||
ast::AssocItem::Fn(def) => ast::AssocItem::Fn(add_body(def)),
|
||||
ast::AssocItem::TypeAlias(def) => ast::AssocItem::TypeAlias(def.remove_bounds()),
|
||||
_ => it,
|
||||
})
|
||||
.map(|it| edit::remove_attrs_and_docs(&it));
|
||||
|
@ -173,7 +172,7 @@ fn add_missing_impl_members_inner(
|
|||
Some(cap) => {
|
||||
let mut cursor = Cursor::Before(first_new_item.syntax());
|
||||
let placeholder;
|
||||
if let ast::AssocItem::FnDef(func) = &first_new_item {
|
||||
if let ast::AssocItem::Fn(func) = &first_new_item {
|
||||
if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) {
|
||||
if m.syntax().text() == "todo!()" {
|
||||
placeholder = m;
|
||||
|
@ -191,7 +190,7 @@ fn add_missing_impl_members_inner(
|
|||
})
|
||||
}
|
||||
|
||||
fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
|
||||
fn add_body(fn_def: ast::Fn) -> ast::Fn {
|
||||
if fn_def.body().is_some() {
|
||||
return fn_def;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ impl AutoImportAssets {
|
|||
|
||||
fn for_regular_path(path_under_caret: ast::Path, ctx: &AssistContext) -> Option<Self> {
|
||||
let syntax_under_caret = path_under_caret.syntax().to_owned();
|
||||
if syntax_under_caret.ancestors().find_map(ast::UseItem::cast).is_some() {
|
||||
if syntax_under_caret.ancestors().find_map(ast::Use::cast).is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ use test_utils::mark;
|
|||
pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
|
||||
// FIXME: extend to lambdas as well
|
||||
let fn_def = ret_type.syntax().parent().and_then(ast::FnDef::cast)?;
|
||||
let fn_def = ret_type.syntax().parent().and_then(ast::Fn::cast)?;
|
||||
|
||||
let type_ref = &ret_type.type_ref()?;
|
||||
let type_ref = &ret_type.ty()?;
|
||||
let ret_type_str = type_ref.syntax().text().to_string();
|
||||
let first_part_ret_type = ret_type_str.splitn(2, '<').next();
|
||||
if let Some(ret_type_first_part) = first_part_ret_type {
|
||||
|
@ -74,6 +74,7 @@ impl TailReturnCollector {
|
|||
let expr = match &stmt {
|
||||
ast::Stmt::ExprStmt(stmt) => stmt.expr(),
|
||||
ast::Stmt::LetStmt(stmt) => stmt.initializer(),
|
||||
ast::Stmt::Item(_) => continue,
|
||||
};
|
||||
if let Some(expr) = &expr {
|
||||
self.handle_exprs(expr, collect_break);
|
||||
|
@ -94,6 +95,7 @@ impl TailReturnCollector {
|
|||
let expr_stmt = match &expr_stmt {
|
||||
ast::Stmt::ExprStmt(stmt) => stmt.expr(),
|
||||
ast::Stmt::LetStmt(stmt) => stmt.initializer(),
|
||||
ast::Stmt::Item(_) => None,
|
||||
};
|
||||
if let Some(expr) = &expr_stmt {
|
||||
self.handle_exprs(expr, collect_break);
|
||||
|
@ -239,8 +241,7 @@ fn get_tail_expr_from_block(expr: &Expr) -> Option<Vec<NodeType>> {
|
|||
Expr::ArrayExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
Expr::ParenExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
Expr::PathExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
Expr::Label(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
Expr::RecordLit(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
Expr::RecordExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
Expr::IndexExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
Expr::MethodCallExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
Expr::AwaitExpr(expr) => Some(vec![NodeType::Leaf(expr.syntax().clone())]),
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use ra_syntax::{
|
||||
ast::{self, NameOwner, VisibilityOwner},
|
||||
AstNode,
|
||||
SyntaxKind::{
|
||||
CONST_DEF, ENUM_DEF, FN_DEF, MODULE, STATIC_DEF, STRUCT_DEF, TRAIT_DEF, VISIBILITY,
|
||||
},
|
||||
SyntaxKind::{CONST, ENUM, FN, MODULE, STATIC, STRUCT, TRAIT, VISIBILITY},
|
||||
T,
|
||||
};
|
||||
use test_utils::mark;
|
||||
|
@ -38,7 +36,7 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
|||
|
||||
let (offset, target) = if let Some(keyword) = item_keyword {
|
||||
let parent = keyword.parent();
|
||||
let def_kws = vec![CONST_DEF, STATIC_DEF, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF];
|
||||
let def_kws = vec![CONST, STATIC, FN, MODULE, STRUCT, ENUM, TRAIT];
|
||||
// Parent is not a definition, can't add visibility
|
||||
if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
|
||||
return None;
|
||||
|
@ -49,7 +47,7 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
|||
}
|
||||
(vis_offset(&parent), keyword.text_range())
|
||||
} else if let Some(field_name) = ctx.find_node_at_offset::<ast::Name>() {
|
||||
let field = field_name.syntax().ancestors().find_map(ast::RecordFieldDef::cast)?;
|
||||
let field = field_name.syntax().ancestors().find_map(ast::RecordField::cast)?;
|
||||
if field.name()? != field_name {
|
||||
mark::hit!(change_visibility_field_false_positive);
|
||||
return None;
|
||||
|
@ -58,7 +56,7 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
|||
return None;
|
||||
}
|
||||
(vis_offset(field.syntax()), field_name.syntax().text_range())
|
||||
} else if let Some(field) = ctx.find_node_at_offset::<ast::TupleFieldDef>() {
|
||||
} else if let Some(field) = ctx.find_node_at_offset::<ast::TupleField>() {
|
||||
if field.visibility().is_some() {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use ra_syntax::{
|
|||
make,
|
||||
},
|
||||
AstNode,
|
||||
SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
|
||||
SyntaxKind::{FN, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
|
||||
SyntaxNode,
|
||||
};
|
||||
|
||||
|
@ -51,11 +51,11 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
|
|||
// Check if there is an IfLet that we can handle.
|
||||
let if_let_pat = match cond.pat() {
|
||||
None => None, // No IfLet, supported.
|
||||
Some(ast::Pat::TupleStructPat(pat)) if pat.args().count() == 1 => {
|
||||
Some(ast::Pat::TupleStructPat(pat)) if pat.fields().count() == 1 => {
|
||||
let path = pat.path()?;
|
||||
match path.qualifier() {
|
||||
None => {
|
||||
let bound_ident = pat.args().next().unwrap();
|
||||
let bound_ident = pat.fields().next().unwrap();
|
||||
Some((path, bound_ident))
|
||||
}
|
||||
Some(_) => return None,
|
||||
|
@ -88,7 +88,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
|
|||
|
||||
let early_expression: ast::Expr = match parent_container.kind() {
|
||||
WHILE_EXPR | LOOP_EXPR => make::expr_continue(),
|
||||
FN_DEF => make::expr_return(),
|
||||
FN => make::expr_return(),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
@ -123,7 +123,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
|
|||
let happy_arm = {
|
||||
let pat = make::tuple_struct_pat(
|
||||
path,
|
||||
once(make::bind_pat(make::name("it")).into()),
|
||||
once(make::ident_pat(make::name("it")).into()),
|
||||
);
|
||||
let expr = {
|
||||
let name_ref = make::name_ref("it");
|
||||
|
@ -136,7 +136,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
|
|||
|
||||
let sad_arm = make::match_arm(
|
||||
// FIXME: would be cool to use `None` or `Err(_)` if appropriate
|
||||
once(make::placeholder_pat().into()),
|
||||
once(make::wildcard_pat().into()),
|
||||
early_expression,
|
||||
);
|
||||
|
||||
|
@ -144,7 +144,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
|
|||
};
|
||||
|
||||
let let_stmt = make::let_stmt(
|
||||
make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(),
|
||||
make::ident_pat(make::name(&bound_ident.syntax().to_string())).into(),
|
||||
Some(match_expr),
|
||||
);
|
||||
let let_stmt = let_stmt.indent(if_indent_level);
|
||||
|
|
391
crates/ra_assists/src/handlers/expand_glob_import.rs
Normal file
391
crates/ra_assists/src/handlers/expand_glob_import.rs
Normal file
|
@ -0,0 +1,391 @@
|
|||
use hir::{AssocItem, MacroDef, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope};
|
||||
use ra_ide_db::{
|
||||
defs::{classify_name_ref, Definition, NameRefClass},
|
||||
RootDatabase,
|
||||
};
|
||||
use ra_syntax::{algo, ast, match_ast, AstNode, SyntaxNode, SyntaxToken, T};
|
||||
|
||||
use crate::{
|
||||
assist_context::{AssistBuilder, AssistContext, Assists},
|
||||
AssistId, AssistKind,
|
||||
};
|
||||
|
||||
use either::Either;
|
||||
|
||||
// Assist: expand_glob_import
|
||||
//
|
||||
// Expands glob imports.
|
||||
//
|
||||
// ```
|
||||
// mod foo {
|
||||
// pub struct Bar;
|
||||
// pub struct Baz;
|
||||
// }
|
||||
//
|
||||
// use foo::*<|>;
|
||||
//
|
||||
// fn qux(bar: Bar, baz: Baz) {}
|
||||
// ```
|
||||
// ->
|
||||
// ```
|
||||
// mod foo {
|
||||
// pub struct Bar;
|
||||
// pub struct Baz;
|
||||
// }
|
||||
//
|
||||
// use foo::{Baz, Bar};
|
||||
//
|
||||
// fn qux(bar: Bar, baz: Baz) {}
|
||||
// ```
|
||||
pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let star = ctx.find_token_at_offset(T![*])?;
|
||||
let mod_path = find_mod_path(&star)?;
|
||||
|
||||
let source_file = ctx.source_file();
|
||||
let scope = ctx.sema.scope_at_offset(source_file.syntax(), ctx.offset());
|
||||
|
||||
let defs_in_mod = find_defs_in_mod(ctx, scope, &mod_path)?;
|
||||
let name_refs_in_source_file =
|
||||
source_file.syntax().descendants().filter_map(ast::NameRef::cast).collect();
|
||||
let used_names = find_used_names(ctx, defs_in_mod, name_refs_in_source_file);
|
||||
|
||||
let parent = star.parent().parent()?;
|
||||
acc.add(
|
||||
AssistId("expand_glob_import", AssistKind::RefactorRewrite),
|
||||
"Expand glob import",
|
||||
parent.text_range(),
|
||||
|builder| {
|
||||
replace_ast(builder, &parent, mod_path, used_names);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn find_mod_path(star: &SyntaxToken) -> Option<ast::Path> {
|
||||
star.ancestors().find_map(|n| ast::UseTree::cast(n).and_then(|u| u.path()))
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum Def {
|
||||
ModuleDef(ModuleDef),
|
||||
MacroDef(MacroDef),
|
||||
}
|
||||
|
||||
impl Def {
|
||||
fn name(&self, db: &RootDatabase) -> Option<Name> {
|
||||
match self {
|
||||
Def::ModuleDef(def) => def.name(db),
|
||||
Def::MacroDef(def) => def.name(db),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_defs_in_mod(
|
||||
ctx: &AssistContext,
|
||||
from: SemanticsScope<'_>,
|
||||
path: &ast::Path,
|
||||
) -> Option<Vec<Def>> {
|
||||
let hir_path = ctx.sema.lower_path(&path)?;
|
||||
let module = if let Some(PathResolution::Def(ModuleDef::Module(module))) =
|
||||
from.resolve_hir_path_qualifier(&hir_path)
|
||||
{
|
||||
module
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let module_scope = module.scope(ctx.db(), from.module());
|
||||
|
||||
let mut defs = vec![];
|
||||
for (_, def) in module_scope {
|
||||
match def {
|
||||
ScopeDef::ModuleDef(def) => defs.push(Def::ModuleDef(def)),
|
||||
ScopeDef::MacroDef(def) => defs.push(Def::MacroDef(def)),
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
||||
Some(defs)
|
||||
}
|
||||
|
||||
fn find_used_names(
|
||||
ctx: &AssistContext,
|
||||
defs_in_mod: Vec<Def>,
|
||||
name_refs_in_source_file: Vec<ast::NameRef>,
|
||||
) -> Vec<Name> {
|
||||
let defs_in_source_file = name_refs_in_source_file
|
||||
.iter()
|
||||
.filter_map(|r| classify_name_ref(&ctx.sema, r))
|
||||
.filter_map(|rc| match rc {
|
||||
NameRefClass::Definition(Definition::ModuleDef(def)) => Some(Def::ModuleDef(def)),
|
||||
NameRefClass::Definition(Definition::Macro(def)) => Some(Def::MacroDef(def)),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<Def>>();
|
||||
|
||||
defs_in_mod
|
||||
.iter()
|
||||
.filter(|def| {
|
||||
if let Def::ModuleDef(ModuleDef::Trait(tr)) = def {
|
||||
for item in tr.items(ctx.db()) {
|
||||
if let AssocItem::Function(f) = item {
|
||||
if defs_in_source_file.contains(&Def::ModuleDef(ModuleDef::Function(f))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defs_in_source_file.contains(def)
|
||||
})
|
||||
.filter_map(|d| d.name(ctx.db()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn replace_ast(
|
||||
builder: &mut AssistBuilder,
|
||||
node: &SyntaxNode,
|
||||
path: ast::Path,
|
||||
used_names: Vec<Name>,
|
||||
) {
|
||||
let replacement: Either<ast::UseTree, ast::UseTreeList> = match used_names.as_slice() {
|
||||
[name] => Either::Left(ast::make::use_tree(
|
||||
ast::make::path_from_text(&format!("{}::{}", path, name)),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
)),
|
||||
names => Either::Right(ast::make::use_tree_list(names.iter().map(|n| {
|
||||
ast::make::use_tree(ast::make::path_from_text(&n.to_string()), None, None, false)
|
||||
}))),
|
||||
};
|
||||
|
||||
let mut replace_node = |replacement: Either<ast::UseTree, ast::UseTreeList>| {
|
||||
algo::diff(node, &replacement.either(|u| u.syntax().clone(), |ut| ut.syntax().clone()))
|
||||
.into_text_edit(builder.text_edit_builder());
|
||||
};
|
||||
|
||||
match_ast! {
|
||||
match node {
|
||||
ast::UseTree(use_tree) => {
|
||||
replace_node(replacement);
|
||||
},
|
||||
ast::UseTreeList(use_tree_list) => {
|
||||
replace_node(replacement);
|
||||
},
|
||||
ast::Use(use_item) => {
|
||||
builder.replace_ast(use_item, ast::make::use_(replacement.left_or_else(|ut| ast::make::use_tree(path, Some(ut), None, false))));
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn expanding_glob_import() {
|
||||
check_assist(
|
||||
expand_glob_import,
|
||||
r"
|
||||
mod foo {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
pub struct Qux;
|
||||
|
||||
pub fn f() {}
|
||||
}
|
||||
|
||||
use foo::*<|>;
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {
|
||||
f();
|
||||
}
|
||||
",
|
||||
r"
|
||||
mod foo {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
pub struct Qux;
|
||||
|
||||
pub fn f() {}
|
||||
}
|
||||
|
||||
use foo::{Baz, Bar, f};
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {
|
||||
f();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expanding_glob_import_with_existing_explicit_names() {
|
||||
check_assist(
|
||||
expand_glob_import,
|
||||
r"
|
||||
mod foo {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
pub struct Qux;
|
||||
|
||||
pub fn f() {}
|
||||
}
|
||||
|
||||
use foo::{*<|>, f};
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {
|
||||
f();
|
||||
}
|
||||
",
|
||||
r"
|
||||
mod foo {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
pub struct Qux;
|
||||
|
||||
pub fn f() {}
|
||||
}
|
||||
|
||||
use foo::{Baz, Bar, f};
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {
|
||||
f();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expanding_nested_glob_import() {
|
||||
check_assist(
|
||||
expand_glob_import,
|
||||
r"
|
||||
mod foo {
|
||||
mod bar {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
pub struct Qux;
|
||||
|
||||
pub fn f() {}
|
||||
}
|
||||
|
||||
mod baz {
|
||||
pub fn g() {}
|
||||
}
|
||||
}
|
||||
|
||||
use foo::{bar::{*<|>, f}, baz::*};
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {
|
||||
f();
|
||||
g();
|
||||
}
|
||||
",
|
||||
r"
|
||||
mod foo {
|
||||
mod bar {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
pub struct Qux;
|
||||
|
||||
pub fn f() {}
|
||||
}
|
||||
|
||||
mod baz {
|
||||
pub fn g() {}
|
||||
}
|
||||
}
|
||||
|
||||
use foo::{bar::{Baz, Bar, f}, baz::*};
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {
|
||||
f();
|
||||
g();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expanding_glob_import_with_macro_defs() {
|
||||
check_assist(
|
||||
expand_glob_import,
|
||||
r"
|
||||
//- /lib.rs crate:foo
|
||||
#[macro_export]
|
||||
macro_rules! bar {
|
||||
() => ()
|
||||
}
|
||||
|
||||
pub fn baz() {}
|
||||
|
||||
//- /main.rs crate:main deps:foo
|
||||
use foo::*<|>;
|
||||
|
||||
fn main() {
|
||||
bar!();
|
||||
baz();
|
||||
}
|
||||
",
|
||||
r"
|
||||
use foo::{bar, baz};
|
||||
|
||||
fn main() {
|
||||
bar!();
|
||||
baz();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expanding_glob_import_with_trait_method_uses() {
|
||||
check_assist(
|
||||
expand_glob_import,
|
||||
r"
|
||||
//- /lib.rs crate:foo
|
||||
pub trait Tr {
|
||||
fn method(&self) {}
|
||||
}
|
||||
impl Tr for () {}
|
||||
|
||||
//- /main.rs crate:main deps:foo
|
||||
use foo::*<|>;
|
||||
|
||||
fn main() {
|
||||
().method();
|
||||
}
|
||||
",
|
||||
r"
|
||||
use foo::Tr;
|
||||
|
||||
fn main() {
|
||||
().method();
|
||||
}
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() {
|
||||
check_assist_not_applicable(
|
||||
expand_glob_import,
|
||||
r"
|
||||
mod foo {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
pub struct Qux;
|
||||
}
|
||||
|
||||
use foo::Bar<|>;
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {}
|
||||
",
|
||||
)
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ pub(crate) fn extract_struct_from_enum_variant(
|
|||
acc: &mut Assists,
|
||||
ctx: &AssistContext,
|
||||
) -> Option<()> {
|
||||
let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?;
|
||||
let variant = ctx.find_node_at_offset::<ast::Variant>()?;
|
||||
let field_list = match variant.kind() {
|
||||
ast::StructKind::Tuple(field_list) => field_list,
|
||||
_ => return None,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use ra_syntax::{
|
||||
ast::{self, AstNode},
|
||||
SyntaxKind::{
|
||||
BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
|
||||
BLOCK_EXPR, BREAK_EXPR, CLOSURE_EXPR, COMMENT, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
|
||||
},
|
||||
SyntaxNode,
|
||||
};
|
||||
|
@ -45,7 +45,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option
|
|||
target,
|
||||
move |edit| {
|
||||
let field_shorthand =
|
||||
match to_extract.syntax().parent().and_then(ast::RecordField::cast) {
|
||||
match to_extract.syntax().parent().and_then(ast::RecordExprField::cast) {
|
||||
Some(field) => field.name_ref(),
|
||||
None => None,
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ impl Anchor {
|
|||
}
|
||||
|
||||
if let Some(parent) = node.parent() {
|
||||
if parent.kind() == MATCH_ARM || parent.kind() == LAMBDA_EXPR {
|
||||
if parent.kind() == MATCH_ARM || parent.kind() == CLOSURE_EXPR {
|
||||
return Some(Anchor::WrapInBlock(node));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
|
|||
|
||||
let mut arms: Vec<MatchArm> = match_arm_list.arms().collect();
|
||||
if arms.len() == 1 {
|
||||
if let Some(Pat::PlaceholderPat(..)) = arms[0].pat() {
|
||||
if let Some(Pat::WildcardPat(..)) = arms[0].pat() {
|
||||
arms.clear();
|
||||
}
|
||||
}
|
||||
|
@ -116,17 +116,15 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
|
|||
match (first_new_arm, ctx.config.snippet_cap) {
|
||||
(Some(first_new_arm), Some(cap)) => {
|
||||
let extend_lifetime;
|
||||
let cursor = match first_new_arm
|
||||
.syntax()
|
||||
.descendants()
|
||||
.find_map(ast::PlaceholderPat::cast)
|
||||
{
|
||||
Some(it) => {
|
||||
extend_lifetime = it.syntax().clone();
|
||||
Cursor::Replace(&extend_lifetime)
|
||||
}
|
||||
None => Cursor::Before(first_new_arm.syntax()),
|
||||
};
|
||||
let cursor =
|
||||
match first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast)
|
||||
{
|
||||
Some(it) => {
|
||||
extend_lifetime = it.syntax().clone();
|
||||
Cursor::Replace(&extend_lifetime)
|
||||
}
|
||||
None => Cursor::Before(first_new_arm.syntax()),
|
||||
};
|
||||
let snippet = render_snippet(cap, new_arm_list.syntax(), cursor);
|
||||
builder.replace_snippet(cap, old_range, snippet);
|
||||
}
|
||||
|
@ -152,7 +150,7 @@ fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {
|
|||
let first_node_text = |pat: &Pat| pat.syntax().first_child().map(|node| node.text());
|
||||
|
||||
let pat_head = match pat {
|
||||
Pat::BindPat(bind_pat) => {
|
||||
Pat::IdentPat(bind_pat) => {
|
||||
if let Some(p) = bind_pat.pat() {
|
||||
first_node_text(&p)
|
||||
} else {
|
||||
|
@ -199,12 +197,11 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> O
|
|||
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
|
||||
let pat: ast::Pat = match var.source(db).value.kind() {
|
||||
ast::StructKind::Tuple(field_list) => {
|
||||
let pats =
|
||||
iter::repeat(make::placeholder_pat().into()).take(field_list.fields().count());
|
||||
let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count());
|
||||
make::tuple_struct_pat(path, pats).into()
|
||||
}
|
||||
ast::StructKind::Record(field_list) => {
|
||||
let pats = field_list.fields().map(|f| make::bind_pat(f.name().unwrap()).into());
|
||||
let pats = field_list.fields().map(|f| make::ident_pat(f.name().unwrap()).into());
|
||||
make::record_pat(path, pats).into()
|
||||
}
|
||||
ast::StructKind::Unit => make::path_pat(path),
|
||||
|
|
|
@ -82,7 +82,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O
|
|||
}
|
||||
|
||||
fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let record_field: ast::RecordField = ctx.find_node_at_offset()?;
|
||||
let record_field: ast::RecordExprField = ctx.find_node_at_offset()?;
|
||||
let (record_field_def, _) = ctx.sema.resolve_record_field(&record_field)?;
|
||||
|
||||
let current_module = ctx.sema.scope(record_field.syntax()).module()?;
|
||||
|
|
|
@ -26,7 +26,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
|
|||
// ```
|
||||
pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let cap = ctx.config.snippet_cap?;
|
||||
let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
|
||||
let nominal = ctx.find_node_at_offset::<ast::AdtDef>()?;
|
||||
let node_start = derive_insertion_offset(&nominal)?;
|
||||
let target = nominal.syntax().text_range();
|
||||
acc.add(
|
||||
|
@ -58,7 +58,7 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext) -> Option<
|
|||
}
|
||||
|
||||
// Insert `derive` after doc comments.
|
||||
fn derive_insertion_offset(nominal: &ast::NominalDef) -> Option<TextSize> {
|
||||
fn derive_insertion_offset(nominal: &ast::AdtDef) -> Option<TextSize> {
|
||||
let non_ws_child = nominal
|
||||
.syntax()
|
||||
.children_with_tokens()
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::{utils::FamousDefs, AssistContext, AssistId, AssistKind, Assists};
|
|||
// }
|
||||
// ```
|
||||
pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?;
|
||||
let variant = ctx.find_node_at_offset::<ast::Variant>()?;
|
||||
let variant_name = variant.name()?;
|
||||
let enum_name = variant.parent_enum().name()?;
|
||||
let field_list = match variant.kind() {
|
||||
|
@ -32,9 +32,9 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext
|
|||
if field_list.fields().count() != 1 {
|
||||
return None;
|
||||
}
|
||||
let field_type = field_list.fields().next()?.type_ref()?;
|
||||
let field_type = field_list.fields().next()?.ty()?;
|
||||
let path = match field_type {
|
||||
ast::TypeRef::PathType(it) => it,
|
||||
ast::Type::PathType(it) => it,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
@ -69,7 +69,7 @@ impl From<{0}> for {1} {{
|
|||
|
||||
fn existing_from_impl(
|
||||
sema: &'_ hir::Semantics<'_, RootDatabase>,
|
||||
variant: &ast::EnumVariant,
|
||||
variant: &ast::Variant,
|
||||
) -> Option<()> {
|
||||
let variant = sema.to_def(variant)?;
|
||||
let enum_ = variant.parent_enum(sema.db);
|
||||
|
|
|
@ -82,7 +82,7 @@ struct FunctionTemplate {
|
|||
insert_offset: TextSize,
|
||||
placeholder_expr: ast::MacroCall,
|
||||
leading_ws: String,
|
||||
fn_def: ast::FnDef,
|
||||
fn_def: ast::Fn,
|
||||
trailing_ws: String,
|
||||
file: FileId,
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ impl FunctionTemplate {
|
|||
struct FunctionBuilder {
|
||||
target: GeneratedFunctionTarget,
|
||||
fn_name: ast::Name,
|
||||
type_params: Option<ast::TypeParamList>,
|
||||
type_params: Option<ast::GenericParamList>,
|
||||
params: ast::ParamList,
|
||||
file: FileId,
|
||||
needs_pub: bool,
|
||||
|
@ -142,7 +142,7 @@ impl FunctionBuilder {
|
|||
let fn_body = make::block_expr(vec![], Some(placeholder_expr));
|
||||
let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
|
||||
let mut fn_def =
|
||||
make::fn_def(visibility, self.fn_name, self.type_params, self.params, fn_body);
|
||||
make::fn_(visibility, self.fn_name, self.type_params, self.params, fn_body);
|
||||
let leading_ws;
|
||||
let trailing_ws;
|
||||
|
||||
|
@ -200,7 +200,7 @@ fn fn_args(
|
|||
ctx: &AssistContext,
|
||||
target_module: hir::Module,
|
||||
call: &ast::CallExpr,
|
||||
) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> {
|
||||
) -> Option<(Option<ast::GenericParamList>, ast::ParamList)> {
|
||||
let mut arg_names = Vec::new();
|
||||
let mut arg_types = Vec::new();
|
||||
for arg in call.arg_list()?.args() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner};
|
||||
use ra_syntax::ast::{self, AstNode, GenericParamsOwner, NameOwner};
|
||||
use stdx::{format_to, SepBy};
|
||||
|
||||
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
||||
|
@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
|
|||
// }
|
||||
// ```
|
||||
pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let nominal = ctx.find_node_at_offset::<ast::NominalDef>()?;
|
||||
let nominal = ctx.find_node_at_offset::<ast::AdtDef>()?;
|
||||
let name = nominal.name()?;
|
||||
let target = nominal.syntax().text_range();
|
||||
acc.add(
|
||||
|
@ -31,7 +31,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()
|
|||
format!("Generate impl for `{}`", name),
|
||||
target,
|
||||
|edit| {
|
||||
let type_params = nominal.type_param_list();
|
||||
let type_params = nominal.generic_param_list();
|
||||
let start_offset = nominal.syntax().text_range().end();
|
||||
let mut buf = String::new();
|
||||
buf.push_str("\n\nimpl");
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use hir::Adt;
|
||||
use ra_syntax::{
|
||||
ast::{
|
||||
self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner,
|
||||
},
|
||||
ast::{self, AstNode, GenericParamsOwner, NameOwner, StructKind, VisibilityOwner},
|
||||
T,
|
||||
};
|
||||
use stdx::{format_to, SepBy};
|
||||
|
@ -30,7 +28,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
|
|||
//
|
||||
// ```
|
||||
pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let strukt = ctx.find_node_at_offset::<ast::StructDef>()?;
|
||||
let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
|
||||
|
||||
// We want to only apply this to non-union structs with named fields
|
||||
let field_list = match strukt.kind() {
|
||||
|
@ -53,9 +51,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
|
|||
|
||||
let params = field_list
|
||||
.fields()
|
||||
.filter_map(|f| {
|
||||
Some(format!("{}: {}", f.name()?.syntax(), f.ascribed_type()?.syntax()))
|
||||
})
|
||||
.filter_map(|f| Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax())))
|
||||
.sep_by(", ");
|
||||
let fields = field_list.fields().filter_map(|f| f.name()).sep_by(", ");
|
||||
|
||||
|
@ -90,8 +86,8 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
|
|||
|
||||
// Generates the surrounding `impl Type { <code> }` including type and lifetime
|
||||
// parameters
|
||||
fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
|
||||
let type_params = strukt.type_param_list();
|
||||
fn generate_impl_text(strukt: &ast::Struct, code: &str) -> String {
|
||||
let type_params = strukt.generic_param_list();
|
||||
let mut buf = String::with_capacity(code.len());
|
||||
buf.push_str("\n\nimpl");
|
||||
if let Some(type_params) = &type_params {
|
||||
|
@ -121,7 +117,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
|
|||
//
|
||||
// FIXME: change the new fn checking to a more semantic approach when that's more
|
||||
// viable (e.g. we process proc macros, etc)
|
||||
fn find_struct_impl(ctx: &AssistContext, strukt: &ast::StructDef) -> Option<Option<ast::ImplDef>> {
|
||||
fn find_struct_impl(ctx: &AssistContext, strukt: &ast::Struct) -> Option<Option<ast::Impl>> {
|
||||
let db = ctx.db();
|
||||
let module = strukt.syntax().ancestors().find(|node| {
|
||||
ast::Module::can_cast(node.kind()) || ast::SourceFile::can_cast(node.kind())
|
||||
|
@ -129,7 +125,7 @@ fn find_struct_impl(ctx: &AssistContext, strukt: &ast::StructDef) -> Option<Opti
|
|||
|
||||
let struct_def = ctx.sema.to_def(strukt)?;
|
||||
|
||||
let block = module.descendants().filter_map(ast::ImplDef::cast).find_map(|impl_blk| {
|
||||
let block = module.descendants().filter_map(ast::Impl::cast).find_map(|impl_blk| {
|
||||
let blk = ctx.sema.to_def(&impl_blk)?;
|
||||
|
||||
// FIXME: handle e.g. `struct S<T>; impl<U> S<U> {}`
|
||||
|
@ -157,10 +153,10 @@ fn find_struct_impl(ctx: &AssistContext, strukt: &ast::StructDef) -> Option<Opti
|
|||
Some(block)
|
||||
}
|
||||
|
||||
fn has_new_fn(imp: &ast::ImplDef) -> bool {
|
||||
if let Some(il) = imp.item_list() {
|
||||
fn has_new_fn(imp: &ast::Impl) -> bool {
|
||||
if let Some(il) = imp.assoc_item_list() {
|
||||
for item in il.assoc_items() {
|
||||
if let ast::AssocItem::FnDef(f) = item {
|
||||
if let ast::AssocItem::Fn(f) = item {
|
||||
if let Some(name) = f.name() {
|
||||
if name.text().eq_ignore_ascii_case("new") {
|
||||
return true;
|
||||
|
|
|
@ -29,7 +29,7 @@ use crate::{
|
|||
pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let let_stmt = ctx.find_node_at_offset::<ast::LetStmt>()?;
|
||||
let bind_pat = match let_stmt.pat()? {
|
||||
ast::Pat::BindPat(pat) => pat,
|
||||
ast::Pat::IdentPat(pat) => pat,
|
||||
_ => return None,
|
||||
};
|
||||
if bind_pat.mut_token().is_some() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ra_syntax::{
|
||||
ast::{self, NameOwner, TypeAscriptionOwner, TypeParamsOwner},
|
||||
ast::{self, GenericParamsOwner, NameOwner},
|
||||
AstNode, SyntaxKind, TextRange, TextSize,
|
||||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
|
@ -38,9 +38,9 @@ pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -
|
|||
let lifetime_token = ctx
|
||||
.find_token_at_offset(SyntaxKind::LIFETIME)
|
||||
.filter(|lifetime| lifetime.text() == "'_")?;
|
||||
if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::FnDef::cast) {
|
||||
if let Some(fn_def) = lifetime_token.ancestors().find_map(ast::Fn::cast) {
|
||||
generate_fn_def_assist(acc, &fn_def, lifetime_token.text_range())
|
||||
} else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::ImplDef::cast) {
|
||||
} else if let Some(impl_def) = lifetime_token.ancestors().find_map(ast::Impl::cast) {
|
||||
generate_impl_def_assist(acc, &impl_def, lifetime_token.text_range())
|
||||
} else {
|
||||
None
|
||||
|
@ -50,11 +50,11 @@ pub(crate) fn introduce_named_lifetime(acc: &mut Assists, ctx: &AssistContext) -
|
|||
/// Generate the assist for the fn def case
|
||||
fn generate_fn_def_assist(
|
||||
acc: &mut Assists,
|
||||
fn_def: &ast::FnDef,
|
||||
fn_def: &ast::Fn,
|
||||
lifetime_loc: TextRange,
|
||||
) -> Option<()> {
|
||||
let param_list: ast::ParamList = fn_def.param_list()?;
|
||||
let new_lifetime_param = generate_unique_lifetime_param_name(&fn_def.type_param_list())?;
|
||||
let new_lifetime_param = generate_unique_lifetime_param_name(&fn_def.generic_param_list())?;
|
||||
let end_of_fn_ident = fn_def.name()?.ident_token()?.text_range().end();
|
||||
let self_param =
|
||||
// use the self if it's a reference and has no explicit lifetime
|
||||
|
@ -67,8 +67,8 @@ fn generate_fn_def_assist(
|
|||
// otherwise, if there's a single reference parameter without a named liftime, use that
|
||||
let fn_params_without_lifetime: Vec<_> = param_list
|
||||
.params()
|
||||
.filter_map(|param| match param.ascribed_type() {
|
||||
Some(ast::TypeRef::ReferenceType(ascribed_type))
|
||||
.filter_map(|param| match param.ty() {
|
||||
Some(ast::Type::RefType(ascribed_type))
|
||||
if ascribed_type.lifetime_token() == None =>
|
||||
{
|
||||
Some(ascribed_type.amp_token()?.text_range().end())
|
||||
|
@ -93,10 +93,10 @@ fn generate_fn_def_assist(
|
|||
/// Generate the assist for the impl def case
|
||||
fn generate_impl_def_assist(
|
||||
acc: &mut Assists,
|
||||
impl_def: &ast::ImplDef,
|
||||
impl_def: &ast::Impl,
|
||||
lifetime_loc: TextRange,
|
||||
) -> Option<()> {
|
||||
let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.type_param_list())?;
|
||||
let new_lifetime_param = generate_unique_lifetime_param_name(&impl_def.generic_param_list())?;
|
||||
let end_of_impl_kw = impl_def.impl_token()?.text_range().end();
|
||||
acc.add(AssistId(ASSIST_NAME, AssistKind::Refactor), ASSIST_LABEL, lifetime_loc, |builder| {
|
||||
add_lifetime_param(impl_def, builder, end_of_impl_kw, new_lifetime_param);
|
||||
|
@ -107,7 +107,7 @@ fn generate_impl_def_assist(
|
|||
/// Given a type parameter list, generate a unique lifetime parameter name
|
||||
/// which is not in the list
|
||||
fn generate_unique_lifetime_param_name(
|
||||
existing_type_param_list: &Option<ast::TypeParamList>,
|
||||
existing_type_param_list: &Option<ast::GenericParamList>,
|
||||
) -> Option<char> {
|
||||
match existing_type_param_list {
|
||||
Some(type_params) => {
|
||||
|
@ -123,13 +123,13 @@ fn generate_unique_lifetime_param_name(
|
|||
|
||||
/// Add the lifetime param to `builder`. If there are type parameters in `type_params_owner`, add it to the end. Otherwise
|
||||
/// add new type params brackets with the lifetime parameter at `new_type_params_loc`.
|
||||
fn add_lifetime_param<TypeParamsOwner: ast::TypeParamsOwner>(
|
||||
fn add_lifetime_param<TypeParamsOwner: ast::GenericParamsOwner>(
|
||||
type_params_owner: &TypeParamsOwner,
|
||||
builder: &mut AssistBuilder,
|
||||
new_type_params_loc: TextSize,
|
||||
new_lifetime_param: char,
|
||||
) {
|
||||
match type_params_owner.type_param_list() {
|
||||
match type_params_owner.generic_param_list() {
|
||||
// add the new lifetime parameter to an existing type param list
|
||||
Some(type_params) => {
|
||||
builder.insert(
|
||||
|
|
|
@ -28,7 +28,7 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()
|
|||
let mut rewriter = SyntaxRewriter::default();
|
||||
let mut offset = ctx.offset();
|
||||
|
||||
if let Some(use_item) = tree.syntax().parent().and_then(ast::UseItem::cast) {
|
||||
if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) {
|
||||
let (merged, to_delete) = next_prev()
|
||||
.filter_map(|dir| neighbor(&use_item, dir))
|
||||
.filter_map(|it| Some((it.clone(), it.use_tree()?)))
|
||||
|
|
|
@ -86,7 +86,7 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option
|
|||
}
|
||||
|
||||
fn contains_placeholder(a: &ast::MatchArm) -> bool {
|
||||
matches!(a.pat(), Some(ast::Pat::PlaceholderPat(..)))
|
||||
matches!(a.pat(), Some(ast::Pat::WildcardPat(..)))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
|
|||
// }
|
||||
// ```
|
||||
pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
let type_param_list = ctx.find_node_at_offset::<ast::TypeParamList>()?;
|
||||
let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?;
|
||||
|
||||
let mut type_params = type_param_list.type_params();
|
||||
if type_params.all(|p| p.type_bound_list().is_none()) {
|
||||
|
@ -37,13 +37,13 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext
|
|||
|
||||
let anchor = match_ast! {
|
||||
match parent {
|
||||
ast::FnDef(it) => it.body()?.syntax().clone().into(),
|
||||
ast::TraitDef(it) => it.item_list()?.syntax().clone().into(),
|
||||
ast::ImplDef(it) => it.item_list()?.syntax().clone().into(),
|
||||
ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(),
|
||||
ast::StructDef(it) => {
|
||||
ast::Fn(it) => it.body()?.syntax().clone().into(),
|
||||
ast::Trait(it) => it.assoc_item_list()?.syntax().clone().into(),
|
||||
ast::Impl(it) => it.assoc_item_list()?.syntax().clone().into(),
|
||||
ast::Enum(it) => it.variant_list()?.syntax().clone().into(),
|
||||
ast::Struct(it) => {
|
||||
it.syntax().children_with_tokens()
|
||||
.find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == T![;])?
|
||||
.find(|it| it.kind() == RECORD_FIELD_LIST || it.kind() == T![;])?
|
||||
},
|
||||
_ => return None
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ fn test_required_hashes() {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
mod tests {
|
||||
use test_utils::mark;
|
||||
|
||||
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use ra_syntax::{
|
||||
ast::{self, AstNode},
|
||||
TextSize, T,
|
||||
TextRange, TextSize, T,
|
||||
};
|
||||
|
||||
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
||||
|
@ -27,19 +27,33 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let macro_range = macro_call.syntax().text_range();
|
||||
let is_leaf = macro_call.syntax().next_sibling().is_none();
|
||||
|
||||
let macro_content = {
|
||||
let macro_args = macro_call.token_tree()?.syntax().clone();
|
||||
let macro_end = if macro_call.semicolon_token().is_some() {
|
||||
macro_call.syntax().text_range().end() - TextSize::of(';')
|
||||
} else {
|
||||
macro_call.syntax().text_range().end()
|
||||
};
|
||||
|
||||
let text = macro_args.text();
|
||||
let without_parens = TextSize::of('(')..text.len() - TextSize::of(')');
|
||||
text.slice(without_parens).to_string()
|
||||
// macro_range determines what will be deleted and replaced with macro_content
|
||||
let macro_range = TextRange::new(macro_call.syntax().text_range().start(), macro_end);
|
||||
let paste_instead_of_dbg = {
|
||||
let text = macro_call.token_tree()?.syntax().text();
|
||||
|
||||
// leafiness determines if we should include the parenthesis or not
|
||||
let slice_index: TextRange = if is_leaf {
|
||||
// leaf means - we can extract the contents of the dbg! in text
|
||||
TextRange::new(TextSize::of('('), text.len() - TextSize::of(')'))
|
||||
} else {
|
||||
// not leaf - means we should keep the parens
|
||||
TextRange::up_to(text.len())
|
||||
};
|
||||
text.slice(slice_index).to_string()
|
||||
};
|
||||
|
||||
let target = macro_call.syntax().text_range();
|
||||
acc.add(AssistId("remove_dbg", AssistKind::Refactor), "Remove dbg!()", target, |builder| {
|
||||
builder.replace(macro_range, macro_content);
|
||||
builder.replace(macro_range, paste_instead_of_dbg);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -99,6 +113,7 @@ fn foo(n: usize) {
|
|||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_dbg_with_brackets_and_braces() {
|
||||
check_assist(remove_dbg, "dbg![<|>1 + 1]", "1 + 1");
|
||||
|
@ -113,7 +128,7 @@ fn foo(n: usize) {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn remove_dbg_target() {
|
||||
fn test_remove_dbg_target() {
|
||||
check_assist_target(
|
||||
remove_dbg,
|
||||
"
|
||||
|
@ -126,4 +141,65 @@ fn foo(n: usize) {
|
|||
"dbg!(n.checked_sub(4))",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_dbg_keep_semicolon() {
|
||||
// https://github.com/rust-analyzer/rust-analyzer/issues/5129#issuecomment-651399779
|
||||
// not quite though
|
||||
// adding a comment at the end of the line makes
|
||||
// the ast::MacroCall to include the semicolon at the end
|
||||
check_assist(
|
||||
remove_dbg,
|
||||
r#"let res = <|>dbg!(1 * 20); // needless comment"#,
|
||||
r#"let res = 1 * 20; // needless comment"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_dbg_keep_expression() {
|
||||
check_assist(
|
||||
remove_dbg,
|
||||
r#"let res = <|>dbg!(a + b).foo();"#,
|
||||
r#"let res = (a + b).foo();"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_dbg_from_inside_fn() {
|
||||
check_assist_target(
|
||||
remove_dbg,
|
||||
r#"
|
||||
fn square(x: u32) -> u32 {
|
||||
x * x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = square(dbg<|>!(5 + 10));
|
||||
println!("{}", x);
|
||||
}"#,
|
||||
"dbg!(5 + 10)",
|
||||
);
|
||||
|
||||
check_assist(
|
||||
remove_dbg,
|
||||
r#"
|
||||
fn square(x: u32) -> u32 {
|
||||
x * x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = square(dbg<|>!(5 + 10));
|
||||
println!("{}", x);
|
||||
}"#,
|
||||
r#"
|
||||
fn square(x: u32) -> u32 {
|
||||
x * x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = square(5 + 10);
|
||||
println!("{}", x);
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
|
|||
// ```
|
||||
//
|
||||
pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
reorder::<ast::RecordLit>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx))
|
||||
reorder::<ast::RecordExpr>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx))
|
||||
}
|
||||
|
||||
fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
||||
|
@ -56,8 +56,8 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
|||
|
||||
fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
|
||||
match node.kind() {
|
||||
RECORD_LIT => vec![RECORD_FIELD],
|
||||
RECORD_PAT => vec![RECORD_FIELD_PAT, BIND_PAT],
|
||||
RECORD_EXPR => vec![RECORD_EXPR_FIELD],
|
||||
RECORD_PAT => vec![RECORD_PAT_FIELD, IDENT_PAT],
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
|
@ -65,8 +65,8 @@ fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
|
|||
fn get_field_name(node: &SyntaxNode) -> String {
|
||||
let res = match_ast! {
|
||||
match node {
|
||||
ast::RecordField(field) => field.field_name().map(|it| it.to_string()),
|
||||
ast::RecordFieldPat(field) => field.field_name().map(|it| it.to_string()),
|
||||
ast::RecordExprField(field) => field.field_name().map(|it| it.to_string()),
|
||||
ast::RecordPatField(field) => field.field_name().map(|it| it.to_string()),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -65,7 +65,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
|
|||
.type_of_pat(&pat)
|
||||
.and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty))
|
||||
.map(|it| it.sad_pattern())
|
||||
.unwrap_or_else(|| make::placeholder_pat().into());
|
||||
.unwrap_or_else(|| make::wildcard_pat().into());
|
||||
let else_expr = unwrap_trivial_block(else_block);
|
||||
make::match_arm(vec![pattern], else_expr)
|
||||
};
|
||||
|
|
|
@ -50,10 +50,10 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
|
|||
target,
|
||||
|edit| {
|
||||
let with_placeholder: ast::Pat = match happy_variant {
|
||||
None => make::placeholder_pat().into(),
|
||||
None => make::wildcard_pat().into(),
|
||||
Some(var_name) => make::tuple_struct_pat(
|
||||
make::path_unqualified(make::path_segment(make::name_ref(var_name))),
|
||||
once(make::placeholder_pat().into()),
|
||||
once(make::wildcard_pat().into()),
|
||||
)
|
||||
.into(),
|
||||
};
|
||||
|
@ -62,8 +62,7 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
|
|||
let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block);
|
||||
let stmt = make::expr_stmt(if_);
|
||||
|
||||
let placeholder =
|
||||
stmt.syntax().descendants().find_map(ast::PlaceholderPat::cast).unwrap();
|
||||
let placeholder = stmt.syntax().descendants().find_map(ast::WildcardPat::cast).unwrap();
|
||||
let stmt = stmt.replace_descendant(placeholder.into(), original_pat);
|
||||
|
||||
edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt));
|
||||
|
|
|
@ -25,7 +25,7 @@ pub(crate) fn replace_qualified_name_with_use(
|
|||
) -> Option<()> {
|
||||
let path: ast::Path = ctx.find_node_at_offset()?;
|
||||
// We don't want to mess with use statements
|
||||
if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
|
||||
if path.syntax().ancestors().find_map(ast::Use::cast).is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path:
|
|||
match child {
|
||||
// Don't modify `use` items, as this can break the `use` item when injecting a new
|
||||
// import into the use tree.
|
||||
ast::UseItem(_it) => continue,
|
||||
ast::Use(_it) => continue,
|
||||
// Don't descend into submodules, they don't have the same `use` items in scope.
|
||||
ast::Module(_it) => continue,
|
||||
|
||||
|
@ -639,6 +639,48 @@ use std::fmt::{self, Display};
|
|||
|
||||
fn main() {
|
||||
fmt;
|
||||
}
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_replace_pub_use() {
|
||||
check_assist(
|
||||
replace_qualified_name_with_use,
|
||||
r"
|
||||
pub use std::fmt;
|
||||
|
||||
impl std::io<|> for Foo {
|
||||
}
|
||||
",
|
||||
r"
|
||||
use std::io;
|
||||
|
||||
pub use std::fmt;
|
||||
|
||||
impl io for Foo {
|
||||
}
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_replace_pub_crate_use() {
|
||||
check_assist(
|
||||
replace_qualified_name_with_use,
|
||||
r"
|
||||
pub(crate) use std::fmt;
|
||||
|
||||
impl std::io<|> for Foo {
|
||||
}
|
||||
",
|
||||
r"
|
||||
use std::io;
|
||||
|
||||
pub(crate) use std::fmt;
|
||||
|
||||
impl io for Foo {
|
||||
}
|
||||
",
|
||||
);
|
||||
|
|
|
@ -52,7 +52,7 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext)
|
|||
target,
|
||||
|builder| {
|
||||
let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant)));
|
||||
let it = make::bind_pat(make::name("a")).into();
|
||||
let it = make::ident_pat(make::name("a")).into();
|
||||
let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
|
||||
|
||||
let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a")));
|
||||
|
@ -60,7 +60,7 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext)
|
|||
|
||||
let unreachable_call = make::expr_unreachable();
|
||||
let err_arm =
|
||||
make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call);
|
||||
make::match_arm(iter::once(make::wildcard_pat().into()), unreachable_call);
|
||||
|
||||
let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]);
|
||||
let match_expr = make::expr_match(caller.clone(), match_arm_list)
|
||||
|
|
|
@ -140,6 +140,7 @@ mod handlers {
|
|||
mod change_return_type_to_result;
|
||||
mod change_visibility;
|
||||
mod early_return;
|
||||
mod expand_glob_import;
|
||||
mod extract_struct_from_enum_variant;
|
||||
mod extract_variable;
|
||||
mod fill_match_arms;
|
||||
|
@ -181,6 +182,7 @@ mod handlers {
|
|||
change_return_type_to_result::change_return_type_to_result,
|
||||
change_visibility::change_visibility,
|
||||
early_return::convert_to_guarded_return,
|
||||
expand_glob_import::expand_glob_import,
|
||||
extract_struct_from_enum_variant::extract_struct_from_enum_variant,
|
||||
extract_variable::extract_variable,
|
||||
fill_match_arms::fill_match_arms,
|
||||
|
|
|
@ -228,6 +228,33 @@ fn main() {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doctest_expand_glob_import() {
|
||||
check_doc_test(
|
||||
"expand_glob_import",
|
||||
r#####"
|
||||
mod foo {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
}
|
||||
|
||||
use foo::*<|>;
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {}
|
||||
"#####,
|
||||
r#####"
|
||||
mod foo {
|
||||
pub struct Bar;
|
||||
pub struct Baz;
|
||||
}
|
||||
|
||||
use foo::{Baz, Bar};
|
||||
|
||||
fn qux(bar: Bar, baz: Baz) {}
|
||||
"#####,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doctest_extract_struct_from_enum_variant() {
|
||||
check_doc_test(
|
||||
|
|
|
@ -56,33 +56,34 @@ pub(crate) fn render_snippet(_cap: SnippetCap, node: &SyntaxNode, cursor: Cursor
|
|||
|
||||
pub fn get_missing_assoc_items(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
impl_def: &ast::ImplDef,
|
||||
impl_def: &ast::Impl,
|
||||
) -> Vec<hir::AssocItem> {
|
||||
// Names must be unique between constants and functions. However, type aliases
|
||||
// may share the same name as a function or constant.
|
||||
let mut impl_fns_consts = FxHashSet::default();
|
||||
let mut impl_type = FxHashSet::default();
|
||||
|
||||
if let Some(item_list) = impl_def.item_list() {
|
||||
if let Some(item_list) = impl_def.assoc_item_list() {
|
||||
for item in item_list.assoc_items() {
|
||||
match item {
|
||||
ast::AssocItem::FnDef(f) => {
|
||||
ast::AssocItem::Fn(f) => {
|
||||
if let Some(n) = f.name() {
|
||||
impl_fns_consts.insert(n.syntax().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
ast::AssocItem::TypeAliasDef(t) => {
|
||||
ast::AssocItem::TypeAlias(t) => {
|
||||
if let Some(n) = t.name() {
|
||||
impl_type.insert(n.syntax().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
ast::AssocItem::ConstDef(c) => {
|
||||
ast::AssocItem::Const(c) => {
|
||||
if let Some(n) = c.name() {
|
||||
impl_fns_consts.insert(n.syntax().to_string());
|
||||
}
|
||||
}
|
||||
ast::AssocItem::MacroCall(_) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,13 +109,10 @@ pub fn get_missing_assoc_items(
|
|||
|
||||
pub(crate) fn resolve_target_trait(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
impl_def: &ast::ImplDef,
|
||||
impl_def: &ast::Impl,
|
||||
) -> Option<hir::Trait> {
|
||||
let ast_path = impl_def
|
||||
.target_trait()
|
||||
.map(|it| it.syntax().clone())
|
||||
.and_then(ast::PathType::cast)?
|
||||
.path()?;
|
||||
let ast_path =
|
||||
impl_def.trait_().map(|it| it.syntax().clone()).and_then(ast::PathType::cast)?.path()?;
|
||||
|
||||
match sema.resolve_path(&ast_path) {
|
||||
Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def),
|
||||
|
@ -183,10 +181,10 @@ impl TryEnum {
|
|||
match self {
|
||||
TryEnum::Result => make::tuple_struct_pat(
|
||||
make::path_unqualified(make::path_segment(make::name_ref("Err"))),
|
||||
iter::once(make::placeholder_pat().into()),
|
||||
iter::once(make::wildcard_pat().into()),
|
||||
)
|
||||
.into(),
|
||||
TryEnum::Option => make::bind_pat(make::name("None")).into(),
|
||||
TryEnum::Option => make::ident_pat(make::name("None")).into(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use hir::{self, ModPath};
|
||||
use ra_syntax::{
|
||||
ast::{self, NameOwner},
|
||||
ast::{self, NameOwner, VisibilityOwner},
|
||||
AstNode, Direction, SmolStr,
|
||||
SyntaxKind::{PATH, PATH_SEGMENT},
|
||||
SyntaxNode, T,
|
||||
|
@ -215,7 +215,7 @@ fn walk_use_tree_for_best_action(
|
|||
let prev_len = current_path_segments.len();
|
||||
|
||||
let tree_list = current_use_tree.use_tree_list();
|
||||
let alias = current_use_tree.alias();
|
||||
let alias = current_use_tree.rename();
|
||||
|
||||
let path = match current_use_tree.path() {
|
||||
Some(path) => path,
|
||||
|
@ -225,7 +225,7 @@ fn walk_use_tree_for_best_action(
|
|||
current_use_tree
|
||||
.syntax()
|
||||
.ancestors()
|
||||
.find_map(ast::UseItem::cast)
|
||||
.find_map(ast::Use::cast)
|
||||
.map(|it| it.syntax().clone()),
|
||||
true,
|
||||
);
|
||||
|
@ -254,7 +254,7 @@ fn walk_use_tree_for_best_action(
|
|||
current_use_tree
|
||||
.syntax()
|
||||
.ancestors()
|
||||
.find_map(ast::UseItem::cast)
|
||||
.find_map(ast::Use::cast)
|
||||
.map(|it| it.syntax().clone()),
|
||||
true,
|
||||
),
|
||||
|
@ -304,7 +304,7 @@ fn walk_use_tree_for_best_action(
|
|||
current_use_tree
|
||||
.syntax()
|
||||
.ancestors()
|
||||
.find_map(ast::UseItem::cast)
|
||||
.find_map(ast::Use::cast)
|
||||
.map(|it| it.syntax().clone()),
|
||||
true,
|
||||
);
|
||||
|
@ -377,7 +377,8 @@ fn best_action_for_target(
|
|||
let mut storage = Vec::with_capacity(16); // this should be the only allocation
|
||||
let best_action = container
|
||||
.children()
|
||||
.filter_map(ast::UseItem::cast)
|
||||
.filter_map(ast::Use::cast)
|
||||
.filter(|u| u.visibility().is_none())
|
||||
.filter_map(|it| it.use_tree())
|
||||
.map(|u| walk_use_tree_for_best_action(&mut storage, None, u, target))
|
||||
.fold(None, |best, a| match best {
|
||||
|
|
|
@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
salsa = "0.15.0"
|
||||
salsa = "0.15.2"
|
||||
rustc-hash = "1.1.0"
|
||||
|
||||
ra_syntax = { path = "../ra_syntax" }
|
||||
|
|
|
@ -361,8 +361,8 @@ pub struct Field {
|
|||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum FieldSource {
|
||||
Named(ast::RecordFieldDef),
|
||||
Pos(ast::TupleFieldDef),
|
||||
Named(ast::RecordField),
|
||||
Pos(ast::TupleField),
|
||||
}
|
||||
|
||||
impl Field {
|
||||
|
@ -1002,7 +1002,7 @@ impl Local {
|
|||
Type::new(db, krate, def, ty)
|
||||
}
|
||||
|
||||
pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::BindPat, ast::SelfParam>> {
|
||||
pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::IdentPat, ast::SelfParam>> {
|
||||
let (_body, source_map) = db.body_with_source_map(self.parent.into());
|
||||
let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm...
|
||||
let root = src.file_syntax(db.upcast());
|
||||
|
|
|
@ -13,14 +13,7 @@ pub use hir_expand::db::{
|
|||
AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery,
|
||||
MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery,
|
||||
};
|
||||
pub use hir_ty::db::{
|
||||
AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery,
|
||||
GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase,
|
||||
HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery,
|
||||
InherentImplsInCrateQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery,
|
||||
TraitDatumQuery, TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery,
|
||||
ValueTyQuery,
|
||||
};
|
||||
pub use hir_ty::db::*;
|
||||
|
||||
#[test]
|
||||
fn hir_database_is_object_safe() {
|
||||
|
|
|
@ -57,56 +57,56 @@ impl HasSource for Field {
|
|||
}
|
||||
}
|
||||
impl HasSource for Struct {
|
||||
type Ast = ast::StructDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::StructDef> {
|
||||
type Ast = ast::Struct;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Struct> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
impl HasSource for Union {
|
||||
type Ast = ast::UnionDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::UnionDef> {
|
||||
type Ast = ast::Union;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Union> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
impl HasSource for Enum {
|
||||
type Ast = ast::EnumDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::EnumDef> {
|
||||
type Ast = ast::Enum;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Enum> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
impl HasSource for EnumVariant {
|
||||
type Ast = ast::EnumVariant;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::EnumVariant> {
|
||||
type Ast = ast::Variant;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Variant> {
|
||||
self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone())
|
||||
}
|
||||
}
|
||||
impl HasSource for Function {
|
||||
type Ast = ast::FnDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::FnDef> {
|
||||
type Ast = ast::Fn;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Fn> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
impl HasSource for Const {
|
||||
type Ast = ast::ConstDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::ConstDef> {
|
||||
type Ast = ast::Const;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Const> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
impl HasSource for Static {
|
||||
type Ast = ast::StaticDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::StaticDef> {
|
||||
type Ast = ast::Static;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Static> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
impl HasSource for Trait {
|
||||
type Ast = ast::TraitDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::TraitDef> {
|
||||
type Ast = ast::Trait;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Trait> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
impl HasSource for TypeAlias {
|
||||
type Ast = ast::TypeAliasDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::TypeAliasDef> {
|
||||
type Ast = ast::TypeAlias;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::TypeAlias> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
|
@ -120,14 +120,14 @@ impl HasSource for MacroDef {
|
|||
}
|
||||
}
|
||||
impl HasSource for ImplDef {
|
||||
type Ast = ast::ImplDef;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::ImplDef> {
|
||||
type Ast = ast::Impl;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Impl> {
|
||||
self.id.lookup(db.upcast()).source(db.upcast())
|
||||
}
|
||||
}
|
||||
|
||||
impl HasSource for TypeParam {
|
||||
type Ast = Either<ast::TraitDef, ast::TypeParam>;
|
||||
type Ast = Either<ast::Trait, ast::TypeParam>;
|
||||
fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
|
||||
let child_source = self.id.parent.child_source(db.upcast());
|
||||
child_source.map(|it| it[self.id.local_id].clone())
|
||||
|
|
|
@ -209,11 +209,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
self.imp.resolve_field(field)
|
||||
}
|
||||
|
||||
pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> {
|
||||
pub fn resolve_record_field(
|
||||
&self,
|
||||
field: &ast::RecordExprField,
|
||||
) -> Option<(Field, Option<Local>)> {
|
||||
self.imp.resolve_record_field(field)
|
||||
}
|
||||
|
||||
pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> {
|
||||
pub fn resolve_record_field_pat(&self, field: &ast::RecordPatField) -> Option<Field> {
|
||||
self.imp.resolve_record_field_pat(field)
|
||||
}
|
||||
|
||||
|
@ -225,7 +228,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
self.imp.resolve_path(path)
|
||||
}
|
||||
|
||||
pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantDef> {
|
||||
pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> {
|
||||
self.imp.resolve_variant(record_lit).map(VariantDef::from)
|
||||
}
|
||||
|
||||
|
@ -233,14 +236,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
self.imp.lower_path(path)
|
||||
}
|
||||
|
||||
pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> {
|
||||
pub fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option<ModuleDef> {
|
||||
self.imp.resolve_bind_pat_to_const(pat)
|
||||
}
|
||||
|
||||
// FIXME: use this instead?
|
||||
// pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
|
||||
|
||||
pub fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> {
|
||||
pub fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> {
|
||||
self.imp.record_literal_missing_fields(literal)
|
||||
}
|
||||
|
||||
|
@ -422,11 +425,11 @@ impl<'db> SemanticsImpl<'db> {
|
|||
self.analyze(field.syntax()).resolve_field(self.db, field)
|
||||
}
|
||||
|
||||
fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> {
|
||||
fn resolve_record_field(&self, field: &ast::RecordExprField) -> Option<(Field, Option<Local>)> {
|
||||
self.analyze(field.syntax()).resolve_record_field(self.db, field)
|
||||
}
|
||||
|
||||
fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> {
|
||||
fn resolve_record_field_pat(&self, field: &ast::RecordPatField) -> Option<Field> {
|
||||
self.analyze(field.syntax()).resolve_record_field_pat(self.db, field)
|
||||
}
|
||||
|
||||
|
@ -440,7 +443,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
self.analyze(path.syntax()).resolve_path(self.db, path)
|
||||
}
|
||||
|
||||
fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> {
|
||||
fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
|
||||
self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit)
|
||||
}
|
||||
|
||||
|
@ -449,11 +452,11 @@ impl<'db> SemanticsImpl<'db> {
|
|||
Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into()))
|
||||
}
|
||||
|
||||
fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> {
|
||||
fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option<ModuleDef> {
|
||||
self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat)
|
||||
}
|
||||
|
||||
fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> {
|
||||
fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> {
|
||||
self.analyze(literal.syntax())
|
||||
.record_literal_missing_fields(self.db, literal)
|
||||
.unwrap_or_default()
|
||||
|
@ -577,21 +580,21 @@ macro_rules! to_def_impls {
|
|||
|
||||
to_def_impls![
|
||||
(crate::Module, ast::Module, module_to_def),
|
||||
(crate::Struct, ast::StructDef, struct_to_def),
|
||||
(crate::Enum, ast::EnumDef, enum_to_def),
|
||||
(crate::Union, ast::UnionDef, union_to_def),
|
||||
(crate::Trait, ast::TraitDef, trait_to_def),
|
||||
(crate::ImplDef, ast::ImplDef, impl_to_def),
|
||||
(crate::TypeAlias, ast::TypeAliasDef, type_alias_to_def),
|
||||
(crate::Const, ast::ConstDef, const_to_def),
|
||||
(crate::Static, ast::StaticDef, static_to_def),
|
||||
(crate::Function, ast::FnDef, fn_to_def),
|
||||
(crate::Field, ast::RecordFieldDef, record_field_to_def),
|
||||
(crate::Field, ast::TupleFieldDef, tuple_field_to_def),
|
||||
(crate::EnumVariant, ast::EnumVariant, enum_variant_to_def),
|
||||
(crate::Struct, ast::Struct, struct_to_def),
|
||||
(crate::Enum, ast::Enum, enum_to_def),
|
||||
(crate::Union, ast::Union, union_to_def),
|
||||
(crate::Trait, ast::Trait, trait_to_def),
|
||||
(crate::ImplDef, ast::Impl, impl_to_def),
|
||||
(crate::TypeAlias, ast::TypeAlias, type_alias_to_def),
|
||||
(crate::Const, ast::Const, const_to_def),
|
||||
(crate::Static, ast::Static, static_to_def),
|
||||
(crate::Function, ast::Fn, fn_to_def),
|
||||
(crate::Field, ast::RecordField, record_field_to_def),
|
||||
(crate::Field, ast::TupleField, tuple_field_to_def),
|
||||
(crate::EnumVariant, ast::Variant, enum_variant_to_def),
|
||||
(crate::TypeParam, ast::TypeParam, type_param_to_def),
|
||||
(crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros
|
||||
(crate::Local, ast::BindPat, bind_pat_to_def),
|
||||
(crate::Local, ast::IdentPat, bind_pat_to_def),
|
||||
];
|
||||
|
||||
fn find_root(node: &SyntaxNode) -> SyntaxNode {
|
||||
|
|
|
@ -65,57 +65,48 @@ impl SourceToDefCtx<'_, '_> {
|
|||
Some(ModuleId { krate: parent_module.krate, local_id: child_id })
|
||||
}
|
||||
|
||||
pub(super) fn trait_to_def(&mut self, src: InFile<ast::TraitDef>) -> Option<TraitId> {
|
||||
pub(super) fn trait_to_def(&mut self, src: InFile<ast::Trait>) -> Option<TraitId> {
|
||||
self.to_def(src, keys::TRAIT)
|
||||
}
|
||||
pub(super) fn impl_to_def(&mut self, src: InFile<ast::ImplDef>) -> Option<ImplId> {
|
||||
pub(super) fn impl_to_def(&mut self, src: InFile<ast::Impl>) -> Option<ImplId> {
|
||||
self.to_def(src, keys::IMPL)
|
||||
}
|
||||
pub(super) fn fn_to_def(&mut self, src: InFile<ast::FnDef>) -> Option<FunctionId> {
|
||||
pub(super) fn fn_to_def(&mut self, src: InFile<ast::Fn>) -> Option<FunctionId> {
|
||||
self.to_def(src, keys::FUNCTION)
|
||||
}
|
||||
pub(super) fn struct_to_def(&mut self, src: InFile<ast::StructDef>) -> Option<StructId> {
|
||||
pub(super) fn struct_to_def(&mut self, src: InFile<ast::Struct>) -> Option<StructId> {
|
||||
self.to_def(src, keys::STRUCT)
|
||||
}
|
||||
pub(super) fn enum_to_def(&mut self, src: InFile<ast::EnumDef>) -> Option<EnumId> {
|
||||
pub(super) fn enum_to_def(&mut self, src: InFile<ast::Enum>) -> Option<EnumId> {
|
||||
self.to_def(src, keys::ENUM)
|
||||
}
|
||||
pub(super) fn union_to_def(&mut self, src: InFile<ast::UnionDef>) -> Option<UnionId> {
|
||||
pub(super) fn union_to_def(&mut self, src: InFile<ast::Union>) -> Option<UnionId> {
|
||||
self.to_def(src, keys::UNION)
|
||||
}
|
||||
pub(super) fn static_to_def(&mut self, src: InFile<ast::StaticDef>) -> Option<StaticId> {
|
||||
pub(super) fn static_to_def(&mut self, src: InFile<ast::Static>) -> Option<StaticId> {
|
||||
self.to_def(src, keys::STATIC)
|
||||
}
|
||||
pub(super) fn const_to_def(&mut self, src: InFile<ast::ConstDef>) -> Option<ConstId> {
|
||||
pub(super) fn const_to_def(&mut self, src: InFile<ast::Const>) -> Option<ConstId> {
|
||||
self.to_def(src, keys::CONST)
|
||||
}
|
||||
pub(super) fn type_alias_to_def(
|
||||
&mut self,
|
||||
src: InFile<ast::TypeAliasDef>,
|
||||
) -> Option<TypeAliasId> {
|
||||
pub(super) fn type_alias_to_def(&mut self, src: InFile<ast::TypeAlias>) -> Option<TypeAliasId> {
|
||||
self.to_def(src, keys::TYPE_ALIAS)
|
||||
}
|
||||
pub(super) fn record_field_to_def(
|
||||
&mut self,
|
||||
src: InFile<ast::RecordFieldDef>,
|
||||
) -> Option<FieldId> {
|
||||
pub(super) fn record_field_to_def(&mut self, src: InFile<ast::RecordField>) -> Option<FieldId> {
|
||||
self.to_def(src, keys::RECORD_FIELD)
|
||||
}
|
||||
pub(super) fn tuple_field_to_def(
|
||||
&mut self,
|
||||
src: InFile<ast::TupleFieldDef>,
|
||||
) -> Option<FieldId> {
|
||||
pub(super) fn tuple_field_to_def(&mut self, src: InFile<ast::TupleField>) -> Option<FieldId> {
|
||||
self.to_def(src, keys::TUPLE_FIELD)
|
||||
}
|
||||
pub(super) fn enum_variant_to_def(
|
||||
&mut self,
|
||||
src: InFile<ast::EnumVariant>,
|
||||
src: InFile<ast::Variant>,
|
||||
) -> Option<EnumVariantId> {
|
||||
self.to_def(src, keys::ENUM_VARIANT)
|
||||
self.to_def(src, keys::VARIANT)
|
||||
}
|
||||
pub(super) fn bind_pat_to_def(
|
||||
&mut self,
|
||||
src: InFile<ast::BindPat>,
|
||||
src: InFile<ast::IdentPat>,
|
||||
) -> Option<(DefWithBodyId, PatId)> {
|
||||
let container = self.find_pat_container(src.as_ref().map(|it| it.syntax()))?;
|
||||
let (_body, source_map) = self.db.body_with_source_map(container);
|
||||
|
@ -163,39 +154,39 @@ impl SourceToDefCtx<'_, '_> {
|
|||
let def = self.module_to_def(container.with_value(it))?;
|
||||
def.into()
|
||||
},
|
||||
ast::TraitDef(it) => {
|
||||
ast::Trait(it) => {
|
||||
let def = self.trait_to_def(container.with_value(it))?;
|
||||
def.into()
|
||||
},
|
||||
ast::ImplDef(it) => {
|
||||
ast::Impl(it) => {
|
||||
let def = self.impl_to_def(container.with_value(it))?;
|
||||
def.into()
|
||||
},
|
||||
ast::FnDef(it) => {
|
||||
ast::Fn(it) => {
|
||||
let def = self.fn_to_def(container.with_value(it))?;
|
||||
DefWithBodyId::from(def).into()
|
||||
},
|
||||
ast::StructDef(it) => {
|
||||
ast::Struct(it) => {
|
||||
let def = self.struct_to_def(container.with_value(it))?;
|
||||
VariantId::from(def).into()
|
||||
},
|
||||
ast::EnumDef(it) => {
|
||||
ast::Enum(it) => {
|
||||
let def = self.enum_to_def(container.with_value(it))?;
|
||||
def.into()
|
||||
},
|
||||
ast::UnionDef(it) => {
|
||||
ast::Union(it) => {
|
||||
let def = self.union_to_def(container.with_value(it))?;
|
||||
VariantId::from(def).into()
|
||||
},
|
||||
ast::StaticDef(it) => {
|
||||
ast::Static(it) => {
|
||||
let def = self.static_to_def(container.with_value(it))?;
|
||||
DefWithBodyId::from(def).into()
|
||||
},
|
||||
ast::ConstDef(it) => {
|
||||
ast::Const(it) => {
|
||||
let def = self.const_to_def(container.with_value(it))?;
|
||||
DefWithBodyId::from(def).into()
|
||||
},
|
||||
ast::TypeAliasDef(it) => {
|
||||
ast::TypeAlias(it) => {
|
||||
let def = self.type_alias_to_def(container.with_value(it))?;
|
||||
def.into()
|
||||
},
|
||||
|
@ -213,12 +204,12 @@ impl SourceToDefCtx<'_, '_> {
|
|||
for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
|
||||
let res: GenericDefId = match_ast! {
|
||||
match (container.value) {
|
||||
ast::FnDef(it) => self.fn_to_def(container.with_value(it))?.into(),
|
||||
ast::StructDef(it) => self.struct_to_def(container.with_value(it))?.into(),
|
||||
ast::EnumDef(it) => self.enum_to_def(container.with_value(it))?.into(),
|
||||
ast::TraitDef(it) => self.trait_to_def(container.with_value(it))?.into(),
|
||||
ast::TypeAliasDef(it) => self.type_alias_to_def(container.with_value(it))?.into(),
|
||||
ast::ImplDef(it) => self.impl_to_def(container.with_value(it))?.into(),
|
||||
ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(),
|
||||
ast::Struct(it) => self.struct_to_def(container.with_value(it))?.into(),
|
||||
ast::Enum(it) => self.enum_to_def(container.with_value(it))?.into(),
|
||||
ast::Trait(it) => self.trait_to_def(container.with_value(it))?.into(),
|
||||
ast::TypeAlias(it) => self.type_alias_to_def(container.with_value(it))?.into(),
|
||||
ast::Impl(it) => self.impl_to_def(container.with_value(it))?.into(),
|
||||
_ => continue,
|
||||
}
|
||||
};
|
||||
|
@ -231,9 +222,9 @@ impl SourceToDefCtx<'_, '_> {
|
|||
for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
|
||||
let res: DefWithBodyId = match_ast! {
|
||||
match (container.value) {
|
||||
ast::ConstDef(it) => self.const_to_def(container.with_value(it))?.into(),
|
||||
ast::StaticDef(it) => self.static_to_def(container.with_value(it))?.into(),
|
||||
ast::FnDef(it) => self.fn_to_def(container.with_value(it))?.into(),
|
||||
ast::Const(it) => self.const_to_def(container.with_value(it))?.into(),
|
||||
ast::Static(it) => self.static_to_def(container.with_value(it))?.into(),
|
||||
ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(),
|
||||
_ => continue,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -159,7 +159,7 @@ impl SourceAnalyzer {
|
|||
pub(crate) fn resolve_record_field(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
field: &ast::RecordField,
|
||||
field: &ast::RecordExprField,
|
||||
) -> Option<(Field, Option<Local>)> {
|
||||
let expr = field.expr()?;
|
||||
let expr_id = self.expr_id(db, &expr)?;
|
||||
|
@ -182,7 +182,7 @@ impl SourceAnalyzer {
|
|||
pub(crate) fn resolve_record_field_pat(
|
||||
&self,
|
||||
_db: &dyn HirDatabase,
|
||||
field: &ast::RecordFieldPat,
|
||||
field: &ast::RecordPatField,
|
||||
) -> Option<Field> {
|
||||
let pat_id = self.pat_id(&field.pat()?)?;
|
||||
let struct_field = self.infer.as_ref()?.record_field_pat_resolution(pat_id)?;
|
||||
|
@ -202,7 +202,7 @@ impl SourceAnalyzer {
|
|||
pub(crate) fn resolve_bind_pat_to_const(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
pat: &ast::BindPat,
|
||||
pat: &ast::IdentPat,
|
||||
) -> Option<ModuleDef> {
|
||||
let pat_id = self.pat_id(&pat.clone().into())?;
|
||||
let body = self.body.as_ref()?;
|
||||
|
@ -246,7 +246,7 @@ impl SourceAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordLit::cast) {
|
||||
if let Some(rec_lit) = path.syntax().parent().and_then(ast::RecordExpr::cast) {
|
||||
let expr_id = self.expr_id(db, &rec_lit.into())?;
|
||||
if let Some(VariantId::EnumVariantId(variant)) =
|
||||
self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
|
||||
|
@ -284,7 +284,7 @@ impl SourceAnalyzer {
|
|||
pub(crate) fn record_literal_missing_fields(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
literal: &ast::RecordLit,
|
||||
literal: &ast::RecordExpr,
|
||||
) -> Option<Vec<(Field, Type)>> {
|
||||
let krate = self.resolver.krate()?;
|
||||
let body = self.body.as_ref()?;
|
||||
|
@ -358,7 +358,7 @@ impl SourceAnalyzer {
|
|||
pub(crate) fn resolve_variant(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
record_lit: ast::RecordLit,
|
||||
record_lit: ast::RecordExpr,
|
||||
) -> Option<VariantId> {
|
||||
let infer = self.infer.as_ref()?;
|
||||
let expr_id = self.expr_id(db, &record_lit.into())?;
|
||||
|
@ -405,8 +405,7 @@ fn scope_for_offset(
|
|||
)
|
||||
})
|
||||
.map(|(expr_range, scope)| {
|
||||
adjust(db, scopes, source_map, expr_range, offset.file_id, offset.value)
|
||||
.unwrap_or(*scope)
|
||||
adjust(db, scopes, source_map, expr_range, offset).unwrap_or(*scope)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -417,8 +416,7 @@ fn adjust(
|
|||
scopes: &ExprScopes,
|
||||
source_map: &BodySourceMap,
|
||||
expr_range: TextRange,
|
||||
file_id: HirFileId,
|
||||
offset: TextSize,
|
||||
offset: InFile<TextSize>,
|
||||
) -> Option<ScopeId> {
|
||||
let child_scopes = scopes
|
||||
.scope_by_expr()
|
||||
|
@ -426,7 +424,7 @@ fn adjust(
|
|||
.filter_map(|(id, scope)| {
|
||||
let source = source_map.expr_syntax(*id).ok()?;
|
||||
// FIXME: correctly handle macro expansion
|
||||
if source.file_id != file_id {
|
||||
if source.file_id != offset.file_id {
|
||||
return None;
|
||||
}
|
||||
let root = source.file_syntax(db.upcast());
|
||||
|
@ -434,7 +432,7 @@ fn adjust(
|
|||
Some((node.syntax().text_range(), scope))
|
||||
})
|
||||
.filter(|&(range, _)| {
|
||||
range.start() <= offset && expr_range.contains_range(range) && range != expr_range
|
||||
range.start() <= offset.value && expr_range.contains_range(range) && range != expr_range
|
||||
});
|
||||
|
||||
child_scopes
|
||||
|
|
|
@ -8,7 +8,7 @@ use hir_expand::{
|
|||
InFile,
|
||||
};
|
||||
use ra_arena::{map::ArenaMap, Arena};
|
||||
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
|
||||
use ra_syntax::ast::{self, NameOwner, VisibilityOwner};
|
||||
|
||||
use crate::{
|
||||
body::{CfgExpander, LowerCtx},
|
||||
|
@ -112,7 +112,7 @@ impl EnumData {
|
|||
|
||||
impl HasChildSource for EnumId {
|
||||
type ChildId = LocalEnumVariantId;
|
||||
type Value = ast::EnumVariant;
|
||||
type Value = ast::Variant;
|
||||
fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> {
|
||||
let src = self.lookup(db).source(db);
|
||||
let mut trace = Trace::new_for_map();
|
||||
|
@ -123,8 +123,8 @@ impl HasChildSource for EnumId {
|
|||
|
||||
fn lower_enum(
|
||||
db: &dyn DefDatabase,
|
||||
trace: &mut Trace<EnumVariantData, ast::EnumVariant>,
|
||||
ast: &InFile<ast::EnumDef>,
|
||||
trace: &mut Trace<EnumVariantData, ast::Variant>,
|
||||
ast: &InFile<ast::Enum>,
|
||||
module_id: ModuleId,
|
||||
) {
|
||||
let expander = CfgExpander::new(db, ast.file_id, module_id.krate);
|
||||
|
@ -179,7 +179,7 @@ impl VariantData {
|
|||
|
||||
impl HasChildSource for VariantId {
|
||||
type ChildId = LocalFieldId;
|
||||
type Value = Either<ast::TupleFieldDef, ast::RecordFieldDef>;
|
||||
type Value = Either<ast::TupleField, ast::RecordField>;
|
||||
|
||||
fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<Self::ChildId, Self::Value>> {
|
||||
let (src, module_id) = match self {
|
||||
|
@ -194,7 +194,7 @@ impl HasChildSource for VariantId {
|
|||
}
|
||||
VariantId::UnionId(it) => (
|
||||
it.lookup(db).source(db).map(|it| {
|
||||
it.record_field_def_list()
|
||||
it.record_field_list()
|
||||
.map(ast::StructKind::Record)
|
||||
.unwrap_or(ast::StructKind::Unit)
|
||||
}),
|
||||
|
@ -218,7 +218,7 @@ pub enum StructKind {
|
|||
fn lower_struct(
|
||||
db: &dyn DefDatabase,
|
||||
expander: &mut CfgExpander,
|
||||
trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
|
||||
trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>,
|
||||
ast: &InFile<ast::StructKind>,
|
||||
) -> StructKind {
|
||||
let ctx = LowerCtx::new(db, ast.file_id);
|
||||
|
@ -234,7 +234,7 @@ fn lower_struct(
|
|||
|| Either::Left(fd.clone()),
|
||||
|| FieldData {
|
||||
name: Name::new_tuple_field(i),
|
||||
type_ref: TypeRef::from_ast_opt(&ctx, fd.type_ref()),
|
||||
type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()),
|
||||
visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
|
||||
},
|
||||
);
|
||||
|
@ -251,7 +251,7 @@ fn lower_struct(
|
|||
|| Either::Right(fd.clone()),
|
||||
|| FieldData {
|
||||
name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
|
||||
type_ref: TypeRef::from_ast_opt(&ctx, fd.ascribed_type()),
|
||||
type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()),
|
||||
visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
|
||||
},
|
||||
);
|
||||
|
|
|
@ -151,18 +151,15 @@ pub enum AttrInput {
|
|||
impl Attr {
|
||||
fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
|
||||
let path = ModPath::from_src(ast.path()?, hygiene)?;
|
||||
let input = match ast.input() {
|
||||
None => None,
|
||||
Some(ast::AttrInput::Literal(lit)) => {
|
||||
// FIXME: escape? raw string?
|
||||
let value = lit.syntax().first_token()?.text().trim_matches('"').into();
|
||||
Some(AttrInput::Literal(value))
|
||||
}
|
||||
Some(ast::AttrInput::TokenTree(tt)) => {
|
||||
Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0))
|
||||
}
|
||||
let input = if let Some(lit) = ast.literal() {
|
||||
// FIXME: escape? raw string?
|
||||
let value = lit.syntax().first_token()?.text().trim_matches('"').into();
|
||||
Some(AttrInput::Literal(value))
|
||||
} else if let Some(tt) = ast.token_tree() {
|
||||
Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(Attr { path, input })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ pub struct BodySourceMap {
|
|||
expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>,
|
||||
pat_map: FxHashMap<PatSource, PatId>,
|
||||
pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
|
||||
field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordField>>>,
|
||||
field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>,
|
||||
expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
|
||||
}
|
||||
|
||||
|
@ -314,7 +314,7 @@ impl BodySourceMap {
|
|||
self.pat_map.get(&src).cloned()
|
||||
}
|
||||
|
||||
pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordField>> {
|
||||
pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> {
|
||||
self.field_map[&(expr, field)].clone()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
|
||||
//! representation.
|
||||
|
||||
use std::{any::type_name, sync::Arc};
|
||||
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
hygiene::Hygiene,
|
||||
|
@ -10,11 +12,12 @@ use hir_expand::{
|
|||
use ra_arena::Arena;
|
||||
use ra_syntax::{
|
||||
ast::{
|
||||
self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
|
||||
SlicePatComponents, TypeAscriptionOwner,
|
||||
self, ArgListOwner, ArrayExprKind, AstChildren, LiteralKind, LoopBodyOwner, NameOwner,
|
||||
SlicePatComponents,
|
||||
},
|
||||
AstNode, AstPtr,
|
||||
};
|
||||
use rustc_hash::FxHashMap;
|
||||
use test_utils::mark;
|
||||
|
||||
use crate::{
|
||||
|
@ -35,9 +38,6 @@ use crate::{
|
|||
};
|
||||
|
||||
use super::{ExprSource, PatSource};
|
||||
use ast::AstChildren;
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::{any::type_name, sync::Arc};
|
||||
|
||||
pub(crate) struct LowerCtx {
|
||||
hygiene: Hygiene,
|
||||
|
@ -224,9 +224,22 @@ impl ExprCollector<'_> {
|
|||
self.alloc_expr(Expr::Unsafe { body }, syntax_ptr)
|
||||
}
|
||||
// FIXME: we need to record these effects somewhere...
|
||||
ast::Effect::Async(_) | ast::Effect::Label(_) => {
|
||||
self.collect_block_opt(e.block_expr())
|
||||
}
|
||||
ast::Effect::Label(label) => match e.block_expr() {
|
||||
Some(block) => {
|
||||
let res = self.collect_block(block);
|
||||
match &mut self.body.exprs[res] {
|
||||
Expr::Block { label: block_label, .. } => {
|
||||
*block_label =
|
||||
label.lifetime_token().map(|t| Name::new_lifetime(&t))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
res
|
||||
}
|
||||
None => self.missing_expr(),
|
||||
},
|
||||
// FIXME: we need to record these effects somewhere...
|
||||
ast::Effect::Async(_) => self.collect_block_opt(e.block_expr()),
|
||||
},
|
||||
ast::Expr::BlockExpr(e) => self.collect_block(e),
|
||||
ast::Expr::LoopExpr(e) => {
|
||||
|
@ -324,7 +337,7 @@ impl ExprCollector<'_> {
|
|||
};
|
||||
let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
|
||||
let generic_args =
|
||||
e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
|
||||
e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
|
||||
self.alloc_expr(
|
||||
Expr::MethodCall { receiver, method_name, args, generic_args },
|
||||
syntax_ptr,
|
||||
|
@ -379,10 +392,10 @@ impl ExprCollector<'_> {
|
|||
let expr = e.expr().map(|e| self.collect_expr(e));
|
||||
self.alloc_expr(Expr::Return { expr }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::RecordLit(e) => {
|
||||
ast::Expr::RecordExpr(e) => {
|
||||
let path = e.path().and_then(|path| self.expander.parse_path(path));
|
||||
let mut field_ptrs = Vec::new();
|
||||
let record_lit = if let Some(nfl) = e.record_field_list() {
|
||||
let record_lit = if let Some(nfl) = e.record_expr_field_list() {
|
||||
let fields = nfl
|
||||
.fields()
|
||||
.inspect(|field| field_ptrs.push(AstPtr::new(field)))
|
||||
|
@ -432,7 +445,7 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
ast::Expr::CastExpr(e) => {
|
||||
let expr = self.collect_expr_opt(e.expr());
|
||||
let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
|
||||
let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty());
|
||||
self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::RefExpr(e) => {
|
||||
|
@ -460,22 +473,19 @@ impl ExprCollector<'_> {
|
|||
self.alloc_expr(Expr::Missing, syntax_ptr)
|
||||
}
|
||||
}
|
||||
ast::Expr::LambdaExpr(e) => {
|
||||
ast::Expr::ClosureExpr(e) => {
|
||||
let mut args = Vec::new();
|
||||
let mut arg_types = Vec::new();
|
||||
if let Some(pl) = e.param_list() {
|
||||
for param in pl.params() {
|
||||
let pat = self.collect_pat_opt(param.pat());
|
||||
let type_ref =
|
||||
param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
|
||||
let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
|
||||
args.push(pat);
|
||||
arg_types.push(type_ref);
|
||||
}
|
||||
}
|
||||
let ret_type = e
|
||||
.ret_type()
|
||||
.and_then(|r| r.type_ref())
|
||||
.map(|it| TypeRef::from_ast(&self.ctx(), it));
|
||||
let ret_type =
|
||||
e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it));
|
||||
let body = self.collect_expr_opt(e.body());
|
||||
self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
|
||||
}
|
||||
|
@ -486,7 +496,7 @@ impl ExprCollector<'_> {
|
|||
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::TupleExpr(e) => {
|
||||
let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect();
|
||||
let exprs = e.fields().map(|expr| self.collect_expr(expr)).collect();
|
||||
self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::BoxExpr(e) => {
|
||||
|
@ -559,9 +569,6 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME implement HIR for these:
|
||||
ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -604,76 +611,84 @@ impl ExprCollector<'_> {
|
|||
self.collect_block_items(&block);
|
||||
let statements = block
|
||||
.statements()
|
||||
.map(|s| match s {
|
||||
ast::Stmt::LetStmt(stmt) => {
|
||||
let pat = self.collect_pat_opt(stmt.pat());
|
||||
let type_ref =
|
||||
stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
|
||||
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
|
||||
Statement::Let { pat, type_ref, initializer }
|
||||
}
|
||||
ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())),
|
||||
.filter_map(|s| {
|
||||
let stmt = match s {
|
||||
ast::Stmt::LetStmt(stmt) => {
|
||||
let pat = self.collect_pat_opt(stmt.pat());
|
||||
let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
|
||||
let initializer = stmt.initializer().map(|e| self.collect_expr(e));
|
||||
Statement::Let { pat, type_ref, initializer }
|
||||
}
|
||||
ast::Stmt::ExprStmt(stmt) => {
|
||||
Statement::Expr(self.collect_expr_opt(stmt.expr()))
|
||||
}
|
||||
ast::Stmt::Item(_) => return None,
|
||||
};
|
||||
Some(stmt)
|
||||
})
|
||||
.collect();
|
||||
let tail = block.expr().map(|e| self.collect_expr(e));
|
||||
let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t));
|
||||
self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
|
||||
self.alloc_expr(Expr::Block { statements, tail, label: None }, syntax_node_ptr)
|
||||
}
|
||||
|
||||
fn collect_block_items(&mut self, block: &ast::BlockExpr) {
|
||||
let container = ContainerId::DefWithBodyId(self.def);
|
||||
|
||||
let items = block
|
||||
.items()
|
||||
.statements()
|
||||
.filter_map(|stmt| match stmt {
|
||||
ast::Stmt::Item(it) => Some(it),
|
||||
ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
|
||||
})
|
||||
.filter_map(|item| {
|
||||
let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
|
||||
ast::ModuleItem::FnDef(def) => {
|
||||
ast::Item::Fn(def) => {
|
||||
let id = self.find_inner_item(&def)?;
|
||||
(
|
||||
FunctionLoc { container: container.into(), id }.intern(self.db).into(),
|
||||
def.name(),
|
||||
)
|
||||
}
|
||||
ast::ModuleItem::TypeAliasDef(def) => {
|
||||
ast::Item::TypeAlias(def) => {
|
||||
let id = self.find_inner_item(&def)?;
|
||||
(
|
||||
TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
|
||||
def.name(),
|
||||
)
|
||||
}
|
||||
ast::ModuleItem::ConstDef(def) => {
|
||||
ast::Item::Const(def) => {
|
||||
let id = self.find_inner_item(&def)?;
|
||||
(
|
||||
ConstLoc { container: container.into(), id }.intern(self.db).into(),
|
||||
def.name(),
|
||||
)
|
||||
}
|
||||
ast::ModuleItem::StaticDef(def) => {
|
||||
ast::Item::Static(def) => {
|
||||
let id = self.find_inner_item(&def)?;
|
||||
(StaticLoc { container, id }.intern(self.db).into(), def.name())
|
||||
}
|
||||
ast::ModuleItem::StructDef(def) => {
|
||||
ast::Item::Struct(def) => {
|
||||
let id = self.find_inner_item(&def)?;
|
||||
(StructLoc { container, id }.intern(self.db).into(), def.name())
|
||||
}
|
||||
ast::ModuleItem::EnumDef(def) => {
|
||||
ast::Item::Enum(def) => {
|
||||
let id = self.find_inner_item(&def)?;
|
||||
(EnumLoc { container, id }.intern(self.db).into(), def.name())
|
||||
}
|
||||
ast::ModuleItem::UnionDef(def) => {
|
||||
ast::Item::Union(def) => {
|
||||
let id = self.find_inner_item(&def)?;
|
||||
(UnionLoc { container, id }.intern(self.db).into(), def.name())
|
||||
}
|
||||
ast::ModuleItem::TraitDef(def) => {
|
||||
ast::Item::Trait(def) => {
|
||||
let id = self.find_inner_item(&def)?;
|
||||
(TraitLoc { container, id }.intern(self.db).into(), def.name())
|
||||
}
|
||||
ast::ModuleItem::ExternBlock(_) => return None, // FIXME: collect from extern blocks
|
||||
ast::ModuleItem::ImplDef(_)
|
||||
| ast::ModuleItem::UseItem(_)
|
||||
| ast::ModuleItem::ExternCrateItem(_)
|
||||
| ast::ModuleItem::Module(_)
|
||||
| ast::ModuleItem::MacroCall(_) => return None,
|
||||
ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
|
||||
ast::Item::Impl(_)
|
||||
| ast::Item::Use(_)
|
||||
| ast::Item::ExternCrate(_)
|
||||
| ast::Item::Module(_)
|
||||
| ast::Item::MacroCall(_) => return None,
|
||||
};
|
||||
|
||||
Some((def, name))
|
||||
|
@ -708,7 +723,7 @@ impl ExprCollector<'_> {
|
|||
|
||||
fn collect_pat(&mut self, pat: ast::Pat) -> PatId {
|
||||
let pattern = match &pat {
|
||||
ast::Pat::BindPat(bp) => {
|
||||
ast::Pat::IdentPat(bp) => {
|
||||
let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
|
||||
let annotation =
|
||||
BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
|
||||
|
@ -747,7 +762,7 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
ast::Pat::TupleStructPat(p) => {
|
||||
let path = p.path().and_then(|path| self.expander.parse_path(path));
|
||||
let (args, ellipsis) = self.collect_tuple_pat(p.args());
|
||||
let (args, ellipsis) = self.collect_tuple_pat(p.fields());
|
||||
Pat::TupleStruct { path, args, ellipsis }
|
||||
}
|
||||
ast::Pat::RefPat(p) => {
|
||||
|
@ -765,40 +780,36 @@ impl ExprCollector<'_> {
|
|||
}
|
||||
ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat()),
|
||||
ast::Pat::TuplePat(p) => {
|
||||
let (args, ellipsis) = self.collect_tuple_pat(p.args());
|
||||
let (args, ellipsis) = self.collect_tuple_pat(p.fields());
|
||||
Pat::Tuple { args, ellipsis }
|
||||
}
|
||||
ast::Pat::PlaceholderPat(_) => Pat::Wild,
|
||||
ast::Pat::WildcardPat(_) => Pat::Wild,
|
||||
ast::Pat::RecordPat(p) => {
|
||||
let path = p.path().and_then(|path| self.expander.parse_path(path));
|
||||
let record_field_pat_list =
|
||||
p.record_field_pat_list().expect("every struct should have a field list");
|
||||
let mut fields: Vec<_> = record_field_pat_list
|
||||
.bind_pats()
|
||||
.filter_map(|bind_pat| {
|
||||
let ast_pat =
|
||||
ast::Pat::cast(bind_pat.syntax().clone()).expect("bind pat is a pat");
|
||||
let args: Vec<_> = p
|
||||
.record_pat_field_list()
|
||||
.expect("every struct should have a field list")
|
||||
.fields()
|
||||
.filter_map(|f| {
|
||||
let ast_pat = f.pat()?;
|
||||
let pat = self.collect_pat(ast_pat);
|
||||
let name = bind_pat.name()?.as_name();
|
||||
let name = f.field_name()?.as_name();
|
||||
Some(RecordFieldPat { name, pat })
|
||||
})
|
||||
.collect();
|
||||
let iter = record_field_pat_list.record_field_pats().filter_map(|f| {
|
||||
let ast_pat = f.pat()?;
|
||||
let pat = self.collect_pat(ast_pat);
|
||||
let name = f.field_name()?.as_name();
|
||||
Some(RecordFieldPat { name, pat })
|
||||
});
|
||||
fields.extend(iter);
|
||||
|
||||
let ellipsis = record_field_pat_list.dotdot_token().is_some();
|
||||
let ellipsis = p
|
||||
.record_pat_field_list()
|
||||
.expect("every struct should have a field list")
|
||||
.dotdot_token()
|
||||
.is_some();
|
||||
|
||||
Pat::Record { path, args: fields, ellipsis }
|
||||
Pat::Record { path, args, ellipsis }
|
||||
}
|
||||
ast::Pat::SlicePat(p) => {
|
||||
let SlicePatComponents { prefix, slice, suffix } = p.components();
|
||||
|
||||
// FIXME properly handle `DotDotPat`
|
||||
// FIXME properly handle `RestPat`
|
||||
Pat::Slice {
|
||||
prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(),
|
||||
slice: slice.map(|p| self.collect_pat(p)),
|
||||
|
@ -815,10 +826,10 @@ impl ExprCollector<'_> {
|
|||
Pat::Missing
|
||||
}
|
||||
}
|
||||
ast::Pat::DotDotPat(_) => {
|
||||
// `DotDotPat` requires special handling and should not be mapped
|
||||
ast::Pat::RestPat(_) => {
|
||||
// `RestPat` requires special handling and should not be mapped
|
||||
// to a Pat. Here we are using `Pat::Missing` as a fallback for
|
||||
// when `DotDotPat` is mapped to `Pat`, which can easily happen
|
||||
// when `RestPat` is mapped to `Pat`, which can easily happen
|
||||
// when the source code being analyzed has a malformed pattern
|
||||
// which includes `..` in a place where it isn't valid.
|
||||
|
||||
|
@ -842,10 +853,10 @@ impl ExprCollector<'_> {
|
|||
fn collect_tuple_pat(&mut self, args: AstChildren<ast::Pat>) -> (Vec<PatId>, Option<usize>) {
|
||||
// Find the location of the `..`, if there is one. Note that we do not
|
||||
// consider the possiblity of there being multiple `..` here.
|
||||
let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::DotDotPat(_)));
|
||||
let ellipsis = args.clone().position(|p| matches!(p, ast::Pat::RestPat(_)));
|
||||
// We want to skip the `..` pattern here, since we account for it above.
|
||||
let args = args
|
||||
.filter(|p| !matches!(p, ast::Pat::DotDotPat(_)))
|
||||
.filter(|p| !matches!(p, ast::Pat::RestPat(_)))
|
||||
.map(|p| self.collect_pat(p))
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ impl ChildBySource for EnumId {
|
|||
let arena_map = arena_map.as_ref();
|
||||
for (local_id, source) in arena_map.value.iter() {
|
||||
let id = EnumVariantId { parent: *self, local_id };
|
||||
res[keys::ENUM_VARIANT].insert(arena_map.with_value(source.clone()), id)
|
||||
res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id)
|
||||
}
|
||||
|
||||
res
|
||||
|
|
|
@ -12,7 +12,7 @@ use hir_expand::{
|
|||
use ra_arena::{map::ArenaMap, Arena};
|
||||
use ra_db::FileId;
|
||||
use ra_prof::profile;
|
||||
use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
|
||||
use ra_syntax::ast::{self, GenericParamsOwner, NameOwner, TypeBoundsOwner};
|
||||
|
||||
use crate::{
|
||||
body::LowerCtx,
|
||||
|
@ -66,7 +66,7 @@ pub enum WherePredicateTarget {
|
|||
TypeParam(LocalTypeParamId),
|
||||
}
|
||||
|
||||
type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::TraitDef, ast::TypeParam>>;
|
||||
type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>;
|
||||
|
||||
impl GenericParams {
|
||||
pub(crate) fn generic_params_query(
|
||||
|
@ -205,9 +205,9 @@ impl GenericParams {
|
|||
&mut self,
|
||||
lower_ctx: &LowerCtx,
|
||||
sm: &mut SourceMap,
|
||||
node: &dyn TypeParamsOwner,
|
||||
node: &dyn GenericParamsOwner,
|
||||
) {
|
||||
if let Some(params) = node.type_param_list() {
|
||||
if let Some(params) = node.generic_param_list() {
|
||||
self.fill_params(lower_ctx, sm, params)
|
||||
}
|
||||
if let Some(where_clause) = node.where_clause() {
|
||||
|
@ -232,7 +232,7 @@ impl GenericParams {
|
|||
&mut self,
|
||||
lower_ctx: &LowerCtx,
|
||||
sm: &mut SourceMap,
|
||||
params: ast::TypeParamList,
|
||||
params: ast::GenericParamList,
|
||||
) {
|
||||
for type_param in params.type_params() {
|
||||
let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
|
||||
|
@ -253,7 +253,7 @@ impl GenericParams {
|
|||
|
||||
fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) {
|
||||
for pred in where_clause.predicates() {
|
||||
let type_ref = match pred.type_ref() {
|
||||
let type_ref = match pred.ty() {
|
||||
Some(type_ref) => type_ref,
|
||||
None => continue,
|
||||
};
|
||||
|
@ -270,7 +270,7 @@ impl GenericParams {
|
|||
bound: ast::TypeBound,
|
||||
type_ref: TypeRef,
|
||||
) {
|
||||
if bound.question_token().is_some() {
|
||||
if bound.question_mark_token().is_some() {
|
||||
// FIXME: remove this bound
|
||||
return;
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ impl GenericParams {
|
|||
|
||||
impl HasChildSource for GenericDefId {
|
||||
type ChildId = LocalTypeParamId;
|
||||
type Value = Either<ast::TraitDef, ast::TypeParam>;
|
||||
type Value = Either<ast::Trait, ast::TypeParam>;
|
||||
fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMap> {
|
||||
let (_, sm) = GenericParams::new(db, *self);
|
||||
sm
|
||||
|
|
|
@ -13,7 +13,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
|
||||
use ast::{AstNode, AttrsOwner, NameOwner, StructKind, TypeAscriptionOwner};
|
||||
use ast::{AstNode, AttrsOwner, NameOwner, StructKind};
|
||||
use either::Either;
|
||||
use hir_expand::{
|
||||
ast_id_map::FileAstId,
|
||||
|
@ -70,7 +70,7 @@ impl GenericParamsId {
|
|||
pub struct ItemTree {
|
||||
top_level: SmallVec<[ModItem; 1]>,
|
||||
attrs: FxHashMap<AttrOwner, Attrs>,
|
||||
inner_items: FxHashMap<FileAstId<ast::ModuleItem>, SmallVec<[ModItem; 1]>>,
|
||||
inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
|
||||
|
||||
data: Option<Box<ItemTreeData>>,
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ impl ItemTree {
|
|||
///
|
||||
/// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered
|
||||
/// to multiple items in the `ItemTree`.
|
||||
pub fn inner_items(&self, ast: FileAstId<ast::ModuleItem>) -> &[ModItem] {
|
||||
pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] {
|
||||
&self.inner_items[&ast]
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>));
|
|||
|
||||
/// Trait implemented by all item nodes in the item tree.
|
||||
pub trait ItemTreeNode: Clone {
|
||||
type Source: AstNode + Into<ast::ModuleItem>;
|
||||
type Source: AstNode + Into<ast::Item>;
|
||||
|
||||
fn ast_id(&self) -> FileAstId<Self::Source>;
|
||||
|
||||
|
@ -411,17 +411,17 @@ macro_rules! mod_items {
|
|||
}
|
||||
|
||||
mod_items! {
|
||||
Import in imports -> ast::UseItem,
|
||||
ExternCrate in extern_crates -> ast::ExternCrateItem,
|
||||
Function in functions -> ast::FnDef,
|
||||
Struct in structs -> ast::StructDef,
|
||||
Union in unions -> ast::UnionDef,
|
||||
Enum in enums -> ast::EnumDef,
|
||||
Const in consts -> ast::ConstDef,
|
||||
Static in statics -> ast::StaticDef,
|
||||
Trait in traits -> ast::TraitDef,
|
||||
Impl in impls -> ast::ImplDef,
|
||||
TypeAlias in type_aliases -> ast::TypeAliasDef,
|
||||
Import in imports -> ast::Use,
|
||||
ExternCrate in extern_crates -> ast::ExternCrate,
|
||||
Function in functions -> ast::Fn,
|
||||
Struct in structs -> ast::Struct,
|
||||
Union in unions -> ast::Union,
|
||||
Enum in enums -> ast::Enum,
|
||||
Const in consts -> ast::Const,
|
||||
Static in statics -> ast::Static,
|
||||
Trait in traits -> ast::Trait,
|
||||
Impl in impls -> ast::Impl,
|
||||
TypeAlias in type_aliases -> ast::TypeAlias,
|
||||
Mod in mods -> ast::Module,
|
||||
MacroCall in macro_calls -> ast::MacroCall,
|
||||
}
|
||||
|
@ -482,7 +482,7 @@ pub struct Import {
|
|||
pub is_prelude: bool,
|
||||
/// AST ID of the `use` or `extern crate` item this import was derived from. Note that many
|
||||
/// `Import`s can map to the same `use` item.
|
||||
pub ast_id: FileAstId<ast::UseItem>,
|
||||
pub ast_id: FileAstId<ast::Use>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -492,7 +492,7 @@ pub struct ExternCrate {
|
|||
pub visibility: RawVisibilityId,
|
||||
/// Whether this is a `#[macro_use] extern crate ...`.
|
||||
pub is_macro_use: bool,
|
||||
pub ast_id: FileAstId<ast::ExternCrateItem>,
|
||||
pub ast_id: FileAstId<ast::ExternCrate>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -505,7 +505,7 @@ pub struct Function {
|
|||
pub params: Box<[TypeRef]>,
|
||||
pub is_varargs: bool,
|
||||
pub ret_type: TypeRef,
|
||||
pub ast_id: FileAstId<ast::FnDef>,
|
||||
pub ast_id: FileAstId<ast::Fn>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -514,7 +514,7 @@ pub struct Struct {
|
|||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub fields: Fields,
|
||||
pub ast_id: FileAstId<ast::StructDef>,
|
||||
pub ast_id: FileAstId<ast::Struct>,
|
||||
pub kind: StructDefKind,
|
||||
}
|
||||
|
||||
|
@ -534,7 +534,7 @@ pub struct Union {
|
|||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub fields: Fields,
|
||||
pub ast_id: FileAstId<ast::UnionDef>,
|
||||
pub ast_id: FileAstId<ast::Union>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -543,7 +543,7 @@ pub struct Enum {
|
|||
pub visibility: RawVisibilityId,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub variants: IdRange<Variant>,
|
||||
pub ast_id: FileAstId<ast::EnumDef>,
|
||||
pub ast_id: FileAstId<ast::Enum>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -552,7 +552,7 @@ pub struct Const {
|
|||
pub name: Option<Name>,
|
||||
pub visibility: RawVisibilityId,
|
||||
pub type_ref: TypeRef,
|
||||
pub ast_id: FileAstId<ast::ConstDef>,
|
||||
pub ast_id: FileAstId<ast::Const>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -561,7 +561,7 @@ pub struct Static {
|
|||
pub visibility: RawVisibilityId,
|
||||
pub mutable: bool,
|
||||
pub type_ref: TypeRef,
|
||||
pub ast_id: FileAstId<ast::StaticDef>,
|
||||
pub ast_id: FileAstId<ast::Static>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -571,7 +571,7 @@ pub struct Trait {
|
|||
pub generic_params: GenericParamsId,
|
||||
pub auto: bool,
|
||||
pub items: Box<[AssocItem]>,
|
||||
pub ast_id: FileAstId<ast::TraitDef>,
|
||||
pub ast_id: FileAstId<ast::Trait>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -581,7 +581,7 @@ pub struct Impl {
|
|||
pub target_type: TypeRef,
|
||||
pub is_negative: bool,
|
||||
pub items: Box<[AssocItem]>,
|
||||
pub ast_id: FileAstId<ast::ImplDef>,
|
||||
pub ast_id: FileAstId<ast::Impl>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -592,7 +592,7 @@ pub struct TypeAlias {
|
|||
pub bounds: Box<[TypeBound]>,
|
||||
pub generic_params: GenericParamsId,
|
||||
pub type_ref: Option<TypeRef>,
|
||||
pub ast_id: FileAstId<ast::TypeAliasDef>,
|
||||
pub ast_id: FileAstId<ast::TypeAlias>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
//! AST -> `ItemTree` lowering code.
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
attr::Attrs,
|
||||
generics::{GenericParams, TypeParamData, TypeParamProvenance},
|
||||
};
|
||||
use std::{collections::hash_map::Entry, mem, sync::Arc};
|
||||
|
||||
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId};
|
||||
use ra_arena::map::ArenaMap;
|
||||
use ra_syntax::{
|
||||
|
@ -12,7 +9,13 @@ use ra_syntax::{
|
|||
SyntaxNode,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{collections::hash_map::Entry, mem, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
attr::Attrs,
|
||||
generics::{GenericParams, TypeParamData, TypeParamProvenance},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
fn id<N: ItemTreeNode>(index: Idx<N>) -> FileItemTreeId<N> {
|
||||
FileItemTreeId { index, _p: PhantomData }
|
||||
|
@ -70,19 +73,19 @@ impl Ctx {
|
|||
self.tree.data_mut()
|
||||
}
|
||||
|
||||
fn lower_mod_item(&mut self, item: &ast::ModuleItem, inner: bool) -> Option<ModItems> {
|
||||
fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems> {
|
||||
assert!(inner || self.inner_items.is_empty());
|
||||
|
||||
// Collect inner items for 1-to-1-lowered items.
|
||||
match item {
|
||||
ast::ModuleItem::StructDef(_)
|
||||
| ast::ModuleItem::UnionDef(_)
|
||||
| ast::ModuleItem::EnumDef(_)
|
||||
| ast::ModuleItem::FnDef(_)
|
||||
| ast::ModuleItem::TypeAliasDef(_)
|
||||
| ast::ModuleItem::ConstDef(_)
|
||||
| ast::ModuleItem::StaticDef(_)
|
||||
| ast::ModuleItem::MacroCall(_) => {
|
||||
ast::Item::Struct(_)
|
||||
| ast::Item::Union(_)
|
||||
| ast::Item::Enum(_)
|
||||
| ast::Item::Fn(_)
|
||||
| ast::Item::TypeAlias(_)
|
||||
| ast::Item::Const(_)
|
||||
| ast::Item::Static(_)
|
||||
| ast::Item::MacroCall(_) => {
|
||||
// Skip this if we're already collecting inner items. We'll descend into all nodes
|
||||
// already.
|
||||
if !inner {
|
||||
|
@ -92,34 +95,30 @@ impl Ctx {
|
|||
|
||||
// These are handled in their respective `lower_X` method (since we can't just blindly
|
||||
// walk them).
|
||||
ast::ModuleItem::TraitDef(_)
|
||||
| ast::ModuleItem::ImplDef(_)
|
||||
| ast::ModuleItem::ExternBlock(_) => {}
|
||||
ast::Item::Trait(_) | ast::Item::Impl(_) | ast::Item::ExternBlock(_) => {}
|
||||
|
||||
// These don't have inner items.
|
||||
ast::ModuleItem::Module(_)
|
||||
| ast::ModuleItem::ExternCrateItem(_)
|
||||
| ast::ModuleItem::UseItem(_) => {}
|
||||
ast::Item::Module(_) | ast::Item::ExternCrate(_) | ast::Item::Use(_) => {}
|
||||
};
|
||||
|
||||
let attrs = Attrs::new(item, &self.hygiene);
|
||||
let items = match item {
|
||||
ast::ModuleItem::StructDef(ast) => self.lower_struct(ast).map(Into::into),
|
||||
ast::ModuleItem::UnionDef(ast) => self.lower_union(ast).map(Into::into),
|
||||
ast::ModuleItem::EnumDef(ast) => self.lower_enum(ast).map(Into::into),
|
||||
ast::ModuleItem::FnDef(ast) => self.lower_function(ast).map(Into::into),
|
||||
ast::ModuleItem::TypeAliasDef(ast) => self.lower_type_alias(ast).map(Into::into),
|
||||
ast::ModuleItem::StaticDef(ast) => self.lower_static(ast).map(Into::into),
|
||||
ast::ModuleItem::ConstDef(ast) => Some(self.lower_const(ast).into()),
|
||||
ast::ModuleItem::Module(ast) => self.lower_module(ast).map(Into::into),
|
||||
ast::ModuleItem::TraitDef(ast) => self.lower_trait(ast).map(Into::into),
|
||||
ast::ModuleItem::ImplDef(ast) => self.lower_impl(ast).map(Into::into),
|
||||
ast::ModuleItem::UseItem(ast) => Some(ModItems(
|
||||
ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into),
|
||||
ast::Item::Union(ast) => self.lower_union(ast).map(Into::into),
|
||||
ast::Item::Enum(ast) => self.lower_enum(ast).map(Into::into),
|
||||
ast::Item::Fn(ast) => self.lower_function(ast).map(Into::into),
|
||||
ast::Item::TypeAlias(ast) => self.lower_type_alias(ast).map(Into::into),
|
||||
ast::Item::Static(ast) => self.lower_static(ast).map(Into::into),
|
||||
ast::Item::Const(ast) => Some(self.lower_const(ast).into()),
|
||||
ast::Item::Module(ast) => self.lower_module(ast).map(Into::into),
|
||||
ast::Item::Trait(ast) => self.lower_trait(ast).map(Into::into),
|
||||
ast::Item::Impl(ast) => self.lower_impl(ast).map(Into::into),
|
||||
ast::Item::Use(ast) => Some(ModItems(
|
||||
self.lower_use(ast).into_iter().map(Into::into).collect::<SmallVec<_>>(),
|
||||
)),
|
||||
ast::ModuleItem::ExternCrateItem(ast) => self.lower_extern_crate(ast).map(Into::into),
|
||||
ast::ModuleItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
|
||||
ast::ModuleItem::ExternBlock(ast) => {
|
||||
ast::Item::ExternCrate(ast) => self.lower_extern_crate(ast).map(Into::into),
|
||||
ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
|
||||
ast::Item::ExternBlock(ast) => {
|
||||
Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
|
||||
}
|
||||
};
|
||||
|
@ -147,27 +146,26 @@ impl Ctx {
|
|||
fn collect_inner_items(&mut self, container: &SyntaxNode) {
|
||||
let forced_vis = self.forced_visibility.take();
|
||||
let mut inner_items = mem::take(&mut self.tree.inner_items);
|
||||
inner_items.extend(
|
||||
container.descendants().skip(1).filter_map(ast::ModuleItem::cast).filter_map(|item| {
|
||||
inner_items.extend(container.descendants().skip(1).filter_map(ast::Item::cast).filter_map(
|
||||
|item| {
|
||||
let ast_id = self.source_ast_id_map.ast_id(&item);
|
||||
Some((ast_id, self.lower_mod_item(&item, true)?.0))
|
||||
}),
|
||||
);
|
||||
},
|
||||
));
|
||||
self.tree.inner_items = inner_items;
|
||||
self.forced_visibility = forced_vis;
|
||||
}
|
||||
|
||||
fn lower_assoc_item(&mut self, item: &ast::ModuleItem) -> Option<AssocItem> {
|
||||
fn lower_assoc_item(&mut self, item: &ast::AssocItem) -> Option<AssocItem> {
|
||||
match item {
|
||||
ast::ModuleItem::FnDef(ast) => self.lower_function(ast).map(Into::into),
|
||||
ast::ModuleItem::TypeAliasDef(ast) => self.lower_type_alias(ast).map(Into::into),
|
||||
ast::ModuleItem::ConstDef(ast) => Some(self.lower_const(ast).into()),
|
||||
ast::ModuleItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
|
||||
_ => None,
|
||||
ast::AssocItem::Fn(ast) => self.lower_function(ast).map(Into::into),
|
||||
ast::AssocItem::TypeAlias(ast) => self.lower_type_alias(ast).map(Into::into),
|
||||
ast::AssocItem::Const(ast) => Some(self.lower_const(ast).into()),
|
||||
ast::AssocItem::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_struct(&mut self, strukt: &ast::StructDef) -> Option<FileItemTreeId<Struct>> {
|
||||
fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
|
||||
let visibility = self.lower_visibility(strukt);
|
||||
let name = strukt.name()?.as_name();
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::Struct, strukt);
|
||||
|
@ -196,7 +194,7 @@ impl Ctx {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_record_fields(&mut self, fields: &ast::RecordFieldDefList) -> IdRange<Field> {
|
||||
fn lower_record_fields(&mut self, fields: &ast::RecordFieldList) -> IdRange<Field> {
|
||||
let start = self.next_field_idx();
|
||||
for field in fields.fields() {
|
||||
if let Some(data) = self.lower_record_field(&field) {
|
||||
|
@ -208,15 +206,15 @@ impl Ctx {
|
|||
IdRange::new(start..end)
|
||||
}
|
||||
|
||||
fn lower_record_field(&mut self, field: &ast::RecordFieldDef) -> Option<Field> {
|
||||
fn lower_record_field(&mut self, field: &ast::RecordField) -> Option<Field> {
|
||||
let name = field.name()?.as_name();
|
||||
let visibility = self.lower_visibility(field);
|
||||
let type_ref = self.lower_type_ref_opt(field.ascribed_type());
|
||||
let type_ref = self.lower_type_ref_opt(field.ty());
|
||||
let res = Field { name, type_ref, visibility };
|
||||
Some(res)
|
||||
}
|
||||
|
||||
fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldDefList) -> IdRange<Field> {
|
||||
fn lower_tuple_fields(&mut self, fields: &ast::TupleFieldList) -> IdRange<Field> {
|
||||
let start = self.next_field_idx();
|
||||
for (i, field) in fields.fields().enumerate() {
|
||||
let data = self.lower_tuple_field(i, &field);
|
||||
|
@ -227,22 +225,20 @@ impl Ctx {
|
|||
IdRange::new(start..end)
|
||||
}
|
||||
|
||||
fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleFieldDef) -> Field {
|
||||
fn lower_tuple_field(&mut self, idx: usize, field: &ast::TupleField) -> Field {
|
||||
let name = Name::new_tuple_field(idx);
|
||||
let visibility = self.lower_visibility(field);
|
||||
let type_ref = self.lower_type_ref_opt(field.type_ref());
|
||||
let type_ref = self.lower_type_ref_opt(field.ty());
|
||||
let res = Field { name, type_ref, visibility };
|
||||
res
|
||||
}
|
||||
|
||||
fn lower_union(&mut self, union: &ast::UnionDef) -> Option<FileItemTreeId<Union>> {
|
||||
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
|
||||
let visibility = self.lower_visibility(union);
|
||||
let name = union.name()?.as_name();
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::Union, union);
|
||||
let fields = match union.record_field_def_list() {
|
||||
Some(record_field_def_list) => {
|
||||
self.lower_fields(&StructKind::Record(record_field_def_list))
|
||||
}
|
||||
let fields = match union.record_field_list() {
|
||||
Some(record_field_list) => self.lower_fields(&StructKind::Record(record_field_list)),
|
||||
None => Fields::Record(IdRange::new(self.next_field_idx()..self.next_field_idx())),
|
||||
};
|
||||
let ast_id = self.source_ast_id_map.ast_id(union);
|
||||
|
@ -250,7 +246,7 @@ impl Ctx {
|
|||
Some(id(self.data().unions.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_enum(&mut self, enum_: &ast::EnumDef) -> Option<FileItemTreeId<Enum>> {
|
||||
fn lower_enum(&mut self, enum_: &ast::Enum) -> Option<FileItemTreeId<Enum>> {
|
||||
let visibility = self.lower_visibility(enum_);
|
||||
let name = enum_.name()?.as_name();
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::Enum, enum_);
|
||||
|
@ -263,7 +259,7 @@ impl Ctx {
|
|||
Some(id(self.data().enums.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_variants(&mut self, variants: &ast::EnumVariantList) -> IdRange<Variant> {
|
||||
fn lower_variants(&mut self, variants: &ast::VariantList) -> IdRange<Variant> {
|
||||
let start = self.next_variant_idx();
|
||||
for variant in variants.variants() {
|
||||
if let Some(data) = self.lower_variant(&variant) {
|
||||
|
@ -275,14 +271,14 @@ impl Ctx {
|
|||
IdRange::new(start..end)
|
||||
}
|
||||
|
||||
fn lower_variant(&mut self, variant: &ast::EnumVariant) -> Option<Variant> {
|
||||
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
|
||||
let name = variant.name()?.as_name();
|
||||
let fields = self.lower_fields(&variant.kind());
|
||||
let res = Variant { name, fields };
|
||||
Some(res)
|
||||
}
|
||||
|
||||
fn lower_function(&mut self, func: &ast::FnDef) -> Option<FileItemTreeId<Function>> {
|
||||
fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> {
|
||||
let visibility = self.lower_visibility(func);
|
||||
let name = func.name()?.as_name();
|
||||
|
||||
|
@ -290,7 +286,7 @@ impl Ctx {
|
|||
let mut has_self_param = false;
|
||||
if let Some(param_list) = func.param_list() {
|
||||
if let Some(self_param) = param_list.self_param() {
|
||||
let self_type = match self_param.ascribed_type() {
|
||||
let self_type = match self_param.ty() {
|
||||
Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
|
||||
None => {
|
||||
let self_type = TypeRef::Path(name![Self].into());
|
||||
|
@ -309,7 +305,7 @@ impl Ctx {
|
|||
has_self_param = true;
|
||||
}
|
||||
for param in param_list.params() {
|
||||
let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ascribed_type());
|
||||
let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
|
||||
params.push(type_ref);
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +317,7 @@ impl Ctx {
|
|||
}
|
||||
}
|
||||
|
||||
let ret_type = match func.ret_type().and_then(|rt| rt.type_ref()) {
|
||||
let ret_type = match func.ret_type().and_then(|rt| rt.ty()) {
|
||||
Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
|
||||
_ => TypeRef::unit(),
|
||||
};
|
||||
|
@ -353,10 +349,10 @@ impl Ctx {
|
|||
|
||||
fn lower_type_alias(
|
||||
&mut self,
|
||||
type_alias: &ast::TypeAliasDef,
|
||||
type_alias: &ast::TypeAlias,
|
||||
) -> Option<FileItemTreeId<TypeAlias>> {
|
||||
let name = type_alias.name()?.as_name();
|
||||
let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it));
|
||||
let type_ref = type_alias.ty().map(|it| self.lower_type_ref(&it));
|
||||
let visibility = self.lower_visibility(type_alias);
|
||||
let bounds = self.lower_type_bounds(type_alias);
|
||||
let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias);
|
||||
|
@ -372,9 +368,9 @@ impl Ctx {
|
|||
Some(id(self.data().type_aliases.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_static(&mut self, static_: &ast::StaticDef) -> Option<FileItemTreeId<Static>> {
|
||||
fn lower_static(&mut self, static_: &ast::Static) -> Option<FileItemTreeId<Static>> {
|
||||
let name = static_.name()?.as_name();
|
||||
let type_ref = self.lower_type_ref_opt(static_.ascribed_type());
|
||||
let type_ref = self.lower_type_ref_opt(static_.ty());
|
||||
let visibility = self.lower_visibility(static_);
|
||||
let mutable = static_.mut_token().is_some();
|
||||
let ast_id = self.source_ast_id_map.ast_id(static_);
|
||||
|
@ -382,9 +378,9 @@ impl Ctx {
|
|||
Some(id(self.data().statics.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_const(&mut self, konst: &ast::ConstDef) -> FileItemTreeId<Const> {
|
||||
fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> {
|
||||
let name = konst.name().map(|it| it.as_name());
|
||||
let type_ref = self.lower_type_ref_opt(konst.ascribed_type());
|
||||
let type_ref = self.lower_type_ref_opt(konst.ty());
|
||||
let visibility = self.lower_visibility(konst);
|
||||
let ast_id = self.source_ast_id_map.ast_id(konst);
|
||||
let res = Const { name, visibility, type_ref, ast_id };
|
||||
|
@ -417,15 +413,15 @@ impl Ctx {
|
|||
Some(id(self.data().mods.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<FileItemTreeId<Trait>> {
|
||||
fn lower_trait(&mut self, trait_def: &ast::Trait) -> Option<FileItemTreeId<Trait>> {
|
||||
let name = trait_def.name()?.as_name();
|
||||
let visibility = self.lower_visibility(trait_def);
|
||||
let generic_params =
|
||||
self.lower_generic_params_and_inner_items(GenericsOwner::Trait(trait_def), trait_def);
|
||||
let auto = trait_def.auto_token().is_some();
|
||||
let items = trait_def.item_list().map(|list| {
|
||||
let items = trait_def.assoc_item_list().map(|list| {
|
||||
self.with_inherited_visibility(visibility, |this| {
|
||||
list.items()
|
||||
list.assoc_items()
|
||||
.filter_map(|item| {
|
||||
let attrs = Attrs::new(&item, &this.hygiene);
|
||||
this.collect_inner_items(item.syntax());
|
||||
|
@ -449,18 +445,18 @@ impl Ctx {
|
|||
Some(id(self.data().traits.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_impl(&mut self, impl_def: &ast::ImplDef) -> Option<FileItemTreeId<Impl>> {
|
||||
fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
|
||||
let generic_params =
|
||||
self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def);
|
||||
let target_trait = impl_def.target_trait().map(|tr| self.lower_type_ref(&tr));
|
||||
let target_type = self.lower_type_ref(&impl_def.target_type()?);
|
||||
let target_trait = impl_def.trait_().map(|tr| self.lower_type_ref(&tr));
|
||||
let target_type = self.lower_type_ref(&impl_def.self_ty()?);
|
||||
let is_negative = impl_def.excl_token().is_some();
|
||||
|
||||
// We cannot use `assoc_items()` here as that does not include macro calls.
|
||||
let items = impl_def
|
||||
.item_list()
|
||||
.assoc_item_list()
|
||||
.into_iter()
|
||||
.flat_map(|it| it.items())
|
||||
.flat_map(|it| it.assoc_items())
|
||||
.filter_map(|item| {
|
||||
self.collect_inner_items(item.syntax());
|
||||
let assoc = self.lower_assoc_item(&item)?;
|
||||
|
@ -474,7 +470,7 @@ impl Ctx {
|
|||
Some(id(self.data().impls.alloc(res)))
|
||||
}
|
||||
|
||||
fn lower_use(&mut self, use_item: &ast::UseItem) -> Vec<FileItemTreeId<Import>> {
|
||||
fn lower_use(&mut self, use_item: &ast::Use) -> Vec<FileItemTreeId<Import>> {
|
||||
// FIXME: cfg_attr
|
||||
let is_prelude = use_item.has_atom_attr("prelude_import");
|
||||
let visibility = self.lower_visibility(use_item);
|
||||
|
@ -503,10 +499,10 @@ impl Ctx {
|
|||
|
||||
fn lower_extern_crate(
|
||||
&mut self,
|
||||
extern_crate: &ast::ExternCrateItem,
|
||||
extern_crate: &ast::ExternCrate,
|
||||
) -> Option<FileItemTreeId<ExternCrate>> {
|
||||
let path = ModPath::from_name_ref(&extern_crate.name_ref()?);
|
||||
let alias = extern_crate.alias().map(|a| {
|
||||
let alias = extern_crate.rename().map(|a| {
|
||||
a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
|
||||
});
|
||||
let visibility = self.lower_visibility(extern_crate);
|
||||
|
@ -552,15 +548,16 @@ impl Ctx {
|
|||
self.collect_inner_items(item.syntax());
|
||||
let attrs = Attrs::new(&item, &self.hygiene);
|
||||
let id: ModItem = match item {
|
||||
ast::ExternItem::FnDef(ast) => {
|
||||
ast::ExternItem::Fn(ast) => {
|
||||
let func = self.lower_function(&ast)?;
|
||||
self.data().functions[func.index].is_unsafe = true;
|
||||
func.into()
|
||||
}
|
||||
ast::ExternItem::StaticDef(ast) => {
|
||||
ast::ExternItem::Static(ast) => {
|
||||
let statik = self.lower_static(&ast)?;
|
||||
statik.into()
|
||||
}
|
||||
ast::ExternItem::MacroCall(_) => return None,
|
||||
};
|
||||
self.add_attrs(id.into(), attrs);
|
||||
Some(id)
|
||||
|
@ -573,10 +570,10 @@ impl Ctx {
|
|||
fn lower_generic_params_and_inner_items(
|
||||
&mut self,
|
||||
owner: GenericsOwner<'_>,
|
||||
node: &impl ast::TypeParamsOwner,
|
||||
node: &impl ast::GenericParamsOwner,
|
||||
) -> GenericParamsId {
|
||||
// Generics are part of item headers and may contain inner items we need to collect.
|
||||
if let Some(params) = node.type_param_list() {
|
||||
if let Some(params) = node.generic_param_list() {
|
||||
self.collect_inner_items(params.syntax());
|
||||
}
|
||||
if let Some(clause) = node.where_clause() {
|
||||
|
@ -589,7 +586,7 @@ impl Ctx {
|
|||
fn lower_generic_params(
|
||||
&mut self,
|
||||
owner: GenericsOwner<'_>,
|
||||
node: &impl ast::TypeParamsOwner,
|
||||
node: &impl ast::GenericParamsOwner,
|
||||
) -> GenericParamsId {
|
||||
let mut sm = &mut ArenaMap::default();
|
||||
let mut generics = GenericParams::default();
|
||||
|
@ -651,10 +648,10 @@ impl Ctx {
|
|||
self.data().vis.alloc(vis)
|
||||
}
|
||||
|
||||
fn lower_type_ref(&self, type_ref: &ast::TypeRef) -> TypeRef {
|
||||
fn lower_type_ref(&self, type_ref: &ast::Type) -> TypeRef {
|
||||
TypeRef::from_ast(&self.body_ctx, type_ref.clone())
|
||||
}
|
||||
fn lower_type_ref_opt(&self, type_ref: Option<ast::TypeRef>) -> TypeRef {
|
||||
fn lower_type_ref_opt(&self, type_ref: Option<ast::Type>) -> TypeRef {
|
||||
type_ref.map(|ty| self.lower_type_ref(&ty)).unwrap_or(TypeRef::Error)
|
||||
}
|
||||
|
||||
|
@ -702,7 +699,7 @@ enum GenericsOwner<'a> {
|
|||
Enum,
|
||||
Union,
|
||||
/// The `TraitDef` is needed to fill the source map for the implicit `Self` parameter.
|
||||
Trait(&'a ast::TraitDef),
|
||||
Trait(&'a ast::Trait),
|
||||
TypeAlias,
|
||||
Impl,
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ fn test_inner_items(ra_fixture: &str) {
|
|||
let mut outer_items = FxHashSet::default();
|
||||
let mut worklist = tree.top_level_items().to_vec();
|
||||
while let Some(item) = worklist.pop() {
|
||||
let node: ast::ModuleItem = match item {
|
||||
let node: ast::Item = match item {
|
||||
ModItem::Import(it) => tree.source(&db, InFile::new(file_id, it)).into(),
|
||||
ModItem::ExternCrate(it) => tree.source(&db, InFile::new(file_id, it)).into(),
|
||||
ModItem::Function(it) => tree.source(&db, InFile::new(file_id, it)).into(),
|
||||
|
@ -53,7 +53,7 @@ fn test_inner_items(ra_fixture: &str) {
|
|||
|
||||
// Now descend the root node and check that all `ast::ModuleItem`s are either recorded above, or
|
||||
// registered as inner items.
|
||||
for item in root.descendants().skip(1).filter_map(ast::ModuleItem::cast) {
|
||||
for item in root.descendants().skip(1).filter_map(ast::Item::cast) {
|
||||
if outer_items.contains(&item) {
|
||||
continue;
|
||||
}
|
||||
|
@ -228,31 +228,31 @@ fn smoke() {
|
|||
|
||||
top-level items:
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }]
|
||||
Import { path: ModPath { kind: Plain, segments: [Name(Text("a"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: false, is_prelude: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::UseItem>(0) }
|
||||
Import { path: ModPath { kind: Plain, segments: [Name(Text("a"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: false, is_prelude: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Use>(0) }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_on_use"))] }, input: None }]) }]
|
||||
Import { path: ModPath { kind: Plain, segments: [Name(Text("b"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: true, is_prelude: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::UseItem>(0) }
|
||||
Import { path: ModPath { kind: Plain, segments: [Name(Text("b"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_glob: true, is_prelude: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Use>(0) }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("ext_crate"))] }, input: None }]) }]
|
||||
ExternCrate { path: ModPath { kind: Plain, segments: [Name(Text("krate"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_macro_use: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ExternCrateItem>(1) }
|
||||
ExternCrate { path: ModPath { kind: Plain, segments: [Name(Text("krate"))] }, alias: None, visibility: RawVisibilityId("pub(self)"), is_macro_use: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ExternCrate>(1) }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_trait"))] }, input: None }]) }]
|
||||
Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [TypeAlias(Idx::<TypeAlias>(0)), Const(Idx::<Const>(0)), Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TraitDef>(2) }
|
||||
Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [TypeAlias(Idx::<TypeAlias>(0)), Const(Idx::<Const>(0)), Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Trait>(2) }
|
||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_ty"))] }, input: None }]) }]
|
||||
> TypeAlias { name: Name(Text("AssocTy")), visibility: RawVisibilityId("pub(self)"), bounds: [Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Tr"))] }, generic_args: [Some(GenericArgs { args: [Type(Tuple([]))], has_self_type: false, bindings: [] })] })], generic_params: GenericParamsId(4294967295), type_ref: None, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TypeAliasDef>(8) }
|
||||
> TypeAlias { name: Name(Text("AssocTy")), visibility: RawVisibilityId("pub(self)"), bounds: [Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Tr"))] }, generic_args: [Some(GenericArgs { args: [Type(Tuple([]))], has_self_type: false, bindings: [] })] })], generic_params: GenericParamsId(4294967295), type_ref: None, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TypeAlias>(8) }
|
||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_const"))] }, input: None }]) }]
|
||||
> Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ConstDef>(9) }
|
||||
> Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Const>(9) }
|
||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_method"))] }, input: None }]) }]
|
||||
> Function { name: Name(Text("method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Shared)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(10) }
|
||||
> Function { name: Name(Text("method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Shared)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(10) }
|
||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_dfl_method"))] }, input: None }]) }]
|
||||
> Function { name: Name(Text("dfl_method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Mut)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(11) }
|
||||
> Function { name: Name(Text("dfl_method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Mut)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(11) }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct0"))] }, input: None }]) }]
|
||||
Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::StructDef>(3), kind: Unit }
|
||||
Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Struct>(3), kind: Unit }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct1"))] }, input: None }]) }]
|
||||
Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(IdRange::<ra_hir_def::item_tree::Field>(0..1)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::StructDef>(4), kind: Tuple }
|
||||
Struct { name: Name(Text("Struct1")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(2), fields: Tuple(IdRange::<ra_hir_def::item_tree::Field>(0..1)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Struct>(4), kind: Tuple }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct2"))] }, input: None }]) }]
|
||||
Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(IdRange::<ra_hir_def::item_tree::Field>(1..2)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::StructDef>(5), kind: Record }
|
||||
Struct { name: Name(Text("Struct2")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(3), fields: Record(IdRange::<ra_hir_def::item_tree::Field>(1..2)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Struct>(5), kind: Record }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("en"))] }, input: None }]) }]
|
||||
Enum { name: Name(Text("En")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), variants: IdRange::<ra_hir_def::item_tree::Variant>(0..1), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::EnumDef>(6) }
|
||||
Enum { name: Name(Text("En")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), variants: IdRange::<ra_hir_def::item_tree::Variant>(0..1), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Enum>(6) }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("un"))] }, input: None }]) }]
|
||||
Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(IdRange::<ra_hir_def::item_tree::Field>(3..4)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::UnionDef>(7) }
|
||||
Union { name: Name(Text("Un")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), fields: Record(IdRange::<ra_hir_def::item_tree::Field>(3..4)), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Union>(7) }
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
@ -274,13 +274,13 @@ fn simple_inner_items() {
|
|||
inner attrs: Attrs { entries: None }
|
||||
|
||||
top-level items:
|
||||
Impl { generic_params: GenericParamsId(0), target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
|
||||
> Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||
Impl { generic_params: GenericParamsId(0), target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Impl>(0) }
|
||||
> Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) }
|
||||
|
||||
inner items:
|
||||
|
||||
for AST FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(2):
|
||||
Function { name: Name(Text("end")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
||||
for AST FileAstId::<ra_syntax::ast::generated::nodes::Item>(2):
|
||||
Function { name: Name(Text("end")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(2) }
|
||||
|
||||
"#]],
|
||||
);
|
||||
|
@ -303,9 +303,9 @@ fn extern_attrs() {
|
|||
|
||||
top-level items:
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }]
|
||||
Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||
Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) }
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }]
|
||||
Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
||||
Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(2) }
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
@ -327,11 +327,11 @@ fn trait_attrs() {
|
|||
|
||||
top-level items:
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("trait_attr"))] }, input: None }]) }]
|
||||
Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TraitDef>(0) }
|
||||
Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Trait>(0) }
|
||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }]
|
||||
> Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||
> Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) }
|
||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }]
|
||||
> Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
||||
> Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(2) }
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
@ -353,11 +353,11 @@ fn impl_attrs() {
|
|||
|
||||
top-level items:
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("impl_attr"))] }, input: None }]) }]
|
||||
Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Ty"))] }, generic_args: [None] }), is_negative: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
|
||||
Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Ty"))] }, generic_args: [None] }), is_negative: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Impl>(0) }
|
||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }]
|
||||
> Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||
> Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) }
|
||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }]
|
||||
> Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
||||
> Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(2) }
|
||||
"##]],
|
||||
);
|
||||
}
|
||||
|
@ -408,13 +408,13 @@ fn inner_item_attrs() {
|
|||
inner attrs: Attrs { entries: None }
|
||||
|
||||
top-level items:
|
||||
Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(0) }
|
||||
Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(0) }
|
||||
|
||||
inner items:
|
||||
|
||||
for AST FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(1):
|
||||
for AST FileAstId::<ra_syntax::ast::generated::nodes::Item>(1):
|
||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_inner"))] }, input: None }]) }]
|
||||
Function { name: Name(Text("inner")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||
Function { name: Name(Text("inner")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Fn>(1) }
|
||||
|
||||
"##]],
|
||||
);
|
||||
|
@ -432,7 +432,7 @@ fn assoc_item_macros() {
|
|||
inner attrs: Attrs { entries: None }
|
||||
|
||||
top-level items:
|
||||
Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("S"))] }, generic_args: [None] }), is_negative: false, items: [MacroCall(Idx::<MacroCall>(0))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
|
||||
Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("S"))] }, generic_args: [None] }), is_negative: false, items: [MacroCall(Idx::<MacroCall>(0))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::Impl>(0) }
|
||||
> MacroCall { name: None, path: ModPath { kind: Plain, segments: [Name(Text("items"))] }, is_export: false, is_local_inner: false, is_builtin: false, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::MacroCall>(1) }
|
||||
"#]],
|
||||
);
|
||||
|
|
|
@ -14,19 +14,19 @@ use crate::{
|
|||
|
||||
pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
|
||||
|
||||
pub const FUNCTION: Key<ast::FnDef, FunctionId> = Key::new();
|
||||
pub const CONST: Key<ast::ConstDef, ConstId> = Key::new();
|
||||
pub const STATIC: Key<ast::StaticDef, StaticId> = Key::new();
|
||||
pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new();
|
||||
pub const IMPL: Key<ast::ImplDef, ImplId> = Key::new();
|
||||
pub const TRAIT: Key<ast::TraitDef, TraitId> = Key::new();
|
||||
pub const STRUCT: Key<ast::StructDef, StructId> = Key::new();
|
||||
pub const UNION: Key<ast::UnionDef, UnionId> = Key::new();
|
||||
pub const ENUM: Key<ast::EnumDef, EnumId> = Key::new();
|
||||
pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new();
|
||||
pub const CONST: Key<ast::Const, ConstId> = Key::new();
|
||||
pub const STATIC: Key<ast::Static, StaticId> = Key::new();
|
||||
pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new();
|
||||
pub const IMPL: Key<ast::Impl, ImplId> = Key::new();
|
||||
pub const TRAIT: Key<ast::Trait, TraitId> = Key::new();
|
||||
pub const STRUCT: Key<ast::Struct, StructId> = Key::new();
|
||||
pub const UNION: Key<ast::Union, UnionId> = Key::new();
|
||||
pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
|
||||
|
||||
pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new();
|
||||
pub const TUPLE_FIELD: Key<ast::TupleFieldDef, FieldId> = Key::new();
|
||||
pub const RECORD_FIELD: Key<ast::RecordFieldDef, FieldId> = Key::new();
|
||||
pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
|
||||
pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
|
||||
pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
|
||||
pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
|
||||
|
||||
pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
|
||||
|
|
|
@ -521,7 +521,7 @@ impl AsMacroCall for AstIdWithPath<ast::MacroCall> {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsMacroCall for AstIdWithPath<ast::ModuleItem> {
|
||||
impl AsMacroCall for AstIdWithPath<ast::Item> {
|
||||
fn as_call_id(
|
||||
&self,
|
||||
db: &dyn db::DefDatabase,
|
||||
|
|
|
@ -170,7 +170,7 @@ struct MacroDirective {
|
|||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct DeriveDirective {
|
||||
module_id: LocalModuleId,
|
||||
ast_id: AstIdWithPath<ast::ModuleItem>,
|
||||
ast_id: AstIdWithPath<ast::Item>,
|
||||
}
|
||||
|
||||
struct DefData<'a> {
|
||||
|
@ -1100,7 +1100,7 @@ impl ModCollector<'_, '_> {
|
|||
res
|
||||
}
|
||||
|
||||
fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::ModuleItem>) {
|
||||
fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) {
|
||||
for derive_subtree in attrs.by_key("derive").tt_values() {
|
||||
// for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
|
||||
for tt in &derive_subtree.token_trees {
|
||||
|
|
|
@ -67,7 +67,7 @@ impl ModPath {
|
|||
|
||||
/// Calls `cb` with all paths, represented by this use item.
|
||||
pub(crate) fn expand_use_item(
|
||||
item_src: InFile<ast::UseItem>,
|
||||
item_src: InFile<ast::Use>,
|
||||
hygiene: &Hygiene,
|
||||
mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<ImportAlias>),
|
||||
) {
|
||||
|
@ -258,7 +258,7 @@ impl<'a> PathSegments<'a> {
|
|||
}
|
||||
|
||||
impl GenericArgs {
|
||||
pub(crate) fn from_ast(lower_ctx: &LowerCtx, node: ast::TypeArgList) -> Option<GenericArgs> {
|
||||
pub(crate) fn from_ast(lower_ctx: &LowerCtx, node: ast::GenericArgList) -> Option<GenericArgs> {
|
||||
lower::lower_generic_args(lower_ctx, node)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use hir_expand::{
|
|||
hygiene::Hygiene,
|
||||
name::{name, AsName},
|
||||
};
|
||||
use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner};
|
||||
use ra_syntax::ast::{self, AstNode, TypeBoundsOwner};
|
||||
|
||||
use super::AssociatedTypeBinding;
|
||||
use crate::{
|
||||
|
@ -41,7 +41,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
|
|||
match hygiene.name_ref_to_name(name_ref) {
|
||||
Either::Left(name) => {
|
||||
let args = segment
|
||||
.type_arg_list()
|
||||
.generic_arg_list()
|
||||
.and_then(|it| lower_generic_args(&ctx, it))
|
||||
.or_else(|| {
|
||||
lower_generic_args_from_fn_path(
|
||||
|
@ -148,33 +148,37 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
|
|||
|
||||
pub(super) fn lower_generic_args(
|
||||
lower_ctx: &LowerCtx,
|
||||
node: ast::TypeArgList,
|
||||
node: ast::GenericArgList,
|
||||
) -> Option<GenericArgs> {
|
||||
let mut args = Vec::new();
|
||||
for type_arg in node.type_args() {
|
||||
let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.type_ref());
|
||||
args.push(GenericArg::Type(type_ref));
|
||||
}
|
||||
// lifetimes ignored for now
|
||||
let mut bindings = Vec::new();
|
||||
for assoc_type_arg in node.assoc_type_args() {
|
||||
let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg;
|
||||
if let Some(name_ref) = assoc_type_arg.name_ref() {
|
||||
let name = name_ref.as_name();
|
||||
let type_ref = assoc_type_arg.type_ref().map(|it| TypeRef::from_ast(lower_ctx, it));
|
||||
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
|
||||
l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
bindings.push(AssociatedTypeBinding { name, type_ref, bounds });
|
||||
for generic_arg in node.generic_args() {
|
||||
match generic_arg {
|
||||
ast::GenericArg::TypeArg(type_arg) => {
|
||||
let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty());
|
||||
args.push(GenericArg::Type(type_ref));
|
||||
}
|
||||
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
|
||||
if let Some(name_ref) = assoc_type_arg.name_ref() {
|
||||
let name = name_ref.as_name();
|
||||
let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
|
||||
let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
|
||||
l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
bindings.push(AssociatedTypeBinding { name, type_ref, bounds });
|
||||
}
|
||||
}
|
||||
// Lifetimes and constants are ignored for now.
|
||||
ast::GenericArg::LifetimeArg(_) | ast::GenericArg::ConstArg(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
if args.is_empty() && bindings.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(GenericArgs { args, has_self_type: false, bindings })
|
||||
return None;
|
||||
}
|
||||
Some(GenericArgs { args, has_self_type: false, bindings })
|
||||
}
|
||||
|
||||
/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
|
||||
|
@ -189,14 +193,14 @@ fn lower_generic_args_from_fn_path(
|
|||
if let Some(params) = params {
|
||||
let mut param_types = Vec::new();
|
||||
for param in params.params() {
|
||||
let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
|
||||
let type_ref = TypeRef::from_ast_opt(&ctx, param.ty());
|
||||
param_types.push(type_ref);
|
||||
}
|
||||
let arg = GenericArg::Type(TypeRef::Tuple(param_types));
|
||||
args.push(arg);
|
||||
}
|
||||
if let Some(ret_type) = ret_type {
|
||||
let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.type_ref());
|
||||
let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.ty());
|
||||
bindings.push(AssociatedTypeBinding {
|
||||
name: name![Output],
|
||||
type_ref: Some(type_ref),
|
||||
|
|
|
@ -31,7 +31,7 @@ pub(crate) fn lower_use_tree(
|
|||
lower_use_tree(prefix.clone(), child_tree, hygiene, cb);
|
||||
}
|
||||
} else {
|
||||
let alias = tree.alias().map(|a| {
|
||||
let alias = tree.rename().map(|a| {
|
||||
a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
|
||||
});
|
||||
let is_glob = tree.star_token().is_some();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! HIR for references to types. Paths in these are not yet resolved. They can
|
||||
//! be directly created from an ast::TypeRef, without further queries.
|
||||
|
||||
use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner};
|
||||
use ra_syntax::ast::{self};
|
||||
|
||||
use crate::{body::LowerCtx, path::Path};
|
||||
|
||||
|
@ -80,14 +79,14 @@ pub enum TypeBound {
|
|||
|
||||
impl TypeRef {
|
||||
/// Converts an `ast::TypeRef` to a `hir::TypeRef`.
|
||||
pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeRef) -> Self {
|
||||
pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Self {
|
||||
match node {
|
||||
ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
|
||||
ast::TypeRef::TupleType(inner) => {
|
||||
ast::Type::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()),
|
||||
ast::Type::TupleType(inner) => {
|
||||
TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect())
|
||||
}
|
||||
ast::TypeRef::NeverType(..) => TypeRef::Never,
|
||||
ast::TypeRef::PathType(inner) => {
|
||||
ast::Type::NeverType(..) => TypeRef::Never,
|
||||
ast::Type::PathType(inner) => {
|
||||
// FIXME: Use `Path::from_src`
|
||||
inner
|
||||
.path()
|
||||
|
@ -95,27 +94,27 @@ impl TypeRef {
|
|||
.map(TypeRef::Path)
|
||||
.unwrap_or(TypeRef::Error)
|
||||
}
|
||||
ast::TypeRef::PointerType(inner) => {
|
||||
let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
|
||||
ast::Type::PtrType(inner) => {
|
||||
let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty());
|
||||
let mutability = Mutability::from_mutable(inner.mut_token().is_some());
|
||||
TypeRef::RawPtr(Box::new(inner_ty), mutability)
|
||||
}
|
||||
ast::TypeRef::ArrayType(inner) => {
|
||||
TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
|
||||
ast::Type::ArrayType(inner) => {
|
||||
TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())))
|
||||
}
|
||||
ast::TypeRef::SliceType(inner) => {
|
||||
TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
|
||||
ast::Type::SliceType(inner) => {
|
||||
TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.ty())))
|
||||
}
|
||||
ast::TypeRef::ReferenceType(inner) => {
|
||||
let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
|
||||
ast::Type::RefType(inner) => {
|
||||
let inner_ty = TypeRef::from_ast_opt(&ctx, inner.ty());
|
||||
let mutability = Mutability::from_mutable(inner.mut_token().is_some());
|
||||
TypeRef::Reference(Box::new(inner_ty), mutability)
|
||||
}
|
||||
ast::TypeRef::PlaceholderType(_inner) => TypeRef::Placeholder,
|
||||
ast::TypeRef::FnPointerType(inner) => {
|
||||
ast::Type::InferType(_inner) => TypeRef::Placeholder,
|
||||
ast::Type::FnPtrType(inner) => {
|
||||
let ret_ty = inner
|
||||
.ret_type()
|
||||
.and_then(|rt| rt.type_ref())
|
||||
.and_then(|rt| rt.ty())
|
||||
.map(|it| TypeRef::from_ast(ctx, it))
|
||||
.unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
|
||||
let mut is_varargs = false;
|
||||
|
@ -124,10 +123,7 @@ impl TypeRef {
|
|||
is_varargs = param.dotdotdot_token().is_some();
|
||||
}
|
||||
|
||||
pl.params()
|
||||
.map(|p| p.ascribed_type())
|
||||
.map(|it| TypeRef::from_ast_opt(&ctx, it))
|
||||
.collect()
|
||||
pl.params().map(|p| p.ty()).map(|it| TypeRef::from_ast_opt(&ctx, it)).collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
@ -135,17 +131,17 @@ impl TypeRef {
|
|||
TypeRef::Fn(params, is_varargs)
|
||||
}
|
||||
// for types are close enough for our purposes to the inner type for now...
|
||||
ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
|
||||
ast::TypeRef::ImplTraitType(inner) => {
|
||||
ast::Type::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.ty()),
|
||||
ast::Type::ImplTraitType(inner) => {
|
||||
TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
|
||||
}
|
||||
ast::TypeRef::DynTraitType(inner) => {
|
||||
ast::Type::DynTraitType(inner) => {
|
||||
TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast_opt(ctx: &LowerCtx, node: Option<ast::TypeRef>) -> Self {
|
||||
pub(crate) fn from_ast_opt(ctx: &LowerCtx, node: Option<ast::Type>) -> Self {
|
||||
if let Some(node) = node {
|
||||
TypeRef::from_ast(ctx, node)
|
||||
} else {
|
||||
|
|
|
@ -73,7 +73,7 @@ impl AstIdMap {
|
|||
// change parent's id. This means that, say, adding a new function to a
|
||||
// trait does not change ids of top-level items, which helps caching.
|
||||
bfs(node, |it| {
|
||||
if let Some(module_item) = ast::ModuleItem::cast(it) {
|
||||
if let Some(module_item) = ast::Item::cast(it) {
|
||||
res.alloc(module_item.syntax());
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ use log::debug;
|
|||
|
||||
use ra_parser::FragmentKind;
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode, ModuleItemOwner, NameOwner, TypeParamsOwner},
|
||||
ast::{self, AstNode, GenericParamsOwner, ModuleItemOwner, NameOwner},
|
||||
match_ast,
|
||||
};
|
||||
|
||||
|
@ -72,9 +72,9 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, mbe::ExpandError> {
|
|||
let node = item.syntax();
|
||||
let (name, params) = match_ast! {
|
||||
match node {
|
||||
ast::StructDef(it) => (it.name(), it.type_param_list()),
|
||||
ast::EnumDef(it) => (it.name(), it.type_param_list()),
|
||||
ast::UnionDef(it) => (it.name(), it.type_param_list()),
|
||||
ast::Struct(it) => (it.name(), it.generic_param_list()),
|
||||
ast::Enum(it) => (it.name(), it.generic_param_list()),
|
||||
ast::Union(it) => (it.name(), it.generic_param_list()),
|
||||
_ => {
|
||||
debug!("unexpected node is {:?}", node);
|
||||
return Err(mbe::ExpandError::ConversionError)
|
||||
|
@ -276,7 +276,7 @@ mod tests {
|
|||
let file_id = file_pos.file_id;
|
||||
let parsed = db.parse(file_id);
|
||||
let items: Vec<_> =
|
||||
parsed.syntax_node().descendants().filter_map(ast::ModuleItem::cast).collect();
|
||||
parsed.syntax_node().descendants().filter_map(ast::Item::cast).collect();
|
||||
|
||||
let ast_id_map = db.ast_id_map(file_id.into());
|
||||
|
||||
|
|
|
@ -379,14 +379,14 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
|
|||
|
||||
FOR_EXPR => FragmentKind::Expr,
|
||||
PATH_EXPR => FragmentKind::Expr,
|
||||
LAMBDA_EXPR => FragmentKind::Expr,
|
||||
CLOSURE_EXPR => FragmentKind::Expr,
|
||||
CONDITION => FragmentKind::Expr,
|
||||
BREAK_EXPR => FragmentKind::Expr,
|
||||
RETURN_EXPR => FragmentKind::Expr,
|
||||
MATCH_EXPR => FragmentKind::Expr,
|
||||
MATCH_ARM => FragmentKind::Expr,
|
||||
MATCH_GUARD => FragmentKind::Expr,
|
||||
RECORD_FIELD => FragmentKind::Expr,
|
||||
RECORD_EXPR_FIELD => FragmentKind::Expr,
|
||||
CALL_EXPR => FragmentKind::Expr,
|
||||
INDEX_EXPR => FragmentKind::Expr,
|
||||
METHOD_CALL_EXPR => FragmentKind::Expr,
|
||||
|
|
|
@ -159,7 +159,7 @@ impl HirFileId {
|
|||
}
|
||||
|
||||
/// Indicate it is macro file generated for builtin derive
|
||||
pub fn is_builtin_derive(&self, db: &dyn db::AstDatabase) -> Option<InFile<ast::ModuleItem>> {
|
||||
pub fn is_builtin_derive(&self, db: &dyn db::AstDatabase) -> Option<InFile<ast::Item>> {
|
||||
match self.0 {
|
||||
HirFileIdRepr::FileId(_) => None,
|
||||
HirFileIdRepr::MacroFile(macro_file) => {
|
||||
|
@ -174,7 +174,7 @@ impl HirFileId {
|
|||
MacroDefKind::BuiltInDerive(_) => loc.kind.node(db),
|
||||
_ => return None,
|
||||
};
|
||||
Some(item.with_value(ast::ModuleItem::cast(item.value.clone())?))
|
||||
Some(item.with_value(ast::Item::cast(item.value.clone())?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ pub struct MacroCallLoc {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum MacroCallKind {
|
||||
FnLike(AstId<ast::MacroCall>),
|
||||
Attr(AstId<ast::ModuleItem>, String),
|
||||
Attr(AstId<ast::Item>, String),
|
||||
}
|
||||
|
||||
impl MacroCallKind {
|
||||
|
|
|
@ -101,7 +101,7 @@ fn remove_derive_attrs(tt: &tt::Subtree) -> Option<tt::Subtree> {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use test_utils::assert_eq_text;
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ test_utils = { path = "../test_utils" }
|
|||
|
||||
scoped-tls = "1"
|
||||
|
||||
chalk-solve = { version = "0.18.0" }
|
||||
chalk-ir = { version = "0.18.0" }
|
||||
chalk-recursive = { version = "0.18.0" }
|
||||
chalk-solve = { version = "0.21.0" }
|
||||
chalk-ir = { version = "0.21.0" }
|
||||
chalk-recursive = { version = "0.21.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
expect = { path = "../expect" }
|
||||
|
|
|
@ -29,7 +29,7 @@ pub fn validate_body(db: &dyn HirDatabase, owner: DefWithBodyId, sink: &mut Diag
|
|||
#[derive(Debug)]
|
||||
pub struct NoSuchField {
|
||||
pub file: HirFileId,
|
||||
pub field: AstPtr<ast::RecordField>,
|
||||
pub field: AstPtr<ast::RecordExprField>,
|
||||
}
|
||||
|
||||
impl Diagnostic for NoSuchField {
|
||||
|
@ -47,19 +47,19 @@ impl Diagnostic for NoSuchField {
|
|||
}
|
||||
|
||||
impl AstDiagnostic for NoSuchField {
|
||||
type AST = ast::RecordField;
|
||||
type AST = ast::RecordExprField;
|
||||
|
||||
fn ast(&self, db: &dyn AstDatabase) -> Self::AST {
|
||||
let root = db.parse_or_expand(self.source().file_id).unwrap();
|
||||
let node = self.source().value.to_node(&root);
|
||||
ast::RecordField::cast(node).unwrap()
|
||||
ast::RecordExprField::cast(node).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MissingFields {
|
||||
pub file: HirFileId,
|
||||
pub field_list: AstPtr<ast::RecordFieldList>,
|
||||
pub field_list: AstPtr<ast::RecordExprFieldList>,
|
||||
pub missed_fields: Vec<Name>,
|
||||
}
|
||||
|
||||
|
@ -80,19 +80,19 @@ impl Diagnostic for MissingFields {
|
|||
}
|
||||
|
||||
impl AstDiagnostic for MissingFields {
|
||||
type AST = ast::RecordFieldList;
|
||||
type AST = ast::RecordExprFieldList;
|
||||
|
||||
fn ast(&self, db: &dyn AstDatabase) -> Self::AST {
|
||||
let root = db.parse_or_expand(self.source().file_id).unwrap();
|
||||
let node = self.source().value.to_node(&root);
|
||||
ast::RecordFieldList::cast(node).unwrap()
|
||||
ast::RecordExprFieldList::cast(node).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MissingPatFields {
|
||||
pub file: HirFileId,
|
||||
pub field_list: AstPtr<ast::RecordFieldPatList>,
|
||||
pub field_list: AstPtr<ast::RecordPatFieldList>,
|
||||
pub missed_fields: Vec<Name>,
|
||||
}
|
||||
|
||||
|
|
|
@ -100,8 +100,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
|||
|
||||
if let Ok(source_ptr) = source_map.expr_syntax(id) {
|
||||
let root = source_ptr.file_syntax(db.upcast());
|
||||
if let ast::Expr::RecordLit(record_lit) = &source_ptr.value.to_node(&root) {
|
||||
if let Some(field_list) = record_lit.record_field_list() {
|
||||
if let ast::Expr::RecordExpr(record_lit) = &source_ptr.value.to_node(&root) {
|
||||
if let Some(field_list) = record_lit.record_expr_field_list() {
|
||||
let variant_data = variant_data(db.upcast(), variant_def);
|
||||
let missed_fields = missed_fields
|
||||
.into_iter()
|
||||
|
@ -131,7 +131,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
|||
if let Some(expr) = source_ptr.value.as_ref().left() {
|
||||
let root = source_ptr.file_syntax(db.upcast());
|
||||
if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
|
||||
if let Some(field_list) = record_pat.record_field_pat_list() {
|
||||
if let Some(field_list) = record_pat.record_pat_field_list() {
|
||||
let variant_data = variant_data(db.upcast(), variant_def);
|
||||
let missed_fields = missed_fields
|
||||
.into_iter()
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::sync::Arc;
|
|||
use hir_def::{
|
||||
body::Body,
|
||||
expr::{Expr, ExprId, UnaryOp},
|
||||
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
|
||||
DefWithBodyId,
|
||||
};
|
||||
use hir_expand::diagnostics::DiagnosticSink;
|
||||
|
@ -70,7 +71,7 @@ pub fn unsafe_expressions(
|
|||
) -> Vec<UnsafeExpr> {
|
||||
let mut unsafe_exprs = vec![];
|
||||
let body = db.body(def);
|
||||
walk_unsafe(&mut unsafe_exprs, db, infer, &body, body.body_expr, false);
|
||||
walk_unsafe(&mut unsafe_exprs, db, infer, def, &body, body.body_expr, false);
|
||||
|
||||
unsafe_exprs
|
||||
}
|
||||
|
@ -79,6 +80,7 @@ fn walk_unsafe(
|
|||
unsafe_exprs: &mut Vec<UnsafeExpr>,
|
||||
db: &dyn HirDatabase,
|
||||
infer: &InferenceResult,
|
||||
def: DefWithBodyId,
|
||||
body: &Body,
|
||||
current: ExprId,
|
||||
inside_unsafe_block: bool,
|
||||
|
@ -97,6 +99,15 @@ fn walk_unsafe(
|
|||
}
|
||||
}
|
||||
}
|
||||
Expr::Path(path) => {
|
||||
let resolver = resolver_for_expr(db.upcast(), def, current);
|
||||
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path.mod_path());
|
||||
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial {
|
||||
if db.static_data(id).mutable {
|
||||
unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::MethodCall { .. } => {
|
||||
if infer
|
||||
.method_resolution(current)
|
||||
|
@ -112,13 +123,13 @@ fn walk_unsafe(
|
|||
}
|
||||
}
|
||||
Expr::Unsafe { body: child } => {
|
||||
return walk_unsafe(unsafe_exprs, db, infer, body, *child, true);
|
||||
return walk_unsafe(unsafe_exprs, db, infer, def, body, *child, true);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
expr.walk_child_exprs(|child| {
|
||||
walk_unsafe(unsafe_exprs, db, infer, body, child, inside_unsafe_block);
|
||||
walk_unsafe(unsafe_exprs, db, infer, def, body, child, inside_unsafe_block);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -167,6 +178,27 @@ fn main() {
|
|||
HasUnsafe.unsafe_fn();
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_unsafe_diagnostic_with_static_mut() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
struct Ty {
|
||||
a: u8,
|
||||
}
|
||||
|
||||
static mut static_mut: Ty = Ty { a: 0 };
|
||||
|
||||
fn main() {
|
||||
let x = static_mut.a;
|
||||
//^^^^^^^^^^ This operation is unsafe and requires an unsafe function or block
|
||||
unsafe {
|
||||
let x = static_mut.a;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -440,6 +440,12 @@ impl<'a> InferenceContext<'a> {
|
|||
let ty = self.insert_type_vars(ty.subst(&substs));
|
||||
forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
|
||||
}
|
||||
TypeNs::AdtId(AdtId::UnionId(u)) => {
|
||||
let substs = Ty::substs_from_path(&ctx, path, u.into(), true);
|
||||
let ty = self.db.ty(u.into());
|
||||
let ty = self.insert_type_vars(ty.subst(&substs));
|
||||
forbid_unresolved_segments((ty, Some(u.into())), unresolved)
|
||||
}
|
||||
TypeNs::EnumVariantId(var) => {
|
||||
let substs = Ty::substs_from_path(&ctx, path, var.into(), true);
|
||||
let ty = self.db.ty(var.parent.into());
|
||||
|
@ -490,10 +496,7 @@ impl<'a> InferenceContext<'a> {
|
|||
// FIXME potentially resolve assoc type
|
||||
(Ty::Unknown, None)
|
||||
}
|
||||
TypeNs::AdtId(AdtId::EnumId(_))
|
||||
| TypeNs::AdtId(AdtId::UnionId(_))
|
||||
| TypeNs::BuiltinType(_)
|
||||
| TypeNs::TraitId(_) => {
|
||||
TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => {
|
||||
// FIXME diagnostic
|
||||
(Ty::Unknown, None)
|
||||
}
|
||||
|
|
|
@ -518,6 +518,7 @@ impl Ty {
|
|||
let (segment, generic_def) = match resolved {
|
||||
ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
|
||||
ValueTyDefId::StructId(it) => (last, Some(it.into())),
|
||||
ValueTyDefId::UnionId(it) => (last, Some(it.into())),
|
||||
ValueTyDefId::ConstId(it) => (last, Some(it.into())),
|
||||
ValueTyDefId::StaticId(_) => (last, None),
|
||||
ValueTyDefId::EnumVariantId(var) => {
|
||||
|
@ -1148,11 +1149,12 @@ impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefI
|
|||
pub enum ValueTyDefId {
|
||||
FunctionId(FunctionId),
|
||||
StructId(StructId),
|
||||
UnionId(UnionId),
|
||||
EnumVariantId(EnumVariantId),
|
||||
ConstId(ConstId),
|
||||
StaticId(StaticId),
|
||||
}
|
||||
impl_from!(FunctionId, StructId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
|
||||
impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
|
||||
|
||||
/// Build the declared type of an item. This depends on the namespace; e.g. for
|
||||
/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
|
||||
|
@ -1179,6 +1181,7 @@ pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders
|
|||
match def {
|
||||
ValueTyDefId::FunctionId(it) => type_for_fn(db, it),
|
||||
ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
|
||||
ValueTyDefId::UnionId(it) => type_for_adt(db, it.into()),
|
||||
ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
|
||||
ValueTyDefId::ConstId(it) => type_for_const(db, it),
|
||||
ValueTyDefId::StaticId(it) => type_for_static(db, it),
|
||||
|
|
|
@ -81,7 +81,7 @@ fn check_types_impl(ra_fixture: &str, display_source: bool) {
|
|||
fn type_at_range(db: &TestDB, pos: FileRange) -> Ty {
|
||||
let file = db.parse(pos.file_id).ok().unwrap();
|
||||
let expr = algo::find_node_at_range::<ast::Expr>(file.syntax(), pos.range).unwrap();
|
||||
let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
|
||||
let fn_def = expr.syntax().ancestors().find_map(ast::Fn::cast).unwrap();
|
||||
let module = db.module_for_file(pos.file_id);
|
||||
let func = *module.child_by_source(db)[keys::FUNCTION]
|
||||
.get(&InFile::new(pos.file_id.into(), fn_def))
|
||||
|
|
|
@ -334,16 +334,44 @@ fn infer_union() {
|
|||
bar: f32,
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let u = MyUnion { foo: 0 };
|
||||
unsafe { baz(u); }
|
||||
let u = MyUnion { bar: 0.0 };
|
||||
unsafe { baz(u); }
|
||||
}
|
||||
|
||||
unsafe fn baz(u: MyUnion) {
|
||||
let inner = u.foo;
|
||||
let inner = u.bar;
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
61..62 'u': MyUnion
|
||||
73..99 '{ ...foo; }': ()
|
||||
83..88 'inner': u32
|
||||
91..92 'u': MyUnion
|
||||
91..96 'u.foo': u32
|
||||
57..172 '{ ...); } }': ()
|
||||
67..68 'u': MyUnion
|
||||
71..89 'MyUnio...o: 0 }': MyUnion
|
||||
86..87 '0': u32
|
||||
95..113 'unsafe...(u); }': ()
|
||||
102..113 '{ baz(u); }': ()
|
||||
104..107 'baz': fn baz(MyUnion)
|
||||
104..110 'baz(u)': ()
|
||||
108..109 'u': MyUnion
|
||||
122..123 'u': MyUnion
|
||||
126..146 'MyUnio... 0.0 }': MyUnion
|
||||
141..144 '0.0': f32
|
||||
152..170 'unsafe...(u); }': ()
|
||||
159..170 '{ baz(u); }': ()
|
||||
161..164 'baz': fn baz(MyUnion)
|
||||
161..167 'baz(u)': ()
|
||||
165..166 'u': MyUnion
|
||||
188..189 'u': MyUnion
|
||||
200..249 '{ ...bar; }': ()
|
||||
210..215 'inner': u32
|
||||
218..219 'u': MyUnion
|
||||
218..223 'u.foo': u32
|
||||
233..238 'inner': f32
|
||||
241..242 'u': MyUnion
|
||||
241..246 'u.bar': f32
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -183,6 +183,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
.collect(),
|
||||
1,
|
||||
),
|
||||
where_clauses: make_binders(vec![], 0),
|
||||
};
|
||||
let num_vars = datas.num_binders;
|
||||
Arc::new(OpaqueTyDatum { opaque_ty_id: id, bound: make_binders(bound, num_vars) })
|
||||
|
@ -193,15 +194,6 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
|||
Ty::Unknown.to_chalk(self.db)
|
||||
}
|
||||
|
||||
fn force_impl_for(
|
||||
&self,
|
||||
_well_known: rust_ir::WellKnownTrait,
|
||||
_ty: &chalk_ir::TyData<Interner>,
|
||||
) -> Option<bool> {
|
||||
// this method is mostly for rustc
|
||||
None
|
||||
}
|
||||
|
||||
fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
|
||||
// FIXME: implement actual object safety
|
||||
true
|
||||
|
@ -547,8 +539,13 @@ pub(crate) fn fn_def_datum_query(
|
|||
),
|
||||
where_clauses,
|
||||
};
|
||||
let datum =
|
||||
FnDefDatum { id: fn_def_id, binders: make_binders(bound, sig.num_binders), abi: () };
|
||||
let datum = FnDefDatum {
|
||||
id: fn_def_id,
|
||||
abi: (),
|
||||
safety: chalk_ir::Safety::Safe,
|
||||
variadic: sig.value.is_varargs,
|
||||
binders: make_binders(bound, sig.num_binders),
|
||||
};
|
||||
Arc::new(datum)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,16 @@ impl ToChalk for Ty {
|
|||
Ty::Apply(apply_ty) => match apply_ty.ctor {
|
||||
TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters),
|
||||
TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
|
||||
TypeCtor::FnPtr { num_args: _, is_varargs: _ } => {
|
||||
// FIXME: handle is_varargs
|
||||
TypeCtor::FnPtr { num_args: _, is_varargs } => {
|
||||
let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner);
|
||||
chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution })
|
||||
.intern(&Interner)
|
||||
chalk_ir::TyData::Function(chalk_ir::FnPointer {
|
||||
num_binders: 0,
|
||||
abi: (),
|
||||
safety: chalk_ir::Safety::Safe,
|
||||
variadic: is_varargs,
|
||||
substitution,
|
||||
})
|
||||
.intern(&Interner)
|
||||
}
|
||||
_ => {
|
||||
let name = apply_ty.ctor.to_chalk(db);
|
||||
|
@ -118,7 +123,12 @@ impl ToChalk for Ty {
|
|||
let parameters = from_chalk(db, opaque_ty.substitution);
|
||||
Ty::Opaque(OpaqueTy { opaque_ty_id: impl_trait_id, parameters })
|
||||
}
|
||||
chalk_ir::TyData::Function(chalk_ir::Fn { num_binders, substitution }) => {
|
||||
chalk_ir::TyData::Function(chalk_ir::FnPointer {
|
||||
num_binders,
|
||||
variadic,
|
||||
substitution,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(num_binders, 0);
|
||||
let parameters: Substs = from_chalk(
|
||||
db,
|
||||
|
@ -127,7 +137,7 @@ impl ToChalk for Ty {
|
|||
Ty::Apply(ApplicationTy {
|
||||
ctor: TypeCtor::FnPtr {
|
||||
num_args: (parameters.len() - 1) as u16,
|
||||
is_varargs: false,
|
||||
is_varargs: variadic,
|
||||
},
|
||||
parameters,
|
||||
})
|
||||
|
|
|
@ -17,7 +17,7 @@ indexmap = "1.3.2"
|
|||
itertools = "0.9.0"
|
||||
log = "0.4.8"
|
||||
rustc-hash = "1.1.0"
|
||||
rand = { version = "0.7.3", features = ["small_rng"] }
|
||||
oorandom = "11.1.2"
|
||||
|
||||
stdx = { path = "../stdx" }
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio
|
|||
if let Some(nav) = syntax.ancestors().find_map(|node| {
|
||||
match_ast! {
|
||||
match node {
|
||||
ast::FnDef(it) => {
|
||||
ast::Fn(it) => {
|
||||
let def = sema.to_def(&it)?;
|
||||
Some(def.to_nav(sema.db))
|
||||
},
|
||||
|
@ -181,8 +181,8 @@ fn caller() {
|
|||
call<|>ee();
|
||||
}
|
||||
"#,
|
||||
"callee FN_DEF FileId(1) 0..14 3..9",
|
||||
&["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"],
|
||||
"callee FN FileId(1) 0..14 3..9",
|
||||
&["caller FN FileId(1) 15..44 18..24 : [33..39]"],
|
||||
&[],
|
||||
);
|
||||
}
|
||||
|
@ -197,8 +197,8 @@ fn caller() {
|
|||
callee();
|
||||
}
|
||||
"#,
|
||||
"callee FN_DEF FileId(1) 0..14 3..9",
|
||||
&["caller FN_DEF FileId(1) 15..44 18..24 : [33..39]"],
|
||||
"callee FN FileId(1) 0..14 3..9",
|
||||
&["caller FN FileId(1) 15..44 18..24 : [33..39]"],
|
||||
&[],
|
||||
);
|
||||
}
|
||||
|
@ -214,8 +214,8 @@ fn caller() {
|
|||
callee();
|
||||
}
|
||||
"#,
|
||||
"callee FN_DEF FileId(1) 0..14 3..9",
|
||||
&["caller FN_DEF FileId(1) 15..58 18..24 : [33..39, 47..53]"],
|
||||
"callee FN FileId(1) 0..14 3..9",
|
||||
&["caller FN FileId(1) 15..58 18..24 : [33..39, 47..53]"],
|
||||
&[],
|
||||
);
|
||||
}
|
||||
|
@ -234,10 +234,10 @@ fn caller2() {
|
|||
callee();
|
||||
}
|
||||
"#,
|
||||
"callee FN_DEF FileId(1) 0..14 3..9",
|
||||
"callee FN FileId(1) 0..14 3..9",
|
||||
&[
|
||||
"caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]",
|
||||
"caller2 FN_DEF FileId(1) 47..77 50..57 : [66..72]",
|
||||
"caller1 FN FileId(1) 15..45 18..25 : [34..40]",
|
||||
"caller2 FN FileId(1) 47..77 50..57 : [66..72]",
|
||||
],
|
||||
&[],
|
||||
);
|
||||
|
@ -263,10 +263,10 @@ mod tests {
|
|||
}
|
||||
}
|
||||
"#,
|
||||
"callee FN_DEF FileId(1) 0..14 3..9",
|
||||
"callee FN FileId(1) 0..14 3..9",
|
||||
&[
|
||||
"caller1 FN_DEF FileId(1) 15..45 18..25 : [34..40]",
|
||||
"test_caller FN_DEF FileId(1) 95..149 110..121 : [134..140]",
|
||||
"caller1 FN FileId(1) 15..45 18..25 : [34..40]",
|
||||
"test_caller FN FileId(1) 95..149 110..121 : [134..140]",
|
||||
],
|
||||
&[],
|
||||
);
|
||||
|
@ -287,8 +287,8 @@ fn caller() {
|
|||
//- /foo/mod.rs
|
||||
pub fn callee() {}
|
||||
"#,
|
||||
"callee FN_DEF FileId(2) 0..18 7..13",
|
||||
&["caller FN_DEF FileId(1) 27..56 30..36 : [45..51]"],
|
||||
"callee FN FileId(2) 0..18 7..13",
|
||||
&["caller FN FileId(1) 27..56 30..36 : [45..51]"],
|
||||
&[],
|
||||
);
|
||||
}
|
||||
|
@ -304,9 +304,9 @@ fn call<|>er() {
|
|||
callee();
|
||||
}
|
||||
"#,
|
||||
"caller FN_DEF FileId(1) 15..58 18..24",
|
||||
"caller FN FileId(1) 15..58 18..24",
|
||||
&[],
|
||||
&["callee FN_DEF FileId(1) 0..14 3..9 : [33..39, 47..53]"],
|
||||
&["callee FN FileId(1) 0..14 3..9 : [33..39, 47..53]"],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -325,9 +325,9 @@ fn call<|>er() {
|
|||
//- /foo/mod.rs
|
||||
pub fn callee() {}
|
||||
"#,
|
||||
"caller FN_DEF FileId(1) 27..56 30..36",
|
||||
"caller FN FileId(1) 27..56 30..36",
|
||||
&[],
|
||||
&["callee FN_DEF FileId(2) 0..18 7..13 : [45..51]"],
|
||||
&["callee FN FileId(2) 0..18 7..13 : [45..51]"],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -348,9 +348,9 @@ fn caller3() {
|
|||
|
||||
}
|
||||
"#,
|
||||
"caller2 FN_DEF FileId(1) 33..64 36..43",
|
||||
&["caller1 FN_DEF FileId(1) 0..31 3..10 : [19..26]"],
|
||||
&["caller3 FN_DEF FileId(1) 66..83 69..76 : [52..59]"],
|
||||
"caller2 FN FileId(1) 33..64 36..43",
|
||||
&["caller1 FN FileId(1) 0..31 3..10 : [19..26]"],
|
||||
&["caller3 FN FileId(1) 66..83 69..76 : [52..59]"],
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -368,9 +368,9 @@ fn main() {
|
|||
a<|>()
|
||||
}
|
||||
"#,
|
||||
"a FN_DEF FileId(1) 0..18 3..4",
|
||||
&["main FN_DEF FileId(1) 31..52 34..38 : [47..48]"],
|
||||
&["b FN_DEF FileId(1) 20..29 23..24 : [13..14]"],
|
||||
"a FN FileId(1) 0..18 3..4",
|
||||
&["main FN FileId(1) 31..52 34..38 : [47..48]"],
|
||||
&["b FN FileId(1) 20..29 23..24 : [13..14]"],
|
||||
);
|
||||
|
||||
check_hierarchy(
|
||||
|
@ -385,8 +385,8 @@ fn main() {
|
|||
a()
|
||||
}
|
||||
"#,
|
||||
"b FN_DEF FileId(1) 20..29 23..24",
|
||||
&["a FN_DEF FileId(1) 0..18 3..4 : [13..14]"],
|
||||
"b FN FileId(1) 20..29 23..24",
|
||||
&["a FN FileId(1) 0..18 3..4 : [13..14]"],
|
||||
&[],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,25 +16,23 @@ use crate::completion::UNSTABLE_FEATURE_DESCRIPTOR;
|
|||
|
||||
pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
|
||||
let attribute = ctx.attribute_under_caret.as_ref()?;
|
||||
match (attribute.path(), attribute.input()) {
|
||||
(Some(path), Some(ast::AttrInput::TokenTree(token_tree)))
|
||||
if path.to_string() == "derive" =>
|
||||
{
|
||||
match (attribute.path(), attribute.token_tree()) {
|
||||
(Some(path), Some(token_tree)) if path.to_string() == "derive" => {
|
||||
complete_derive(acc, ctx, token_tree)
|
||||
}
|
||||
(Some(path), Some(ast::AttrInput::TokenTree(token_tree)))
|
||||
(Some(path), Some(token_tree))
|
||||
if path.to_string() == "feature" =>
|
||||
{
|
||||
complete_lint(acc, ctx, token_tree, UNSTABLE_FEATURE_DESCRIPTOR);
|
||||
}
|
||||
(Some(path), Some(ast::AttrInput::TokenTree(token_tree)))
|
||||
(Some(path), Some(token_tree))
|
||||
if ["allow", "warn", "deny", "forbid"]
|
||||
.iter()
|
||||
.any(|lint_level| lint_level == &path.to_string()) =>
|
||||
{
|
||||
complete_lint(acc, ctx, token_tree, DEFAULT_LINT_COMPLETIONS)
|
||||
}
|
||||
(_, Some(ast::AttrInput::TokenTree(_token_tree))) => {}
|
||||
(_, Some(_token_tree)) => {}
|
||||
_ => complete_attribute_start(acc, ctx, attribute),
|
||||
}
|
||||
Some(())
|
||||
|
|
|
@ -18,26 +18,36 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
|
|||
}
|
||||
|
||||
let mut params = FxHashMap::default();
|
||||
let me = ctx.token.ancestors().find_map(ast::FnDef::cast);
|
||||
|
||||
let me = ctx.token.ancestors().find_map(ast::Fn::cast);
|
||||
let mut process_fn = |func: ast::Fn| {
|
||||
if Some(&func) == me.as_ref() {
|
||||
return;
|
||||
}
|
||||
func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| {
|
||||
let text = param.syntax().text().to_string();
|
||||
params.entry(text).or_insert(param);
|
||||
})
|
||||
};
|
||||
|
||||
for node in ctx.token.parent().ancestors() {
|
||||
let items = match_ast! {
|
||||
match_ast! {
|
||||
match node {
|
||||
ast::SourceFile(it) => it.items(),
|
||||
ast::ItemList(it) => it.items(),
|
||||
ast::SourceFile(it) => it.items().filter_map(|item| match item {
|
||||
ast::Item::Fn(it) => Some(it),
|
||||
_ => None,
|
||||
}).for_each(&mut process_fn),
|
||||
ast::ItemList(it) => it.items().filter_map(|item| match item {
|
||||
ast::Item::Fn(it) => Some(it),
|
||||
_ => None,
|
||||
}).for_each(&mut process_fn),
|
||||
ast::AssocItemList(it) => it.assoc_items().filter_map(|item| match item {
|
||||
ast::AssocItem::Fn(it) => Some(it),
|
||||
_ => None,
|
||||
}).for_each(&mut process_fn),
|
||||
_ => continue,
|
||||
}
|
||||
};
|
||||
for item in items {
|
||||
if let ast::ModuleItem::FnDef(func) = item {
|
||||
if Some(&func) == me.as_ref() {
|
||||
continue;
|
||||
}
|
||||
func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| {
|
||||
let text = param.syntax().text().to_string();
|
||||
params.entry(text).or_insert(param);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params
|
||||
|
|
|
@ -66,27 +66,24 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
|||
add_keyword(ctx, acc, "fn", "fn $0() {}")
|
||||
}
|
||||
|
||||
if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
|
||||
|| ctx.block_expr_parent
|
||||
{
|
||||
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
|
||||
add_keyword(ctx, acc, "trait", "trait $0 {}");
|
||||
add_keyword(ctx, acc, "impl", "impl $0 {}");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent {
|
||||
if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent
|
||||
{
|
||||
add_keyword(ctx, acc, "fn", "fn $0() {}");
|
||||
}
|
||||
if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
|
||||
|| ctx.block_expr_parent
|
||||
{
|
||||
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
|
||||
add_keyword(ctx, acc, "use", "use ");
|
||||
add_keyword(ctx, acc, "impl", "impl $0 {}");
|
||||
add_keyword(ctx, acc, "trait", "trait $0 {}");
|
||||
}
|
||||
|
||||
if ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent {
|
||||
if ctx.has_item_list_or_source_file_parent {
|
||||
add_keyword(ctx, acc, "enum", "enum $0 {}");
|
||||
add_keyword(ctx, acc, "struct", "struct $0");
|
||||
add_keyword(ctx, acc, "union", "union $0 {}");
|
||||
|
@ -108,29 +105,28 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
|||
add_keyword(ctx, acc, "else", "else {$0}");
|
||||
add_keyword(ctx, acc, "else if", "else if $0 {}");
|
||||
}
|
||||
if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
|
||||
|| ctx.block_expr_parent
|
||||
{
|
||||
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
|
||||
add_keyword(ctx, acc, "mod", "mod $0 {}");
|
||||
}
|
||||
if ctx.bind_pat_parent || ctx.ref_pat_parent {
|
||||
add_keyword(ctx, acc, "mut", "mut ");
|
||||
}
|
||||
if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent {
|
||||
if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent
|
||||
{
|
||||
add_keyword(ctx, acc, "const", "const ");
|
||||
add_keyword(ctx, acc, "type", "type ");
|
||||
}
|
||||
if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
|
||||
|| ctx.block_expr_parent
|
||||
{
|
||||
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
|
||||
add_keyword(ctx, acc, "static", "static ");
|
||||
};
|
||||
if (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
|
||||
|| ctx.block_expr_parent
|
||||
{
|
||||
if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
|
||||
add_keyword(ctx, acc, "extern", "extern ");
|
||||
}
|
||||
if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm {
|
||||
if ctx.has_item_list_or_source_file_parent
|
||||
|| has_trait_or_impl_parent
|
||||
|| ctx.block_expr_parent
|
||||
|| ctx.is_match_arm
|
||||
{
|
||||
add_keyword(ctx, acc, "unsafe", "unsafe ");
|
||||
}
|
||||
if ctx.in_loop_body {
|
||||
|
@ -142,7 +138,7 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
|||
add_keyword(ctx, acc, "break", "break");
|
||||
}
|
||||
}
|
||||
if ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent {
|
||||
if ctx.has_item_list_or_source_file_parent || ctx.has_impl_parent {
|
||||
add_keyword(ctx, acc, "pub", "pub ")
|
||||
}
|
||||
|
||||
|
@ -173,7 +169,7 @@ fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet
|
|||
|
||||
fn complete_return(
|
||||
ctx: &CompletionContext,
|
||||
fn_def: &ast::FnDef,
|
||||
fn_def: &ast::Fn,
|
||||
can_be_stmt: bool,
|
||||
) -> Option<CompletionItem> {
|
||||
let snip = match (can_be_stmt, fn_def.ret_type().is_some()) {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
//!
|
||||
//! This module adds the completion items related to implementing associated
|
||||
//! items within a `impl Trait for Struct` block. The current context node
|
||||
//! must be within either a `FN_DEF`, `TYPE_ALIAS_DEF`, or `CONST_DEF` node
|
||||
//! and an direct child of an `IMPL_DEF`.
|
||||
//! must be within either a `FN`, `TYPE_ALIAS`, or `CONST` node
|
||||
//! and an direct child of an `IMPL`.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
|
@ -34,7 +34,7 @@
|
|||
use hir::{self, Docs, HasSource};
|
||||
use ra_assists::utils::get_missing_assoc_items;
|
||||
use ra_syntax::{
|
||||
ast::{self, edit, ImplDef},
|
||||
ast::{self, edit, Impl},
|
||||
AstNode, SyntaxKind, SyntaxNode, TextRange, T,
|
||||
};
|
||||
use ra_text_edit::TextEdit;
|
||||
|
@ -63,7 +63,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
|
|||
}
|
||||
}),
|
||||
|
||||
SyntaxKind::FN_DEF => {
|
||||
SyntaxKind::FN => {
|
||||
for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def)
|
||||
.into_iter()
|
||||
.filter_map(|item| match item {
|
||||
|
@ -75,7 +75,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
|
|||
}
|
||||
}
|
||||
|
||||
SyntaxKind::TYPE_ALIAS_DEF => {
|
||||
SyntaxKind::TYPE_ALIAS => {
|
||||
for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def)
|
||||
.into_iter()
|
||||
.filter_map(|item| match item {
|
||||
|
@ -87,7 +87,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
|
|||
}
|
||||
}
|
||||
|
||||
SyntaxKind::CONST_DEF => {
|
||||
SyntaxKind::CONST => {
|
||||
for missing_fn in get_missing_assoc_items(&ctx.sema, &impl_def)
|
||||
.into_iter()
|
||||
.filter_map(|item| match item {
|
||||
|
@ -104,18 +104,17 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
|
|||
}
|
||||
}
|
||||
|
||||
fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, ImplDef)> {
|
||||
fn completion_match(ctx: &CompletionContext) -> Option<(SyntaxNode, Impl)> {
|
||||
let (trigger, impl_def_offset) = ctx.token.ancestors().find_map(|p| match p.kind() {
|
||||
SyntaxKind::FN_DEF
|
||||
| SyntaxKind::TYPE_ALIAS_DEF
|
||||
| SyntaxKind::CONST_DEF
|
||||
| SyntaxKind::BLOCK_EXPR => Some((p, 2)),
|
||||
SyntaxKind::FN | SyntaxKind::TYPE_ALIAS | SyntaxKind::CONST | SyntaxKind::BLOCK_EXPR => {
|
||||
Some((p, 2))
|
||||
}
|
||||
SyntaxKind::NAME_REF => Some((p, 5)),
|
||||
_ => None,
|
||||
})?;
|
||||
let impl_def = (0..impl_def_offset - 1)
|
||||
.try_fold(trigger.parent()?, |t, _| t.parent())
|
||||
.and_then(ast::ImplDef::cast)?;
|
||||
.and_then(ast::Impl::cast)?;
|
||||
Some((trigger, impl_def))
|
||||
}
|
||||
|
||||
|
@ -201,7 +200,7 @@ fn add_const_impl(
|
|||
}
|
||||
}
|
||||
|
||||
fn make_const_compl_syntax(const_: &ast::ConstDef) -> String {
|
||||
fn make_const_compl_syntax(const_: &ast::Const) -> String {
|
||||
let const_ = edit::remove_attrs_and_docs(const_);
|
||||
|
||||
let const_start = const_.syntax().text_range().start();
|
||||
|
|
|
@ -35,12 +35,12 @@ pub(crate) struct CompletionContext<'a> {
|
|||
pub(super) krate: Option<hir::Crate>,
|
||||
pub(super) expected_type: Option<Type>,
|
||||
pub(super) name_ref_syntax: Option<ast::NameRef>,
|
||||
pub(super) function_syntax: Option<ast::FnDef>,
|
||||
pub(super) use_item_syntax: Option<ast::UseItem>,
|
||||
pub(super) record_lit_syntax: Option<ast::RecordLit>,
|
||||
pub(super) function_syntax: Option<ast::Fn>,
|
||||
pub(super) use_item_syntax: Option<ast::Use>,
|
||||
pub(super) record_lit_syntax: Option<ast::RecordExpr>,
|
||||
pub(super) record_pat_syntax: Option<ast::RecordPat>,
|
||||
pub(super) record_field_syntax: Option<ast::RecordField>,
|
||||
pub(super) impl_def: Option<ast::ImplDef>,
|
||||
pub(super) record_field_syntax: Option<ast::RecordExprField>,
|
||||
pub(super) impl_def: Option<ast::Impl>,
|
||||
/// FIXME: `ActiveParameter` is string-based, which is very very wrong
|
||||
pub(super) active_parameter: Option<ActiveParameter>,
|
||||
pub(super) is_param: bool,
|
||||
|
@ -265,7 +265,7 @@ impl<'a> CompletionContext<'a> {
|
|||
return;
|
||||
}
|
||||
// FIXME: remove this (V) duplication and make the check more precise
|
||||
if name_ref.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() {
|
||||
if name_ref.syntax().ancestors().find_map(ast::RecordPatFieldList::cast).is_some() {
|
||||
self.record_pat_syntax =
|
||||
self.sema.find_node_at_offset_with_macros(&original_file, offset);
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ impl<'a> CompletionContext<'a> {
|
|||
// Otherwise, see if this is a declaration. We can use heuristics to
|
||||
// suggest declaration names, see `CompletionKind::Magic`.
|
||||
if let Some(name) = find_node_at_offset::<ast::Name>(&file_with_fake_ident, offset) {
|
||||
if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) {
|
||||
if let Some(bind_pat) = name.syntax().ancestors().find_map(ast::IdentPat::cast) {
|
||||
self.is_pat_binding_or_const = true;
|
||||
if bind_pat.at_token().is_some()
|
||||
|| bind_pat.ref_token().is_some()
|
||||
|
@ -283,7 +283,7 @@ impl<'a> CompletionContext<'a> {
|
|||
{
|
||||
self.is_pat_binding_or_const = false;
|
||||
}
|
||||
if bind_pat.syntax().parent().and_then(ast::RecordFieldPatList::cast).is_some() {
|
||||
if bind_pat.syntax().parent().and_then(ast::RecordPatFieldList::cast).is_some() {
|
||||
self.is_pat_binding_or_const = false;
|
||||
}
|
||||
if let Some(let_stmt) = bind_pat.syntax().ancestors().find_map(ast::LetStmt::cast) {
|
||||
|
@ -300,7 +300,7 @@ impl<'a> CompletionContext<'a> {
|
|||
return;
|
||||
}
|
||||
// FIXME: remove this (^) duplication and make the check more precise
|
||||
if name.syntax().ancestors().find_map(ast::RecordFieldPatList::cast).is_some() {
|
||||
if name.syntax().ancestors().find_map(ast::RecordPatFieldList::cast).is_some() {
|
||||
self.record_pat_syntax =
|
||||
self.sema.find_node_at_offset_with_macros(&original_file, offset);
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ impl<'a> CompletionContext<'a> {
|
|||
self.name_ref_syntax =
|
||||
find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
|
||||
let name_range = name_ref.syntax().text_range();
|
||||
if ast::RecordField::for_field_name(&name_ref).is_some() {
|
||||
if ast::RecordExprField::for_field_name(&name_ref).is_some() {
|
||||
self.record_lit_syntax =
|
||||
self.sema.find_node_at_offset_with_macros(&original_file, offset);
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ impl<'a> CompletionContext<'a> {
|
|||
.sema
|
||||
.ancestors_with_macros(self.token.parent())
|
||||
.take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
|
||||
.find_map(ast::ImplDef::cast);
|
||||
.find_map(ast::Impl::cast);
|
||||
|
||||
let top_node = name_ref
|
||||
.syntax()
|
||||
|
@ -343,13 +343,13 @@ impl<'a> CompletionContext<'a> {
|
|||
}
|
||||
|
||||
self.use_item_syntax =
|
||||
self.sema.ancestors_with_macros(self.token.parent()).find_map(ast::UseItem::cast);
|
||||
self.sema.ancestors_with_macros(self.token.parent()).find_map(ast::Use::cast);
|
||||
|
||||
self.function_syntax = self
|
||||
.sema
|
||||
.ancestors_with_macros(self.token.parent())
|
||||
.take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
|
||||
.find_map(ast::FnDef::cast);
|
||||
.find_map(ast::Fn::cast);
|
||||
|
||||
self.record_field_syntax = self
|
||||
.sema
|
||||
|
@ -357,7 +357,7 @@ impl<'a> CompletionContext<'a> {
|
|||
.take_while(|it| {
|
||||
it.kind() != SOURCE_FILE && it.kind() != MODULE && it.kind() != CALL_EXPR
|
||||
})
|
||||
.find_map(ast::RecordField::cast);
|
||||
.find_map(ast::RecordExprField::cast);
|
||||
|
||||
let parent = match name_ref.syntax().parent() {
|
||||
Some(it) => it,
|
||||
|
@ -377,7 +377,7 @@ impl<'a> CompletionContext<'a> {
|
|||
path.syntax().parent().and_then(ast::TupleStructPat::cast).is_some();
|
||||
|
||||
self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some();
|
||||
self.has_type_args = segment.type_arg_list().is_some();
|
||||
self.has_type_args = segment.generic_arg_list().is_some();
|
||||
|
||||
#[allow(deprecated)]
|
||||
if let Some(path) = hir::Path::from_ast(path.clone()) {
|
||||
|
|
|
@ -13,9 +13,9 @@ use crate::completion::test_utils::check_pattern_is_applicable;
|
|||
|
||||
pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool {
|
||||
not_same_range_ancestor(element)
|
||||
.filter(|it| it.kind() == ITEM_LIST)
|
||||
.filter(|it| it.kind() == ASSOC_ITEM_LIST)
|
||||
.and_then(|it| it.parent())
|
||||
.filter(|it| it.kind() == TRAIT_DEF)
|
||||
.filter(|it| it.kind() == TRAIT)
|
||||
.is_some()
|
||||
}
|
||||
#[test]
|
||||
|
@ -25,9 +25,9 @@ fn test_has_trait_parent() {
|
|||
|
||||
pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool {
|
||||
not_same_range_ancestor(element)
|
||||
.filter(|it| it.kind() == ITEM_LIST)
|
||||
.filter(|it| it.kind() == ASSOC_ITEM_LIST)
|
||||
.and_then(|it| it.parent())
|
||||
.filter(|it| it.kind() == IMPL_DEF)
|
||||
.filter(|it| it.kind() == IMPL)
|
||||
.is_some()
|
||||
}
|
||||
#[test]
|
||||
|
@ -44,7 +44,7 @@ fn test_has_block_expr_parent() {
|
|||
}
|
||||
|
||||
pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool {
|
||||
element.ancestors().find(|it| it.kind() == BIND_PAT).is_some()
|
||||
element.ancestors().find(|it| it.kind() == IDENT_PAT).is_some()
|
||||
}
|
||||
#[test]
|
||||
fn test_has_bind_pat_parent() {
|
||||
|
@ -73,7 +73,7 @@ pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> boo
|
|||
#[test]
|
||||
fn test_has_item_list_or_source_file_parent() {
|
||||
check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent);
|
||||
check_pattern_is_applicable(r"impl { f<|> }", has_item_list_or_source_file_parent);
|
||||
check_pattern_is_applicable(r"mod foo { f<|> }", has_item_list_or_source_file_parent);
|
||||
}
|
||||
|
||||
pub(crate) fn is_match_arm(element: SyntaxElement) -> bool {
|
||||
|
@ -113,7 +113,7 @@ fn test_if_is_prev() {
|
|||
}
|
||||
|
||||
pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool {
|
||||
previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT_DEF).is_some()
|
||||
previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT).is_some()
|
||||
}
|
||||
#[test]
|
||||
fn test_has_trait_as_prev_sibling() {
|
||||
|
@ -121,7 +121,7 @@ fn test_has_trait_as_prev_sibling() {
|
|||
}
|
||||
|
||||
pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool {
|
||||
previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == IMPL_DEF).is_some()
|
||||
previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == IMPL).is_some()
|
||||
}
|
||||
#[test]
|
||||
fn test_has_impl_as_prev_sibling() {
|
||||
|
@ -134,7 +134,7 @@ pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
|
|||
NodeOrToken::Token(token) => token.parent(),
|
||||
};
|
||||
for node in leaf.ancestors() {
|
||||
if node.kind() == FN_DEF || node.kind() == LAMBDA_EXPR {
|
||||
if node.kind() == FN || node.kind() == CLOSURE_EXPR {
|
||||
break;
|
||||
}
|
||||
let loop_body = match_ast! {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -78,8 +78,10 @@ pub(crate) fn diagnostics(
|
|||
} else {
|
||||
let mut field_list = d.ast(db);
|
||||
for f in d.missed_fields.iter() {
|
||||
let field =
|
||||
make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit()));
|
||||
let field = make::record_expr_field(
|
||||
make::name_ref(&f.to_string()),
|
||||
Some(make::expr_unit()),
|
||||
);
|
||||
field_list = field_list.append_field(&field);
|
||||
}
|
||||
|
||||
|
@ -146,7 +148,7 @@ fn missing_struct_field_fix(
|
|||
) -> Option<Fix> {
|
||||
let record_expr = sema.ast(d);
|
||||
|
||||
let record_lit = ast::RecordLit::cast(record_expr.syntax().parent()?.parent()?)?;
|
||||
let record_lit = ast::RecordExpr::cast(record_expr.syntax().parent()?.parent()?)?;
|
||||
let def_id = sema.resolve_variant(record_lit)?;
|
||||
let module;
|
||||
let def_file_id;
|
||||
|
@ -155,21 +157,21 @@ fn missing_struct_field_fix(
|
|||
module = s.module(sema.db);
|
||||
let source = s.source(sema.db);
|
||||
def_file_id = source.file_id;
|
||||
let fields = source.value.field_def_list()?;
|
||||
record_field_def_list(fields)?
|
||||
let fields = source.value.field_list()?;
|
||||
record_field_list(fields)?
|
||||
}
|
||||
VariantDef::Union(u) => {
|
||||
module = u.module(sema.db);
|
||||
let source = u.source(sema.db);
|
||||
def_file_id = source.file_id;
|
||||
source.value.record_field_def_list()?
|
||||
source.value.record_field_list()?
|
||||
}
|
||||
VariantDef::EnumVariant(e) => {
|
||||
module = e.module(sema.db);
|
||||
let source = e.source(sema.db);
|
||||
def_file_id = source.file_id;
|
||||
let fields = source.value.field_def_list()?;
|
||||
record_field_def_list(fields)?
|
||||
let fields = source.value.field_list()?;
|
||||
record_field_list(fields)?
|
||||
}
|
||||
};
|
||||
let def_file_id = def_file_id.original_file(sema.db);
|
||||
|
@ -178,9 +180,9 @@ fn missing_struct_field_fix(
|
|||
if new_field_type.is_unknown() {
|
||||
return None;
|
||||
}
|
||||
let new_field = make::record_field_def(
|
||||
let new_field = make::record_field(
|
||||
record_expr.field_name()?,
|
||||
make::type_ref(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
|
||||
make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
|
||||
);
|
||||
|
||||
let last_field = record_fields.fields().last()?;
|
||||
|
@ -205,10 +207,10 @@ fn missing_struct_field_fix(
|
|||
let fix = Fix::new("Create field", source_change.into());
|
||||
return Some(fix);
|
||||
|
||||
fn record_field_def_list(field_def_list: ast::FieldDefList) -> Option<ast::RecordFieldDefList> {
|
||||
fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> {
|
||||
match field_def_list {
|
||||
ast::FieldDefList::RecordFieldDefList(it) => Some(it),
|
||||
ast::FieldDefList::TupleFieldDefList(_) => None,
|
||||
ast::FieldList::RecordFieldList(it) => Some(it),
|
||||
ast::FieldList::TupleFieldList(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,8 +265,8 @@ fn check_struct_shorthand_initialization(
|
|||
file_id: FileId,
|
||||
node: &SyntaxNode,
|
||||
) -> Option<()> {
|
||||
let record_lit = ast::RecordLit::cast(node.clone())?;
|
||||
let record_field_list = record_lit.record_field_list()?;
|
||||
let record_lit = ast::RecordExpr::cast(node.clone())?;
|
||||
let record_field_list = record_lit.record_expr_field_list()?;
|
||||
for record_field in record_field_list.fields() {
|
||||
if let (Some(name_ref), Some(expr)) = (record_field.name_ref(), record_field.expr()) {
|
||||
let field_name = name_ref.syntax().text().to_string();
|
||||
|
|
|
@ -5,7 +5,7 @@ mod navigation_target;
|
|||
mod short_label;
|
||||
|
||||
use ra_syntax::{
|
||||
ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
|
||||
ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner},
|
||||
SyntaxKind::{ATTR, COMMENT},
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ pub use navigation_target::NavigationTarget;
|
|||
pub(crate) use navigation_target::{ToNav, TryToNav};
|
||||
pub(crate) use short_label::ShortLabel;
|
||||
|
||||
pub(crate) fn function_declaration(node: &ast::FnDef) -> String {
|
||||
pub(crate) fn function_declaration(node: &ast::Fn) -> String {
|
||||
let mut buf = String::new();
|
||||
if let Some(vis) = node.visibility() {
|
||||
format_to!(buf, "{} ", vis);
|
||||
|
@ -37,14 +37,14 @@ pub(crate) fn function_declaration(node: &ast::FnDef) -> String {
|
|||
if let Some(name) = node.name() {
|
||||
format_to!(buf, "fn {}", name)
|
||||
}
|
||||
if let Some(type_params) = node.type_param_list() {
|
||||
if let Some(type_params) = node.generic_param_list() {
|
||||
format_to!(buf, "{}", type_params);
|
||||
}
|
||||
if let Some(param_list) = node.param_list() {
|
||||
format_to!(buf, "{}", param_list);
|
||||
}
|
||||
if let Some(ret_type) = node.ret_type() {
|
||||
if ret_type.type_ref().is_some() {
|
||||
if ret_type.ty().is_some() {
|
||||
format_to!(buf, " {}", ret_type);
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ pub(crate) fn function_declaration(node: &ast::FnDef) -> String {
|
|||
buf
|
||||
}
|
||||
|
||||
pub(crate) fn const_label(node: &ast::ConstDef) -> String {
|
||||
pub(crate) fn const_label(node: &ast::Const) -> String {
|
||||
let label: String = node
|
||||
.syntax()
|
||||
.children_with_tokens()
|
||||
|
@ -65,7 +65,7 @@ pub(crate) fn const_label(node: &ast::ConstDef) -> String {
|
|||
label.trim().to_owned()
|
||||
}
|
||||
|
||||
pub(crate) fn type_label(node: &ast::TypeAliasDef) -> String {
|
||||
pub(crate) fn type_label(node: &ast::TypeAlias) -> String {
|
||||
let label: String = node
|
||||
.syntax()
|
||||
.children_with_tokens()
|
||||
|
|
|
@ -7,7 +7,7 @@ use ra_ide_db::{defs::Definition, RootDatabase};
|
|||
use ra_syntax::{
|
||||
ast::{self, DocCommentsOwner, NameOwner},
|
||||
match_ast, AstNode, SmolStr,
|
||||
SyntaxKind::{self, BIND_PAT, TYPE_PARAM},
|
||||
SyntaxKind::{self, IDENT_PAT, TYPE_PARAM},
|
||||
TextRange,
|
||||
};
|
||||
|
||||
|
@ -253,7 +253,7 @@ impl ToNav for hir::ImplDef {
|
|||
let focus_range = if derive_attr.is_some() {
|
||||
None
|
||||
} else {
|
||||
src.value.target_type().map(|ty| original_range(db, src.with_value(ty.syntax())).range)
|
||||
src.value.self_ty().map(|ty| original_range(db, src.with_value(ty.syntax())).range)
|
||||
};
|
||||
|
||||
NavigationTarget::from_syntax(
|
||||
|
@ -339,7 +339,7 @@ impl ToNav for hir::Local {
|
|||
NavigationTarget {
|
||||
file_id: full_range.file_id,
|
||||
name,
|
||||
kind: BIND_PAT,
|
||||
kind: IDENT_PAT,
|
||||
full_range: full_range.range,
|
||||
focus_range: None,
|
||||
container_name: None,
|
||||
|
@ -379,16 +379,16 @@ pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option
|
|||
|
||||
match_ast! {
|
||||
match node {
|
||||
ast::FnDef(it) => it.doc_comment_text(),
|
||||
ast::StructDef(it) => it.doc_comment_text(),
|
||||
ast::EnumDef(it) => it.doc_comment_text(),
|
||||
ast::TraitDef(it) => it.doc_comment_text(),
|
||||
ast::Fn(it) => it.doc_comment_text(),
|
||||
ast::Struct(it) => it.doc_comment_text(),
|
||||
ast::Enum(it) => it.doc_comment_text(),
|
||||
ast::Trait(it) => it.doc_comment_text(),
|
||||
ast::Module(it) => it.doc_comment_text(),
|
||||
ast::TypeAliasDef(it) => it.doc_comment_text(),
|
||||
ast::ConstDef(it) => it.doc_comment_text(),
|
||||
ast::StaticDef(it) => it.doc_comment_text(),
|
||||
ast::RecordFieldDef(it) => it.doc_comment_text(),
|
||||
ast::EnumVariant(it) => it.doc_comment_text(),
|
||||
ast::TypeAlias(it) => it.doc_comment_text(),
|
||||
ast::Const(it) => it.doc_comment_text(),
|
||||
ast::Static(it) => it.doc_comment_text(),
|
||||
ast::RecordField(it) => it.doc_comment_text(),
|
||||
ast::Variant(it) => it.doc_comment_text(),
|
||||
ast::MacroCall(it) => it.doc_comment_text(),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -404,16 +404,16 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) ->
|
|||
|
||||
match_ast! {
|
||||
match node {
|
||||
ast::FnDef(it) => it.short_label(),
|
||||
ast::StructDef(it) => it.short_label(),
|
||||
ast::EnumDef(it) => it.short_label(),
|
||||
ast::TraitDef(it) => it.short_label(),
|
||||
ast::Fn(it) => it.short_label(),
|
||||
ast::Struct(it) => it.short_label(),
|
||||
ast::Enum(it) => it.short_label(),
|
||||
ast::Trait(it) => it.short_label(),
|
||||
ast::Module(it) => it.short_label(),
|
||||
ast::TypeAliasDef(it) => it.short_label(),
|
||||
ast::ConstDef(it) => it.short_label(),
|
||||
ast::StaticDef(it) => it.short_label(),
|
||||
ast::RecordFieldDef(it) => it.short_label(),
|
||||
ast::EnumVariant(it) => it.short_label(),
|
||||
ast::TypeAlias(it) => it.short_label(),
|
||||
ast::Const(it) => it.short_label(),
|
||||
ast::Static(it) => it.short_label(),
|
||||
ast::RecordField(it) => it.short_label(),
|
||||
ast::Variant(it) => it.short_label(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +446,7 @@ fn foo() { enum FooInner { } }
|
|||
5..13,
|
||||
),
|
||||
name: "FooInner",
|
||||
kind: ENUM_DEF,
|
||||
kind: ENUM,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"enum FooInner",
|
||||
|
@ -462,7 +462,7 @@ fn foo() { enum FooInner { } }
|
|||
34..42,
|
||||
),
|
||||
name: "FooInner",
|
||||
kind: ENUM_DEF,
|
||||
kind: ENUM,
|
||||
container_name: Some(
|
||||
"foo",
|
||||
),
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
//! FIXME: write short doc here
|
||||
|
||||
use ra_syntax::ast::{self, AstNode, NameOwner, TypeAscriptionOwner, VisibilityOwner};
|
||||
use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
|
||||
use stdx::format_to;
|
||||
|
||||
pub(crate) trait ShortLabel {
|
||||
fn short_label(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::FnDef {
|
||||
impl ShortLabel for ast::Fn {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
Some(crate::display::function_declaration(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::StructDef {
|
||||
impl ShortLabel for ast::Struct {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
short_label_from_node(self, "struct ")
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::UnionDef {
|
||||
impl ShortLabel for ast::Union {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
short_label_from_node(self, "union ")
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::EnumDef {
|
||||
impl ShortLabel for ast::Enum {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
short_label_from_node(self, "enum ")
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::TraitDef {
|
||||
impl ShortLabel for ast::Trait {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
if self.unsafe_token().is_some() {
|
||||
short_label_from_node(self, "unsafe trait ")
|
||||
|
@ -47,43 +47,43 @@ impl ShortLabel for ast::Module {
|
|||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::TypeAliasDef {
|
||||
impl ShortLabel for ast::TypeAlias {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
short_label_from_node(self, "type ")
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::ConstDef {
|
||||
impl ShortLabel for ast::Const {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
short_label_from_ascribed_node(self, "const ")
|
||||
short_label_from_ty(self, self.ty(), "const ")
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::StaticDef {
|
||||
impl ShortLabel for ast::Static {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
short_label_from_ascribed_node(self, "static ")
|
||||
short_label_from_ty(self, self.ty(), "static ")
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::RecordFieldDef {
|
||||
impl ShortLabel for ast::RecordField {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
short_label_from_ascribed_node(self, "")
|
||||
short_label_from_ty(self, self.ty(), "")
|
||||
}
|
||||
}
|
||||
|
||||
impl ShortLabel for ast::EnumVariant {
|
||||
impl ShortLabel for ast::Variant {
|
||||
fn short_label(&self) -> Option<String> {
|
||||
Some(self.name()?.text().to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn short_label_from_ascribed_node<T>(node: &T, prefix: &str) -> Option<String>
|
||||
fn short_label_from_ty<T>(node: &T, ty: Option<ast::Type>, prefix: &str) -> Option<String>
|
||||
where
|
||||
T: NameOwner + VisibilityOwner + TypeAscriptionOwner,
|
||||
T: NameOwner + VisibilityOwner,
|
||||
{
|
||||
let mut buf = short_label_from_node(node, prefix)?;
|
||||
|
||||
if let Some(type_ref) = node.ascribed_type() {
|
||||
if let Some(type_ref) = ty {
|
||||
format_to!(buf, ": {}", type_ref.syntax());
|
||||
}
|
||||
|
||||
|
|
|
@ -37,15 +37,15 @@ fn try_extend_selection(
|
|||
|
||||
let string_kinds = [COMMENT, STRING, RAW_STRING, BYTE_STRING, RAW_BYTE_STRING];
|
||||
let list_kinds = [
|
||||
RECORD_FIELD_PAT_LIST,
|
||||
RECORD_PAT_FIELD_LIST,
|
||||
MATCH_ARM_LIST,
|
||||
RECORD_FIELD_DEF_LIST,
|
||||
TUPLE_FIELD_DEF_LIST,
|
||||
RECORD_FIELD_LIST,
|
||||
ENUM_VARIANT_LIST,
|
||||
TUPLE_FIELD_LIST,
|
||||
RECORD_EXPR_FIELD_LIST,
|
||||
VARIANT_LIST,
|
||||
USE_TREE_LIST,
|
||||
TYPE_PARAM_LIST,
|
||||
TYPE_ARG_LIST,
|
||||
GENERIC_PARAM_LIST,
|
||||
GENERIC_ARG_LIST,
|
||||
TYPE_BOUND_LIST,
|
||||
PARAM_LIST,
|
||||
ARG_LIST,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ra_syntax::{
|
||||
ast::{self, AttrsOwner, NameOwner, TypeAscriptionOwner, TypeParamsOwner},
|
||||
ast::{self, AttrsOwner, GenericParamsOwner, NameOwner},
|
||||
match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, WalkEvent,
|
||||
};
|
||||
|
||||
|
@ -52,19 +52,12 @@ pub fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
|
|||
|
||||
fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
||||
fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> {
|
||||
decl_with_detail(node, None)
|
||||
}
|
||||
|
||||
fn decl_with_ascription<N: NameOwner + AttrsOwner + TypeAscriptionOwner>(
|
||||
node: N,
|
||||
) -> Option<StructureNode> {
|
||||
let ty = node.ascribed_type();
|
||||
decl_with_type_ref(node, ty)
|
||||
decl_with_detail(&node, None)
|
||||
}
|
||||
|
||||
fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
|
||||
node: N,
|
||||
type_ref: Option<ast::TypeRef>,
|
||||
node: &N,
|
||||
type_ref: Option<ast::Type>,
|
||||
) -> Option<StructureNode> {
|
||||
let detail = type_ref.map(|type_ref| {
|
||||
let mut detail = String::new();
|
||||
|
@ -75,7 +68,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
|||
}
|
||||
|
||||
fn decl_with_detail<N: NameOwner + AttrsOwner>(
|
||||
node: N,
|
||||
node: &N,
|
||||
detail: Option<String>,
|
||||
) -> Option<StructureNode> {
|
||||
let name = node.name()?;
|
||||
|
@ -111,9 +104,9 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
|||
|
||||
match_ast! {
|
||||
match node {
|
||||
ast::FnDef(it) => {
|
||||
ast::Fn(it) => {
|
||||
let mut detail = String::from("fn");
|
||||
if let Some(type_param_list) = it.type_param_list() {
|
||||
if let Some(type_param_list) = it.generic_param_list() {
|
||||
collapse_ws(type_param_list.syntax(), &mut detail);
|
||||
}
|
||||
if let Some(param_list) = it.param_list() {
|
||||
|
@ -124,24 +117,21 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
|
|||
collapse_ws(ret_type.syntax(), &mut detail);
|
||||
}
|
||||
|
||||
decl_with_detail(it, Some(detail))
|
||||
decl_with_detail(&it, Some(detail))
|
||||
},
|
||||
ast::StructDef(it) => decl(it),
|
||||
ast::UnionDef(it) => decl(it),
|
||||
ast::EnumDef(it) => decl(it),
|
||||
ast::EnumVariant(it) => decl(it),
|
||||
ast::TraitDef(it) => decl(it),
|
||||
ast::Struct(it) => decl(it),
|
||||
ast::Union(it) => decl(it),
|
||||
ast::Enum(it) => decl(it),
|
||||
ast::Variant(it) => decl(it),
|
||||
ast::Trait(it) => decl(it),
|
||||
ast::Module(it) => decl(it),
|
||||
ast::TypeAliasDef(it) => {
|
||||
let ty = it.type_ref();
|
||||
decl_with_type_ref(it, ty)
|
||||
},
|
||||
ast::RecordFieldDef(it) => decl_with_ascription(it),
|
||||
ast::ConstDef(it) => decl_with_ascription(it),
|
||||
ast::StaticDef(it) => decl_with_ascription(it),
|
||||
ast::ImplDef(it) => {
|
||||
let target_type = it.target_type()?;
|
||||
let target_trait = it.target_trait();
|
||||
ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty()),
|
||||
ast::RecordField(it) => decl_with_type_ref(&it, it.ty()),
|
||||
ast::Const(it) => decl_with_type_ref(&it, it.ty()),
|
||||
ast::Static(it) => decl_with_type_ref(&it, it.ty()),
|
||||
ast::Impl(it) => {
|
||||
let target_type = it.self_ty()?;
|
||||
let target_trait = it.trait_();
|
||||
let label = match target_trait {
|
||||
None => format!("impl {}", target_type.syntax().text()),
|
||||
Some(t) => {
|
||||
|
@ -238,7 +228,7 @@ fn very_obsolete() {}
|
|||
label: "Foo",
|
||||
navigation_range: 8..11,
|
||||
node_range: 1..26,
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
detail: None,
|
||||
deprecated: false,
|
||||
},
|
||||
|
@ -249,7 +239,7 @@ fn very_obsolete() {}
|
|||
label: "x",
|
||||
navigation_range: 18..19,
|
||||
node_range: 18..24,
|
||||
kind: RECORD_FIELD_DEF,
|
||||
kind: RECORD_FIELD,
|
||||
detail: Some(
|
||||
"i32",
|
||||
),
|
||||
|
@ -271,7 +261,7 @@ fn very_obsolete() {}
|
|||
label: "bar1",
|
||||
navigation_range: 43..47,
|
||||
node_range: 40..52,
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
detail: Some(
|
||||
"fn()",
|
||||
),
|
||||
|
@ -284,7 +274,7 @@ fn very_obsolete() {}
|
|||
label: "bar2",
|
||||
navigation_range: 60..64,
|
||||
node_range: 57..81,
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
detail: Some(
|
||||
"fn<T>(t: T) -> T",
|
||||
),
|
||||
|
@ -297,7 +287,7 @@ fn very_obsolete() {}
|
|||
label: "bar3",
|
||||
navigation_range: 89..93,
|
||||
node_range: 86..156,
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
detail: Some(
|
||||
"fn<A, B>(a: A, b: B) -> Vec< u32 >",
|
||||
),
|
||||
|
@ -308,7 +298,7 @@ fn very_obsolete() {}
|
|||
label: "E",
|
||||
navigation_range: 165..166,
|
||||
node_range: 160..180,
|
||||
kind: ENUM_DEF,
|
||||
kind: ENUM,
|
||||
detail: None,
|
||||
deprecated: false,
|
||||
},
|
||||
|
@ -319,7 +309,7 @@ fn very_obsolete() {}
|
|||
label: "X",
|
||||
navigation_range: 169..170,
|
||||
node_range: 169..170,
|
||||
kind: ENUM_VARIANT,
|
||||
kind: VARIANT,
|
||||
detail: None,
|
||||
deprecated: false,
|
||||
},
|
||||
|
@ -330,7 +320,7 @@ fn very_obsolete() {}
|
|||
label: "Y",
|
||||
navigation_range: 172..173,
|
||||
node_range: 172..178,
|
||||
kind: ENUM_VARIANT,
|
||||
kind: VARIANT,
|
||||
detail: None,
|
||||
deprecated: false,
|
||||
},
|
||||
|
@ -339,7 +329,7 @@ fn very_obsolete() {}
|
|||
label: "T",
|
||||
navigation_range: 186..187,
|
||||
node_range: 181..193,
|
||||
kind: TYPE_ALIAS_DEF,
|
||||
kind: TYPE_ALIAS,
|
||||
detail: Some(
|
||||
"()",
|
||||
),
|
||||
|
@ -350,7 +340,7 @@ fn very_obsolete() {}
|
|||
label: "S",
|
||||
navigation_range: 201..202,
|
||||
node_range: 194..213,
|
||||
kind: STATIC_DEF,
|
||||
kind: STATIC,
|
||||
detail: Some(
|
||||
"i32",
|
||||
),
|
||||
|
@ -361,7 +351,7 @@ fn very_obsolete() {}
|
|||
label: "C",
|
||||
navigation_range: 220..221,
|
||||
node_range: 214..232,
|
||||
kind: CONST_DEF,
|
||||
kind: CONST,
|
||||
detail: Some(
|
||||
"i32",
|
||||
),
|
||||
|
@ -372,7 +362,7 @@ fn very_obsolete() {}
|
|||
label: "impl E",
|
||||
navigation_range: 239..240,
|
||||
node_range: 234..243,
|
||||
kind: IMPL_DEF,
|
||||
kind: IMPL,
|
||||
detail: None,
|
||||
deprecated: false,
|
||||
},
|
||||
|
@ -381,7 +371,7 @@ fn very_obsolete() {}
|
|||
label: "impl fmt::Debug for E",
|
||||
navigation_range: 265..266,
|
||||
node_range: 245..269,
|
||||
kind: IMPL_DEF,
|
||||
kind: IMPL,
|
||||
detail: None,
|
||||
deprecated: false,
|
||||
},
|
||||
|
@ -417,7 +407,7 @@ fn very_obsolete() {}
|
|||
label: "obsolete",
|
||||
navigation_range: 428..436,
|
||||
node_range: 411..441,
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
detail: Some(
|
||||
"fn()",
|
||||
),
|
||||
|
@ -428,7 +418,7 @@ fn very_obsolete() {}
|
|||
label: "very_obsolete",
|
||||
navigation_range: 481..494,
|
||||
node_range: 443..499,
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
detail: Some(
|
||||
"fn()",
|
||||
),
|
||||
|
|
|
@ -58,7 +58,7 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
|
|||
}
|
||||
NodeOrToken::Node(node) => {
|
||||
// Fold groups of imports
|
||||
if node.kind() == USE_ITEM && !visited_imports.contains(&node) {
|
||||
if node.kind() == USE && !visited_imports.contains(&node) {
|
||||
if let Some(range) = contiguous_range_for_group(&node, &mut visited_imports) {
|
||||
res.push(Fold { range, kind: FoldKind::Imports })
|
||||
}
|
||||
|
@ -83,17 +83,18 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec<Fold> {
|
|||
fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
|
||||
match kind {
|
||||
COMMENT => Some(FoldKind::Comment),
|
||||
USE_ITEM => Some(FoldKind::Imports),
|
||||
USE => Some(FoldKind::Imports),
|
||||
ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList),
|
||||
RECORD_FIELD_DEF_LIST
|
||||
| RECORD_FIELD_PAT_LIST
|
||||
ASSOC_ITEM_LIST
|
||||
| RECORD_FIELD_LIST
|
||||
| RECORD_PAT_FIELD_LIST
|
||||
| RECORD_EXPR_FIELD_LIST
|
||||
| ITEM_LIST
|
||||
| EXTERN_ITEM_LIST
|
||||
| USE_TREE_LIST
|
||||
| BLOCK_EXPR
|
||||
| MATCH_ARM_LIST
|
||||
| ENUM_VARIANT_LIST
|
||||
| VARIANT_LIST
|
||||
| TOKEN_TREE => Some(FoldKind::Block),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -336,6 +337,26 @@ fn main() <fold block>{
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_folds_structs() {
|
||||
check(
|
||||
r#"
|
||||
struct Foo <fold block>{
|
||||
}</fold>
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_folds_traits() {
|
||||
check(
|
||||
r#"
|
||||
trait Foo <fold block>{
|
||||
}</fold>
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_folds_macros() {
|
||||
check(
|
||||
|
|
|
@ -23,12 +23,12 @@ pub(crate) fn goto_implementation(
|
|||
|
||||
let krate = sema.to_module_def(position.file_id)?.krate();
|
||||
|
||||
if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) {
|
||||
if let Some(nominal_def) = find_node_at_offset::<ast::AdtDef>(&syntax, position.offset) {
|
||||
return Some(RangeInfo::new(
|
||||
nominal_def.syntax().text_range(),
|
||||
impls_for_def(&sema, &nominal_def, krate)?,
|
||||
));
|
||||
} else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) {
|
||||
} else if let Some(trait_def) = find_node_at_offset::<ast::Trait>(&syntax, position.offset) {
|
||||
return Some(RangeInfo::new(
|
||||
trait_def.syntax().text_range(),
|
||||
impls_for_trait(&sema, &trait_def, krate)?,
|
||||
|
@ -40,13 +40,13 @@ pub(crate) fn goto_implementation(
|
|||
|
||||
fn impls_for_def(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
node: &ast::NominalDef,
|
||||
node: &ast::AdtDef,
|
||||
krate: Crate,
|
||||
) -> Option<Vec<NavigationTarget>> {
|
||||
let ty = match node {
|
||||
ast::NominalDef::StructDef(def) => sema.to_def(def)?.ty(sema.db),
|
||||
ast::NominalDef::EnumDef(def) => sema.to_def(def)?.ty(sema.db),
|
||||
ast::NominalDef::UnionDef(def) => sema.to_def(def)?.ty(sema.db),
|
||||
ast::AdtDef::Struct(def) => sema.to_def(def)?.ty(sema.db),
|
||||
ast::AdtDef::Enum(def) => sema.to_def(def)?.ty(sema.db),
|
||||
ast::AdtDef::Union(def) => sema.to_def(def)?.ty(sema.db),
|
||||
};
|
||||
|
||||
let impls = ImplDef::all_in_crate(sema.db, krate);
|
||||
|
@ -62,7 +62,7 @@ fn impls_for_def(
|
|||
|
||||
fn impls_for_trait(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
node: &ast::TraitDef,
|
||||
node: &ast::Trait,
|
||||
krate: Crate,
|
||||
) -> Option<Vec<NavigationTarget>> {
|
||||
let tr = sema.to_def(node)?;
|
||||
|
|
|
@ -1361,7 +1361,7 @@ fn foo_<|>test() {}
|
|||
11..19,
|
||||
),
|
||||
name: "foo_test",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -1443,7 +1443,7 @@ fn main() { let s<|>t = S{ f1:0 }; }
|
|||
7..8,
|
||||
),
|
||||
name: "S",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S",
|
||||
|
@ -1482,7 +1482,7 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; }
|
|||
24..25,
|
||||
),
|
||||
name: "S",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S",
|
||||
|
@ -1501,7 +1501,7 @@ fn main() { let s<|>t = S{ f1:Arg(0) }; }
|
|||
7..10,
|
||||
),
|
||||
name: "Arg",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct Arg",
|
||||
|
@ -1540,7 +1540,7 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
|
|||
24..25,
|
||||
),
|
||||
name: "S",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S",
|
||||
|
@ -1559,7 +1559,7 @@ fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; }
|
|||
7..10,
|
||||
),
|
||||
name: "Arg",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct Arg",
|
||||
|
@ -1601,7 +1601,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
|
|||
7..8,
|
||||
),
|
||||
name: "A",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct A",
|
||||
|
@ -1620,7 +1620,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
|
|||
22..23,
|
||||
),
|
||||
name: "B",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct B",
|
||||
|
@ -1639,7 +1639,7 @@ fn main() { let s<|>t = (A(1), B(2), M::C(3) ); }
|
|||
53..54,
|
||||
),
|
||||
name: "C",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"pub struct C",
|
||||
|
@ -1678,7 +1678,7 @@ fn main() { let s<|>t = foo(); }
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -1718,7 +1718,7 @@ fn main() { let s<|>t = foo(); }
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -1737,7 +1737,7 @@ fn main() { let s<|>t = foo(); }
|
|||
23..24,
|
||||
),
|
||||
name: "S",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S",
|
||||
|
@ -1777,7 +1777,7 @@ fn main() { let s<|>t = foo(); }
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -1796,7 +1796,7 @@ fn main() { let s<|>t = foo(); }
|
|||
19..22,
|
||||
),
|
||||
name: "Bar",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Bar",
|
||||
|
@ -1839,7 +1839,7 @@ fn main() { let s<|>t = foo(); }
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -1858,7 +1858,7 @@ fn main() { let s<|>t = foo(); }
|
|||
22..25,
|
||||
),
|
||||
name: "Bar",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Bar",
|
||||
|
@ -1877,7 +1877,7 @@ fn main() { let s<|>t = foo(); }
|
|||
39..41,
|
||||
),
|
||||
name: "S1",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S1",
|
||||
|
@ -1896,7 +1896,7 @@ fn main() { let s<|>t = foo(); }
|
|||
52..54,
|
||||
),
|
||||
name: "S2",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S2",
|
||||
|
@ -1933,7 +1933,7 @@ fn foo(ar<|>g: &impl Foo) {}
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -1973,7 +1973,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -1992,7 +1992,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
|
|||
19..22,
|
||||
),
|
||||
name: "Bar",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Bar",
|
||||
|
@ -2011,7 +2011,7 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {}
|
|||
36..37,
|
||||
),
|
||||
name: "S",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S",
|
||||
|
@ -2049,7 +2049,7 @@ fn foo(ar<|>g: &impl Foo<S>) {}
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -2068,7 +2068,7 @@ fn foo(ar<|>g: &impl Foo<S>) {}
|
|||
23..24,
|
||||
),
|
||||
name: "S",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S",
|
||||
|
@ -2111,7 +2111,7 @@ fn main() { let s<|>t = foo(); }
|
|||
49..50,
|
||||
),
|
||||
name: "B",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct B",
|
||||
|
@ -2130,7 +2130,7 @@ fn main() { let s<|>t = foo(); }
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -2167,7 +2167,7 @@ fn foo(ar<|>g: &dyn Foo) {}
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -2205,7 +2205,7 @@ fn foo(ar<|>g: &dyn Foo<S>) {}
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
@ -2224,7 +2224,7 @@ fn foo(ar<|>g: &dyn Foo<S>) {}
|
|||
23..24,
|
||||
),
|
||||
name: "S",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S",
|
||||
|
@ -2265,7 +2265,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
|
|||
6..15,
|
||||
),
|
||||
name: "ImplTrait",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait ImplTrait",
|
||||
|
@ -2284,7 +2284,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
|
|||
50..51,
|
||||
),
|
||||
name: "B",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct B",
|
||||
|
@ -2303,7 +2303,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
|
|||
28..36,
|
||||
),
|
||||
name: "DynTrait",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait DynTrait",
|
||||
|
@ -2322,7 +2322,7 @@ fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
|
|||
65..66,
|
||||
),
|
||||
name: "S",
|
||||
kind: STRUCT_DEF,
|
||||
kind: STRUCT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"struct S",
|
||||
|
@ -2370,7 +2370,7 @@ fn main() { let s<|>t = test().get(); }
|
|||
6..9,
|
||||
),
|
||||
name: "Foo",
|
||||
kind: TRAIT_DEF,
|
||||
kind: TRAIT,
|
||||
container_name: None,
|
||||
description: Some(
|
||||
"trait Foo",
|
||||
|
|
|
@ -2,7 +2,7 @@ use hir::{Adt, Callable, HirDisplay, Semantics, Type};
|
|||
use ra_ide_db::RootDatabase;
|
||||
use ra_prof::profile;
|
||||
use ra_syntax::{
|
||||
ast::{self, ArgListOwner, AstNode, TypeAscriptionOwner},
|
||||
ast::{self, ArgListOwner, AstNode},
|
||||
match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T,
|
||||
};
|
||||
use stdx::to_lower_snake_case;
|
||||
|
@ -78,7 +78,7 @@ pub(crate) fn inlay_hints(
|
|||
match node {
|
||||
ast::CallExpr(it) => { get_param_name_hints(&mut res, &sema, config, ast::Expr::from(it)); },
|
||||
ast::MethodCallExpr(it) => { get_param_name_hints(&mut res, &sema, config, ast::Expr::from(it)); },
|
||||
ast::BindPat(it) => { get_bind_pat_hints(&mut res, &sema, config, it); },
|
||||
ast::IdentPat(it) => { get_bind_pat_hints(&mut res, &sema, config, it); },
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ fn get_chaining_hints(
|
|||
return None;
|
||||
}
|
||||
|
||||
if matches!(expr, ast::Expr::RecordLit(_)) {
|
||||
if matches!(expr, ast::Expr::RecordExpr(_)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ fn get_param_name_hints(
|
|||
Either::Left(self_param) => Some((self_param.to_string(), arg)),
|
||||
Either::Right(pat) => {
|
||||
let param_name = match pat {
|
||||
ast::Pat::BindPat(it) => it.name()?.to_string(),
|
||||
ast::Pat::IdentPat(it) => it.name()?.to_string(),
|
||||
it => it.to_string(),
|
||||
};
|
||||
Some((param_name, arg))
|
||||
|
@ -182,7 +182,7 @@ fn get_bind_pat_hints(
|
|||
acc: &mut Vec<InlayHint>,
|
||||
sema: &Semantics<RootDatabase>,
|
||||
config: &InlayHintsConfig,
|
||||
pat: ast::BindPat,
|
||||
pat: ast::IdentPat,
|
||||
) -> Option<()> {
|
||||
if !config.type_hints {
|
||||
return None;
|
||||
|
@ -202,7 +202,7 @@ fn get_bind_pat_hints(
|
|||
Some(())
|
||||
}
|
||||
|
||||
fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ty: &Type) -> bool {
|
||||
fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &Type) -> bool {
|
||||
if let Some(Adt::Enum(enum_data)) = pat_ty.as_adt() {
|
||||
let pat_text = bind_pat.to_string();
|
||||
enum_data
|
||||
|
@ -215,7 +215,11 @@ fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ty: &Type
|
|||
}
|
||||
}
|
||||
|
||||
fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_ty: &Type) -> bool {
|
||||
fn should_not_display_type_hint(
|
||||
db: &RootDatabase,
|
||||
bind_pat: &ast::IdentPat,
|
||||
pat_ty: &Type,
|
||||
) -> bool {
|
||||
if pat_ty.is_unknown() {
|
||||
return true;
|
||||
}
|
||||
|
@ -230,10 +234,10 @@ fn should_not_display_type_hint(db: &RootDatabase, bind_pat: &ast::BindPat, pat_
|
|||
match_ast! {
|
||||
match node {
|
||||
ast::LetStmt(it) => {
|
||||
return it.ascribed_type().is_some()
|
||||
return it.ty().is_some()
|
||||
},
|
||||
ast::Param(it) => {
|
||||
return it.ascribed_type().is_some()
|
||||
return it.ty().is_some()
|
||||
},
|
||||
ast::MatchArm(_it) => {
|
||||
return pat_is_enum_variant(db, bind_pat, pat_ty);
|
||||
|
|
|
@ -510,9 +510,10 @@ impl Analysis {
|
|||
query: &str,
|
||||
parse_only: bool,
|
||||
position: FilePosition,
|
||||
selections: Vec<FileRange>,
|
||||
) -> Cancelable<Result<SourceChange, SsrError>> {
|
||||
self.with_db(|db| {
|
||||
let edits = ssr::parse_search_replace(query, parse_only, db, position)?;
|
||||
let edits = ssr::parse_search_replace(query, parse_only, db, position, selections)?;
|
||||
Ok(SourceChange::from(edits))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Optio
|
|||
let stmt = find_node_at_offset::<ast::LetStmt>(syntax, range.start())?;
|
||||
if stmt.initializer().is_some() {
|
||||
let pat = stmt.pat()?;
|
||||
if let ast::Pat::BindPat(it) = pat {
|
||||
if let ast::Pat::IdentPat(it) = pat {
|
||||
if it.mut_token().is_some() {
|
||||
return Some(ReferenceAccess::Write);
|
||||
}
|
||||
|
@ -172,16 +172,16 @@ fn get_struct_def_name_for_struct_literal_search(
|
|||
if let Some(name) =
|
||||
sema.find_node_at_offset_with_descend::<ast::Name>(&syntax, left.text_range().start())
|
||||
{
|
||||
return name.syntax().ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name());
|
||||
return name.syntax().ancestors().find_map(ast::Struct::cast).and_then(|l| l.name());
|
||||
}
|
||||
if sema
|
||||
.find_node_at_offset_with_descend::<ast::TypeParamList>(
|
||||
.find_node_at_offset_with_descend::<ast::GenericParamList>(
|
||||
&syntax,
|
||||
left.text_range().start(),
|
||||
)
|
||||
.is_some()
|
||||
{
|
||||
return left.ancestors().find_map(ast::StructDef::cast).and_then(|l| l.name());
|
||||
return left.ancestors().find_map(ast::Struct::cast).and_then(|l| l.name());
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -212,7 +212,7 @@ fn main() {
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"Foo STRUCT_DEF FileId(1) 0..26 7..10 Other",
|
||||
"Foo STRUCT FileId(1) 0..26 7..10 Other",
|
||||
&["FileId(1) 101..104 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ struct Foo<|> {}
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"Foo STRUCT_DEF FileId(1) 0..13 7..10 Other",
|
||||
"Foo STRUCT FileId(1) 0..13 7..10 Other",
|
||||
&["FileId(1) 41..44 Other", "FileId(1) 54..57 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ struct Foo<T> <|>{}
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"Foo STRUCT_DEF FileId(1) 0..16 7..10 Other",
|
||||
"Foo STRUCT FileId(1) 0..16 7..10 Other",
|
||||
&["FileId(1) 64..67 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ fn main() {
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"Foo STRUCT_DEF FileId(1) 0..16 7..10 Other",
|
||||
"Foo STRUCT FileId(1) 0..16 7..10 Other",
|
||||
&["FileId(1) 54..57 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ fn main() {
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"i BIND_PAT FileId(1) 24..25 Other Write",
|
||||
"i IDENT_PAT FileId(1) 24..25 Other Write",
|
||||
&[
|
||||
"FileId(1) 50..51 Other Write",
|
||||
"FileId(1) 54..55 Other Read",
|
||||
|
@ -316,7 +316,7 @@ fn bar() {
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"spam BIND_PAT FileId(1) 19..23 Other",
|
||||
"spam IDENT_PAT FileId(1) 19..23 Other",
|
||||
&["FileId(1) 34..38 Other Read", "FileId(1) 41..45 Other Read"],
|
||||
);
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ fn foo(i : u32) -> u32 {
|
|||
}
|
||||
"#,
|
||||
);
|
||||
check_result(refs, "i BIND_PAT FileId(1) 7..8 Other", &["FileId(1) 29..30 Other Read"]);
|
||||
check_result(refs, "i IDENT_PAT FileId(1) 7..8 Other", &["FileId(1) 29..30 Other Read"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -342,7 +342,7 @@ fn foo(i<|> : u32) -> u32 {
|
|||
}
|
||||
"#,
|
||||
);
|
||||
check_result(refs, "i BIND_PAT FileId(1) 7..8 Other", &["FileId(1) 29..30 Other Read"]);
|
||||
check_result(refs, "i IDENT_PAT FileId(1) 7..8 Other", &["FileId(1) 29..30 Other Read"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -361,7 +361,7 @@ fn main(s: Foo) {
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"spam RECORD_FIELD_DEF FileId(1) 17..30 21..25 Other",
|
||||
"spam RECORD_FIELD FileId(1) 17..30 21..25 Other",
|
||||
&["FileId(1) 67..71 Other Read"],
|
||||
);
|
||||
}
|
||||
|
@ -376,7 +376,7 @@ impl Foo {
|
|||
}
|
||||
"#,
|
||||
);
|
||||
check_result(refs, "f FN_DEF FileId(1) 27..43 30..31 Other", &[]);
|
||||
check_result(refs, "f FN FileId(1) 27..43 30..31 Other", &[]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -390,7 +390,7 @@ enum Foo {
|
|||
}
|
||||
"#,
|
||||
);
|
||||
check_result(refs, "B ENUM_VARIANT FileId(1) 22..23 22..23 Other", &[]);
|
||||
check_result(refs, "B VARIANT FileId(1) 22..23 22..23 Other", &[]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -431,7 +431,7 @@ fn f() {
|
|||
let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
|
||||
check_result(
|
||||
refs,
|
||||
"Foo STRUCT_DEF FileId(2) 17..51 28..31 Other",
|
||||
"Foo STRUCT FileId(2) 17..51 28..31 Other",
|
||||
&["FileId(1) 53..56 StructLiteral", "FileId(3) 79..82 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
@ -486,7 +486,7 @@ pub(super) struct Foo<|> {
|
|||
let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
|
||||
check_result(
|
||||
refs,
|
||||
"Foo STRUCT_DEF FileId(3) 0..41 18..21 Other",
|
||||
"Foo STRUCT FileId(3) 0..41 18..21 Other",
|
||||
&["FileId(2) 20..23 Other", "FileId(2) 47..50 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
@ -514,7 +514,7 @@ pub(super) struct Foo<|> {
|
|||
let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
|
||||
check_result(
|
||||
refs,
|
||||
"quux FN_DEF FileId(1) 19..35 26..30 Other",
|
||||
"quux FN FileId(1) 19..35 26..30 Other",
|
||||
&["FileId(2) 16..20 StructLiteral", "FileId(3) 16..20 StructLiteral"],
|
||||
);
|
||||
|
||||
|
@ -522,7 +522,7 @@ pub(super) struct Foo<|> {
|
|||
analysis.find_all_refs(pos, Some(SearchScope::single_file(bar))).unwrap().unwrap();
|
||||
check_result(
|
||||
refs,
|
||||
"quux FN_DEF FileId(1) 19..35 26..30 Other",
|
||||
"quux FN FileId(1) 19..35 26..30 Other",
|
||||
&["FileId(3) 16..20 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
@ -559,7 +559,7 @@ fn foo() {
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"i BIND_PAT FileId(1) 23..24 Other Write",
|
||||
"i IDENT_PAT FileId(1) 23..24 Other Write",
|
||||
&["FileId(1) 34..35 Other Write", "FileId(1) 38..39 Other Read"],
|
||||
);
|
||||
}
|
||||
|
@ -580,7 +580,7 @@ fn foo() {
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"f RECORD_FIELD_DEF FileId(1) 15..21 15..16 Other",
|
||||
"f RECORD_FIELD FileId(1) 15..21 15..16 Other",
|
||||
&["FileId(1) 55..56 Other Read", "FileId(1) 68..69 Other Write"],
|
||||
);
|
||||
}
|
||||
|
@ -595,7 +595,7 @@ fn foo() {
|
|||
}
|
||||
"#,
|
||||
);
|
||||
check_result(refs, "i BIND_PAT FileId(1) 19..20 Other", &["FileId(1) 26..27 Other Write"]);
|
||||
check_result(refs, "i IDENT_PAT FileId(1) 19..20 Other", &["FileId(1) 26..27 Other Write"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -619,7 +619,7 @@ fn main() {
|
|||
);
|
||||
check_result(
|
||||
refs,
|
||||
"new FN_DEF FileId(1) 54..101 61..64 Other",
|
||||
"new FN FileId(1) 54..101 61..64 Other",
|
||||
&["FileId(1) 146..149 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
@ -646,7 +646,7 @@ fn main() {
|
|||
let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
|
||||
check_result(
|
||||
refs,
|
||||
"f FN_DEF FileId(1) 26..35 29..30 Other",
|
||||
"f FN FileId(1) 26..35 29..30 Other",
|
||||
&["FileId(2) 11..12 Other", "FileId(2) 28..29 StructLiteral"],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ use ra_ide_db::{
|
|||
RootDatabase,
|
||||
};
|
||||
use ra_syntax::{
|
||||
algo::find_node_at_offset, ast, ast::NameOwner, ast::TypeAscriptionOwner,
|
||||
algo::find_node_at_offset,
|
||||
ast::{self, NameOwner},
|
||||
lex_single_valid_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken,
|
||||
};
|
||||
use ra_text_edit::TextEdit;
|
||||
|
@ -149,14 +150,14 @@ fn rename_to_self(
|
|||
let source_file = sema.parse(position.file_id);
|
||||
let syn = source_file.syntax();
|
||||
|
||||
let fn_def = find_node_at_offset::<ast::FnDef>(syn, position.offset)?;
|
||||
let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)?;
|
||||
let params = fn_def.param_list()?;
|
||||
if params.self_param().is_some() {
|
||||
return None; // method already has self param
|
||||
}
|
||||
let first_param = params.params().next()?;
|
||||
let mutable = match first_param.ascribed_type() {
|
||||
Some(ast::TypeRef::ReferenceType(rt)) => rt.mut_token().is_some(),
|
||||
let mutable = match first_param.ty() {
|
||||
Some(ast::Type::RefType(rt)) => rt.mut_token().is_some(),
|
||||
_ => return None, // not renaming other types
|
||||
};
|
||||
|
||||
|
@ -192,15 +193,14 @@ fn text_edit_from_self_param(
|
|||
self_param: &ast::SelfParam,
|
||||
new_name: &str,
|
||||
) -> Option<TextEdit> {
|
||||
fn target_type_name(impl_def: &ast::ImplDef) -> Option<String> {
|
||||
if let Some(ast::TypeRef::PathType(p)) = impl_def.target_type() {
|
||||
fn target_type_name(impl_def: &ast::Impl) -> Option<String> {
|
||||
if let Some(ast::Type::PathType(p)) = impl_def.self_ty() {
|
||||
return Some(p.path()?.segment()?.name_ref()?.text().to_string());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
let impl_def =
|
||||
find_node_at_offset::<ast::ImplDef>(syn, self_param.syntax().text_range().start())?;
|
||||
let impl_def = find_node_at_offset::<ast::Impl>(syn, self_param.syntax().text_range().start())?;
|
||||
let type_name = target_type_name(&impl_def)?;
|
||||
|
||||
let mut replacement_text = String::from(new_name);
|
||||
|
@ -221,7 +221,7 @@ fn rename_self_to_param(
|
|||
let syn = source_file.syntax();
|
||||
|
||||
let text = sema.db.file_text(position.file_id);
|
||||
let fn_def = find_node_at_offset::<ast::FnDef>(syn, position.offset)?;
|
||||
let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)?;
|
||||
let search_range = fn_def.syntax().text_range();
|
||||
|
||||
let mut edits: Vec<SourceFileEdit> = vec![];
|
||||
|
|
|
@ -102,7 +102,7 @@ pub(crate) fn runnable(
|
|||
) -> Option<Runnable> {
|
||||
match_ast! {
|
||||
match item {
|
||||
ast::FnDef(it) => runnable_fn(sema, it, file_id),
|
||||
ast::Fn(it) => runnable_fn(sema, it, file_id),
|
||||
ast::Module(it) => runnable_mod(sema, it, file_id),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ pub(crate) fn runnable(
|
|||
|
||||
fn runnable_fn(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
fn_def: ast::FnDef,
|
||||
fn_def: ast::Fn,
|
||||
file_id: FileId,
|
||||
) -> Option<Runnable> {
|
||||
let name_string = fn_def.name()?.text().to_string();
|
||||
|
@ -188,7 +188,7 @@ pub struct TestAttr {
|
|||
}
|
||||
|
||||
impl TestAttr {
|
||||
fn from_fn(fn_def: &ast::FnDef) -> TestAttr {
|
||||
fn from_fn(fn_def: &ast::Fn) -> TestAttr {
|
||||
let ignore = fn_def
|
||||
.attrs()
|
||||
.filter_map(|attr| attr.simple_name())
|
||||
|
@ -203,7 +203,7 @@ impl TestAttr {
|
|||
///
|
||||
/// It may produce false positives, for example, `#[wasm_bindgen_test]` requires a different command to run the test,
|
||||
/// but it's better than not to have the runnables for the tests at all.
|
||||
fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
|
||||
fn has_test_related_attribute(fn_def: &ast::Fn) -> bool {
|
||||
fn_def
|
||||
.attrs()
|
||||
.filter_map(|attr| attr.path())
|
||||
|
@ -211,7 +211,7 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
|
|||
.any(|attribute_text| attribute_text.contains("test"))
|
||||
}
|
||||
|
||||
fn has_doc_test(fn_def: &ast::FnDef) -> bool {
|
||||
fn has_doc_test(fn_def: &ast::Fn) -> bool {
|
||||
fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```"))
|
||||
}
|
||||
|
||||
|
@ -220,15 +220,7 @@ fn runnable_mod(
|
|||
module: ast::Module,
|
||||
file_id: FileId,
|
||||
) -> Option<Runnable> {
|
||||
let has_test_function = module
|
||||
.item_list()?
|
||||
.items()
|
||||
.filter_map(|it| match it {
|
||||
ast::ModuleItem::FnDef(it) => Some(it),
|
||||
_ => None,
|
||||
})
|
||||
.any(|f| has_test_related_attribute(&f));
|
||||
if !has_test_function {
|
||||
if !has_test_function_or_multiple_test_submodules(&module) {
|
||||
return None;
|
||||
}
|
||||
let module_def = sema.to_def(&module)?;
|
||||
|
@ -246,6 +238,34 @@ fn runnable_mod(
|
|||
Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs })
|
||||
}
|
||||
|
||||
// We could create runnables for modules with number_of_test_submodules > 0,
|
||||
// but that bloats the runnables for no real benefit, since all tests can be run by the submodule already
|
||||
fn has_test_function_or_multiple_test_submodules(module: &ast::Module) -> bool {
|
||||
if let Some(item_list) = module.item_list() {
|
||||
let mut number_of_test_submodules = 0;
|
||||
|
||||
for item in item_list.items() {
|
||||
match item {
|
||||
ast::Item::Fn(f) => {
|
||||
if has_test_related_attribute(&f) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ast::Item::Module(submodule) => {
|
||||
if has_test_function_or_multiple_test_submodules(&submodule) {
|
||||
number_of_test_submodules += 1;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
number_of_test_submodules > 1
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use expect::{expect, Expect};
|
||||
|
@ -300,7 +320,7 @@ fn bench() {}
|
|||
4..8,
|
||||
),
|
||||
name: "main",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -318,7 +338,7 @@ fn bench() {}
|
|||
26..34,
|
||||
),
|
||||
name: "test_foo",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -343,7 +363,7 @@ fn bench() {}
|
|||
62..70,
|
||||
),
|
||||
name: "test_foo",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -368,7 +388,7 @@ fn bench() {}
|
|||
89..94,
|
||||
),
|
||||
name: "bench",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -411,7 +431,7 @@ fn foo() {}
|
|||
4..8,
|
||||
),
|
||||
name: "main",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -427,7 +447,7 @@ fn foo() {}
|
|||
full_range: 15..57,
|
||||
focus_range: None,
|
||||
name: "foo",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -473,7 +493,7 @@ impl Data {
|
|||
4..8,
|
||||
),
|
||||
name: "main",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -489,7 +509,7 @@ impl Data {
|
|||
full_range: 44..98,
|
||||
focus_range: None,
|
||||
name: "foo",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -550,7 +570,7 @@ mod test_mod {
|
|||
35..44,
|
||||
),
|
||||
name: "test_foo1",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -571,19 +591,33 @@ mod test_mod {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_runnables_one_depth_layer_module() {
|
||||
fn only_modules_with_test_functions_or_more_than_one_test_submodule_have_runners() {
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
<|>
|
||||
mod foo {
|
||||
mod test_mod {
|
||||
#[test]
|
||||
fn test_foo1() {}
|
||||
mod root_tests {
|
||||
mod nested_tests_0 {
|
||||
mod nested_tests_1 {
|
||||
#[test]
|
||||
fn nested_test_11() {}
|
||||
|
||||
#[test]
|
||||
fn nested_test_12() {}
|
||||
}
|
||||
|
||||
mod nested_tests_2 {
|
||||
#[test]
|
||||
fn nested_test_2() {}
|
||||
}
|
||||
|
||||
mod nested_tests_3 {}
|
||||
}
|
||||
|
||||
mod nested_tests_4 {}
|
||||
}
|
||||
"#,
|
||||
&[&TEST, &TEST],
|
||||
&[&TEST, &TEST, &TEST, &TEST, &TEST, &TEST],
|
||||
expect![[r#"
|
||||
[
|
||||
Runnable {
|
||||
|
@ -591,18 +625,18 @@ mod foo {
|
|||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 15..77,
|
||||
full_range: 22..323,
|
||||
focus_range: Some(
|
||||
19..27,
|
||||
26..40,
|
||||
),
|
||||
name: "test_mod",
|
||||
name: "nested_tests_0",
|
||||
kind: MODULE,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: TestMod {
|
||||
path: "foo::test_mod",
|
||||
path: "root_tests::nested_tests_0",
|
||||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
|
@ -611,19 +645,39 @@ mod foo {
|
|||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 38..71,
|
||||
full_range: 51..192,
|
||||
focus_range: Some(
|
||||
57..66,
|
||||
55..69,
|
||||
),
|
||||
name: "test_foo1",
|
||||
kind: FN_DEF,
|
||||
name: "nested_tests_1",
|
||||
kind: MODULE,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: TestMod {
|
||||
path: "root_tests::nested_tests_0::nested_tests_1",
|
||||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
Runnable {
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 84..126,
|
||||
focus_range: Some(
|
||||
107..121,
|
||||
),
|
||||
name: "nested_test_11",
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: Test {
|
||||
test_id: Path(
|
||||
"foo::test_mod::test_foo1",
|
||||
"root_tests::nested_tests_0::nested_tests_1::nested_test_11",
|
||||
),
|
||||
attr: TestAttr {
|
||||
ignore: false,
|
||||
|
@ -631,46 +685,28 @@ mod foo {
|
|||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
]
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_runnables_multiple_depth_module() {
|
||||
check(
|
||||
r#"
|
||||
//- /lib.rs
|
||||
<|>
|
||||
mod foo {
|
||||
mod bar {
|
||||
mod test_mod {
|
||||
#[test]
|
||||
fn test_foo1() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
"#,
|
||||
&[&TEST, &TEST],
|
||||
expect![[r#"
|
||||
[
|
||||
Runnable {
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 33..107,
|
||||
full_range: 140..182,
|
||||
focus_range: Some(
|
||||
37..45,
|
||||
163..177,
|
||||
),
|
||||
name: "test_mod",
|
||||
kind: MODULE,
|
||||
name: "nested_test_12",
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: TestMod {
|
||||
path: "foo::bar::test_mod",
|
||||
kind: Test {
|
||||
test_id: Path(
|
||||
"root_tests::nested_tests_0::nested_tests_1::nested_test_12",
|
||||
),
|
||||
attr: TestAttr {
|
||||
ignore: false,
|
||||
},
|
||||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
|
@ -679,19 +715,39 @@ mod foo {
|
|||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 60..97,
|
||||
full_range: 202..286,
|
||||
focus_range: Some(
|
||||
83..92,
|
||||
206..220,
|
||||
),
|
||||
name: "test_foo1",
|
||||
kind: FN_DEF,
|
||||
name: "nested_tests_2",
|
||||
kind: MODULE,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: TestMod {
|
||||
path: "root_tests::nested_tests_0::nested_tests_2",
|
||||
},
|
||||
cfg_exprs: [],
|
||||
},
|
||||
Runnable {
|
||||
nav: NavigationTarget {
|
||||
file_id: FileId(
|
||||
1,
|
||||
),
|
||||
full_range: 235..276,
|
||||
focus_range: Some(
|
||||
258..271,
|
||||
),
|
||||
name: "nested_test_2",
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
},
|
||||
kind: Test {
|
||||
test_id: Path(
|
||||
"foo::bar::test_mod::test_foo1",
|
||||
"root_tests::nested_tests_0::nested_tests_2::nested_test_2",
|
||||
),
|
||||
attr: TestAttr {
|
||||
ignore: false,
|
||||
|
@ -727,7 +783,7 @@ fn test_foo1() {}
|
|||
36..45,
|
||||
),
|
||||
name: "test_foo1",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
@ -775,7 +831,7 @@ fn test_foo1() {}
|
|||
58..67,
|
||||
),
|
||||
name: "test_foo1",
|
||||
kind: FN_DEF,
|
||||
kind: FN,
|
||||
container_name: None,
|
||||
description: None,
|
||||
docs: None,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue