• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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