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 #include "bmhParser.h"
9 #include "selfCheck.h"
10
11 #ifdef SK_BUILD_FOR_WIN
12 #include <windows.h>
13 #endif
14
15
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(...) \
23 do { \
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
36 // Check that mutiple like-named methods are under one Subtopic
37
38 // 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
43 class SelfChecker {
44 public:
SelfChecker(const BmhParser & bmh)45 SelfChecker(const BmhParser& bmh)
46 : fBmhParser(bmh)
47 {}
48
check()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();
59 if (!this->checkSeeAlso()) {
60 return false;
61 }
62 // report functions that are not covered by related hierarchy
63 if (!this->checkRelatedFunctions()) {
64 return false;
65 }
66 }
67 return true;
68 }
69
70 protected:
71
checkMethod(string topic,const Definition * csChild,vector<string> * reported)72 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 }
82 bool containsMarkTypeIn =
83 Definition::MethodType::kConstructor == csChild->fMethodType
84 || 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);
100 }
101 }
102 }
103 }
104 if (!containsMarkTypeIn) {
105 PRINTF("No #In: %s\n", csChild->fName.c_str());
106 }
107 }
108
checkRelatedFunctions()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);
123 }
124 for (auto missing : reported) {
125 string fullname = topicName + '_' + missing;
126 PRINTF("No #Subtopic: %s\n", fullname.c_str());
127 }
128 return true;
129 }
130
checkSeeAlso()131 bool checkSeeAlso() {
132 return true;
133 }
134
classOrStruct()135 const Definition* classOrStruct() {
136 for (auto& rootChild : fRoot->fChildren) {
137 if (rootChild->isStructOrClass()) {
138 return rootChild;
139 }
140 }
141 return nullptr;
142 }
143
144 enum class Optional {
145 kNo,
146 kYes,
147 };
148
149 private:
150 const BmhParser& fBmhParser;
151 RootDefinition* fRoot;
152 };
153
SelfCheck(const BmhParser & bmh)154 bool SelfCheck(const BmhParser& bmh) {
155 SelfChecker checker(bmh);
156 return checker.check();
157 }
158