Merge #3951
3951: Simplify records grammar r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
1a1c09ed3e
@ -139,7 +139,7 @@ impl SourceAnalyzer {
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
field: &ast::FieldExpr,
|
||||
) -> Option<crate::StructField> {
|
||||
) -> Option<StructField> {
|
||||
let expr_id = self.expr_id(db, &field.clone().into())?;
|
||||
self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into())
|
||||
}
|
||||
@ -148,21 +148,19 @@ impl SourceAnalyzer {
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
field: &ast::RecordField,
|
||||
) -> Option<(crate::StructField, Option<Local>)> {
|
||||
let (expr_id, local) = match field.expr() {
|
||||
Some(it) => (self.expr_id(db, &it)?, None),
|
||||
None => {
|
||||
let src = InFile { file_id: self.file_id, value: field };
|
||||
let expr_id = self.body_source_map.as_ref()?.field_init_shorthand_expr(src)?;
|
||||
let local_name = field.name_ref()?.as_name();
|
||||
let path = ModPath::from_segments(PathKind::Plain, once(local_name));
|
||||
let local = match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) {
|
||||
Some(ValueNs::LocalBinding(pat_id)) => {
|
||||
Some(Local { pat_id, parent: self.resolver.body_owner()? })
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
(expr_id, local)
|
||||
) -> Option<(StructField, Option<Local>)> {
|
||||
let expr = field.expr()?;
|
||||
let expr_id = self.expr_id(db, &expr)?;
|
||||
let local = if field.name_ref().is_some() {
|
||||
None
|
||||
} else {
|
||||
let local_name = field.field_name()?.as_name();
|
||||
let path = ModPath::from_segments(PathKind::Plain, once(local_name));
|
||||
match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) {
|
||||
Some(ValueNs::LocalBinding(pat_id)) => {
|
||||
Some(Local { pat_id, parent: self.resolver.body_owner()? })
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
let struct_field = self.infer.as_ref()?.record_field_resolution(expr_id)?;
|
||||
@ -319,8 +317,7 @@ fn scope_for_offset(
|
||||
if source.file_id != offset.file_id {
|
||||
return None;
|
||||
}
|
||||
let syntax_node_ptr =
|
||||
source.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
|
||||
let syntax_node_ptr = source.value.syntax_node_ptr();
|
||||
Some((syntax_node_ptr, scope))
|
||||
})
|
||||
// find containing scope
|
||||
@ -399,8 +396,7 @@ fn adjust(
|
||||
if source.file_id != file_id {
|
||||
return None;
|
||||
}
|
||||
let syntax_node_ptr =
|
||||
source.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
|
||||
let syntax_node_ptr = source.value.syntax_node_ptr();
|
||||
Some((syntax_node_ptr, scope))
|
||||
})
|
||||
.map(|(ptr, scope)| (ptr.range(), scope))
|
||||
|
@ -9,6 +9,8 @@ use drop_bomb::DropBomb;
|
||||
use either::Either;
|
||||
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId};
|
||||
use ra_arena::{map::ArenaMap, Arena};
|
||||
use ra_cfg::CfgOptions;
|
||||
use ra_db::CrateId;
|
||||
use ra_prof::profile;
|
||||
use ra_syntax::{ast, AstNode, AstPtr};
|
||||
use rustc_hash::FxHashMap;
|
||||
@ -24,8 +26,6 @@ use crate::{
|
||||
src::HasSource,
|
||||
AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId,
|
||||
};
|
||||
use ra_cfg::CfgOptions;
|
||||
use ra_db::CrateId;
|
||||
|
||||
/// A subser of Exander that only deals with cfg attributes. We only need it to
|
||||
/// avoid cyclic queries in crate def map during enum processing.
|
||||
@ -187,7 +187,7 @@ pub struct Body {
|
||||
pub item_scope: ItemScope,
|
||||
}
|
||||
|
||||
pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
|
||||
pub type ExprPtr = AstPtr<ast::Expr>;
|
||||
pub type ExprSource = InFile<ExprPtr>;
|
||||
|
||||
pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
|
||||
@ -285,7 +285,7 @@ impl BodySourceMap {
|
||||
}
|
||||
|
||||
pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> {
|
||||
let src = node.map(|it| Either::Left(AstPtr::new(it)));
|
||||
let src = node.map(|it| AstPtr::new(it));
|
||||
self.expr_map.get(&src).cloned()
|
||||
}
|
||||
|
||||
@ -294,11 +294,6 @@ impl BodySourceMap {
|
||||
self.expansions.get(&src).cloned()
|
||||
}
|
||||
|
||||
pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
|
||||
let src = node.map(|it| Either::Right(AstPtr::new(it)));
|
||||
self.expr_map.get(&src).cloned()
|
||||
}
|
||||
|
||||
pub fn pat_syntax(&self, pat: PatId) -> Result<PatSource, SyntheticSyntax> {
|
||||
self.pat_map_back[pat].clone()
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use crate::{
|
||||
},
|
||||
item_scope::BuiltinShadowMode,
|
||||
path::GenericArgs,
|
||||
path::Path,
|
||||
type_ref::{Mutability, TypeRef},
|
||||
AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
|
||||
StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
|
||||
@ -102,7 +101,6 @@ impl ExprCollector<'_> {
|
||||
}
|
||||
|
||||
fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
|
||||
let ptr = Either::Left(ptr);
|
||||
let src = self.expander.to_source(ptr);
|
||||
let id = self.make_expr(expr, Ok(src.clone()));
|
||||
self.source_map.expr_map.insert(src, id);
|
||||
@ -113,13 +111,6 @@ impl ExprCollector<'_> {
|
||||
fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
|
||||
self.make_expr(expr, Err(SyntheticSyntax))
|
||||
}
|
||||
fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId {
|
||||
let ptr = Either::Right(ptr);
|
||||
let src = self.expander.to_source(ptr);
|
||||
let id = self.make_expr(expr, Ok(src.clone()));
|
||||
self.source_map.expr_map.insert(src, id);
|
||||
id
|
||||
}
|
||||
fn empty_block(&mut self) -> ExprId {
|
||||
self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None })
|
||||
}
|
||||
@ -289,7 +280,7 @@ impl ExprCollector<'_> {
|
||||
ast::Expr::ParenExpr(e) => {
|
||||
let inner = self.collect_expr_opt(e.expr());
|
||||
// make the paren expr point to the inner expression as well
|
||||
let src = self.expander.to_source(Either::Left(syntax_ptr));
|
||||
let src = self.expander.to_source(syntax_ptr);
|
||||
self.source_map.expr_map.insert(src, inner);
|
||||
inner
|
||||
}
|
||||
@ -309,22 +300,13 @@ impl ExprCollector<'_> {
|
||||
if !self.expander.is_cfg_enabled(&attrs) {
|
||||
return None;
|
||||
}
|
||||
let name = field.field_name()?.as_name();
|
||||
|
||||
Some(RecordLitField {
|
||||
name: field
|
||||
.name_ref()
|
||||
.map(|nr| nr.as_name())
|
||||
.unwrap_or_else(Name::missing),
|
||||
expr: if let Some(e) = field.expr() {
|
||||
self.collect_expr(e)
|
||||
} else if let Some(nr) = field.name_ref() {
|
||||
// field shorthand
|
||||
self.alloc_expr_field_shorthand(
|
||||
Expr::Path(Path::from_name_ref(&nr)),
|
||||
AstPtr::new(&field),
|
||||
)
|
||||
} else {
|
||||
self.missing_expr()
|
||||
name,
|
||||
expr: match field.expr() {
|
||||
Some(e) => self.collect_expr(e),
|
||||
None => self.missing_expr(),
|
||||
},
|
||||
})
|
||||
})
|
||||
|
@ -134,11 +134,6 @@ impl Path {
|
||||
lower::lower_path(path, hygiene)
|
||||
}
|
||||
|
||||
/// Converts an `ast::NameRef` into a single-identifier `Path`.
|
||||
pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
|
||||
Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] }
|
||||
}
|
||||
|
||||
/// Converts a known mod path to `Path`.
|
||||
pub(crate) fn from_known_path(
|
||||
path: ModPath,
|
||||
|
@ -89,21 +89,19 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
||||
let (_, source_map) = db.body_with_source_map(self.func.into());
|
||||
|
||||
if let Ok(source_ptr) = source_map.expr_syntax(id) {
|
||||
if let Some(expr) = source_ptr.value.as_ref().left() {
|
||||
let root = source_ptr.file_syntax(db.upcast());
|
||||
if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) {
|
||||
if let Some(field_list) = record_lit.record_field_list() {
|
||||
let variant_data = variant_data(db.upcast(), variant_def);
|
||||
let missed_fields = missed_fields
|
||||
.into_iter()
|
||||
.map(|idx| variant_data.fields()[idx].name.clone())
|
||||
.collect();
|
||||
self.sink.push(MissingFields {
|
||||
file: source_ptr.file_id,
|
||||
field_list: AstPtr::new(&field_list),
|
||||
missed_fields,
|
||||
})
|
||||
}
|
||||
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() {
|
||||
let variant_data = variant_data(db.upcast(), variant_def);
|
||||
let missed_fields = missed_fields
|
||||
.into_iter()
|
||||
.map(|idx| variant_data.fields()[idx].name.clone())
|
||||
.collect();
|
||||
self.sink.push(MissingFields {
|
||||
file: source_ptr.file_id,
|
||||
field_list: AstPtr::new(&field_list),
|
||||
missed_fields,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,18 +203,16 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
||||
}
|
||||
|
||||
if let Ok(source_ptr) = source_map.expr_syntax(id) {
|
||||
if let Some(expr) = source_ptr.value.as_ref().left() {
|
||||
let root = source_ptr.file_syntax(db.upcast());
|
||||
if let ast::Expr::MatchExpr(match_expr) = expr.to_node(&root) {
|
||||
if let (Some(match_expr), Some(arms)) =
|
||||
(match_expr.expr(), match_expr.match_arm_list())
|
||||
{
|
||||
self.sink.push(MissingMatchArms {
|
||||
file: source_ptr.file_id,
|
||||
match_expr: AstPtr::new(&match_expr),
|
||||
arms: AstPtr::new(&arms),
|
||||
})
|
||||
}
|
||||
let root = source_ptr.file_syntax(db.upcast());
|
||||
if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) {
|
||||
if let (Some(match_expr), Some(arms)) =
|
||||
(match_expr.expr(), match_expr.match_arm_list())
|
||||
{
|
||||
self.sink.push(MissingMatchArms {
|
||||
file: source_ptr.file_id,
|
||||
match_expr: AstPtr::new(&match_expr),
|
||||
arms: AstPtr::new(&arms),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,9 +243,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
||||
let (_, source_map) = db.body_with_source_map(self.func.into());
|
||||
|
||||
if let Ok(source_ptr) = source_map.expr_syntax(id) {
|
||||
if let Some(expr) = source_ptr.value.left() {
|
||||
self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr });
|
||||
}
|
||||
self.sink
|
||||
.push(MissingOkInTailExpr { file: source_ptr.file_id, expr: source_ptr.value });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,9 +82,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
|
||||
|
||||
for (expr, ty) in inference_result.type_of_expr.iter() {
|
||||
let syntax_ptr = match body_source_map.expr_syntax(expr) {
|
||||
Ok(sp) => {
|
||||
sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()))
|
||||
}
|
||||
Ok(sp) => sp.map(|ast| ast.syntax_node_ptr()),
|
||||
Err(SyntheticSyntax) => continue,
|
||||
};
|
||||
types.push((syntax_ptr.clone(), ty));
|
||||
|
@ -3,7 +3,7 @@
|
||||
use crate::completion::{CompletionContext, Completions};
|
||||
|
||||
pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const) {
|
||||
if !(ctx.is_trivial_path && !ctx.is_pat_binding_or_const && !ctx.record_lit_syntax.is_some()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -227,7 +227,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 name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() {
|
||||
if ast::RecordField::for_field_name(&name_ref).is_some() {
|
||||
self.record_lit_syntax =
|
||||
self.sema.find_node_at_offset_with_macros(&original_file, offset);
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ pub fn classify_name_ref(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(record_field) = ast::RecordField::cast(parent.clone()) {
|
||||
if let Some(record_field) = ast::RecordField::for_field_name(name_ref) {
|
||||
tested_by!(goto_def_for_record_fields; force);
|
||||
tested_by!(goto_def_for_field_init_shorthand; force);
|
||||
if let Some((field, local)) = sema.resolve_record_field(&record_field) {
|
||||
|
@ -619,26 +619,39 @@ pub(crate) fn record_field_list(p: &mut Parser) {
|
||||
let m = p.start();
|
||||
p.bump(T!['{']);
|
||||
while !p.at(EOF) && !p.at(T!['}']) {
|
||||
let m = p.start();
|
||||
// test record_literal_field_with_attr
|
||||
// fn main() {
|
||||
// S { #[cfg(test)] field: 1 }
|
||||
// }
|
||||
attributes::outer_attributes(p);
|
||||
|
||||
match p.current() {
|
||||
// test record_literal_field_with_attr
|
||||
// fn main() {
|
||||
// S { #[cfg(test)] field: 1 }
|
||||
// }
|
||||
IDENT | INT_NUMBER | T![#] => {
|
||||
let m = p.start();
|
||||
attributes::outer_attributes(p);
|
||||
name_ref_or_index(p);
|
||||
if p.eat(T![:]) {
|
||||
expr(p);
|
||||
IDENT | INT_NUMBER => {
|
||||
// test_err record_literal_before_ellipsis_recovery
|
||||
// fn main() {
|
||||
// S { field ..S::default() }
|
||||
// }
|
||||
if p.nth_at(1, T![:]) || p.nth_at(1, T![..]) {
|
||||
name_ref_or_index(p);
|
||||
p.expect(T![:]);
|
||||
}
|
||||
expr(p);
|
||||
m.complete(p, RECORD_FIELD);
|
||||
}
|
||||
T![.] if p.at(T![..]) => {
|
||||
m.abandon(p);
|
||||
p.bump(T![..]);
|
||||
expr(p);
|
||||
}
|
||||
T!['{'] => error_block(p, "expected a field"),
|
||||
_ => p.err_and_bump("expected identifier"),
|
||||
T!['{'] => {
|
||||
error_block(p, "expected a field");
|
||||
m.abandon(p);
|
||||
}
|
||||
_ => {
|
||||
p.err_and_bump("expected identifier");
|
||||
m.abandon(p);
|
||||
}
|
||||
}
|
||||
if !p.at(T!['}']) {
|
||||
p.expect(T![,]);
|
||||
|
@ -187,6 +187,36 @@ impl ast::StructDef {
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::RecordField {
|
||||
pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordField> {
|
||||
let candidate =
|
||||
field_name.syntax().parent().and_then(ast::RecordField::cast).or_else(|| {
|
||||
field_name.syntax().ancestors().nth(4).and_then(ast::RecordField::cast)
|
||||
})?;
|
||||
if candidate.field_name().as_ref() == Some(field_name) {
|
||||
Some(candidate)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Deals with field init shorthand
|
||||
pub fn field_name(&self) -> Option<ast::NameRef> {
|
||||
if let Some(name_ref) = self.name_ref() {
|
||||
return Some(name_ref);
|
||||
}
|
||||
if let Some(ast::Expr::PathExpr(expr)) = self.expr() {
|
||||
let path = expr.path()?;
|
||||
let segment = path.segment()?;
|
||||
let name_ref = segment.name_ref()?;
|
||||
if path.qualifier().is_none() {
|
||||
return Some(name_ref);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::EnumVariant {
|
||||
pub fn parent_enum(&self) -> ast::EnumDef {
|
||||
self.syntax()
|
||||
|
@ -19,6 +19,11 @@
|
||||
//! [RFC]: <https://github.com/rust-lang/rfcs/pull/2256>
|
||||
//! [Swift]: <https://github.com/apple/swift/blob/13d593df6f359d0cb2fc81cfaac273297c539455/lib/Syntax/README.md>
|
||||
|
||||
#[allow(unused)]
|
||||
macro_rules! eprintln {
|
||||
($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
|
||||
}
|
||||
|
||||
mod syntax_node;
|
||||
mod syntax_error;
|
||||
mod parsing;
|
||||
|
@ -0,0 +1,49 @@
|
||||
SOURCE_FILE@[0; 45)
|
||||
FN_DEF@[0; 44)
|
||||
FN_KW@[0; 2) "fn"
|
||||
WHITESPACE@[2; 3) " "
|
||||
NAME@[3; 7)
|
||||
IDENT@[3; 7) "main"
|
||||
PARAM_LIST@[7; 9)
|
||||
L_PAREN@[7; 8) "("
|
||||
R_PAREN@[8; 9) ")"
|
||||
WHITESPACE@[9; 10) " "
|
||||
BLOCK_EXPR@[10; 44)
|
||||
BLOCK@[10; 44)
|
||||
L_CURLY@[10; 11) "{"
|
||||
WHITESPACE@[11; 16) "\n "
|
||||
RECORD_LIT@[16; 42)
|
||||
PATH@[16; 17)
|
||||
PATH_SEGMENT@[16; 17)
|
||||
NAME_REF@[16; 17)
|
||||
IDENT@[16; 17) "S"
|
||||
WHITESPACE@[17; 18) " "
|
||||
RECORD_FIELD_LIST@[18; 42)
|
||||
L_CURLY@[18; 19) "{"
|
||||
WHITESPACE@[19; 20) " "
|
||||
RECORD_FIELD@[20; 40)
|
||||
NAME_REF@[20; 25)
|
||||
IDENT@[20; 25) "field"
|
||||
WHITESPACE@[25; 26) " "
|
||||
RANGE_EXPR@[26; 40)
|
||||
DOT2@[26; 28) ".."
|
||||
CALL_EXPR@[28; 40)
|
||||
PATH_EXPR@[28; 38)
|
||||
PATH@[28; 38)
|
||||
PATH@[28; 29)
|
||||
PATH_SEGMENT@[28; 29)
|
||||
NAME_REF@[28; 29)
|
||||
IDENT@[28; 29) "S"
|
||||
COLON2@[29; 31) "::"
|
||||
PATH_SEGMENT@[31; 38)
|
||||
NAME_REF@[31; 38)
|
||||
IDENT@[31; 38) "default"
|
||||
ARG_LIST@[38; 40)
|
||||
L_PAREN@[38; 39) "("
|
||||
R_PAREN@[39; 40) ")"
|
||||
WHITESPACE@[40; 41) " "
|
||||
R_CURLY@[41; 42) "}"
|
||||
WHITESPACE@[42; 43) "\n"
|
||||
R_CURLY@[43; 44) "}"
|
||||
WHITESPACE@[44; 45) "\n"
|
||||
error [25; 25): expected COLON
|
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
S { field ..S::default() }
|
||||
}
|
@ -35,8 +35,11 @@ SOURCE_FILE@[0; 112)
|
||||
L_CURLY@[27; 28) "{"
|
||||
WHITESPACE@[28; 29) " "
|
||||
RECORD_FIELD@[29; 30)
|
||||
NAME_REF@[29; 30)
|
||||
IDENT@[29; 30) "x"
|
||||
PATH_EXPR@[29; 30)
|
||||
PATH@[29; 30)
|
||||
PATH_SEGMENT@[29; 30)
|
||||
NAME_REF@[29; 30)
|
||||
IDENT@[29; 30) "x"
|
||||
COMMA@[30; 31) ","
|
||||
WHITESPACE@[31; 32) " "
|
||||
RECORD_FIELD@[32; 37)
|
||||
@ -62,8 +65,11 @@ SOURCE_FILE@[0; 112)
|
||||
L_CURLY@[48; 49) "{"
|
||||
WHITESPACE@[49; 50) " "
|
||||
RECORD_FIELD@[50; 51)
|
||||
NAME_REF@[50; 51)
|
||||
IDENT@[50; 51) "x"
|
||||
PATH_EXPR@[50; 51)
|
||||
PATH@[50; 51)
|
||||
PATH_SEGMENT@[50; 51)
|
||||
NAME_REF@[50; 51)
|
||||
IDENT@[50; 51) "x"
|
||||
COMMA@[51; 52) ","
|
||||
WHITESPACE@[52; 53) " "
|
||||
RECORD_FIELD@[53; 58)
|
||||
|
@ -163,10 +163,7 @@ pub fn analysis_stats(
|
||||
if let Ok(src) = src {
|
||||
let original_file = src.file_id.original_file(db);
|
||||
let line_index = host.analysis().file_line_index(original_file).unwrap();
|
||||
let text_range = src.value.either(
|
||||
|it| it.syntax_node_ptr().range(),
|
||||
|it| it.syntax_node_ptr().range(),
|
||||
);
|
||||
let text_range = src.value.syntax_node_ptr().range();
|
||||
let (start, end) = (
|
||||
line_index.line_col(text_range.start()),
|
||||
line_index.line_col(text_range.end()),
|
||||
@ -192,12 +189,7 @@ pub fn analysis_stats(
|
||||
// FIXME: it might be nice to have a function (on Analysis?) that goes from Source<T> -> (LineCol, LineCol) directly
|
||||
// But also, we should just turn the type mismatches into diagnostics and provide these
|
||||
let root = db.parse_or_expand(src.file_id).unwrap();
|
||||
let node = src.map(|e| {
|
||||
e.either(
|
||||
|p| p.to_node(&root).syntax().clone(),
|
||||
|p| p.to_node(&root).syntax().clone(),
|
||||
)
|
||||
});
|
||||
let node = src.map(|e| e.to_node(&root).syntax().clone());
|
||||
let original_range = original_range(db, node.as_ref());
|
||||
let path = db.file_relative_path(original_range.file_id);
|
||||
let line_index =
|
||||
|
@ -395,7 +395,7 @@ pub fn skip_slow_tests() -> bool {
|
||||
should_skip
|
||||
}
|
||||
|
||||
const REWRITE: bool = true;
|
||||
const REWRITE: bool = false;
|
||||
|
||||
/// Asserts that `expected` and `actual` strings are equal. If they differ only
|
||||
/// in trailing or leading whitespace the test won't fail and
|
||||
|
Loading…
x
Reference in New Issue
Block a user