@@ -109,6 +109,7 @@ class JavadocVisitor
109109 Diagnostics& diags_;
110110 doc::List<doc::Param> params_;
111111 doc::Block* block_ = nullptr ;
112+ doc::Text* last_child_ = nullptr ;
112113 std::size_t htmlTagNesting_ = 0 ;
113114 Comment::child_iterator it_;
114115 Comment::child_iterator end_;
@@ -130,11 +131,13 @@ class JavadocVisitor
130131 , prev_ (visitor.block_ )
131132 {
132133 visitor_.block_ = blk;
134+ visitor_.last_child_ = nullptr ;
133135 }
134136
135137 ~BlockScope ()
136138 {
137139 visitor_.block_ = prev_;
140+ visitor_.last_child_ = nullptr ;
138141 }
139142 };
140143
@@ -169,6 +172,39 @@ class JavadocVisitor
169172
170173 // helpers
171174 bool goodArgCount (std::size_t n, InlineCommandComment const & C);
175+
176+
177+ template <std::derived_from<doc::Text> TextTy, typename ... Args>
178+ void emplaceText (bool end_with_nl, Args&&... args)
179+ {
180+ TextTy elem (std::forward<Args>(args)...);
181+ bool can_merge = false ;
182+
183+ if (last_child_ && last_child_->kind == elem.kind )
184+ {
185+ if constexpr (TextTy::static_kind == doc::Kind::text)
186+ can_merge = true ;
187+
188+ if constexpr (TextTy::static_kind == doc::Kind::styled)
189+ can_merge = static_cast <doc::Styled*>(
190+ last_child_)->style == elem.style ;
191+ }
192+
193+ if (! can_merge)
194+ {
195+ auto new_text = std::make_unique<TextTy>(std::move (elem));
196+ last_child_ = new_text.get ();
197+ block_->children .emplace_back (std::move (new_text));
198+
199+ }
200+ else
201+ {
202+ last_child_->string .append (elem.string );
203+ }
204+
205+ if (end_with_nl)
206+ last_child_ = nullptr ;
207+ }
172208};
173209
174210// ------------------------------------------------
@@ -245,7 +281,6 @@ visitTextComment(
245281 TextComment const * C)
246282{
247283 llvm::StringRef s = C->getText ();
248-
249284 // If this is the first text comment in the
250285 // paragraph then remove all the leading space.
251286 // Otherwise, just remove the trailing space.
@@ -256,7 +291,9 @@ visitTextComment(
256291
257292 // Only insert non-empty text nodes
258293 if (! s.empty ())
259- block_->emplace_back (doc::Text (ensureUTF8 (s.str ())));
294+ emplaceText<doc::Text>(
295+ C->hasTrailingNewline (),
296+ ensureUTF8 (s.str ()));
260297}
261298
262299void
@@ -265,6 +302,7 @@ visitHTMLStartTagComment(
265302 HTMLStartTagComment const * C)
266303{
267304 MRDOCS_ASSERT (C->child_begin () == C->child_end ());
305+ last_child_ = nullptr ;
268306 auto const tag = C->getTagName ();
269307 if (tag == " a" )
270308 {
@@ -310,9 +348,10 @@ visitHTMLStartTagComment(
310348 break ;
311349 }
312350 }
313- block_->emplace_back (doc::Link (
351+ emplaceText<doc::Link>(
352+ C->hasTrailingNewline (),
314353 ensureUTF8 (std::move (text)),
315- ensureUTF8 (std::move (href)))) ;
354+ ensureUTF8 (std::move (href)));
316355
317356 it_ += 2 ; // bit of a hack
318357 }
@@ -408,8 +447,10 @@ visitInlineCommandComment(
408447 if (! goodArgCount (1 , *C))
409448 return ;
410449 auto style = doc::Style::italic;
411- block_->emplace_back (doc::Styled (
412- C->getArgText (0 ).str (), style));
450+ emplaceText<doc::Styled>(
451+ C->hasTrailingNewline (),
452+ C->getArgText (0 ).str (),
453+ style);
413454 return ;
414455 }
415456
@@ -422,8 +463,10 @@ visitInlineCommandComment(
422463 return ;
423464 // the referenced symbol will be resolved during
424465 // the finalization step once all symbol are extracted
425- block_->emplace_back (doc::Copied (
426- C->getArgText (0 ).str (), convertCopydoc (ID)));
466+ emplaceText<doc::Copied>(
467+ C->hasTrailingNewline (),
468+ C->getArgText (0 ).str (),
469+ convertCopydoc (ID));
427470 return ;
428471 }
429472 case CommandTraits::KCI_ref:
@@ -432,8 +475,9 @@ visitInlineCommandComment(
432475 return ;
433476 // the referenced symbol will be resolved during
434477 // the finalization step once all symbol are extracted
435- block_->emplace_back (doc::Reference (
436- C->getArgText (0 ).str ()));
478+ emplaceText<doc::Reference>(
479+ C->hasTrailingNewline (),
480+ C->getArgText (0 ).str ());
437481 return ;
438482 }
439483
@@ -455,9 +499,14 @@ visitInlineCommandComment(
455499
456500 doc::Style style = convertStyle (C->getRenderKind ());
457501 if (style != doc::Style::none)
458- block_->emplace_back (doc::Styled (std::move (s), style));
502+ emplaceText<doc::Styled>(
503+ C->hasTrailingNewline (),
504+ std::move (s),
505+ style);
459506 else
460- block_->emplace_back (doc::Text (std::move (s)));
507+ emplaceText<doc::Text>(
508+ C->hasTrailingNewline (),
509+ std::move (s));
461510}
462511
463512// ------------------------------------------------
@@ -892,7 +941,7 @@ JavadocVisitor::
892941visitVerbatimBlockLineComment (
893942 VerbatimBlockLineComment const * C)
894943{
895- block_-> emplace_back ( doc::Text ( C->getText ().str () ));
944+ emplaceText< doc::Text>( true , C->getText ().str ());
896945}
897946
898947// ------------------------------------------------
0 commit comments