Doxygen
Loading...
Searching...
No Matches
RequirementManager Class Reference

#include <src/requirement.h>

Classes

class  Private

Public Member Functions

void addRequirement (Entry *e)
void generatePage ()
void writeTagFile (TextStream &tagFile)
void addRequirementRefsForSymbol (const Definition *symbol)
const RequirementIntffind (const DString &reqId) const
void writeRef (OutputList &ol, const RequirementRef &ref)
bool hasRequirements () const
RequirementIntfList requirements () const
const PageDefrequirementsPage () const

Static Public Member Functions

static RequirementManagerinstance ()

Private Member Functions

 RequirementManager ()

Private Attributes

std::unique_ptr< Privatep

Detailed Description

Definition at line 79 of file requirement.h.

Constructor & Destructor Documentation

◆ RequirementManager()

RequirementManager::RequirementManager ( )
private

Definition at line 107 of file requirement.cpp.

107 : p(std::make_unique<Private>())
108{
109}
std::unique_ptr< Private > p
Definition requirement.h:95

References p.

Referenced by instance().

Member Function Documentation

◆ addRequirement()

void RequirementManager::addRequirement ( Entry * e)

Definition at line 116 of file requirement.cpp.

117{
118 DString tagFile;
119 DString extPage;
120 if (!Config_getBool(GENERATE_REQUIREMENTS)) // still record the requirement, so we can refer to it.
121 {
122 if (e->tagInfo())
123 {
124 //printf("External requirement %s title=%s fileName=%s tagName=%s anchor=%s\n",
125 // qPrint(e->name),qPrint(e->type),qPrint(e->tagInfo()->fileName),qPrint(e->tagInfo()->tagName),qPrint(e->tagInfo()->anchor));
126 tagFile = e->tagInfo()->tagName;
127 extPage = e->tagInfo()->fileName;
128 // register requirement id as anchor; for non-external links this is
129 // done in commentscan.l in the comment block containing the @requirement command
131 }
132 p->requirements.add(e->name, e->fileName, e->startLine, e->type, e->doc, tagFile, extPage);
133 }
134 else
135 {
136 if (p->reqPageDef==nullptr)
137 {
138 p->reqPageDef = addRelatedPage("requirements", // name
139 theTranslator->trRequirements(), // ptitle
140 DString(), // doc
141 "requirements", // fileName
142 1, // docLine
143 1 // startLine
144 );
145 }
146 //printf("requirement ID=%s title='%s' file=%s line=%d brief='%s' doc='%s'\n",
147 // qPrint(e->name), qPrint(e->type), qPrint(e->fileName), e->startLine, qPrint(e->brief), qPrint(e->doc));
148 DString title = parseCommentAsText(p->reqPageDef,nullptr,e->type,e->fileName,e->startLine);
149 DString doc = e->doc;
150 if (e->tagInfo())
151 {
152 //printf("External requirement %s title=%s fileName=%s tagName=%s anchor=%s\n",
153 // qPrint(e->name),qPrint(e->type),qPrint(e->tagInfo()->fileName),qPrint(e->tagInfo()->tagName),qPrint(e->tagInfo()->anchor));
154 tagFile = e->tagInfo()->tagName;
155 extPage = e->tagInfo()->fileName;
156 // register requirement id as anchor; for non-external links this is
157 // done in commentscan.l in the comment block containing the @requirement command
158 SectionManager::instance().add(e->name,"requirements",1,title,SectionType::Anchor,1);
159 }
160 if (!e->brief.empty())
161 {
162 doc.prepend(e->brief+"\n<p>");
163 }
164 p->requirements.add(e->name, e->fileName, e->startLine, title, doc, tagFile, extPage);
165
166 p->reqPageDef->setRefItems(e->sli);
167 }
168}
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
DString & prepend(const char *s)
Definition dstring.h:515
const TagInfo * tagInfo() const
Definition entry.h:176
DString fileName
file this entry was extracted from
Definition entry.h:223
DString doc
documentation block (partly parsed)
Definition entry.h:200
DString brief
brief description (doc block)
Definition entry.h:203
int startLine
start line of entry in the source
Definition entry.h:224
DString type
member type
Definition entry.h:172
DString name
member name
Definition entry.h:173
RefItemVector sli
special lists (test/todo/bug/deprecated/..) this entry is in
Definition entry.h:226
SectionInfo * add(const SectionInfo &si)
Definition section.h:139
static SectionManager & instance()
returns a reference to the singleton
Definition section.h:179
static constexpr int Anchor
Definition section.h:40
static constexpr int Requirement
Definition section.h:42
DString tagName
Definition entry.h:103
DString fileName
Definition entry.h:104
virtual DString trRequirements()=0
#define Config_getBool(name)
Definition config.h:33
DString parseCommentAsText(const Definition *scope, const MemberDef *md, const DString &doc, const DString &fileName, int lineNr)
Translator * theTranslator
Definition language.cpp:76
PageDef * addRelatedPage(const DString &name, const DString &ptitle, const DString &doc, const DString &fileName, int docLine, int startLine, const RefItemVector &sli, GroupDef *gd, const TagInfo *tagInfo, bool xref, SrcLangExt lang)
Definition pagedef.cpp:524

