Home | History | Annotate | Download | only in bookmaker
      1 /*
      2  * Copyright 2018 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef definition_DEFINED
      9 #define definition_DEFINED
     10 
     11 #include "textParser.h"
     12 
     13 class RootDefinition;
     14 class TextParser;
     15 
     16 class Definition : public NonAssignable {
     17 public:
     18     enum Type {
     19         kNone,
     20         kWord,
     21         kMark,
     22         kKeyWord,
     23         kBracket,
     24         kPunctuation,
     25         kFileType,
     26     };
     27 
     28     enum class MethodType {
     29         kNone,
     30         kConstructor,
     31         kDestructor,
     32         kOperator,
     33     };
     34 
     35     enum class Operator {
     36         kUnknown,
     37         kAdd,
     38         kAddTo,
     39         kArray,
     40         kCast,
     41         kCopy,
     42         kDelete,
     43         kDereference,
     44         kEqual,
     45         kMinus,
     46         kMove,
     47         kMultiply,
     48         kMultiplyBy,
     49         kNew,
     50         kNotEqual,
     51         kSubtract,
     52         kSubtractFrom,
     53     };
     54 
     55     enum class Format {
     56         kIncludeReturn,
     57         kOmitReturn,
     58     };
     59 
     60     enum class Details {
     61         kNone,
     62         kSoonToBe_Deprecated,
     63         kTestingOnly_Experiment,
     64         kDoNotUse_Experiment,
     65         kNotReady_Experiment,
     66     };
     67 
     68     enum class DetailsType {
     69         kPhrase,
     70         kSentence,
     71     };
     72 
     73     Definition() {}
     74 
     75     Definition(const char* start, const char* end, int line, Definition* parent, char mc)
     76         : fStart(start)
     77         , fContentStart(start)
     78         , fContentEnd(end)
     79         , fParent(parent)
     80         , fLineCount(line)
     81         , fType(Type::kWord)
     82         , fMC(mc) {
     83         if (parent) {
     84             SkASSERT(parent->fFileName.length() > 0);
     85             fFileName = parent->fFileName;
     86         }
     87         this->setParentIndex();
     88     }
     89 
     90     Definition(MarkType markType, const char* start, int line, Definition* parent, char mc)
     91         : Definition(markType, start, nullptr, line, parent, mc) {
     92     }
     93 
     94     Definition(MarkType markType, const char* start, const char* end, int line, Definition* parent, char mc)
     95         : Definition(start, end, line, parent, mc) {
     96         fMarkType = markType;
     97         fType = Type::kMark;
     98     }
     99 
    100     Definition(Bracket bracket, const char* start, int lineCount, Definition* parent, char mc)
    101         : Definition(start, nullptr, lineCount, parent, mc) {
    102         fBracket = bracket;
    103         fType = Type::kBracket;
    104     }
    105 
    106     Definition(KeyWord keyWord, const char* start, const char* end, int lineCount,
    107             Definition* parent, char mc)
    108         : Definition(start, end, lineCount, parent, mc) {
    109         fKeyWord = keyWord;
    110         fType = Type::kKeyWord;
    111     }
    112 
    113     Definition(Punctuation punctuation, const char* start, int lineCount, Definition* parent, char mc)
    114         : Definition(start, nullptr, lineCount, parent, mc) {
    115         fPunctuation = punctuation;
    116         fType = Type::kPunctuation;
    117     }
    118 
    119     virtual ~Definition() {}
    120 
    121     virtual RootDefinition* asRoot() { SkASSERT(0); return nullptr; }
    122     bool boilerplateIfDef();
    123 
    124     bool boilerplateEndIf() {
    125         return true;
    126     }
    127 
    128     bool checkMethod() const;
    129     bool crossCheck2(const Definition& includeToken) const;
    130     bool crossCheck(const Definition& includeToken) const;
    131     bool crossCheckInside(const char* start, const char* end, const Definition& includeToken) const;
    132 
    133     Definition* csParent() {
    134         Definition* test = fParent;
    135         while (test) {
    136             if (MarkType::kStruct == test->fMarkType || MarkType::kClass == test->fMarkType) {
    137                 return test;
    138             }
    139             test = test->fParent;
    140         }
    141         return nullptr;
    142     }
    143 
    144     string fiddleName() const;
    145     string fileName() const;
    146     const Definition* findClone(string match) const;
    147     string formatFunction(Format format) const;
    148     const Definition* hasChild(MarkType markType) const;
    149     bool hasMatch(string name) const;
    150     Definition* hasParam(string ref);
    151     bool isClone() const { return fClone; }
    152 
    153     const Definition* iRootParent() const {
    154         const Definition* test = fParent;
    155         while (test) {
    156             if (KeyWord::kClass == test->fKeyWord || KeyWord::kStruct == test->fKeyWord) {
    157                 return test;
    158             }
    159             test = test->fParent;
    160         }
    161         return nullptr;
    162     }
    163 
    164     virtual bool isRoot() const { return false; }
    165     bool isStructOrClass() const;
    166 
    167     int length() const {
    168         return (int) (fContentEnd - fContentStart);
    169     }
    170 
    171     const char* methodEnd() const;
    172     bool methodHasReturn(string name, TextParser* methodParser) const;
    173     string methodName() const;
    174     bool nextMethodParam(TextParser* methodParser, const char** nextEndPtr,
    175                          string* paramName) const;
    176     static string NormalizedName(string name);
    177     bool paramsMatch(string fullRef, string name) const;
    178     bool parseOperator(size_t doubleColons, string& result);
    179 
    180     string printableName() const {
    181         string result(fName);
    182         std::replace(result.begin(), result.end(), '_', ' ');
    183         return result;
    184     }
    185 
    186     template <typename T> T reportError(const char* errorStr) const {
    187         TextParser tp(this);
    188         tp.reportError(errorStr);
    189         return T();
    190     }
    191 
    192     virtual RootDefinition* rootParent() { SkASSERT(0); return nullptr; }
    193     virtual const RootDefinition* rootParent() const { SkASSERT(0); return nullptr; }
    194     void setCanonicalFiddle();
    195 
    196     void setParentIndex() {
    197         fParentIndex = fParent ? (int) fParent->fTokens.size() : -1;
    198     }
    199 
    200     static bool SkipImplementationWords(TextParser& inc);
    201 
    202     string simpleName() {
    203         size_t doubleColon = fName.rfind("::");
    204         return string::npos == doubleColon ? fName : fName.substr(doubleColon + 2);
    205     }
    206 
    207     const Definition* subtopicParent() const {
    208         Definition* test = fParent;
    209         while (test) {
    210             if (MarkType::kTopic == test->fMarkType || MarkType::kSubtopic == test->fMarkType) {
    211                 return test;
    212             }
    213             test = test->fParent;
    214         }
    215         return nullptr;
    216     }
    217 
    218     const Definition* topicParent() const {
    219         Definition* test = fParent;
    220         while (test) {
    221             if (MarkType::kTopic == test->fMarkType) {
    222                 return test;
    223             }
    224             test = test->fParent;
    225         }
    226         return nullptr;
    227     }
    228 
    229     void trimEnd();
    230 
    231     string fText;  // if text is constructed instead of in a file, it's put here
    232     const char* fStart = nullptr;  // .. in original text file, or the start of fText
    233     const char* fContentStart;  // start past optional markup name
    234     string fName;
    235     string fFiddle;  // if its a constructor or operator, fiddle name goes here
    236     string fCode;  // suitable for autogeneration of #Code blocks in bmh
    237     const char* fContentEnd = nullptr;  // the end of the contained text
    238     const char* fTerminator = nullptr;  // the end of the markup, normally ##\n or \n
    239     Definition* fParent = nullptr;
    240     list<Definition> fTokens;
    241     vector<Definition*> fChildren;
    242     string fHash;  // generated by fiddle
    243     string fFileName;
    244     mutable string fWrapper; // used by Example to wrap into proper function
    245     size_t fLineCount = 0;
    246     int fParentIndex = 0;
    247     MarkType fMarkType = MarkType::kNone;
    248     KeyWord fKeyWord = KeyWord::kNone;
    249     Bracket fBracket = Bracket::kNone;
    250     Punctuation fPunctuation = Punctuation::kNone;
    251     MethodType fMethodType = MethodType::kNone;
    252     Operator fOperator = Operator::kUnknown;
    253     Type fType = Type::kNone;
    254     char fMC = '#';
    255     bool fClone = false;
    256     bool fCloned = false;
    257     bool fOperatorConst = false;
    258     bool fPrivate = false;
    259     Details fDetails = Details::kNone;
    260     bool fMemberStart = false;
    261     bool fAnonymous = false;
    262     bool fUndocumented = false;  // include symbol comment has deprecated, private, experimental
    263     mutable bool fVisited = false;
    264 };
    265 
    266 class RootDefinition : public Definition {
    267 public:
    268     enum class AllowParens {
    269         kNo,
    270         kYes,
    271     };
    272 
    273     struct SubtopicContents {
    274         SubtopicContents()
    275             : fShowClones(false) {
    276         }
    277 
    278         vector<Definition*> fMembers;
    279         bool fShowClones;
    280     };
    281 
    282     RootDefinition() {
    283     }
    284 
    285     RootDefinition(MarkType markType, const char* start, int line, Definition* parent, char mc)
    286             : Definition(markType, start, line, parent, mc) {
    287         if (MarkType::kSubtopic != markType && MarkType::kTopic != markType) {
    288             if (parent) {
    289                 fNames.fName = parent->fName;
    290                 fNames.fParent = &parent->asRoot()->fNames;
    291             }
    292         }
    293     }
    294 
    295     RootDefinition(MarkType markType, const char* start, const char* end, int line,
    296             Definition* parent, char mc) : Definition(markType, start, end, line, parent, mc) {
    297     }
    298 
    299     ~RootDefinition() override {
    300         for (auto& iter : fBranches) {
    301             delete iter.second;
    302         }
    303     }
    304 
    305     RootDefinition* asRoot() override { return this; }
    306     void clearVisited();
    307     bool dumpUnVisited();
    308     Definition* find(string ref, AllowParens );
    309     bool isRoot() const override { return true; }
    310 
    311     SubtopicContents& populator(const char* key) {
    312         return fPopulators[key];
    313     }
    314 
    315     RootDefinition* rootParent() override { return fRootParent; }
    316     const RootDefinition* rootParent() const override { return fRootParent; }
    317     void setRootParent(RootDefinition* rootParent) { fRootParent = rootParent; }
    318 
    319     unordered_map<string, RootDefinition*> fBranches;
    320     unordered_map<string, Definition> fLeaves;
    321     unordered_map<string, SubtopicContents> fPopulators;
    322     NameMap fNames;
    323 private:
    324     RootDefinition* fRootParent = nullptr;
    325 };
    326 
    327 #endif
    328