6331: correct hover text for items with doc attribute with raw strings r=matklad a=JoshMcguigan Fixes #6300 by improving the handling of raw string literals in attribute style doc comments. This still has a bug where it could consume too many `"` at the start or end of the comment text, just as the original code had. Not sure if we want to fix that as part of this PR or not? If so, I think I'd prefer to add a unit test for either the `as_simple_key_value` function (I'm not exactly sure where this would belong / how to set this up) or create a `fn(&SmolStr) -> &SmolStr` to unit test by factoring out the `trim` operations from `as_simple_key_value`. Thoughts on this? 6342: Shorter dependency chain r=matklad a=popzxc Continuing implementing suggestions from the `Completion refactoring` zulip thread. This PR does the following: - Removes dependency of `completions` on `assists` by moving required functionality into `ide_db`. - Moves completely `call_info` crate into `ide_db` as it looks like it fits perfect there. - Adds a bunch of new tests and docs. - Adds the re-export of `base_db` to the `ide_db` and removes direct dependency on `base_db` from other crates. The last point is controversial, I guess, but I noticed that in places where `ide_db` is used, `base_db` is also *always* used. Thus I think the dependency on the `base_db` is implied by the fact of `ide_db` interfaces, and thus it makes sense to just provide `base_db` out of the box. Co-authored-by: Josh Mcguigan <joshmcg88@gmail.com> Co-authored-by: Igor Aleksanov <popzxc@yandex.ru>
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
use std::mem;
|
||||
|
||||
use algo::find_covering_element;
|
||||
use base_db::{FileId, FileRange};
|
||||
use hir::Semantics;
|
||||
use ide_db::base_db::{FileId, FileRange};
|
||||
use ide_db::{
|
||||
label::Label,
|
||||
source_change::{SourceChange, SourceFileEdit},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use hir::HasSource;
|
||||
use ide_db::traits::{get_missing_assoc_items, resolve_target_trait};
|
||||
use syntax::{
|
||||
ast::{
|
||||
self,
|
||||
@@ -11,7 +12,7 @@ use syntax::{
|
||||
use crate::{
|
||||
assist_context::{AssistContext, Assists},
|
||||
ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
|
||||
utils::{get_missing_assoc_items, render_snippet, resolve_target_trait, Cursor},
|
||||
utils::{render_snippet, Cursor},
|
||||
AssistId, AssistKind,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use base_db::FileId;
|
||||
use hir::{EnumVariant, Module, ModuleDef, Name};
|
||||
use ide_db::base_db::FileId;
|
||||
use ide_db::{defs::Definition, search::Reference, RootDatabase};
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use base_db::FileId;
|
||||
use hir::{db::HirDatabase, HasSource, HasVisibility, PathResolution};
|
||||
use ide_db::base_db::FileId;
|
||||
use syntax::{
|
||||
ast::{self, VisibilityOwner},
|
||||
AstNode, TextRange, TextSize,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use base_db::FileId;
|
||||
use hir::HirDisplay;
|
||||
use ide_db::base_db::FileId;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use syntax::{
|
||||
ast::{
|
||||
|
||||
@@ -7,10 +7,8 @@ use syntax::{
|
||||
AstNode,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
utils::{unwrap_trivial_block, TryEnum},
|
||||
AssistContext, AssistId, AssistKind, Assists,
|
||||
};
|
||||
use crate::{utils::unwrap_trivial_block, AssistContext, AssistId, AssistKind, Assists};
|
||||
use ide_db::ty_filter::TryEnum;
|
||||
|
||||
// Assist: replace_if_let_with_match
|
||||
//
|
||||
|
||||
@@ -9,7 +9,8 @@ use syntax::{
|
||||
AstNode, T,
|
||||
};
|
||||
|
||||
use crate::{utils::TryEnum, AssistContext, AssistId, AssistKind, Assists};
|
||||
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
||||
use ide_db::ty_filter::TryEnum;
|
||||
|
||||
// Assist: replace_let_with_if_let
|
||||
//
|
||||
|
||||
@@ -10,9 +10,10 @@ use syntax::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
utils::{render_snippet, Cursor, TryEnum},
|
||||
utils::{render_snippet, Cursor},
|
||||
AssistContext, AssistId, AssistKind, Assists,
|
||||
};
|
||||
use ide_db::ty_filter::TryEnum;
|
||||
|
||||
// Assist: replace_unwrap_with_match
|
||||
//
|
||||
|
||||
@@ -17,8 +17,8 @@ mod tests;
|
||||
pub mod utils;
|
||||
pub mod ast_transform;
|
||||
|
||||
use base_db::FileRange;
|
||||
use hir::Semantics;
|
||||
use ide_db::base_db::FileRange;
|
||||
use ide_db::{label::Label, source_change::SourceChange, RootDatabase};
|
||||
use syntax::TextRange;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod generated;
|
||||
|
||||
use base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
|
||||
use hir::Semantics;
|
||||
use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
|
||||
use ide_db::RootDatabase;
|
||||
use syntax::TextRange;
|
||||
use test_utils::{assert_eq_text, extract_offset, extract_range};
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
pub(crate) mod insert_use;
|
||||
pub(crate) mod import_assets;
|
||||
|
||||
use std::{iter, ops};
|
||||
use std::ops;
|
||||
|
||||
use hir::{Adt, Crate, Enum, Module, ScopeDef, Semantics, Trait, Type};
|
||||
use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait};
|
||||
use ide_db::RootDatabase;
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashSet;
|
||||
use syntax::{
|
||||
ast::{self, make, ArgListOwner, NameOwner},
|
||||
ast::{self, make, ArgListOwner},
|
||||
AstNode, Direction,
|
||||
SyntaxKind::*,
|
||||
SyntaxNode, TextSize, T,
|
||||
@@ -115,72 +114,6 @@ pub(crate) fn render_snippet(_cap: SnippetCap, node: &SyntaxNode, cursor: Cursor
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_missing_assoc_items(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
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.assoc_item_list() {
|
||||
for item in item_list.assoc_items() {
|
||||
match item {
|
||||
ast::AssocItem::Fn(f) => {
|
||||
if let Some(n) = f.name() {
|
||||
impl_fns_consts.insert(n.syntax().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
ast::AssocItem::TypeAlias(t) => {
|
||||
if let Some(n) = t.name() {
|
||||
impl_type.insert(n.syntax().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
ast::AssocItem::Const(c) => {
|
||||
if let Some(n) = c.name() {
|
||||
impl_fns_consts.insert(n.syntax().to_string());
|
||||
}
|
||||
}
|
||||
ast::AssocItem::MacroCall(_) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolve_target_trait(sema, impl_def).map_or(vec![], |target_trait| {
|
||||
target_trait
|
||||
.items(sema.db)
|
||||
.iter()
|
||||
.filter(|i| match i {
|
||||
hir::AssocItem::Function(f) => {
|
||||
!impl_fns_consts.contains(&f.name(sema.db).to_string())
|
||||
}
|
||||
hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(sema.db).to_string()),
|
||||
hir::AssocItem::Const(c) => c
|
||||
.name(sema.db)
|
||||
.map(|n| !impl_fns_consts.contains(&n.to_string()))
|
||||
.unwrap_or_default(),
|
||||
})
|
||||
.cloned()
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_target_trait(
|
||||
sema: &Semantics<RootDatabase>,
|
||||
impl_def: &ast::Impl,
|
||||
) -> Option<hir::Trait> {
|
||||
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),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn vis_offset(node: &SyntaxNode) -> TextSize {
|
||||
node.children_with_tokens()
|
||||
.find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR))
|
||||
@@ -223,54 +156,6 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum TryEnum {
|
||||
Result,
|
||||
Option,
|
||||
}
|
||||
|
||||
impl TryEnum {
|
||||
const ALL: [TryEnum; 2] = [TryEnum::Option, TryEnum::Result];
|
||||
|
||||
pub fn from_ty(sema: &Semantics<RootDatabase>, ty: &Type) -> Option<TryEnum> {
|
||||
let enum_ = match ty.as_adt() {
|
||||
Some(Adt::Enum(it)) => it,
|
||||
_ => return None,
|
||||
};
|
||||
TryEnum::ALL.iter().find_map(|&var| {
|
||||
if &enum_.name(sema.db).to_string() == var.type_name() {
|
||||
return Some(var);
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn happy_case(self) -> &'static str {
|
||||
match self {
|
||||
TryEnum::Result => "Ok",
|
||||
TryEnum::Option => "Some",
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn sad_pattern(self) -> ast::Pat {
|
||||
match self {
|
||||
TryEnum::Result => make::tuple_struct_pat(
|
||||
make::path_unqualified(make::path_segment(make::name_ref("Err"))),
|
||||
iter::once(make::wildcard_pat().into()),
|
||||
)
|
||||
.into(),
|
||||
TryEnum::Option => make::ident_pat(make::name("None")).into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn type_name(self) -> &'static str {
|
||||
match self {
|
||||
TryEnum::Result => "Result",
|
||||
TryEnum::Option => "Option",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
||||
Reference in New Issue
Block a user