@specs-feup/clava-misra 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/.gitignore +8 -0
  2. package/README.md +53 -19
  3. package/dist/MISRA.d.ts +28 -10
  4. package/dist/MISRA.d.ts.map +1 -1
  5. package/dist/MISRA.js +30 -10
  6. package/dist/MISRA.js.map +1 -1
  7. package/dist/MISRAContext.d.ts +65 -11
  8. package/dist/MISRAContext.d.ts.map +1 -1
  9. package/dist/MISRAContext.js +131 -35
  10. package/dist/MISRAContext.js.map +1 -1
  11. package/dist/MISRARule.d.ts +38 -25
  12. package/dist/MISRARule.d.ts.map +1 -1
  13. package/dist/MISRARule.js +40 -18
  14. package/dist/MISRARule.js.map +1 -1
  15. package/dist/MISRATool.d.ts +46 -5
  16. package/dist/MISRATool.d.ts.map +1 -1
  17. package/dist/MISRATool.js +118 -45
  18. package/dist/MISRATool.js.map +1 -1
  19. package/dist/StandardGuideline.d.ts +22 -0
  20. package/dist/StandardGuideline.d.ts.map +1 -0
  21. package/dist/StandardGuideline.js +12 -0
  22. package/dist/StandardGuideline.js.map +1 -0
  23. package/dist/ast-visitor/Context.d.ts +11 -0
  24. package/dist/ast-visitor/Context.d.ts.map +1 -0
  25. package/dist/ast-visitor/Context.js +15 -0
  26. package/dist/ast-visitor/Context.js.map +1 -0
  27. package/dist/ast-visitor/Visit.d.ts +23 -0
  28. package/dist/ast-visitor/Visit.d.ts.map +1 -0
  29. package/dist/ast-visitor/Visit.js +18 -0
  30. package/dist/ast-visitor/Visit.js.map +1 -0
  31. package/dist/ast-visitor/VisitWithContext.d.ts +32 -0
  32. package/dist/ast-visitor/VisitWithContext.d.ts.map +1 -0
  33. package/dist/ast-visitor/VisitWithContext.js +26 -0
  34. package/dist/ast-visitor/VisitWithContext.js.map +1 -0
  35. package/dist/main.js +1 -2
  36. package/dist/main.js.map +1 -1
  37. package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.d.ts +27 -0
  38. package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.d.ts.map +1 -0
  39. package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.js +98 -0
  40. package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.js.map +1 -0
  41. package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.d.ts +45 -6
  42. package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.d.ts.map +1 -1
  43. package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.js +91 -8
  44. package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.js.map +1 -1
  45. package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.d.ts +15 -5
  46. package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.d.ts.map +1 -1
  47. package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.js +20 -6
  48. package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.js.map +1 -1
  49. package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.d.ts +11 -5
  50. package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.d.ts.map +1 -1
  51. package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.js +13 -10
  52. package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.js.map +1 -1
  53. package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.d.ts +11 -6
  54. package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.d.ts.map +1 -1
  55. package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.js +19 -11
  56. package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.js.map +1 -1
  57. package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.d.ts +15 -5
  58. package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.d.ts.map +1 -1
  59. package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.js +24 -10
  60. package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.js.map +1 -1
  61. package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.d.ts +22 -6
  62. package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.d.ts.map +1 -1
  63. package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.js +37 -10
  64. package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.js.map +1 -1
  65. package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.d.ts +66 -0
  66. package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.d.ts.map +1 -0
  67. package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.js +209 -0
  68. package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.js.map +1 -0
  69. package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.d.ts +37 -12
  70. package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.d.ts.map +1 -1
  71. package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.js +112 -39
  72. package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.js.map +1 -1
  73. package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.d.ts +15 -5
  74. package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.d.ts.map +1 -1
  75. package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.js +21 -7
  76. package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.js.map +1 -1
  77. package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.d.ts +11 -6
  78. package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.d.ts.map +1 -1
  79. package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.js +17 -8
  80. package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.js.map +1 -1
  81. package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.d.ts +105 -0
  82. package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.d.ts.map +1 -0
  83. package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.js +258 -0
  84. package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.js.map +1 -0
  85. package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.d.ts +25 -0
  86. package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.d.ts.map +1 -0
  87. package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.js +27 -0
  88. package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.js.map +1 -0
  89. package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.d.ts +29 -0
  90. package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.d.ts.map +1 -0
  91. package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.js +31 -0
  92. package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.js.map +1 -0
  93. package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.d.ts +25 -0
  94. package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.d.ts.map +1 -0
  95. package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.js +27 -0
  96. package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.js.map +1 -0
  97. package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.d.ts +25 -0
  98. package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.d.ts.map +1 -0
  99. package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.js +27 -0
  100. package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.js.map +1 -0
  101. package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.d.ts +25 -0
  102. package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.d.ts.map +1 -0
  103. package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.js +27 -0
  104. package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.js.map +1 -0
  105. package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.d.ts +30 -0
  106. package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.d.ts.map +1 -0
  107. package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.js +32 -0
  108. package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.js.map +1 -0
  109. package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.d.ts +25 -0
  110. package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.d.ts.map +1 -0
  111. package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.js +27 -0
  112. package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.js.map +1 -0
  113. package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.d.ts +6 -14
  114. package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.d.ts.map +1 -1
  115. package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.js +17 -27
  116. package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.js.map +1 -1
  117. package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.d.ts +13 -7
  118. package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.d.ts.map +1 -1
  119. package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.js +31 -17
  120. package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.js.map +1 -1
  121. package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.d.ts +26 -7
  122. package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.d.ts.map +1 -1
  123. package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.js +32 -14
  124. package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.js.map +1 -1
  125. package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.d.ts +48 -6
  126. package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.d.ts.map +1 -1
  127. package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.js +84 -34
  128. package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.js.map +1 -1
  129. package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.d.ts +24 -5
  130. package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.d.ts.map +1 -1
  131. package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.js +27 -7
  132. package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.js.map +1 -1
  133. package/dist/rules/Section5_Identifiers/IdentifierRenameRule.d.ts +46 -0
  134. package/dist/rules/Section5_Identifiers/IdentifierRenameRule.d.ts.map +1 -0
  135. package/dist/rules/Section5_Identifiers/IdentifierRenameRule.js +40 -0
  136. package/dist/rules/Section5_Identifiers/IdentifierRenameRule.js.map +1 -0
  137. package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.d.ts +25 -0
  138. package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.d.ts.map +1 -0
  139. package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.js +46 -0
  140. package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.js.map +1 -0
  141. package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.d.ts +26 -0
  142. package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.d.ts.map +1 -0
  143. package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.js +54 -0
  144. package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.js.map +1 -0
  145. package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.d.ts +27 -0
  146. package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.d.ts.map +1 -0
  147. package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.js +55 -0
  148. package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.js.map +1 -0
  149. package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.d.ts +24 -0
  150. package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.d.ts.map +1 -0
  151. package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.js +42 -0
  152. package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.js.map +1 -0
  153. package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.d.ts +24 -0
  154. package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.d.ts.map +1 -0
  155. package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.js +42 -0
  156. package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.js.map +1 -0
  157. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.d.ts +35 -0
  158. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.d.ts.map +1 -0
  159. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.js +98 -0
  160. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.js.map +1 -0
  161. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.d.ts +35 -0
  162. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.d.ts.map +1 -0
  163. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.js +76 -0
  164. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.js.map +1 -0
  165. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.d.ts +32 -0
  166. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.d.ts.map +1 -0
  167. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.js +57 -0
  168. package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.js.map +1 -0
  169. package/dist/rules/UserConfigurableRule.d.ts +55 -0
  170. package/dist/rules/UserConfigurableRule.d.ts.map +1 -0
  171. package/dist/rules/UserConfigurableRule.js +16 -0
  172. package/dist/rules/UserConfigurableRule.js.map +1 -0
  173. package/dist/rules/index.d.ts +11 -18
  174. package/dist/rules/index.d.ts.map +1 -1
  175. package/dist/rules/index.js +47 -7
  176. package/dist/rules/index.js.map +1 -1
  177. package/dist/tests/Section17_Functions/misra_config.json +10 -0
  178. package/dist/tests/Section21-StandardLibraries/misra_config.json +88 -0
  179. package/dist/tests/Section21-StandardLibraries/problematic_misra_config.json +19 -0
  180. package/dist/tests/utils.d.ts +6 -3
  181. package/dist/tests/utils.d.ts.map +1 -1
  182. package/dist/tests/utils.js +33 -7
  183. package/dist/tests/utils.js.map +1 -1
  184. package/dist/utils/CallUtils.d.ts +15 -0
  185. package/dist/utils/CallUtils.d.ts.map +1 -0
  186. package/dist/utils/CallUtils.js +34 -0
  187. package/dist/utils/CallUtils.js.map +1 -0
  188. package/dist/utils/CommentUtils.d.ts +21 -0
  189. package/dist/utils/CommentUtils.d.ts.map +1 -0
  190. package/dist/utils/CommentUtils.js +27 -0
  191. package/dist/utils/CommentUtils.js.map +1 -0
  192. package/dist/utils/FileUtils.d.ts +67 -0
  193. package/dist/utils/FileUtils.d.ts.map +1 -0
  194. package/dist/utils/FileUtils.js +144 -0
  195. package/dist/utils/FileUtils.js.map +1 -0
  196. package/dist/utils/FunctionUtils.d.ts +47 -0
  197. package/dist/utils/FunctionUtils.d.ts.map +1 -0
  198. package/dist/utils/FunctionUtils.js +87 -0
  199. package/dist/utils/FunctionUtils.js.map +1 -0
  200. package/dist/utils/IdentifierUtils.d.ts +63 -0
  201. package/dist/utils/IdentifierUtils.d.ts.map +1 -0
  202. package/dist/utils/IdentifierUtils.js +133 -0
  203. package/dist/utils/IdentifierUtils.js.map +1 -0
  204. package/dist/utils/JoinpointUtils.d.ts +36 -0
  205. package/dist/utils/JoinpointUtils.d.ts.map +1 -0
  206. package/dist/utils/JoinpointUtils.js +63 -0
  207. package/dist/utils/JoinpointUtils.js.map +1 -0
  208. package/dist/utils/ProgramUtils.d.ts +39 -0
  209. package/dist/utils/ProgramUtils.d.ts.map +1 -0
  210. package/dist/utils/ProgramUtils.js +97 -0
  211. package/dist/utils/ProgramUtils.js.map +1 -0
  212. package/dist/utils/SwitchUtils.d.ts +21 -0
  213. package/dist/utils/SwitchUtils.d.ts.map +1 -0
  214. package/dist/utils/SwitchUtils.js +47 -0
  215. package/dist/utils/SwitchUtils.js.map +1 -0
  216. package/dist/utils/TypeDeclUtils.d.ts +35 -0
  217. package/dist/utils/TypeDeclUtils.d.ts.map +1 -0
  218. package/dist/utils/TypeDeclUtils.js +78 -0
  219. package/dist/utils/TypeDeclUtils.js.map +1 -0
  220. package/dist/utils/VarUtils.d.ts +51 -0
  221. package/dist/utils/VarUtils.d.ts.map +1 -0
  222. package/dist/utils/VarUtils.js +91 -0
  223. package/dist/utils/VarUtils.js.map +1 -0
  224. package/package.json +16 -7
  225. package/src/MISRA.ts +33 -17
  226. package/src/MISRAContext.ts +128 -30
  227. package/src/MISRARule.ts +61 -29
  228. package/src/MISRATool.ts +126 -42
  229. package/src/StandardGuideline.ts +23 -0
  230. package/src/ast-visitor/Context.ts +16 -0
  231. package/src/ast-visitor/Visit.ts +26 -0
  232. package/src/ast-visitor/VisitWithContext.ts +42 -0
  233. package/src/main.ts +1 -4
  234. package/src/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.ts +114 -0
  235. package/src/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.ts +103 -13
  236. package/src/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.ts +24 -10
  237. package/src/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.ts +17 -8
  238. package/src/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.ts +20 -12
  239. package/src/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.ts +23 -12
  240. package/src/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.ts +44 -13
  241. package/src/rules/Section17_Functions/Rule_17_3_ImplicitFunction.ts +153 -104
  242. package/src/rules/Section17_Functions/Rule_17_4_NonVoidReturn.ts +114 -44
  243. package/src/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.ts +27 -10
  244. package/src/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.ts +20 -12
  245. package/src/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.ts +317 -0
  246. package/src/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.ts +30 -0
  247. package/src/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.ts +35 -0
  248. package/src/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.ts +30 -0
  249. package/src/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.ts +30 -0
  250. package/src/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.ts +29 -0
  251. package/src/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.ts +36 -0
  252. package/src/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.ts +30 -0
  253. package/src/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.ts +14 -29
  254. package/src/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.ts +33 -19
  255. package/src/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.ts +33 -20
  256. package/src/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.ts +90 -45
  257. package/src/rules/Section3_Comments/Rule_3_1_CommentSequences.ts +27 -8
  258. package/src/rules/Section5_Identifiers/IdentifierRenameRule.ts +63 -0
  259. package/src/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.ts +52 -0
  260. package/src/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.ts +62 -0
  261. package/src/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.ts +61 -0
  262. package/src/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.ts +47 -0
  263. package/src/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.ts +47 -0
  264. package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.ts +118 -0
  265. package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.ts +89 -0
  266. package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.ts +65 -0
  267. package/src/rules/UserConfigurableRule.ts +60 -0
  268. package/src/rules/index.ts +45 -7
  269. package/src/tests/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.test.ts +114 -0
  270. package/src/tests/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.test.ts +7 -5
  271. package/src/tests/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.test.ts +40 -13
  272. package/src/tests/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.test.ts +10 -12
  273. package/src/tests/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.test.ts +5 -5
  274. package/src/tests/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.test.ts +5 -5
  275. package/src/tests/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.test.ts +5 -5
  276. package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions.test.ts +68 -40
  277. package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions_MissingConfig.test.ts +98 -0
  278. package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions_ProblematicConfig.test.ts +71 -0
  279. package/src/tests/Section17_Functions/Rule_17_4_NonVoidReturn.test.ts +103 -49
  280. package/src/tests/Section17_Functions/Rule_17_4_NonVoidReturn_MissingConfig.test.ts +7 -7
  281. package/src/tests/Section17_Functions/Rule_17_6_StaticArraySizeParam.test.ts +36 -7
  282. package/src/tests/Section17_Functions/Rule_17_7_UnusedReturnValue.test.ts +25 -21
  283. package/src/tests/Section17_Functions/misra_config.json +4 -3
  284. package/src/tests/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.test.ts +62 -0
  285. package/src/tests/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.test.ts +67 -0
  286. package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.test.ts +84 -0
  287. package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory_MissingConfig.test.ts +33 -0
  288. package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory_ProblematicConfig.test.ts +71 -0
  289. package/src/tests/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.test.ts +63 -0
  290. package/src/tests/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.test.ts +91 -0
  291. package/src/tests/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.test.ts +65 -0
  292. package/src/tests/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.test.ts +89 -0
  293. package/src/tests/Section21-StandardLibraries/misra_config.json +88 -0
  294. package/src/tests/Section21-StandardLibraries/problematic_misra_config.json +19 -0
  295. package/src/tests/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.test.ts +148 -113
  296. package/src/tests/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.test.ts +243 -163
  297. package/src/tests/Section2_UnusedCode/Rule_2_6_UnusedLabels.test.ts +32 -20
  298. package/src/tests/Section2_UnusedCode/Rule_2_7_UnusedParameters.test.ts +36 -30
  299. package/src/tests/Section3_Comments/Rule_3_1_CommentSequences.test.ts +37 -8
  300. package/src/tests/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.test.ts +78 -0
  301. package/src/tests/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.test.ts +120 -0
  302. package/src/tests/Section5_Identifiers/Rule_5_7_UniqueTagNames.test.ts +51 -0
  303. package/src/tests/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.test.ts +73 -0
  304. package/src/tests/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.test.ts +97 -0
  305. package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.test.ts +160 -0
  306. package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.test.ts +46 -0
  307. package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.test.ts +69 -0
  308. package/src/tests/utils.ts +32 -7
  309. package/src/utils/CallUtils.ts +37 -0
  310. package/src/utils/CommentUtils.ts +29 -0
  311. package/src/utils/FileUtils.ts +169 -0
  312. package/src/utils/FunctionUtils.ts +97 -0
  313. package/src/utils/IdentifierUtils.ts +142 -0
  314. package/src/utils/JoinpointUtils.ts +70 -0
  315. package/src/utils/ProgramUtils.ts +107 -0
  316. package/src/utils/SwitchUtils.ts +52 -0
  317. package/src/utils/TypeDeclUtils.ts +88 -0
  318. package/src/utils/VarUtils.ts +102 -0
  319. package/tsconfig.json +2 -1
  320. package/src/rules/Section20-PreprocessingDirectives/Rule_20_2_InvalidHeaderFileName.ts +0 -120
  321. package/src/rules/Section3_Comments/Rule_3_2_LineSplicing.ts +0 -36
  322. package/src/utils/utils.ts +0 -280
