Extract the import code into the shared module

This commit is contained in:
Kirill Bulatov 2020-11-24 23:25:13 +02:00
parent 0993f9067c
commit f4ae3650d8
30 changed files with 298 additions and 254 deletions

18
Cargo.lock generated
View file

@ -53,6 +53,7 @@ dependencies = [
"either",
"hir",
"ide_db",
"ide_helpers",
"itertools",
"profile",
"rustc-hash",
@ -253,12 +254,12 @@ dependencies = [
name = "completion"
version = "0.0.0"
dependencies = [
"assists",
"base_db",
"either",
"expect-test",
"hir",
"ide_db",
"ide_helpers",
"itertools",
"log",
"profile",
@ -657,6 +658,7 @@ dependencies = [
"expect-test",
"hir",
"ide_db",
"ide_helpers",
"indexmap",
"itertools",
"log",
@ -693,6 +695,19 @@ dependencies = [
"text_edit",
]
[[package]]
name = "ide_helpers"
version = "0.0.0"
dependencies = [
"either",
"hir",
"ide_db",
"itertools",
"profile",
"syntax",
"test_utils",
]
[[package]]
name = "idna"
version = "0.2.0"
@ -1361,6 +1376,7 @@ dependencies = [
"hir_ty",
"ide",
"ide_db",
"ide_helpers",
"itertools",
"jod-thread",
"log",

View file

@ -12,7 +12,7 @@ doctest = false
[dependencies]
rustc-hash = "1.1.0"
itertools = "0.9.0"
either = "1.5.3"
either = "1.6.1"
stdx = { path = "../stdx", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
@ -21,3 +21,4 @@ profile = { path = "../profile", version = "0.0.0" }
ide_db = { path = "../ide_db", version = "0.0.0" }
hir = { path = "../hir", version = "0.0.0" }
test_utils = { path = "../test_utils", version = "0.0.0" }
ide_helpers = { path = "../ide_helpers", version = "0.0.0" }

View file

@ -5,8 +5,9 @@
//! assists if we are allowed to.
use hir::PrefixKind;
use ide_helpers::insert_use::MergeBehaviour;
use crate::{utils::MergeBehaviour, AssistKind};
use crate::AssistKind;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AssistConfig {

View file

@ -1,5 +1,6 @@
//! `AstTransformer`s are functions that replace nodes in an AST and can be easily combined.
use hir::{HirDisplay, PathResolution, SemanticsScope};
use ide_helpers::mod_path_to_ast;
use rustc_hash::FxHashMap;
use syntax::{
algo::SyntaxRewriter,
@ -7,8 +8,6 @@ use syntax::{
SyntaxNode,
};
use crate::utils::mod_path_to_ast;
pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N {
SyntaxRewriter::from_fn(|element| match element {
syntax::SyntaxElement::Node(n) => {

View file

@ -1,8 +1,11 @@
use ide_helpers::{
insert_use::{insert_use, ImportScope},
mod_path_to_ast,
};
use syntax::ast;
use crate::{
utils::import_assets::{ImportAssets, ImportCandidate},
utils::{insert_use, mod_path_to_ast, ImportScope},
AssistContext, AssistId, AssistKind, Assists, GroupLabel,
};

View file

@ -3,6 +3,10 @@ use std::iter;
use either::Either;
use hir::{AsName, EnumVariant, Module, ModuleDef, Name};
use ide_db::{defs::Definition, search::Reference, RootDatabase};
use ide_helpers::{
insert_use::{insert_use, ImportScope},
mod_path_to_ast,
};
use rustc_hash::{FxHashMap, FxHashSet};
use syntax::{
algo::{find_node_at_offset, SyntaxRewriter},
@ -10,10 +14,7 @@ use syntax::{
SourceFile, SyntaxElement, SyntaxNode, T,
};
use crate::{
utils::{insert_use, mod_path_to_ast, ImportScope},
AssistContext, AssistId, AssistKind, Assists,
};
use crate::{AssistContext, AssistId, AssistKind, Assists};
// Assist: extract_struct_from_enum_variant
//
@ -236,10 +237,9 @@ fn update_reference(
#[cfg(test)]
mod tests {
use crate::{
tests::{check_assist, check_assist_not_applicable},
utils::FamousDefs,
};
use ide_helpers::FamousDefs;
use crate::tests::{check_assist, check_assist_not_applicable};
use super::*;

View file

@ -2,12 +2,13 @@ use std::iter;
use hir::{Adt, HasSource, ModuleDef, Semantics};
use ide_db::RootDatabase;
use ide_helpers::{mod_path_to_ast, FamousDefs};
use itertools::Itertools;
use syntax::ast::{self, make, AstNode, MatchArm, NameOwner, Pat};
use test_utils::mark;
use crate::{
utils::{mod_path_to_ast, render_snippet, Cursor, FamousDefs},
utils::{render_snippet, Cursor},
AssistContext, AssistId, AssistKind, Assists,
};
@ -212,12 +213,10 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> O
#[cfg(test)]
mod tests {
use ide_helpers::FamousDefs;
use test_utils::mark;
use crate::{
tests::{check_assist, check_assist_not_applicable, check_assist_target},
utils::FamousDefs,
};
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
use super::fill_match_arms;

View file

@ -1,8 +1,9 @@
use ide_db::RootDatabase;
use ide_helpers::FamousDefs;
use syntax::ast::{self, AstNode, NameOwner};
use test_utils::mark;
use crate::{utils::FamousDefs, AssistContext, AssistId, AssistKind, Assists};
use crate::{AssistContext, AssistId, AssistKind, Assists};
// Assist: generate_from_impl_for_enum
//

View file

@ -1,3 +1,4 @@
use ide_helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehaviour};
use syntax::{
algo::{neighbor, SyntaxRewriter},
ast, AstNode,
@ -5,10 +6,7 @@ use syntax::{
use crate::{
assist_context::{AssistContext, Assists},
utils::{
insert_use::{try_merge_imports, try_merge_trees},
next_prev, MergeBehaviour,
},
utils::next_prev,
AssistId, AssistKind,
};

View file

@ -2,6 +2,7 @@ use std::iter;
use hir::AsName;
use ide_db::RootDatabase;
use ide_helpers::mod_path_to_ast;
use syntax::{
ast,
ast::{make, ArgListOwner},
@ -12,7 +13,6 @@ use test_utils::mark;
use crate::{
assist_context::{AssistContext, Assists},
utils::import_assets::{ImportAssets, ImportCandidate},
utils::mod_path_to_ast,
AssistId, AssistKind, GroupLabel,
};

View file

@ -1,4 +1,5 @@
use ide_db::imports_locator;
use ide_helpers::mod_path_to_ast;
use itertools::Itertools;
use syntax::{
ast::{self, make, AstNode},
@ -10,8 +11,7 @@ use syntax::{
use crate::{
assist_context::{AssistBuilder, AssistContext, Assists},
utils::{
add_trait_assoc_items_to_impl, filter_assoc_items, mod_path_to_ast, render_snippet, Cursor,
DefaultMethods,
add_trait_assoc_items_to_impl, filter_assoc_items, render_snippet, Cursor, DefaultMethods,
},
AssistId, AssistKind,
};

View file

@ -1,10 +1,8 @@
use ide_helpers::insert_use::{insert_use, ImportScope};
use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode};
use test_utils::mark;
use crate::{
utils::{insert_use, ImportScope},
AssistContext, AssistId, AssistKind, Assists,
};
use crate::{AssistContext, AssistId, AssistKind, Assists};
// Assist: replace_qualified_name_with_use
//
@ -53,7 +51,7 @@ pub(crate) fn replace_qualified_name_with_use(
)
}
/// Adds replacements to `re` that shorten `path` in all descendants of `node`.
/// Adds replacements to `re` that shorten `path` in all descendants of `node`.g
fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ast::Path) {
for child in node.children() {
match_ast! {

View file

@ -1,10 +1,9 @@
//! Assorted functions shared by several assists.
pub(crate) mod insert_use;
pub(crate) mod import_assets;
use std::ops;
use hir::{Crate, Enum, HasSource, Module, ScopeDef, Semantics, Trait};
use hir::HasSource;
use ide_db::RootDatabase;
use itertools::Itertools;
use syntax::{
@ -22,30 +21,6 @@ use crate::{
ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
};
pub use insert_use::{insert_use, ImportScope, MergeBehaviour};
pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
let _p = profile::span("mod_path_to_ast");
let mut segments = Vec::new();
let mut is_abs = false;
match path.kind {
hir::PathKind::Plain => {}
hir::PathKind::Super(0) => segments.push(make::path_segment_self()),
hir::PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
hir::PathKind::DollarCrate(_) | hir::PathKind::Crate => {
segments.push(make::path_segment_crate())
}
hir::PathKind::Abs => is_abs = true,
}
segments.extend(
path.segments
.iter()
.map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
);
make::path_from_segments(segments, is_abs)
}
pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr {
extract_trivial_expression(&block)
.filter(|expr| !expr.syntax().text().contains_char('\n'))
@ -260,179 +235,6 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
}
}
/// Helps with finding well-know things inside the standard library. This is
/// somewhat similar to the known paths infra inside hir, but it different; We
/// want to make sure that IDE specific paths don't become interesting inside
/// the compiler itself as well.
pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>);
#[allow(non_snake_case)]
impl FamousDefs<'_, '_> {
pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
pub mod convert {
pub trait From<T> {
fn from(t: T) -> Self;
}
}
pub mod default {
pub trait Default {
fn default() -> Self;
}
}
pub mod iter {
pub use self::traits::{collect::IntoIterator, iterator::Iterator};
mod traits {
pub(crate) mod iterator {
use crate::option::Option;
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
fn by_ref(&mut self) -> &mut Self {
self
}
fn take(self, n: usize) -> crate::iter::Take<Self> {
crate::iter::Take { inner: self }
}
}
impl<I: Iterator> Iterator for &mut I {
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
(**self).next()
}
}
}
pub(crate) mod collect {
pub trait IntoIterator {
type Item;
}
}
}
pub use self::sources::*;
pub(crate) mod sources {
use super::Iterator;
use crate::option::Option::{self, *};
pub struct Repeat<A> {
element: A,
}
pub fn repeat<T>(elt: T) -> Repeat<T> {
Repeat { element: elt }
}
impl<A> Iterator for Repeat<A> {
type Item = A;
fn next(&mut self) -> Option<A> {
None
}
}
}
pub use self::adapters::*;
pub(crate) mod adapters {
use super::Iterator;
use crate::option::Option::{self, *};
pub struct Take<I> { pub(crate) inner: I }
impl<I> Iterator for Take<I> where I: Iterator {
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<<I as Iterator>::Item> {
None
}
}
}
}
pub mod option {
pub enum Option<T> { None, Some(T)}
}
pub mod prelude {
pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}, default::Default};
}
#[prelude_import]
pub use prelude::*;
"#;
pub fn core(&self) -> Option<Crate> {
self.find_crate("core")
}
pub(crate) fn core_convert_From(&self) -> Option<Trait> {
self.find_trait("core:convert:From")
}
pub(crate) fn core_option_Option(&self) -> Option<Enum> {
self.find_enum("core:option:Option")
}
pub fn core_default_Default(&self) -> Option<Trait> {
self.find_trait("core:default:Default")
}
pub fn core_iter_Iterator(&self) -> Option<Trait> {
self.find_trait("core:iter:traits:iterator:Iterator")
}
pub fn core_iter(&self) -> Option<Module> {
self.find_module("core:iter")
}
fn find_trait(&self, path: &str) -> Option<Trait> {
match self.find_def(path)? {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
_ => None,
}
}
fn find_enum(&self, path: &str) -> Option<Enum> {
match self.find_def(path)? {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
_ => None,
}
}
fn find_module(&self, path: &str) -> Option<Module> {
match self.find_def(path)? {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(it)) => Some(it),
_ => None,
}
}
fn find_crate(&self, name: &str) -> Option<Crate> {
let krate = self.1?;
let db = self.0.db;
let res =
krate.dependencies(db).into_iter().find(|dep| dep.name.to_string() == name)?.krate;
Some(res)
}
fn find_def(&self, path: &str) -> Option<ScopeDef> {
let db = self.0.db;
let mut path = path.split(':');
let trait_ = path.next_back()?;
let std_crate = path.next()?;
let std_crate = self.find_crate(std_crate)?;
let mut module = std_crate.root_module(db);
for segment in path {
module = module.children(db).find_map(|child| {
let name = child.name(db)?;
if name.to_string() == segment {
Some(child)
} else {
None
}
})?;
}
let def =
module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1;
Some(def)
}
}
pub(crate) fn next_prev() -> impl Iterator<Item = Direction> {
[Direction::Next, Direction::Prev].iter().copied()
}

View file

@ -15,7 +15,6 @@ log = "0.4.8"
rustc-hash = "1.1.0"
either = "1.6.1"
assists = { path = "../assists", version = "0.0.0" }
stdx = { path = "../stdx", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
text_edit = { path = "../text_edit", version = "0.0.0" }
@ -23,6 +22,7 @@ base_db = { path = "../base_db", version = "0.0.0" }
ide_db = { path = "../ide_db", version = "0.0.0" }
profile = { path = "../profile", version = "0.0.0" }
test_utils = { path = "../test_utils", version = "0.0.0" }
ide_helpers = { path = "../ide_helpers", version = "0.0.0" }
# completions crate should depend only on the top-level `hir` package. if you need
# something from some `hir_xxx` subpackage, reexport the API via `hir`.

View file

@ -1,5 +1,5 @@
//! Complete fields in record literals and patterns.
use assists::utils::FamousDefs;
use ide_helpers::FamousDefs;
use syntax::ast::Expr;
use crate::{
@ -45,8 +45,8 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
#[cfg(test)]
mod tests {
use assists::utils::FamousDefs;
use expect_test::{expect, Expect};
use ide_helpers::FamousDefs;
use crate::{test_utils::completion_list, CompletionKind};

View file

@ -1,9 +1,9 @@
//! Completion of names from the current scope, e.g. locals and imported items.
use assists::utils::ImportScope;
use either::Either;
use hir::{Adt, ModuleDef, ScopeDef, Type};
use ide_db::imports_locator;
use ide_helpers::insert_use::ImportScope;
use syntax::AstNode;
use test_utils::mark;

View file

@ -4,7 +4,7 @@
//! module, and we use to statically check that we only produce snippet
//! completions if we are allowed to.
use assists::utils::MergeBehaviour;
use ide_helpers::insert_use::MergeBehaviour;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CompletionConfig {

View file

@ -2,8 +2,11 @@
use std::fmt;
use assists::utils::{insert_use, mod_path_to_ast, ImportScope, MergeBehaviour};
use hir::{Documentation, ModPath, Mutability};
use ide_helpers::{
insert_use::{self, ImportScope, MergeBehaviour},
mod_path_to_ast,
};
use syntax::{algo, TextRange};
use text_edit::TextEdit;
@ -300,7 +303,7 @@ impl Builder {
label = format!("{}::{}", import_path_without_last_segment, label);
}
let rewriter = insert_use(&import_scope, import, merge_behaviour);
let rewriter = insert_use::insert_use(&import_scope, import, merge_behaviour);
if let Some(old_ast) = rewriter.rewrite_root() {
algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut text_edits);
}

View file

@ -9,9 +9,9 @@ pub(crate) mod type_alias;
mod builder_ext;
use assists::utils::{ImportScope, MergeBehaviour};
use hir::{Documentation, HasAttrs, HirDisplay, ModPath, Mutability, ScopeDef, Type};
use ide_db::RootDatabase;
use ide_helpers::insert_use::{ImportScope, MergeBehaviour};
use syntax::TextRange;
use test_utils::mark;

View file

@ -1,7 +1,7 @@
//! Renderer for `enum` variants.
use assists::utils::{ImportScope, MergeBehaviour};
use hir::{HasAttrs, HirDisplay, ModPath, StructKind};
use ide_helpers::insert_use::{ImportScope, MergeBehaviour};
use itertools::Itertools;
use test_utils::mark;

View file

@ -1,7 +1,7 @@
//! Renderer for function calls.
use assists::utils::{ImportScope, MergeBehaviour};
use hir::{HasSource, ModPath, Type};
use ide_helpers::insert_use::{ImportScope, MergeBehaviour};
use syntax::{ast::Fn, display::function_declaration};
use crate::{

View file

@ -1,7 +1,7 @@
//! Renderer for macro invocations.
use assists::utils::{ImportScope, MergeBehaviour};
use hir::{Documentation, HasSource, ModPath};
use ide_helpers::insert_use::{ImportScope, MergeBehaviour};
use syntax::display::macro_label;
use test_utils::mark;
@ -12,6 +12,7 @@ use crate::{
pub(crate) fn render_macro<'a>(
ctx: RenderContext<'a>,
// TODO kb add some object instead of a tuple?
import_data: Option<(ModPath, ImportScope, Option<MergeBehaviour>)>,
name: String,
macro_: hir::MacroDef,

View file

@ -24,6 +24,7 @@ stdx = { path = "../stdx", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
text_edit = { path = "../text_edit", version = "0.0.0" }
ide_db = { path = "../ide_db", version = "0.0.0" }
ide_helpers = { path = "../ide_helpers", version = "0.0.0" }
cfg = { path = "../cfg", version = "0.0.0" }
profile = { path = "../profile", version = "0.0.0" }
test_utils = { path = "../test_utils", version = "0.0.0" }

View file

@ -1,7 +1,7 @@
use assists::utils::FamousDefs;
use either::Either;
use hir::{known, Callable, HirDisplay, Semantics};
use ide_db::RootDatabase;
use ide_helpers::FamousDefs;
use stdx::to_lower_snake_case;
use syntax::{
ast::{self, ArgListOwner, AstNode, NameOwner},
@ -427,8 +427,8 @@ fn get_callable(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<hir:
#[cfg(test)]
mod tests {
use assists::utils::FamousDefs;
use expect_test::{expect, Expect};
use ide_helpers::FamousDefs;
use test_utils::extract_annotations;
use crate::{fixture, inlay_hints::InlayHintsConfig};

View file

@ -87,9 +87,7 @@ pub use ide_db::{
search::{Reference, ReferenceAccess, ReferenceKind},
};
pub use assists::{
utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist,
};
pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
pub use hir::{Documentation, Semantics};
pub use ide_db::base_db::{
Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,

View file

@ -0,0 +1,23 @@
[package]
name = "ide_helpers"
version = "0.0.0"
description = "A set of helper methods shared between various ide-level modules"
license = "MIT OR Apache-2.0"
authors = ["rust-analyzer developers"]
edition = "2018"
[lib]
doctest = false
[features]
wasm = []
[dependencies]
either = "1.6.1"
itertools = "0.9.0"
syntax = { path = "../syntax", version = "0.0.0" }
ide_db = { path = "../ide_db", version = "0.0.0" }
hir = { path = "../hir", version = "0.0.0" }
profile = { path = "../profile", version = "0.0.0" }
test_utils = { path = "../test_utils", version = "0.0.0" }

View file

@ -22,7 +22,7 @@ pub enum ImportScope {
}
impl ImportScope {
pub(crate) fn from(syntax: SyntaxNode) -> Option<Self> {
pub fn from(syntax: SyntaxNode) -> Option<Self> {
if let Some(module) = ast::Module::cast(syntax.clone()) {
module.item_list().map(ImportScope::Module)
} else if let this @ Some(_) = ast::SourceFile::cast(syntax.clone()) {
@ -180,7 +180,7 @@ fn eq_visibility(vis0: Option<ast::Visibility>, vis1: Option<ast::Visibility>) -
}
}
pub(crate) fn try_merge_imports(
pub fn try_merge_imports(
lhs: &ast::Use,
rhs: &ast::Use,
merge_behaviour: MergeBehaviour,
@ -195,7 +195,7 @@ pub(crate) fn try_merge_imports(
Some(lhs.with_use_tree(merged))
}
pub(crate) fn try_merge_trees(
pub fn try_merge_trees(
lhs: &ast::UseTree,
rhs: &ast::UseTree,
merge: MergeBehaviour,

View file

@ -0,0 +1,201 @@
use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait};
use ide_db::RootDatabase;
use syntax::ast::{self, make};
pub mod insert_use;
pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
let _p = profile::span("mod_path_to_ast");
let mut segments = Vec::new();
let mut is_abs = false;
match path.kind {
hir::PathKind::Plain => {}
hir::PathKind::Super(0) => segments.push(make::path_segment_self()),
hir::PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
hir::PathKind::DollarCrate(_) | hir::PathKind::Crate => {
segments.push(make::path_segment_crate())
}
hir::PathKind::Abs => is_abs = true,
}
segments.extend(
path.segments
.iter()
.map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
);
make::path_from_segments(segments, is_abs)
}
/// Helps with finding well-know things inside the standard library. This is
/// somewhat similar to the known paths infra inside hir, but it different; We
/// want to make sure that IDE specific paths don't become interesting inside
/// the compiler itself as well.
pub struct FamousDefs<'a, 'b>(pub &'a Semantics<'b, RootDatabase>, pub Option<Crate>);
#[allow(non_snake_case)]
impl FamousDefs<'_, '_> {
pub const FIXTURE: &'static str = r#"//- /libcore.rs crate:core
pub mod convert {
pub trait From<T> {
fn from(t: T) -> Self;
}
}
pub mod default {
pub trait Default {
fn default() -> Self;
}
}
pub mod iter {
pub use self::traits::{collect::IntoIterator, iterator::Iterator};
mod traits {
pub(crate) mod iterator {
use crate::option::Option;
pub trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
fn by_ref(&mut self) -> &mut Self {
self
}
fn take(self, n: usize) -> crate::iter::Take<Self> {
crate::iter::Take { inner: self }
}
}
impl<I: Iterator> Iterator for &mut I {
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
(**self).next()
}
}
}
pub(crate) mod collect {
pub trait IntoIterator {
type Item;
}
}
}
pub use self::sources::*;
pub(crate) mod sources {
use super::Iterator;
use crate::option::Option::{self, *};
pub struct Repeat<A> {
element: A,
}
pub fn repeat<T>(elt: T) -> Repeat<T> {
Repeat { element: elt }
}
impl<A> Iterator for Repeat<A> {
type Item = A;
fn next(&mut self) -> Option<A> {
None
}
}
}
pub use self::adapters::*;
pub(crate) mod adapters {
use super::Iterator;
use crate::option::Option::{self, *};
pub struct Take<I> { pub(crate) inner: I }
impl<I> Iterator for Take<I> where I: Iterator {
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<<I as Iterator>::Item> {
None
}
}
}
}
pub mod option {
pub enum Option<T> { None, Some(T)}
}
pub mod prelude {
pub use crate::{convert::From, iter::{IntoIterator, Iterator}, option::Option::{self, *}, default::Default};
}
#[prelude_import]
pub use prelude::*;
"#;
pub fn core(&self) -> Option<Crate> {
self.find_crate("core")
}
pub fn core_convert_From(&self) -> Option<Trait> {
self.find_trait("core:convert:From")
}
pub fn core_option_Option(&self) -> Option<Enum> {
self.find_enum("core:option:Option")
}
pub fn core_default_Default(&self) -> Option<Trait> {
self.find_trait("core:default:Default")
}
pub fn core_iter_Iterator(&self) -> Option<Trait> {
self.find_trait("core:iter:traits:iterator:Iterator")
}
pub fn core_iter(&self) -> Option<Module> {
self.find_module("core:iter")
}
fn find_trait(&self, path: &str) -> Option<Trait> {
match self.find_def(path)? {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),
_ => None,
}
}
fn find_enum(&self, path: &str) -> Option<Enum> {
match self.find_def(path)? {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(it))) => Some(it),
_ => None,
}
}
fn find_module(&self, path: &str) -> Option<Module> {
match self.find_def(path)? {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(it)) => Some(it),
_ => None,
}
}
fn find_crate(&self, name: &str) -> Option<Crate> {
let krate = self.1?;
let db = self.0.db;
let res =
krate.dependencies(db).into_iter().find(|dep| dep.name.to_string() == name)?.krate;
Some(res)
}
fn find_def(&self, path: &str) -> Option<ScopeDef> {
let db = self.0.db;
let mut path = path.split(':');
let trait_ = path.next_back()?;
let std_crate = path.next()?;
let std_crate = self.find_crate(std_crate)?;
let mut module = std_crate.root_module(db);
for segment in path {
module = module.children(db).find_map(|child| {
let name = child.name(db)?;
if name.to_string() == segment {
Some(child)
} else {
None
}
})?;
}
let def =
module.scope(db, None).into_iter().find(|(name, _def)| name.to_string() == trait_)?.1;
Some(def)
}
}

View file

@ -39,6 +39,7 @@ tracing-tree = { version = "0.1.4" }
stdx = { path = "../stdx", version = "0.0.0" }
flycheck = { path = "../flycheck", version = "0.0.0" }
ide = { path = "../ide", version = "0.0.0" }
ide_helpers = { path = "../ide_helpers", version = "0.0.0" }
profile = { path = "../profile", version = "0.0.0" }
project_model = { path = "../project_model", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }

View file

@ -11,10 +11,8 @@ use std::{convert::TryFrom, ffi::OsString, path::PathBuf};
use flycheck::FlycheckConfig;
use hir::PrefixKind;
use ide::{
AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig,
MergeBehaviour,
};
use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig};
use ide_helpers::insert_use::MergeBehaviour;
use lsp_types::{ClientCapabilities, MarkupKind};
use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
use rustc_hash::FxHashSet;