Skip to content

Commit 8e69377

Browse files
committed
Move explicit range handling out of goto_definition, use OperatorClass instead
1 parent e46ea16 commit 8e69377

File tree

5 files changed

+70
-53
lines changed

5 files changed

+70
-53
lines changed

src/tools/rust-analyzer/crates/hir/src/semantics.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use hir_def::{
1717
path::ModPath,
1818
resolver::{self, HasResolver, Resolver, TypeNs},
1919
type_ref::Mutability,
20-
AsMacroCall, DefWithBodyId, FunctionId, MacroId, TraitId, VariantId,
20+
AsMacroCall, DefWithBodyId, FunctionId, MacroId, StructId, TraitId, VariantId,
2121
};
2222
use hir_expand::{
2323
attrs::collect_attrs,
@@ -203,6 +203,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
203203
self.imp.descend_node_at_offset(node, offset).filter_map(|mut it| it.find_map(N::cast))
204204
}
205205

206+
pub fn resolve_range_expr(&self, range_expr: &ast::RangeExpr) -> Option<Struct> {
207+
self.imp.resolve_range_expr(range_expr).map(Struct::from)
208+
}
209+
206210
pub fn resolve_await_to_poll(&self, await_expr: &ast::AwaitExpr) -> Option<Function> {
207211
self.imp.resolve_await_to_poll(await_expr).map(Function::from)
208212
}
@@ -1357,6 +1361,10 @@ impl<'db> SemanticsImpl<'db> {
13571361
self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call)
13581362
}
13591363

1364+
fn resolve_range_expr(&self, range_expr: &ast::RangeExpr) -> Option<StructId> {
1365+
self.analyze(range_expr.syntax())?.resolve_range_expr(self.db, range_expr)
1366+
}
1367+
13601368
fn resolve_await_to_poll(&self, await_expr: &ast::AwaitExpr) -> Option<FunctionId> {
13611369
self.analyze(await_expr.syntax())?.resolve_await_to_poll(self.db, await_expr)
13621370
}

src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
//! purely for "IDE needs".
88
use std::iter::{self, once};
99

