aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-11-12 11:09:44 +0000
committerGitHub <[email protected]>2020-11-12 11:09:44 +0000
commit99fa139beab0c03583c676554c3d807525f602af (patch)
treea2df8b9f6d26611283120faccb387723b1a0c944
parent802665873ddfa3f6a2ba6e97a3d9078f2e5cfa90 (diff)
parenta27186636d030c847193ab21c59a1857a1e93785 (diff)
Merge #6534
6534: Fix attachment of inner doc comments r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r--crates/syntax/src/ast.rs19
-rw-r--r--crates/syntax/src/ast/token_ext.rs51
-rw-r--r--crates/syntax/src/parsing/text_tree_sink.rs27
-rw-r--r--crates/syntax/test_data/parser/ok/0037_mod.rast6
4 files changed, 56 insertions, 47 deletions
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
index 8a0e3d27b..7844f9ed6 100644
--- a/crates/syntax/src/ast.rs
+++ b/crates/syntax/src/ast.rs
@@ -115,10 +115,10 @@ fn test_doc_comment_none() {
115} 115}
116 116
117#[test] 117#[test]
118fn test_doc_comment_of_items() { 118fn test_outer_doc_comment_of_items() {
119 let file = SourceFile::parse( 119 let file = SourceFile::parse(
120 r#" 120 r#"
121 //! doc 121 /// doc
122 // non-doc 122 // non-doc
123 mod foo {} 123 mod foo {}
124 "#, 124 "#,
@@ -130,6 +130,21 @@ fn test_doc_comment_of_items() {
130} 130}
131 131
132#[test] 132#[test]
133fn test_inner_doc_comment_of_items() {
134 let file = SourceFile::parse(
135 r#"
136 //! doc
137 // non-doc
138 mod foo {}
139 "#,
140 )
141 .ok()
142 .unwrap();
143 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
144 assert!(module.doc_comment_text().is_none());
145}
146
147#[test]
133fn test_doc_comment_of_statics() { 148fn test_doc_comment_of_statics() {
134 let file = SourceFile::parse( 149 let file = SourceFile::parse(
135 r#" 150 r#"
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index e4e512f2e..2661c753e 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -14,16 +14,15 @@ use crate::{
14 14
15impl ast::Comment { 15impl ast::Comment {
16 pub fn kind(&self) -> CommentKind { 16 pub fn kind(&self) -> CommentKind {
17 kind_by_prefix(self.text()) 17 CommentKind::from_text(self.text())
18 } 18 }
19 19
20 pub fn prefix(&self) -> &'static str { 20 pub fn prefix(&self) -> &'static str {
21 for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() { 21 let &(prefix, _kind) = CommentKind::BY_PREFIX
22 if *k == self.kind() && self.text().starts_with(prefix) { 22 .iter()
23 return prefix; 23 .find(|&(prefix, kind)| self.kind() == *kind && self.text().starts_with(prefix))
24 } 24 .unwrap();
25 } 25 prefix
26 unreachable!()
27 } 26 }
28} 27}
29 28
@@ -55,29 +54,25 @@ pub enum CommentPlacement {
55 Outer, 54 Outer,
56} 55}
57 56
58const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = { 57impl CommentKind {
59 use {CommentPlacement::*, CommentShape::*}; 58 const BY_PREFIX: [(&'static str, CommentKind); 8] = [
60 &[ 59 ("/**/", CommentKind { shape: CommentShape::Block, doc: None }),
61 ("////", CommentKind { shape: Line, doc: None }), 60 ("////", CommentKind { shape: CommentShape::Line, doc: None }),
62 ("///", CommentKind { shape: Line, doc: Some(Outer) }), 61 ("///", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Outer) }),
63 ("//!", CommentKind { shape: Line, doc: Some(Inner) }), 62 ("//!", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Inner) }),
64 ("/**", CommentKind { shape: Block, doc: Some(Outer) }), 63 ("/**", CommentKind { shape: CommentShape::Block, doc: Some(CommentPlacement::Outer) }),
65 ("/*!", CommentKind { shape: Block, doc: Some(Inner) }), 64 ("/*!", CommentKind { shape: CommentShape::Block, doc: Some(CommentPlacement::Inner) }),
66 ("//", CommentKind { shape: Line, doc: None }), 65 ("//", CommentKind { shape: CommentShape::Line, doc: None }),
67 ("/*", CommentKind { shape: Block, doc: None }), 66 ("/*", CommentKind { shape: CommentShape::Block, doc: None }),
68 ] 67 ];
69};
70 68
71fn kind_by_prefix(text: &str) -> CommentKind { 69 pub(crate) fn from_text(text: &str) -> CommentKind {
72 if text == "/**/" { 70 let &(_prefix, kind) = CommentKind::BY_PREFIX
73 return CommentKind { shape: CommentShape::Block, doc: None }; 71 .iter()
74 } 72 .find(|&(prefix, _kind)| text.starts_with(prefix))
75 for (prefix, kind) in COMMENT_PREFIX_TO_KIND.iter() { 73 .unwrap();
76 if text.starts_with(prefix) { 74 kind
77 return *kind;
78 }
79 } 75 }
80 panic!("bad comment text: {:?}", text)
81} 76}
82 77
83impl ast::Whitespace { 78impl ast::Whitespace {
diff --git a/crates/syntax/src/parsing/text_tree_sink.rs b/crates/syntax/src/parsing/text_tree_sink.rs
index c1b5f246d..997bc5d28 100644
--- a/crates/syntax/src/parsing/text_tree_sink.rs
+++ b/crates/syntax/src/parsing/text_tree_sink.rs
@@ -5,6 +5,7 @@ use std::mem;
5use parser::{ParseError, TreeSink}; 5use parser::{ParseError, TreeSink};
6 6
7use crate::{ 7use crate::{
8 ast,
8 parsing::Token, 9 parsing::Token,
9 syntax_node::GreenNode, 10 syntax_node::GreenNode,
10 SmolStr, SyntaxError, 11 SmolStr, SyntaxError,
@@ -153,24 +154,22 @@ fn n_attached_trivias<'a>(
153 154
154 while let Some((i, (kind, text))) = trivias.next() { 155 while let Some((i, (kind, text))) = trivias.next() {
155 match kind { 156 match kind {
156 WHITESPACE => { 157 WHITESPACE if text.contains("\n\n") => {
157 if text.contains("\n\n") { 158 // we check whether the next token is a doc-comment
158 // we check whether the next token is a doc-comment 159 // and skip the whitespace in this case
159 // and skip the whitespace in this case 160 if let Some((COMMENT, peek_text)) = trivias.peek().map(|(_, pair)| pair) {
160 if let Some((peek_kind, peek_text)) = 161 let comment_kind = ast::CommentKind::from_text(peek_text);
161 trivias.peek().map(|(_, pair)| pair) 162 if comment_kind.doc == Some(ast::CommentPlacement::Outer) {
162 { 163 continue;
163 if *peek_kind == COMMENT
164 && peek_text.starts_with("///")
165 && !peek_text.starts_with("////")
166 {
167 continue;
168 }
169 } 164 }
170 break;
171 } 165 }
166 break;
172 } 167 }
173 COMMENT => { 168 COMMENT => {
169 let comment_kind = ast::CommentKind::from_text(text);
170 if comment_kind.doc == Some(ast::CommentPlacement::Inner) {
171 break;
172 }
174 res = i + 1; 173 res = i + 1;
175 } 174 }
176 _ => (), 175 _ => (),
diff --git a/crates/syntax/test_data/parser/ok/0037_mod.rast b/crates/syntax/test_data/parser/ok/0037_mod.rast
index 1d5d94bde..35577272e 100644
--- a/crates/syntax/test_data/parser/ok/0037_mod.rast
+++ b/crates/syntax/test_data/parser/ok/0037_mod.rast
@@ -1,9 +1,9 @@
1[email protected] 1[email protected]
2 [email protected] "// https://github.com ..." 2 [email protected] "// https://github.com ..."
3 [email protected] "\n\n" 3 [email protected] "\n\n"
4 MODULE@62..93 4 COMMENT@62..70 "//! docs"
5 COMMENT@62..70 "//! docs" 5 WHITESPACE@70..71 "\n"
6 WHITESPACE@70..71 "\n" 6 MODULE@71..93
7 [email protected] "// non-docs" 7 [email protected] "// non-docs"
8 [email protected] "\n" 8 [email protected] "\n"
9 [email protected] "mod" 9 [email protected] "mod"