LCOV - code coverage report
Current view: top level - src/parser - Syntax.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 863ef6 Lines: 162 179 90.5 %
Date: 2025-10-15 18:16:15 Functions: 29 32 90.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "Syntax.h"
      11             : #include "MooseUtils.h"
      12             : 
      13             : #include "libmesh/simple_range.h"
      14             : 
      15             : #include <algorithm>
      16             : 
      17       69864 : Syntax::Syntax() : _actions_to_syntax_valid(false) {}
      18             : 
      19             : void
      20    10129937 : Syntax::registerTaskName(const std::string & task, bool should_auto_build)
      21             : {
      22    10129937 :   if (_registered_tasks.count(task) > 0)
      23      139704 :     return;
      24     9990233 :   _tasks.addItem(task);
      25     9990233 :   _registered_tasks[task] = should_auto_build;
      26             : }
      27             : 
      28             : void
      29     4585102 : Syntax::registerTaskName(const std::string & task,
      30             :                          const std::string & moose_object_type,
      31             :                          bool should_auto_build)
      32             : {
      33     4585102 :   auto range = _moose_systems_to_tasks.equal_range(moose_object_type);
      34     5399574 :   for (auto it = range.first; it != range.second; ++it)
      35      814472 :     if (it->second == task)
      36           0 :       return;
      37             : 
      38     4585102 :   if (_registered_tasks.find(task) != _registered_tasks.end())
      39           4 :     mooseError("A ", task, " is already registered.  Do you need to use appendTaskName instead?");
      40             : 
      41     4585098 :   registerTaskName(task, should_auto_build);
      42     4585098 :   _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      43             : }
      44             : 
      45             : void
      46     1114826 : Syntax::appendTaskName(const std::string & task,
      47             :                        const std::string & moose_object_type,
      48             :                        bool deprecated)
      49             : {
      50     1114826 :   if (_registered_tasks.find(task) == _registered_tasks.end())
      51           2 :     mooseError("A ", task, " is not a registered task name.");
      52             : 
      53     1114824 :   if (!deprecated)
      54      905268 :     _moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      55             :   else
      56      209556 :     _deprecated_list_moose_systems_to_tasks.insert(std::make_pair(moose_object_type, task));
      57     1114824 : }
      58             : 
      59             : void
      60    12293866 : Syntax::addDependency(const std::string & task, const std::string & pre_req)
      61             : {
      62    12293866 :   if (_registered_tasks.find(task) == _registered_tasks.end())
      63           2 :     mooseError("A ", task, " is not a registered task name.");
      64             : 
      65    12293864 :   _tasks.insertDependency(task, pre_req);
      66    12293864 : }
      67             : 
      68             : void
      69       69852 : Syntax::addDependencySets(const std::string & action_sets)
      70             : {
      71       69852 :   std::vector<std::string> sets, prev_names, tasks;
      72       69852 :   MooseUtils::tokenize(action_sets, sets, 1, "()");
      73             : 
      74     6985200 :   for (unsigned int i = 0; i < sets.size(); ++i)
      75             :   {
      76     6915348 :     tasks.clear();
      77     6915348 :     MooseUtils::tokenize(sets[i], tasks, 0, ", ");
      78    16065960 :     for (unsigned int j = 0; j < tasks.size(); ++j)
      79             :     {
      80             :       // Each line should depend on each item in the previous line
      81    20466636 :       for (unsigned int k = 0; k < prev_names.size(); ++k)
      82    11316024 :         addDependency(tasks[j], prev_names[k]);
      83             :     }
      84             :     // Copy the the current items to the previous items for the next iteration
      85     6915348 :     std::swap(tasks, prev_names);
      86             :   }
      87       69852 : }
      88             : 
      89             : void
      90           0 : Syntax::deleteTaskDependencies(const std::string & task)
      91             : {
      92           0 :   if (_registered_tasks.find(task) == _registered_tasks.end())
      93           0 :     mooseError("A ", task, " is not a registered task name.");
      94             : 
      95           0 :   _tasks.deleteDependenciesOfKey(task);
      96           0 : }
      97             : 
      98             : void
      99           0 : Syntax::clearTaskDependencies()
     100             : {
     101           0 :   _tasks.clear();
     102           0 : }
     103             : 
     104             : const std::vector<std::string> &
     105       68819 : Syntax::getSortedTask()
     106             : {
     107             :   try
     108             :   {
     109       68819 :     return _tasks.getSortedValues();
     110             :   }
     111           2 :   catch (CyclicDependencyException<std::string> & e)
     112             :   {
     113           2 :     const auto & cycle = e.getCyclicDependencies();
     114           6 :     mooseError("Cyclic dependencies detected: ", MooseUtils::join(cycle, " <- "));
     115           2 :   }
     116             : }
     117             : 
     118             : const std::vector<std::vector<std::string>> &
     119          20 : Syntax::getSortedTaskSet()
     120             : {
     121          20 :   return _tasks.getSortedValuesSets();
     122             : }
     123             : 
     124             : bool
     125     5283728 : Syntax::hasTask(const std::string & task) const
     126             : {
     127     5283728 :   return (_registered_tasks.find(task) != _registered_tasks.end());
     128             : }
     129             : 
     130             : bool
     131           0 : Syntax::isActionRequired(const std::string & task) const
     132             : {
     133           0 :   mooseDeprecated("Syntax::isActionRequired is deprecated, use shouldAutoBuild() instead");
     134           0 :   return shouldAutoBuild(task);
     135             : }
     136             : 
     137             : bool
     138     9841839 : Syntax::shouldAutoBuild(const std::string & task) const
     139             : {
     140     9841839 :   auto map_pair = _registered_tasks.find(task);
     141             :   mooseAssert(map_pair != _registered_tasks.end(), std::string("Unregistered task: ") + task);
     142             : 
     143    19683678 :   return map_pair->second;
     144             : }
     145             : 
     146             : void
     147     8535632 : Syntax::registerActionSyntax(const std::string & action,
     148             :                              const std::string & syntax,
     149             :                              const std::string & task,
     150             :                              const std::string & file,
     151             :                              int line)
     152             : {
     153     8535632 :   auto range = _syntax_to_actions.equal_range(syntax);
     154    10212235 :   for (auto it = range.first; it != range.second; ++it)
     155     1676603 :     if (it->second._action == action && it->second._task == task)
     156           0 :       return;
     157             : 
     158     8535632 :   _syntax_to_actions.insert(std::make_pair(syntax, ActionInfo{action, task}));
     159     8535632 :   _syntax_to_line.addInfo(syntax, action, task, file, line);
     160     8535632 :   _actions_to_syntax_valid = false;
     161             : }
     162             : 
     163             : void
     164           2 : Syntax::replaceActionSyntax(const std::string & action,
     165             :                             const std::string & syntax,
     166             :                             const std::string & task,
     167             :                             const std::string & file,
     168             :                             int line)
     169             : {
     170           2 :   _syntax_to_actions.erase(syntax);
     171           2 :   registerActionSyntax(action, syntax, task, file, line);
     172           2 : }
     173             : 
     174             : void
     175           2 : Syntax::removeAllActionsForSyntax(const std::string & syntax)
     176             : {
     177           2 :   _syntax_to_actions.erase(syntax);
     178           2 : }
     179             : 
     180             : void
     181           2 : Syntax::deprecateActionSyntax(const std::string & syntax)
     182             : {
     183           2 :   const std::string message = "\"[" + syntax + "]\" is deprecated.";
     184           2 :   deprecateActionSyntax(syntax, message);
     185           2 : }
     186             : 
     187             : void
     188          52 : Syntax::deprecateActionSyntax(const std::string & syntax, const std::string & message)
     189             : {
     190          52 :   _deprecated_syntax.insert(std::make_pair(syntax, message));
     191          52 : }
     192             : 
     193             : std::string
     194           4 : Syntax::deprecatedActionSyntaxMessage(const std::string syntax)
     195             : {
     196           4 :   auto it = _deprecated_syntax.find(syntax);
     197             : 
     198           4 :   if (it != _deprecated_syntax.end())
     199           8 :     return it->second;
     200             :   else
     201           0 :     mooseError("The action syntax ", syntax, " is not deprecated");
     202             : }
     203             : 
     204             : bool
     205     1824798 : Syntax::isDeprecatedSyntax(const std::string & syntax) const
     206             : {
     207     1824798 :   return _deprecated_syntax.find(syntax) != _deprecated_syntax.end();
     208             : }
     209             : 
     210             : std::vector<std::string>
     211      554826 : Syntax::getSyntaxByAction(const std::string & action, const std::string & task)
     212             : {
     213             :   // See if the reverse multimap has been built yet, if not build it now
     214      554826 :   if (!_actions_to_syntax_valid)
     215             :   {
     216      138214 :     std::transform(_syntax_to_actions.begin(),
     217             :                    _syntax_to_actions.end(),
     218       69107 :                    std::inserter(_actions_to_syntax, _actions_to_syntax.begin()),
     219     8449137 :                    [](const std::pair<std::string, ActionInfo> pair) {
     220     8449137 :                      return std::make_pair(pair.second._action,
     221     8449137 :                                            std::make_pair(pair.first, pair.second._task));
     222             :                    });
     223       69107 :     _actions_to_syntax_valid = true;
     224             :   }
     225             : 
     226      554826 :   std::vector<std::string> syntax;
     227      554826 :   auto it_pair = _actions_to_syntax.equal_range(action);
     228     1109709 :   for (const auto & syntax_pair : as_range(it_pair))
     229             :     // If task is blank, return all syntax, otherwise filter by task
     230      554883 :     if (task == "" || syntax_pair.second.second == task)
     231      554883 :       syntax.emplace_back(syntax_pair.second.first);
     232             : 
     233     1109652 :   return syntax;
     234           0 : }
     235             : 
     236             : std::vector<std::string>
     237      278428 : Syntax::getNonDeprecatedSyntaxByAction(const std::string & action, const std::string & task)
     238             : {
     239      278428 :   auto syntaxes = getSyntaxByAction(action, task);
     240      835341 :   for (auto syntax_it = begin(syntaxes); syntax_it != end(syntaxes);)
     241             :   {
     242      278485 :     if (isDeprecatedSyntax(*syntax_it))
     243           0 :       syntax_it = syntaxes.erase(syntax_it);
     244             :     else
     245      278485 :       ++syntax_it;
     246             :   }
     247      278428 :   return syntaxes;
     248           0 : }
     249             : 
     250             : std::string
     251     4000628 : Syntax::isAssociated(const std::string & real_id,
     252             :                      bool * is_parent,
     253             :                      const std::map<std::string, std::set<std::string>> & alt_map) const
     254             : {
     255             :   // if non-empty alt_map was provided then traverse its syntax instead of _syntax_to_actions
     256     4000628 :   std::set<std::string> syntax_to_traverse;
     257     4000628 :   if (!alt_map.empty())
     258          14 :     std::transform(alt_map.begin(),
     259             :                    alt_map.end(),
     260             :                    std::inserter(syntax_to_traverse, syntax_to_traverse.end()),
     261         924 :                    [](auto pair) { return pair.first; });
     262             :   else
     263     4000614 :     std::transform(_syntax_to_actions.begin(),
     264             :                    _syntax_to_actions.end(),
     265             :                    std::inserter(syntax_to_traverse, syntax_to_traverse.end()),
     266   489192612 :                    [](auto pair) { return pair.first; });
     267             : 
     268             :   /**
     269             :    * This implementation assumes that wildcards can occur in the place of an entire token but not as
     270             :    * part of a token (i.e.  'Variables/ * /InitialConditions' is valid but not 'Variables/Partial*
     271             :    * /InitialConditions'. Since maps are ordered, a reverse traversal through the registered list
     272             :    * will always select a more specific match before a wildcard match ('*' == char(42)).
     273             :    */
     274             :   bool local_is_parent;
     275     4000628 :   if (is_parent == nullptr)
     276          12 :     is_parent = &local_is_parent; // Just so we don't have to keep checking below when we want to
     277             :                                   // set the value
     278     4000628 :   std::vector<std::string> real_elements, reg_elements;
     279     4000628 :   std::string return_value;
     280             : 
     281     4000628 :   MooseUtils::tokenize(real_id, real_elements);
     282             : 
     283     4000628 :   *is_parent = false;
     284   287488703 :   for (auto it = syntax_to_traverse.rbegin(); it != syntax_to_traverse.rend(); ++it)
     285             :   {
     286   285822845 :     std::string reg_id = *it;
     287   285822845 :     if (reg_id == real_id)
     288             :     {
     289     1198890 :       *is_parent = false;
     290     1198890 :       return reg_id;
     291             :     }
     292   284623955 :     reg_elements.clear();
     293   284623955 :     MooseUtils::tokenize(reg_id, reg_elements);
     294   284623955 :     if (real_elements.size() <= reg_elements.size())
     295             :     {
     296   270554705 :       bool keep_going = true;
     297   536483884 :       for (unsigned int j = 0; keep_going && j < real_elements.size(); ++j)
     298             :       {
     299   783836765 :         if (real_elements[j] != reg_elements[j] && reg_elements[j] != std::string("*"))
     300   256830526 :           keep_going = false;
     301             :       }
     302   270554705 :       if (keep_going)
     303             :       {
     304    13724179 :         if (real_elements.size() < reg_elements.size() && !*is_parent)
     305             :         {
     306             :           // We found a parent, the longest parent in fact but we need to keep
     307             :           // looking to make sure that the real thing isn't registered
     308     1873190 :           *is_parent = true;
     309     1873190 :           return_value = reg_id;
     310             :         }
     311    11850989 :         else if (real_elements.size() == reg_elements.size())
     312             :         {
     313     1135880 :           *is_parent = false;
     314     1135880 :           return reg_id;
     315             :         }
     316             :       }
     317             :     }
     318   285822845 :   }
     319             : 
     320     1665858 :   if (*is_parent)
     321      348730 :     return return_value;
     322             :   else
     323     2634256 :     return "";
     324     4000628 : }
     325             : 
     326             : std::pair<std::multimap<std::string, Syntax::ActionInfo>::const_iterator,
     327             :           std::multimap<std::string, Syntax::ActionInfo>::const_iterator>
     328     4306799 : Syntax::getActions(const std::string & syntax) const
     329             : {
     330     4306799 :   return _syntax_to_actions.equal_range(syntax);
     331             : }
     332             : 
     333             : bool
     334    24113298 : Syntax::verifyMooseObjectTask(const std::string & base, const std::string & task) const
     335             : {
     336    24113298 :   auto iters = _moose_systems_to_tasks.equal_range(base);
     337             : 
     338    52097525 :   for (const auto & task_it : as_range(iters))
     339    29686824 :     if (task == task_it.second)
     340     1702597 :       return true;
     341             : 
     342    22410701 :   iters = _deprecated_list_moose_systems_to_tasks.equal_range(base);
     343    22983652 :   for (const auto & task_it : as_range(iters))
     344      587535 :     if (task == task_it.second)
     345             :     {
     346       14584 :       std::string object_tasks = "";
     347       29168 :       for (const auto & other_task : as_range(_moose_systems_to_tasks.equal_range(base)))
     348       14584 :         object_tasks += (object_tasks == "" ? "" : " ") + other_task.second;
     349             : 
     350       14584 :       mooseDeprecated(
     351       29168 :           "Adding objects from system '" + base + "' through task '" + task +
     352       29168 :           "' is deprecated. This object should only be added from task(s): " + object_tasks +
     353             :           ". This is likely caused by adding objects in a block they no longer belong to. For "
     354             :           "example, FunctorMaterials should no longer be added in the [Materials] block.");
     355       14584 :       return true;
     356       14584 :     }
     357             : 
     358    22396117 :   return false;
     359             : }
     360             : 
     361             : void
     362     1862252 : Syntax::registerSyntaxType(const std::string & syntax, const std::string & type)
     363             : {
     364     1862252 :   _associated_types.insert(std::make_pair(syntax, type));
     365     1862252 : }
     366             : 
     367             : const std::multimap<std::string, std::string> &
     368         317 : Syntax::getAssociatedTypes() const
     369             : {
     370         317 :   return _associated_types;
     371             : }
     372             : 
     373             : const std::multimap<std::string, Syntax::ActionInfo> &
     374         207 : Syntax::getAssociatedActions() const
     375             : {
     376         207 :   return _syntax_to_actions;
     377             : }
     378             : 
     379             : FileLineInfo
     380       22170 : Syntax::getLineInfo(const std::string & syntax,
     381             :                     const std::string & action,
     382             :                     const std::string & task) const
     383             : {
     384       22170 :   return _syntax_to_line.getInfo(syntax, action, task);
     385             : }

Generated by: LCOV version 1.14