10+
use crate::{
11+
db::HirDatabase, semantics::PathResolution, Adt, AssocItem, BindingMode, BuiltinAttr,
12+
BuiltinType, Callable, Const, DeriveHelper, Field, Function, Local, Macro, ModuleDef, Static,
13+
Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, Variant,
14+
};
1015
use either::Either;
1116
use hir_def::{
1217
body::{
@@ -21,7 +26,7 @@ use hir_def::{
2126
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
2227
type_ref::Mutability,
2328
AsMacroCall, AssocItemId, ConstId, DefWithBodyId, FieldId, FunctionId, ItemContainerId,
24-
LocalFieldId, Lookup, ModuleDefId, TraitId, VariantId,
29+
LocalFieldId, Lookup, ModuleDefId, StructId, TraitId, VariantId,
2530
};
2631
use hir_expand::{
2732
mod_path::path,
@@ -40,18 +45,13 @@ use hir_ty::{
4045
use intern::sym;
4146
use itertools::Itertools;
4247
use smallvec::SmallVec;
48+
use syntax::ast::{RangeItem, RangeOp};
4349
use syntax::{
4450
ast::{self, AstNode},
4551
SyntaxKind, SyntaxNode, TextRange, TextSize,
4652
};
4753
use triomphe::Arc;
4854

49-
use crate::{
50-
db::HirDatabase, semantics::PathResolution, Adt, AssocItem, BindingMode, BuiltinAttr,
51-
BuiltinType, Callable, Const, DeriveHelper, Field, Function, Local, Macro, ModuleDef, Static,
52-
Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, Variant,
53-
};
54-
5555
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
5656
/// original source files. It should not be used inside the HIR itself.
5757
#[derive(Debug)]
@@ -348,6 +348,18 @@ impl SourceAnalyzer {
348348
}
349349
}
350350

351+
pub(crate) fn resolve_range_expr(
352+
&self,
353+
db: &dyn HirDatabase,
354+
range_expr: &ast::RangeExpr,
355+
) -> Option<StructId> {
356+
let path = match range_expr.op_kind()? {
357+
RangeOp::Exclusive => path![core::ops::Range],
358+
RangeOp::Inclusive => path![core::ops::RangeInclusive],
359+
};
360+
self.resolver.resolve_known_struct(db.upcast(), &path)
361+
}
362+
351363
pub(crate) fn resolve_await_to_poll(
352364
&self,
353365
db: &dyn HirDatabase,

src/tools/rust-analyzer/crates/ide-db/src/defs.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
66
// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
77

8+
use crate::documentation::{Documentation, HasDocs};
9+
use crate::famous_defs::FamousDefs;
10+
use crate::RootDatabase;
811
use arrayvec::ArrayVec;
912
use either::Either;
1013
use hir::{
1114
Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType,
1215
Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field,
1316
Function, GenericParam, HasVisibility, HirDisplay, Impl, InlineAsmOperand, Label, Local, Macro,
14-
Module, ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, ToolModule, Trait,
15-
TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
17+
Module, ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, Struct, ToolModule,
18+
Trait, TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
1619
};
1720
use span::Edition;
1821
use stdx::{format_to, impl_from};
@@ -21,10 +24,6 @@ use syntax::{
2124
match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
2225
};
2326

24-
use crate::documentation::{Documentation, HasDocs};
25-
use crate::famous_defs::FamousDefs;
26-
use crate::RootDatabase;
27-
2827
// FIXME: a more precise name would probably be `Symbol`?
2928
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
3029
pub enum Definition {
@@ -319,6 +318,7 @@ impl IdentClass {
319318
.map(IdentClass::NameClass)
320319
.or_else(|| NameRefClass::classify_lifetime(sema, &lifetime).map(IdentClass::NameRefClass))
321320
},
321+
ast::RangeExpr(range_expr) => OperatorClass::classify_range(sema, &range_expr).map(IdentClass::Operator),
322322
ast::AwaitExpr(await_expr) => OperatorClass::classify_await(sema, &await_expr).map(IdentClass::Operator),
323323
ast::BinExpr(bin_expr) => OperatorClass::classify_bin(sema, &bin_expr).map(IdentClass::Operator),
324324
ast::IndexExpr(index_expr) => OperatorClass::classify_index(sema, &index_expr).map(IdentClass::Operator),
@@ -372,6 +372,9 @@ impl IdentClass {
372372
| OperatorClass::Index(func)
373373
| OperatorClass::Try(func),
374374
) => res.push(Definition::Function(func)),
375+
IdentClass::Operator(OperatorClass::Range(struct0)) => {
376+
res.push(Definition::Adt(Adt::Struct(struct0)))
377+
}
375378
}
376379
res
377380
}
@@ -546,6 +549,7 @@ impl NameClass {
546549

547550
#[derive(Debug)]
548551
pub enum OperatorClass {
552+
Range(Struct),
549553
Await(Function),
550554
Prefix(Function),
551555
Index(Function),
@@ -554,6 +558,13 @@ pub enum OperatorClass {
554558
}
555559

556560
impl OperatorClass {
561+
pub fn classify_range(
562+
sema: &Semantics<'_, RootDatabase>,
563+
range_expr: &ast::RangeExpr,
564+
) -> Option<OperatorClass> {
565+
sema.resolve_range_expr(range_expr).map(OperatorClass::Range)
566+
}
567+
557568
pub fn classify_await(
558569
sema: &Semantics<'_, RootDatabase>,
559570
await_expr: &ast::AwaitExpr,

src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! See [`FamousDefs`].
22
33
use base_db::{CrateOrigin, LangCrateOrigin, SourceDatabase};
4-
use hir::{Crate, Enum, Function, Macro, Module, ScopeDef, Semantics, Struct, Trait};
4+
use hir::{Crate, Enum, Function, Macro, Module, ScopeDef, Semantics, Trait};
55

66
use crate::RootDatabase;
77

@@ -102,14 +102,6 @@ impl FamousDefs<'_, '_> {
102102
self.find_trait("core:ops:Drop")
103103
}
104104

105-
pub fn core_ops_Range(&self) -> Option<Struct> {
106-
self.find_struct("core:ops:Range")
107-
}
108-
109-
pub fn core_ops_RangeInclusive(&self) -> Option<Struct> {
110-
self.find_struct("core:ops:RangeInclusive")
111-
}
112-
113105
pub fn core_marker_Copy(&self) -> Option<Trait> {
114106
self.find_trait("core:marker:Copy")
115107
}
@@ -145,13 +137,6 @@ impl FamousDefs<'_, '_> {
145137
.flatten()
146138
}
147139

148-
fn find_struct(&self, path: &str) -> Option<Struct> {
149-
match self.find_def(path)? {
150-
hir::ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(it))) => Some(it),
151-
_ => None,
152-
}
153-
}
154-
155140
fn find_trait(&self, path: &str) -> Option<Trait> {
156141
match self.find_def(path)? {
157142
hir::ScopeDef::ModuleDef(hir::ModuleDef::Trait(it)) => Some(it),

src/tools/rust-analyzer/crates/ide/src/goto_definition.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ use crate::{
55
navigation_target::{self, ToNav},
66
FilePosition, NavigationTarget, RangeInfo, TryToNav, UpmappingResult,
77
};
8-
use hir::{Adt, AsAssocItem, AssocItem, FileRange, InFile, MacroFileIdExt, ModuleDef, Semantics};
8+
use hir::{AsAssocItem, AssocItem, FileRange, InFile, MacroFileIdExt, ModuleDef, Semantics};
99
use ide_db::{
1010
base_db::{AnchoredPath, FileLoader, SourceDatabase},
1111
defs::{Definition, IdentClass},
1212
helpers::pick_best_token,
1313
RootDatabase, SymbolKind,
1414
};
1515
use itertools::Itertools;
16-
use ide_db::famous_defs::FamousDefs;
1716
use span::{Edition, FileId};
1817
use syntax::{
1918
ast::{self, HasLoopBody},
@@ -41,22 +40,6 @@ pub(crate) fn goto_definition(
4140
) -> Option<RangeInfo<Vec<NavigationTarget>>> {
4241
let sema = &Semantics::new(db);
4342
let file = sema.parse_guess_edition(file_id).syntax().clone();
44-
45-
if let syntax::TokenAtOffset::Single(tok) = file.token_at_offset(offset) {
46-
if let Some(module) = sema.file_to_module_def(file_id) {
47-
let famous_defs = FamousDefs(sema, module.krate());
48-
let maybe_famous_struct = match tok.kind() {
49-
T![..] => famous_defs.core_ops_Range(),
50-
T![..=] => famous_defs.core_ops_RangeInclusive(),
51-
_ => None
52-
};
53-
if let Some(fstruct) = maybe_famous_struct {
54-
let target = def_to_nav(db, Definition::Adt(Adt::Struct(fstruct)));
55-
return Some(RangeInfo::new(tok.text_range(), target));
56-
}
57-
}
58-
}
59-
6043
let edition =
6144
sema.attach_first_edition(file_id).map(|it| it.edition()).unwrap_or(Edition::CURRENT);
6245
let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
@@ -434,10 +417,10 @@ fn expr_to_nav(
434417

435418
#[cfg(test)]
436419
mod tests {
420+
use crate::fixture;
437421
use ide_db::FileRange;
438422
use itertools::Itertools;
439423
use syntax::SmolStr;
440-
use crate::fixture;
441424

442425
#[track_caller]
443426
fn check(ra_fixture: &str) {
@@ -466,9 +449,25 @@ mod tests {
466449
assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}")
467450
}
468451

452+
#[test]
453+
fn goto_def_range_inclusive_0() {
454+
let ra_fixture = r#"
455+
//- minicore: range
456+
fn f(a: usize, b: usize) {
457+
for _ in a.$0.=b {
458+
459+
}
460+
}
461+
"#;
462+
let (analysis, position, _) = fixture::annotations(ra_fixture);
463+
let mut navs =
464+
analysis.goto_definition(position).unwrap().expect("no definition found").info;
465+
let Some(target) = navs.pop() else { panic!("no target found") };
466+
assert_eq!(target.name, SmolStr::new_inline("RangeInclusive"));
467+
}
469468

470469
#[test]
471-
fn goto_def_range_inclusive() {
470+
fn goto_def_range_inclusive_1() {
472471
let ra_fixture = r#"
473472
//- minicore: range
474473
fn f(a: usize, b: usize) {
@@ -478,13 +477,14 @@ fn f(a: usize, b: usize) {
478477
}
479478
"#;
480479
let (analysis, position, _) = fixture::annotations(ra_fixture);
481-
let mut navs = analysis.goto_definition(position).unwrap().expect("no definition found").info;
480+
let mut navs =
481+
analysis.goto_definition(position).unwrap().expect("no definition found").info;
482482
let Some(target) = navs.pop() else { panic!("no target found") };
483483
assert_eq!(target.name, SmolStr::new_inline("RangeInclusive"));
484484
}
485485

486486
#[test]
487-
fn goto_def_range_half_open() {
487+
fn goto_def_range() {
488488
let ra_fixture = r#"
489489
//- minicore: range
490490
fn f(a: usize, b: usize) {
@@ -494,7 +494,8 @@ fn f(a: usize, b: usize) {
494494
}
495495
"#;
496496
let (analysis, position, _) = fixture::annotations(ra_fixture);
497-
let mut navs = analysis.goto_definition(position).unwrap().expect("no definition found").info;
497+
let mut navs =
498+
analysis.goto_definition(position).unwrap().expect("no definition found").info;
498499
let Some(target) = navs.pop() else { panic!("no target found") };
499500
assert_eq!(target.name, SmolStr::new_inline("Range"));
500501
}

0 commit comments

Comments
 (0)