References SectionManager::add(), addRelatedPage(), SectionType::Anchor, Entry::brief, Config_getBool, Entry::doc, DString::empty(), Entry::fileName, TagInfo::fileName, SectionManager::instance(), Entry::name, p, parseCommentAsText(), DString::prepend(), SectionType::Requirement, Entry::sli, Entry::startLine, Entry::tagInfo(), TagInfo::tagName, theTranslator, Translator::trRequirements(), and Entry::type.

Referenced by buildRequirementsList().

◆ addRequirementRefsForSymbol()

void RequirementManager::addRequirementRefsForSymbol ( const Definition * symbol)

Definition at line 337 of file requirement.cpp.

338{
339 for (const auto &ref : symbol->requirementReferences())
340 {
341 Requirement *req = p->requirements.find(ref.reqId());
342 if (req)
343 {
344 //printf("adding reference from %s to requirement %s\n",qPrint(symbol->name()),qPrint(ref.reqId()));
345 switch (ref.type())
346 {
347 case RequirementRefType::Satisfies: req->addSatisfiedBy(symbol); break;
348 case RequirementRefType::Verifies: req->addVerifiedBy(symbol); break;
349 }
350 }
351 else
352 {
353 warn(ref.file(),ref.line(),"Reference to unknown requirement '{}' found",ref.reqId());
354 // invalid reference (file, and line needed)
355 }
356 }
357}
virtual const RequirementRefs & requirementReferences() const =0
#define warn(file, line, fmt,...)
Definition message.h:97
void addSatisfiedBy(const Definition *def)
void addVerifiedBy(const Definition *def)

References Requirement::addSatisfiedBy(), Requirement::addVerifiedBy(), p, Definition::requirementReferences(), Satisfies, Verifies, and warn.

Referenced by ClassDefImpl::addRequirementReferences(), ConceptDefImpl::addRequirementReferences(), DirDefImpl::addRequirementReferences(), FileDefImpl::addRequirementReferences(), GroupDefImpl::addRequirementReferences(), MemberDefImpl::addRequirementReferences(), ModuleDefImpl::addRequirementReferences(), NamespaceDefImpl::addRequirementReferences(), and PageDefImpl::addRequirementReferences().

◆ find()

const RequirementIntf * RequirementManager::find ( const DString & reqId) const

Definition at line 332 of file requirement.cpp.

333{
334 return p->requirements.find(reqId);
335}

References p.

Referenced by generatePage(), and writeRef().

◆ generatePage()

void RequirementManager::generatePage ( )

Definition at line 185 of file requirement.cpp.

