@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
package/src/MISRA.ts CHANGED
@@ -1,9 +1,23 @@
1
- import { BinaryOp, Break, Case, Expression, If, Joinpoint, Program, Scope, Statement, Switch } from "@specs-feup/clava/api/Joinpoints.js";
2
- import { getNumOfSwitchClauses, isCommentStmt } from "./utils/utils.js";
1
+ import { BinaryOp, Break, Case, Expression, If, Joinpoint, Scope, Statement, Switch } from "@specs-feup/clava/api/Joinpoints.js";
2
+ import { isCommentStmt } from "./utils/CommentUtils.js";
3
3
  import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
4
4
  import Query from "@specs-feup/lara/api/weaver/Query.js";
5
- import Clava from "@specs-feup/clava/api/clava/Clava.js";
5
+ import { countSwitchClauses } from "./utils/SwitchUtils.js";
6
6
 
7
+ type NodeID = string;
8
+
9
+ /**
10
+ * Specifies whether a MISRA rule is applied to a single translation unit
11
+ * or requires analysis of the entire program.
12
+ */
13
+ export enum AnalysisType {
14
+ SINGLE_TRANSLATION_UNIT = "single",
15
+ SYSTEM = "system"
16
+ }
17
+
18
+ /**
19
+ * Types of transformations a rule can apply to a AST node.
20
+ */
7
21
  export enum MISRATransformationType {
8
22
  NoChange,
9
23
  DescendantChange,
@@ -11,32 +25,34 @@ export enum MISRATransformationType {
11
25
  Removal
12
26
  }
13
27
 
28
+ export type MISRATransformationResults = Map<NodeID, MISRATransformationType>;
29
+
14
30
  /**
15
- * Represents an error in MISRA compliance, including the rule ID, the joinpoint where the violation occurred, and a descriptive message.
31
+ * Represents a MISRA-C rule violation.
16
32
  */
17
33
  export class MISRAError {
18
34
  /**
19
35
  * Represents the specific MISRA-C rule that was violated
20
36
  */
21
- public ruleID: string;
37
+ public readonly ruleID: string;
22
38
  /**
23
39
  * The joinpoint where the error was detected
24
40
  */
25
- public $jp: Joinpoint;
41
+ public readonly joinpoint: Joinpoint;
26
42
  /**
27
43
  * Explanation of the violation
28
44
  */
29
- public message: string;
45
+ public readonly message: string;
30
46
 
31
47
  /**
32
48
  *
33
- * @param ruleID - specific MISRA rule that was violated
34
- * @param $jp - joinpoint where the error was detected
35
- * @param message - description of the error
49
+ * @param ruleID Identifier of the violated rule
50
+ * @param $jp Joinpoint where the error was detected
51
+ * @param message Description of the error
36
52
  */
37
53
  constructor(ruleID: string, $jp: Joinpoint, message: string) {
38
54
  this.ruleID = ruleID;
39
- this.$jp = $jp;
55
+ this.joinpoint = $jp;
40
56
  this.message = message;
41
57
  }
42
58
 
@@ -47,15 +63,15 @@ export class MISRAError {
47
63
  */
48
64
  equals(other: MISRAError): boolean {
49
65
  return this.ruleID === other.ruleID &&
50
- this.$jp.astId === other.$jp.astId &&
66
+ this.joinpoint.astId === other.joinpoint.astId &&
51
67
  this.message === other.message;
52
68
  }
53
69
 
54
70
  /**
55
- *
71
+ * Checks if the associated joinpoint is still present in program's AST
56
72
  */
57
73
  isActiveError(): boolean {
58
- return (Query.root() as Joinpoint).contains(this.$jp);
74
+ return (Query.root() as Joinpoint).contains(this.joinpoint);
59
75
  }
60
76
  }
61
77
 
@@ -68,11 +84,11 @@ export class MISRATransformationReport {
68
84
  /**
69
85
  * The type of the MISRA transformation
70
86
  */
71
- type: MISRATransformationType;
87
+ public readonly type: MISRATransformationType;
72
88
  /**
73
89
  * An optional new joinpoint node, provided if the transformation involves a replacement
74
90
  */
75
- newNode?: Joinpoint;
91
+ public readonly newNode?: Joinpoint;
76
92
 
77
93
  /**
78
94
  *
@@ -101,7 +117,7 @@ export class MISRASwitchConverter {
101
117
  * @returns The converted statements or `undefined` if no statements remain
102
118
  */
103
119
  static convert(switchStmt: Switch): Statement | undefined {
104
- if (switchStmt.hasDefaultCase && getNumOfSwitchClauses(switchStmt) < 2) { // The statements will always be executed
120
+ if (switchStmt.hasDefaultCase && countSwitchClauses(switchStmt) < 2) { // The statements will always be executed
105
121
  return this.convertToConsecutiveStmts(switchStmt);
106
122
  } else {
107
123
  return this.convertToIfStatements(switchStmt);
@@ -1,42 +1,77 @@
1
- import { Joinpoint } from "@specs-feup/clava/api/Joinpoints.js";
2
- import { MISRAError } from "./MISRA.js";
1
+ import { EnumDecl, FunctionJp, Joinpoint, LabelStmt, RecordJp, TypedefDecl, Vardecl } from "@specs-feup/clava/api/Joinpoints.js";
2
+ import { MISRAError, MISRATransformationResults, MISRATransformationType } from "./MISRA.js";
3
3
  import * as fs from 'fs';
4
+ import Context from "./ast-visitor/Context.js";
5
+ import { compareLocation, getFileLocation } from "./utils/JoinpointUtils.js";
4
6
 
5
7
  /**
6
- * Tracks MISRA errors and warnings during the analysis and/or transformation of the code.
7
- * Also generated unique variable and function names.
8
+ * Tracks MISRA-C violations during the analysis and/or transformation of the code.
9
+ * Also generates unique variable and function names.
8
10
  */
9
- export default class MISRAContext {
11
+ export default class MISRAContext extends Context<MISRATransformationResults> {
10
12
  /**
11
- * List of MISRA errors, that could not be resolved during the transformation process
13
+ * Stores MISRA-C rule violations.
14
+ *
15
+ * When checking compliance, this includes all detected violations.
16
+ * When performing transformations, it includes only the violations that could not be resolved.
12
17
  */
13
18
  #misraErrors: MISRAError[] = [];
19
+ #misraErrorKeys = new Set<string>();
14
20
 
15
21
  /**
16
- * Configuration provided by the user to assist in rule corrections
22
+ * User-provided configuration to assist in violation correction
17
23
  */
18
24
  #config: Map<string, any> | undefined = undefined;
19
25
 
20
26
  #varCounter = 0;
21
- #funcCounter = 0;
22
- #headerCounter = 0;
27
+ #functionCounter = 0;
28
+ #labelCounter = 0;
29
+ #typeDefCounter = 0;
30
+ #enumCounter = 0;
31
+ #structCounter = 0;
32
+ #unionCounter = 0;
23
33
 
24
- #varPrefix = "__misra_var_";
25
- #funcPrefix = "__misra_func_";
26
- #headerPrefix = "misra_hdr_";
34
+ #varPrefix = "_misra_var_";
35
+ #funcPrefix = "_misra_func_";
36
+ #labelPrefix = "_misra_label_";
37
+ #typeDefPrefix = "_misra_typedef_";
38
+ #enumPrefix = "_misra_enum_";
39
+ #structPrefix = "_misra_struct_";
40
+ #unionPrefix = "_misra_union_";
27
41
 
42
+ /**
43
+ * Returns all violations found in the source code.
44
+ */
28
45
  get errors(): MISRAError[] {
29
46
  return this.#misraErrors;
30
47
  }
31
48
 
49
+ /**
50
+ * Returns violations linked to nodes that are still present in the AST after correction.
51
+ */
32
52
  get activeErrors(): MISRAError[] {
33
53
  return this.#misraErrors.filter(error => error.isActiveError());
34
54
  }
35
55
 
56
+ /**
57
+ * Orders errors according to their location
58
+ */
59
+ private sortErrors(errors?: MISRAError[]) {
60
+ let errorList = errors ? errors : this.#misraErrors;
61
+ errorList.sort((error1, error2) => compareLocation(error1.joinpoint, error2.joinpoint));
62
+ }
63
+
64
+ /**
65
+ * Returns the user-provided configuration that assists in violation correction, if provided. Otherwise, returns undefined.
66
+ */
36
67
  get config(): Map<string, any> | undefined {
37
68
  return this.#config;
38
69
  }
39
70
 
71
+ /**
72
+ * Loads the JSON config file and transforms it into an internal Map representation.
73
+ * If the file does not exist, logs an error and exits the process.
74
+ */
40
75
  set config(configFilePath: string) {
41
76
  if (fs.existsSync(configFilePath)) {
42
77
  const data = fs.readFileSync(configFilePath, 'utf-8');
@@ -47,38 +82,101 @@ export default class MISRAContext {
47
82
  }
48
83
  }
49
84
 
50
- generateVarName() {
51
- return `${this.#varPrefix}${this.#varCounter++}`;
85
+ /**
86
+ * Clears stored information.
87
+ */
88
+ resetStorage() {
89
+ [...this.storage.keys()].forEach(key => {
90
+ this.storage.set(key, new Map())
91
+ });
92
+ this.#misraErrors = [];
93
+ this.#misraErrorKeys = new Set<string>();
52
94
  }
53
95
 
54
- generateFuncName() {
55
- return `${this.#funcPrefix}${this.#funcCounter++}`;
96
+ /**
97
+ * Returns the type of transformation applied by the specified rule to the given AST node.
98
+ * If no transformation was recorded, returns undefined.
99
+ *
100
+ * @param ruleID Identifier of the violated rule
101
+ * @param $jp AST node
102
+ * @returns The type of transformation applied, or undefined if none was recorded.
103
+ */
104
+ getRuleResult(ruleID: string, $jp: Joinpoint): MISRATransformationType | undefined {
105
+ return this.get(ruleID)?.get($jp.astId);
56
106
  }
57
107
 
58
- generateHeaderFilename() {
59
- return `${this.#headerPrefix}${this.#headerCounter++}.h`;
108
+ /**
109
+ * Registers the type of transformation a rule applied to a AST node
110
+ * @param ruleID Identifier of the violated rule
111
+ * @param $jp
112
+ * @param result Applied transformation
113
+ */
114
+ addRuleResult(ruleID: string, $jp: Joinpoint, result: MISRATransformationType) {
115
+ let transformations = this.get(ruleID);
116
+
117
+ if (transformations === undefined) {
118
+ transformations = new Map();
119
+ this.put(ruleID, transformations);
120
+ }
121
+ transformations.set($jp.astId, result);
60
122
  }
61
123
 
124
+ /**
125
+ * Registers a new violation of the standard
126
+ *
127
+ * @param ruleID Identifier of the violated rule
128
+ * @param $jp Joinpoint where the error was detected
129
+ * @param message Description of the error
130
+ */
62
131
  addMISRAError(ruleID: string, $jp: Joinpoint, message: string) {
63
- const newError = new MISRAError(ruleID, $jp, message);
132
+ const key = `${ruleID}-${$jp.astId}-${message}`;
133
+ if (!this.#misraErrorKeys.has(key)) {
134
+ this.#misraErrorKeys.add(key);
135
+ this.#misraErrors.push(new MISRAError(ruleID, $jp, message));
136
+ }
137
+ }
64
138
 
65
- if (!this.#misraErrors.some(error => error.equals(newError))) {
66
- this.#misraErrors.push(newError);
139
+ generateIdentifierName($jp: Joinpoint) {
140
+ if ($jp instanceof Vardecl) {
141
+ return `${this.#varPrefix}${this.#varCounter++}`;
142
+ } else if ($jp instanceof FunctionJp) {
143
+ return `${this.#funcPrefix}${this.#functionCounter++}`;
144
+ } else if ($jp instanceof LabelStmt) {
145
+ return `${this.#labelPrefix}${this.#labelCounter++}`;
146
+ } else if ($jp instanceof TypedefDecl) {
147
+ return `${this.#typeDefPrefix}${this.#typeDefCounter++}`;
148
+ } else if ($jp instanceof EnumDecl) {
149
+ return `${this.#enumPrefix}${this.#enumCounter++}`;
150
+ } else if ($jp instanceof RecordJp) {
151
+ return $jp.kind === `struct` ?
152
+ `${this.#structPrefix}${this.#structCounter++}` :
153
+ `${this.#unionPrefix}${this.#unionCounter++}`
67
154
  }
68
155
  }
69
156
 
70
- private printError(error: MISRAError): void {
71
- console.log(`MISRA-C Rule ${error.ruleID} violation at ${error.$jp.filepath}@${error.$jp.line}:${error.$jp.column}: ${error.message}\n`);
157
+ /**
158
+ * Outputs a formatted MISRA-C rule violation message
159
+ *
160
+ * @param error - The MISRA error object containing the rule ID, message, and location
161
+ */
162
+ private outputError(error: MISRAError): void {
163
+ console.log(`- [Rule ${error.ruleID}] at ${getFileLocation(error.joinpoint)}: ${error.message}\n`);
72
164
  }
73
165
 
74
- public printAllErrors(): void {
75
- this.#misraErrors.forEach(error => this.printError(error));
166
+ /**
167
+ * Displays all violations found in the source code.
168
+ */
169
+ outputAllErrors(): void {
170
+ this.sortErrors();
171
+ this.#misraErrors.forEach(error => this.outputError(error));
76
172
  }
77
173
 
78
- public printActiveErrors(): void {
79
- this.#misraErrors
80
- .filter(error => error.isActiveError())
81
- .forEach(error => this.printError(error));
174
+ /**
175
+ * Displays violations linked to nodes that are still present in the AST after correction.
176
+ */
177
+ outputActiveErrors(): void {
178
+ const errors = this.activeErrors;
179
+ this.sortErrors(errors);
180
+ errors.forEach(error => this.outputError(error));
82
181
  }
83
-
84
182
  }
package/src/MISRARule.ts CHANGED
@@ -1,56 +1,64 @@
1
- import { Joinpoint } from "@specs-feup/clava/api/Joinpoints.js";
1
+ import { Joinpoint, Program } from "@specs-feup/clava/api/Joinpoints.js";
2
2
  import MISRAContext from "./MISRAContext.js";
3
- import { MISRATransformationReport } from "./MISRA.js";
3
+ import { AnalysisType, MISRATransformationReport, MISRATransformationResults } from "./MISRA.js";
4
+ import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js";
5
+ import Clava from "@specs-feup/clava/api/clava/Clava.js";
6
+ import Query from "@specs-feup/lara/api/weaver/Query.js";
7
+ import { resetCaches } from "./utils/ProgramUtils.js";
8
+ import StandardGuideline from "./StandardGuideline.js";
4
9
 
5
10
  /**
6
11
  * Represents a MISRA Rule that detects and corrects violations in the code according to MISRA standards.
7
12
  *
8
- * Need to implement:
13
+ * Need to implement/define:
14
+ * - analysisType
15
+ * - name()
9
16
  * - match($jp, logErrors)
10
- * - transform($jp)
17
+ * - apply($jp)
11
18
  */
12
- export default abstract class MISRARule {
19
+ export default abstract class MISRARule extends StandardGuideline<MISRATransformationResults, MISRAContext> {
13
20
  /**
14
- * Unique identifier for the MISRA rule.
21
+ * A positive integer starting from 1 that indicates the rule's priority, determining the order in which rules are applied.
22
+ * By default, a rule has the lowest priority unless overridden.
15
23
  */
16
- readonly ruleID: string;
24
+ readonly priority: number = Number.MAX_VALUE;
17
25
 
18
26
  /**
19
- * Priority of the rule which is low by default.
27
+ * Scope of analysis: single unit or entire system.
20
28
  */
21
- readonly priority: number = 4;
22
-
23
- /**
24
- * MISRA context for error tracking and rule transformations state
25
- */
26
- protected context: MISRAContext;
29
+ abstract readonly analysisType: AnalysisType;
30
+
31
+ /**
32
+ * Standards to which this rule applies to
33
+ */
34
+ protected readonly appliesTo: Set<string> = new Set(["c90", "c99", "c11"]);
27
35
 
28
36
  /**
29
37
  *
30
- * @param ruleID - Unique identifier for the MISRA-C rule
31
38
  * @param context - MISRA context for error tracking and rule transformations state
32
39
  */
33
- constructor(ruleID: string, context: MISRAContext) {
34
- this.ruleID = ruleID;
35
- this.context = context;
40
+ constructor(context: MISRAContext) {
41
+ super(context);
36
42
  }
37
43
 
38
44
  /**
39
- * Checks if the joinpoint violates the rule
40
- *
41
- * @param $jp - Joinpoint to analyze
42
- * @param logErrors - [logErrors=false] - Whether to log errors if a violation is detected
43
- * @returns Returns true if the joinpoint violates the rule, false otherwise
45
+ * @returns Initial value stored in the shared context
44
46
  */
45
- abstract match($jp: Joinpoint, logErrors: boolean): boolean;
47
+ override initialValue(): MISRATransformationResults {
48
+ return new Map();
49
+ }
46
50
 
47
51
  /**
48
- * Transforms the joinpoint to comply with the MISRA-C rule
49
- *
50
- * @param $jp - Joinpoint to transform
51
- * @returns Report detailing the transformation result
52
+ * @returns Rule identifier according to MISRA-C:2012
52
53
  */
53
- abstract transform($jp: Joinpoint): MISRATransformationReport;
54
+ abstract override get name(): string;
55
+
56
+ /**
57
+ * An alias for 'name'
58
+ */
59
+ get ruleID(): string {
60
+ return this.name;
61
+ }
54
62
 
55
63
  /**
56
64
  * Logs a MISRA-C rule violation error
@@ -61,4 +69,28 @@ export default abstract class MISRARule {
61
69
  protected logMISRAError($jp: Joinpoint, msg:string): void {
62
70
  this.context.addMISRAError(this.ruleID, $jp, msg);
63
71
  }
72
+
73
+ /**
74
+ * Verifies if the rule applies to the standard being used
75
+ */
76
+ protected appliesToCurrentStandard(): boolean {
77
+ return this.appliesTo.has(Clava.getStandard());
78
+ }
79
+
80
+ /**
81
+ * Rebuilds the program based on the current AST, clears stored data in the shared context, and resets all caches
82
+ */
83
+ protected rebuildProgram() {
84
+ (Query.root() as Program).rebuild();
85
+ this.context.resetStorage();
86
+ resetCaches();
87
+ }
88
+
89
+ /**
90
+ * Transforms the joinpoint to comply with the MISRA-C rule
91
+ *
92
+ * @param $jp - Joinpoint to transform
93
+ * @returns Report detailing the transformation result
94
+ */
95
+ abstract apply($jp: LaraJoinPoint): MISRATransformationReport;
64
96
  }
package/src/MISRATool.ts CHANGED
@@ -1,33 +1,30 @@
1
1
  import Query from "@specs-feup/lara/api/weaver/Query.js";
2
- import { Call, FileJp, Joinpoint, Program } from "@specs-feup/clava/api/Joinpoints.js";
2
+ import { FileJp, FunctionJp, Joinpoint, Program } from "@specs-feup/clava/api/Joinpoints.js";
3
3
  import MISRARule from "./MISRARule.js";
4
- import sortRules from "./rules/index.js";
5
4
  import MISRAContext from "./MISRAContext.js";
6
- import { MISRAError, MISRATransformationType } from "./MISRA.js";
7
- import { isCallToImplicitFunction } from "./utils/utils.js";
5
+ import { MISRATransformationType } from "./MISRA.js";
6
+ import Clava from "@specs-feup/clava/api/clava/Clava.js";
7
+ import { resetCaches } from "./utils/ProgramUtils.js";
8
+ import { selectRules } from "./rules/index.js";
9
+ import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
10
+
11
+ enum ExecutionMode {
12
+ CORRECTION,
13
+ DETECTION
14
+ }
8
15
 
9
16
  export default class MISRATool {
10
17
  static #misraRules: MISRARule[];
11
- static #context: MISRAContext;
12
-
13
- private static init(startingPoint: FileJp | Program) {
14
- this.validateStdVersion(startingPoint);
15
- this.#context = new MISRAContext();
16
- this.#misraRules = sortRules(this.#context);
17
- }
18
-
19
- private static validateStdVersion(startingPoint: FileJp | Program) {
20
- const allowedVersions = ["c90", "c99", "c11"];
21
- const stdVersion = startingPoint instanceof Program ? startingPoint.standard : (startingPoint.root as Program).standard;
22
-
23
- if (!allowedVersions.includes(stdVersion)) {
24
- console.error(`[Clava-MISRATool] Invalid --std value. Allowed values: ${allowedVersions.join(", ")}`);
25
- process.exit(1);
26
- }
27
- }
18
+ public static context: MISRAContext;
19
+ static readonly #standards = new Set(["c90", "c99", "c11"]);
20
+ static readonly #ruleTypes = new Set(["all", "single", "system"]);
28
21
 
22
+ /**
23
+ * Checks whether the source code complies with MISRA C coding guidelines and reports all violations identified during the analysis
24
+ * @param startingPoint The AST node from which to start the analysis
25
+ */
29
26
  public static checkCompliance(startingPoint: Program | FileJp = Query.root() as Program) {
30
- this.init(startingPoint);
27
+ this.init();
31
28
 
32
29
  const nodes = [startingPoint, ...startingPoint.descendants];
33
30
  for (const node of nodes) {
@@ -35,39 +32,52 @@ export default class MISRATool {
35
32
  rule.match(node, true);
36
33
  }
37
34
  }
38
- if (this.#context.errors.length > 0) {
39
- this.#context.printAllErrors();
40
- } else {
41
- console.log("[Clava-MISRATool] No MISRA-C violations detected.");
42
- }
35
+ this.outputReport(ExecutionMode.DETECTION);
43
36
  }
44
37
 
45
- public static applyCorrections(configFilePath?: string) {
46
- this.init(Query.root() as Program);
38
+ /**
39
+ * Transforms the source code to comply with the coding guidelines.
40
+ * After the transformation, any violations that could not be fixed will be displayed along with their justification.
41
+ */
42
+ public static correctViolations() {
43
+ this.init();
44
+
45
+ // Store config file in context, if provided
46
+ const configFilePath = this.getArgValue("config");
47
47
  if (configFilePath) {
48
- this.#context.config = configFilePath;
48
+ this.context.config = configFilePath;
49
49
  }
50
50
 
51
+ // Correct violations
51
52
  let iteration = 0;
52
- let modified = false;
53
- do {
53
+ let modified = true;
54
+ while (modified) {
54
55
  console.log(`[Clava-MISRATool] Iteration #${++iteration}: Applying MISRA-C transformations...`);
55
56
  modified = this.transformAST(Query.root() as Program);
56
- } while(modified);
57
-
58
- if (this.#context.errors.length === 0) {
59
- console.log("[Clava-MISRATool] All detected violations were corrected.");
60
- } else {
61
- console.log("\n[Clava-MISRATool] Remaining MISRA-C violations:");
62
- this.#context.printActiveErrors();
63
57
  }
58
+
59
+ // Additional transformation: insert explicit 'void' in the argument list of functions with no parameters
60
+ const functionJps = Query.search(FunctionJp).get();
61
+ functionJps.forEach(functionJp => {
62
+ if (functionJp.params.length === 0) {
63
+ functionJp.addParam("", ClavaJoinPoints.builtinType("void"));
64
+ }
65
+ })
66
+
67
+ this.outputReport(ExecutionMode.CORRECTION);
64
68
  }
65
69
 
70
+ /**
71
+ * Recursively transforms the AST using a pre-order traversal
72
+ *
73
+ * @param $jp AST node from which to start the visit.
74
+ * @returns Return true if any modification was made (removal, replacement or changes in descendants). Otherwise, returns false.
75
+ */
66
76
  private static transformAST($jp: Joinpoint): boolean {
67
77
  let modified = false;
68
78
 
69
79
  for (const rule of this.#misraRules) {
70
- const transformReport = rule.transform($jp);
80
+ const transformReport = rule.apply($jp);
71
81
 
72
82
  if (transformReport.type !== MISRATransformationType.NoChange) {
73
83
  modified = true;
@@ -85,11 +95,85 @@ export default class MISRATool {
85
95
  return modified;
86
96
  }
87
97
 
98
+ /**
99
+ * Validates the C standard, creates a MISRA context, and initializes rules.
100
+ */
101
+ private static init() {
102
+ this.validateStdVersion();
103
+ this.context = new MISRAContext();
104
+ resetCaches();
105
+ this.initRules();
106
+ }
107
+
108
+ /**
109
+ * Selects applicable rules according to the analysis type. When not specified, both system and single translation unit rules are selected.
110
+ */
111
+ private static initRules() {
112
+ const typeStr = this.getArgValue("type", this.#ruleTypes) ?? "all";
113
+ this.#misraRules = selectRules(this.context, typeStr);
114
+ }
115
+
116
+ /**
117
+ * Checks whether the provided standard version is valid and supported
118
+ */
119
+ private static validateStdVersion() {
120
+ const stdVersion = (Query.root() as Program).standard;
121
+
122
+ if (!this.#standards.has(stdVersion)) {
123
+ console.error(`[Clava-MISRATool] Invalid -std value. Allowed values: ${[...this.#standards].join(", ")}`);
124
+ process.exit(1);
125
+ }
126
+ }
127
+
128
+ private static getArgValue(field: string, validValues?: Set<string>): string | undefined{
129
+ const args = Clava.getData().get("argv") as string;
130
+ if (!args) return undefined;
131
+
132
+ const pair = args.split(/\s+/).find(arg => arg.startsWith(field + "="));
133
+ if (!pair) return undefined;
134
+
135
+ const value = pair.split("=")[1];
136
+ if (validValues && !validValues.has(value)) {
137
+ console.error(`[Clava-MISRATool] Invalid '${field}' value. Allowed values: ${[...validValues].join(", ")}`);
138
+ process.exit(1);
139
+ }
140
+ return value;
141
+ }
142
+
143
+ /**
144
+ * Displays standard violations based on execution mode.
145
+ * - In detection mode, all violations are shown.
146
+ * - In correction mode, only the remaining violations are displayed
147
+ *
148
+ * @param mode execution mode
149
+ */
150
+ private static outputReport(mode: ExecutionMode) {
151
+ const isDetection = mode === ExecutionMode.DETECTION;
152
+ const errorCount = isDetection ? this.getErrorCount() : this.getActiveErrorCount();
153
+
154
+ if (errorCount > 0) {
155
+ console.log(isDetection
156
+ ? `[Clava-MISRATool] Detected ${errorCount} MISRA-C violation${errorCount === 1 ? "" : "s"}:\n`
157
+ : `[Clava-MISRATool] ${errorCount} MISRA-C violation${errorCount === 1 ? "" : "s"} remain${errorCount === 1 ? "s" : ""} after transformation:\n`
158
+ );
159
+ isDetection ? this.context.outputAllErrors() : this.context.outputActiveErrors();
160
+ }
161
+ else {
162
+ console.log(isDetection ? "[Clava-MISRATool] No MISRA-C violations detected.\n" : "[Clava-MISRATool] All detected violations were corrected.\n");
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @returns Returns the number of identified violations.
168
+ */
88
169
  public static getErrorCount(): number {
89
- return this.#context.errors.length;
170
+ return this.context.errors.length;
90
171
  }
91
172
 
173
+ /**
174
+ * @returns Returns the number of active errors linked to nodes that are still present in the AST after correction.
175
+ */
92
176
  public static getActiveErrorCount(): number {
93
- return this.#context.activeErrors.length;
177
+ return this.context.activeErrors.length;
94
178
  }
95
179
  }
@@ -0,0 +1,23 @@
1
+ import { Joinpoint } from "@specs-feup/clava/api/Joinpoints.js";
2
+ import Context from "./ast-visitor/Context.js";
3
+ import VisitWithContext from "./ast-visitor/VisitWithContext.js";
4
+
5
+ /**
6
+ * Represents a standard guideline that detects and corrects violations in the code according to a particular coding standard.
7
+ *
8
+ * Need to implement/define:
9
+ * - initialValue()
10
+ * - match($jp, logErrors)
11
+ * - apply($jp)
12
+ */
13
+ export default abstract class StandardGuideline<T,C extends Context<T> = Context<T>> extends VisitWithContext<T, C> {
14
+
15
+ /**
16
+ * Checks if the joinpoint violates the guideline
17
+ *
18
+ * @param $jp - Joinpoint to analyze
19
+ * @param logErrors - [logErrors=false] - Whether to log errors if a violation is detected
20
+ * @returns Returns true if the joinpoint violates the guideline, false otherwise
21
+ */
22
+ abstract match($jp: Joinpoint, logErrors: boolean): boolean;
23
+ }