mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-27 02:06:57 +00:00
Fix flyimport not filtering via stability of import path
This commit is contained in:
parent
e22bcfbf57
commit
b31f53e0d6
21 changed files with 89 additions and 20 deletions
|
|
@ -445,6 +445,10 @@ fn find_in_dep(
|
|||
};
|
||||
cov_mark::hit!(partially_imported);
|
||||
if info.is_unstable {
|
||||
if !ctx.cfg.allow_unstable {
|
||||
// the item is unstable and we are not allowed to use unstable items
|
||||
continue;
|
||||
}
|
||||
choice.stability = Unstable;
|
||||
}
|
||||
|
||||
|
|
@ -670,6 +674,7 @@ mod tests {
|
|||
prefer_prelude: bool,
|
||||
prefer_absolute: bool,
|
||||
prefer_no_std: bool,
|
||||
allow_unstable: bool,
|
||||
expect: Expect,
|
||||
) {
|
||||
let (db, pos) = TestDB::with_position(ra_fixture);
|
||||
|
|
@ -711,7 +716,7 @@ mod tests {
|
|||
module,
|
||||
prefix,
|
||||
ignore_local_imports,
|
||||
ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute },
|
||||
ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute, allow_unstable },
|
||||
);
|
||||
format_to!(
|
||||
res,
|
||||
|
|
@ -732,7 +737,7 @@ mod tests {
|
|||
path: &str,
|
||||
expect: Expect,
|
||||
) {
|
||||
check_found_path_(ra_fixture, path, false, false, false, expect);
|
||||
check_found_path_(ra_fixture, path, false, false, false, false, expect);
|
||||
}
|
||||
|
||||
fn check_found_path_prelude(
|
||||
|
|
@ -740,7 +745,7 @@ mod tests {
|
|||
path: &str,
|
||||
expect: Expect,
|
||||
) {
|
||||
check_found_path_(ra_fixture, path, true, false, false, expect);
|
||||
check_found_path_(ra_fixture, path, true, false, false, false, expect);
|
||||
}
|
||||
|
||||
fn check_found_path_absolute(
|
||||
|
|
@ -748,7 +753,7 @@ mod tests {
|
|||
path: &str,
|
||||
expect: Expect,
|
||||
) {
|
||||
check_found_path_(ra_fixture, path, false, true, false, expect);
|
||||
check_found_path_(ra_fixture, path, false, true, false, false, expect);
|
||||
}
|
||||
|
||||
fn check_found_path_prefer_no_std(
|
||||
|
|
@ -756,7 +761,15 @@ mod tests {
|
|||
path: &str,
|
||||
expect: Expect,
|
||||
) {
|
||||
check_found_path_(ra_fixture, path, false, false, true, expect);
|
||||
check_found_path_(ra_fixture, path, false, false, true, false, expect);
|
||||
}
|
||||
|
||||
fn check_found_path_prefer_no_std_allow_unstable(
|
||||
#[rust_analyzer::rust_fixture] ra_fixture: &str,
|
||||
path: &str,
|
||||
expect: Expect,
|
||||
) {
|
||||
check_found_path_(ra_fixture, path, false, false, true, true, expect);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1951,7 +1964,7 @@ pub mod ops {
|
|||
|
||||
#[test]
|
||||
fn respect_unstable_modules() {
|
||||
check_found_path_prefer_no_std(
|
||||
check_found_path_prefer_no_std_allow_unstable(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std,core
|
||||
extern crate std;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ pub struct ImportPathConfig {
|
|||
pub prefer_prelude: bool,
|
||||
/// If true, prefer abs path (starting with `::`) where it is available.
|
||||
pub prefer_absolute: bool,
|
||||
/// If true, paths containing `#[unstable]` segments may be returned, but only if if there is no
|
||||
/// stable path. This does not check, whether the item itself that is being imported is `#[unstable]`.
|
||||
pub allow_unstable: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
|||
|
|
@ -1159,6 +1159,7 @@ impl HirDisplay for Ty {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
prefer_absolute: false,
|
||||
allow_unstable: true,
|
||||
},
|
||||
) {
|
||||
write!(f, "{}", path.display(f.db.upcast(), f.edition()))?;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ impl AssistConfig {
|
|||
prefer_no_std: self.prefer_no_std,
|
||||
prefer_prelude: self.prefer_prelude,
|
||||
prefer_absolute: self.prefer_absolute,
|
||||
allow_unstable: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -660,7 +660,7 @@ fn enum_variants_with_paths(
|
|||
if let Some(path) = ctx.module.find_path(
|
||||
ctx.db,
|
||||
hir::ModuleDef::from(variant),
|
||||
ctx.config.import_path_config(),
|
||||
ctx.config.import_path_config(ctx.is_nightly),
|
||||
) {
|
||||
// Variants with trivial paths are already added by the existing completion logic,
|
||||
// so we should avoid adding these twice
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ pub(crate) fn complete_expr_path(
|
|||
.find_path(
|
||||
ctx.db,
|
||||
hir::ModuleDef::from(strukt),
|
||||
ctx.config.import_path_config(),
|
||||
ctx.config.import_path_config(ctx.is_nightly),
|
||||
)
|
||||
.filter(|it| it.len() > 1);
|
||||
|
||||
|
|
@ -269,7 +269,7 @@ pub(crate) fn complete_expr_path(
|
|||
.find_path(
|
||||
ctx.db,
|
||||
hir::ModuleDef::from(un),
|
||||
ctx.config.import_path_config(),
|
||||
ctx.config.import_path_config(ctx.is_nightly),
|
||||
)
|
||||
.filter(|it| it.len() > 1);
|
||||
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ fn import_on_the_fly(
|
|||
};
|
||||
let user_input_lowercased = potential_import_name.to_lowercase();
|
||||
|
||||
let import_cfg = ctx.config.import_path_config();
|
||||
let import_cfg = ctx.config.import_path_config(ctx.is_nightly);
|
||||
|
||||
import_assets
|
||||
.search_for_imports(&ctx.sema, import_cfg, ctx.config.insert_use.prefix_kind)
|
||||
|
|
@ -316,7 +316,7 @@ fn import_on_the_fly_pat_(
|
|||
ItemInNs::Values(def) => matches!(def, hir::ModuleDef::Const(_)),
|
||||
};
|
||||
let user_input_lowercased = potential_import_name.to_lowercase();
|
||||
let cfg = ctx.config.import_path_config();
|
||||
let cfg = ctx.config.import_path_config(ctx.is_nightly);
|
||||
|
||||
import_assets
|
||||
.search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
|
||||
|
|
@ -358,7 +358,7 @@ fn import_on_the_fly_method(
|
|||
|
||||
let user_input_lowercased = potential_import_name.to_lowercase();
|
||||
|
||||
let cfg = ctx.config.import_path_config();
|
||||
let cfg = ctx.config.import_path_config(ctx.is_nightly);
|
||||
|
||||
import_assets
|
||||
.search_for_imports(&ctx.sema, cfg, ctx.config.insert_use.prefix_kind)
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ pub(crate) fn complete_postfix(
|
|||
None => return,
|
||||
};
|
||||
|
||||
let cfg = ctx.config.import_path_config();
|
||||
let cfg = ctx.config.import_path_config(ctx.is_nightly);
|
||||
|
||||
if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
|
||||
if receiver_ty.impls_trait(ctx.db, drop_trait, &[]) {
|
||||
|
|
|
|||
|
|
@ -59,11 +59,12 @@ impl CompletionConfig<'_> {
|
|||
.flat_map(|snip| snip.prefix_triggers.iter().map(move |trigger| (&**trigger, snip)))
|
||||
}
|
||||
|
||||
pub fn import_path_config(&self) -> ImportPathConfig {
|
||||
pub fn import_path_config(&self, allow_unstable: bool) -> ImportPathConfig {
|
||||
ImportPathConfig {
|
||||
prefer_no_std: self.prefer_no_std,
|
||||
prefer_prelude: self.prefer_prelude,
|
||||
prefer_absolute: self.prefer_absolute,
|
||||
allow_unstable,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -443,7 +443,9 @@ pub(crate) struct CompletionContext<'a> {
|
|||
/// The module of the `scope`.
|
||||
pub(crate) module: hir::Module,
|
||||
/// Whether nightly toolchain is used. Cached since this is looked up a lot.
|
||||
is_nightly: bool,
|
||||
pub(crate) is_nightly: bool,
|
||||
/// The edition of the current crate
|
||||
// FIXME: This should probably be the crate of the current token?
|
||||
pub(crate) edition: Edition,
|
||||
|
||||
/// The expected name of what we are completing.
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ pub fn resolve_completion_edits(
|
|||
let new_ast = scope.clone_for_update();
|
||||
let mut import_insert = TextEdit::builder();
|
||||
|
||||
let cfg = config.import_path_config();
|
||||
let cfg = config.import_path_config(true);
|
||||
|
||||
imports.into_iter().for_each(|(full_import_path, imported_name)| {
|
||||
let items_with_name = items_locator::items_with_name(
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ pub(crate) fn render_expr(
|
|||
.unwrap_or_else(|| String::from("..."))
|
||||
};
|
||||
|
||||
let cfg = ctx.config.import_path_config();
|
||||
let cfg = ctx.config.import_path_config(ctx.is_nightly);
|
||||
|
||||
let label = expr.gen_source_code(&ctx.scope, &mut label_formatter, cfg, ctx.edition).ok()?;
|
||||
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ impl Snippet {
|
|||
}
|
||||
|
||||
fn import_edits(ctx: &CompletionContext<'_>, requires: &[ModPath]) -> Option<Vec<LocatedImport>> {
|
||||
let import_cfg = ctx.config.import_path_config();
|
||||
let import_cfg = ctx.config.import_path_config(ctx.is_nightly);
|
||||
|
||||
let resolve = |import| {
|
||||
let item = ctx.scope.resolve_mod_path(import).next()?;
|
||||
|
|
|
|||
|
|
@ -1390,6 +1390,41 @@ pub struct FooStruct {}
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flyimport_pattern_unstable_path() {
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std
|
||||
fn function() {
|
||||
let foo$0
|
||||
}
|
||||
//- /std.rs crate:std
|
||||
#[unstable]
|
||||
pub mod unstable {
|
||||
pub struct FooStruct {}
|
||||
}
|
||||
"#,
|
||||
expect![""],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
//- toolchain:nightly
|
||||
//- /main.rs crate:main deps:std
|
||||
fn function() {
|
||||
let foo$0
|
||||
}
|
||||
//- /std.rs crate:std
|
||||
#[unstable]
|
||||
pub mod unstable {
|
||||
pub struct FooStruct {}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
st FooStruct (use std::unstable::FooStruct)
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flyimport_pattern_unstable_item_on_nightly() {
|
||||
check(
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ impl Ctx<'_> {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
prefer_absolute: false,
|
||||
allow_unstable: true,
|
||||
};
|
||||
let found_path = self.target_module.find_path(
|
||||
self.source_scope.db.upcast(),
|
||||
|
|
@ -378,6 +379,7 @@ impl Ctx<'_> {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
prefer_absolute: false,
|
||||
allow_unstable: true,
|
||||
};
|
||||
let found_path =
|
||||
self.target_module.find_path(self.source_scope.db.upcast(), def, cfg)?;
|
||||
|
|
@ -417,6 +419,7 @@ impl Ctx<'_> {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
prefer_absolute: false,
|
||||
allow_unstable: true,
|
||||
};
|
||||
let found_path = self.target_module.find_path(
|
||||
self.source_scope.db.upcast(),
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ pub(crate) fn json_in_items(
|
|||
prefer_no_std: config.prefer_no_std,
|
||||
prefer_prelude: config.prefer_prelude,
|
||||
prefer_absolute: config.prefer_absolute,
|
||||
allow_unstable: true,
|
||||
};
|
||||
|
||||
if !scope_has("Serialize") {
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
|
|||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
allow_unstable: ctx.is_nightly,
|
||||
},
|
||||
)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>
|
|||
prefer_no_std: ctx.config.prefer_no_std,
|
||||
prefer_prelude: ctx.config.prefer_prelude,
|
||||
prefer_absolute: ctx.config.prefer_absolute,
|
||||
allow_unstable: ctx.is_nightly,
|
||||
},
|
||||
ctx.edition,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ use either::Either;
|
|||
use hir::{db::ExpandDatabase, diagnostics::AnyDiagnostic, Crate, HirFileId, InFile, Semantics};
|
||||
use ide_db::{
|
||||
assists::{Assist, AssistId, AssistKind, AssistResolveStrategy},
|
||||
base_db::SourceDatabase,
|
||||
base_db::{ReleaseChannel, SourceDatabase},
|
||||
generated::lints::{Lint, LintGroup, CLIPPY_LINT_GROUPS, DEFAULT_LINTS, DEFAULT_LINT_GROUPS},
|
||||
imports::insert_use::InsertUseConfig,
|
||||
label::Label,
|
||||
|
|
@ -276,6 +276,7 @@ struct DiagnosticsContext<'a> {
|
|||
sema: Semantics<'a, RootDatabase>,
|
||||
resolve: &'a AssistResolveStrategy,
|
||||
edition: Edition,
|
||||
is_nightly: bool,
|
||||
}
|
||||
|
||||
impl DiagnosticsContext<'_> {
|
||||
|
|
@ -368,7 +369,11 @@ pub fn semantic_diagnostics(
|
|||
|
||||
let module = sema.file_to_module_def(file_id);
|
||||
|
||||
let ctx = DiagnosticsContext { config, sema, resolve, edition: file_id.edition() };
|
||||
let is_nightly = matches!(
|
||||
module.and_then(|m| db.toolchain_channel(m.krate().into())),
|
||||
Some(ReleaseChannel::Nightly) | None
|
||||
);
|
||||
let ctx = DiagnosticsContext { config, sema, resolve, edition: file_id.edition(), is_nightly };
|
||||
|
||||
let mut diags = Vec::new();
|
||||
match module {
|
||||
|
|
|
|||
|
|
@ -673,6 +673,7 @@ impl Match {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
prefer_absolute: false,
|
||||
allow_unstable: true,
|
||||
};
|
||||
let mod_path = module.find_path(sema.db, module_def, cfg).ok_or_else(|| {
|
||||
match_error!("Failed to render template path `{}` at match location")
|
||||
|
|
|
|||
|
|
@ -465,6 +465,7 @@ impl flags::AnalysisStats {
|
|||
prefer_no_std: false,
|
||||
prefer_prelude: true,
|
||||
prefer_absolute: false,
|
||||
allow_unstable: true,
|
||||
},
|
||||
Edition::LATEST,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue