xref: /petsc/lib/petsc/bin/maint/petsclinter/petsclinter/checks/_register.py (revision c12c126234ed623246a63bfa78c9f75a3aa00323)
1#!/usr/bin/env python3
2"""
3# Created: Mon Jun 20 20:07:30 2022 (-0400)
4# @author: Jacob Faibussowitsch
5"""
6from __future__ import annotations
7
8from .._typing import *
9
10import clang.cindex as clx # type: ignore[import]
11
12_T = TypeVar('_T')
13_U = TypeVar('_U')
14
15classid_map: dict[str, str]                     = {}
16check_function_map: dict[str, FunctionChecker]  = {}
17check_doc_map: dict[clx.CursorKind, DocChecker] = {}
18
19def filter_check_function_map(allowed_symbol_names: Collection[str]) -> None:
20  r"""Remove checks from check_function_map
21
22  Parameters
23  ----------
24  allowed_symbol_names :
25    a set of symbol names
26
27  Notes
28  -----
29  After this routine returns, the check function map will only contain functions whose symbol name
30  was in `allowed_symbol_names`
31  """
32  if allowed_symbol_names:
33    global check_function_map
34
35    # note the list, this makes a copy of the keys allowing us to delete entries "in place"
36    for key in list(check_function_map.keys()):
37      if key not in allowed_symbol_names:
38        del check_function_map[key]
39  return
40
41def __register_base(key: _T, value: _U, target_map: dict[_T, _U], exist_ok: bool) -> None:
42  if key in target_map:
43    if not exist_ok:
44      raise RuntimeError(f'Key {key} already registered with check map')
45
46  target_map[key] = value
47  return
48
49def register_classid(struct_name: str, classid_name: str, exist_ok: bool = False) -> None:
50  r"""Register a classid to match struct names
51
52  Parameters
53  ----------
54  struct_name :
55    the fully qualified structure typename to match against, e.g. _p_PetscObject *
56  classid_name :
57    the string name of the classid variable, e.g. "KSP_CLASSID"
58  exist_ok : optional
59    is it ok if there already exists a classid for this struct?
60
61  Raises
62  ------
63  RuntimeError
64    if a classid has already been registered for `struct_name` and `exist_ok` is False
65  """
66  __register_base(struct_name, classid_name, classid_map, exist_ok)
67  return
68
69def register_symbol_check(name: str, function: FunctionChecker, exist_ok: bool = False) -> None:
70  r"""Register a symbol checking function
71
72  Parameters
73  ----------
74  name :
75    the name of the symbol this checker will trigger on
76  function :
77    the function to check the symbol
78  exist_ok : optional
79    is it ok if there already exists a checker for this kind?
80
81  Raises
82  ------
83  RuntimeError
84    if a function has already been registered for `name` and `exist_ok` is False
85  """
86  __register_base(name, function, check_function_map, exist_ok)
87  return
88
89def register_doc_check(cursor_kind: clx.CursorKind, function: DocChecker, exist_ok: bool = False) -> None:
90  r"""Register a docs-checking function
91
92  Parameters
93  ----------
94  cursor_kind :
95    the kind of cursor this docs checker will trigger on, (e.g. functions, enums, etc.)
96  function :
97    the function to check the docstring
98  exist_ok : optional
99    is it ok if there already exists a checker for this kind?
100
101  Raises
102  ------
103  RuntimeError
104    if a function has already been registered for `cursor_kind` and `exist_ok` is False
105  """
106  __register_base(cursor_kind, function, check_doc_map, exist_ok)
107  return
108
109def __register_all_classids() -> None:
110  r"""
111  Adding new classes
112  ------------------
113
114  You must register new instances of PETSc classes in the classid_map which expects its
115  contents to be in the form:
116
117  "CaseSensitiveNameOfPrivateStruct *" : "CaseSensitiveNameOfCorrespondingClassId",
118
119  See below for examples.
120
121  * please add your new class in alphabetical order and preserve the alignment! *
122
123  The automated way to do it (in emacs) is to slap it in the first entry then highlight
124  the contents (i.e. excluding "classid_map = {" and the closing "}") and do:
125
126  1. M-x sort-fields RET
127  2. M-x align-regexp RET : RET
128  """
129  default_classid_map = {
130    "_p_AO *"                     : "AO_CLASSID",
131    "_p_PetscBench *"                : "BM_CLASSID",
132    "_p_Characteristic *"         : "CHARACTERISTIC_CLASSID",
133    "_p_DM *"                     : "DM_CLASSID",
134    "_p_DMAdaptor *"              : "DMADAPTOR_CLASSID",
135    "_p_DMField *"                : "DMFIELD_CLASSID",
136    "_p_DMKSP *"                  : "DMKSP_CLASSID",
137    "_p_DMLabel *"                : "DMLABEL_CLASSID",
138    "_p_DMPlexTransform *"        : "DMPLEXTRANSFORM_CLASSID",
139    "_p_DMSwarmCellDM *"          : "DMSWARMCELLDM_CLASSID",
140    "_p_DMSNES *"                 : "DMSNES_CLASSID",
141    "_p_DMTS *"                   : "DMTS_CLASSID",
142    "_p_IS *"                     : "IS_CLASSID",
143    "_p_ISLocalToGlobalMapping *" : "IS_LTOGM_CLASSID",
144    "_p_KSP *"                    : "KSP_CLASSID",
145    "_p_KSPGuess *"               : "KSPGUESS_CLASSID",
146    "_p_LineSearch *"             : "SNESLINESEARCH_CLASSID",
147    "_p_Mat *"                    : "MAT_CLASSID",
148    "_p_MatCoarsen *"             : "MAT_COARSEN_CLASSID",
149    "_p_MatColoring *"            : "MAT_COLORING_CLASSID",
150    "_p_MatFDColoring *"          : "MAT_FDCOLORING_CLASSID",
151    "_p_MatMFFD *"                : "MATMFFD_CLASSID",
152    "_p_MatNullSpace *"           : "MAT_NULLSPACE_CLASSID",
153    "_p_MatPartitioning *"        : "MAT_PARTITIONING_CLASSID",
154    "_p_MatTransposeColoring *"   : "MAT_TRANSPOSECOLORING_CLASSID",
155    "_p_PC *"                     : "PC_CLASSID",
156    "_p_PF *"                     : "PF_CLASSID",
157    "_p_PetscContainer *"         : "PETSC_CONTAINER_CLASSID",
158    "_p_PetscConvEst *"           : "PETSC_OBJECT_CLASSID",
159    "_p_PetscDS *"                : "PETSCDS_CLASSID",
160    "_p_PetscDraw *"              : "PETSC_DRAW_CLASSID",
161    "_p_PetscDrawAxis *"          : "PETSC_DRAWAXIS_CLASSID",
162    "_p_PetscDrawBar *"           : "PETSC_DRAWBAR_CLASSID",
163    "_p_PetscDrawHG *"            : "PETSC_DRAWHG_CLASSID",
164    "_p_PetscDrawLG *"            : "PETSC_DRAWLG_CLASSID",
165    "_p_PetscDrawSP *"            : "PETSC_DRAWSP_CLASSID",
166    "_p_PetscDualSpace *"         : "PETSCDUALSPACE_CLASSID",
167    "_p_PetscFE *"                : "PETSCFE_CLASSID",
168    "_p_PetscFV *"                : "PETSCFV_CLASSID",
169    "_p_PetscLimiter *"           : "PETSCLIMITER_CLASSID",
170    "_p_PetscLinterDummyObj *"    : "PETSC_LINTER_DUMMY_OBJECT",
171    "_p_PetscLogHandler *"        : "PETSCLOGHANDLER_CLASSID",
172    "_p_PetscObject *"            : "PETSC_OBJECT_CLASSID",
173    "_p_PetscPartitioner *"       : "PETSCPARTITIONER_CLASSID",
174    "_p_PetscQuadrature *"        : "PETSCQUADRATURE_CLASSID",
175    "_p_PetscRandom *"            : "PETSC_RANDOM_CLASSID",
176    "_p_PetscSF *"                : "PETSCSF_CLASSID",
177    "_p_PetscSection *"           : "PETSC_SECTION_CLASSID",
178    "_p_PetscSectionSym *"        : "PETSC_SECTION_SYM_CLASSID",
179    "_p_PetscSpace *"             : "PETSCSPACE_CLASSID",
180    "_p_PetscViewer *"            : "PETSC_VIEWER_CLASSID",
181    "_p_PetscWeakForm *"          : "PETSCWEAKFORM_CLASSID",
182    "_p_SNES *"                   : "SNES_CLASSID",
183    "_p_TS *"                     : "TS_CLASSID",
184    "_p_TSAdapt *"                : "TSADAPT_CLASSID",
185    "_p_TSGLLEAdapt *"            : "TSGLLEADAPT_CLASSID",
186    "_p_TSTrajectory *"           : "TSTRAJECTORY_CLASSID",
187    "_p_Tao *"                    : "TAO_CLASSID",
188    "_p_TaoLineSearch *"          : "TAOLINESEARCH_CLASSID",
189    "_p_PetscRegressor *"         : "PETSCREGRESSOR_CLASSID",
190    "_p_Vec *"                    : "VEC_CLASSID",
191    "_p_VecTagger *"              : "VEC_TAGGER_CLASSID",
192  }
193  for key, value in default_classid_map.items():
194    register_classid(key, value)
195  return
196
197def __register_all_symbol_checks() -> None:
198  from . import _code
199
200  default_checks = {
201    "PetscValidHeaderSpecificType"       : _code.checkPetscValidHeaderSpecificType,
202    "PetscValidHeaderSpecific"           : _code.checkPetscValidHeaderSpecific,
203    "PetscValidHeader"                   : _code.checkPetscValidHeader,
204    "PetscAssertPointer"                 : _code.check_obj_idx_generic,
205    "PetscCheckSameType"                 : _code.check_obj_idx_generic,
206    "PetscValidType"                     : _code.check_obj_idx_generic,
207    "PetscCheckSameComm"                 : _code.check_obj_idx_generic,
208    "PetscCheckSameTypeAndComm"          : _code.check_obj_idx_generic,
209    "PetscValidLogicalCollectiveScalar"  : _code.checkPetscValidLogicalCollectiveScalar,
210    "PetscValidLogicalCollectiveReal"    : _code.checkPetscValidLogicalCollectiveReal,
211    "PetscValidLogicalCollectiveInt"     : _code.checkPetscValidLogicalCollectiveInt,
212    "PetscValidLogicalCollectiveMPIInt"  : _code.checkPetscValidLogicalCollectiveMPIInt,
213    "PetscValidLogicalCollectiveBool"    : _code.checkPetscValidLogicalCollectiveBool,
214    "PetscValidLogicalCollectiveEnum"    : _code.checkPetscValidLogicalCollectiveEnum,
215    "VecNestCheckCompatible2"            : _code.check_obj_idx_generic,
216    "VecNestCheckCompatible3"            : _code.check_obj_idx_generic,
217    "MatCheckPreallocated"               : _code.check_obj_idx_generic,
218    "MatCheckProduct"                    : _code.check_obj_idx_generic,
219    "MatCheckSameLocalSize"              : _code.check_obj_idx_generic,
220    "MatCheckSameSize"                   : _code.check_obj_idx_generic,
221    "PetscValidDevice"                   : _code.check_obj_idx_generic,
222    "PetscCheckCompatibleDevices"        : _code.check_obj_idx_generic,
223    "PetscValidDeviceContext"            : _code.check_obj_idx_generic,
224    "PetscCheckCompatibleDeviceContexts" : _code.check_obj_idx_generic,
225    "PetscSFCheckGraphSet"               : _code.check_obj_idx_generic,
226  }
227  for key, value in default_checks.items():
228    register_symbol_check(key, value)
229  return
230
231def __register_all_doc_checks() -> None:
232  from . import _docs
233
234  default_checks = {
235    clx.CursorKind.FUNCTION_DECL : _docs.check_petsc_function_docstring,
236    clx.CursorKind.ENUM_DECL     : _docs.check_petsc_enum_docstring,
237  }
238  for key, value in default_checks.items():
239    register_doc_check(key, value)
240  return
241
242def __register_all() -> None:
243  __register_all_classids()
244  __register_all_symbol_checks()
245  __register_all_doc_checks()
246  return
247
248__register_all()
249