Skip to content

Commit ca8bd3e

Browse files
bors[bot]Veykril
andauthored
Merge #11237
11237: fix: Fix outline modules spilling inner doc injections into their parent r=Veykril a=Veykril Fixes another regression caused by #11225 bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents 01c3303 + b32f611 commit ca8bd3e

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

crates/hir_def/src/attr.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,9 @@ impl AttrsWithOwner {
390390
if let InFile { file_id, value: ModuleSource::SourceFile(file) } =
391391
mod_data.definition_source(db)
392392
{
393-
map.merge(AttrSourceMap::new(InFile::new(file_id, &file)));
393+
map.append_module_inline_attrs(AttrSourceMap::new(InFile::new(
394+
file_id, &file,
395+
)));
394396
}
395397
return map;
396398
}
@@ -552,18 +554,31 @@ fn inner_attributes(
552554
pub struct AttrSourceMap {
553555
source: Vec<Either<ast::Attr, ast::Comment>>,
554556
file_id: HirFileId,
557+
/// If this map is for a module, this will be the [`HirFileId`] of the module's definition site,
558+
/// while `file_id` will be the one of the module declaration site.
559+
/// The usize is the index into `source` from which point on the entries reside in the def site
560+
/// file.
561+
mod_def_site_file_id: Option<(HirFileId, usize)>,
555562
}
556563

557564
impl AttrSourceMap {
558565
fn new(owner: InFile<&dyn ast::HasAttrs>) -> Self {
559566
Self {
560567
source: collect_attrs(owner.value).map(|(_, it)| it).collect(),
561568
file_id: owner.file_id,
569+
mod_def_site_file_id: None,
562570
}
563571
}
564572

565-
fn merge(&mut self, other: Self) {
573+
/// Append a second source map to this one, this is required for modules, whose outline and inline
574+
/// attributes can reside in different files
575+
fn append_module_inline_attrs(&mut self, other: Self) {
576+
assert!(self.mod_def_site_file_id.is_none() && other.mod_def_site_file_id.is_none());
577+
let len = self.source.len();
566578
self.source.extend(other.source);
579+
if other.file_id != self.file_id {
580+
self.mod_def_site_file_id = Some((other.file_id, len));
581+
}
567582
}
568583

569584
/// Maps the lowered `Attr` back to its original syntax node.
@@ -577,9 +592,15 @@ impl AttrSourceMap {
577592
}
578593

579594
fn source_of_id(&self, id: AttrId) -> InFile<&Either<ast::Attr, ast::Comment>> {
595+
let ast_idx = id.ast_index as usize;
596+
let file_id = match self.mod_def_site_file_id {
597+
Some((file_id, def_site_cut)) if def_site_cut <= ast_idx => file_id,
598+
_ => self.file_id,
599+
};
600+
580601
self.source
581-
.get(id.ast_index as usize)
582-
.map(|it| InFile::new(self.file_id, it))
602+
.get(ast_idx)
603+
.map(|it| InFile::new(file_id, it))
583604
.unwrap_or_else(|| panic!("cannot find attr at index {:?}", id))
584605
}
585606
}

crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
<span class="comment documentation">//! </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function declaration injected">test</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span><span class="brace injected">}</span>
4747
<span class="comment documentation">//! ```</span>
4848

49+
<span class="keyword">mod</span> <span class="module declaration">outline_module</span><span class="semicolon">;</span>
50+
4951
<span class="comment documentation">/// ```</span>
5052
<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="punctuation injected">_</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="semicolon injected">;</span>
5153
<span class="comment documentation">/// ```</span>
@@ -170,4 +172,6 @@
170172
```
171173
</span><span class="function documentation injected intra_doc_link">[`block_comments`]</span><span class="comment documentation"> tests these without indentation
172174
*/</span>
173-
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration public">block_comments2</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span></code></pre>
175+
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration public">block_comments2</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
176+
177+
</code></pre>

crates/ide/src/syntax_highlighting/tests.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,11 +641,14 @@ fn main() {
641641
fn test_highlight_doc_comment() {
642642
check_highlighting(
643643
r#"
644+
//- /main.rs
644645
//! This is a module to test doc injection.
645646
//! ```
646647
//! fn test() {}
647648
//! ```
648649
650+
mod outline_module;
651+
649652
/// ```
650653
/// let _ = "early doctests should not go boom";
651654
/// ```
@@ -771,6 +774,13 @@ pub fn block_comments() {}
771774
[`block_comments`] tests these without indentation
772775
*/
773776
pub fn block_comments2() {}
777+
778+
//- /outline_module.rs
779+
//! This is an outline module whose purpose is to test that its inline attribute injection does not
780+
//! spill into its parent.
781+
//! ```
782+
//! fn test() {}
783+
//! ```
774784
"#
775785
.trim(),
776786
expect_file!["./test_data/highlight_doctest.html"],

0 commit comments

Comments
 (0)