| 325 | } |
| 326 | |
| 327 | void CommentHandler::handleComment(Annotator &A, Generator& generator, clang::Sema &Sema, |
| 328 | const char *bufferStart, int commentStart, int len, |
| 329 | clang::SourceLocation searchLocBegin, clang::SourceLocation searchLocEnd, |
| 330 | clang::SourceLocation commentLoc) |
| 331 | { |
| 332 | llvm::StringRef rawString(bufferStart+commentStart, len); |
| 333 | |
| 334 | handleUrlsInComment(generator, rawString, commentStart); |
| 335 | |
| 336 | std::string attributes; |
| 337 | |
| 338 | if ((rawString.ltrim().startswith("/**") && !rawString.ltrim().startswith("/***")) |
| 339 | || rawString.ltrim().startswith("/*!") || rawString.ltrim().startswith("//!") |
| 340 | || (rawString.ltrim().startswith("///") && !rawString.ltrim().startswith("////"))) |
| 341 | #if CLANG_VERSION_MAJOR==3 && CLANG_VERSION_MINOR<=4 |
| 342 | if (rawString.find("deprecated") == rawString.npos) // workaround crash in comments::Sema::checkDeprecatedCommand |
| 343 | #endif |
| 344 | { |
| 345 | attributes = "class=\"doc\""; |
| 346 | |
| 347 | clang::Preprocessor &PP = Sema.getPreprocessor(); |
| 348 | clang::comments::CommandTraits traits(PP.getPreprocessorAllocator(), clang::CommentOptions()); |
| 349 | traits.registerBlockCommand("value"); // enum value |
| 350 | #if CLANG_VERSION_MAJOR==3 && CLANG_VERSION_MINOR<=4 |
| 351 | traits.registerBlockCommand("deprecated"); // avoid typo correction leading to crash. |
| 352 | #endif |
| 353 | clang::comments::Lexer lexer(PP.getPreprocessorAllocator(), PP.getDiagnostics(), traits, |
| 354 | commentLoc, bufferStart + commentStart, bufferStart + commentStart + len); |
| 355 | clang::comments::Sema sema(PP.getPreprocessorAllocator(), PP.getSourceManager(), PP.getDiagnostics(), traits, &PP); |
| 356 | clang::comments::Parser parser(lexer, sema, PP.getPreprocessorAllocator(), PP.getSourceManager(), |
| 357 | PP.getDiagnostics(), traits); |
| 358 | auto fullComment = parser.parseFullComment(); |
| 359 | CommentVisitor visitor{A, generator, traits, Sema}; |
| 360 | visitor.visit(fullComment); |
| 361 | if (!visitor.DeclRef.empty()) { |
| 362 | for (auto &p : visitor.SubDocs) |
| 363 | docs.insert(std::move(p)); |
| 364 | docs.insert({std::move(visitor.DeclRef), { rawString.str() , commentLoc }}); |
| 365 | generator.addTag("i", attributes, commentStart, len); |
| 366 | return; |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | |
| 371 | // Try to find a matching declaration |
| 372 | const auto &dof = decl_offsets; |
| 373 | //is there one and one single decl in that range. |
| 374 | auto it_before = dof.lower_bound(searchLocBegin); |
| 375 | auto it_after = dof.upper_bound(searchLocEnd); |
| 376 | if (it_before != dof.end() && it_after != dof.begin() && it_before == (--it_after)) { |
| 377 | if (it_before->second.second) { |
| 378 | docs.insert({it_before->second.first, { rawString.str() , commentLoc }}); |
| 379 | } else { |
| 380 | attributes %= " data-doc=\"" % it_before->second.first % "\""; |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | generator.addTag("i", attributes, commentStart, len); |
no test coverage detected