1ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark/* 2ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark * Copyright 2018 Google Inc. 3ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark * 4ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark * Use of this source code is governed by a BSD-style license that can be 5ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark * found in the LICENSE file. 6ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark */ 7ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 8ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark#include "bookmaker.h" 9ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 104855f78dd16ad50003ec537c98062e24a831cd45Cary Clark#ifdef SK_BUILD_FOR_WIN 114855f78dd16ad50003ec537c98062e24a831cd45Cary Clark#include <windows.h> 124855f78dd16ad50003ec537c98062e24a831cd45Cary Clark#endif 13ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 1478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark 1578de7519692ea93a2d2c70f8c0e773668df49fceCary Clark /* SkDebugf works in both visual studio and git shell, but 1678de7519692ea93a2d2c70f8c0e773668df49fceCary Clark in git shell output is not piped to grep. 1778de7519692ea93a2d2c70f8c0e773668df49fceCary Clark printf does not generate output in visual studio, but 1878de7519692ea93a2d2c70f8c0e773668df49fceCary Clark does in git shell and can be piped. 1978de7519692ea93a2d2c70f8c0e773668df49fceCary Clark */ 2078de7519692ea93a2d2c70f8c0e773668df49fceCary Clark#ifdef SK_BUILD_FOR_WIN 2178de7519692ea93a2d2c70f8c0e773668df49fceCary Clark#define PRINTF(...) \ 2278de7519692ea93a2d2c70f8c0e773668df49fceCary Clarkdo { \ 2378de7519692ea93a2d2c70f8c0e773668df49fceCary Clark if (IsDebuggerPresent()) { \ 2478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark SkDebugf(__VA_ARGS__); \ 2578de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } else { \ 2678de7519692ea93a2d2c70f8c0e773668df49fceCary Clark printf(__VA_ARGS__); \ 2778de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } \ 2878de7519692ea93a2d2c70f8c0e773668df49fceCary Clark} while (false) 2978de7519692ea93a2d2c70f8c0e773668df49fceCary Clark#else 3078de7519692ea93a2d2c70f8c0e773668df49fceCary Clark#define PRINTF(...) \ 3178de7519692ea93a2d2c70f8c0e773668df49fceCary Clark printf(__VA_ARGS__) 3278de7519692ea93a2d2c70f8c0e773668df49fceCary Clark#endif 3378de7519692ea93a2d2c70f8c0e773668df49fceCary Clark 3478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark 35ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark// Check that mutiple like-named methods are under one Subtopic 36ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 37ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark// Check that SeeAlso reference each other 38ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 39ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark// Would be nice to check if other classes have 'create' methods that are included 40ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark// SkSurface::makeImageSnapShot should be referenced under SkImage 'creators' 41ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 42ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clarkclass SelfChecker { 43ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clarkpublic: 44ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark SelfChecker(const BmhParser& bmh) 45ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark : fBmhParser(bmh) 46ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark {} 47ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 48ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark bool check() { 49ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark for (const auto& topic : fBmhParser.fTopicMap) { 50ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark Definition* topicDef = topic.second; 51ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark if (topicDef->fParent) { 52ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark continue; 53ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark } 54ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark if (!topicDef->isRoot()) { 55ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark return fBmhParser.reportError<bool>("expected root topic"); 56ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark } 57ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark fRoot = topicDef->asRoot(); 58ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark if (!this->checkSeeAlso()) { 59ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark return false; 60ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark } 614855f78dd16ad50003ec537c98062e24a831cd45Cary Clark // report functions that are not covered by related hierarchy 62ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark if (!this->checkRelatedFunctions()) { 63ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark return false; 64ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark } 65ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark } 66ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark return true; 67ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark } 68ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 69ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clarkprotected: 705081eede67601e5c5c0fc343b787490603e058ccCary Clark 7178de7519692ea93a2d2c70f8c0e773668df49fceCary Clark void checkMethod(string topic, const Definition* csChild, vector<string>* reported) { 7278de7519692ea93a2d2c70f8c0e773668df49fceCary Clark if (MarkType::kSubtopic == csChild->fMarkType) { 7378de7519692ea93a2d2c70f8c0e773668df49fceCary Clark for (auto child : csChild->fChildren) { 7478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark checkMethod(topic, child, reported); 7578de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } 7678de7519692ea93a2d2c70f8c0e773668df49fceCary Clark return; 7778de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } else if (MarkType::kMethod != csChild->fMarkType) { 7878de7519692ea93a2d2c70f8c0e773668df49fceCary Clark // only check methods for now 7978de7519692ea93a2d2c70f8c0e773668df49fceCary Clark return; 8078de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } 8178de7519692ea93a2d2c70f8c0e773668df49fceCary Clark bool containsMarkTypeIn = csChild->fDeprecated // no markup for deprecated 8278de7519692ea93a2d2c70f8c0e773668df49fceCary Clark || Definition::MethodType::kConstructor == csChild->fMethodType 8378de7519692ea93a2d2c70f8c0e773668df49fceCary Clark || Definition::MethodType::kDestructor == csChild->fMethodType 8478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark || Definition::MethodType::kOperator == csChild->fMethodType 8578de7519692ea93a2d2c70f8c0e773668df49fceCary Clark || csChild->fClone; 8678de7519692ea93a2d2c70f8c0e773668df49fceCary Clark for (auto child : csChild->fChildren) { 8778de7519692ea93a2d2c70f8c0e773668df49fceCary Clark if (MarkType::kIn == child->fMarkType) { 8878de7519692ea93a2d2c70f8c0e773668df49fceCary Clark containsMarkTypeIn = true; 8978de7519692ea93a2d2c70f8c0e773668df49fceCary Clark string subtopic(child->fContentStart, 9078de7519692ea93a2d2c70f8c0e773668df49fceCary Clark child->fContentEnd - child->fContentStart); 9178de7519692ea93a2d2c70f8c0e773668df49fceCary Clark string fullname = topic + '_' + subtopic; 9278de7519692ea93a2d2c70f8c0e773668df49fceCary Clark auto topEnd = fBmhParser.fTopicMap.end(); 9378de7519692ea93a2d2c70f8c0e773668df49fceCary Clark auto topFind = fBmhParser.fTopicMap.find(fullname); 9478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark auto reportEnd = reported->end(); 9578de7519692ea93a2d2c70f8c0e773668df49fceCary Clark auto reportFind = std::find(reported->begin(), reported->end(), subtopic); 9678de7519692ea93a2d2c70f8c0e773668df49fceCary Clark if (topEnd == topFind) { 9778de7519692ea93a2d2c70f8c0e773668df49fceCary Clark if (reportEnd == reportFind) { 9878de7519692ea93a2d2c70f8c0e773668df49fceCary Clark reported->push_back(subtopic); 994855f78dd16ad50003ec537c98062e24a831cd45Cary Clark } 1004855f78dd16ad50003ec537c98062e24a831cd45Cary Clark } 10178de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } 10278de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } 10378de7519692ea93a2d2c70f8c0e773668df49fceCary Clark if (!containsMarkTypeIn) { 10478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark PRINTF("No #In: %s\n", csChild->fName.c_str()); 10578de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } 10678de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } 10778de7519692ea93a2d2c70f8c0e773668df49fceCary Clark 10878de7519692ea93a2d2c70f8c0e773668df49fceCary Clark bool checkRelatedFunctions() { 10978de7519692ea93a2d2c70f8c0e773668df49fceCary Clark const Definition* cs = this->classOrStruct(); 11078de7519692ea93a2d2c70f8c0e773668df49fceCary Clark if (!cs) { 11178de7519692ea93a2d2c70f8c0e773668df49fceCary Clark return true; 11278de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } 11378de7519692ea93a2d2c70f8c0e773668df49fceCary Clark const Definition* topic = cs->fParent; 11478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark SkASSERT(topic); 11578de7519692ea93a2d2c70f8c0e773668df49fceCary Clark SkASSERT(MarkType::kTopic == topic->fMarkType); 11678de7519692ea93a2d2c70f8c0e773668df49fceCary Clark string topicName = topic->fName; 11778de7519692ea93a2d2c70f8c0e773668df49fceCary Clark vector<string> methodNames; 11878de7519692ea93a2d2c70f8c0e773668df49fceCary Clark vector<string> reported; 11978de7519692ea93a2d2c70f8c0e773668df49fceCary Clark string prefix = cs->fName + "::"; 12078de7519692ea93a2d2c70f8c0e773668df49fceCary Clark for (auto& csChild : cs->fChildren) { 12178de7519692ea93a2d2c70f8c0e773668df49fceCary Clark checkMethod(topicName, csChild, &reported); 122ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark } 12378de7519692ea93a2d2c70f8c0e773668df49fceCary Clark for (auto missing : reported) { 12478de7519692ea93a2d2c70f8c0e773668df49fceCary Clark string fullname = topicName + '_' + missing; 12578de7519692ea93a2d2c70f8c0e773668df49fceCary Clark PRINTF("No #Subtopic: %s\n", fullname.c_str()); 12678de7519692ea93a2d2c70f8c0e773668df49fceCary Clark } 127ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark return true; 128ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark } 129ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark 1305081eede67601e5c5c0fc343b787490603e058ccCary Clark bool checkSeeAlso() { 1315081eede67601e5c5c0fc343b787490603e058ccCary Clark return true; 1325081eede67601e5c5c0fc343b787490603e058ccCary Clark } 1335081eede67601e5c5c0fc343b787490603e058ccCary Clark 134ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark const Definition* classOrStruct() { 135ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark for (auto& rootChild : fRoot->fChildren) { 13608895c48144cedaf81006803afe4a5a2becfdb92Cary Clark if (rootChild->isStructOrClass()) { 137ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark return rootChild; 138ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark } 139ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark } 140ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark return nullptr; 141ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark } 142ab2621d3e2d2055096b9fbebf16ee443e4ea90fbCary Clark 1432dc84ad3ef88320f612a9459d53f67b63082aebcCary Clark enum class Optional { 1442dc84ad3ef88320f612a9459d53f67b63082aebcCary Clark kNo, 1452dc84ad3ef88320f612a9459d53f67b63082aebcCary Clark kYes, 1462dc84ad3ef88320f612a9459d53f67b63082aebcCary Clark }; 1472dc84ad3ef88320f612a9459d53f67b63082aebcCary Clark 148ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clarkprivate: 149ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark const BmhParser& fBmhParser; 150ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark RootDefinition* fRoot; 151ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark}; 152ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark 153ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clarkbool SelfCheck(const BmhParser& bmh) { 154ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark SelfChecker checker(bmh); 155ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark return checker.check(); 156ac47b88d3c4b6232ea8664cea99fbd8394f2dc38Cary Clark} 157