186{
187 AUTO_TRACE("#requirements={}",p->requirements.size());
188 if (!Config_getBool(GENERATE_REQUIREMENTS) || p->requirements.empty()) return;
189 std::vector<const SectionInfo*> anchors;
190 std::stable_sort(p->requirements.begin(),p->requirements.end(),
191 [](const auto &left,const auto &right) { return dstricmp(left->id(),right->id()) < 0; });
192 DString doc = "<table class=\"doxtable reqlist\">";
193 doc.reserve(10*1024); // prevent too many reallocs
194 doc += "<tr><th>";
196 doc += "</th><th>";
197 doc += "</th>";
198 using RequirementPtrVector = std::vector<const Requirement*>;
199 RequirementPtrVector missingSatisfiedRef, missingVerifiedRef;
200 for (const auto &req : p->requirements) // TODO: filter out external references?
201 {
202 if (const SectionInfo *si = SectionManager::instance().find(req->id()); si!=nullptr)
203 {
204 anchors.push_back(si);
205 }
206 doc += "<tr><td valign=\"top\">";
207 doc += " \\ifile \""+req->file()+"\" \\iline "+DString().setNum(req->line())+" ";
208 doc += "\\anchor ";
209 doc += req->id();
210 doc += " ";
211 doc += "<span class=\"req_id\">";
212 if (DString tagFile = req->getTagFile(); !tagFile.empty())
213 {
214 //printf("tagFile=%s extPage=%s\n",qPrint(tagFile),qPrint(req->getExtPage()));
215 doc += "<a href=\"";
216 doc += createHtmlUrl(DString(),tagFile,false,req->getExtPage(),req->id());
217 doc +="\">"+req->id()+"</a>";
218 }
219 else
220 {
221 doc += req->id();
222 }
223 doc += "</span> ";
224 doc += "</td><td>";
225 doc += "<div class=\"req_title\">"+req->title()+"</div>";
226 doc += "<p/><div class=\"req_docs\">";
227 doc += req->doc();
228 req->sortReferences();
229 auto symToString = [](const Definition *sym)
230 {
231 DString symName = sym->qualifiedName();
232 if (sym->definitionType()==Definition::TypeMember)
233 {
234 const MemberDef *md = toMemberDef(sym);
235 if (!md->isObjCMethod() && md->isFunctionOrSignalSlot()) symName += "()";
236 }
237 return symName;
238 };
239 int numSatisfiedBy = static_cast<int>(req->satisfiedBy().size());
240 if (numSatisfiedBy>0)
241 {
242 doc += "<p><div class=\"satisfiedby\">";
244 writeMarkerList(theTranslator->trWriteList(numSatisfiedBy).str(),
245 numSatisfiedBy,
246 [&symToString, &refs = req->satisfiedBy()](size_t entryIndex) {
247 return symToString(refs[entryIndex]);
248 }));
249 doc += "</div></p>";
250 }
251 else
252 {
253 missingSatisfiedRef.push_back(req.get());
254 }
255 int numVerifiedBy = static_cast<int>(req->verifiedBy().size());
256 if (numVerifiedBy>0)
257 {
258 doc += "<p><div class=\"verifiedby\">";
261 numVerifiedBy,
262 [&symToString, &refs = req->verifiedBy()](size_t entryIndex) {
263 return symToString(refs[entryIndex]);
264 }));
265 doc += "</div></p>";
266 }
267 else
268 {
269 missingVerifiedRef.push_back(req.get());
270 }
271 doc += "\n</div></td></tr>\n";
272 }
273 doc += "</table>\n";
274
275 //------------
276 doc += " \\ifile \"requirements\" \\iline 1\n";
277
278 auto writeMissingRef = [&doc,&anchors](const RequirementPtrVector &reqs,
279 const char *label,const DString &section,const DString &text)
280 {
281 if (!reqs.empty())
282 {
283 SectionManager &sm = SectionManager::instance();
284 const SectionInfo *si = sm.add(DString("missing_")+label,"requirements",1,section,SectionType::Section,1);
285 anchors.push_back(si);
286 doc += "\\htmlonly <div class=\"missing_";
287 doc += label;
288 doc += "\">\\endhtmlonly\n";
289 doc += DString("@section missing_")+label+" "+section+"\n"+text+"\n";
290 doc += "\\htmlonly </div>\\endhtmlonly\n";
291 }
292 };
293
294 // write list of requirements that do not have a satisfies relation
295 auto traceInfo = Config_getEnum(REQ_TRACEABILITY_INFO);
296 int numMissingSatisfied = static_cast<int>(missingSatisfiedRef.size());
297 if ((traceInfo==REQ_TRACEABILITY_INFO_t::YES || traceInfo==REQ_TRACEABILITY_INFO_t::UNSATISFIED_ONLY) && numMissingSatisfied>0)
298 {
299 writeMissingRef(missingSatisfiedRef,
300 "satisfies",
302 theTranslator->trUnsatisfiedRequirementsText(numMissingSatisfied==1,
303 writeMarkerList(theTranslator->trWriteList(numMissingSatisfied).str(),
304 numMissingSatisfied,
305 [&missingSatisfiedRef](size_t entryIndex) {
306 DString id = missingSatisfiedRef[entryIndex]->id();
307 return "@ref "+id + " \""+id+"\"";
308 })));
309 }
310
311 // write list of requirements that do not have a verifies relation
312 int numMissingVerified = static_cast<int>(missingVerifiedRef.size());
313 if ((traceInfo==REQ_TRACEABILITY_INFO_t::YES || traceInfo==REQ_TRACEABILITY_INFO_t::UNVERIFIED_ONLY) && numMissingVerified>0)
314 {
315 writeMissingRef(missingVerifiedRef,
316 "verifies",
318 theTranslator->trUnverifiedRequirementsText(numMissingVerified==1,
319 writeMarkerList(theTranslator->trWriteList(numMissingVerified).str(),
320 numMissingVerified,
321 [&missingVerifiedRef](size_t entryIndex) {
322 DString id = missingVerifiedRef[entryIndex]->id();
323 return "@ref "+id + " \""+id+"\"";
324 })));
325 }
326
327 AUTO_TRACE_ADD("doc=[[\n{}\n]]\n",doc);
328 p->reqPageDef->setDocumentation(doc,"requirements",1,false);
329 p->reqPageDef->addSectionsToDefinition(anchors);
330}
DString & setNum(short n)
Definition dstring.h:552
void reserve(size_t size)
Reserve space for size bytes without changing the string contents.
Definition dstring.h:217
const std::string & str() const
Definition dstring.h:645
virtual bool isObjCMethod() const =0
virtual bool isFunctionOrSignalSlot() const =0
const RequirementIntf * find(const DString &reqId) const
static constexpr int Section
Definition section.h:33
virtual DString trUnsatisfiedRequirements()=0
virtual DString trRequirementID()=0
virtual DString trUnverifiedRequirementsText(bool singular, const DString &list)=0
virtual DString trSatisfiedBy(const DString &list)=0
virtual DString trUnsatisfiedRequirementsText(bool singular, const DString &list)=0
virtual DString trVerifiedBy(const DString &list)=0
virtual DString trWriteList(int numEntries)=0
virtual DString trUnverifiedRequirements()=0
#define Config_getEnum(name)
Definition config.h:35
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:54
#define AUTO_TRACE(...)
Definition docnode.cpp:53
MemberDef * toMemberDef(Definition *d)
DString createHtmlUrl(const DString &relPath, const DString &ref, bool isLocalFile, const DString &targetFileName, const DString &anchor)
Definition util.cpp:4502
void writeMarkerList(OutputList &ol, const std::string &markerText, size_t numMarkers, std::function< void(size_t)> replaceFunc)
Definition util.cpp:753

