@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.
- package/.gitignore +8 -0
- package/README.md +53 -19
- package/dist/MISRA.d.ts +28 -10
- package/dist/MISRA.d.ts.map +1 -1
- package/dist/MISRA.js +30 -10
- package/dist/MISRA.js.map +1 -1
- package/dist/MISRAContext.d.ts +65 -11
- package/dist/MISRAContext.d.ts.map +1 -1
- package/dist/MISRAContext.js +131 -35
- package/dist/MISRAContext.js.map +1 -1
- package/dist/MISRARule.d.ts +38 -25
- package/dist/MISRARule.d.ts.map +1 -1
- package/dist/MISRARule.js +40 -18
- package/dist/MISRARule.js.map +1 -1
- package/dist/MISRATool.d.ts +46 -5
- package/dist/MISRATool.d.ts.map +1 -1
- package/dist/MISRATool.js +118 -45
- package/dist/MISRATool.js.map +1 -1
- package/dist/StandardGuideline.d.ts +22 -0
- package/dist/StandardGuideline.d.ts.map +1 -0
- package/dist/StandardGuideline.js +12 -0
- package/dist/StandardGuideline.js.map +1 -0
- package/dist/ast-visitor/Context.d.ts +11 -0
- package/dist/ast-visitor/Context.d.ts.map +1 -0
- package/dist/ast-visitor/Context.js +15 -0
- package/dist/ast-visitor/Context.js.map +1 -0
- package/dist/ast-visitor/Visit.d.ts +23 -0
- package/dist/ast-visitor/Visit.d.ts.map +1 -0
- package/dist/ast-visitor/Visit.js +18 -0
- package/dist/ast-visitor/Visit.js.map +1 -0
- package/dist/ast-visitor/VisitWithContext.d.ts +32 -0
- package/dist/ast-visitor/VisitWithContext.d.ts.map +1 -0
- package/dist/ast-visitor/VisitWithContext.js +26 -0
- package/dist/ast-visitor/VisitWithContext.js.map +1 -0
- package/dist/main.js +1 -2
- package/dist/main.js.map +1 -1
- package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.d.ts +27 -0
- package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.d.ts.map +1 -0
- package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.js +98 -0
- package/dist/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.js.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.d.ts +45 -6
- package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.d.ts.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.js +91 -8
- package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.js.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.d.ts +15 -5
- package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.d.ts.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.js +20 -6
- package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.js.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.d.ts +11 -5
- package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.d.ts.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.js +13 -10
- package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.js.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.d.ts +11 -6
- package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.d.ts.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.js +19 -11
- package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.js.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.d.ts +15 -5
- package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.d.ts.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.js +24 -10
- package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.js.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.d.ts +22 -6
- package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.d.ts.map +1 -1
- package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.js +37 -10
- package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.js.map +1 -1
- package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.d.ts +66 -0
- package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.d.ts.map +1 -0
- package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.js +209 -0
- package/dist/rules/Section17_Functions/Rule_17_3_ImplicitFunction.js.map +1 -0
- package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.d.ts +37 -12
- package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.d.ts.map +1 -1
- package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.js +112 -39
- package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.js.map +1 -1
- package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.d.ts +15 -5
- package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.d.ts.map +1 -1
- package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.js +21 -7
- package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.js.map +1 -1
- package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.d.ts +11 -6
- package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.d.ts.map +1 -1
- package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.js +17 -8
- package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.js.map +1 -1
- package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.d.ts +105 -0
- package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.d.ts.map +1 -0
- package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.js +258 -0
- package/dist/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.js.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.d.ts +25 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.d.ts.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.js +27 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.js.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.d.ts +29 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.d.ts.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.js +31 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.js.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.d.ts +25 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.d.ts.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.js +27 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.js.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.d.ts +25 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.d.ts.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.js +27 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.js.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.d.ts +25 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.d.ts.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.js +27 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.js.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.d.ts +30 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.d.ts.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.js +32 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.js.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.d.ts +25 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.d.ts.map +1 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.js +27 -0
- package/dist/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.js.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.d.ts +6 -14
- package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.d.ts.map +1 -1
- package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.js +17 -27
- package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.js.map +1 -1
- package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.d.ts +13 -7
- package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.d.ts.map +1 -1
- package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.js +31 -17
- package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.js.map +1 -1
- package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.d.ts +26 -7
- package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.d.ts.map +1 -1
- package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.js +32 -14
- package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.js.map +1 -1
- package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.d.ts +48 -6
- package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.d.ts.map +1 -1
- package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.js +84 -34
- package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.js.map +1 -1
- package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.d.ts +24 -5
- package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.d.ts.map +1 -1
- package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.js +27 -7
- package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.js.map +1 -1
- package/dist/rules/Section5_Identifiers/IdentifierRenameRule.d.ts +46 -0
- package/dist/rules/Section5_Identifiers/IdentifierRenameRule.d.ts.map +1 -0
- package/dist/rules/Section5_Identifiers/IdentifierRenameRule.js +40 -0
- package/dist/rules/Section5_Identifiers/IdentifierRenameRule.js.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.d.ts +25 -0
- package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.d.ts.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.js +46 -0
- package/dist/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.js.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.d.ts +26 -0
- package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.d.ts.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.js +54 -0
- package/dist/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.js.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.d.ts +27 -0
- package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.d.ts.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.js +55 -0
- package/dist/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.js.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.d.ts +24 -0
- package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.d.ts.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.js +42 -0
- package/dist/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.js.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.d.ts +24 -0
- package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.d.ts.map +1 -0
- package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.js +42 -0
- package/dist/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.js.map +1 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.d.ts +35 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.d.ts.map +1 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.js +98 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.js.map +1 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.d.ts +35 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.d.ts.map +1 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.js +76 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.js.map +1 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.d.ts +32 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.d.ts.map +1 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.js +57 -0
- package/dist/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.js.map +1 -0
- package/dist/rules/UserConfigurableRule.d.ts +55 -0
- package/dist/rules/UserConfigurableRule.d.ts.map +1 -0
- package/dist/rules/UserConfigurableRule.js +16 -0
- package/dist/rules/UserConfigurableRule.js.map +1 -0
- package/dist/rules/index.d.ts +11 -18
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +47 -7
- package/dist/rules/index.js.map +1 -1
- package/dist/tests/Section17_Functions/misra_config.json +10 -0
- package/dist/tests/Section21-StandardLibraries/misra_config.json +88 -0
- package/dist/tests/Section21-StandardLibraries/problematic_misra_config.json +19 -0
- package/dist/tests/utils.d.ts +6 -3
- package/dist/tests/utils.d.ts.map +1 -1
- package/dist/tests/utils.js +33 -7
- package/dist/tests/utils.js.map +1 -1
- package/dist/utils/CallUtils.d.ts +15 -0
- package/dist/utils/CallUtils.d.ts.map +1 -0
- package/dist/utils/CallUtils.js +34 -0
- package/dist/utils/CallUtils.js.map +1 -0
- package/dist/utils/CommentUtils.d.ts +21 -0
- package/dist/utils/CommentUtils.d.ts.map +1 -0
- package/dist/utils/CommentUtils.js +27 -0
- package/dist/utils/CommentUtils.js.map +1 -0
- package/dist/utils/FileUtils.d.ts +67 -0
- package/dist/utils/FileUtils.d.ts.map +1 -0
- package/dist/utils/FileUtils.js +144 -0
- package/dist/utils/FileUtils.js.map +1 -0
- package/dist/utils/FunctionUtils.d.ts +47 -0
- package/dist/utils/FunctionUtils.d.ts.map +1 -0
- package/dist/utils/FunctionUtils.js +87 -0
- package/dist/utils/FunctionUtils.js.map +1 -0
- package/dist/utils/IdentifierUtils.d.ts +63 -0
- package/dist/utils/IdentifierUtils.d.ts.map +1 -0
- package/dist/utils/IdentifierUtils.js +133 -0
- package/dist/utils/IdentifierUtils.js.map +1 -0
- package/dist/utils/JoinpointUtils.d.ts +36 -0
- package/dist/utils/JoinpointUtils.d.ts.map +1 -0
- package/dist/utils/JoinpointUtils.js +63 -0
- package/dist/utils/JoinpointUtils.js.map +1 -0
- package/dist/utils/ProgramUtils.d.ts +39 -0
- package/dist/utils/ProgramUtils.d.ts.map +1 -0
- package/dist/utils/ProgramUtils.js +97 -0
- package/dist/utils/ProgramUtils.js.map +1 -0
- package/dist/utils/SwitchUtils.d.ts +21 -0
- package/dist/utils/SwitchUtils.d.ts.map +1 -0
- package/dist/utils/SwitchUtils.js +47 -0
- package/dist/utils/SwitchUtils.js.map +1 -0
- package/dist/utils/TypeDeclUtils.d.ts +35 -0
- package/dist/utils/TypeDeclUtils.d.ts.map +1 -0
- package/dist/utils/TypeDeclUtils.js +78 -0
- package/dist/utils/TypeDeclUtils.js.map +1 -0
- package/dist/utils/VarUtils.d.ts +51 -0
- package/dist/utils/VarUtils.d.ts.map +1 -0
- package/dist/utils/VarUtils.js +91 -0
- package/dist/utils/VarUtils.js.map +1 -0
- package/package.json +16 -7
- package/src/MISRA.ts +33 -17
- package/src/MISRAContext.ts +128 -30
- package/src/MISRARule.ts +61 -29
- package/src/MISRATool.ts +126 -42
- package/src/StandardGuideline.ts +23 -0
- package/src/ast-visitor/Context.ts +16 -0
- package/src/ast-visitor/Visit.ts +26 -0
- package/src/ast-visitor/VisitWithContext.ts +42 -0
- package/src/main.ts +1 -4
- package/src/rules/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.ts +114 -0
- package/src/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.ts +103 -13
- package/src/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.ts +24 -10
- package/src/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.ts +17 -8
- package/src/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.ts +20 -12
- package/src/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.ts +23 -12
- package/src/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.ts +44 -13
- package/src/rules/Section17_Functions/Rule_17_3_ImplicitFunction.ts +153 -104
- package/src/rules/Section17_Functions/Rule_17_4_NonVoidReturn.ts +114 -44
- package/src/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.ts +27 -10
- package/src/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.ts +20 -12
- package/src/rules/Section21-StandardLibraries/DisallowedStdLibFunctionRule.ts +317 -0
- package/src/rules/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.ts +30 -0
- package/src/rules/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.ts +35 -0
- package/src/rules/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.ts +30 -0
- package/src/rules/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.ts +30 -0
- package/src/rules/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.ts +29 -0
- package/src/rules/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.ts +36 -0
- package/src/rules/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.ts +30 -0
- package/src/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.ts +14 -29
- package/src/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.ts +33 -19
- package/src/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.ts +33 -20
- package/src/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.ts +90 -45
- package/src/rules/Section3_Comments/Rule_3_1_CommentSequences.ts +27 -8
- package/src/rules/Section5_Identifiers/IdentifierRenameRule.ts +63 -0
- package/src/rules/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.ts +52 -0
- package/src/rules/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.ts +62 -0
- package/src/rules/Section5_Identifiers/Rule_5_7_UniqueTagNames.ts +61 -0
- package/src/rules/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.ts +47 -0
- package/src/rules/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.ts +47 -0
- package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.ts +118 -0
- package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.ts +89 -0
- package/src/rules/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.ts +65 -0
- package/src/rules/UserConfigurableRule.ts +60 -0
- package/src/rules/index.ts +45 -7
- package/src/tests/Section13_SideEffects/Rule_13_6_SafeSizeOfOperand.test.ts +114 -0
- package/src/tests/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.test.ts +7 -5
- package/src/tests/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.test.ts +40 -13
- package/src/tests/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.test.ts +10 -12
- package/src/tests/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.test.ts +5 -5
- package/src/tests/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.test.ts +5 -5
- package/src/tests/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.test.ts +5 -5
- package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions.test.ts +68 -40
- package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions_MissingConfig.test.ts +98 -0
- package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions_ProblematicConfig.test.ts +71 -0
- package/src/tests/Section17_Functions/Rule_17_4_NonVoidReturn.test.ts +103 -49
- package/src/tests/Section17_Functions/Rule_17_4_NonVoidReturn_MissingConfig.test.ts +7 -7
- package/src/tests/Section17_Functions/Rule_17_6_StaticArraySizeParam.test.ts +36 -7
- package/src/tests/Section17_Functions/Rule_17_7_UnusedReturnValue.test.ts +25 -21
- package/src/tests/Section17_Functions/misra_config.json +4 -3
- package/src/tests/Section21-StandardLibraries/Rule_21_10_NoTimeDateFunctions.test.ts +62 -0
- package/src/tests/Section21-StandardLibraries/Rule_21_11_NoTgmathFunctions.test.ts +67 -0
- package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory.test.ts +84 -0
- package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory_MissingConfig.test.ts +33 -0
- package/src/tests/Section21-StandardLibraries/Rule_21_3_NoDynamicMemory_ProblematicConfig.test.ts +71 -0
- package/src/tests/Section21-StandardLibraries/Rule_21_6_NoStdIOFunctions.test.ts +63 -0
- package/src/tests/Section21-StandardLibraries/Rule_21_7_NoNumericStringConversions.test.ts +91 -0
- package/src/tests/Section21-StandardLibraries/Rule_21_8_NoProcessControlFunctions.test.ts +65 -0
- package/src/tests/Section21-StandardLibraries/Rule_21_9_NoGenericSearchOrSort.test.ts +89 -0
- package/src/tests/Section21-StandardLibraries/misra_config.json +88 -0
- package/src/tests/Section21-StandardLibraries/problematic_misra_config.json +19 -0
- package/src/tests/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.test.ts +148 -113
- package/src/tests/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.test.ts +243 -163
- package/src/tests/Section2_UnusedCode/Rule_2_6_UnusedLabels.test.ts +32 -20
- package/src/tests/Section2_UnusedCode/Rule_2_7_UnusedParameters.test.ts +36 -30
- package/src/tests/Section3_Comments/Rule_3_1_CommentSequences.test.ts +37 -8
- package/src/tests/Section5_Identifiers/Rule_5_1_DistinctExternalIdentifiers.test.ts +78 -0
- package/src/tests/Section5_Identifiers/Rule_5_6_UniqueTypedefNames.test.ts +120 -0
- package/src/tests/Section5_Identifiers/Rule_5_7_UniqueTagNames.test.ts +51 -0
- package/src/tests/Section5_Identifiers/Rule_5_8_UniqueExternalLinkIdentifiers.test.ts +73 -0
- package/src/tests/Section5_Identifiers/Rule_5_9_UniqueInternalLinkIdentifiers.test.ts +97 -0
- package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_6_SingleExternalDefinition.test.ts +160 -0
- package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_7_RestrictExternalLinkage.test.ts +46 -0
- package/src/tests/Section8_DeclarationsAndDefinitions/Rule_8_9_BlockScopeDefinition.test.ts +69 -0
- package/src/tests/utils.ts +32 -7
- package/src/utils/CallUtils.ts +37 -0
- package/src/utils/CommentUtils.ts +29 -0
- package/src/utils/FileUtils.ts +169 -0
- package/src/utils/FunctionUtils.ts +97 -0
- package/src/utils/IdentifierUtils.ts +142 -0
- package/src/utils/JoinpointUtils.ts +70 -0
- package/src/utils/ProgramUtils.ts +107 -0
- package/src/utils/SwitchUtils.ts +52 -0
- package/src/utils/TypeDeclUtils.ts +88 -0
- package/src/utils/VarUtils.ts +102 -0
- package/tsconfig.json +2 -1
- package/src/rules/Section20-PreprocessingDirectives/Rule_20_2_InvalidHeaderFileName.ts +0 -120
- package/src/rules/Section3_Comments/Rule_3_2_LineSplicing.ts +0 -36
- package/src/utils/utils.ts +0 -280
package/src/MISRA.ts
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
import { BinaryOp, Break, Case, Expression, If, Joinpoint,
|
|
2
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
34
|
-
* @param $jp
|
|
35
|
-
* @param message
|
|
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
|
|
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
|
|
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
|
|
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 &&
|
|
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);
|
package/src/MISRAContext.ts
CHANGED
|
@@ -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
|
|
7
|
-
* Also
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
#
|
|
22
|
-
#
|
|
27
|
+
#functionCounter = 0;
|
|
28
|
+
#labelCounter = 0;
|
|
29
|
+
#typeDefCounter = 0;
|
|
30
|
+
#enumCounter = 0;
|
|
31
|
+
#structCounter = 0;
|
|
32
|
+
#unionCounter = 0;
|
|
23
33
|
|
|
24
|
-
#varPrefix = "
|
|
25
|
-
#funcPrefix = "
|
|
26
|
-
#
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
55
|
-
|
|
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
|
-
|
|
59
|
-
|
|
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
|
|
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
|
-
|
|
66
|
-
|
|
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
|
-
|
|
71
|
-
|
|
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
|
-
|
|
75
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
-
* -
|
|
17
|
+
* - apply($jp)
|
|
11
18
|
*/
|
|
12
|
-
export default abstract class MISRARule {
|
|
19
|
+
export default abstract class MISRARule extends StandardGuideline<MISRATransformationResults, MISRAContext> {
|
|
13
20
|
/**
|
|
14
|
-
*
|
|
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
|
|
24
|
+
readonly priority: number = Number.MAX_VALUE;
|
|
17
25
|
|
|
18
26
|
/**
|
|
19
|
-
*
|
|
27
|
+
* Scope of analysis: single unit or entire system.
|
|
20
28
|
*/
|
|
21
|
-
readonly
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
*/
|
|
26
|
-
protected
|
|
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(
|
|
34
|
-
|
|
35
|
-
this.context = context;
|
|
40
|
+
constructor(context: MISRAContext) {
|
|
41
|
+
super(context);
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
/**
|
|
39
|
-
*
|
|
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
|
-
|
|
47
|
+
override initialValue(): MISRATransformationResults {
|
|
48
|
+
return new Map();
|
|
49
|
+
}
|
|
46
50
|
|
|
47
51
|
/**
|
|
48
|
-
*
|
|
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
|
|
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 {
|
|
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 {
|
|
7
|
-
import
|
|
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
|
|
12
|
-
|
|
13
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
46
|
-
|
|
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
|
|
48
|
+
this.context.config = configFilePath;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
// Correct violations
|
|
51
52
|
let iteration = 0;
|
|
52
|
-
let modified =
|
|
53
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
+
}
|