MinitScript  0.9.31 PRE-BETA
Documentation.cpp
Go to the documentation of this file.
2 
3 #include <algorithm>
4 #include <map>
5 #include <string>
6 #include <set>
7 #include <unordered_set>
8 #include <utility>
9 #include <vector>
10 
15 
16 using std::map;
17 using std::pair;
18 using std::string;
19 using std::set;
20 using std::sort;
21 using std::to_string;
22 using std::unordered_set;
23 using std::vector;
24 
26 
29 
30 const set<string> Documentation::getAllClassMethods(MinitScript* minitScript) {
31  set<string> allClassMethods;
32  //
33  for (auto typeIdx = static_cast<int>(MinitScript::TYPE_STRING); ; typeIdx++) {
34  const auto& className = MinitScript::Variable::getTypeAsString(static_cast<MinitScript::VariableType>(typeIdx));
35  if (className.empty() == true) break;
36  allClassMethods.insert(className);
37  }
38  //
39  for (auto scriptMethod: minitScript->getMethods()) {
40  string className;
41  if (scriptMethod->getMethodName().rfind("::") != string::npos) className = StringTools::substring(scriptMethod->getMethodName(), 0, scriptMethod->getMethodName().rfind("::"));
42  if (className.empty() == true && allClassMethods.find(scriptMethod->getMethodName()) == allClassMethods.end()) continue;
43  //
44  auto _class = false;
45  for (auto typeIdx = static_cast<int>(MinitScript::TYPE_STRING); ; typeIdx++) {
46  const auto& classNameCandidate = MinitScript::Variable::getTypeAsString(static_cast<MinitScript::VariableType>(typeIdx));
47  if (classNameCandidate.empty() == true) break;
48  if (classNameCandidate == className) {
49  _class = true;
50  break;
51  }
52  }
53  if (_class == false) continue;
54  //
55  auto method =
56  StringTools::substring(
57  scriptMethod->getMethodName(),
58  className.empty() == true?0:className.size() + 2,
59  scriptMethod->getMethodName().size());
60  // no arguments or no "this" argument
61  auto _static =
62  scriptMethod->getArgumentTypes().empty() == true ||
63  scriptMethod->getArgumentTypes()[0].name != StringTools::toLowerCase(className) ||
64  MinitScript::Variable::getTypeAsString(scriptMethod->getArgumentTypes()[0].type) != className;
65  //
66  allClassMethods.insert(scriptMethod->getMethodName());
67  }
68  //
69  return allClassMethods;
70 }
71 
72 const set<string> Documentation::getMethodsCategories(MinitScript* minitScript, const set<string>& allClassMethods, MinitScript* excludeMinitScript) {
73  set<string> categories;
74  auto scriptMethods = minitScript->getMethods();
75  for (auto scriptMethod: scriptMethods) {
76  if (excludeMinitScript != nullptr && excludeMinitScript->hasMethod(scriptMethod->getMethodName()) == true) continue;
77  if (allClassMethods.find(scriptMethod->getMethodName()) != allClassMethods.end()) continue;
78  string result;
79  string category;
80  if (scriptMethod->getMethodName().rfind('.') != string::npos) category = StringTools::substring(scriptMethod->getMethodName(), 0, scriptMethod->getMethodName().rfind('.'));
81  categories.insert(category);
82  }
83  return categories;
84 }
85 
86 const string Documentation::generateClassesDocumentation(const string& heading, int mainHeadingIdx, MinitScript* minitScript, Properties& descriptions, const string& descriptionPrefix, const set<string>& allClassMethods) {
87  auto scriptMethods = minitScript->getMethods();
88  //
89  map<string, array<map<string, string>, 2>> methodMarkupByClassName;
90  for (auto scriptMethod: scriptMethods) {
91  //
92  if (allClassMethods.find(scriptMethod->getMethodName()) == allClassMethods.end()) continue;
93  //
94  string result;
95  string className;
96  if (scriptMethod->getMethodName().rfind("::") != string::npos) className = StringTools::substring(scriptMethod->getMethodName(), 0, scriptMethod->getMethodName().rfind("::"));
97  // constructors
98  auto _static = false;
99  if (className.empty() == true) {
100  for (auto typeIdx = static_cast<int>(MinitScript::TYPE_STRING); ; typeIdx++) {
101  const auto& classNameCandidate = MinitScript::Variable::getTypeAsString(static_cast<MinitScript::VariableType>(typeIdx));
102  if (classNameCandidate.empty() == true) break;
103  if (scriptMethod->getMethodName() == classNameCandidate) {
104  className = classNameCandidate;
105  _static = true;
106  break;
107  }
108  }
109  }
110  //
111  if (_static == false) {
112  _static =
113  scriptMethod->getArgumentTypes().empty() == true ||
114  scriptMethod->getArgumentTypes()[0].name != StringTools::toLowerCase(className) ||
115  MinitScript::Variable::getTypeAsString(scriptMethod->getArgumentTypes()[0].type) != className;
116  }
117  //
118  string description;
119  description+= "| ";
120  description+= descriptions.get(descriptionPrefix + scriptMethod->getMethodName(), "Not documented");
121  while (description.size() < 99) description+= " ";
122  description+= "|";
123  result+= description + "\n";
124  string method;
125  method+= "| <sub>";
126  if (_static == true) {
127  method+= "<b>static</b> ";
128  }
129  method+= _static == true?scriptMethod->getMethodName():StringTools::substring(scriptMethod->getMethodName(), className.size() + 2, scriptMethod->getMethodName().size());
130  method+= "(";
131  method+= scriptMethod->getArgumentsInformation(_static == true?0:1);
132  method+= "): ";
133  method+= MinitScript::Variable::getReturnTypeAsString(scriptMethod->getReturnValueType(), scriptMethod->isReturnValueNullable());
134  method+= "</sub>";
135  while (method.size() < 99) method+= " ";
136  method+= "|";
137  method+= "\n";
138  result+= method;
139  methodMarkupByClassName[className][_static == true?0:1][scriptMethod->getMethodName()] = result;
140  }
141  //
142  string result;
143  auto classIdx = 1;
144  for (auto typeIdx = static_cast<int>(MinitScript::TYPE_STRING); ; typeIdx++) {
145  const auto& className = MinitScript::Variable::getTypeAsString(static_cast<MinitScript::VariableType>(typeIdx));
146  if (className.empty() == true) break;
147  auto classNameDescription = descriptions.get("minitscript.baseclass." + (className.empty() == true?"No class":className), "Not documented");
148  //
149  result+= "\n";
150  result+= "## " + to_string(mainHeadingIdx) + "." + to_string(classIdx++) + ". " + classNameDescription + "\n";
151  result+= "\n";
152  //
153  for (auto staticIdx = 0; staticIdx < 2; staticIdx++) {
154  //
155  if (methodMarkupByClassName[className][staticIdx].empty() == true) continue;
156  //
157  if (staticIdx == 0) {
158  result+= string() + "| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Table of methods &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |" + "\n";
159  result+= string() + "|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|" + "\n";
160  result+= string() + "| &nbsp; |" + "\n";
161  result+= string() + "| <b>STATIC METHODS</b> |" + "\n";
162  } else {
163  result+= string() + "| &nbsp; |" + "\n";
164  result+= string() + "| <b>NON STATIC METHODS</b> |" + "\n";
165  }
166  //
167  for (const auto& [method, methodMarkup]: methodMarkupByClassName[className][staticIdx]) {
168  result+= methodMarkup;
169  }
170  }
171  }
172  //
173  return result;
174 }
175 
176 const string Documentation::generateMethodsDocumentation(const string& heading, int mainHeadingIdx, MinitScript* minitScript, Properties& descriptions, const string& descriptionPrefix, const set<string>& allClassMethods, MinitScript* excludeMinitScript) {
177  auto scriptMethods = minitScript->getMethods();
178  map<string, vector<pair<string, string>>> methodMarkupByCategory;
179  for (auto scriptMethod: scriptMethods) {
180  if (excludeMinitScript != nullptr && excludeMinitScript->hasMethod(scriptMethod->getMethodName()) == true) continue;
181  if (allClassMethods.find(scriptMethod->getMethodName()) != allClassMethods.end()) continue;
182  string result;
183  string category;
184  if (scriptMethod->getMethodName().rfind('.') != string::npos) category = StringTools::substring(scriptMethod->getMethodName(), 0, scriptMethod->getMethodName().rfind('.'));
185  string description;
186  description+= "| ";
187  description+= descriptions.get(descriptionPrefix + scriptMethod->getMethodName(), "Not documented");
188  if (scriptMethod->getContextFunctions().empty() == false) {
189  string contextFunctions;
190  for (const auto& contextFunction: scriptMethod->getContextFunctions()) {
191  if (contextFunctions.empty() == false) contextFunctions+= ", ";
192  contextFunctions+= contextFunction + "()";
193  }
194  description+= " - <i>available in " + contextFunctions + "</i>";
195  }
196  while (description.size() < 99) description+= " ";
197  description+= "|";
198  result+= description + "\n";
199  string method;
200  method+= "| <sub>";
201  method+= scriptMethod->getMethodName();
202  method+= "(";
203  method+= scriptMethod->getArgumentsInformation();
204  method+= "): ";
205  method+= MinitScript::Variable::getReturnTypeAsString(scriptMethod->getReturnValueType(), scriptMethod->isReturnValueNullable());
206  method+= "</sub>";
207  while (method.size() < 99) method+= " ";
208  method+= "|";
209  method+= "\n";
210  result+= method;
211  methodMarkupByCategory[category].push_back(make_pair(scriptMethod->getMethodName(), result));
212  }
213  // collect categories
214  unordered_set<string> categories;
215  for (const auto& [category, methodMarkup]: methodMarkupByCategory) {
216  categories.insert(category);
217  }
218  //
219  map<string, vector<string>> methodMarkupByCategory2;
220  for (const auto& [category, methods]: methodMarkupByCategory) {
221  if (category.empty() == true) continue;
222  for (const auto& [methodName, methodMarkup]: methods) {
223  methodMarkupByCategory2[category].push_back(methodMarkup);
224  }
225  }
226  {
227  auto emptyCategoryMethodsIt = methodMarkupByCategory.find(string());
228  if (emptyCategoryMethodsIt != methodMarkupByCategory.end()) {
229  const auto& methods = emptyCategoryMethodsIt->second;
230  for (const auto& [methodName, methodMarkup]: methods) {
231  if (categories.contains(methodName) == true) {
232  methodMarkupByCategory2[methodName].insert(methodMarkupByCategory2[methodName].begin(), methodMarkup);
233  } else {
234  methodMarkupByCategory2[string()].push_back(methodMarkup);
235  }
236  }
237  }
238  }
239  //
240  string result;
241  result+= "# " + to_string(mainHeadingIdx) + ". " + heading;
242  auto categoryIdx = 1;
243  for (const auto& [category, methodsMarkup]: methodMarkupByCategory2) {
244  auto categoryName = descriptions.get(descriptionPrefix + "group." + (category.empty() == true?"uncategorized":category), "Not documented");
245  result+= "\n";
246  result+= "## " + to_string(mainHeadingIdx) + "." + to_string(categoryIdx++) + ". " + categoryName + "\n";
247  result+= "\n";
248  result+= string() + "| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Table of methods &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |" + "\n";
249  result+= string() + "|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|" + "\n";
250  for (const auto& methodMarkup: methodsMarkup) result+= methodMarkup;
251  }
252  return result;
253 }
254 
255 const string Documentation::generateOperatorsDocumentation(
256  const string& heading,
257  int mainHeadingIdx,
258  MinitScript* minitScript
259 ) {
260  // operators
261  auto scriptOperatorMethods = minitScript->getOperatorMethods();
262  vector<string> operators;
263  for (auto scriptMethod: scriptOperatorMethods) {
264  string operatorString;
265  operatorString = "| ";
266  operatorString+= StringTools::replace(MinitScript::getOperatorAsString(scriptMethod->getOperator()), "|", "\\|");
267  while (operatorString.size() < 5) operatorString+= " ";
268  operatorString+= "| ";
269  operatorString+= scriptMethod->getMethodName();
270  operatorString+= "(";
271  operatorString+= scriptMethod->getArgumentsInformation();
272  operatorString+= "): ";
273  operatorString+= MinitScript::Variable::getReturnTypeAsString(scriptMethod->getReturnValueType(), scriptMethod->isReturnValueNullable());
274  while (operatorString.size() < 99) operatorString+= " ";
275  operatorString+= "|";
276  operators.push_back(operatorString);
277  }
278  sort(operators.begin(), operators.end());
279  //
280  string result;
281  result+= string() + "\n";
282  result+= string() + "# " + to_string(mainHeadingIdx) + ". " + heading + "\n";
283  result+= string() + "\n";
284  result+= string() + "| Op | Method |" + "\n";
285  result+= string() + "|----|---------------------------------------------------------------------------------------------|" + "\n";
286  for (const auto& method: operators) result+= string() + method + "\n";
287  return result;
288 }
289 
290 const string Documentation::generateVariablesDocumentation(
291  const string& heading,
292  int mainHeadingIdx,
293  MinitScript* minitScript
294 ) {
295  //
296  vector<string> variables;
297  for (const auto& [variableName, variable]: minitScript->getRootScriptState().variables) {
298  string variableString;
299  variableString = "| ";
300  variableString+= variableName;
301  while (variableString.size() < 62) variableString+= " ";
302  variableString+= "| ";
303  auto idx = variableString.size();
304  variableString+= variable->getValueAsString();
305  while (variableString.size() - idx < 35) variableString+= " ";
306  variableString+= "|";
307  variables.push_back(variableString);
308  }
309  sort(variables.begin(), variables.end());
310  //
311  string result;
312  result+= string() + "\n";
313  result+= string() + "# " + to_string(mainHeadingIdx) + ". " + heading + "\n";
314  result+= string() + "\n";
315  result+= string() + "| Name | Value |" + "\n";
316  result+= string() + "|-------------------------------------------------------------|------------------------------------|" + "\n";
317  for (const auto& method: variables) result+= string() + method + "\n";
318  return result;
319 }
MinitScript documentation.
Definition: Documentation.h:21
bool hasMethod(const string &methodName)
Returns if method with given name does exist.
Definition: MinitScript.h:4508
const vector< Method * > getMethods()
const vector< Method * > getOperatorMethods()
Properties class, which helps out with storeing or loading key value pairs from/to property files.
Definition: Properties.h:17
const string & get(const string &key, const string &defaultValue) const
Get property value by key.
Definition: Properties.h:40
unordered_map< string, Variable * > variables
Definition: MinitScript.h:3109