Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry 2020-08-09 20:35:51 +07:00
commit 8068302fef
478 changed files with 9538 additions and 10722 deletions

View File

@ -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
View File

@ -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",
]

View File

@ -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" }

View File

@ -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

View File

@ -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()

View File

@ -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();

View File

@ -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()

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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())]),

View File

@ -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;
}

View File

@ -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);

View 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) {}
",
)
}
}

View File

@ -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,

View File

@ -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));
}
}

View File

@ -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),

View File

@ -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()?;

View File

@ -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()

View File

@ -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);

View File

@ -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() {

View File

@ -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");

View File

@ -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;

View File

@ -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() {

View File

@ -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(

View File

@ -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()?)))

View File

@ -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)]

View File

@ -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
}

View File

@ -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};

View File

@ -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);
}"#,
);
}
}

View File

@ -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,
}
};

View File

@ -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)
};

View File

@ -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));

View File

@ -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 {
}
",
);

View File

@ -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)

View File

@ -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,

View File

@ -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(

View File

@ -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(),
}
}

View File

@ -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 {

View File

@ -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" }

View File

@ -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());

View File

@ -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() {

View File

@ -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())

View File

@ -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 {

View File

@ -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,
}
};

View File

@ -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

View File

@ -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())),
},
);

View File

@ -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 })
}
}

View File

@ -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()
}
}

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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)]

View File

@ -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,
}

View File

@ -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) }
"#]],
);

View File

@ -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();

View File

@ -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,

View File

@ -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 {

View File

@ -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)
}

View File

@ -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),

View File

@ -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();

View File

@ -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 {

View File

@ -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());
}
});

View File

@ -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());

View File

@ -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,

View File

@ -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 {

View File

@ -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;

View File

@ -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" }

View File

@ -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>,
}

View File

@ -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()

View File

@ -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;
}
}
"#,
);
}

View File

@ -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)
}

View File

@ -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),

View File

@ -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))

View File

@ -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
"#]],
);
}

View File

@ -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)
}

View File

@ -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,
})

View File

@ -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" }

View File

@ -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]"],
&[],
);
}

View File

@ -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(())

View File

@ -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

View File

@ -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()) {

View File

@ -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();

View File

@ -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()) {

View File

@ -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

View File

@ -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();

View File

@ -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()

View File

@ -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",
),

View File

@ -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());
}

View File

@ -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,

View File

@ -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()",
),

View File

@ -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(

View File

@ -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)?;

View File

@ -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",

View File

@ -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);

View File

@ -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))
})
}

View File

@ -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"],
);
}

View File

@ -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![];

View File

@ -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