@@ -4,15 +4,38 @@ import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
4
4
  import { FileJp, Program } from "@specs-feup/clava/api/Joinpoints.js";
5
5
  import Query from "@specs-feup/lara/api/weaver/Query.js";
6
6
  import * as os from 'os';
7
+ import { resetCaches } from "../utils/ProgramUtils.js";
8
+
9
+ export function countMISRAErrors(): number;
10
+ export function countMISRAErrors(ruleID: string): number;
11
+ export function countMISRAErrors(startingPoint: FileJp | Program): number;
12
+ export function countMISRAErrors(startingPoint: FileJp | Program, ruleID: string): number;
13
+
14
+ export function countMISRAErrors(arg1?: FileJp | Program | string, arg2?: string): number {
15
+ let startingPoint: FileJp | Program;
16
+ let ruleID: string | undefined;
17
+
18
+ if (typeof arg1 === "string") {
19
+ ruleID = arg1;
20
+ startingPoint = Query.root() as Program;
21
+ } else {
22
+ startingPoint = arg1 ?? (Query.root() as Program);
23
+ ruleID = arg2;
24
+ }
7
25
 
8
- export function countMISRAErrors(startingPoint: FileJp | Program = Query.root() as Program): number {
9
26
  MISRATool.checkCompliance(startingPoint);
10
- return MISRATool.getErrorCount();
27
+
28
+ return ruleID ?
29
+ MISRATool.context.errors.filter(error => error.ruleID === ruleID).length :
30
+ MISRATool.getErrorCount();
11
31
  }
12
32
 
13
- export function countErrorsAfterCorrection(configPath?: string): number {
14
- MISRATool.applyCorrections(configPath);
15
- return MISRATool.getActiveErrorCount();
33
+ export function countErrorsAfterCorrection(ruleID?: string): number {
34
+ MISRATool.correctViolations();
35
+
36
+ return ruleID ?
37
+ MISRATool.context.activeErrors.filter(error => error.ruleID === ruleID).length :
38
+ MISRATool.getActiveErrorCount();
16
39
  }
17
40
 
18
41
  export interface TestFile {
@@ -21,11 +44,13 @@ export interface TestFile {
21
44
  path?: string
22
45
  }
23
46
 
24
- export function registerSourceCode(files: TestFile[]): void {
47
+ export function registerSourceCode(files: TestFile[], configPath?: string): void {
25
48
  beforeEach(() => {
26
- const dataStore = Clava.getData();
49
+ resetCaches();
27
50
 
51
+ const dataStore = Clava.getData();
28
52
  dataStore.setStandard(process.env.STD_VERSION!);
53
+ dataStore.put("argv", configPath ? `config=${configPath}` : undefined);
29
54
 
30
55
  // If running on macOS, change libcCxxMode
31
56
  if (os.platform() === 'darwin') {
@@ -0,0 +1,37 @@
1
+ import { Call, FileJp, FunctionJp, Varref } from "@specs-feup/clava/api/Joinpoints.js";
2
+ import Query from "@specs-feup/lara/api/weaver/Query.js";
3
+
4
+ /**
5
+ * Checks if the given joinpoint represents a call to an implicit function.
6
+ *
7
+ * @param callJp The call join point to analyze
8
+ */
9
+ export function isCallToImplicitFunction(callJp: Call): boolean {
10
+ if ( callJp.function?.isInSystemHeader) { // Call to system header function
11
+ return false;
12
+ }
13
+
14
+ const varrefs = Query.searchFrom(callJp, Varref, {isFunctionCall: false}).get().map(varRef => varRef.astId);
15
+ const args = new Set(callJp.argList.flatMap(arg => Query.searchFromInclusive(arg, Varref).get().map(varRef => varRef.astId)));
16
+ if (varrefs.length > 0 && !args.has(varrefs[0])) { // Call using function pointer
17
+ return false;
18
+ }
19
+
20
+ const directCallee = callJp.directCallee;
21
+ if (directCallee === undefined) return true;
22
+
23
+ const fileJp = directCallee.getAncestor("file");
24
+ if (fileJp === undefined) return true;
25
+
26
+ return Query.searchFrom(fileJp, FunctionJp, {name: callJp.name}).get().length === 0;
27
+ }
28
+
29
+ /**
30
+ * Computes the index of a call in a file
31
+ * @param fileJp The file to search in
32
+ * @param callJp The call to find
33
+ * @returns The index of the call or -1 if not found
34
+ */
35
+ export function getCallIndex(fileJp: FileJp, callJp: Call): number {
36
+ return Query.searchFrom(fileJp, Call, { name: callJp.name }).get().findIndex(c => c.equals(callJp));
37
+ }
@@ -0,0 +1,29 @@
1
+ import { Joinpoint, WrapperStmt, Comment } from "@specs-feup/clava/api/Joinpoints.js";
2
+
3
+ /**
4
+ * Checks if the comment is an inline comment
5
+ * @param $comment - The comment to check
6
+ * @returns Returns true if it's an inline comment, otherwise returns false
7
+ */
8
+ export function isInlineComment($comment: Comment): boolean {
9
+ return $comment.astName === "InlineComment";
10
+ }
11
+
12
+ /**
13
+ * Retrieves all comments associated with a given joinpoint
14
+ * @param $jp - The joinpoint to retrieve comments from
15
+ * @returns Array of comments
16
+ */
17
+ export function getComments($jp: Joinpoint): Comment[] {
18
+ return $jp instanceof Comment ? [$jp] : $jp.inlineComments;
19
+ }
20
+
21
+ /**
22
+ * Checks if a given join point is a comment statement
23
+ *
24
+ * @param $jp The join point to check
25
+ * @returns Returns true if the given join point is a comment statement, otherwise false
26
+ */
27
+ export function isCommentStmt($jp: Joinpoint): boolean {
28
+ return $jp instanceof WrapperStmt && $jp.kind === "comment";
29
+ }
@@ -0,0 +1,169 @@
1
+ import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
2
+ import { FileJp, Program, Include, Call, FunctionJp, Joinpoint, StorageClass } from "@specs-feup/clava/api/Joinpoints.js";
3
+ import Query from "@specs-feup/lara/api/weaver/Query.js";
4
+ import { isCallToImplicitFunction } from "./CallUtils.js";
5
+ import { isExternalLinkageIdentifier } from "./IdentifierUtils.js";
6
+ import path from "path";
7
+
8
+ /**
9
+ * Checks if a file compiles correctly after adding a statement by rebuilding it.
10
+ * If rebuilding fails, the file is considered invalid with the new statement.
11
+ *
12
+ * @param fileJp - The file to validate.
13
+ */
14
+ export function isValidFile(fileJp: FileJp, jpType?: typeof Joinpoint, index?: number) : boolean | Joinpoint | undefined {
15
+ let result: boolean | Joinpoint = true;
16
+
17
+ // Create a temporary copy of the file for validation
18
+ const programJp = fileJp.parent as Program;
19
+ let copyFile = ClavaJoinPoints.fileWithSource(`temp_misra_${fileJp.name}`, fileJp.code, fileJp.relativeFolderpath);
20
+ copyFile = programJp.addFile(copyFile) as FileJp;
21
+
22
+ try {
23
+ const rebuiltFile = copyFile.rebuild();
24
+ if (jpType && index) { // If requested, return a specific join point inside the rebuilt file
25
+ result = Query.searchFrom(rebuiltFile, jpType).get()[index];
26
+ }
27
+
28
+ // Remove the temporary file
29
+ const fileToRemove = Query.searchFrom(programJp, FileJp, {filepath: rebuiltFile.filepath}).first();
30
+ fileToRemove?.detach();
31
+ return result;
32
+ } catch(error) {
33
+ // On rebuild failure, delete copy file and return false
34
+ copyFile.detach();
35
+ return false;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Checks if the rebuilt version of the file compiles and if the provided call is no longer implicit.
41
+ *
42
+ * @param fileJp The file to analyze
43
+ * @param funcName The function name to search the call
44
+ * @param callIndex The index of the call
45
+ */
46
+ export function isValidFileWithExplicitCall(fileJp: FileJp, funcName: string, callIndex: number, checkNumParams: boolean = false): boolean {
47
+ const programJp = fileJp.parent as Program;
48
+
49
+ // Create a temporary copy of the file for validation
50
+ let copyFile = ClavaJoinPoints.fileWithSource(`temp_misra_${fileJp.name}`, fileJp.code, fileJp.relativeFolderpath);
51
+ copyFile = programJp.addFile(copyFile) as FileJp;
52
+
53
+ try {
54
+ // Rebuild the file to check validity
55
+ const rebuiltFile = copyFile.rebuild();
56
+ const fileToRemove = Query.searchFrom(programJp, FileJp, {filepath: rebuiltFile.filepath}).first() as FileJp;
57
+
58
+ // Locate the function call and check if it is implicit
59
+ const callJp = Query.searchFrom(fileToRemove, Call, {name: funcName}).get().at(callIndex);
60
+ let isExplicitCall = callJp !== undefined && !isCallToImplicitFunction(callJp);
61
+
62
+ if (checkNumParams && isExplicitCall) {
63
+ isExplicitCall = isExplicitCall && callJp!.args.length === callJp!.directCallee.params.length;
64
+ }
65
+
66
+ // Remove the temporary file
67
+ fileToRemove?.detach();
68
+ return isExplicitCall;
69
+
70
+ } catch(error) { // On rebuild failure, delete copy file and return false
71
+ copyFile.detach();
72
+ return false;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Retrieves the list of header files included in the given file
78
+ *
79
+ * @param fileJp The file join point
80
+ * @returns An array of strings with the names of the includes
81
+ */
82
+ export function getIncludesOfFile(fileJp: FileJp): Set<string> {
83
+ return new Set(fileJp.includes.map(includeJp => includeJp.isAngled ? includeJp.name : path.basename(includeJp.name)));
84
+ }
85
+
86
+ /**
87
+ * Removes a specific include directive from the given file, if it exists
88
+ *
89
+ * @param includeName The name of the include to remove
90
+ * @param fileJp The file from which the include should be removed
91
+ */
92
+ export function removeIncludeFromFile(includeName: string, fileJp: FileJp) {
93
+ const include = Query.searchFrom(fileJp, Include, {name: includeName}).first();
94
+ include?.detach();
95
+ }
96
+
97
+ /**
98
+ * Returns all files in the program that include a given header file using the `#include` directive
99
+ *
100
+ * @param headerName - The name of the header file to search for
101
+ * @returns An array of files that include the specified header
102
+ */
103
+ export function findFilesReferencingHeader(headerName: string): FileJp[] {
104
+ return Query.search(FileJp, (jp) =>{ return getIncludesOfFile(jp).has(headerName)}).get();
105
+ }
106
+
107
+ /**
108
+ * Returns all files in the program that contain at least one call to an implicit function
109
+ *
110
+ * @param programJp - The program to analyze
111
+ * @returns A list of files with implicit function calls
112
+ */
113
+ export function getFilesWithCallToImplicitFunction(programJp: Program): FileJp[] {
114
+ const files = Query.searchFrom(programJp, FileJp).get();
115
+ return files.filter(
116
+ (fileJp) =>
117
+ Query.searchFrom(fileJp, Call, (callJp) =>
118
+ isCallToImplicitFunction(callJp)
119
+ ).get().length > 0
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Inserts an extern declaration of the given function into the file.
125
+ *
126
+ * @param fileJp The file to modify.
127
+ * @param functionJp The function to declare as extern.
128
+ * @returns The inserted join point, or undefined if the function has no external linkage.
129
+ */
130
+ export function addExternFunctionDecl(fileJp: FileJp, functionJp: FunctionJp): Joinpoint | undefined {
131
+ if (!isExternalLinkageIdentifier(functionJp)) {
132
+ return undefined;
133
+ }
134
+
135
+ let childAfterExtern: Joinpoint = fileJp.firstChild;
136
+
137
+ while(childAfterExtern instanceof Include) {
138
+ childAfterExtern = childAfterExtern.siblingsRight[0];
139
+ }
140
+
141
+ const externStr = `extern ${functionJp.getDeclaration(true)};`;
142
+ const externStmt = ClavaJoinPoints.stmtLiteral(externStr);
143
+ const newExternStmt = childAfterExtern.insertBefore(externStmt);
144
+ return newExternStmt;
145
+ }
146
+
147
+ /**
148
+ * Returns all extern function declarations in the given file
149
+ * @param fileJp The file join point
150
+ * @returns An array of functions declared with 'extern'
151
+ */
152
+ export function getExternFunctionDecls(fileJp: FileJp): FunctionJp[] {
153
+ return Query.searchFrom(fileJp, FunctionJp, {storageClass: StorageClass.EXTERN}).get();
154
+ }
155
+
156
+ /**
157
+ * Returns function calls from a file that are defined in the provided library header. Optionally filters by function names.
158
+ *
159
+ * @param fileJp The file join point
160
+ * @param libraryName Header filename
161
+ * @param functionNames Optional list of function names to filter
162
+ */
163
+ export function getCallsToLibrary(fileJp: FileJp, libraryName: string, functionNames: Set<string> = new Set()): Call[] {
164
+ return Query.searchFrom(fileJp, Call, (callJp) =>
165
+ callJp.function?.isInSystemHeader &&
166
+ callJp.function?.filepath.endsWith(libraryName) &&
167
+ (functionNames.size === 0 || functionNames.has(callJp.name))
168
+ ).get();
169
+ }
@@ -0,0 +1,97 @@
1
+ import { Param, Varref, FunctionJp, StorageClass, GotoStmt, LabelStmt, FileJp, Call, VariableArrayType } from "@specs-feup/clava/api/Joinpoints.js";
2
+ import Query from "@specs-feup/lara/api/weaver/Query.js";
3
+ import { findFilesReferencingHeader } from "./FileUtils.js";
4
+ import { hasDefinedType } from "./JoinpointUtils.js";
5
+
6
+ /**
7
+ * Gets direct references to a parameter within a function
8
+ * @param $param Parameter to find references for
9
+ * @param functionJp Function joinpoint to search in
10
+ */
11
+ export function getDirectParamReferences($param: Param, functionJp: FunctionJp): Varref[] {
12
+ return Query.searchFrom(functionJp, Varref, (ref) => { return ref.decl && ref.decl.astId === $param.astId}).get();
13
+ }
14
+
15
+ /**
16
+ * Gets variable references to a parameter inside Variable-Length Array (VLA) fields
17
+ * @param $param Parameter to find references for
18
+ * @param functionJp Function joinpoint to search in
19
+ */
20
+ export function getVLAFieldParamReferences($param: Param, functionJp: FunctionJp): Varref[] {
21
+ const vlaJoinpoints = functionJp.descendants.filter(jp => hasDefinedType(jp) && jp.type instanceof VariableArrayType);
22
+ const fieldsInVLAs = vlaJoinpoints.flatMap(jp => jp.jpFields(true).flatMap(field => [field, ...field.descendants]));
23
+
24
+ return fieldsInVLAs.filter(field => field instanceof Varref && field.decl?.astId === $param.astId) as Varref[];
25
+ }
26
+
27
+ /**
28
+ * Gets all unique variable references to a parameter in a function.
29
+ * @param $param Parameter to find references for
30
+ * @param functionJp Function joinpoint to search in
31
+ * @returns Array of unique Varref references
32
+ */
33
+ export function getParamReferences($param: Param, functionJp: FunctionJp): Varref[] {
34
+ const directRefs = getDirectParamReferences($param, functionJp);
35
+ const refsInVLAFields = getVLAFieldParamReferences($param, functionJp);
36
+
37
+ // Remove duplicated nodes
38
+ return Array.from(new Map([...directRefs, ...refsInVLAFields as Varref[]].map(ref => [ref.ast, ref])).values());
39
+ }
40
+
41
+ /**
42
+ * Gets all label statements in the given function that are never referenced
43
+ * @param func The function to analyze
44
+ * @returns An array of unused labels statements
45
+ */
46
+ export function getUnusedLabels(func: FunctionJp): LabelStmt[] {
47
+ return Query.searchFrom(func, LabelStmt).get().filter(label =>
48
+ Query.searchFrom(func, GotoStmt, { label: jp => jp.astId === label.decl.astId }).get().length === 0
49
+ );
50
+ }
51
+
52
+ /**
53
+ * Returns the first function definition matching the given name and file path suffix
54
+ *
55
+ * @param functionName Name of the function
56
+ * @param pathSuffix File path suffix
57
+ * @returns The function definition, or undefined if not found
58
+ */
59
+
60
+ export function findFunctionDef(functionName: string, pathSuffix: string) {
61
+ const funcDefs = Query.search(FunctionJp, (func) => {
62
+ try {
63
+ return func.name === functionName && func.isImplementation && func.filepath.endsWith(pathSuffix)
64
+ } catch (error) {
65
+ return false;
66
+ }
67
+ }).get();
68
+ return funcDefs.length > 0 ? funcDefs[0] : undefined;
69
+ }
70
+
71
+ /**
72
+ * Finds extern declarations for the given function
73
+ * @param functionJp The function join point
74
+ * @returns List of extern function declarations
75
+ */
76
+ export function findExternalFunctionDecl(functionJp: FunctionJp): FunctionJp[] {
77
+ return functionJp.declarationJps
78
+ .filter((declJp) => declJp.storageClass === StorageClass.EXTERN);
79
+ }
80
+
81
+ /**
82
+ * Checks if the given function is called anywhere in the project
83
+ * @param functionJp The function to evaluate
84
+ * @returns True if the function is used, false otherwise
85
+ */
86
+ export function isFunctionUsed(functionJp: FunctionJp): boolean {
87
+ const fileJp = functionJp.getAncestor("file") as FileJp;
88
+ let referencingFiles: FileJp[];
89
+
90
+ if (fileJp.isHeader) {
91
+ const filesWithInclude = findFilesReferencingHeader(fileJp.name);
92
+ referencingFiles = [fileJp, ...filesWithInclude];
93
+ } else {
94
+ referencingFiles = [fileJp];
95
+ }
96
+ return referencingFiles.some(fileJp => Query.searchFrom(fileJp, Call, {name: functionJp.name, directCallee: (jp) => jp?.ast === functionJp.ast}).get().length > 0)
97
+ }
@@ -0,0 +1,142 @@
1
+ import { Joinpoint, Vardecl, StorageClass, FunctionJp, TypedefDecl, LabelStmt, NamedDecl } from "@specs-feup/clava/api/Joinpoints.js";
2
+ import { compareLocation, isTagDecl } from "./JoinpointUtils.js";
3
+ import { findDuplicateVarDefinition, findExternalVarRefs, isSameVarDecl } from "./VarUtils.js";
4
+
5
+ /**
6
+ * Checks if the given joinpoint is an identifier declaration (variable, function, typedef, label, or tag)
7
+ *
8
+ * @param $jp The joinpoint to evaluate
9
+ * @returns True if the join point is an identifier declaration, false otherwise
10
+ */
11
+ export function isIdentifierDecl($jp: Joinpoint): boolean {
12
+ return ($jp instanceof Vardecl && $jp.storageClass !== StorageClass.EXTERN) ||
13
+ ($jp instanceof FunctionJp && $jp.isImplementation) ||
14
+ $jp instanceof TypedefDecl ||
15
+ $jp instanceof LabelStmt ||
16
+ isTagDecl($jp);
17
+ }
18
+
19
+ /**
20
+ * Retrieves the name of the given joinpoint
21
+ * @param $jp The joinpoint to evaluate
22
+ * @returns The name of the identifier, or undefined if the join point does not represent an identifier
23
+ */
24
+ export function getIdentifierName($jp: Joinpoint): string | undefined {
25
+ if ($jp instanceof NamedDecl) {
26
+ return $jp.name;
27
+ } else if ($jp instanceof LabelStmt) {
28
+ return $jp.decl.name;
29
+ }
30
+ return undefined;
31
+ }
32
+
33
+ /**
34
+ * Checks if two joinpoints represent different identifiers with the same name
35
+ * @param identifier1 The first joinpoint to evaluate
36
+ * @param identifier2 The second joinpoint to evaluate
37
+ * @returns True if names match and the nodes differ, otherwise returns false
38
+ */
39
+ export function areIdentifierNamesEqual(identifier1: Joinpoint, identifier2: Joinpoint) {
40
+ const name1 = getIdentifierName(identifier1);
41
+ const name2 = getIdentifierName(identifier2);
42
+
43
+ if (!name1 || !name2) return false;
44
+ return identifier1.ast !== identifier2.ast && name1 === name2;
45
+ }
46
+
47
+ /**
48
+ * Updates the name of an identifier joinpoint
49
+ * @param $jp The joinpoint to rename
50
+ * @param newName the new identifier name
51
+ * @returns True if renaming was successful, false otherwise
52
+ */
53
+ export function renameIdentifier($jp: Joinpoint, newName: string): boolean {
54
+ if ($jp instanceof LabelStmt) {
55
+ $jp.decl.setName(newName);
56
+ }
57
+ else if ($jp instanceof Vardecl) {
58
+ const externalRefs = findExternalVarRefs($jp);
59
+ const duplicateDefs = findDuplicateVarDefinition($jp);
60
+
61
+ $jp.setName(newName);
62
+ if (isExternalLinkageIdentifier($jp)) {
63
+ externalRefs.forEach((varRef) => varRef.setName(newName));
64
+ duplicateDefs.forEach((defJp) => defJp.setName(newName));
65
+ }
66
+ }
67
+ else if ($jp instanceof NamedDecl) {
68
+ $jp.setName(newName);
69
+ }
70
+ return true;
71
+ }
72
+
73
+ /**
74
+ * Checks if a given joinpoint represents an identifier with external linkage
75
+ *
76
+ * @param $jp The joinpoint to evaluate
77
+ * @returns True if the joinpoint has external linkage, false otherwise
78
+ */
79
+ export function isExternalLinkageIdentifier($jp: Joinpoint): boolean {
80
+ if (!($jp instanceof FunctionJp || $jp instanceof Vardecl)) {
81
+ return false;
82
+ }
83
+ let result = $jp.storageClass !== StorageClass.STATIC && $jp.storageClass !== StorageClass.EXTERN && $jp.getAncestor("function") === undefined;
84
+ if ($jp instanceof FunctionJp) {
85
+ result = result && $jp.isImplementation;
86
+ }
87
+ return result;
88
+ }
89
+
90
+ /**
91
+ * Checks if a given joinpoint represents an identifier with internal linkage
92
+ *
93
+ * @param $jp The joinpoint to evaluate
94
+ * @returns True if the joinpoint has internal linkage, false otherwise
95
+ */
96
+ export function isInternalLinkageIdentifier($jp: Joinpoint): boolean {
97
+ if (!($jp instanceof FunctionJp || $jp instanceof Vardecl)) {
98
+ return false;
99
+ }
100
+
101
+ let result = $jp.storageClass === StorageClass.STATIC && $jp.getAncestor("function") === undefined;
102
+ if ($jp instanceof FunctionJp) {
103
+ result = result && $jp.isImplementation;
104
+ }
105
+ return result;
106
+ }
107
+
108
+ /**
109
+ * Determines if an identifier is duplicated in a collection of join points
110
+ *
111
+ * @param $jp The identifier to evaluate
112
+ * @param $others Other join points to compare with
113
+ * @returns True if a duplicate exists, false otherwise
114
+ */
115
+ export function isIdentifierDuplicated($jp: Joinpoint, $others: Joinpoint[]) {
116
+ return $others.some((identifier) => identifier.astId !== $jp.astId && !isSameVarDecl($jp, identifier) && areIdentifierNamesEqual($jp, identifier));
117
+ }
118
+
119
+ /**
120
+ * Checks if another identifier with the same name is declared before the given joinpoint
121
+ *
122
+ * @param $jp The identifier join point to check
123
+ * @param $others The list of other identifiers to compare with
124
+ * @returns True if a matching identifier is declared earlier, false otherwise.
125
+ */
126
+
127
+ export function isIdentifierNameDeclaredBefore($jp: Joinpoint, $others: Joinpoint[]) {
128
+ return $others.some((identifier) => {
129
+ return identifier.astId !== $jp.astId && !isSameVarDecl($jp, identifier) && compareLocation(identifier, $jp) < 0 && areIdentifierNamesEqual(identifier, $jp)
130
+ });
131
+ }
132
+
133
+ /**
134
+ * @returns Returns true if the identifiers represent different AST nodes but are not distinct within the first 31 characters. Otherwise returns false.
135
+ */
136
+ export function areDistinctIdentifiers($jp1: Vardecl | FunctionJp, $jp2: Vardecl | FunctionJp): boolean {
137
+ try {
138
+ return $jp1.astId !== $jp2.ast && $jp1.name.substring(0, 31) !== $jp2.name.substring(0, 31);
139
+ } catch (error) {
140
+ return false;
141
+ }
142
+ }
@@ -0,0 +1,70 @@
1
+ import { Joinpoint, Type, PointerType, ArrayType, RecordJp, EnumDecl, DeclStmt, Program, QualType, Include } from "@specs-feup/clava/api/Joinpoints.js";
2
+
3
+ export type TagDecl = RecordJp | EnumDecl;
4
+
5
+ export function isTagDecl($jp: Joinpoint): $jp is TagDecl {
6
+ return $jp instanceof RecordJp || $jp instanceof EnumDecl;
7
+ }
8
+
9
+ /**
10
+ * Checks if the provided node has a defined type
11
+ * @param $jp The joinpoint to check its type
12
+ * @returns true if the joinpoint has a defined type, otherwise false
13
+ */
14
+ export function hasDefinedType($jp: Joinpoint): boolean {
15
+ return $jp.hasType && $jp.type !== null && $jp.type !== undefined;
16
+ }
17
+
18
+ /**
19
+ * Retrieves the base type of the provided joinpoint.
20
+ * @param $jp The joinpoint to retrieve its type
21
+ * @returns The base type of the joinpoint, or undefined if the joinpoint does not have a type
22
+ */
23
+ export function getBaseType($jp: Joinpoint): Type | undefined {
24
+ if (!hasDefinedType($jp)) return undefined;
25
+ let jpType = $jp.type instanceof QualType ? $jp.type.unqualifiedType : $jp.type;
26
+
27
+ while (jpType instanceof PointerType || jpType instanceof ArrayType) {
28
+ jpType = jpType instanceof PointerType ? jpType.pointee : jpType.elementType;
29
+ }
30
+ return jpType;
31
+ }
32
+
33
+ /**
34
+ * Gets the file path of the given join point.
35
+ * @param $jp The join point
36
+ * @returns The file path string
37
+ */
38
+ export function getFilepath($jp: Joinpoint): string {
39
+ return $jp instanceof Include ? $jp.parent.filepath : $jp.filepath;
40
+ }
41
+
42
+ /**
43
+ * Returns the exact location of a given join point
44
+ * @param $jp The joinpoint to evaluate
45
+ * @returns A location string containing the filepath, line and column in the format "filepath@line:column"
46
+ */
47
+ export function getFileLocation($jp: Joinpoint) {
48
+ if ($jp instanceof Include && $jp.line === undefined) {
49
+ return `${$jp.parent?.filepath}`;
50
+ }
51
+ return `${$jp.filepath}@${$jp.line}:${$jp.column}`
52
+ }
53
+
54
+ /**
55
+ * Orders two join points by their source location: filepath, line, and column
56
+ *
57
+ * @param $jp1 The first join point
58
+ * @param $jp2 The second join point
59
+ * @returns A negative value if $jp1 comes before $jp2, positive if after, or 0 if equal.
60
+ */
61
+ export function compareLocation($jp1: Joinpoint, $jp2: Joinpoint): number {
62
+ const filepath1 = getFilepath($jp1), filepath2 = getFilepath($jp2);
63
+
64
+ if (filepath1 !== filepath2) return getFileLocation($jp1).localeCompare(getFileLocation($jp2));
65
+
66
+ if (($jp1 instanceof Include) && !($jp2 instanceof Include)) return -1;
67
+ if (!($jp1 instanceof Include) && ($jp2 instanceof Include)) return 1;
68
+
69
+ return $jp1.line !== $jp2.line ? $jp1.line - $jp2.line : $jp1.column - $jp2.column;
70
+ }