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