References SectionManager::add(), AUTO_TRACE, AUTO_TRACE_ADD, Config_getBool, Config_getEnum, createHtmlUrl(), DString::empty(), find(), SectionManager::instance(), MemberDef::isFunctionOrSignalSlot(), MemberDef::isObjCMethod(), p, DString::reserve(), SectionType::Section, DString::setNum(), DString::str(), theTranslator, toMemberDef(), Translator::trRequirementID(), Translator::trSatisfiedBy(), Translator::trUnsatisfiedRequirements(), Translator::trUnsatisfiedRequirementsText(), Translator::trUnverifiedRequirements(), Translator::trUnverifiedRequirementsText(), Translator::trVerifiedBy(), Translator::trWriteList(), Definition::TypeMember, and writeMarkerList().

Referenced by parseInput().

◆ hasRequirements()

bool RequirementManager::hasRequirements ( ) const

Definition at line 170 of file requirement.cpp.

171{
172 return !p->requirements.empty();
173}

References p.

◆ instance()

◆ requirements()

RequirementIntfList RequirementManager::requirements ( ) const

Definition at line 175 of file requirement.cpp.

176{
177 RequirementIntfList result;
178 for (const auto &req : p->requirements)
179 {
180 result.push_back(req.get());
181 }
182 return result;
183}
std::vector< const RequirementIntf * > RequirementIntfList
Definition requirement.h:77

