├── .gitignore ├── .sonarsource.properties ├── README.md ├── pom.xml └── src ├── main ├── files │ ├── README.md │ ├── cppcheck-1.52.xml │ ├── cppcheck-1.53.xml │ ├── cppcheck-1.54.xml │ ├── cppcheck-1.55.xml │ ├── cppcheck-1.56.xml │ ├── cppcheck-1.57.xml │ ├── cppcheck-1.58.xml │ ├── cppcheck-1.59.xml │ ├── cppcheck-1.60.xml │ ├── cppcheck-1.61.xml │ ├── cppcheck-1.62.xml │ ├── cppcheck-1.63.xml │ ├── cppcheck-1.64.xml │ ├── cppcheck-1.65.xml │ ├── cppcheck-1.66.xml │ ├── cppcheck-1.67.xml │ ├── cppcheck-1.68.xml │ ├── cppcheck-1.69.xml │ ├── cppcheck-1.70.xml │ ├── cppcheck-1.71.xml │ ├── cppcheck_replacements.properties │ └── export-rules.sh ├── java │ └── org │ │ └── sonarqube │ │ └── cppcheck │ │ ├── CppcheckConfiguration.java │ │ ├── CppcheckPlugin.java │ │ ├── CppcheckRuleRepository.java │ │ ├── CppcheckSensor.java │ │ ├── CppcheckXmlParser.java │ │ └── package-info.java └── resources │ └── org │ └── sonarqube │ └── cppcheck.xml └── test ├── java └── org │ └── sonarqube │ └── cppcheck │ ├── CppcheckConfigurationTest.java │ ├── CppcheckPluginTest.java │ ├── CppcheckRuleRepositoryTest.java │ ├── CppcheckSensorTest.java │ └── CppcheckXmlParserTest.java └── resources ├── cppcheck2.xml └── no-location.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven 2 | target/ 3 | 4 | # IntelliJ IDEA 5 | *.iws 6 | *.iml 7 | *.ipr 8 | .idea/ 9 | 10 | # Eclipse 11 | .classpath 12 | .project 13 | .settings 14 | 15 | # ---- Mac OS X 16 | .DS_Store 17 | Icon? 18 | # Thumbnails 19 | ._* 20 | # Files that might appear on external disk 21 | .Spotlight-V100 22 | .Trashes 23 | 24 | # ---- Windows 25 | # Windows image file caches 26 | Thumbs.db 27 | # Folder config file 28 | Desktop.ini 29 | -------------------------------------------------------------------------------- /.sonarsource.properties: -------------------------------------------------------------------------------- 1 | # Wallboard to be used at SonarSource 2 | wallboard.teamAtSonarSource=language 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SonarQube Cppcheck Plugin 2 | ========================= 3 | 4 | This plugin can be used to import [Cppcheck](http://cppcheck.sourceforge.net/) reports into [SonarQube](http://sonarqube.org/). 5 | 6 | The plugin will not run Cppcheck but instead re-use the report generated by it. 7 | Here are the steps: 8 | 9 | 1. Download and install Cppcheck (version 1.47 or higher) on the machine running the SonarQube analysis 10 | 2. Install this SonarQube Cppcheck plugin (see the [release](https://github.com/SonarQubeCommunity/sonar-cppcheck/releases) section and the [instructions](http://docs.sonarqube.org/display/SONAR/Installing+a+Plugin) to manually install a SonarQube plugin) 11 | 2. Run Cppcheck to create an xml report: 12 | 13 | ``` 14 | cppcheck --xml --xml-version=2 --enable=all 2> cppcheck-report.xml 15 | ``` 16 | 17 | 3. Set the `sonar.cppcheck.reportPath` analysis property to the path of the Cppcheck xml report, e.g.: 18 | 19 | ``` 20 | sonar.cppcheck.reportPath=cppcheck-report.xml 21 | ``` 22 | 23 | 4. Activate some Cppcheck rules in your quality profile 24 | 5. Run the SonarQube analysis on your project 25 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.sonarqube.cppcheck 6 | sonar-cppcheck-plugin 7 | 1.1-SNAPSHOT 8 | sonar-plugin 9 | 10 | SonarQube :: Cppcheck Plugin 11 | Import Cppcheck reports. 12 | https://github.com/SonarQubeCommunity/sonar-cppcheck 13 | 2016 14 | 15 | 16 | GNU LGPL 3 17 | http://www.gnu.org/licenses/lgpl.txt 18 | repo 19 | 20 | 21 | 22 | 23 | 3.0.5 24 | 25 | 26 | 27 | scm:git:git@github.com:SonarQubeCommunity/sonar-cppcheck.git 28 | scm:git:git@github.com:SonarQubeCommunity/sonar-cppcheck.git 29 | https://github.com/SonarQubeCommunity/sonar-cppcheck 30 | HEAD 31 | 32 | 33 | 34 | UTF-8 35 | 36 | 1.7 37 | 1.7 38 | 39 | 4.5.4 40 | 41 | 42 | 43 | 44 | org.codehaus.sonar 45 | sonar-plugin-api 46 | ${sonar.version} 47 | provided 48 | 49 | 50 | org.codehaus.sonar 51 | sonar-deprecated 52 | ${sonar.version} 53 | provided 54 | 55 | 56 | 57 | org.easytesting 58 | fest-assert 59 | 1.4 60 | test 61 | 62 | 63 | junit 64 | junit 65 | 4.12 66 | test 67 | 68 | 69 | org.mockito 70 | mockito-all 71 | 1.9.5 72 | test 73 | 74 | 75 | xmlunit 76 | xmlunit 77 | 1.4 78 | test 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | org.apache.maven.plugins 87 | maven-compiler-plugin 88 | 3.5.1 89 | 90 | 91 | 92 | 93 | 94 | org.apache.maven.plugins 95 | maven-enforcer-plugin 96 | 1.2 97 | 98 | 99 | enforce-plugin-size 100 | 101 | enforce 102 | 103 | verify 104 | 105 | 106 | 107 | 35000 108 | 34000 109 | 110 | ${project.build.directory}/${project.build.finalName}.jar 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | org.sonarsource.sonar-packaging-maven-plugin 120 | sonar-packaging-maven-plugin 121 | 1.15 122 | true 123 | 124 | org.sonarqube.cppcheck.CppcheckPlugin 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /src/main/files/README.md: -------------------------------------------------------------------------------- 1 | Descriptions of rules from different Cppcheck versions for automatic merge. 2 | 3 | # Export rules using the bash script 4 | 5 | Use ```export-rules.sh``` to export the rules, for example: 6 | 7 | ```bash 8 | ./export-rules.sh 1.68 1.69 1.70 9 | ``` 10 | 11 | # Export rules manually 12 | 13 | - Download the source of the new cppcheck version from http://sourceforge.net/projects/cppcheck/files/cppcheck/ 14 | - Uncompress and build cppcheck using the command: 15 | 16 | ```bash 17 | make 18 | ``` 19 | 20 | - Export the rules using ```cppcheck```, for example: 21 | 22 | ```bash 23 | ./cppcheck --xml --xml-version=2 --errorlist > cppcheck-1.68.xml 24 | ``` 25 | -------------------------------------------------------------------------------- /src/main/files/cppcheck-1.52.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | -------------------------------------------------------------------------------- /src/main/files/cppcheck-1.53.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | -------------------------------------------------------------------------------- /src/main/files/cppcheck-1.54.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | -------------------------------------------------------------------------------- /src/main/files/cppcheck_replacements.properties: -------------------------------------------------------------------------------- 1 | multiCondition=S1862 2 | duplicateIf=S1862 3 | 4 | selfAssignment=S1656 5 | duplicateExpression=S1764 6 | unreachableCode=S1763 7 | sizeofsizeof=SizeofSizeof 8 | sizeofCalculation=SideEffectInSizeOf 9 | operatorEqRetRefThis=S1236 10 | operatorEqToSelf=S1250 11 | postfixOperator=S1705 12 | preprocessorErrorDirective=PPErrorDirectiveReached 13 | catchExceptionByValue=S1044 14 | clarifyCalculation=S864 15 | switchCaseFallThrough=NonEmptyCaseWithoutBreak 16 | exceptThrowInDestructor=ExceptionInDestructor 17 | suspiciousEqualityComparison=S905 18 | constStatement=S905 19 | commaSeparatedReturn=S878 20 | incrementboolean=S2668 21 | duplicateBranch=S1871 22 | cstyleCast=S871 23 | sizeofVoid=S2665 24 | sizeofDereferencedVoidPointer=S2665 25 | initializerList=S3229:cpp 26 | virtualDestructor=S1235:cpp 27 | 28 | nonreentrantFunctionsasctime=NonReentrantFunction 29 | nonreentrantFunctionscrypt=NonReentrantFunction 30 | nonreentrantFunctionsctermid=NonReentrantFunction 31 | nonreentrantFunctionsctime=NonReentrantFunction 32 | nonreentrantFunctionsecvt=NonReentrantFunction 33 | nonreentrantFunctionsfcvt=NonReentrantFunction 34 | nonreentrantFunctionsfgetgrent=NonReentrantFunction 35 | nonreentrantFunctionsfgetpwent=NonReentrantFunction 36 | nonreentrantFunctionsfgetspent=NonReentrantFunction 37 | nonreentrantFunctionsgcvt=NonReentrantFunction 38 | nonreentrantFunctionsgetgrent=NonReentrantFunction 39 | nonreentrantFunctionsgetgrgid=NonReentrantFunction 40 | nonreentrantFunctionsgetgrnam=NonReentrantFunction 41 | nonreentrantFunctionsgethostbyaddr=NonReentrantFunction 42 | nonreentrantFunctionsgethostbyname=NonReentrantFunction 43 | nonreentrantFunctionsgethostbyname2=NonReentrantFunction 44 | nonreentrantFunctionsgethostent=NonReentrantFunction 45 | nonreentrantFunctionsgetlogin=NonReentrantFunction 46 | nonreentrantFunctionsgetnetbyaddr=NonReentrantFunction 47 | nonreentrantFunctionsgetnetbyname=NonReentrantFunction 48 | nonreentrantFunctionsgetnetgrent=NonReentrantFunction 49 | nonreentrantFunctionsgetprotobyname=NonReentrantFunction 50 | nonreentrantFunctionsgetpwent=NonReentrantFunction 51 | nonreentrantFunctionsgetpwnam=NonReentrantFunction 52 | nonreentrantFunctionsgetpwuid=NonReentrantFunction 53 | nonreentrantFunctionsgetrpcbyname=NonReentrantFunction 54 | nonreentrantFunctionsgetrpcbynumber=NonReentrantFunction 55 | nonreentrantFunctionsgetrpcent=NonReentrantFunction 56 | nonreentrantFunctionsgetservbyname=NonReentrantFunction 57 | nonreentrantFunctionsgetservbyport=NonReentrantFunction 58 | nonreentrantFunctionsgetservent=NonReentrantFunction 59 | nonreentrantFunctionsgetspent=NonReentrantFunction 60 | nonreentrantFunctionsgetspnam=NonReentrantFunction 61 | nonreentrantFunctionsgmtime=NonReentrantFunction 62 | nonreentrantFunctionslocaltime=NonReentrantFunction 63 | nonreentrantFunctionsrand=NonReentrantFunction 64 | nonreentrantFunctionsreaddir=NonReentrantFunction 65 | nonreentrantFunctionsstrtok=NonReentrantFunction 66 | nonreentrantFunctionstempnam=NonReentrantFunction 67 | nonreentrantFunctionstmpnam=NonReentrantFunction 68 | nonreentrantFunctionsttyname=NonReentrantFunction 69 | 70 | obsoleteFunctionsasctime=ObsoletePosixFunction 71 | obsoleteFunctionsasctime_r=ObsoletePosixFunction 72 | obsoleteFunctionsbcmp=ObsoletePosixFunction 73 | obsoleteFunctionsbcopy=ObsoletePosixFunction 74 | obsoleteFunctionsbsd_signal=ObsoletePosixFunction 75 | obsoleteFunctionsbzero=ObsoletePosixFunction 76 | obsoleteFunctionsctime=ObsoletePosixFunction 77 | obsoleteFunctionsctime_r=ObsoletePosixFunction 78 | obsoleteFunctionsecvt=ObsoletePosixFunction 79 | obsoleteFunctionsfcvt=ObsoletePosixFunction 80 | obsoleteFunctionsftime=ObsoletePosixFunction 81 | obsoleteFunctionsgcvt=ObsoletePosixFunction 82 | obsoleteFunctionsgetcontext=ObsoletePosixFunction 83 | obsoleteFunctionsgethostbyaddr=ObsoletePosixFunction 84 | obsoleteFunctionsgethostbyname=ObsoletePosixFunction 85 | obsoleteFunctionsgetwd=ObsoletePosixFunction 86 | obsoleteFunctionsindex=ObsoletePosixFunction 87 | obsoleteFunctionsmakecontext=ObsoletePosixFunction 88 | obsoleteFunctionspthread_attr_getstackaddr=ObsoletePosixFunction 89 | obsoleteFunctionspthread_attr_setstackaddr=ObsoletePosixFunction 90 | obsoleteFunctionsrand_r=ObsoletePosixFunction 91 | obsoleteFunctionsrindex=ObsoletePosixFunction 92 | obsoleteFunctionsscalbln=ObsoletePosixFunction 93 | obsoleteFunctionsswapcontext=ObsoletePosixFunction 94 | obsoleteFunctionstmpnam=ObsoletePosixFunction 95 | obsoleteFunctionstmpnam_r=ObsoletePosixFunction 96 | obsoleteFunctionsualarm=ObsoletePosixFunction 97 | obsoleteFunctionsusleep=ObsoletePosixFunction 98 | obsoleteFunctionsutime=ObsoletePosixFunction 99 | obsoleteFunctionsvfork=ObsoletePosixFunction 100 | obsoleteFunctionswcswcs=ObsoletePosixFunction 101 | 102 | bitwiseOnBoolean=S872 103 | comparisonOfBoolWithBoolError=S872 104 | comparisonOfFuncReturningBoolError=S872 105 | comparisonOfTwoFuncsReturningBoolError=S872 106 | 107 | unusedScopedObject=S1481 108 | unusedVariable=S1481 109 | 110 | coutCerrMisusage=S106:cpp 111 | duplicateBreak=S1763 112 | invalidscanf=S1079 113 | missingScanfFormatWidth=S1079 114 | clarifyCondition=S864 115 | unnecessaryForwardDeclaration=S3231 116 | useInitializationList=S3230:cpp 117 | 118 | unsignedLessThanZero=S1768 119 | unsignedPositive=S1768 120 | 121 | duplicateExpressionTernary=S1871 122 | noExplicitConstructor=S1709:cpp 123 | unusedLabel=S1065 124 | duplInheritedMember=S2387 125 | -------------------------------------------------------------------------------- /src/main/files/export-rules.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -e 4 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 5 | PROJECT_DIR="$(readlink -f "$SCRIPT_DIR/../../..")" 6 | TARGET_DIR="$PROJECT_DIR/target" 7 | 8 | function check_project_dir_and_create_target_dir { 9 | if [ ! -f "$PROJECT_DIR/pom.xml" ]; then 10 | echo "ERROR, invalid project folder '$PROJECT_DIR' missing 'pom.xml'" 1>&2 11 | return 1 12 | fi 13 | mkdir -p "$TARGET_DIR" 14 | } 15 | 16 | function prepare_working_dir { 17 | local WORKING_DIR="$1" 18 | echo "Working dir : $WORKING_DIR" 19 | if [ -d "$WORKING_DIR" ]; then 20 | rm -r "$WORKING_DIR" 21 | fi 22 | mkdir "$WORKING_DIR" 23 | } 24 | 25 | function download_source { 26 | local SRC_URL="$1" 27 | local TARGET_FILE="$2" 28 | echo "Downloading : $SRC_URL" 29 | echo "Into : $TARGET_FILE" 30 | curl --location --max-redirs 10 -o "$TARGET_FILE" "$SRC_URL" 31 | } 32 | 33 | function unzip_source { 34 | local WORKING_DIR="$1" 35 | local SRC_FILE="$2" 36 | tar -zxf "$SRC_FILE" --directory "$WORKING_DIR" 37 | } 38 | 39 | function compile_source { 40 | local WORKING_DIR="$1" 41 | echo "Compiling : $WORKING_DIR" 42 | ( 43 | cd "$WORKING_DIR" 44 | make 45 | ) 46 | } 47 | 48 | function run_cppcheck_to_export_rules { 49 | local CPPCHECK_DIR="$1" 50 | local OUTPUT_FILE="$2" 51 | echo "Exporting : $OUTPUT_FILE" 52 | ( 53 | cd "$CPPCHECK_DIR" 54 | ./cppcheck --xml --xml-version=2 --errorlist > "$OUTPUT_FILE" 55 | ) 56 | } 57 | 58 | function export_rules { 59 | local VERSION="$1" 60 | echo "___________________________________________________________" 61 | echo "Exporting cppcheck version $VERSION" 62 | local WORKING_DIR="$TARGET_DIR/cppcheck-export-$VERSION" 63 | local SRC_URL="http://sourceforge.net/projects/cppcheck/files/cppcheck/$VERSION/cppcheck-$VERSION.tar.gz/download" 64 | local SRC_FILE="cppcheck-$VERSION.tar.gz" 65 | local CPPCHECK_DIR="$WORKING_DIR/cppcheck-$VERSION" 66 | 67 | prepare_working_dir "$WORKING_DIR" 68 | download_source "$SRC_URL" "$WORKING_DIR/$SRC_FILE" 69 | unzip_source "$WORKING_DIR" "$WORKING_DIR/$SRC_FILE" 70 | compile_source "$CPPCHECK_DIR" 71 | run_cppcheck_to_export_rules "$CPPCHECK_DIR" "$SCRIPT_DIR/cppcheck-$VERSION.xml" 72 | echo "-- success --" 73 | echo 74 | } 75 | 76 | check_project_dir_and_create_target_dir 77 | 78 | if [ -z "$1" ]; then 79 | echo "ERROR, please provide a list of cppcheck version" 1>&2 80 | echo "Example: ./export-rules.sh 1.68 1.69 1.70" 1>&2 81 | else 82 | for VERSION in "$@"; do 83 | export_rules "$VERSION" 84 | done 85 | fi 86 | -------------------------------------------------------------------------------- /src/main/java/org/sonarqube/cppcheck/CppcheckConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import com.google.common.base.Strings; 23 | import org.sonar.api.BatchExtension; 24 | import org.sonar.api.config.Settings; 25 | import org.sonar.api.utils.SonarException; 26 | 27 | import java.io.File; 28 | 29 | public class CppcheckConfiguration implements BatchExtension { 30 | 31 | public static final String CPPCHECK_REPORT_PATH_PROPERTY = "sonar.cppcheck.reportPath"; 32 | 33 | private final Settings settings; 34 | 35 | public CppcheckConfiguration(Settings settings) { 36 | this.settings = settings; 37 | } 38 | 39 | public File getCppcheckReportFile() { 40 | String cppcheckReportPath = settings.getString(CPPCHECK_REPORT_PATH_PROPERTY); 41 | if (Strings.isNullOrEmpty(cppcheckReportPath)) { 42 | throw new SonarException("Cppcheck report property found empty, you should run cppcheck externally and " + 43 | "import its report using " + CppcheckConfiguration.CPPCHECK_REPORT_PATH_PROPERTY + " property, for more information see the plugin documentation."); 44 | } 45 | File executable = new File(cppcheckReportPath); 46 | if (!executable.isFile()) { 47 | throw new SonarException("Cppcheck report is not found, please check property '" + CPPCHECK_REPORT_PATH_PROPERTY + "': " + cppcheckReportPath); 48 | } 49 | return executable; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/sonarqube/cppcheck/CppcheckPlugin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import com.google.common.collect.ImmutableList; 23 | import org.sonar.api.SonarPlugin; 24 | import org.sonar.api.config.PropertyDefinition; 25 | import org.sonar.api.resources.Qualifiers; 26 | 27 | import java.util.List; 28 | 29 | public class CppcheckPlugin extends SonarPlugin { 30 | 31 | private static final String CPPCHECK_SUBCATEGORY = "Cppcheck"; 32 | 33 | @Override 34 | public List getExtensions() { 35 | ImmutableList.Builder builder = ImmutableList.builder(); 36 | builder.add(CppcheckSensor.class); 37 | builder.add(CppcheckConfiguration.class); 38 | builder.add(new CppcheckRuleRepository("c")); 39 | builder.add(new CppcheckRuleRepository("cpp")); 40 | builder.add(PropertyDefinition.builder(CppcheckConfiguration.CPPCHECK_REPORT_PATH_PROPERTY) 41 | .subCategory(CPPCHECK_SUBCATEGORY) 42 | .name("Cppcheck Report Path") 43 | .description("Path to the CppCheck XML report, ex: report/cppcheck.xml") 44 | .onQualifiers(Qualifiers.PROJECT) 45 | .build()); 46 | return builder.build(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/sonarqube/cppcheck/CppcheckRuleRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import com.google.common.collect.Lists; 23 | import org.apache.commons.lang.StringUtils; 24 | import org.sonar.api.rules.Rule; 25 | import org.sonar.api.rules.RulePriority; 26 | import org.sonar.api.rules.RuleRepository; 27 | import org.sonar.api.utils.SonarException; 28 | 29 | import javax.xml.stream.XMLStreamException; 30 | import java.io.InputStream; 31 | import java.util.Collection; 32 | import java.util.List; 33 | 34 | public class CppcheckRuleRepository extends RuleRepository { 35 | 36 | static final String REPOSITORY_KEY = "cppcheck"; 37 | private static final String REPOSITORY_NAME = "Cppcheck"; 38 | 39 | public CppcheckRuleRepository(String language) { 40 | super(repositoryKeyForLanguage(language), language); 41 | setName(REPOSITORY_NAME); 42 | } 43 | 44 | @Override 45 | public List createRules() { 46 | List rules = Lists.newArrayList(); 47 | for (CppcheckXmlParser.Message message : load()) { 48 | Rule rule = Rule.create() 49 | .setKey(message.getId()) 50 | .setConfigKey(message.getId()) 51 | .setSeverity(RulePriority.MAJOR) 52 | .setName(message.getMsg()) 53 | .setDescription("

