https://mooseframework.inl.gov
Loading...
Searching...
No Matches
JsonSyntaxTree.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "JsonSyntaxTree.h"
11
12// MOOSE includes
13#include "MooseEnum.h"
14#include "MultiMooseEnum.h"
15#include "ExecFlagEnum.h"
16#include "Builder.h"
17#include "pcrecpp.h"
18#include "Action.h"
19#include "AppFactory.h"
20#include "Registry.h"
21#include "MooseUtils.h"
22
23#include "libmesh/vector_value.h"
24
25// C++ includes
26#include <algorithm>
27#include <cctype>
28
29JsonSyntaxTree::JsonSyntaxTree(const std::string & search_string) : _search(search_string)
30{
31 // Registry holds a map with labels (ie MooseApp) as keys and a vector of RegistryEntry
32 // as values. We need the reverse map: given an action or object name then get the label.
33 auto & actmap = Registry::allActions();
34 for (auto & entry : actmap)
35 for (auto & act : entry.second)
36 _action_label_map[act->_classname] = std::make_pair(entry.first, act->_file);
37
38 auto & objmap = Registry::allObjects();
39 for (auto & entry : objmap)
40 for (auto & obj : entry.second)
41 _object_label_map[obj->name()] = std::make_pair(entry.first, obj->_file);
42}
43
44std::vector<std::string>
45JsonSyntaxTree::splitPath(const std::string & path)
46{
47 std::string s;
48 std::istringstream f(path);
49 std::vector<std::string> paths;
50 while (std::getline(f, s, '/'))
51 if (s.size() > 0)
52 paths.push_back(s);
53 return paths;
54}
55
56nlohmann::json &
57JsonSyntaxTree::getJson(const std::string & path)
58{
59 auto paths = splitPath(path);
60 mooseAssert(paths.size() > 0, "path is empty");
61 auto * next = &(_root["blocks"][paths[0]]);
62
63 for (auto pit = paths.begin() + 1; pit != paths.end(); ++pit)
64 {
65 if (*pit == "*")
66 // It has an action syntax as a parent
67 next = &(*next)["star"];
68 else if (*pit == "<type>")
69 next = &(*next)["types"];
70 else
71 next = &(*next)["subblocks"][*pit];
72 }
73 return *next;
74}
75
76nlohmann::json &
77JsonSyntaxTree::getJson(const std::string & parent, const std::string & path, bool is_type)
78{
79 if (parent.empty())
80 {
81 auto & j = getJson(path);
82 if (path.back() == '*' && !j.contains("subblock_types"))
83 j["subblock_types"] = nlohmann::json();
84 else if (path.back() != '*' && !j.contains("types"))
85 j["types"] = nlohmann::json();
86 return j["actions"];
87 }
88
89 auto & parent_json = getJson(parent);
90 auto paths = splitPath(path);
91 std::string key = "subblock_types";
92 if (is_type)
93 key = "types";
94 auto & val = parent_json[key][paths.back()];
95 return val;
96}
97
98size_t
99JsonSyntaxTree::setParams(InputParameters * params, bool search_match, nlohmann::json & all_params)
100{
101 size_t count = 0;
102 for (auto & iter : *params)
103 {
104 // Make sure we want to see this parameter
105 bool param_match = !_search.empty() && MooseUtils::wildCardMatch(iter.first, _search);
106 if (params->isPrivate(iter.first) || (!_search.empty() && !search_match && !param_match))
107 continue;
108
109 ++count;
110 nlohmann::json param_json;
111
112 param_json["required"] = params->isParamRequired(iter.first);
113
114 // Only output default if it has one
115 if (params->isParamValid(iter.first))
116 param_json["default"] = buildOutputString(iter);
117 else if (params->hasDefaultCoupledValue(iter.first))
118 param_json["default"] = params->defaultCoupledValue(iter.first);
119
120 bool out_of_range_allowed = false;
121 std::map<MooseEnumItem, std::string> docs;
122 param_json["options"] = buildOptions(iter, out_of_range_allowed, docs);
123 if (!nlohmann::to_string(param_json["options"]).empty())
124 {
125 param_json["out_of_range_allowed"] = out_of_range_allowed;
126 if (!docs.empty())
127 {
128 nlohmann::json jdocs;
129 for (const auto & doc : docs)
130 jdocs[doc.first.name()] = doc.second;
131 param_json["option_docs"] = jdocs;
132 }
133 }
134 auto reserved_values = params->reservedValues(iter.first);
135 for (const auto & reserved : reserved_values)
136 param_json["reserved_values"].push_back(reserved);
137
138 std::string t = documentationCppType(MooseUtils::prettyCppType(params->type(iter.first)));
139 param_json["cpp_type"] = t;
140 param_json["basic_type"] = basicCppType(t);
141 param_json["group_name"] = params->getGroupName(iter.first);
142 param_json["name"] = iter.first;
143
144 std::string doc = params->getDocString(iter.first);
146 param_json["description"] = doc;
147
148 param_json["doc_unit"] = params->getDocUnit(iter.first);
149 param_json["doc_range"] =
150 params->isRangeChecked(iter.first) ? params->rangeCheckedFunction(iter.first) : "";
151
152 param_json["controllable"] = params->isControllable(iter.first);
153 param_json["deprecated"] = params->isParamDeprecated(iter.first);
154 all_params[iter.first] = param_json;
155 }
156 return count;
157}
158
159void
161{
162 // If they are doing a search they probably don't want to see this
163 if (_search.empty())
164 {
165 auto params = Moose::Builder::validParams();
166 nlohmann::json jparams;
167 setParams(&params, true, jparams);
168 _root["global"]["parameters"] = jparams;
169
170 // Just create a list of registered app names
171 nlohmann::json apps;
172 auto & factory = AppFactory::instance();
173 for (const auto & name_bi_pair : factory.registeredObjects())
174 apps.push_back(name_bi_pair.first);
175
176 _root["global"]["registered_apps"] = apps;
177 }
178}
179
180bool
181JsonSyntaxTree::addParameters(const std::string & parent,
182 const std::string & path,
183 bool is_type,
184 const std::string & action,
185 bool is_action,
186 InputParameters * params,
187 const FileLineInfo & lineinfo,
188 const std::string & classname)
189{
190 if (action == "EmptyAction")
191 return false;
192
193 nlohmann::json all_params;
194 bool search_match = !_search.empty() && (MooseUtils::wildCardMatch(path, _search) ||
197 auto count = setParams(params, search_match, all_params);
198 if (!_search.empty() && count == 0)
199 // no parameters that matched the search string
200 return false;
201
202 nlohmann::json & json = getJson(parent, path, is_type);
203
204 if (is_action)
205 {
206 json[action]["parameters"] = all_params;
207 json[action]["description"] = params->getClassDescription();
208 json[action]["action_path"] = path;
209 auto label_pair = getActionLabel(action);
210 json[action]["label"] = label_pair.first;
211 json[action]["register_file"] = label_pair.second;
212 if (lineinfo.isValid())
213 json[action]["file_info"][lineinfo.file()] = lineinfo.line();
214 }
215 else if (params)
216 {
217 if (params->hasBase())
218 json["moose_base"] = params->getBase();
219
220 json["parameters"] = all_params;
221 json["syntax_path"] = path;
222 json["parent_syntax"] = parent;
223 json["description"] = params->getClassDescription();
224 // We do this for ActionComponents which are registered as Actions but
225 // dumped to the syntax tree as Objects
226 if (params->hasBase() && json["moose_base"] == "Action")
227 {
228 auto label_pair = getActionLabel(classname);
229 json["label"] = label_pair.first;
230 json["register_file"] = label_pair.second;
231 }
232 else
233 {
234 auto label_pair = getObjectLabel(path);
235 json["label"] = label_pair.first;
236 json["register_file"] = label_pair.second;
237 }
238 if (lineinfo.isValid())
239 {
240 json["file_info"][lineinfo.file()] = lineinfo.line();
241 if (!classname.empty())
242 json["class"] = classname;
243 }
244 }
245 return true;
246}
247
248std::string
249JsonSyntaxTree::buildOptions(const std::iterator_traits<InputParameters::iterator>::value_type & p,
250 bool & out_of_range_allowed,
251 std::map<MooseEnumItem, std::string> & docs)
252{
253 libMesh::Parameters::Value * val = MooseUtils::get(p.second);
254
255 std::string options;
256 {
257 auto * enum_type = dynamic_cast<InputParameters::Parameter<MooseEnum> *>(val);
258 if (enum_type)
259 {
260 out_of_range_allowed = enum_type->get().isOutOfRangeAllowed();
261 options = enum_type->get().getRawNames();
262 docs = enum_type->get().getItemDocumentation();
263 }
264 }
265 {
266 auto * enum_type = dynamic_cast<InputParameters::Parameter<MultiMooseEnum> *>(val);
267 if (enum_type)
268 {
269 out_of_range_allowed = enum_type->get().isOutOfRangeAllowed();
270 options = enum_type->get().getRawNames();
271 docs = enum_type->get().getItemDocumentation();
272 }
273 }
274 {
275 auto * enum_type = dynamic_cast<InputParameters::Parameter<ExecFlagEnum> *>(val);
276 if (enum_type)
277 {
278 out_of_range_allowed = enum_type->get().isOutOfRangeAllowed();
279 options = enum_type->get().getRawNames();
280 docs = enum_type->get().getItemDocumentation();
281 }
282 }
283 {
284 auto * enum_type = dynamic_cast<InputParameters::Parameter<std::vector<MooseEnum>> *>(val);
285 if (enum_type)
286 {
287 out_of_range_allowed = (enum_type->get())[0].isOutOfRangeAllowed();
288 options = (enum_type->get())[0].getRawNames();
289 docs = enum_type->get()[0].getItemDocumentation();
290 }
291 }
292 {
293 auto * enum_type = dynamic_cast<InputParameters::Parameter<std::vector<MultiMooseEnum>> *>(val);
294 if (enum_type)
295 {
296 out_of_range_allowed = (enum_type->get())[0].isOutOfRangeAllowed();
297 options = (enum_type->get())[0].getRawNames();
298 docs = enum_type->get()[0].getItemDocumentation();
299 }
300 }
301 return options;
302}
303
304std::string
306 const std::iterator_traits<InputParameters::iterator>::value_type & p)
307{
308 libMesh::Parameters::Value * val = MooseUtils::get(p.second);
309
310 // Account for Point
311 std::stringstream str;
312 InputParameters::Parameter<Point> * ptr0 = dynamic_cast<InputParameters::Parameter<Point> *>(val);
313
314 // Account for RealVectorValues
315 InputParameters::Parameter<RealVectorValue> * ptr1 =
316 dynamic_cast<InputParameters::Parameter<RealVectorValue> *>(val);
317
318 // Output the Point components
319 if (ptr0)
320 str << ptr0->get().operator()(0) << " " << ptr0->get().operator()(1) << " "
321 << ptr0->get().operator()(2);
322
323 // Output the RealVectorValue components
324 else if (ptr1)
325 str << ptr1->get().operator()(0) << " " << ptr1->get().operator()(1) << " "
326 << ptr1->get().operator()(2);
327
328 // General case, call the print operator
329 else
330 val->print(str);
331
332 // remove additional '\n' possibly generated in output (breaks JSON parsing)
333 std::string tmp_str = str.str();
334 for (auto & ch : tmp_str)
335 if (ch == '\n')
336 ch = ' ';
337
338 return tmp_str.substr(0, tmp_str.find("<RESIDUAL>"));
339}
340
341void
342JsonSyntaxTree::addSyntaxType(const std::string & path, const std::string type)
343{
345 {
346 auto & j = getJson(path);
347 j["associated_types"].push_back(type);
348 }
349 // If they are doing a search they probably don't want to see this
350 if (_search.empty())
351 {
352 _root["global"]["associated_types"][type].push_back(path);
353 }
354}
355
356void
357JsonSyntaxTree::addActionTask(const std::string & path,
358 const std::string & action,
359 const std::string & task_name,
360 const FileLineInfo & lineinfo)
361{
362 nlohmann::json & json = getJson("", path, false);
363 if (lineinfo.isValid())
364 json[action]["tasks"][task_name]["file_info"][lineinfo.file()] = lineinfo.line();
365}
366
367std::string
368JsonSyntaxTree::documentationCppType(const std::string & cpp_type)
369{
370 auto s = cpp_type;
371 pcrecpp::RE("\\bdouble\\b").GlobalReplace("Real", &s);
372 return s;
373}
374
375std::string
376JsonSyntaxTree::basicCppType(const std::string & cpp_type)
377{
378 std::string s = "String";
379 if (cpp_type.find("std::vector") != std::string::npos ||
380 cpp_type.find("libMesh::VectorValue") != std::string::npos ||
381 cpp_type.find("libMesh::TensorValue") != std::string::npos ||
382 cpp_type.find("Eigen::Matrix") != std::string::npos)
383 {
384 // Get the template type and use its basic type for the array type
385 pcrecpp::RE r("^[^<]+<\\s*(.*)\\s*>$");
386 std::string t;
387 r.FullMatch(cpp_type, &t);
388
389 // Capture type just to the first comma for Eigen::Matrix<type,V,W,X,Y,Z>
390 if (cpp_type.find("Eigen::Matrix") != std::string::npos)
391 t = t.substr(0, t.find(","));
392
393 s = "Array:" + basicCppType(t);
394 }
395 else if (cpp_type.find("std::map") != std::string::npos ||
396 cpp_type.find("std::unordered_map") != std::string::npos)
397 {
398 // Get the template types
399 // Matches std::map< K , V [, ...] >
400 // and std::unordered_map< K , V [, ...] >
401 pcrecpp::RE r_map(
402 "^(?:std::)?(?:unordered_)?map\\s*<\\s*([^,>]+)\\s*,\\s*([^,>]+)(?:\\s*,.*)?\\s*>$");
403
404 // k and v hold the key and value types
405 std::string k, v;
406 r_map.FullMatch(cpp_type, &k, &v);
407
408 s = "Map:" + k + "->" + v;
409 }
410 else if (cpp_type.find("MultiMooseEnum") != std::string::npos ||
411 cpp_type.find("ExecFlagEnum") != std::string::npos ||
412 cpp_type.find("VectorPostprocessorName") != std::string::npos)
413 s = "Array:String";
414 else if (cpp_type.find("libMesh::Point") != std::string::npos)
415 s = "Array:Real";
416 else if (cpp_type == "int" || cpp_type == "unsigned int" || cpp_type == "short" ||
417 cpp_type == "unsigned short" || cpp_type == "char" || cpp_type == "unsigned char" ||
418 cpp_type == "long" || cpp_type == "unsigned long" || cpp_type == "long long" ||
419 cpp_type == "unsigned long long")
420 s = "Integer";
421 else if (cpp_type == "Real" || cpp_type == "double" || cpp_type == "float")
422 s = "Real";
423 else if (cpp_type == "bool")
424 s = "Boolean";
425
426 return s;
427}
428
429std::pair<std::string, std::string>
430JsonSyntaxTree::getObjectLabel(const std::string & obj) const
431{
432 auto paths = splitPath(obj);
433 auto it = _object_label_map.find(paths.back());
434 if (it != _object_label_map.end())
435 return it->second;
436 else
437 return std::make_pair("", "");
438}
439
440std::pair<std::string, std::string>
441JsonSyntaxTree::getActionLabel(const std::string & action) const
442{
443 auto it = _action_label_map.find(action);
444 if (it != _action_label_map.end())
445 return it->second;
446 else
447 return std::make_pair("", "");
448}
unsigned int count
Definition MortarUtils.C:53
static AppFactory & instance()
Get the instance of the AppFactory.
Definition AppFactory.C:20
Holds file and line information.
bool isValid() const
int line() const
std::string file() const
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
bool isPrivate(const std::string &name) const
Returns a Boolean indicating whether the specified parameter is private or not.
std::string rangeCheckedFunction(const std::string &name) const
Return the range check function for any parameter (empty string if it is not range checked)
std::string getDocString(const std::string &name) const
Returns the documentation string for the specified parameter name.
std::string type(const std::string &name) const
Prints the type of the requested parameter by name.
std::string getDocUnit(const std::string &name) const
Returns the documentation unit string for the specified parameter name.
bool isParamRequired(const std::string &name) const
Returns a boolean indicating whether the specified parameter is required or not.
std::set< std::string > reservedValues(const std::string &name) const
Get a set of reserved parameter values.
bool hasDefaultCoupledValue(const std::string &coupling_name) const
Return whether or not the requested parameter has a default coupled value.
std::string getGroupName(const std::string &param_name) const
This method retrieves the group name for the passed parameter name if one exists.
std::string getClassDescription() const
Returns the class description.
Real defaultCoupledValue(const std::string &coupling_name, unsigned int i=0) const
Get the default value for an optionally coupled variable.
bool isParamDeprecated(const std::string &name) const
Returns True if the parameters is deprecated.
bool isControllable(const std::string &name) const
Returns a Boolean indicating whether the specified parameter is controllable.
const std::string & getBase() const
bool hasBase() const
bool isRangeChecked(const std::string &param_name) const
Return whether a parameter has a range check.
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another,...
std::string _search
bool addParameters(const std::string &parent_path, const std::string &path, bool is_type, const std::string &action, bool is_action, InputParameters *params, const FileLineInfo &lineinfo, const std::string &classname)
Add parameters to the tree.
void addSyntaxType(const std::string &path, const std::string type)
Add an associated type to a block.
static std::string documentationCppType(const std::string &cpp_type)
Utilities for making sense of c++ types.
void addActionTask(const std::string &path, const std::string &action, const std::string &task, const FileLineInfo &lineinfo)
Add a task to the tree.
static std::string basicCppType(const std::string &cpp_type)
nlohmann::json & getJson(const std::string &parent, const std::string &path, bool is_type)
std::pair< std::string, std::string > getObjectLabel(const std::string &obj) const
std::map< std::string, std::pair< std::string, std::string > > _action_label_map
nlohmann::json _root
std::pair< std::string, std::string > getActionLabel(const std::string &action) const
std::map< std::string, std::pair< std::string, std::string > > _object_label_map
static std::string buildOutputString(const std::iterator_traits< InputParameters::iterator >::value_type &p)
size_t setParams(InputParameters *params, bool search_match, nlohmann::json &all_params)
JsonSyntaxTree(const std::string &search_string)
void addGlobal()
Add the global section to the output.
static std::vector< std::string > splitPath(const std::string &path)
std::string buildOptions(const std::iterator_traits< InputParameters::iterator >::value_type &p, bool &out_of_range_allowed, std::map< MooseEnumItem, std::string > &docs)
static InputParameters validParams()
Parameters that are processed directly by the Parser and are valid anywhere in the input.
Definition Builder.C:121
static const std::map< std::string, std::vector< std::shared_ptr< RegistryEntryBase > > > & allObjects()
Returns a per-label keyed map of all MooseObjects in the registry.
Definition Registry.h:250
static const std::map< std::string, std::vector< std::shared_ptr< RegistryEntryBase > > > & allActions()
Returns a per-label keyed map of all Actions in the registry.
Definition Registry.h:255
virtual void print(std::ostream &) const=0
void escape(std::string &str)
Definition MooseUtils.C:218
std::string prettyCppType(const std::string &cpp_type)
bool wildCardMatch(std::string name, std::string search_string)
Definition MooseUtils.C:899