Add an expr_source method analogous to the source methods in the code model
... and use that instead of exposing the source map.
This commit is contained in:
parent
a7858bb7bf
commit
f92177cfb5
@ -1,7 +1,7 @@
|
||||
use std::{collections::HashSet, fmt::Write, path::Path, time::Instant};
|
||||
|
||||
use ra_db::SourceDatabase;
|
||||
use ra_hir::{Crate, HasSource, HirDisplay, ImplItem, ModuleDef, Ty};
|
||||
use ra_hir::{Crate, HasBodySource, HasSource, HirDisplay, ImplItem, ModuleDef, Ty};
|
||||
use ra_syntax::AstNode;
|
||||
|
||||
use crate::Result;
|
||||
@ -104,35 +104,34 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -
|
||||
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
|
||||
num_type_mismatches += 1;
|
||||
if verbose {
|
||||
let src = f.source(db);
|
||||
let original_file = src.file_id.original_file(db);
|
||||
let path = db.file_relative_path(original_file);
|
||||
let line_index = host.analysis().file_line_index(original_file).unwrap();
|
||||
let body_source_map = f.body_source_map(db);
|
||||
let syntax_node = body_source_map.expr_syntax(expr_id);
|
||||
let line_col = syntax_node.map(|syntax_node| {
|
||||
(
|
||||
line_index.line_col(syntax_node.range().start()),
|
||||
line_index.line_col(syntax_node.range().end()),
|
||||
)
|
||||
});
|
||||
let line_col = match line_col {
|
||||
Some((start, end)) => format!(
|
||||
"{}:{}-{}:{}",
|
||||
let src = f.expr_source(db, expr_id);
|
||||
if let Some(src) = src {
|
||||
// FIXME: it might be nice to have a function (on Analysis?) that goes from Source<T> -> (LineCol, LineCol) directly
|
||||
let original_file = src.file_id.original_file(db);
|
||||
let path = db.file_relative_path(original_file);
|
||||
let line_index = host.analysis().file_line_index(original_file).unwrap();
|
||||
let (start, end) = (
|
||||
line_index.line_col(src.ast.syntax().text_range().start()),
|
||||
line_index.line_col(src.ast.syntax().text_range().end()),
|
||||
);
|
||||
bar.println(format!(
|
||||
"{} {}:{}-{}:{}: Expected {}, got {}",
|
||||
path.display(),
|
||||
start.line + 1,
|
||||
start.col_utf16,
|
||||
end.line + 1,
|
||||
end.col_utf16
|
||||
),
|
||||
None => "?:?".to_string(),
|
||||
};
|
||||
bar.println(format!(
|
||||
"{} {}: Expected {}, got {}",
|
||||
path.display(),
|
||||
line_col,
|
||||
mismatch.expected.display(db),
|
||||
mismatch.actual.display(db)
|
||||
));
|
||||
end.col_utf16,
|
||||
mismatch.expected.display(db),
|
||||
mismatch.actual.display(db)
|
||||
));
|
||||
} else {
|
||||
bar.println(format!(
|
||||
"{}: Expected {}, got {}",
|
||||
name,
|
||||
mismatch.expected.display(db),
|
||||
mismatch.actual.display(db)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -510,18 +510,6 @@ pub enum DefWithBody {
|
||||
impl_froms!(DefWithBody: Function, Const, Static);
|
||||
|
||||
impl DefWithBody {
|
||||
pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
|
||||
db.infer(self)
|
||||
}
|
||||
|
||||
pub fn body(self, db: &impl HirDatabase) -> Arc<Body> {
|
||||
db.body_hir(self)
|
||||
}
|
||||
|
||||
pub fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
db.body_with_source_map(self).1
|
||||
}
|
||||
|
||||
/// Builds a resolver for code inside this item.
|
||||
pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
|
||||
match self {
|
||||
@ -532,6 +520,43 @@ impl DefWithBody {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasBody: Copy {
|
||||
fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult>;
|
||||
fn body(self, db: &impl HirDatabase) -> Arc<Body>;
|
||||
fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap>;
|
||||
}
|
||||
|
||||
impl<T> HasBody for T
|
||||
where
|
||||
T: Into<DefWithBody> + Copy + HasSource,
|
||||
{
|
||||
fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
|
||||
db.infer(self.into())
|
||||
}
|
||||
|
||||
fn body(self, db: &impl HirDatabase) -> Arc<Body> {
|
||||
db.body_hir(self.into())
|
||||
}
|
||||
|
||||
fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
db.body_with_source_map(self.into()).1
|
||||
}
|
||||
}
|
||||
|
||||
impl HasBody for DefWithBody {
|
||||
fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
|
||||
db.infer(self)
|
||||
}
|
||||
|
||||
fn body(self, db: &impl HirDatabase) -> Arc<Body> {
|
||||
db.body_hir(self)
|
||||
}
|
||||
|
||||
fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
db.body_with_source_map(self).1
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Function {
|
||||
pub(crate) id: FunctionId,
|
||||
@ -617,7 +642,7 @@ impl Function {
|
||||
self.data(db).name.clone()
|
||||
}
|
||||
|
||||
pub fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
pub(crate) fn body_source_map(self, db: &impl HirDatabase) -> Arc<BodySourceMap> {
|
||||
db.body_with_source_map(self.into()).1
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
use ra_syntax::ast;
|
||||
use ra_syntax::ast::{self, AstNode};
|
||||
|
||||
use crate::{
|
||||
ids::AstItemDef, AstDatabase, Const, DefDatabase, Enum, EnumVariant, FieldSource, Function,
|
||||
HirFileId, MacroDef, Module, ModuleSource, Static, Struct, StructField, Trait, TypeAlias,
|
||||
Union,
|
||||
HasBody, HirDatabase, HirFileId, MacroDef, Module, ModuleSource, Static, Struct, StructField,
|
||||
Trait, TypeAlias, Union,
|
||||
};
|
||||
|
||||
pub struct Source<T> {
|
||||
@ -108,3 +108,27 @@ impl HasSource for MacroDef {
|
||||
Source { file_id: self.id.0.file_id(), ast: self.id.0.to_node(db) }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasBodySource: HasBody + HasSource
|
||||
where
|
||||
Self::Ast: AstNode,
|
||||
{
|
||||
fn expr_source(
|
||||
self,
|
||||
db: &impl HirDatabase,
|
||||
expr_id: crate::expr::ExprId,
|
||||
) -> Option<Source<ast::Expr>> {
|
||||
let source_map = self.body_source_map(db);
|
||||
let expr_syntax = source_map.expr_syntax(expr_id)?;
|
||||
let source = self.source(db);
|
||||
let node = expr_syntax.to_node(&source.ast.syntax());
|
||||
ast::Expr::cast(node).map(|ast| Source { file_id: source.file_id, ast })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> HasBodySource for T
|
||||
where
|
||||
T: HasBody + HasSource,
|
||||
T::Ast: AstNode,
|
||||
{
|
||||
}
|
||||
|
@ -128,27 +128,27 @@ impl Index<PatId> for Body {
|
||||
}
|
||||
|
||||
impl BodySourceMap {
|
||||
pub fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> {
|
||||
pub(crate) fn expr_syntax(&self, expr: ExprId) -> Option<SyntaxNodePtr> {
|
||||
self.expr_map_back.get(expr).cloned()
|
||||
}
|
||||
|
||||
pub fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> {
|
||||
pub(crate) fn syntax_expr(&self, ptr: SyntaxNodePtr) -> Option<ExprId> {
|
||||
self.expr_map.get(&ptr).cloned()
|
||||
}
|
||||
|
||||
pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
|
||||
pub(crate) fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> {
|
||||
self.expr_map.get(&SyntaxNodePtr::new(node.syntax())).cloned()
|
||||
}
|
||||
|
||||
pub fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> {
|
||||
pub(crate) fn pat_syntax(&self, pat: PatId) -> Option<PatPtr> {
|
||||
self.pat_map_back.get(pat).cloned()
|
||||
}
|
||||
|
||||
pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
|
||||
pub(crate) fn node_pat(&self, node: &ast::Pat) -> Option<PatId> {
|
||||
self.pat_map.get(&Either::A(AstPtr::new(node))).cloned()
|
||||
}
|
||||
|
||||
pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
|
||||
pub(crate) fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
|
||||
self.field_map[&(expr, field)]
|
||||
}
|
||||
}
|
||||
|
@ -75,8 +75,8 @@ pub use self::{
|
||||
|
||||
pub use self::code_model::{
|
||||
docs::{DocDef, Docs, Documentation},
|
||||
src::{HasSource, Source},
|
||||
src::{HasBodySource, HasSource, Source},
|
||||
BuiltinType, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum,
|
||||
EnumVariant, FieldSource, FnData, Function, MacroDef, Module, ModuleDef, ModuleSource, Static,
|
||||
Struct, StructField, Trait, TypeAlias, Union,
|
||||
EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef, ModuleSource,
|
||||
Static, Struct, StructField, Trait, TypeAlias, Union,
|
||||
};
|
||||
|
@ -27,9 +27,9 @@ use crate::{
|
||||
name,
|
||||
path::{PathKind, PathSegment},
|
||||
ty::method_resolution::implements_trait,
|
||||
AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId,
|
||||
MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static, Struct, Trait,
|
||||
Ty,
|
||||
AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirDatabase,
|
||||
HirFileId, MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static,
|
||||
Struct, Trait, Ty,
|
||||
};
|
||||
|
||||
/// Locates the module by `FileId`. Picks topmost module in the file.
|
||||
|
@ -50,8 +50,8 @@ use crate::{
|
||||
},
|
||||
ty::infer::diagnostics::InferenceDiagnostic,
|
||||
type_ref::{Mutability, TypeRef},
|
||||
AdtDef, ConstData, DefWithBody, FnData, Function, HirDatabase, ImplItem, ModuleDef, Name, Path,
|
||||
StructField,
|
||||
AdtDef, ConstData, DefWithBody, FnData, Function, HasBody, HirDatabase, ImplItem, ModuleDef,
|
||||
Name, Path, StructField,
|
||||
};
|
||||
|
||||
mod unify;
|
||||
|
@ -15,9 +15,8 @@ impl SyntaxNodePtr {
|
||||
SyntaxNodePtr { range: node.text_range(), kind: node.kind() }
|
||||
}
|
||||
|
||||
pub fn to_node(self, root: &SyntaxNode) -> SyntaxNode {
|
||||
assert!(root.parent().is_none());
|
||||
successors(Some(root.clone()), |node| {
|
||||
pub fn to_node(self, parent: &SyntaxNode) -> SyntaxNode {
|
||||
successors(Some(parent.clone()), |node| {
|
||||
node.children().find(|it| self.range.is_subrange(&it.text_range()))
|
||||
})
|
||||
.find(|it| it.text_range() == self.range && it.kind() == self.kind)
|
||||
|
Loading…
x
Reference in New Issue
Block a user