" + message.getVerbose() + "

"); 54 | 55 | String replacement = message.getReplacement(); 56 | if (replacement != null) { 57 | rule.setStatus(Rule.STATUS_DEPRECATED); 58 | String [] pieces = StringUtils.split(replacement, ':'); 59 | if (pieces.length == 1 || pieces[1].equalsIgnoreCase(getLanguage())) { 60 | rule.setDescription(rule.getDescription() + "

Deprecated

This rule is deprecated, use {rule:" + getLanguage() + ":" + pieces[0] + "} instead.

"); 61 | rules.add(rule); 62 | } 63 | } else { 64 | rules.add(rule); 65 | } 66 | } 67 | return rules; 68 | } 69 | 70 | private Collection load() { 71 | InputStream is = getClass().getResourceAsStream("/org/sonarqube/cppcheck.xml"); 72 | try { 73 | return CppcheckXmlParser.parse(is); 74 | } catch (XMLStreamException e) { 75 | throw new SonarException("Unable to load descriptions of rules for Cppcheck", e); 76 | } 77 | } 78 | 79 | public static String repositoryKeyForLanguage(String language) { 80 | return language + "-" + REPOSITORY_KEY; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/sonarqube/cppcheck/CppcheckSensor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import com.google.common.collect.Sets; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.sonar.api.batch.Sensor; 26 | import org.sonar.api.batch.SensorContext; 27 | import org.sonar.api.batch.fs.FileSystem; 28 | import org.sonar.api.component.ResourcePerspectives; 29 | import org.sonar.api.issue.Issuable; 30 | import org.sonar.api.profiles.RulesProfile; 31 | import org.sonar.api.resources.Project; 32 | import org.sonar.api.resources.Resource; 33 | import org.sonar.api.rules.Rule; 34 | import org.sonar.api.rules.RuleFinder; 35 | 36 | import java.io.File; 37 | import java.util.Collection; 38 | import java.util.Set; 39 | 40 | public class CppcheckSensor implements Sensor { 41 | 42 | private static final Logger LOG = LoggerFactory.getLogger(CppcheckSensor.class); 43 | 44 | private final CppcheckConfiguration configuration; 45 | private final RulesProfile profile; 46 | private final RuleFinder ruleFinder; 47 | private final FileSystem fileSystem; 48 | private final ResourcePerspectives resourcePerspectives; 49 | 50 | public CppcheckSensor(CppcheckConfiguration configuration, RulesProfile profile, RuleFinder ruleFinder, FileSystem fileSystem, ResourcePerspectives resourcePerspectives) { 51 | this.configuration = configuration; 52 | this.profile = profile; 53 | this.ruleFinder = ruleFinder; 54 | this.fileSystem = fileSystem; 55 | this.resourcePerspectives = resourcePerspectives; 56 | } 57 | 58 | private boolean hasRulesEnabledFor(String key) { 59 | return !profile.getActiveRulesByRepository(CppcheckRuleRepository.repositoryKeyForLanguage(key)).isEmpty(); 60 | } 61 | 62 | @Override 63 | public boolean shouldExecuteOnProject(Project project) { 64 | return (fileSystem.hasFiles(fileSystem.predicates().hasLanguages("c")) && hasRulesEnabledFor("c")) || 65 | (fileSystem.hasFiles(fileSystem.predicates().hasLanguages("cpp")) && hasRulesEnabledFor("cpp")); 66 | } 67 | 68 | @Override 69 | public void analyse(Project project, SensorContext context) { 70 | File report = configuration.getCppcheckReportFile(); 71 | Collection messages = CppcheckXmlParser.parse(report); 72 | saveAll(project, context, "c", messages); 73 | saveAll(project, context, "cpp", messages); 74 | } 75 | 76 | private void saveAll(Project project, SensorContext context, String language, Collection messages) { 77 | if (hasRulesEnabledFor(language)) { 78 | Set indexedFiles = Sets.newHashSet(fileSystem.files(fileSystem.predicates().hasLanguage(language))); 79 | for (CppcheckXmlParser.Message message : messages) { 80 | save(project, context, language, indexedFiles, message); 81 | } 82 | } 83 | } 84 | 85 | private Rule getRule(String key, String id) { 86 | return ruleFinder.findByKey(CppcheckRuleRepository.repositoryKeyForLanguage(key), id); 87 | } 88 | 89 | private void save(Project project, SensorContext context, String language, Set indexedFiles, CppcheckXmlParser.Message message) { 90 | Rule rule = getRule(language, message.getId()); 91 | if (rule == null) { 92 | LOG.warn("No such rule in Sonar, so issue from Cppcheck will be ignored: {}", message.getId()); 93 | return; 94 | } 95 | final Resource resource; 96 | if (message.getFilename() == null) { 97 | resource = project; 98 | } else { 99 | File file = new File(message.getFilename()).getAbsoluteFile(); 100 | if (!indexedFiles.contains(file)) { 101 | return; 102 | } 103 | resource = org.sonar.api.resources.File.fromIOFile(file, project); 104 | if (!context.isIndexed(resource, false)) { 105 | LOG.warn("File not analysed by Sonar, so issue from Cppcheck will be ignored: {}", file); 106 | return; 107 | } 108 | } 109 | save(resource, rule, message); 110 | } 111 | 112 | void save(Resource resource, Rule rule, CppcheckXmlParser.Message message) { 113 | Issuable issuable = resourcePerspectives.as(Issuable.class, resource); 114 | if (issuable == null) { 115 | return; 116 | } 117 | Issuable.IssueBuilder issue = issuable.newIssueBuilder() 118 | .ruleKey(rule.ruleKey()) 119 | .message(message.getMsg()); 120 | if (message.getLine() != null) { 121 | int line = Integer.parseInt(message.getLine()); 122 | if (line != 0) { 123 | issue.line(line); 124 | } 125 | } 126 | issuable.addIssue(issue.build()); 127 | } 128 | 129 | @Override 130 | public String toString() { 131 | return "Cppcheck"; 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/main/java/org/sonarqube/cppcheck/CppcheckXmlParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import com.google.common.collect.ImmutableList; 23 | import com.google.common.io.Closeables; 24 | import org.codehaus.staxmate.in.SMHierarchicCursor; 25 | import org.codehaus.staxmate.in.SMInputCursor; 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | import org.sonar.api.utils.SonarException; 29 | import org.sonar.api.utils.StaxParser; 30 | 31 | import javax.annotation.Nullable; 32 | import javax.annotation.WillClose; 33 | import javax.xml.stream.XMLStreamException; 34 | import java.io.File; 35 | import java.io.InputStream; 36 | import java.util.Collection; 37 | 38 | public final class CppcheckXmlParser implements StaxParser.XmlStreamHandler { 39 | 40 | private static final Logger LOG = LoggerFactory.getLogger(CppcheckXmlParser.class); 41 | 42 | private CppcheckXmlParser() { 43 | } 44 | 45 | public static class Message { 46 | 47 | @Nullable 48 | private final String replacement; 49 | 50 | private final String id; 51 | private final String severity; 52 | private final String msg; 53 | private final String verbose; 54 | private final String filename; 55 | private final String line; 56 | 57 | public Message(@Nullable String replacement, String id, String severity, String msg, String verbose) { 58 | this.replacement = replacement; 59 | this.id = id; 60 | this.severity = severity; 61 | this.msg = msg; 62 | this.verbose = verbose; 63 | this.filename = null; 64 | this.line = null; 65 | } 66 | 67 | public Message(String id, String severity, String msg, String verbose, @Nullable String filename, @Nullable String line) { 68 | this.replacement = null; 69 | this.id = id; 70 | this.severity = severity; 71 | this.msg = msg; 72 | this.verbose = verbose; 73 | this.filename = filename; 74 | this.line = line; 75 | } 76 | 77 | @Nullable 78 | public String getReplacement() { 79 | return replacement; 80 | } 81 | 82 | public String getId() { 83 | return id; 84 | } 85 | 86 | public String getSeverity() { 87 | return severity; 88 | } 89 | 90 | public String getMsg() { 91 | return msg; 92 | } 93 | 94 | public String getVerbose() { 95 | return verbose; 96 | } 97 | 98 | @Nullable 99 | public String getFilename() { 100 | return filename; 101 | } 102 | 103 | @Nullable 104 | public String getLine() { 105 | return line; 106 | } 107 | 108 | } 109 | 110 | public static Collection parse(@WillClose InputStream is) throws XMLStreamException { 111 | CppcheckXmlParser handler = new CppcheckXmlParser(); 112 | try { 113 | new StaxParser(handler).parse(is); 114 | } finally { 115 | Closeables.closeQuietly(is); 116 | } 117 | return handler.result.build(); 118 | } 119 | 120 | public static Collection parse(File file) { 121 | CppcheckXmlParser handler = new CppcheckXmlParser(); 122 | try { 123 | new StaxParser(handler).parse(file); 124 | } catch (XMLStreamException e) { 125 | throw new SonarException("Unable to parse file: " + file, e); 126 | } 127 | return handler.result.build(); 128 | } 129 | 130 | private final ImmutableList.Builder result = ImmutableList.builder(); 131 | 132 | @Override 133 | public void stream(SMHierarchicCursor rootCursor) throws XMLStreamException { 134 | rootCursor.advance(); 135 | SMInputCursor cppcheckCursor = rootCursor.childElementCursor(); 136 | while (cppcheckCursor.getNext() != null) { 137 | String localName = cppcheckCursor.getLocalName(); 138 | if ("cppcheck".equals(localName)) { 139 | String version = cppcheckCursor.getAttrValue("version"); 140 | if (version != null) { 141 | LOG.info("Cppcheck version: " + version); 142 | } 143 | } else if ("errors".equals(localName)) { 144 | loopOnErrors(cppcheckCursor.childElementCursor("error")); 145 | } else { 146 | throw new IllegalStateException("Unexpected cppcheck file format, unexpected xml element: " + localName); 147 | } 148 | } 149 | 150 | loopOnErrors(cppcheckCursor); 151 | } 152 | 153 | private void loopOnErrors(SMInputCursor error) throws XMLStreamException { 154 | while (error.getNext() != null) { 155 | String id = error.getAttrValue("id"); 156 | String severity = error.getAttrValue("severity"); 157 | String msg = error.getAttrValue("msg"); 158 | String verbose = error.getAttrValue("verbose"); 159 | 160 | String replacement = error.getAttrValue("SonarQube"); 161 | 162 | SMInputCursor location = error.childElementCursor("location"); 163 | if (location.getNext() != null) { 164 | String filename = location.getAttrValue("file"); 165 | String line = location.getAttrValue("line"); 166 | result.add(new Message(id, severity, msg, verbose, filename, line)); 167 | } else { 168 | result.add(new Message(replacement, id, severity, msg, verbose)); 169 | } 170 | } 171 | } 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/main/java/org/sonarqube/cppcheck/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | @javax.annotation.ParametersAreNonnullByDefault 21 | package org.sonarqube.cppcheck; 22 | -------------------------------------------------------------------------------- /src/test/java/org/sonarqube/cppcheck/CppcheckConfigurationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import org.junit.Before; 23 | import org.junit.Rule; 24 | import org.junit.Test; 25 | import org.junit.rules.ExpectedException; 26 | import org.sonar.api.config.Settings; 27 | import org.sonar.api.utils.SonarException; 28 | 29 | import java.io.File; 30 | 31 | import static org.fest.assertions.Assertions.assertThat; 32 | 33 | public class CppcheckConfigurationTest { 34 | 35 | @Rule 36 | public ExpectedException thrown = ExpectedException.none(); 37 | 38 | private Settings settings; 39 | private CppcheckConfiguration configuration; 40 | 41 | @Before 42 | public void setUp() { 43 | settings = new Settings(); 44 | configuration = new CppcheckConfiguration(settings); 45 | } 46 | 47 | @Test 48 | public void should_check_for_missing_property() { 49 | thrown.expect(SonarException.class); 50 | thrown.expectMessage("Cppcheck report property found empty, you should run cppcheck externally and import its report using sonar.cppcheck.reportPath property, for more information see the plugin documentation."); 51 | configuration.getCppcheckReportFile(); 52 | } 53 | 54 | @Test 55 | public void should_check_correctness_of_path_to_cppcheck_report() { 56 | String reportPath = "not-existing"; 57 | settings.setProperty(CppcheckConfiguration.CPPCHECK_REPORT_PATH_PROPERTY, reportPath); 58 | thrown.expect(SonarException.class); 59 | thrown.expectMessage("Cppcheck report is not found, please check property 'sonar.cppcheck.reportPath': not-existing"); 60 | configuration.getCppcheckReportFile(); 61 | } 62 | 63 | @Test 64 | public void should_return_path_to_cppcheck_report() { 65 | String reportPath = "src/test/resources/cppcheck2.xml"; 66 | settings.setProperty(CppcheckConfiguration.CPPCHECK_REPORT_PATH_PROPERTY, reportPath); 67 | assertThat(configuration.getCppcheckReportFile()).isEqualTo(new File(reportPath)); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/org/sonarqube/cppcheck/CppcheckPluginTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import org.junit.Test; 23 | 24 | import static org.fest.assertions.Assertions.assertThat; 25 | 26 | public class CppcheckPluginTest { 27 | @Test 28 | public void testExtensions() throws Exception { 29 | CppcheckPlugin cppcheckPlugin = new CppcheckPlugin(); 30 | assertThat(cppcheckPlugin.getExtensions()).hasSize(5); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/org/sonarqube/cppcheck/CppcheckRuleRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import com.google.common.annotations.VisibleForTesting; 23 | import com.google.common.base.Throwables; 24 | import com.google.common.collect.Lists; 25 | import com.google.common.collect.Maps; 26 | import com.google.common.io.Closeables; 27 | import org.apache.commons.io.FileUtils; 28 | import org.apache.commons.lang.StringEscapeUtils; 29 | import org.apache.commons.lang.StringUtils; 30 | import org.custommonkey.xmlunit.Diff; 31 | import org.custommonkey.xmlunit.XMLUnit; 32 | import org.junit.Test; 33 | import org.sonar.api.rules.Rule; 34 | import org.sonar.api.rules.RulePriority; 35 | 36 | import java.io.File; 37 | import java.io.FileReader; 38 | import java.io.FileWriter; 39 | import java.io.IOException; 40 | import java.io.PrintWriter; 41 | import java.util.Collection; 42 | import java.util.Collections; 43 | import java.util.List; 44 | import java.util.Map; 45 | import java.util.Properties; 46 | import java.util.TreeMap; 47 | 48 | import static org.fest.assertions.Assertions.assertThat; 49 | 50 | public class CppcheckRuleRepositoryTest { 51 | 52 | @Test 53 | public void test() throws Exception { 54 | CppcheckRuleRepository repository = new CppcheckRuleRepository("cpp"); 55 | List rules = repository.createRules(); 56 | assertThat(rules).onProperty("name").excludes(null, ""); 57 | assertThat(rules).onProperty("description").excludes(null, ""); 58 | assertThat(rules).onProperty("severity").containsOnly(RulePriority.MAJOR); 59 | 60 | int numberOfDeprecated = 0; 61 | for (Rule rule : rules) { 62 | if (Rule.STATUS_DEPRECATED.equals(rule.getStatus())) { 63 | numberOfDeprecated++; 64 | } 65 | } 66 | 67 | assertThat(rules.size()).as("total").isEqualTo(350); 68 | System.out.println("Number of deprecated rules: " + numberOfDeprecated); 69 | assertThat(numberOfDeprecated).as("deprecated").isGreaterThan(90); 70 | } 71 | 72 | @Test 73 | public void update() throws Exception { 74 | generate(); 75 | Diff diff = XMLUnit.compareXML( 76 | new FileReader(new File("target/generated-cppcheck.xml")), 77 | new FileReader(new File("src/main/resources/org/sonarqube/cppcheck.xml")) 78 | ); 79 | assertThat(diff.identical()).as("Generated cppcheck.xml identical to currently used").isTrue(); 80 | } 81 | 82 | public static void generate() throws Exception { 83 | PrintWriter writer = new PrintWriter(new FileWriter("target/generated-cppcheck.xml")); 84 | TreeMap map = Maps.newTreeMap(); 85 | String prevVersion = ""; 86 | for (String version : listVersions()) { 87 | for (CppcheckXmlParser.Message msg : CppcheckXmlParser.parse(new File("src/main/files/cppcheck-" + version + ".xml"))) { 88 | RuleDescription ruleDescription = map.get(msg.getId()); 89 | if (ruleDescription == null) { 90 | // new rule 91 | ruleDescription = new RuleDescription(); 92 | map.put(msg.getId(), ruleDescription); 93 | ruleDescription.minVersion = version; 94 | } else { 95 | // existing rule 96 | if (!prevVersion.equals(ruleDescription.maxVersion)) { 97 | System.err.println("Merge of rule, which appear and disappear from version to version: " + msg.getId()); 98 | } 99 | } 100 | ruleDescription.maxVersion = version; 101 | // Supposed that message from newer version is better 102 | ruleDescription.msg = msg; 103 | } 104 | prevVersion = version; 105 | } 106 | 107 | Properties replacements = loadReplacements(); 108 | 109 | writer.println(""); 110 | writer.println(""); 111 | for (Map.Entry entry : map.entrySet()) { 112 | RuleDescription description = entry.getValue(); 113 | final String versions; 114 | if (description.maxVersion.equals(prevVersion)) { 115 | versions = " (since Cppcheck " + description.minVersion + ")"; 116 | } else if (description.minVersion.equals(description.maxVersion)) { 117 | versions = " (Cppcheck " + description.minVersion + ")"; 118 | } else { 119 | versions = " (Cppcheck " + description.minVersion + "-" + description.maxVersion + ")"; 120 | } 121 | writer.append("") 129 | .println(); 130 | } 131 | writer.println(""); 132 | writer.println(""); 133 | writer.close(); 134 | } 135 | 136 | private static List listVersions() { 137 | Collection files = FileUtils.listFiles(new File("src/main/files"), new String[]{"xml"}, false); 138 | List names = Lists.newArrayList(); 139 | for (File file : files) { 140 | names.add(StringUtils.substringBetween(file.getName(), "cppcheck-", ".xml")); 141 | } 142 | Collections.sort(names); 143 | return names; 144 | } 145 | 146 | private static class RuleDescription { 147 | String minVersion, maxVersion; 148 | CppcheckXmlParser.Message msg; 149 | } 150 | 151 | @VisibleForTesting 152 | static Properties loadReplacements() { 153 | Properties properties = new Properties(); 154 | FileReader reader = null; 155 | try { 156 | reader = new FileReader("src/main/files/cppcheck_replacements.properties"); 157 | properties.load(reader); 158 | } catch (IOException e) { 159 | throw Throwables.propagate(e); 160 | } finally { 161 | Closeables.closeQuietly(reader); 162 | } 163 | return properties; 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /src/test/java/org/sonarqube/cppcheck/CppcheckSensorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import com.google.common.collect.ImmutableList; 23 | import org.junit.Before; 24 | import org.junit.Test; 25 | import org.junit.rules.ExpectedException; 26 | import org.mockito.Mockito; 27 | import org.sonar.api.batch.SensorContext; 28 | import org.sonar.api.batch.fs.FilePredicate; 29 | import org.sonar.api.batch.fs.internal.DefaultFileSystem; 30 | import org.sonar.api.profiles.RulesProfile; 31 | import org.sonar.api.resources.Project; 32 | import org.sonar.api.resources.Resource; 33 | import org.sonar.api.rules.ActiveRule; 34 | import org.sonar.api.rules.Rule; 35 | import org.sonar.api.rules.RuleFinder; 36 | 37 | import java.io.File; 38 | import java.util.Collections; 39 | 40 | import static org.fest.assertions.Assertions.assertThat; 41 | import static org.mockito.Matchers.any; 42 | import static org.mockito.Matchers.anyString; 43 | import static org.mockito.Mockito.mock; 44 | import static org.mockito.Mockito.spy; 45 | import static org.mockito.Mockito.times; 46 | import static org.mockito.Mockito.verify; 47 | import static org.mockito.Mockito.when; 48 | 49 | public class CppcheckSensorTest { 50 | 51 | private RuleFinder ruleFinder; 52 | private RulesProfile profile; 53 | private CppcheckConfiguration configuration; 54 | private CppcheckSensor sensor; 55 | private DefaultFileSystem fileSystem; 56 | 57 | @org.junit.Rule 58 | public ExpectedException thrown = ExpectedException.none(); 59 | 60 | @Before 61 | public void setUp() { 62 | ruleFinder = mock(RuleFinder.class); 63 | profile = mock(RulesProfile.class); 64 | configuration = mock(CppcheckConfiguration.class); 65 | fileSystem = spy(new DefaultFileSystem(new File("src/test/resources/cppcheck"))); 66 | 67 | sensor = spy(new CppcheckSensor(configuration, profile, ruleFinder, fileSystem, null)); 68 | Mockito.doNothing().when(sensor).save(any(Resource.class), Mockito.any(Rule.class), any(CppcheckXmlParser.Message.class)); 69 | } 70 | 71 | @Test 72 | public void shouldExecuteOnProject() { 73 | Project project = mock(Project.class); 74 | assertThat(sensor.shouldExecuteOnProject(project)).isFalse(); 75 | 76 | when(profile.getActiveRulesByRepository("cpp-cppcheck")) 77 | .thenReturn(Collections.singletonList(mock(ActiveRule.class))); 78 | when(fileSystem.hasFiles(any(FilePredicate.class))).thenReturn(false); 79 | assertThat(sensor.shouldExecuteOnProject(project)).isFalse(); 80 | 81 | when(fileSystem.hasFiles(any(FilePredicate.class))).thenReturn(true); 82 | assertThat(sensor.shouldExecuteOnProject(project)).isTrue(); 83 | 84 | // no active rules: 85 | when(profile.getActiveRulesByRepository("cpp-cppcheck")) 86 | .thenReturn(Collections.emptyList()); 87 | assertThat(sensor.shouldExecuteOnProject(project)).isFalse(); 88 | } 89 | 90 | @Test 91 | public void should_parse() { 92 | when(ruleFinder.findByKey(anyString(), anyString())) 93 | .thenReturn(null) 94 | .thenReturn(Rule.create()); 95 | 96 | Project project = mock(Project.class); 97 | 98 | SensorContext context = mock(SensorContext.class); 99 | when(context.isIndexed(Mockito.eq((Resource) null), Mockito.eq(false))) 100 | .thenReturn(false) 101 | .thenReturn(true); 102 | 103 | when(profile.getActiveRulesByRepository(anyString())).thenReturn(ImmutableList.of(mock(ActiveRule.class))); 104 | 105 | when(configuration.getCppcheckReportFile()).thenReturn(new File("src/test/resources/cppcheck2.xml")); 106 | sensor.analyse(project, context); 107 | 108 | verify(sensor, times(2)).save(any(Resource.class), Mockito.any(Rule.class), any(CppcheckXmlParser.Message.class)); 109 | } 110 | 111 | @Test 112 | public void test_toString() { 113 | assertThat(sensor.toString()).isEqualTo("Cppcheck"); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/test/java/org/sonarqube/cppcheck/CppcheckXmlParserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube :: Cppcheck Plugin 3 | * Copyright (C) 2016-2016 SonarSource SA 4 | * mailto:contact AT sonarsource DOT com 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package org.sonarqube.cppcheck; 21 | 22 | import com.google.common.collect.Iterables; 23 | import org.apache.commons.io.FileUtils; 24 | import org.junit.Rule; 25 | import org.junit.Test; 26 | import org.junit.rules.ExpectedException; 27 | import org.sonar.api.utils.SonarException; 28 | 29 | import java.io.File; 30 | import java.util.Collection; 31 | 32 | import static org.fest.assertions.Assertions.assertThat; 33 | 34 | public class CppcheckXmlParserTest { 35 | 36 | @Rule 37 | public ExpectedException thrown = ExpectedException.none(); 38 | 39 | @Test 40 | public void test2() { 41 | File file = FileUtils.toFile(getClass().getResource("/cppcheck2.xml")); 42 | 43 | Collection messages = CppcheckXmlParser.parse(file); 44 | assertThat(messages.size()).isEqualTo(9); 45 | 46 | CppcheckXmlParser.Message message = messages.iterator().next(); 47 | assertThat(message.getId()).isEqualTo("autoVariables"); 48 | assertThat(message.getMsg()).isEqualTo("Assigning address of local auto-variable to a function parameter."); 49 | assertThat(message.getVerbose()).startsWith("Dangerous assignment"); 50 | assertThat(message.getSeverity()).isEqualTo("error"); 51 | assertThat(message.getLine()).isEqualTo("4"); 52 | assertThat(message.getFilename()).isEqualTo("src/autoVariables/bad.c"); 53 | } 54 | 55 | @Test 56 | public void test3() { 57 | File file = FileUtils.toFile(getClass().getResource("/no-location.xml")); 58 | Collection messages = CppcheckXmlParser.parse(file); 59 | CppcheckXmlParser.Message message = Iterables.getOnlyElement(messages); 60 | assertThat(message.getMsg()).isNotNull(); 61 | assertThat(message.getLine()).isNull(); 62 | assertThat(message.getFilename()).isNull(); 63 | } 64 | 65 | @Test 66 | public void should_throw_exception() throws Exception { 67 | thrown.expect(SonarException.class); 68 | thrown.expectMessage("Unable to parse file: notfound.xml"); 69 | CppcheckXmlParser.parse(new File("notfound.xml")); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/test/resources/cppcheck2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/test/resources/no-location.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | --------------------------------------------------------------------------------