@specs-feup/clava-misra 1.0.0 → 1.0.2
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 +117 -0
- package/README.md +70 -15
- package/dist/MISRA.d.ts +129 -0
- package/dist/MISRA.d.ts.map +1 -0
- package/dist/MISRA.js +245 -0
- package/dist/MISRA.js.map +1 -0
- package/dist/MISRAContext.d.ts +21 -0
- package/dist/MISRAContext.d.ts.map +1 -0
- package/dist/MISRAContext.js +75 -0
- package/dist/MISRAContext.js.map +1 -0
- package/dist/MISRARule.d.ts +56 -0
- package/dist/MISRARule.d.ts.map +1 -0
- package/dist/MISRARule.js +45 -0
- package/dist/MISRARule.js.map +1 -0
- package/dist/MISRATool.d.ts +12 -0
- package/dist/MISRATool.d.ts.map +1 -0
- package/dist/MISRATool.js +84 -0
- package/dist/MISRATool.js.map +1 -0
- package/dist/foo.d.ts +2 -0
- package/dist/foo.d.ts.map +1 -0
- package/{src/foo.ts → dist/foo.js} +3 -2
- package/dist/foo.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +5 -0
- package/dist/main.js.map +1 -0
- package/dist/misra/MISRAAnalyser.d.ts +14 -0
- package/dist/misra/MISRAAnalyser.d.ts.map +1 -0
- package/{src/misra/MISRAAnalyser.ts → dist/misra/MISRAAnalyser.js} +13 -23
- package/dist/misra/MISRAAnalyser.js.map +1 -0
- package/dist/misra/MISRAPass.d.ts +27 -0
- package/dist/misra/MISRAPass.d.ts.map +1 -0
- package/dist/misra/MISRAPass.js +60 -0
- package/dist/misra/MISRAPass.js.map +1 -0
- package/dist/misra/MISRAPassResult.d.ts +13 -0
- package/dist/misra/MISRAPassResult.d.ts.map +1 -0
- package/dist/misra/MISRAPassResult.js +11 -0
- package/dist/misra/MISRAPassResult.js.map +1 -0
- package/dist/misra/MISRAReporter.d.ts +20 -0
- package/dist/misra/MISRAReporter.d.ts.map +1 -0
- package/dist/misra/MISRAReporter.js +43 -0
- package/dist/misra/MISRAReporter.js.map +1 -0
- package/dist/misra/passes/S10_EssentialTypePass.d.ts +42 -0
- package/dist/misra/passes/S10_EssentialTypePass.d.ts.map +1 -0
- package/dist/misra/passes/S10_EssentialTypePass.js +370 -0
- package/dist/misra/passes/S10_EssentialTypePass.js.map +1 -0
- package/dist/misra/passes/S12_ExpressionPass.d.ts +18 -0
- package/dist/misra/passes/S12_ExpressionPass.d.ts.map +1 -0
- package/dist/misra/passes/S12_ExpressionPass.js +72 -0
- package/dist/misra/passes/S12_ExpressionPass.js.map +1 -0
- package/dist/misra/passes/S13_SideEffectPass.d.ts +18 -0
- package/dist/misra/passes/S13_SideEffectPass.d.ts.map +1 -0
- package/dist/misra/passes/S13_SideEffectPass.js +105 -0
- package/dist/misra/passes/S13_SideEffectPass.js.map +1 -0
- package/dist/misra/passes/S15_ControlFlowPass.d.ts +19 -0
- package/dist/misra/passes/S15_ControlFlowPass.d.ts.map +1 -0
- package/dist/misra/passes/S15_ControlFlowPass.js +94 -0
- package/dist/misra/passes/S15_ControlFlowPass.js.map +1 -0
- package/dist/misra/passes/S16_SwitchStatementPass.d.ts +17 -0
- package/dist/misra/passes/S16_SwitchStatementPass.d.ts.map +1 -0
- package/dist/misra/passes/S16_SwitchStatementPass.js +152 -0
- package/dist/misra/passes/S16_SwitchStatementPass.js.map +1 -0
- package/dist/misra/passes/S17_FunctionPass.d.ts +12 -0
- package/dist/misra/passes/S17_FunctionPass.d.ts.map +1 -0
- package/dist/misra/passes/S17_FunctionPass.js +38 -0
- package/dist/misra/passes/S17_FunctionPass.js.map +1 -0
- package/dist/misra/passes/S18_PointersArraysPass.d.ts +17 -0
- package/dist/misra/passes/S18_PointersArraysPass.d.ts.map +1 -0
- package/dist/misra/passes/S18_PointersArraysPass.js +115 -0
- package/dist/misra/passes/S18_PointersArraysPass.js.map +1 -0
- package/dist/misra/passes/S19_OverlappingStoragePass.d.ts +11 -0
- package/dist/misra/passes/S19_OverlappingStoragePass.d.ts.map +1 -0
- package/dist/misra/passes/S19_OverlappingStoragePass.js +20 -0
- package/dist/misra/passes/S19_OverlappingStoragePass.js.map +1 -0
- package/dist/misra/passes/S21_StandardLibPass.d.ts +20 -0
- package/dist/misra/passes/S21_StandardLibPass.d.ts.map +1 -0
- package/dist/misra/passes/S21_StandardLibPass.js +77 -0
- package/dist/misra/passes/S21_StandardLibPass.js.map +1 -0
- package/dist/misra/passes/S3_CommentPass.d.ts +12 -0
- package/dist/misra/passes/S3_CommentPass.d.ts.map +1 -0
- package/dist/misra/passes/S3_CommentPass.js +27 -0
- package/dist/misra/passes/S3_CommentPass.js.map +1 -0
- package/dist/misra/passes/S5_IdentifierPass.d.ts +13 -0
- package/dist/misra/passes/S5_IdentifierPass.d.ts.map +1 -0
- package/dist/misra/passes/S5_IdentifierPass.js +60 -0
- package/dist/misra/passes/S5_IdentifierPass.js.map +1 -0
- package/dist/misra/passes/S6_TypePass.d.ts +11 -0
- package/dist/misra/passes/S6_TypePass.d.ts.map +1 -0
- package/dist/misra/passes/S6_TypePass.js +25 -0
- package/dist/misra/passes/S6_TypePass.js.map +1 -0
- package/dist/misra/passes/S7_LiteralsConstantsPass.d.ts +14 -0
- package/dist/misra/passes/S7_LiteralsConstantsPass.d.ts.map +1 -0
- package/dist/misra/passes/S7_LiteralsConstantsPass.js +71 -0
- package/dist/misra/passes/S7_LiteralsConstantsPass.js.map +1 -0
- package/dist/misra/passes/S8_DeclDefPass.d.ts +18 -0
- package/dist/misra/passes/S8_DeclDefPass.d.ts.map +1 -0
- package/dist/misra/passes/S8_DeclDefPass.js +127 -0
- package/dist/misra/passes/S8_DeclDefPass.js.map +1 -0
- package/dist/misra/sections/Section10_EssentialTypeModel.d.ts +33 -0
- package/dist/misra/sections/Section10_EssentialTypeModel.d.ts.map +1 -0
- package/{src/misra/sections/Section10_EssentialTypeModel.ts → dist/misra/sections/Section10_EssentialTypeModel.js} +58 -73
- package/dist/misra/sections/Section10_EssentialTypeModel.js.map +1 -0
- package/dist/misra/sections/Section11_PointerTypeConversions.d.ts +12 -0
- package/dist/misra/sections/Section11_PointerTypeConversions.d.ts.map +1 -0
- package/{src/misra/sections/Section11_PointerTypeConversions.ts → dist/misra/sections/Section11_PointerTypeConversions.js} +16 -27
- package/dist/misra/sections/Section11_PointerTypeConversions.js.map +1 -0
- package/dist/misra/sections/Section12_Expressions.d.ts +15 -0
- package/dist/misra/sections/Section12_Expressions.d.ts.map +1 -0
- package/dist/misra/sections/Section12_Expressions.js +70 -0
- package/dist/misra/sections/Section12_Expressions.js.map +1 -0
- package/dist/misra/sections/Section13_SideEffects.d.ts +14 -0
- package/dist/misra/sections/Section13_SideEffects.d.ts.map +1 -0
- package/dist/misra/sections/Section13_SideEffects.js +90 -0
- package/dist/misra/sections/Section13_SideEffects.js.map +1 -0
- package/dist/misra/sections/Section14_ControlStmtExprs.d.ts +8 -0
- package/dist/misra/sections/Section14_ControlStmtExprs.d.ts.map +1 -0
- package/{src/misra/sections/Section14_ControlStmtExprs.ts → dist/misra/sections/Section14_ControlStmtExprs.js} +8 -10
- package/dist/misra/sections/Section14_ControlStmtExprs.js.map +1 -0
- package/dist/misra/sections/Section15_ControlFlow.d.ts +14 -0
- package/dist/misra/sections/Section15_ControlFlow.d.ts.map +1 -0
- package/dist/misra/sections/Section15_ControlFlow.js +97 -0
- package/dist/misra/sections/Section15_ControlFlow.js.map +1 -0
- package/dist/misra/sections/Section16_SwitchStatements.d.ts +13 -0
- package/dist/misra/sections/Section16_SwitchStatements.d.ts.map +1 -0
- package/{src/misra/sections/Section16_SwitchStatements.ts → dist/misra/sections/Section16_SwitchStatements.js} +49 -74
- package/dist/misra/sections/Section16_SwitchStatements.js.map +1 -0
- package/dist/misra/sections/Section17_Functions.d.ts +9 -0
- package/dist/misra/sections/Section17_Functions.d.ts.map +1 -0
- package/{src/misra/sections/Section17_Functions.ts → dist/misra/sections/Section17_Functions.js} +10 -13
- package/dist/misra/sections/Section17_Functions.js.map +1 -0
- package/dist/misra/sections/Section18_PointersAndArrays.d.ts +13 -0
- package/dist/misra/sections/Section18_PointersAndArrays.d.ts.map +1 -0
- package/{src/misra/sections/Section18_PointersAndArrays.ts → dist/misra/sections/Section18_PointersAndArrays.js} +36 -40
- package/dist/misra/sections/Section18_PointersAndArrays.js.map +1 -0
- package/dist/misra/sections/Section19_OverlappingStorage.d.ts +8 -0
- package/dist/misra/sections/Section19_OverlappingStorage.d.ts.map +1 -0
- package/dist/misra/sections/Section19_OverlappingStorage.js +16 -0
- package/dist/misra/sections/Section19_OverlappingStorage.js.map +1 -0
- package/dist/misra/sections/Section20_PreprocessingDirectives.d.ts +8 -0
- package/dist/misra/sections/Section20_PreprocessingDirectives.d.ts.map +1 -0
- package/{src/misra/sections/Section20_PreprocessingDirectives.ts → dist/misra/sections/Section20_PreprocessingDirectives.js} +7 -9
- package/dist/misra/sections/Section20_PreprocessingDirectives.js.map +1 -0
- package/dist/misra/sections/Section21_StandardLibraries.d.ts +17 -0
- package/dist/misra/sections/Section21_StandardLibraries.d.ts.map +1 -0
- package/dist/misra/sections/Section21_StandardLibraries.js +54 -0
- package/dist/misra/sections/Section21_StandardLibraries.js.map +1 -0
- package/dist/misra/sections/Section2_UnusedCode.d.ts +9 -0
- package/dist/misra/sections/Section2_UnusedCode.d.ts.map +1 -0
- package/{src/misra/sections/Section2_UnusedCode.ts → dist/misra/sections/Section2_UnusedCode.js} +11 -16
- package/dist/misra/sections/Section2_UnusedCode.js.map +1 -0
- package/dist/misra/sections/Section3_Comments.d.ts +9 -0
- package/dist/misra/sections/Section3_Comments.d.ts.map +1 -0
- package/{src/misra/sections/Section3_Comments.ts → dist/misra/sections/Section3_Comments.js} +7 -10
- package/dist/misra/sections/Section3_Comments.js.map +1 -0
- package/dist/misra/sections/Section5_Identifiers.d.ts +12 -0
- package/dist/misra/sections/Section5_Identifiers.d.ts.map +1 -0
- package/dist/misra/sections/Section5_Identifiers.js +139 -0
- package/dist/misra/sections/Section5_Identifiers.js.map +1 -0
- package/dist/misra/sections/Section6_Types.d.ts +8 -0
- package/dist/misra/sections/Section6_Types.d.ts.map +1 -0
- package/dist/misra/sections/Section6_Types.js +23 -0
- package/dist/misra/sections/Section6_Types.js.map +1 -0
- package/dist/misra/sections/Section7_LiteralsConstants.d.ts +11 -0
- package/dist/misra/sections/Section7_LiteralsConstants.d.ts.map +1 -0
- package/{src/misra/sections/Section7_LiteralsConstants.ts → dist/misra/sections/Section7_LiteralsConstants.js} +18 -25
- package/dist/misra/sections/Section7_LiteralsConstants.js.map +1 -0
- package/dist/misra/sections/Section8_DeclarationsDefinitions.d.ts +15 -0
- package/dist/misra/sections/Section8_DeclarationsDefinitions.d.ts.map +1 -0
- package/{src/misra/sections/Section8_DeclarationsDefinitions.ts → dist/misra/sections/Section8_DeclarationsDefinitions.js} +18 -33
- package/dist/misra/sections/Section8_DeclarationsDefinitions.js.map +1 -0
- package/dist/misra/tests/utils.d.ts +10 -0
- package/dist/misra/tests/utils.d.ts.map +1 -0
- package/dist/misra/tests/utils.js +33 -0
- package/dist/misra/tests/utils.js.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.d.ts +15 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.d.ts.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.js +33 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.js.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.d.ts +16 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.d.ts.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.js +60 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.js.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.d.ts +19 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.d.ts.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.js +42 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.js.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.d.ts +43 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.d.ts.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.js +103 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.js.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.d.ts +26 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.d.ts.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.js +49 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.js.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.d.ts +26 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.d.ts.map +1 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.js +49 -0
- package/dist/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.js.map +1 -0
- package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.d.ts +31 -0
- package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.d.ts.map +1 -0
- package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.js +71 -0
- package/dist/rules/Section17_Functions/Rule_17_4_NonVoidReturn.js.map +1 -0
- package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.d.ts +27 -0
- package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.d.ts.map +1 -0
- package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.js +58 -0
- package/dist/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.js.map +1 -0
- package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.d.ts +28 -0
- package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.d.ts.map +1 -0
- package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.js +44 -0
- package/dist/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.js.map +1 -0
- package/dist/rules/Section20-PreprocessingDirectives/Rule_20_2_InvalidHeaderFileName.d.ts +55 -0
- package/dist/rules/Section20-PreprocessingDirectives/Rule_20_2_InvalidHeaderFileName.d.ts.map +1 -0
- package/dist/rules/Section20-PreprocessingDirectives/Rule_20_2_InvalidHeaderFileName.js +108 -0
- package/dist/rules/Section20-PreprocessingDirectives/Rule_20_2_InvalidHeaderFileName.js.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.d.ts +43 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.d.ts.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.js +68 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.js.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.d.ts +29 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.d.ts.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.js +53 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.js.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.d.ts +15 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.d.ts.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.js +35 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.js.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.d.ts +13 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.d.ts.map +1 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.js +53 -0
- package/dist/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.js.map +1 -0
- package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.d.ts +13 -0
- package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.d.ts.map +1 -0
- package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.js +32 -0
- package/dist/rules/Section3_Comments/Rule_3_1_CommentSequences.js.map +1 -0
- package/dist/rules/Section3_Comments/Rule_3_2_LineSplicing.d.ts +10 -0
- package/dist/rules/Section3_Comments/Rule_3_2_LineSplicing.d.ts.map +1 -0
- package/dist/rules/Section3_Comments/Rule_3_2_LineSplicing.js +26 -0
- package/dist/rules/Section3_Comments/Rule_3_2_LineSplicing.js.map +1 -0
- package/dist/rules/index.d.ts +20 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +38 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/tests/Section17_Functions/misra_config.json +10 -0
- package/dist/tests/utils.d.ts +10 -0
- package/dist/tests/utils.d.ts.map +1 -0
- package/dist/tests/utils.js +29 -0
- package/dist/tests/utils.js.map +1 -0
- package/dist/utils/utils.d.ts +102 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +202 -0
- package/dist/utils/utils.js.map +1 -0
- package/jest.config.js +6 -6
- package/package.json +44 -8
- package/src/MISRA.ts +276 -0
- package/src/MISRAContext.ts +84 -0
- package/src/MISRARule.ts +64 -0
- package/src/MISRATool.ts +95 -0
- package/src/main.ts +4 -33
- package/src/misra-old/MISRAAnalyser.ts +60 -0
- package/src/misra-old/MISRAAnalyserResult.ts +16 -0
- package/src/misra-old/sections/Section10_EssentialTypeModel.ts +377 -0
- package/src/misra-old/sections/Section11_PointerTypeConversions.ts +104 -0
- package/src/{misra → misra-old}/sections/Section12_Expressions.ts +7 -7
- package/src/{misra → misra-old}/sections/Section13_SideEffects.ts +15 -15
- package/src/misra-old/sections/Section14_ControlStmtExprs.ts +27 -0
- package/src/{misra → misra-old}/sections/Section15_ControlFlow.ts +10 -10
- package/src/misra-old/sections/Section18_PointersAndArrays.ts +108 -0
- package/src/{misra → misra-old}/sections/Section19_OverlappingStorage.ts +4 -4
- package/src/misra-old/sections/Section20_PreprocessingDirectives.ts +22 -0
- package/src/misra-old/sections/Section21_StandardLibraries.ts +99 -0
- package/src/{misra → misra-old}/sections/Section5_Identifiers.ts +16 -15
- package/src/{misra → misra-old}/sections/Section6_Types.ts +4 -4
- package/src/misra-old/sections/Section7_LiteralsConstants.ts +76 -0
- package/src/misra-old/sections/Section8_DeclarationsDefinitions.ts +133 -0
- package/src/rules/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.ts +41 -0
- package/src/rules/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.ts +70 -0
- package/src/rules/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.ts +41 -0
- package/src/rules/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.ts +113 -0
- package/src/rules/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.ts +61 -0
- package/src/rules/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.ts +57 -0
- package/src/rules/Section17_Functions/Rule_17_3_ImplicitFunction.ts +180 -0
- package/src/rules/Section17_Functions/Rule_17_4_NonVoidReturn.ts +91 -0
- package/src/rules/Section17_Functions/Rule_17_6_StaticArraySizeParam.ts +68 -0
- package/src/rules/Section17_Functions/Rule_17_7_UnusedReturnValue.ts +49 -0
- package/src/rules/Section20-PreprocessingDirectives/Rule_20_2_InvalidHeaderFileName.ts +120 -0
- package/src/rules/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.ts +78 -0
- package/src/rules/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.ts +61 -0
- package/src/rules/Section2_UnusedCode/Rule_2_6_UnusedLabels.ts +47 -0
- package/src/rules/Section2_UnusedCode/Rule_2_7_UnusedParameters.ts +67 -0
- package/src/rules/Section3_Comments/Rule_3_1_CommentSequences.ts +41 -0
- package/src/rules/Section3_Comments/Rule_3_2_LineSplicing.ts +36 -0
- package/src/rules/index.ts +44 -0
- package/src/tests/Section16_SwitchStatements/Rule_16_2_TopLevelSwitch.test.ts +55 -0
- package/src/tests/Section16_SwitchStatements/Rule_16_3_UnconditionalBreak.test.ts +70 -0
- package/src/tests/Section16_SwitchStatements/Rule_16_4_SwitchHasDefault.test.ts +128 -0
- package/src/tests/Section16_SwitchStatements/Rule_16_5_DefaultFirstOrLast.test.ts +132 -0
- package/src/tests/Section16_SwitchStatements/Rule_16_6_SwitchMinTwoClauses.test.ts +146 -0
- package/src/tests/Section16_SwitchStatements/Rule_16_7_NonBooleanSwitchCondition.test.ts +102 -0
- package/src/tests/Section17_Functions/Rule_17_3_ImplicitFunctions.test.ts +79 -0
- package/src/tests/Section17_Functions/Rule_17_4_NonVoidReturn.test.ts +98 -0
- package/src/tests/Section17_Functions/Rule_17_4_NonVoidReturn_MissingConfig.test.ts +77 -0
- package/src/tests/Section17_Functions/Rule_17_6_StaticArraySizeParam.test.ts +36 -0
- package/src/tests/Section17_Functions/Rule_17_7_UnusedReturnValue.test.ts +44 -0
- package/src/tests/Section17_Functions/misra_config.json +19 -0
- package/src/tests/Section2_UnusedCode/Rule_2_3_UnusedTypeDecl.test.ts +175 -0
- package/src/tests/Section2_UnusedCode/Rule_2_4_UnusedTagDecl.test.ts +219 -0
- package/src/tests/Section2_UnusedCode/Rule_2_6_UnusedLabels.test.ts +49 -0
- package/src/tests/Section2_UnusedCode/Rule_2_7_UnusedParameters.test.ts +55 -0
- package/src/tests/Section3_Comments/Rule_3_1_CommentSequences.test.ts +37 -0
- package/src/tests/utils.ts +51 -0
- package/src/utils/utils.ts +280 -0
- package/tsconfig.json +4 -3
- package/typedoc.config.js +1 -1
- package/CxxSources/lib.cpp +0 -3
- package/CxxSources/lib.h +0 -8
- package/CxxSources/main.cpp +0 -40
- package/TODO.md +0 -1
- package/consumer_order.txt +0 -2
- package/enum_integer_type.txt +0 -0
- package/is_temporary.txt +0 -0
- package/omp.txt +0 -0
- package/src/misra/passes/S16_SwitchStatementPass.ts +0 -168
- package/src/misra/passes/S3_CommentPass.ts +0 -40
- package/src/misra/sections/Section21_StandardLibraries.ts +0 -65
- package/src/misra/tests/S10_EssentialTypes.test.ts +0 -253
- package/src/misra/tests/S12_Expressions.test.ts +0 -43
- package/src/misra/tests/S13_SideEffects.test.ts +0 -77
- package/src/misra/tests/S15_ControlFlow.test.ts +0 -144
- package/src/misra/tests/S16_SwitchStatements.test.ts +0 -164
- package/src/misra/tests/S17_Functions.test.ts +0 -46
- package/src/misra/tests/S18_PointersArrays.test.ts +0 -167
- package/src/misra/tests/S19_OverlappingStorage.test.ts +0 -38
- package/src/misra/tests/S3_Comments.test.ts +0 -36
- package/src/misra/tests/S6_Types.test.ts +0 -36
- package/src/misra/tests/S7_LiteralsConstants.test.ts +0 -48
- package/src/misra/tests/utils.ts +0 -47
- package/types_with_templates.txt +0 -0
- /package/src/{misra → misra-old}/MISRAPass.ts +0 -0
- /package/src/{misra → misra-old}/MISRAPassResult.ts +0 -0
- /package/src/{misra → misra-old}/MISRAReporter.ts +0 -0
- /package/src/{misra → misra-old}/passes/S10_EssentialTypePass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S12_ExpressionPass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S13_SideEffectPass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S15_ControlFlowPass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S17_FunctionPass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S18_PointersArraysPass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S19_OverlappingStoragePass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S21_StandardLibPass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S5_IdentifierPass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S6_TypePass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S7_LiteralsConstantsPass.ts +0 -0
- /package/src/{misra → misra-old}/passes/S8_DeclDefPass.ts +0 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
import { Case, Joinpoint, Switch } from "@specs-feup/clava/api/Joinpoints.js";
|
2
|
+
import MISRARule from "../../MISRARule.js";
|
3
|
+
import MISRAContext from "../../MISRAContext.js";
|
4
|
+
import Query from "@specs-feup/lara/api/weaver/Query.js";
|
5
|
+
import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
|
6
|
+
|
7
|
+
/**
|
8
|
+
* MISRA Rule 16.2: A switch label shall only be used when the most closely-enclosing
|
9
|
+
compound statement is the body of a switch statement
|
10
|
+
*/
|
11
|
+
export default class Rule_16_2_TopLevelSwitch extends MISRARule {
|
12
|
+
priority = 2;
|
13
|
+
#misplacedCases: Case[] = [];
|
14
|
+
|
15
|
+
constructor(context: MISRAContext) {
|
16
|
+
super("16.2", context);
|
17
|
+
}
|
18
|
+
|
19
|
+
match($jp: Joinpoint, logErrors: boolean = false): boolean {
|
20
|
+
if (!($jp instanceof Switch)) return false;
|
21
|
+
|
22
|
+
this.#misplacedCases = Query.searchFrom($jp, Case).get()
|
23
|
+
.filter(caseLabel => !(caseLabel.currentRegion instanceof Switch));
|
24
|
+
|
25
|
+
if (logErrors) {
|
26
|
+
this.#misplacedCases.forEach(caseLabel =>
|
27
|
+
this.logMISRAError(caseLabel, "A switch label can only be used if its enclosing compound statement is the switch statement itself.")
|
28
|
+
);
|
29
|
+
}
|
30
|
+
return this.#misplacedCases.length > 0;
|
31
|
+
}
|
32
|
+
|
33
|
+
transform($jp: Joinpoint): MISRATransformationReport {
|
34
|
+
if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
|
35
|
+
|
36
|
+
for (const caseLabel of this.#misplacedCases) {
|
37
|
+
caseLabel.detach();
|
38
|
+
}
|
39
|
+
return new MISRATransformationReport(MISRATransformationType.DescendantChange);
|
40
|
+
}
|
41
|
+
}
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import { Break, Joinpoint, Statement, Switch, Case } from "@specs-feup/clava/api/Joinpoints.js";
|
2
|
+
import MISRARule from "../../MISRARule.js";
|
3
|
+
import MISRAContext from "../../MISRAContext.js";
|
4
|
+
import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
|
5
|
+
import { getLastStmtOfCase } from "../../utils/utils.js";
|
6
|
+
import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
|
7
|
+
|
8
|
+
/**
|
9
|
+
* MISRA Rule 16.3: An unconditional break statement shall terminate every switch-clause
|
10
|
+
*/
|
11
|
+
export default class Rule_16_3_UnconditionalBreak extends MISRARule {
|
12
|
+
priority = 2;
|
13
|
+
#statementsNeedingBreakAfter: Joinpoint[] = [];
|
14
|
+
|
15
|
+
constructor(context: MISRAContext) {
|
16
|
+
super("16.3", context);
|
17
|
+
}
|
18
|
+
|
19
|
+
match($jp: Joinpoint, logErrors: boolean = false): boolean {
|
20
|
+
if (!($jp instanceof Switch)) return false;
|
21
|
+
|
22
|
+
this.#statementsNeedingBreakAfter = $jp.cases.map(caseLabel => getLastStmtOfCase(caseLabel))
|
23
|
+
.filter(lastStmt => lastStmt && !(lastStmt instanceof Break)) as Joinpoint[];
|
24
|
+
|
25
|
+
if (logErrors) {
|
26
|
+
this.#statementsNeedingBreakAfter.forEach(stmt => {
|
27
|
+
this.logMISRAError(stmt, `Missing unconditional break after statement '${stmt.code}'`);
|
28
|
+
});
|
29
|
+
}
|
30
|
+
return this.#statementsNeedingBreakAfter.length > 0;
|
31
|
+
}
|
32
|
+
|
33
|
+
private getNextStatementsToExecute(jp: Joinpoint): Joinpoint[] {
|
34
|
+
let stmts = [];
|
35
|
+
|
36
|
+
for (const sibling of jp.siblingsRight) {
|
37
|
+
if (sibling instanceof Break)
|
38
|
+
break;
|
39
|
+
if (sibling instanceof Case)
|
40
|
+
continue;
|
41
|
+
stmts.push(sibling.deepCopy());
|
42
|
+
}
|
43
|
+
return stmts;
|
44
|
+
}
|
45
|
+
|
46
|
+
private insertNextStatementsToExecute(jp: Joinpoint) {
|
47
|
+
const nextStmts = this.getNextStatementsToExecute(jp);
|
48
|
+
let lastStmt = jp;
|
49
|
+
|
50
|
+
for (const stmt of nextStmts) {
|
51
|
+
lastStmt.insertAfter(stmt);
|
52
|
+
lastStmt = stmt;
|
53
|
+
}
|
54
|
+
lastStmt.insertAfter(ClavaJoinPoints.breakStmt());
|
55
|
+
}
|
56
|
+
|
57
|
+
transform($jp: Joinpoint): MISRATransformationReport {
|
58
|
+
if (!this.match($jp))
|
59
|
+
return new MISRATransformationReport(MISRATransformationType.NoChange);
|
60
|
+
|
61
|
+
for (const stmt of this.#statementsNeedingBreakAfter) {
|
62
|
+
if (stmt.rightJp === undefined) { // last statement of the switch
|
63
|
+
stmt.insertAfter(ClavaJoinPoints.breakStmt());
|
64
|
+
} else {
|
65
|
+
this.insertNextStatementsToExecute(stmt);
|
66
|
+
}
|
67
|
+
}
|
68
|
+
return new MISRATransformationReport(MISRATransformationType.DescendantChange);
|
69
|
+
}
|
70
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { Joinpoint, Switch } from "@specs-feup/clava/api/Joinpoints.js";
|
2
|
+
import MISRARule from "../../MISRARule.js";
|
3
|
+
import MISRAContext from "../../MISRAContext.js";
|
4
|
+
import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
|
5
|
+
import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
|
6
|
+
import { getNumOfSwitchClauses, switchHasBooleanCondition, switchHasConditionalBreak } from "../../utils/utils.js";
|
7
|
+
|
8
|
+
/**
|
9
|
+
* MISRA Rule 16.4: Every switch statement shall have a default label
|
10
|
+
*/
|
11
|
+
export default class Rule_16_4_SwitchHasDefault extends MISRARule {
|
12
|
+
constructor(context: MISRAContext) {
|
13
|
+
super("16.4", context);
|
14
|
+
}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Checks if the given joinpoint is a switch statement with a default case
|
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 rule, false otherwise
|
21
|
+
*/
|
22
|
+
match($jp: Joinpoint, logErrors: boolean = false): boolean {
|
23
|
+
if (!($jp instanceof Switch)) return false;
|
24
|
+
|
25
|
+
const noDefaultCase = !$jp.hasDefaultCase;
|
26
|
+
if (noDefaultCase && logErrors) {
|
27
|
+
this.logMISRAError($jp, "Switch statement is missing a default case.")
|
28
|
+
}
|
29
|
+
return noDefaultCase;
|
30
|
+
}
|
31
|
+
|
32
|
+
transform($jp: Joinpoint): MISRATransformationReport {
|
33
|
+
if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
|
34
|
+
|
35
|
+
$jp.children[1].lastChild
|
36
|
+
.insertAfter(ClavaJoinPoints.defaultStmt())
|
37
|
+
.insertAfter(ClavaJoinPoints.emptyStmt())
|
38
|
+
.insertAfter(ClavaJoinPoints.breakStmt());
|
39
|
+
return new MISRATransformationReport(MISRATransformationType.DescendantChange);
|
40
|
+
}
|
41
|
+
}
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import {Case, Comment, Joinpoint, Statement, Switch, WrapperStmt } from "@specs-feup/clava/api/Joinpoints.js";
|
2
|
+
import MISRARule from "../../MISRARule.js";
|
3
|
+
import MISRAContext from "../../MISRAContext.js";
|
4
|
+
import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
|
5
|
+
import { isCommentStmt } from "../../utils/utils.js";
|
6
|
+
|
7
|
+
/**
|
8
|
+
* MISRA Rule 16.5: A default label shall appear as either the first or the last switch label of
|
9
|
+
a switch statement
|
10
|
+
*/
|
11
|
+
export default class Rule_16_5_DefaultFirstOrLast extends MISRARule {
|
12
|
+
|
13
|
+
constructor(context: MISRAContext) {
|
14
|
+
super("16.5", context);
|
15
|
+
}
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Retrieves all consecutive case statements to the left of a given case statement
|
19
|
+
*
|
20
|
+
* @param $jp - The starting case statement from which the search will begin
|
21
|
+
* @returns Array containing consecutive case statements to the left of the provided joinpoint
|
22
|
+
*
|
23
|
+
*/
|
24
|
+
private getConsecutiveRightCases($jp: Case): Joinpoint[] {
|
25
|
+
const cases = [];
|
26
|
+
for (const stmt of $jp.siblingsRight) {
|
27
|
+
if (!(stmt instanceof Case || isCommentStmt($jp)))
|
28
|
+
break;
|
29
|
+
cases.push(stmt);
|
30
|
+
}
|
31
|
+
return cases;
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Retrieves all consecutive case statements to the right of a given case statement
|
36
|
+
*
|
37
|
+
* @param $jp - The starting case statement from which the search will begin
|
38
|
+
* @returns Array containing consecutive case statements to the right of the provided joinpoint
|
39
|
+
*
|
40
|
+
*/
|
41
|
+
private getConsecutiveLeftCases($jp: Case): Joinpoint[] {
|
42
|
+
let cases: Joinpoint[] = [];
|
43
|
+
for (let i = $jp.siblingsLeft.length - 1; i >= 0; i--) {
|
44
|
+
const currentStmt = $jp.siblingsLeft[i];
|
45
|
+
if (!(currentStmt instanceof Case || isCommentStmt($jp))) {
|
46
|
+
break;
|
47
|
+
}
|
48
|
+
cases.push($jp.siblingsLeft[i]);
|
49
|
+
}
|
50
|
+
return cases.reverse();
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Checks if the given joinpoint is a switch statement where the default label appears either as first of last label
|
55
|
+
* @param $jp - Joinpoint to analyze
|
56
|
+
* @param logErrors - [logErrors=false] - Whether to log errors if a violation is detected
|
57
|
+
* @returns Returns true if the joinpoint violates the rule, false otherwise
|
58
|
+
*/
|
59
|
+
match($jp: Joinpoint, logErrors: boolean = false): boolean {
|
60
|
+
if (!($jp instanceof Switch)) return false;
|
61
|
+
|
62
|
+
const caseStmts = $jp.cases;
|
63
|
+
for (let i = 0; i < caseStmts.length; i++) {
|
64
|
+
const currentCase = caseStmts[i];
|
65
|
+
if (currentCase.isDefault) {
|
66
|
+
if (i == 0 || i == caseStmts.length - 1) {
|
67
|
+
return false;
|
68
|
+
}
|
69
|
+
if (logErrors) {
|
70
|
+
this.logMISRAError($jp, "The default case of a switch statement must be the first or last label.")
|
71
|
+
}
|
72
|
+
return true;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
return false;
|
76
|
+
}
|
77
|
+
|
78
|
+
/**
|
79
|
+
* Transforms a switch statement so that the default case appears as the last label
|
80
|
+
* - If the default case is not already the last case within its case clause list, it is repositioned
|
81
|
+
* - Then, the entire case clause list containing the default case to the end of the switch statement
|
82
|
+
* @param $jp - Joinpoint to transform
|
83
|
+
* @returns Report detailing the transformation result
|
84
|
+
*/
|
85
|
+
transform($jp: Joinpoint): MISRATransformationReport {
|
86
|
+
if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
|
87
|
+
|
88
|
+
const defaultCase = ($jp as Switch).getDefaultCase;
|
89
|
+
const rightStatements = defaultCase.siblingsRight.filter(sibling => !isCommentStmt(sibling));
|
90
|
+
|
91
|
+
// Reposition the default case to the last position within its case clause list
|
92
|
+
if (rightStatements[0] instanceof Case) { // At least one of the first statements is a Case
|
93
|
+
const rightConsecutiveCases = this.getConsecutiveRightCases(defaultCase);
|
94
|
+
const lastRightCase = rightConsecutiveCases[rightConsecutiveCases.length - 1];
|
95
|
+
|
96
|
+
defaultCase.detach();
|
97
|
+
lastRightCase.insertAfter(defaultCase);
|
98
|
+
if (defaultCase.nextCase === undefined) { // Default is now the last case
|
99
|
+
return new MISRATransformationReport(MISRATransformationType.DescendantChange);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
// Move the entire case clause list containing the default case to the end of the switch statement
|
104
|
+
const switchScope = $jp.children[1];
|
105
|
+
const stmts = [...this.getConsecutiveLeftCases(defaultCase), defaultCase, ...defaultCase.instructions];
|
106
|
+
|
107
|
+
for (const stmt of stmts) {
|
108
|
+
stmt.detach();
|
109
|
+
switchScope.lastChild.insertAfter(stmt);
|
110
|
+
}
|
111
|
+
return new MISRATransformationReport(MISRATransformationType.DescendantChange);
|
112
|
+
}
|
113
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import {Break, Case, Joinpoint, Statement, Expression, Switch } from "@specs-feup/clava/api/Joinpoints.js";
|
2
|
+
import MISRARule from "../../MISRARule.js";
|
3
|
+
import MISRAContext from "../../MISRAContext.js";
|
4
|
+
import { MISRASwitchConverter, MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
|
5
|
+
import { getNumOfSwitchClauses, switchHasConditionalBreak } from "../../utils/utils.js";
|
6
|
+
|
7
|
+
/**
|
8
|
+
* MISRA Rule 16.6: Every switch statement shall have at least two switch-clauses.
|
9
|
+
*/
|
10
|
+
export default class Rule_16_6_SwitchMinTwoClauses extends MISRARule {
|
11
|
+
priority = 3;
|
12
|
+
|
13
|
+
constructor(context: MISRAContext) {
|
14
|
+
super("16.6", context);
|
15
|
+
}
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Checks if the given joinpoint is a switch statement with less than two clauses
|
19
|
+
* @param $jp - Joinpoint to analyze
|
20
|
+
* @param logErrors - [logErrors=false] - Whether to log errors if a violation is detected
|
21
|
+
* @returns Returns true if the joinpoint violates the rule, false otherwise
|
22
|
+
*/
|
23
|
+
match($jp: Joinpoint, logErrors: boolean = false): boolean {
|
24
|
+
if (!($jp instanceof Switch)) return false;
|
25
|
+
|
26
|
+
const nonCompliant = getNumOfSwitchClauses($jp) < 2;
|
27
|
+
if (nonCompliant && logErrors) {
|
28
|
+
this.logMISRAError($jp, "Switch statements should have at least two clauses.")
|
29
|
+
}
|
30
|
+
return nonCompliant;
|
31
|
+
}
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Transforms a switch statement with less than two clauses into equivalent statement(s), only if there is no conditional break.
|
35
|
+
* If a conditional break is present, no transformation is performed and an error is generated.
|
36
|
+
*
|
37
|
+
* @param $jp - Joinpoint to transform
|
38
|
+
* @returns Report detailing the transformation result
|
39
|
+
*/
|
40
|
+
transform($jp: Joinpoint): MISRATransformationReport {
|
41
|
+
if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
|
42
|
+
|
43
|
+
const switchJp = $jp as Switch;
|
44
|
+
if (switchHasConditionalBreak(switchJp)) {
|
45
|
+
if (switchJp.hasDefaultCase) {
|
46
|
+
this.logMISRAError($jp, "Switch statement must have at least two clauses and cannot be transformed due to a conditional break statement.")
|
47
|
+
}
|
48
|
+
return new MISRATransformationReport(MISRATransformationType.NoChange);
|
49
|
+
}
|
50
|
+
|
51
|
+
const transformResultNode = MISRASwitchConverter.convert(switchJp);
|
52
|
+
if (transformResultNode) {
|
53
|
+
return new MISRATransformationReport(
|
54
|
+
MISRATransformationType.Replacement,
|
55
|
+
transformResultNode
|
56
|
+
);
|
57
|
+
}
|
58
|
+
// Only breaks were present, so the switch was removed
|
59
|
+
return new MISRATransformationReport(MISRATransformationType.Removal);
|
60
|
+
}
|
61
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import { BuiltinType, Joinpoint, Switch } from "@specs-feup/clava/api/Joinpoints.js";
|
2
|
+
import MISRARule from "../../MISRARule.js";
|
3
|
+
import MISRAContext from "../../MISRAContext.js";
|
4
|
+
import { MISRASwitchConverter, MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
|
5
|
+
import { switchHasBooleanCondition, switchHasConditionalBreak } from "../../utils/utils.js";
|
6
|
+
|
7
|
+
/**
|
8
|
+
* MISRA Rule 16.7: A switch-expression shall not have essentially Boolean type.
|
9
|
+
*/
|
10
|
+
export default class Rule_16_7_NonBooleanSwitchCondition extends MISRARule {
|
11
|
+
priority = 3;
|
12
|
+
constructor(context: MISRAContext) {
|
13
|
+
super("16.7", context);
|
14
|
+
}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Checks if the given joinpoint is a switch statement with an essentially Boolean condition
|
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 rule, false otherwise
|
21
|
+
*/
|
22
|
+
match($jp: Joinpoint, logErrors: boolean = false): boolean {
|
23
|
+
if (!($jp instanceof Switch)) return false;
|
24
|
+
|
25
|
+
const booleanCondition = switchHasBooleanCondition($jp);
|
26
|
+
if (booleanCondition && logErrors) {
|
27
|
+
this.logMISRAError($jp, `Switch statement controlling expression ${$jp.condition.code} must not have essentially boolean type.`)
|
28
|
+
}
|
29
|
+
return booleanCondition;
|
30
|
+
}
|
31
|
+
|
32
|
+
/**
|
33
|
+
* Transforms a switch statement with a Boolean condition into equivalent statement(s), only if there is no conditional break.
|
34
|
+
* If a conditional break is present, no transformation is performed and an error is generated.
|
35
|
+
*
|
36
|
+
* @param $jp - Joinpoint to transform
|
37
|
+
* @returns Report detailing the transformation result
|
38
|
+
*/
|
39
|
+
transform($jp: Joinpoint): MISRATransformationReport {
|
40
|
+
if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
|
41
|
+
|
42
|
+
if (switchHasConditionalBreak($jp as Switch)) {
|
43
|
+
this.logMISRAError($jp, `The switch statement's controlling expression ${($jp as Switch).condition.code} must not be of a boolean type and cannot be transformed due to a conditional break statement.`)
|
44
|
+
return new MISRATransformationReport(MISRATransformationType.NoChange);
|
45
|
+
}
|
46
|
+
|
47
|
+
const transformResultNode = MISRASwitchConverter.convert($jp as Switch);
|
48
|
+
if (transformResultNode) {
|
49
|
+
return new MISRATransformationReport(
|
50
|
+
MISRATransformationType.Replacement,
|
51
|
+
transformResultNode
|
52
|
+
);
|
53
|
+
}
|
54
|
+
// Only breaks were present, so the switch was removed
|
55
|
+
return new MISRATransformationReport(MISRATransformationType.Removal);
|
56
|
+
}
|
57
|
+
}
|
@@ -0,0 +1,180 @@
|
|
1
|
+
import { Call, FileJp, Joinpoint, Program } from "@specs-feup/clava/api/Joinpoints.js";
|
2
|
+
import MISRARule from "../../MISRARule.js";
|
3
|
+
import MISRAContext from "../../MISRAContext.js";
|
4
|
+
import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
|
5
|
+
import { getFilesWithCallToImplicitFunction, getIncludesOfFile, isCallToImplicitFunction, isValidFile, removeIncludeFromFile } from "../../utils/utils.js";
|
6
|
+
import Query from "@specs-feup/lara/api/weaver/Query.js";
|
7
|
+
import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
|
8
|
+
|
9
|
+
/**
|
10
|
+
* MISRA Rule 17.3: A function shall not be declared implicitly
|
11
|
+
*/
|
12
|
+
export default class Rule_17_3_ImplicitFunction extends MISRARule {
|
13
|
+
priority = 1;
|
14
|
+
|
15
|
+
constructor(context: MISRAContext) {
|
16
|
+
super("17.3", context);
|
17
|
+
}
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Checks if the given joinpoint represents a call to an implicit function.
|
21
|
+
*
|
22
|
+
* @param $jp - Joinpoint to analyze
|
23
|
+
* @param logErrors - [logErrors=false] - Whether to log errors if a violation is detected
|
24
|
+
* @returns Returns true if the joinpoint violates the rule, false otherwise
|
25
|
+
*/
|
26
|
+
match($jp: Joinpoint, logErrors: boolean = false): boolean {
|
27
|
+
if (!($jp instanceof Program)) return false;
|
28
|
+
|
29
|
+
const implicitCalls = Query.searchFrom($jp, Call, (callJp) => isCallToImplicitFunction(callJp)). get();
|
30
|
+
for (const callJp of implicitCalls) {
|
31
|
+
if (logErrors) {
|
32
|
+
this.logMISRAError(callJp, `Function '${callJp.name}' is declared implicitly.`);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
return implicitCalls.length > 0;
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Transforms every implicit call by adding a missing include directive or extern statement specified on the config file.
|
40
|
+
*
|
41
|
+
* - If the configuration is missing or the specified fix is invalid (i.e., not a '.h' or '.c'), no transformation is performed and the call is left unchanged.
|
42
|
+
* - The fix is applied only if it successfully resolves the issue (i.e., makes the call explicit and the file compiles with no error).
|
43
|
+
* - Otherwise, the fix is removed.
|
44
|
+
*
|
45
|
+
* @param $jp - Joinpoint to transform
|
46
|
+
* @returns Report detailing the transformation result
|
47
|
+
*/
|
48
|
+
transform($jp: Joinpoint): MISRATransformationReport {
|
49
|
+
if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
|
50
|
+
|
51
|
+
const programJp = $jp as Program;
|
52
|
+
const filesWithImplicitCall = getFilesWithCallToImplicitFunction(programJp);
|
53
|
+
let changedDescendant = false;
|
54
|
+
|
55
|
+
for (const fileJp of filesWithImplicitCall) {
|
56
|
+
changedDescendant = changedDescendant || this.solveImplicitCalls(fileJp);
|
57
|
+
}
|
58
|
+
|
59
|
+
if (changedDescendant) {
|
60
|
+
programJp.rebuild();
|
61
|
+
return new MISRATransformationReport(MISRATransformationType.Replacement, Query.root() as Program);
|
62
|
+
} else {
|
63
|
+
return new MISRATransformationReport(MISRATransformationType.NoChange);
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
/**
|
68
|
+
* Retrieves the fix for a implicit call specified on the config file (.h or .c)
|
69
|
+
* @param callJp
|
70
|
+
* @param errorMsgPrefix
|
71
|
+
* @returns
|
72
|
+
*/
|
73
|
+
private getImplicitFixFromConfig(callJp: Call, errorMsgPrefix: string): string | undefined {
|
74
|
+
if (!this.context.config) {
|
75
|
+
this.logMISRAError(callJp, `${errorMsgPrefix} Include or extern not added due to missing config file.`);
|
76
|
+
return undefined;
|
77
|
+
}
|
78
|
+
|
79
|
+
let configFix: string | undefined;
|
80
|
+
try {
|
81
|
+
configFix = this.context.config.get("implicitCalls")[callJp.name];
|
82
|
+
} catch {
|
83
|
+
this.logMISRAError(callJp, `${errorMsgPrefix} Include or extern was not added as \'implicitCalls\' is not defined in the configuration file.`);
|
84
|
+
return undefined;
|
85
|
+
}
|
86
|
+
|
87
|
+
if (configFix === undefined) {
|
88
|
+
this.logMISRAError(callJp, `${errorMsgPrefix} Couldn't add include or extern due to missing configuration for function '${callJp.name}'.`);
|
89
|
+
return undefined;
|
90
|
+
}
|
91
|
+
|
92
|
+
if (!(configFix.endsWith(".h") || configFix.endsWith(".c"))) {
|
93
|
+
this.logMISRAError(callJp, `${errorMsgPrefix} Cannot add include or extern without a .h or .c reference.`);
|
94
|
+
return undefined;
|
95
|
+
}
|
96
|
+
return configFix;
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Attempts to resolve implicit function calls in a file by adding missing includes or extern statements based on the configuration file.
|
101
|
+
* @param fileJp The file to analyze
|
102
|
+
* @returns `true` if any changes were made to the file, otherwise `false`.
|
103
|
+
*/
|
104
|
+
private solveImplicitCalls(fileJp: FileJp): boolean {
|
105
|
+
const implicitCalls = Query.searchFrom(fileJp, Call, (callJp) => (isCallToImplicitFunction(callJp))).get();
|
106
|
+
const originalIncludes = getIncludesOfFile(fileJp);
|
107
|
+
let solvedCalls = new Set<string>();
|
108
|
+
let addedIncludes: string[] = [];
|
109
|
+
let changedFile = false;
|
110
|
+
|
111
|
+
for (const callJp of implicitCalls) {
|
112
|
+
const errorMsgPrefix = `Function '${callJp.name}' is declared implicitly.`;
|
113
|
+
|
114
|
+
if (solvedCalls.has(callJp.name)) {
|
115
|
+
continue;
|
116
|
+
}
|
117
|
+
|
118
|
+
const configFix = this.getImplicitFixFromConfig(callJp, errorMsgPrefix);
|
119
|
+
if (!configFix) {
|
120
|
+
continue;
|
121
|
+
}
|
122
|
+
|
123
|
+
const callIndex = Query.searchFrom(fileJp, Call, { name: callJp.name }).get().findIndex(c => c.equals(callJp));
|
124
|
+
const isInclude = configFix.endsWith(".h");
|
125
|
+
if (isInclude) {
|
126
|
+
if (originalIncludes.includes(configFix)) {
|
127
|
+
this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${configFix}\' does not fix the violation.`);
|
128
|
+
}
|
129
|
+
else if (addedIncludes.includes(configFix)) {
|
130
|
+
|
131
|
+
if (this.isValidFileWithExplicitCall(fileJp, callJp.name, callIndex)) {
|
132
|
+
solvedCalls.add(callJp.name);
|
133
|
+
} else {
|
134
|
+
this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${configFix}\' does not fix the violation.`);
|
135
|
+
}
|
136
|
+
}
|
137
|
+
else {
|
138
|
+
fileJp.addInclude(configFix);
|
139
|
+
const fileCompiles = this.isValidFileWithExplicitCall(fileJp, callJp.name, callIndex);
|
140
|
+
|
141
|
+
if (fileCompiles) {
|
142
|
+
solvedCalls.add(callJp.name);
|
143
|
+
addedIncludes.push(configFix);
|
144
|
+
changedFile = true;
|
145
|
+
} else {
|
146
|
+
removeIncludeFromFile(configFix, fileJp);
|
147
|
+
this.logMISRAError(callJp, `${errorMsgPrefix} Provided include \'${configFix}\' does not fix the violation.`);
|
148
|
+
}
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
return changedFile;
|
153
|
+
}
|
154
|
+
|
155
|
+
/**
|
156
|
+
* Checks if the rebuilt version of the file compiles and if the provided call is no longer implicit
|
157
|
+
* @param fileJp The file to analyze
|
158
|
+
* @param funcName The function name to search the call
|
159
|
+
* @param callIndex The index of the call
|
160
|
+
*/
|
161
|
+
private isValidFileWithExplicitCall(fileJp: FileJp, funcName: string, callIndex: number) {
|
162
|
+
const programJp = fileJp.parent as Program;
|
163
|
+
let copyFile = ClavaJoinPoints.fileWithSource(`temp_misra_${fileJp.name}`, fileJp.code, fileJp.relativeFolderpath);
|
164
|
+
|
165
|
+
copyFile = programJp.addFile(copyFile) as FileJp;
|
166
|
+
try {
|
167
|
+
const rebuiltFile = copyFile.rebuild();
|
168
|
+
const fileToRemove = Query.searchFrom(programJp, FileJp, {filepath: rebuiltFile.filepath}).first() as FileJp;
|
169
|
+
const callJp = Query.searchFrom(fileToRemove, Call, {name: funcName}).get().at(callIndex);
|
170
|
+
const isExplicitCall = callJp !== undefined && !isCallToImplicitFunction(callJp);
|
171
|
+
|
172
|
+
fileToRemove?.detach();
|
173
|
+
return isExplicitCall;
|
174
|
+
|
175
|
+
} catch(error) {
|
176
|
+
copyFile.detach();
|
177
|
+
return false;
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import { BuiltinType, FileJp, FunctionJp, Joinpoint, ReturnStmt } from "@specs-feup/clava/api/Joinpoints.js";
|
2
|
+
import MISRARule from "../../MISRARule.js";
|
3
|
+
import MISRAContext from "../../MISRAContext.js";
|
4
|
+
import ClavaJoinPoints from "@specs-feup/clava/api/clava/ClavaJoinPoints.js";
|
5
|
+
import { MISRATransformationReport, MISRATransformationType } from "../../MISRA.js";
|
6
|
+
import Query from "@specs-feup/lara/api/weaver/Query.js";
|
7
|
+
import { isValidFile } from "../../utils/utils.js";
|
8
|
+
|
9
|
+
/**
|
10
|
+
* MISRA Rule 17.4: All exit paths from a function with non-void return type shall have an
|
11
|
+
explicit return statement with an expression. In a non-void function:
|
12
|
+
- Every return statement has an expression, and
|
13
|
+
- Control cannot reach the end of the function without encountering a return statement
|
14
|
+
*/
|
15
|
+
export default class Rule_17_4_NonVoidReturn extends MISRARule {
|
16
|
+
constructor(context: MISRAContext) {
|
17
|
+
super("17.4", context);
|
18
|
+
}
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Checks if the given joinpoint represents a non-void function that lacks an explicit return statement with an expression.
|
22
|
+
*
|
23
|
+
* @param $jp - Joinpoint to analyze
|
24
|
+
* @param logErrors - [logErrors=false] - Whether to log errors if a violation is detected
|
25
|
+
* @returns Returns true if the joinpoint violates the rule, false otherwise
|
26
|
+
*/
|
27
|
+
match($jp: Joinpoint, logErrors: boolean = false): boolean {
|
28
|
+
if (!($jp instanceof FunctionJp && $jp.isImplementation)) return false;
|
29
|
+
|
30
|
+
if ($jp.returnType instanceof BuiltinType && $jp.returnType.isVoid) return false;
|
31
|
+
|
32
|
+
const emptyReturnStms = Query.searchFrom($jp, ReturnStmt, {returnExpr: undefined}).get();
|
33
|
+
const exitReturn = $jp.body.children.filter(child => child instanceof ReturnStmt && !emptyReturnStms.includes(child))[0];
|
34
|
+
if (logErrors) {
|
35
|
+
emptyReturnStms?.forEach(emptyReturn =>
|
36
|
+
this.logMISRAError(emptyReturn, "Every return statement in a non-void function must include an expression.")
|
37
|
+
)
|
38
|
+
if (exitReturn === undefined) {
|
39
|
+
this.logMISRAError($jp, `Function '${$jp.name}' reaches the end without a return statement.`)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
return emptyReturnStms.length > 0 || exitReturn === undefined;
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Transforms a non-void function joinpoint that has no return statement at the end, by adding a default return value based on the config file.
|
47
|
+
* - If the configuration file is missing/invalid or the specified default value is invalid, no transformation is performed and the function is left unchanged.
|
48
|
+
* - Otherwise, a return statement is inserted as the last statement of the function.
|
49
|
+
*
|
50
|
+
* @param $jp - Joinpoint to transform
|
51
|
+
* @returns Report detailing the transformation result
|
52
|
+
*/
|
53
|
+
transform($jp: Joinpoint): MISRATransformationReport {
|
54
|
+
if (!this.match($jp)) return new MISRATransformationReport(MISRATransformationType.NoChange);
|
55
|
+
|
56
|
+
const functionJp = $jp as FunctionJp;
|
57
|
+
const fileJp = functionJp.getAncestor("file") as FileJp;
|
58
|
+
const returnType = functionJp.type.code;
|
59
|
+
const errorMsgPrefix = `Function '${functionJp.name}' reaches the end without a return statement.`;
|
60
|
+
|
61
|
+
if (!this.context.config) {
|
62
|
+
this.logMISRAError($jp, `${errorMsgPrefix} Default value return not added due to missing config file.`)
|
63
|
+
return new MISRATransformationReport(MISRATransformationType.NoChange);
|
64
|
+
}
|
65
|
+
|
66
|
+
let defaultValueReturn;
|
67
|
+
try {
|
68
|
+
defaultValueReturn = this.context.config.get("defaultValues")[returnType];
|
69
|
+
} catch (error) {
|
70
|
+
this.logMISRAError($jp, `${errorMsgPrefix} Default value return was not added as \'defaultValues\' is not defined in the configuration file.`);
|
71
|
+
return new MISRATransformationReport(MISRATransformationType.NoChange);
|
72
|
+
}
|
73
|
+
|
74
|
+
if (defaultValueReturn === undefined) {
|
75
|
+
this.logMISRAError($jp, `${errorMsgPrefix} Default value return not added due to missing default value configuration for type '${returnType}'.`);
|
76
|
+
return new MISRATransformationReport(MISRATransformationType.NoChange);
|
77
|
+
}
|
78
|
+
|
79
|
+
// Insert return statement and validate it
|
80
|
+
const returnStmt = ClavaJoinPoints.returnStmt(ClavaJoinPoints.exprLiteral(String(defaultValueReturn), functionJp.returnType)) as ReturnStmt;
|
81
|
+
functionJp.body.lastChild ? functionJp.body.lastChild.insertAfter(returnStmt) : functionJp.body.setFirstChild(returnStmt);
|
82
|
+
|
83
|
+
// Validate the provided default value. If it is invalid, the return stmt is removed
|
84
|
+
if (isValidFile(fileJp)) {
|
85
|
+
return new MISRATransformationReport(MISRATransformationType.DescendantChange);
|
86
|
+
}
|
87
|
+
returnStmt.detach();
|
88
|
+
this.logMISRAError($jp, `${errorMsgPrefix} Provided default value for type '${functionJp.type.code}' is invalid and was therefore not inserted.`);
|
89
|
+
return new MISRATransformationReport(MISRATransformationType.NoChange);
|
90
|
+
}
|
91
|
+
}
|