skia2/tools/bookmaker/definition.h
Cary Clark fd32e724d6 bookmaker error handling
Bookmaker will generate instructions on how to
fix detected errors in a few cases:
- if class function is missing description
- if global function is missing description
- if function parameters don't match doxygen
- if function parameters don't match bmh

(The last case above won't happen if bmh #Method
uses #Populate to retrieve parameter descriptions
from the include.)

Adding this revealed that globals weren't always
accounted for in bookmaker's cross-check; fix
that as well.

TBR=reed@google.com
Docs-Preview: https://skia.org/?cl=171224
Bug: skia:
Change-Id: Ic1b41d4722954fa8a42685a8fe7266b8a860c362
Reviewed-on: https://skia-review.googlesource.com/c/171224
Reviewed-by: Cary Clark <caryclark@skia.org>
Commit-Queue: Cary Clark <caryclark@skia.org>
Auto-Submit: Cary Clark <caryclark@skia.org>
2018-11-16 20:30:18 +00:00

328 lines
9.3 KiB
C++

/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef definition_DEFINED
#define definition_DEFINED
#include "textParser.h"
class RootDefinition;
class TextParser;
class Definition : public NonAssignable {
public:
enum Type {
kNone,
kWord,
kMark,
kKeyWord,
kBracket,
kPunctuation,
kFileType,
};
enum class MethodType {
kNone,
kConstructor,
kDestructor,
kOperator,
};
enum class Operator {
kUnknown,
kAdd,
kAddTo,
kArray,
kCast,
kCopy,
kDelete,
kDereference,
kEqual,
kMinus,
kMove,
kMultiply,
kMultiplyBy,
kNew,
kNotEqual,
kSubtract,
kSubtractFrom,
};
enum class Format {
kIncludeReturn,
kOmitReturn,
};
enum class Details {
kNone,
kSoonToBe_Deprecated,
kTestingOnly_Experiment,
kDoNotUse_Experiment,
kNotReady_Experiment,
};
enum class DetailsType {
kPhrase,
kSentence,
};
Definition() {}
Definition(const char* start, const char* end, int line, Definition* parent, char mc)
: fStart(start)
, fContentStart(start)
, fContentEnd(end)
, fParent(parent)
, fLineCount(line)
, fType(Type::kWord)
, fMC(mc) {
if (parent) {
SkASSERT(parent->fFileName.length() > 0);
fFileName = parent->fFileName;
}
this->setParentIndex();
}
Definition(MarkType markType, const char* start, int line, Definition* parent, char mc)
: Definition(markType, start, nullptr, line, parent, mc) {
}
Definition(MarkType markType, const char* start, const char* end, int line, Definition* parent, char mc)
: Definition(start, end, line, parent, mc) {
fMarkType = markType;
fType = Type::kMark;
}
Definition(Bracket bracket, const char* start, int lineCount, Definition* parent, char mc)
: Definition(start, nullptr, lineCount, parent, mc) {
fBracket = bracket;
fType = Type::kBracket;
}
Definition(KeyWord keyWord, const char* start, const char* end, int lineCount,
Definition* parent, char mc)
: Definition(start, end, lineCount, parent, mc) {
fKeyWord = keyWord;
fType = Type::kKeyWord;
}
Definition(Punctuation punctuation, const char* start, int lineCount, Definition* parent, char mc)
: Definition(start, nullptr, lineCount, parent, mc) {
fPunctuation = punctuation;
fType = Type::kPunctuation;
}
virtual ~Definition() {}
virtual RootDefinition* asRoot() { SkASSERT(0); return nullptr; }
bool boilerplateIfDef();
bool boilerplateEndIf() {
return true;
}
bool checkMethod() const;
bool crossCheck2(const Definition& includeToken) const;
bool crossCheck(const Definition& includeToken) const;
bool crossCheckInside(const char* start, const char* end, const Definition& includeToken) const;
Definition* csParent() {
Definition* test = fParent;
while (test) {
if (MarkType::kStruct == test->fMarkType || MarkType::kClass == test->fMarkType) {
return test;
}
test = test->fParent;
}
return nullptr;
}
string fiddleName() const;
string fileName() const;
const Definition* findClone(string match) const;
string formatFunction(Format format) const;
const Definition* hasChild(MarkType markType) const;
bool hasMatch(string name) const;
Definition* hasParam(string ref);
bool isClone() const { return fClone; }
const Definition* iRootParent() const {
const Definition* test = fParent;
while (test) {
if (KeyWord::kClass == test->fKeyWord || KeyWord::kStruct == test->fKeyWord) {
return test;
}
test = test->fParent;
}
return nullptr;
}
virtual bool isRoot() const { return false; }
bool isStructOrClass() const;
int length() const {
return (int) (fContentEnd - fContentStart);
}
const char* methodEnd() const;
bool methodHasReturn(string name, TextParser* methodParser) const;
string methodName() const;
bool nextMethodParam(TextParser* methodParser, const char** nextEndPtr,
string* paramName) const;
static string NormalizedName(string name);
bool paramsMatch(string fullRef, string name) const;
bool parseOperator(size_t doubleColons, string& result);
string printableName() const {
string result(fName);
std::replace(result.begin(), result.end(), '_', ' ');
return result;
}
template <typename T> T reportError(const char* errorStr) const {
TextParser tp(this);
tp.reportError(errorStr);
return T();
}
virtual RootDefinition* rootParent() { SkASSERT(0); return nullptr; }
virtual const RootDefinition* rootParent() const { SkASSERT(0); return nullptr; }
void setCanonicalFiddle();
void setParentIndex() {
fParentIndex = fParent ? (int) fParent->fTokens.size() : -1;
}
static bool SkipImplementationWords(TextParser& inc);
string simpleName() {
size_t doubleColon = fName.rfind("::");
return string::npos == doubleColon ? fName : fName.substr(doubleColon + 2);
}
const Definition* subtopicParent() const {
Definition* test = fParent;
while (test) {
if (MarkType::kTopic == test->fMarkType || MarkType::kSubtopic == test->fMarkType) {
return test;
}
test = test->fParent;
}
return nullptr;
}
const Definition* topicParent() const {
Definition* test = fParent;
while (test) {
if (MarkType::kTopic == test->fMarkType) {
return test;
}
test = test->fParent;
}
return nullptr;
}
void trimEnd();
string fText; // if text is constructed instead of in a file, it's put here
const char* fStart = nullptr; // .. in original text file, or the start of fText
const char* fContentStart; // start past optional markup name
string fName;
string fFiddle; // if its a constructor or operator, fiddle name goes here
string fCode; // suitable for autogeneration of #Code blocks in bmh
const char* fContentEnd = nullptr; // the end of the contained text
const char* fTerminator = nullptr; // the end of the markup, normally ##\n or \n
Definition* fParent = nullptr;
list<Definition> fTokens;
vector<Definition*> fChildren;
string fHash; // generated by fiddle
string fFileName;
mutable string fWrapper; // used by Example to wrap into proper function
size_t fLineCount = 0;
int fParentIndex = 0;
MarkType fMarkType = MarkType::kNone;
KeyWord fKeyWord = KeyWord::kNone;
Bracket fBracket = Bracket::kNone;
Punctuation fPunctuation = Punctuation::kNone;
MethodType fMethodType = MethodType::kNone;
Operator fOperator = Operator::kUnknown;
Type fType = Type::kNone;
char fMC = '#';
bool fClone = false;
bool fCloned = false;
bool fOperatorConst = false;
bool fPrivate = false;
Details fDetails = Details::kNone;
bool fMemberStart = false;
bool fAnonymous = false;
bool fUndocumented = false; // include symbol comment has deprecated, private, experimental
mutable bool fVisited = false;
};
class RootDefinition : public Definition {
public:
enum class AllowParens {
kNo,
kYes,
};
struct SubtopicContents {
SubtopicContents()
: fShowClones(false) {
}
vector<Definition*> fMembers;
bool fShowClones;
};
RootDefinition() {
}
RootDefinition(MarkType markType, const char* start, int line, Definition* parent, char mc)
: Definition(markType, start, line, parent, mc) {
if (MarkType::kSubtopic != markType && MarkType::kTopic != markType) {
if (parent) {
fNames.fName = parent->fName;
fNames.fParent = &parent->asRoot()->fNames;
}
}
}
RootDefinition(MarkType markType, const char* start, const char* end, int line,
Definition* parent, char mc) : Definition(markType, start, end, line, parent, mc) {
}
~RootDefinition() override {
for (auto& iter : fBranches) {
delete iter.second;
}
}
RootDefinition* asRoot() override { return this; }
void clearVisited();
bool dumpUnVisited();
Definition* find(string ref, AllowParens );
bool isRoot() const override { return true; }
SubtopicContents& populator(const char* key) {
return fPopulators[key];
}
RootDefinition* rootParent() override { return fRootParent; }
const RootDefinition* rootParent() const override { return fRootParent; }
void setRootParent(RootDefinition* rootParent) { fRootParent = rootParent; }
unordered_map<string, RootDefinition*> fBranches;
unordered_map<string, Definition> fLeaves;
unordered_map<string, SubtopicContents> fPopulators;
NameMap fNames;
private:
RootDefinition* fRootParent = nullptr;
};
#endif