blob: 341b9e38e8d4a2eaeed062bd91b296f8905ea308 [file] [log] [blame]
Cary Clarkac47b882018-01-11 10:35:44 -05001/*
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
Cary Clark2da9fb82018-11-01 09:29:36 -04008#include "bmhParser.h"
9#include "selfCheck.h"
Cary Clarkac47b882018-01-11 10:35:44 -050010
Cary Clark4855f782018-02-06 09:41:53 -050011#ifdef SK_BUILD_FOR_WIN
12#include <windows.h>
13#endif
Cary Clarkac47b882018-01-11 10:35:44 -050014
Cary Clark78de7512018-02-07 07:27:09 -050015
16 /* SkDebugf works in both visual studio and git shell, but
17 in git shell output is not piped to grep.
18 printf does not generate output in visual studio, but
19 does in git shell and can be piped.
20 */
21#ifdef SK_BUILD_FOR_WIN
22#define PRINTF(...) \
23do { \
24 if (IsDebuggerPresent()) { \
25 SkDebugf(__VA_ARGS__); \
26 } else { \
27 printf(__VA_ARGS__); \
28 } \
29} while (false)
30#else
31#define PRINTF(...) \
32 printf(__VA_ARGS__)
33#endif
34
35
Cary Clarkac47b882018-01-11 10:35:44 -050036// Check that mutiple like-named methods are under one Subtopic
37
Cary Clarkac47b882018-01-11 10:35:44 -050038// Check that SeeAlso reference each other
39
40// Would be nice to check if other classes have 'create' methods that are included
41// SkSurface::makeImageSnapShot should be referenced under SkImage 'creators'
42
43class SelfChecker {
44public:
45 SelfChecker(const BmhParser& bmh)
46 : fBmhParser(bmh)
47 {}
48
49 bool check() {
50 for (const auto& topic : fBmhParser.fTopicMap) {
51 Definition* topicDef = topic.second;
52 if (topicDef->fParent) {
53 continue;
54 }
55 if (!topicDef->isRoot()) {
56 return fBmhParser.reportError<bool>("expected root topic");
57 }
58 fRoot = topicDef->asRoot();
Cary Clarkac47b882018-01-11 10:35:44 -050059 if (!this->checkSeeAlso()) {
60 return false;
61 }
Cary Clark4855f782018-02-06 09:41:53 -050062 // report functions that are not covered by related hierarchy
Cary Clarkab2621d2018-01-30 10:08:57 -050063 if (!this->checkRelatedFunctions()) {
64 return false;
65 }
Cary Clarkac47b882018-01-11 10:35:44 -050066 }
67 return true;
68 }
69
70protected:
Cary Clarkac47b882018-01-11 10:35:44 -050071
Cary Clark78de7512018-02-07 07:27:09 -050072 void checkMethod(string topic, const Definition* csChild, vector<string>* reported) {
73 if (MarkType::kSubtopic == csChild->fMarkType) {
74 for (auto child : csChild->fChildren) {
75 checkMethod(topic, child, reported);
76 }
77 return;
78 } else if (MarkType::kMethod != csChild->fMarkType) {
79 // only check methods for now
80 return;
81 }
Cary Clarkabaffd82018-11-15 08:25:12 -050082 bool containsMarkTypeIn =
83 Definition::MethodType::kConstructor == csChild->fMethodType
Cary Clark78de7512018-02-07 07:27:09 -050084 || Definition::MethodType::kDestructor == csChild->fMethodType
85 || Definition::MethodType::kOperator == csChild->fMethodType
86 || csChild->fClone;
87 for (auto child : csChild->fChildren) {
88 if (MarkType::kIn == child->fMarkType) {
89 containsMarkTypeIn = true;
90 string subtopic(child->fContentStart,
91 child->fContentEnd - child->fContentStart);
92 string fullname = topic + '_' + subtopic;
93 auto topEnd = fBmhParser.fTopicMap.end();
94 auto topFind = fBmhParser.fTopicMap.find(fullname);
95 auto reportEnd = reported->end();
96 auto reportFind = std::find(reported->begin(), reported->end(), subtopic);
97 if (topEnd == topFind) {
98 if (reportEnd == reportFind) {
99 reported->push_back(subtopic);
Cary Clark4855f782018-02-06 09:41:53 -0500100 }
101 }
Cary Clark78de7512018-02-07 07:27:09 -0500102 }
103 }
104 if (!containsMarkTypeIn) {
105 PRINTF("No #In: %s\n", csChild->fName.c_str());
106 }
107 }
108
109 bool checkRelatedFunctions() {
110 const Definition* cs = this->classOrStruct();
111 if (!cs) {
112 return true;
113 }
114 const Definition* topic = cs->fParent;
115 SkASSERT(topic);
116 SkASSERT(MarkType::kTopic == topic->fMarkType);
117 string topicName = topic->fName;
118 vector<string> methodNames;
119 vector<string> reported;
120 string prefix = cs->fName + "::";
121 for (auto& csChild : cs->fChildren) {
122 checkMethod(topicName, csChild, &reported);
Cary Clarkab2621d2018-01-30 10:08:57 -0500123 }
Cary Clark78de7512018-02-07 07:27:09 -0500124 for (auto missing : reported) {
125 string fullname = topicName + '_' + missing;
126 PRINTF("No #Subtopic: %s\n", fullname.c_str());
127 }
Cary Clarkab2621d2018-01-30 10:08:57 -0500128 return true;
129 }
130
Cary Clarkac47b882018-01-11 10:35:44 -0500131 bool checkSeeAlso() {
132 return true;
133 }
134
Cary Clarkab2621d2018-01-30 10:08:57 -0500135 const Definition* classOrStruct() {
136 for (auto& rootChild : fRoot->fChildren) {
Cary Clark08895c42018-02-01 09:37:32 -0500137 if (rootChild->isStructOrClass()) {
Cary Clarkab2621d2018-01-30 10:08:57 -0500138 return rootChild;
139 }
140 }
141 return nullptr;
142 }
143
Cary Clark2dc84ad2018-01-26 12:56:22 -0500144 enum class Optional {
145 kNo,
146 kYes,
147 };
148
Cary Clarkac47b882018-01-11 10:35:44 -0500149private:
150 const BmhParser& fBmhParser;
151 RootDefinition* fRoot;
152};
153
154bool SelfCheck(const BmhParser& bmh) {
155 SelfChecker checker(bmh);
156 return checker.check();
157}