From 70293476acadcb432317a8856628e05548ce6d82 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Dec 2024 16:55:28 +0100 Subject: [PATCH 1/4] Enable "jump to def" feature on prelude variants --- src/librustdoc/html/highlight.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 48a537ad5e7ad..62cf2b63f7fd6 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -337,7 +337,7 @@ enum Class { Ident(Span), Lifetime, PreludeTy(Span), - PreludeVal, + PreludeVal(Span), QuestionMark, Decoration(&'static str), } @@ -385,7 +385,7 @@ impl Class { Class::Ident(_) => "", Class::Lifetime => "lifetime", Class::PreludeTy(_) => "prelude-ty", - Class::PreludeVal => "prelude-val", + Class::PreludeVal(_) => "prelude-val", Class::QuestionMark => "question-mark", Class::Decoration(kind) => kind, } @@ -395,7 +395,11 @@ impl Class { /// a "span" (a tuple representing `(lo, hi)` equivalent of `Span`). fn get_span(self) -> Option { match self { - Self::Ident(sp) | Self::Self_(sp) | Self::Macro(sp) | Self::PreludeTy(sp) => Some(sp), + Self::Ident(sp) + | Self::Self_(sp) + | Self::Macro(sp) + | Self::PreludeTy(sp) + | Self::PreludeVal(sp) => Some(sp), Self::Comment | Self::DocComment | Self::Attribute @@ -406,7 +410,6 @@ impl Class { | Self::Number | Self::Bool | Self::Lifetime - | Self::PreludeVal | Self::QuestionMark | Self::Decoration(_) => None, } @@ -851,7 +854,9 @@ impl<'src> Classifier<'src> { TokenKind::Ident => match get_real_ident_class(text, false) { None => match text { "Option" | "Result" => Class::PreludeTy(self.new_span(before, text)), - "Some" | "None" | "Ok" | "Err" => Class::PreludeVal, + "Some" | "None" | "Ok" | "Err" => { + Class::PreludeVal(self.new_span(before, text)) + } // "union" is a weak keyword and is only considered as a keyword when declaring // a union type. "union" if self.check_if_is_union_keyword() => Class::KeyWord, From f6525a621ae815a981aff1c9d2e05ef631e62bd5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Dec 2024 16:55:53 +0100 Subject: [PATCH 2/4] Enable "jump to def" feature on patterns --- src/librustdoc/html/render/span_map.rs | 27 +++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 81d79a6be9683..e9250cf7edd10 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node}; +use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, Pat, PatKind, QPath}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::hygiene::MacroKind; @@ -189,6 +189,27 @@ impl SpanMapVisitor<'_> { self.matches.insert(span, link); } } + + fn handle_pat(&mut self, p: &Pat<'_>) { + match p.kind { + PatKind::Binding(_, _, _, Some(p)) => self.handle_pat(p), + PatKind::Struct(qpath, _, _) + | PatKind::TupleStruct(qpath, _, _) + | PatKind::Path(qpath) => match qpath { + QPath::TypeRelative(_, path) if matches!(path.res, Res::Err) => { + self.handle_call(path.hir_id, Some(p.hir_id), qpath.span()); + } + QPath::Resolved(_, path) => self.handle_path(path), + _ => {} + }, + PatKind::Or(pats) => { + for pat in pats { + self.handle_pat(pat); + } + } + _ => {} + } + } } impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { @@ -206,6 +227,10 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { intravisit::walk_path(self, path); } + fn visit_pat(&mut self, p: &Pat<'tcx>) { + self.handle_pat(p); + } + fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) { // To make the difference between "mod foo {}" and "mod foo;". In case we "import" another // file, we want to link to it. Otherwise no need to create a link. From 140640a8cf7650f0c574f444c300e4c7cbf92cf3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Dec 2024 17:08:36 +0100 Subject: [PATCH 3/4] Add regression test for patterns support in "jump to def" feature --- tests/rustdoc/jump-to-def-pats.rs | 52 +++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/rustdoc/jump-to-def-pats.rs diff --git a/tests/rustdoc/jump-to-def-pats.rs b/tests/rustdoc/jump-to-def-pats.rs new file mode 100644 index 0000000000000..147902b44cf5c --- /dev/null +++ b/tests/rustdoc/jump-to-def-pats.rs @@ -0,0 +1,52 @@ +// This test ensures that patterns also get a link generated. + +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +//@ has 'src/foo/jump-to-def-pats.rs.html' + +use std::fmt; + +pub enum MyEnum { + Ok(T), + Err(E), + Some(T), + None, +} + +pub enum X { + A, +} + +pub fn foo() -> Result<(), ()> { + // FIXME: would be nice to be able to check both the class and the href at the same time so + // we could check the text as well... + //@ has - '//a[@class="prelude-val"]/@href' '{{channel}}/core/result/enum.Result.html#variant.Ok' + //@ has - '//a[@href="{{channel}}/core/result/enum.Result.html#variant.Ok"]' 'Ok' + Ok(()) +} + +impl fmt::Display for MyEnum { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + //@ has - '//a[@href="#12"]' 'Self::Ok' + Self::Ok(_) => f.write_str("MyEnum::Ok"), + //@ has - '//a[@href="#13"]' 'MyEnum::Err' + MyEnum::Err(_) => f.write_str("MyEnum::Err"), + //@ has - '//a[@href="#14"]' 'Self::Some' + Self::Some(_) => f.write_str("MyEnum::Some"), + //@ has - '//a[@href="#15"]' 'Self::None' + Self::None => f.write_str("MyEnum::None"), + } + } +} + +impl X { + fn p(&self) -> &str { + match self { + //@ has - '//a[@href="#19"]' 'Self::A' + Self::A => "X::A", + } + } +} From 12a12c9a8399bd7f4eacb42d76a7480df5623989 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Dec 2024 17:09:38 +0100 Subject: [PATCH 4/4] Rename `handle_call` into `infer_id` --- src/librustdoc/html/render/span_map.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index e9250cf7edd10..2570596a49ca8 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -170,7 +170,7 @@ impl SpanMapVisitor<'_> { true } - fn handle_call(&mut self, hir_id: HirId, expr_hir_id: Option, span: Span) { + fn infer_id(&mut self, hir_id: HirId, expr_hir_id: Option, span: Span) { let hir = self.tcx.hir(); let body_id = hir.enclosing_body_owner(hir_id); // FIXME: this is showing error messages for parts of the code that are not @@ -197,7 +197,7 @@ impl SpanMapVisitor<'_> { | PatKind::TupleStruct(qpath, _, _) | PatKind::Path(qpath) => match qpath { QPath::TypeRelative(_, path) if matches!(path.res, Res::Err) => { - self.handle_call(path.hir_id, Some(p.hir_id), qpath.span()); + self.infer_id(path.hir_id, Some(p.hir_id), qpath.span()); } QPath::Resolved(_, path) => self.handle_path(path), _ => {} @@ -253,9 +253,9 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) { match expr.kind { ExprKind::MethodCall(segment, ..) => { - self.handle_call(segment.hir_id, Some(expr.hir_id), segment.ident.span) + self.infer_id(segment.hir_id, Some(expr.hir_id), segment.ident.span) } - ExprKind::Call(call, ..) => self.handle_call(call.hir_id, None, call.span), + ExprKind::Call(call, ..) => self.infer_id(call.hir_id, None, call.span), _ => { if self.handle_macro(expr.span) { // We don't want to go deeper into the macro.