References p.

Referenced by generateXMLForRequirements().

◆ requirementsPage()

const PageDef * RequirementManager::requirementsPage ( ) const

Definition at line 111 of file requirement.cpp.

112{
113 return p->reqPageDef;
114}

References p.

Referenced by generateXMLForRequirement().

◆ writeRef()

void RequirementManager::writeRef ( OutputList & ol,
const RequirementRef & ref )

Definition at line 360 of file requirement.cpp.

361{
362 if (!Config_getBool(GENERATE_REQUIREMENTS)) return;
363 if (const RequirementIntf *req = RequirementManager::instance().find(ref.reqId()); req!=nullptr)
364 {
365 DString title = ref.reqId();
366 if (!ref.title().empty())
367 {
368 title +=" (";
369 title += parseCommentAsText(p->reqPageDef,nullptr,ref.title(),ref.file(),ref.line());
370 title +=")";
371 }
372 else if (!req->title().empty())
373 {
374 title += " (";
375 title += req->title();
376 title += ")";
377 }
378 else
379 {
380 title = ref.reqId();
381 }
382 ol.writeObjectLink(DString(),req->getOutputFileBase(),ref.reqId(),title);
383 }
384 else
385 {
386 ol.docify(ref.reqId());
387 }
388}
void writeObjectLink(const DString &ref, const DString &file, const DString &anchor, const DString &name)
Definition outputlist.h:435
void docify(const DString &s)
Definition outputlist.h:433
static RequirementManager & instance()
DString title() const
Definition requirement.h:43
DString reqId() const
Definition requirement.h:42
DString file() const
Definition requirement.h:44
int line() const
Definition requirement.h:45

References Config_getBool, OutputList::docify(), DString::empty(), RequirementRef::file(), find(), instance(), RequirementRef::line(), p, parseCommentAsText(), RequirementRef::reqId(), RequirementRef::title(), and OutputList::writeObjectLink().

◆ writeTagFile()

void RequirementManager::writeTagFile ( TextStream & tagFile)

Definition at line 390 of file requirement.cpp.

391{
392 if (!Config_getBool(GENERATE_REQUIREMENTS)) return;
393 if (!p->requirements.empty())
394 {
395 for (const auto &req : p->requirements)
396 {
397 tagFile << " <compound kind=\"requirement\">\n";
398 tagFile << " <id>" << req->id() << "</id>\n";
399 tagFile << " <title>" << convertToXML(req->title()) << "</title>\n";
400 DString fn = req->getOutputFileBase();
402 tagFile << " <filename>" << fn << "</filename>\n";
403 tagFile << " </compound>\n";
404 }
405 }
406}
void addHtmlExtensionIfMissing(DString &fName)
Definition util.cpp:3931
DString convertToXML(const DString &s, bool keepEntities, const bool citeEntry)
Definition util.cpp:3232

References addHtmlExtensionIfMissing(), Config_getBool, convertToXML(), and p.

Referenced by writeTagFile().

Member Data Documentation

◆ p


The documentation for this class was generated from the following files: