├── .github └── ISSUE_TEMPLATE │ ├── BUG_REPORT.md │ ├── FEATURE_REQUEST.md │ ├── QUESTION.md │ └── REGRESSION.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── SwitchProfiles.png ├── build-and-deploy.sh ├── commons ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── backelite │ └── sonarqube │ └── commons │ ├── Constants.java │ ├── MeasureUtil.java │ ├── TestFileFinder.java │ ├── TestFileFinders.java │ └── surefire │ ├── StaxParser.java │ ├── SurefireReportParser.java │ ├── SurefireSensor.java │ ├── SurefireStaxHandler.java │ ├── UnitTestClassReport.java │ ├── UnitTestIndex.java │ └── UnitTestResult.java ├── docs └── sonarqube-fastlane.md ├── objclang ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── backelite │ │ │ └── sonarqube │ │ │ └── objectivec │ │ │ ├── ObjectiveCConstants.java │ │ │ ├── ObjectiveCSquidSensor.java │ │ │ ├── issues │ │ │ ├── ObjectiveCProfile.java │ │ │ ├── fauxpas │ │ │ │ ├── FauxPasProfile.java │ │ │ │ ├── FauxPasProfileImporter.java │ │ │ │ ├── FauxPasReportParser.java │ │ │ │ ├── FauxPasRulesDefinition.java │ │ │ │ └── FauxPasSensor.java │ │ │ └── oclint │ │ │ │ ├── OCLintParser.java │ │ │ │ ├── OCLintProfile.java │ │ │ │ ├── OCLintProfileImporter.java │ │ │ │ ├── OCLintRuleSeverity.java │ │ │ │ ├── OCLintRulesDefinition.java │ │ │ │ ├── OCLintSensor.java │ │ │ │ └── OCLintXMLStreamHandler.java │ │ │ ├── lang │ │ │ ├── ObjectiveCAstScanner.java │ │ │ ├── ObjectiveCConfiguration.java │ │ │ ├── api │ │ │ │ ├── ObjectiveCGrammar.java │ │ │ │ ├── ObjectiveCKeyword.java │ │ │ │ ├── ObjectiveCMetric.java │ │ │ │ ├── ObjectiveCPunctuator.java │ │ │ │ └── ObjectiveCTokenType.java │ │ │ ├── checks │ │ │ │ └── CheckList.java │ │ │ ├── core │ │ │ │ └── ObjectiveC.java │ │ │ ├── lexer │ │ │ │ └── ObjectiveCLexer.java │ │ │ └── parser │ │ │ │ ├── ObjectiveCGrammarImpl.java │ │ │ │ └── ObjectiveCParser.java │ │ │ └── surefire │ │ │ └── ObjectiveCTestFileFinder.java │ ├── resources │ │ ├── com │ │ │ └── sonar │ │ │ │ └── sqale │ │ │ │ ├── fauxpas-model.xml │ │ │ │ └── oclint-model.xml │ │ └── org │ │ │ └── sonar │ │ │ └── plugins │ │ │ ├── fauxpas │ │ │ ├── profile-fauxpas.xml │ │ │ └── rules.json │ │ │ └── oclint │ │ │ ├── profile-oclint.xml │ │ │ └── rules.txt │ └── shell │ │ └── run-sonar.sh │ └── test │ ├── java │ └── com │ │ └── backelite │ │ └── sonarqube │ │ └── objectivec │ │ └── lang │ │ ├── ObjectiveCAstScannerTest.java │ │ ├── api │ │ └── ObjectiveCPunctuatorTest.java │ │ └── lexer │ │ └── ObjectiveCLexerTest.java │ └── resources │ ├── Profile.m │ └── objcSample.h ├── pom.xml ├── screenshot.png ├── sonar-project.properties ├── sonar-swift-plugin ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── backelite │ │ │ └── sonarqube │ │ │ └── swift │ │ │ ├── SwiftPlugin.java │ │ │ ├── complexity │ │ │ ├── LizardReportParser.java │ │ │ └── LizardSensor.java │ │ │ └── coverage │ │ │ ├── CoberturaReportParser.java │ │ │ └── CoberturaSensor.java │ └── shell │ │ └── run-sonar-swift.sh │ └── test │ └── resources │ └── coverage │ ├── dir1 │ └── cobertura.xml │ ├── dir2 │ └── cobertura.xml │ └── dir3 │ └── cobertura.xml ├── swiftlang ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── backelite │ │ │ └── sonarqube │ │ │ └── swift │ │ │ ├── SwiftConstants.java │ │ │ ├── SwiftSquidSensor.java │ │ │ ├── issues │ │ │ ├── SwiftProfile.java │ │ │ ├── swiftlint │ │ │ │ ├── SwiftLintProfile.java │ │ │ │ ├── SwiftLintProfileImporter.java │ │ │ │ ├── SwiftLintReportParser.java │ │ │ │ ├── SwiftLintRulesDefinition.java │ │ │ │ └── SwiftLintSensor.java │ │ │ └── tailor │ │ │ │ ├── TailorProfile.java │ │ │ │ ├── TailorProfileImporter.java │ │ │ │ ├── TailorReportParser.java │ │ │ │ ├── TailorRulesDefinition.java │ │ │ │ └── TailorSensor.java │ │ │ ├── lang │ │ │ ├── SwiftAstScanner.java │ │ │ ├── SwiftConfiguration.java │ │ │ ├── SwiftFileSystem.java │ │ │ ├── api │ │ │ │ ├── SwiftGrammar.java │ │ │ │ ├── SwiftKeyword.java │ │ │ │ └── SwiftMetric.java │ │ │ ├── checks │ │ │ │ └── CheckList.java │ │ │ ├── core │ │ │ │ └── Swift.java │ │ │ ├── lexer │ │ │ │ └── SwiftLexer.java │ │ │ └── parser │ │ │ │ ├── SwiftGrammarImpl.java │ │ │ │ └── SwiftParser.java │ │ │ └── surefire │ │ │ └── SwiftTestFileFinder.java │ └── resources │ │ ├── com │ │ └── sonar │ │ │ └── sqale │ │ │ ├── swiftlint-model.xml │ │ │ └── tailor-model.xml │ │ └── org │ │ └── sonar │ │ └── plugins │ │ ├── swiftlint │ │ ├── profile-swiftlint.xml │ │ └── rules.json │ │ └── tailor │ │ ├── profile-tailor.xml │ │ └── rules.json │ └── test │ ├── java │ └── com │ │ └── backelite │ │ └── sonarqube │ │ └── swift │ │ └── lang │ │ ├── SwiftAstScannerTest.java │ │ └── lexer │ │ └── SwiftLexerTest.java │ └── resources │ └── Test.swift ├── tools ├── updateFauxPasRules.groovy ├── updateOCLintRules.groovy ├── updateSwiftLintProfile.groovy └── updateTailorProfile.groovy └── updateVersion.sh /.github/ISSUE_TEMPLATE/BUG_REPORT.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug Report 3 | about: If something isn't working as expected 🤔 4 | 5 | --- 6 | 7 | 8 | 9 | ### New Issue Checklist 10 | 11 | - [ ] Updated the plugin to the latest version 12 | - [ ] I read the [Contribution Guidelines](https://github.com/Backelite/sonar-swift/blob/master/CONTRIBUTING.md) 13 | - [ ] I read the [documentation](https://github.com/Backelite/sonar-swift/wiki) 14 | - [ ] I searched for existing [GitHub issues](https://github.com/Backelite/sonar-swift/issues) 15 | 16 | ### Issue Description 17 | 18 | 19 | ##### Command executed 20 | 21 | 22 | ##### Complete output when running fastlane, including the stack trace and command used 23 | 26 | 27 |
28 |
 [REPLACE THIS WITH YOUR INFORMATION] 
29 |
30 | 31 | ### Environment 32 | 33 | 34 |
35 |
 [REPLACE THIS WITH YOUR INFORMATION] 
36 |
37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | about: A suggestion for a new feature ✨ 4 | 5 | --- 6 | 7 | ### Feature Request 8 | 9 | #### Motivation Behind Feature 10 | 11 | 12 | #### Feature Description 13 | 14 | 15 | 16 | 17 | #### Alternatives or Workarounds 18 | 19 | 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/QUESTION.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ❓ Support Question 3 | about: Not sure how something works or how to implement some functionality? Ask us here! (But please check the docs first 🙃) 4 | 5 | --- 6 | 7 | ### Question Checklist 8 | 9 | - [ ] Updated the plugin to the latest version 10 | - [ ] I read the [Contribution Guidelines](https://github.com/Backelite/sonar-swift/blob/master/CONTRIBUTING.md) 11 | - [ ] I read the [documentation](https://github.com/Backelite/sonar-swift/wiki) 12 | - [ ] I searched for existing [GitHub issues](https://github.com/Backelite/sonar-swift/issues) 13 | 14 | ### Question Subject 15 | 16 | 17 | 18 | 19 | 20 | ### Question Description 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/REGRESSION.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 😱 Regression 3 | about: If a recent release broke a feature 😬 (Please make sure you know the last known working release version) 4 | 5 | --- 6 | 7 | 8 | 9 | ### New Regression Checklist 10 | 11 | - [ ] Updated the plugin to the latest version 12 | - [ ] I read the [Contribution Guidelines](https://github.com/Backelite/sonar-swift/blob/master/CONTRIBUTING.md) 13 | - [ ] I read the [documentation](https://github.com/Backelite/sonar-swift/wiki) 14 | - [ ] I searched for existing [GitHub issues](https://github.com/Backelite/sonar-swift/issues) 15 | 16 | ### Regression Information 17 | 18 | - Breaking version: [e.g. `x.y.z`] 19 | - Last working version: [e.g. `x.y.z`] 20 | 21 | ### Regression Description 22 | 23 | 24 | ##### Complete output when running the plugin, including the stack trace and command used 25 | 26 | 27 | 28 |
29 |
[INSERT OUTPUT HERE]
30 |
31 | 32 | ### Environment 33 | 34 | 35 | 36 |
37 |
[INSERT OUTPUT HERE]
38 |
39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .settings/ 4 | target/ 5 | 6 | # Exclude OS X folder attributes 7 | .DS_Store 8 | 9 | # IntelliJ files 10 | *.ipr 11 | *.iml 12 | *.iws 13 | .idea 14 | 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - openjdk11 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at oss@backelite.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.4, available at [http://contributor-covenant.org/version/1/4](http://contributor-covenant.org/version/1/4/). -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to _SonarQube Plugin for Swift_ 2 | 3 | The following is a set of guidelines for contributing to _SonarQube Plugin for Swift_ on GitHub. 4 | 5 | > Above all, thank you for your interest in the project and for taking the time to contribute! 👍 6 | 7 | ## I want to report a problem or ask a question 8 | 9 | Before submitting a new GitHub issue, please make sure to 10 | 11 | - Check out the [documentation](https://github.com/Backelite/sonar-swift/tree/develop/docs). 12 | - Check out the README and especially the usage guide. 13 | - Search for [existing GitHub issues](https://github.com/Backelite/sonar-swift/issues). 14 | 15 | If the above doesn't help, please [submit an issue](https://github.com/Backelite/sonar-swift/issues) on GitHub and provide information about your setup (SonarQube version, etc.) 16 | 17 | **Note**: If you want to report a regression in *SonarQube Plugin for Swift* (something that has worked before, but broke with a new release), please mark your issue title as such using `[Regression] Your title here`. This enables us to quickly detect and fix regressions. 18 | 19 | ## I want to contribute to _SonarQube Plugin for Swift_ 20 | 21 | ### Prerequisites 22 | 23 | To develop _SonarQube Plugin for Swift_, you will need to meet the prerequisites as specified in the [README](https://github.com/Backelite/sonar-swift#prerequisites). 24 | 25 | ### Checking out the repository 26 | 27 | - Make sure you are on the *develop* branch: https://github.com/Backelite/sonar-swift/tree/develop 28 | - Click the “Fork” button in the upper right corner of repo 29 | - Clone your fork: 30 | - `git clone https://github.com//sonar-swift.git` 31 | - Learn more about how to manage your fork: 32 | - Create a new branch to work on: 33 | - `git checkout -b ` 34 | - A good name for a branch describes the thing you’ll be working on, e.g. `add-swiftlint-rules`, `fix-swift-lexer`, etc. 35 | 36 | That’s it! Now you’re ready to work on _SonarQube Plugin for Swift_. 37 | 38 | ### Things to keep in mind 39 | 40 | - Please do not change the minimum SonarQube version 41 | - Always document new public methods and properties 42 | 43 | ### Testing your local changes 44 | 45 | Before opening a pull request, please make sure your changes don't break things. 46 | 47 | - The project and the plugin should build without warnings 48 | - The [Swift Language Weather](https://github.com/JakeLin/SwiftLanguageWeather) project should run without issues 49 | 50 | ### Submitting the PR 51 | 52 | When the coding is done and you’ve finished testing your changes, you are ready to submit the PR to the [main repo](https://github.com/Backelite/sonar-swift). Again, make sure you submit your PR to the *develop* branch: https://github.com/Backelite/sonar-swift/tree/develop 53 | 54 | Some best practices are: 55 | 56 | - Use a descriptive title 57 | - Link the issues that are related to your PR in the body 58 | 59 | ## Code of Conduct 60 | 61 | Help us keep _SonarQube Plugin for Swift_ open and inclusive. Please read and follow our [Code of Conduct](CODE_OF_CONDUCT.md). 62 | 63 | ## Above All, Thanks for Your Contributions 64 | 65 | Thank you for reading to the end, and for taking the time to contribute to the project! If you include the 🔑 emoji at the top of the body of your issue or pull request, we'll know that you've given this your full attention and are doing your best to help! 66 | 67 | ## License 68 | 69 | This project is licensed under the terms of the GNU LGPL v3 license. See the [LICENSE](./LICENSE.md) file for more info. 70 | 71 | _These contribution guidelines were adapted from [_fastlane_](https://github.com/fastlane/fastlane) guides._ -------------------------------------------------------------------------------- /SwitchProfiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/sonar-swift/a5e219515cd39701aa5c8d93f954a64acff3aa82/SwitchProfiles.png -------------------------------------------------------------------------------- /build-and-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube. 4 | # Copyright © 2015 Backelite (${email}) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (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 14 | # GNU 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, see . 18 | # 19 | 20 | # Build and install snapshot plugin in Sonar 21 | 22 | # Build first and check status 23 | mvn clean license:format install 24 | if [ "$?" != 0 ]; then 25 | echo "ERROR - Java build failed!" 1>&2 26 | exit $? 27 | fi 28 | 29 | # Run shell surefire 30 | #shelltest src/test/shell --execdir --diff 31 | #if [ "$?" != 0 ]; then 32 | # echo "ERROR - Shell surefire failed!" 1>&2 33 | # exit $? 34 | #fi 35 | 36 | # Deploy new version of plugin in Sonar dir 37 | rm sonar-swift-plugin/target/*sources.jar 38 | rm $SONARQUBE_HOME/extensions/plugins/backelite-sonar-swift* 39 | cp sonar-swift-plugin/target/backelite*.jar $SONARQUBE_HOME/extensions/plugins 40 | rm $SONARQUBE_HOME/extensions/plugins/*sources.jar 41 | 42 | # Stop/start Sonar 43 | unset GEM_PATH GEM_HOME 44 | $SONARQUBE_HOME/bin/macosx-universal-64/sonar.sh stop 45 | $SONARQUBE_HOME/bin/macosx-universal-64/sonar.sh start 46 | 47 | -------------------------------------------------------------------------------- /commons/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 24 | 25 | backelite-swift 26 | com.backelite.sonarqube 27 | 0.4.7-SNAPSHOT 28 | 29 | 4.0.0 30 | 31 | com.backelite.sonarqube 32 | commons 33 | 34 | 35 | 36 | 37 | org.sonarsource.sslr 38 | sslr-core 39 | 40 | 41 | org.sonarsource.sslr-squid-bridge 42 | sslr-squid-bridge 43 | 44 | 45 | ch.qos.logback 46 | logback-classic 47 | 48 | 49 | ant 50 | ant 51 | 52 | 53 | 54 | 55 | junit 56 | junit 57 | compile 58 | 59 | 60 | org.mockito 61 | mockito-all 62 | compile 63 | 64 | 65 | org.assertj 66 | assertj-core 67 | 68 | 69 | org.sonarsource.sonarqube 70 | sonar-testing-harness 71 | 72 | 73 | org.sonarsource.sslr 74 | sslr-testing-harness 75 | compile 76 | 77 | 78 | org.sonarsource.sonarlint.core 79 | sonarlint-core 80 | 81 | 82 | org.sonarsource.orchestrator 83 | sonar-orchestrator 84 | 85 | 86 | org.sonarsource.sonarqube 87 | sonar-plugin-api 88 | 89 | 90 | org.slf4j 91 | slf4j-api 92 | 93 | 94 | commons-lang 95 | commons-lang 96 | 2.6 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/Constants.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons; 19 | 20 | /** 21 | * Created by gillesgrousset on 23/08/2018. 22 | */ 23 | public final class Constants { 24 | public static final String PROPERTY_PREFIX = "sonar.swift"; 25 | } 26 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/MeasureUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons; 19 | 20 | import org.sonar.api.batch.fs.InputComponent; 21 | import org.sonar.api.batch.sensor.SensorContext; 22 | import org.sonar.api.measures.Metric; 23 | 24 | /** 25 | * Created by gillesgrousset on 29/08/2018. 26 | */ 27 | public final class MeasureUtil { 28 | 29 | public static void saveMeasure(SensorContext context, InputComponent component, Metric metric, int value) { 30 | context.newMeasure() 31 | .on(component) 32 | .forMetric(metric) 33 | .withValue(value) 34 | .save(); 35 | } 36 | 37 | public static void saveMeasure(SensorContext context, InputComponent component, Metric metric, long value) { 38 | context.newMeasure() 39 | .on(component) 40 | .forMetric(metric) 41 | .withValue(value) 42 | .save(); 43 | } 44 | 45 | public static void saveMeasure(SensorContext context, InputComponent component, Metric metric, double value) { 46 | context.newMeasure() 47 | .on(component) 48 | .forMetric(metric) 49 | .withValue(value) 50 | .save(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/TestFileFinder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons; 19 | 20 | import org.sonar.api.batch.fs.FileSystem; 21 | import org.sonar.api.batch.fs.InputFile; 22 | 23 | public interface TestFileFinder { 24 | InputFile getUnitTestResource(FileSystem fileSystem, String classname); 25 | } 26 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/TestFileFinders.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons; 19 | 20 | import org.sonar.api.batch.fs.FileSystem; 21 | import org.sonar.api.batch.fs.InputFile; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | public class TestFileFinders { 27 | private static TestFileFinders instance; 28 | private final List finders = new ArrayList<>(); 29 | private TestFileFinders() {} 30 | 31 | public static synchronized TestFileFinders getInstance() { 32 | if (instance == null) { 33 | instance = new TestFileFinders(); 34 | } 35 | return instance; 36 | } 37 | 38 | public void addFinder(TestFileFinder finder) { 39 | finders.add(finder); 40 | } 41 | 42 | public InputFile getUnitTestResource(FileSystem fileSystem, String classname) { 43 | for (TestFileFinder finder : finders) { 44 | InputFile result = finder.getUnitTestResource(fileSystem, classname); 45 | if (result != null) { 46 | return result; 47 | } 48 | } 49 | 50 | return null; 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/surefire/StaxParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons.surefire; 19 | 20 | import org.codehaus.staxmate.SMInputFactory; 21 | import com.ctc.wstx.stax.WstxInputFactory; 22 | import java.io.File; 23 | import java.io.FileInputStream; 24 | import java.io.IOException; 25 | import javax.xml.stream.XMLInputFactory; 26 | import javax.xml.stream.XMLStreamException; 27 | import org.codehaus.staxmate.in.SMHierarchicCursor; 28 | 29 | public class StaxParser { 30 | 31 | private SMInputFactory inf; 32 | private SurefireStaxHandler streamHandler; 33 | 34 | public StaxParser(UnitTestIndex index) { 35 | this.streamHandler = new SurefireStaxHandler(index); 36 | XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); 37 | if (xmlInputFactory instanceof WstxInputFactory) { 38 | WstxInputFactory wstxInputfactory = (WstxInputFactory) xmlInputFactory; 39 | wstxInputfactory.configureForLowMemUsage(); 40 | wstxInputfactory.getConfig().setUndeclaredEntityResolver((String publicID, String systemID, String baseURI, String namespace) -> namespace); 41 | } 42 | this.inf = new SMInputFactory(xmlInputFactory); 43 | } 44 | 45 | public void parse(File xmlFile) throws XMLStreamException { 46 | try(FileInputStream input = new FileInputStream(xmlFile)) { 47 | parse(inf.rootElementCursor(input)); 48 | } catch (IOException e) { 49 | throw new XMLStreamException(e); 50 | } 51 | } 52 | 53 | private void parse(SMHierarchicCursor rootCursor) throws XMLStreamException { 54 | try { 55 | streamHandler.stream(rootCursor); 56 | } finally { 57 | rootCursor.getStreamReader().closeCompletely(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/surefire/SurefireSensor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons.surefire; 19 | 20 | import com.backelite.sonarqube.commons.Constants; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.sonar.api.batch.fs.FileSystem; 24 | import org.sonar.api.batch.sensor.Sensor; 25 | import org.sonar.api.batch.sensor.SensorContext; 26 | import org.sonar.api.batch.sensor.SensorDescriptor; 27 | import org.sonar.api.component.ResourcePerspectives; 28 | 29 | import java.io.File; 30 | import java.io.IOException; 31 | import java.nio.file.DirectoryStream; 32 | import java.nio.file.Files; 33 | import java.nio.file.Path; 34 | 35 | public class SurefireSensor implements Sensor { 36 | private static final Logger LOGGER = LoggerFactory.getLogger(SurefireSensor.class); 37 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".surefire.junit.reportsPath"; 38 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/"; 39 | 40 | private final SensorContext context; 41 | private final ResourcePerspectives perspectives; 42 | private final FileSystem fileSystem; 43 | 44 | public SurefireSensor(FileSystem fileSystem, ResourcePerspectives perspectives, SensorContext context) { 45 | this.fileSystem = fileSystem; 46 | this.perspectives = perspectives; 47 | this.context = context; 48 | } 49 | 50 | protected String reportPath() { 51 | return context.config() 52 | .get(REPORT_PATH_KEY) 53 | .orElse(DEFAULT_REPORT_PATH); 54 | } 55 | 56 | @Override 57 | public void describe(SensorDescriptor descriptor) { 58 | descriptor 59 | .name("Surefire") 60 | .onlyOnLanguages("swift","objc"); 61 | } 62 | 63 | @Override 64 | public void execute(SensorContext context) { 65 | SurefireReportParser surefireParser = new SurefireReportParser(fileSystem, perspectives, context); 66 | String reportFileName = context.fileSystem().baseDir().getAbsolutePath() + "/"+ reportPath(); 67 | File reportsDir = new File(reportFileName); 68 | 69 | if (!reportsDir.isDirectory()) { 70 | LOGGER.warn("JUnit report directory not found at {}", reportsDir); 71 | return; 72 | } else { 73 | surefireParser.collect(reportsDir); 74 | } 75 | 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/surefire/UnitTestClassReport.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons.surefire; 19 | 20 | import com.google.common.collect.Lists; 21 | 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | public final class UnitTestClassReport { 26 | private int errors = 0; 27 | private int failures = 0; 28 | private int skipped = 0; 29 | private int tests = 0; 30 | private long durationMilliseconds = 0L; 31 | 32 | private long negativeTimeTestNumber = 0L; 33 | private List results = null; 34 | 35 | private void initResults() { 36 | if (results == null) { 37 | results = Lists.newArrayList(); 38 | } 39 | } 40 | 41 | public UnitTestClassReport add(UnitTestResult result) { 42 | initResults(); 43 | results.add(result); 44 | if (result.getStatus().equals(UnitTestResult.STATUS_SKIPPED)) { 45 | skipped += 1; 46 | 47 | } else if (result.getStatus().equals(UnitTestResult.STATUS_FAILURE)) { 48 | failures += 1; 49 | 50 | } else if (result.getStatus().equals(UnitTestResult.STATUS_ERROR)) { 51 | errors += 1; 52 | } 53 | tests += 1; 54 | if (result.getDurationMilliseconds() < 0) { 55 | negativeTimeTestNumber += 1; 56 | } else { 57 | durationMilliseconds += result.getDurationMilliseconds(); 58 | } 59 | return this; 60 | } 61 | 62 | public int getErrors() { 63 | return errors; 64 | } 65 | 66 | public int getFailures() { 67 | return failures; 68 | } 69 | 70 | public int getSkipped() { 71 | return skipped; 72 | } 73 | 74 | public int getTests() { 75 | return tests; 76 | } 77 | 78 | public long getNegativeTimeTestNumber() { 79 | return negativeTimeTestNumber; 80 | } 81 | 82 | public List getResults() { 83 | if (results == null) { 84 | return Collections.emptyList(); 85 | } 86 | return results; 87 | } 88 | 89 | public long getDurationMilliseconds() { 90 | return durationMilliseconds; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/surefire/UnitTestIndex.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons.surefire; 19 | 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | 23 | /** 24 | * @since 2.8 25 | */ 26 | public class UnitTestIndex { 27 | 28 | private Map indexByClassname; 29 | 30 | public UnitTestIndex() { 31 | this.indexByClassname = new HashMap<>(); 32 | } 33 | 34 | public UnitTestClassReport index(String classname) { 35 | return indexByClassname.computeIfAbsent(classname, k -> new UnitTestClassReport()); 36 | } 37 | 38 | public UnitTestClassReport get(String classname) { 39 | return indexByClassname.get(classname); 40 | } 41 | 42 | public Map getIndexByClassname() { 43 | return indexByClassname; 44 | } 45 | 46 | public int size() { 47 | return indexByClassname.size(); 48 | } 49 | } -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/surefire/UnitTestResult.java: -------------------------------------------------------------------------------- 1 | /** 2 | * commons - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.commons.surefire; 19 | 20 | public final class UnitTestResult { 21 | public static final String STATUS_OK = "ok"; 22 | public static final String STATUS_ERROR = "error"; 23 | public static final String STATUS_FAILURE = "failure"; 24 | public static final String STATUS_SKIPPED = "skipped"; 25 | 26 | private String name; 27 | private String testSuiteClassName; 28 | private String status; 29 | private String stackTrace; 30 | private String message; 31 | private long durationMilliseconds = 0L; 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public UnitTestResult setName(String name) { 38 | this.name = name; 39 | return this; 40 | } 41 | 42 | public String getStatus() { 43 | return status; 44 | } 45 | 46 | public UnitTestResult setStatus(String status) { 47 | this.status = status; 48 | return this; 49 | } 50 | 51 | public String getStackTrace() { 52 | return stackTrace; 53 | } 54 | 55 | public UnitTestResult setStackTrace(String stackTrace) { 56 | this.stackTrace = stackTrace; 57 | return this; 58 | } 59 | 60 | public String getMessage() { 61 | return message; 62 | } 63 | 64 | public UnitTestResult setMessage(String message) { 65 | this.message = message; 66 | return this; 67 | } 68 | 69 | public long getDurationMilliseconds() { 70 | return durationMilliseconds; 71 | } 72 | 73 | public UnitTestResult setDurationMilliseconds(long l) { 74 | this.durationMilliseconds = l; 75 | return this; 76 | } 77 | 78 | public boolean isErrorOrFailure() { 79 | return STATUS_ERROR.equals(status) || STATUS_FAILURE.equals(status); 80 | } 81 | 82 | public boolean isError() { 83 | return STATUS_ERROR.equals(status); 84 | } 85 | 86 | public UnitTestResult setTestSuiteClassName(String testSuiteClassName) { 87 | this.testSuiteClassName = testSuiteClassName; 88 | return this; 89 | } 90 | 91 | public String getTestSuiteClassName() { 92 | return testSuiteClassName; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /docs/sonarqube-fastlane.md: -------------------------------------------------------------------------------- 1 | # Using with fastlane 🚀 2 | 3 | If you already use fastlane, you can simply setup a new lane performing the analysis as follows: 4 | 5 | Add `fastlane-plugin-lizard` gem into `Gemfile`, run `bundle install` 6 | 7 | Then add the following lane. 8 | ```ruby 9 | lane :metrics do 10 | scan(scheme: "[SCHEME]", code_coverage: true, derived_data_path: "./DerivedData", output_directory: "./reports") 11 | slather(cobertura_xml: true, jenkins: true, scheme: "[SCHEME]", build_directory: "./DerivedData", output_directory: "./reports", proj: "./[PROJECT].xcodeproj") 12 | lizard(source_folder: "[SOURCE_FOLDER]", language: "swift", export_type: "xml", report_file: "reports/lizard-report.xml") 13 | swiftlint(output_file: "./reports/swiftlint.txt", ignore_exit_status: true) 14 | sonar 15 | end 16 | 17 | ``` 18 | 19 | ## Options 20 | 21 | fastlane's `sonar` action allows you to define or override a number of SonarQube properties, such as `sonar.project-version`. 22 | 23 | For instance: 24 | 25 | ```ruby 26 | sonar(project_version: "1.0b") 27 | ``` 28 | 29 | You can read the complete documentation of fastlane's `sonar` action on your terminal via: 30 | 31 | ```bash 32 | fastlane action sonar 33 | ``` 34 | 35 | ## `sonar-project.properties` 36 | 37 | Please note that, in order to have your analysis performed via the tools above, you'll need to setup your `sonar-project.properties` file accordingly, as per the following example. 38 | 39 | ``` 40 | sonar.junit.reportsPath=reports/ 41 | sonar.junit.include=*.junit 42 | sonar.swift.lizard.report=reports/lizard-report.xml 43 | sonar.swift.coverage.reportPattern=reports/cobertura.xml 44 | sonar.swift.swiftlint.report=reports/*swiftlint.txt 45 | ``` 46 | -------------------------------------------------------------------------------- /objclang/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 24 | 25 | backelite-swift 26 | com.backelite.sonarqube 27 | 0.4.7-SNAPSHOT 28 | 29 | 4.0.0 30 | 31 | com.backelite.sonarqube 32 | objc-lang 33 | Swift SonarQube Plugin - Objective-C module 34 | 35 | 36 | 37 | 38 | com.backelite.sonarqube 39 | commons 40 | 0.4.7-SNAPSHOT 41 | 42 | 43 | 44 | org.sonarsource.sslr 45 | sslr-core 46 | 47 | 48 | org.sonarsource.sslr-squid-bridge 49 | sslr-squid-bridge 50 | 51 | 52 | ch.qos.logback 53 | logback-classic 54 | 55 | 56 | ant 57 | ant 58 | 59 | 60 | com.google.guava 61 | guava 62 | 63 | 64 | com.googlecode.json-simple 65 | json-simple 66 | 67 | 68 | junit 69 | junit 70 | compile 71 | 72 | 73 | org.mockito 74 | mockito-all 75 | compile 76 | 77 | 78 | org.assertj 79 | assertj-core 80 | 81 | 82 | org.sonarsource.sonarqube 83 | sonar-testing-harness 84 | 85 | 86 | org.sonarsource.sslr 87 | sslr-testing-harness 88 | compile 89 | 90 | 91 | org.sonarsource.sonarlint.core 92 | sonarlint-core 93 | 94 | 95 | org.sonarsource.orchestrator 96 | sonar-orchestrator 97 | 98 | 99 | org.sonarsource.sonarqube 100 | sonar-plugin-api 101 | 102 | 103 | org.slf4j 104 | slf4j-api 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/ObjectiveCConstants.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec; 19 | 20 | 21 | public final class ObjectiveCConstants { 22 | public static final String FILE_SUFFIXES = "h,m,mm"; 23 | } 24 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/ObjectiveCProfile.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues; 19 | 20 | import com.backelite.sonarqube.objectivec.issues.fauxpas.FauxPasProfile; 21 | import com.backelite.sonarqube.objectivec.issues.fauxpas.FauxPasProfileImporter; 22 | import com.backelite.sonarqube.objectivec.issues.oclint.OCLintProfile; 23 | import com.backelite.sonarqube.objectivec.issues.oclint.OCLintProfileImporter; 24 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | import org.sonar.api.profiles.RulesProfile; 28 | import org.sonar.api.rules.ActiveRule; 29 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 30 | import org.sonar.api.utils.ValidationMessages; 31 | 32 | import java.io.IOException; 33 | import java.io.InputStreamReader; 34 | import java.io.Reader; 35 | 36 | public class ObjectiveCProfile implements BuiltInQualityProfilesDefinition { 37 | private static final Logger LOGGER = LoggerFactory.getLogger(ObjectiveCProfile.class); 38 | private final OCLintProfileImporter ocLintProfileImporter; 39 | private final FauxPasProfileImporter fauxPasProfileImporter; 40 | 41 | public ObjectiveCProfile(final OCLintProfileImporter ocLintProfileImporter, final FauxPasProfileImporter fauxPasProfileImporter) { 42 | this.ocLintProfileImporter = ocLintProfileImporter; 43 | this.fauxPasProfileImporter = fauxPasProfileImporter; 44 | } 45 | 46 | @Override 47 | public void define(Context context) { 48 | LOGGER.info("Creating Objective-C Profile"); 49 | 50 | NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile("Objective-C", ObjectiveC.KEY); 51 | nbiqp.setDefault(true); 52 | 53 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(OCLintProfile.PROFILE_PATH))) { 54 | RulesProfile ocLintRulesProfile = ocLintProfileImporter.importProfile(config, ValidationMessages.create()); 55 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 56 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 57 | } 58 | } catch (IOException ex){ 59 | LOGGER.error("Error Creating Objective-C Profile",ex); 60 | } 61 | 62 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(FauxPasProfile.PROFILE_PATH))){ 63 | RulesProfile fauxPasRulesProfile = fauxPasProfileImporter.importProfile(config, ValidationMessages.create()); 64 | for (ActiveRule rule : fauxPasRulesProfile.getActiveRules()) { 65 | nbiqp.activateRule(rule.getRepositoryKey(),rule.getRuleKey()); 66 | } 67 | } catch (IOException ex){ 68 | LOGGER.error("Error Creating Objective-C Profile",ex); 69 | } 70 | nbiqp.done(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/fauxpas/FauxPasProfile.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.fauxpas; 19 | 20 | import com.backelite.sonarqube.objectivec.issues.oclint.OCLintProfile; 21 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.sonar.api.profiles.RulesProfile; 25 | import org.sonar.api.rules.ActiveRule; 26 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 27 | import org.sonar.api.utils.ValidationMessages; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStreamReader; 31 | import java.io.Reader; 32 | 33 | public class FauxPasProfile implements BuiltInQualityProfilesDefinition { 34 | private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasProfile.class); 35 | public static final String PROFILE_PATH = "/org/sonar/plugins/fauxpas/profile-fauxpas.xml"; 36 | 37 | private final FauxPasProfileImporter profileImporter; 38 | 39 | public FauxPasProfile(final FauxPasProfileImporter importer) { 40 | profileImporter = importer; 41 | } 42 | 43 | @Override 44 | public void define(Context context) { 45 | LOGGER.info("Creating FauxPas Profile"); 46 | NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile(FauxPasRulesDefinition.REPOSITORY_KEY, ObjectiveC.KEY); 47 | 48 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(OCLintProfile.PROFILE_PATH))) { 49 | RulesProfile ocLintRulesProfile = profileImporter.importProfile(config, ValidationMessages.create()); 50 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 51 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 52 | } 53 | } catch (IOException ex){ 54 | LOGGER.error("Error Creating FauxPas Profile",ex); 55 | } 56 | nbiqp.done(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/fauxpas/FauxPasProfileImporter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.fauxpas; 19 | 20 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.sonar.api.profiles.ProfileImporter; 24 | import org.sonar.api.profiles.RulesProfile; 25 | import org.sonar.api.profiles.XMLProfileParser; 26 | import org.sonar.api.utils.ValidationMessages; 27 | 28 | import java.io.Reader; 29 | 30 | public class FauxPasProfileImporter extends ProfileImporter { 31 | private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasProfileImporter.class); 32 | private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default FauxPas profile"; 33 | 34 | private final XMLProfileParser profileParser; 35 | 36 | public FauxPasProfileImporter(final XMLProfileParser xmlProfileParser) { 37 | super(FauxPasRulesDefinition.REPOSITORY_KEY, FauxPasRulesDefinition.REPOSITORY_KEY); 38 | setSupportedLanguages(ObjectiveC.KEY); 39 | profileParser = xmlProfileParser; 40 | } 41 | 42 | @Override 43 | public RulesProfile importProfile(Reader reader, ValidationMessages messages) { 44 | final RulesProfile profile = profileParser.parse(reader, messages); 45 | 46 | if (null == profile) { 47 | messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); 48 | LOGGER.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); 49 | } 50 | return profile; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/fauxpas/FauxPasReportParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.fauxpas; 19 | 20 | import org.json.simple.JSONArray; 21 | import org.json.simple.JSONObject; 22 | import org.json.simple.JSONValue; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.sonar.api.batch.fs.FilePredicate; 26 | import org.sonar.api.batch.fs.InputFile; 27 | import org.sonar.api.batch.sensor.SensorContext; 28 | import org.sonar.api.batch.sensor.issue.NewIssueLocation; 29 | import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation; 30 | import org.sonar.api.rule.RuleKey; 31 | 32 | import java.io.File; 33 | import java.io.FileNotFoundException; 34 | import java.io.FileReader; 35 | import java.io.IOException; 36 | 37 | public class FauxPasReportParser { 38 | private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasReportParser.class); 39 | 40 | private final SensorContext context; 41 | 42 | public FauxPasReportParser(final SensorContext context) { 43 | this.context = context; 44 | } 45 | 46 | public void parseReport(File reportFile) { 47 | 48 | try(FileReader fr = new FileReader(reportFile)){ 49 | // Read and parse report 50 | Object reportObj = JSONValue.parse(fr); 51 | 52 | // Record issues 53 | if (reportObj != null) { 54 | JSONObject reportJson = (JSONObject) reportObj; 55 | JSONArray diagnosticsJson = (JSONArray) reportJson.get("diagnostics"); 56 | 57 | for (Object obj : diagnosticsJson) { 58 | recordIssue((JSONObject) obj); 59 | } 60 | } 61 | 62 | } catch (FileNotFoundException e) { 63 | LOGGER.error("Failed to parse FauxPas report file", e); 64 | } catch (IOException e) { 65 | LOGGER.error("Failed to parse FauxPas report file", e); 66 | } 67 | } 68 | 69 | private void recordIssue(final JSONObject diagnosticJson) { 70 | String filePath = (String) diagnosticJson.get("file"); 71 | if (filePath != null) { 72 | FilePredicate fp = context.fileSystem().predicates().hasAbsolutePath(filePath); 73 | 74 | if (!context.fileSystem().hasFiles(fp)) { 75 | LOGGER.warn("file not included in sonar {}", filePath); 76 | return; 77 | } 78 | 79 | JSONObject extent = (JSONObject) diagnosticJson.get("extent"); 80 | JSONObject start = (JSONObject) extent.get("start"); 81 | 82 | String info = (String) diagnosticJson.get("info"); 83 | if (info == null) { 84 | info = (String) diagnosticJson.get("ruleName"); 85 | } 86 | 87 | // Prevent line num 0 case 88 | int lineNum = Integer.parseInt(start.get("line").toString()); 89 | if (lineNum == 0) { 90 | lineNum++; 91 | } 92 | 93 | InputFile inputFile = context.fileSystem().inputFile(fp); 94 | NewIssueLocation dil = new DefaultIssueLocation() 95 | .on(inputFile) 96 | .at(inputFile.selectLine(lineNum)) 97 | .message(info); 98 | context.newIssue() 99 | .forRule(RuleKey.of(FauxPasRulesDefinition.REPOSITORY_KEY, (String) diagnosticJson.get("ruleShortName"))) 100 | .at(dil) 101 | .save(); 102 | } 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/fauxpas/FauxPasRulesDefinition.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.fauxpas; 19 | 20 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 21 | import org.json.simple.JSONArray; 22 | import org.json.simple.JSONObject; 23 | import org.json.simple.JSONValue; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.sonar.api.server.rule.RulesDefinition; 27 | import org.sonar.squidbridge.rules.SqaleXmlLoader; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStreamReader; 31 | import java.io.Reader; 32 | import java.nio.charset.Charset; 33 | 34 | /** 35 | * Created by gillesgrousset on 18/02/2016. 36 | */ 37 | public class FauxPasRulesDefinition implements RulesDefinition { 38 | 39 | public static final String REPOSITORY_KEY = "FauxPas"; 40 | public static final String REPOSITORY_NAME = REPOSITORY_KEY; 41 | private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasRulesDefinition.class); 42 | private static final String RULES_FILE = "/org/sonar/plugins/fauxpas/rules.json"; 43 | 44 | 45 | @Override 46 | public void define(final Context context) { 47 | NewRepository repository = context.createRepository(REPOSITORY_KEY, ObjectiveC.KEY).setName(REPOSITORY_NAME); 48 | 49 | try(Reader reader = new InputStreamReader(getClass().getResourceAsStream(RULES_FILE), Charset.forName("UTF-8"))){ 50 | JSONArray slRules = (JSONArray)JSONValue.parse(reader); 51 | if(slRules != null){ 52 | for (Object obj : slRules) { 53 | JSONObject slRule = (JSONObject) obj; 54 | repository.createRule((String) slRule.get("key")) 55 | .setName((String) slRule.get("name")) 56 | .setSeverity((String) slRule.get("severity")) 57 | .setHtmlDescription((String) slRule.get("description")); 58 | } 59 | } 60 | } catch (IOException e) { 61 | LOGGER.error("Failed to load FauxPas rules", e); 62 | } 63 | SqaleXmlLoader.load(repository, "/com/sonar/sqale/fauxpas-model.xml"); 64 | repository.done(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/fauxpas/FauxPasSensor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.fauxpas; 19 | 20 | import com.backelite.sonarqube.commons.Constants; 21 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 22 | import org.apache.tools.ant.DirectoryScanner; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.sonar.api.batch.fs.FileSystem; 26 | import org.sonar.api.batch.fs.InputFile; 27 | import org.sonar.api.batch.sensor.Sensor; 28 | import org.sonar.api.batch.sensor.SensorContext; 29 | import org.sonar.api.batch.sensor.SensorDescriptor; 30 | import org.sonar.api.component.ResourcePerspectives; 31 | import org.sonar.api.config.Settings; 32 | 33 | import java.io.File; 34 | 35 | public class FauxPasSensor implements Sensor { 36 | private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasSensor.class); 37 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".fauxpas.report"; 38 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/*fauxpas.json"; 39 | 40 | private final SensorContext context; 41 | 42 | public FauxPasSensor(SensorContext context) { 43 | this.context = context; 44 | } 45 | 46 | private void parseReportIn(final String baseDir, final FauxPasReportParser parser) { 47 | DirectoryScanner scanner = new DirectoryScanner(); 48 | scanner.setIncludes(new String[]{reportPath()}); 49 | scanner.setBasedir(baseDir); 50 | scanner.setCaseSensitive(false); 51 | scanner.scan(); 52 | String[] files = scanner.getIncludedFiles(); 53 | 54 | for (String filename : files) { 55 | LOGGER.info("Processing FauxPas report {}", filename); 56 | parser.parseReport(new File(filename)); 57 | } 58 | } 59 | 60 | private String reportPath() { 61 | return context.config() 62 | .get(REPORT_PATH_KEY) 63 | .orElse(DEFAULT_REPORT_PATH); 64 | } 65 | 66 | @Override 67 | public void describe(SensorDescriptor descriptor) { 68 | descriptor 69 | .onlyOnLanguage(ObjectiveC.KEY) 70 | .name("FauxPas") 71 | .onlyOnFileType(InputFile.Type.MAIN); 72 | } 73 | 74 | @Override 75 | public void execute(SensorContext context) { 76 | final String projectBaseDir = context.fileSystem().baseDir().getAbsolutePath(); 77 | 78 | FauxPasReportParser parser = new FauxPasReportParser(context); 79 | parseReportIn(projectBaseDir, parser); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/oclint/OCLintParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.oclint; 19 | 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.sonar.api.batch.fs.FilePredicate; 23 | import org.sonar.api.batch.fs.InputFile; 24 | import org.sonar.api.batch.sensor.SensorContext; 25 | import org.sonar.api.batch.sensor.issue.NewIssueLocation; 26 | import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation; 27 | import org.sonar.api.rule.RuleKey; 28 | import org.w3c.dom.Document; 29 | import org.w3c.dom.Element; 30 | import org.w3c.dom.Node; 31 | import org.w3c.dom.NodeList; 32 | import org.xml.sax.SAXException; 33 | 34 | import javax.xml.parsers.DocumentBuilder; 35 | import javax.xml.parsers.DocumentBuilderFactory; 36 | import javax.xml.parsers.ParserConfigurationException; 37 | import java.io.File; 38 | import java.io.FileNotFoundException; 39 | import java.io.IOException; 40 | 41 | final class OCLintParser { 42 | private static final Logger LOGGER = LoggerFactory.getLogger(OCLintParser.class); 43 | private static final String FILE = "file"; 44 | private static final String FILENAME = "name"; 45 | private static final String VIOLATION = "violation"; 46 | private static final String LINE = "beginline"; 47 | private static final String RULE = "rule"; 48 | private final SensorContext context; 49 | private final DocumentBuilderFactory dbfactory; 50 | 51 | public OCLintParser(SensorContext context) { 52 | this.context = context; 53 | this.dbfactory = DocumentBuilderFactory.newInstance(); 54 | } 55 | 56 | public void parseReport(final File xmlFile) { 57 | try { 58 | DocumentBuilder builder = dbfactory.newDocumentBuilder(); 59 | Document document = builder.parse(xmlFile); 60 | parseFiles(document.getElementsByTagName(FILE)); 61 | } catch (final FileNotFoundException e) { 62 | LOGGER.error("Cobertura Report not found {}", xmlFile, e); 63 | } catch (final IOException e) { 64 | LOGGER.error("Error processing file named {}", xmlFile, e); 65 | } catch (final ParserConfigurationException e) { 66 | LOGGER.error("Error in parser config {}", e); 67 | } catch (final SAXException e) { 68 | LOGGER.error("Error processing file named {}", xmlFile, e); 69 | } 70 | 71 | } 72 | 73 | private void parseFiles(NodeList nodeList) { 74 | for (int i = 0; i < nodeList.getLength(); i++) { 75 | Node node = nodeList.item(i); 76 | if (node.getNodeType() == Node.ELEMENT_NODE) { 77 | Element element = (Element) node; 78 | 79 | String filePath = element.getAttribute(FILENAME); 80 | NodeList nl = element.getElementsByTagName(VIOLATION); 81 | collectFileViolations(filePath,nl); 82 | } 83 | } 84 | } 85 | 86 | private void collectFileViolations(String filePath, NodeList nodeList) { 87 | File file = new File(filePath); 88 | FilePredicate fp = context.fileSystem().predicates().hasAbsolutePath(file.getAbsolutePath()); 89 | if(!context.fileSystem().hasFiles(fp)){ 90 | LOGGER.warn("file not included in sonar {}", filePath); 91 | } else { 92 | InputFile inputFile = context.fileSystem().inputFile(fp); 93 | for (int i = 0; i < nodeList.getLength(); i++) { 94 | Node node = nodeList.item(i); 95 | if (node.getNodeType() == Node.ELEMENT_NODE) { 96 | Element element = (Element) node; 97 | NewIssueLocation dil = new DefaultIssueLocation() 98 | .on(inputFile) 99 | .at(inputFile.selectLine(Integer.valueOf(element.getAttribute(LINE)))) 100 | .message(element.getTextContent()); 101 | context.newIssue() 102 | .forRule(RuleKey.of(OCLintRulesDefinition.REPOSITORY_KEY, element.getAttribute(RULE))) 103 | .at(dil) 104 | .save(); 105 | } 106 | } 107 | } 108 | 109 | 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/oclint/OCLintProfile.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.oclint; 19 | 20 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.sonar.api.profiles.RulesProfile; 24 | import org.sonar.api.rules.ActiveRule; 25 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 26 | import org.sonar.api.utils.ValidationMessages; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStreamReader; 30 | import java.io.Reader; 31 | 32 | public final class OCLintProfile implements BuiltInQualityProfilesDefinition { 33 | private static final Logger LOGGER = LoggerFactory.getLogger(OCLintProfile.class); 34 | public static final String PROFILE_PATH = "/org/sonar/plugins/oclint/profile-oclint.xml"; 35 | 36 | private final OCLintProfileImporter profileImporter; 37 | 38 | public OCLintProfile(final OCLintProfileImporter importer) { 39 | profileImporter = importer; 40 | } 41 | 42 | @Override 43 | public void define(Context context) { 44 | LOGGER.info("Creating OCLint Profile"); 45 | NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile(OCLintRulesDefinition.REPOSITORY_KEY, ObjectiveC.KEY); 46 | 47 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(OCLintProfile.PROFILE_PATH))) { 48 | RulesProfile ocLintRulesProfile = profileImporter.importProfile(config, ValidationMessages.create()); 49 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 50 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 51 | } 52 | } catch (IOException ex){ 53 | LOGGER.error("Error Creating OCLint Profile",ex); 54 | } 55 | nbiqp.done(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/oclint/OCLintProfileImporter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.oclint; 19 | 20 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.sonar.api.profiles.ProfileImporter; 24 | import org.sonar.api.profiles.RulesProfile; 25 | import org.sonar.api.profiles.XMLProfileParser; 26 | import org.sonar.api.utils.ValidationMessages; 27 | 28 | import java.io.Reader; 29 | 30 | public final class OCLintProfileImporter extends ProfileImporter { 31 | private static final Logger LOGGER = LoggerFactory.getLogger(OCLintProfileImporter.class); 32 | private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default OCLint profile"; 33 | 34 | private final XMLProfileParser profileParser; 35 | 36 | public OCLintProfileImporter(final XMLProfileParser xmlProfileParser) { 37 | super(OCLintRulesDefinition.REPOSITORY_KEY, OCLintRulesDefinition.REPOSITORY_KEY); 38 | setSupportedLanguages(ObjectiveC.KEY); 39 | profileParser = xmlProfileParser; 40 | } 41 | 42 | @Override 43 | public RulesProfile importProfile(Reader reader, ValidationMessages messages) { 44 | final RulesProfile profile = profileParser.parse(reader, messages); 45 | 46 | if (null == profile) { 47 | messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); 48 | LOGGER.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); 49 | } 50 | return profile; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/oclint/OCLintRuleSeverity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.oclint; 19 | 20 | /** 21 | * Created by gillesgrousset on 18/02/2016. 22 | */ 23 | public enum OCLintRuleSeverity { 24 | 25 | // Rules are priority 26 | // INFO = 0, MINOR = 1, MAJOR = 2, CRITICAL = 3, BLOCKER = 4 27 | 28 | INFO, 29 | MINOR, 30 | MAJOR, 31 | CRITICAL, 32 | BLOCKER; 33 | 34 | public static OCLintRuleSeverity valueOfInt(int ordinal) { 35 | return values()[ordinal]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/oclint/OCLintSensor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.oclint; 19 | 20 | import com.backelite.sonarqube.commons.Constants; 21 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 22 | import org.apache.tools.ant.DirectoryScanner; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.sonar.api.batch.fs.InputFile; 26 | import org.sonar.api.batch.sensor.Sensor; 27 | import org.sonar.api.batch.sensor.SensorContext; 28 | import org.sonar.api.batch.sensor.SensorDescriptor; 29 | 30 | import java.io.File; 31 | 32 | public final class OCLintSensor implements Sensor { 33 | private static final Logger LOGGER = LoggerFactory.getLogger(OCLintSensor.class); 34 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".oclint.report"; 35 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/*oclint.xml"; 36 | private final SensorContext context; 37 | 38 | public OCLintSensor(SensorContext context) { 39 | this.context = context; 40 | } 41 | 42 | private String reportPath() { 43 | return context.config() 44 | .get(REPORT_PATH_KEY) 45 | .orElse(DEFAULT_REPORT_PATH); 46 | } 47 | 48 | @Override 49 | public void describe(SensorDescriptor descriptor) { 50 | descriptor 51 | .onlyOnLanguage(ObjectiveC.KEY) 52 | .name("OCLint") 53 | .onlyOnFileType(InputFile.Type.MAIN); 54 | } 55 | 56 | @Override 57 | public void execute(SensorContext context) { 58 | OCLintParser parser = new OCLintParser(context); 59 | DirectoryScanner scanner = new DirectoryScanner(); 60 | scanner.setIncludes(new String[]{reportPath()}); 61 | scanner.setBasedir(context.fileSystem().baseDir().getAbsolutePath()); 62 | scanner.setCaseSensitive(false); 63 | scanner.scan(); 64 | String[] files = scanner.getIncludedFiles(); 65 | 66 | for (String filename : files) { 67 | LOGGER.info("Processing OCLint report {}", filename); 68 | parser.parseReport(new File(filename)); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/oclint/OCLintXMLStreamHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.issues.oclint; 19 | 20 | import org.codehaus.staxmate.in.SMHierarchicCursor; 21 | import org.codehaus.staxmate.in.SMInputCursor; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.sonar.api.batch.fs.FileSystem; 25 | import org.sonar.api.batch.fs.InputFile; 26 | import org.sonar.api.component.ResourcePerspectives; 27 | import org.sonar.api.issue.Issuable; 28 | import org.sonar.api.issue.Issue; 29 | import org.sonar.api.rule.RuleKey; 30 | import org.sonar.api.utils.StaxParser.XmlStreamHandler; 31 | 32 | import javax.xml.stream.XMLStreamException; 33 | import java.io.File; 34 | 35 | final class OCLintXMLStreamHandler implements XmlStreamHandler { 36 | private static final Logger LOGGER = LoggerFactory.getLogger(OCLintXMLStreamHandler.class); 37 | private static final int PMD_MINIMUM_PRIORITY = 5; 38 | private final ResourcePerspectives resourcePerspectives; 39 | private final FileSystem fileSystem; 40 | 41 | public OCLintXMLStreamHandler(final ResourcePerspectives resourcePerspectives, final FileSystem fileSystem) { 42 | this.resourcePerspectives = resourcePerspectives; 43 | this.fileSystem = fileSystem; 44 | } 45 | 46 | public void stream(final SMHierarchicCursor rootCursor) throws XMLStreamException { 47 | 48 | final SMInputCursor file = rootCursor.advance().childElementCursor("file"); 49 | while (null != file.getNext()) { 50 | collectIssuesFor(file); 51 | } 52 | } 53 | 54 | private void collectIssuesFor(final SMInputCursor file) throws XMLStreamException { 55 | 56 | final String filePath = file.getAttrValue("name"); 57 | LoggerFactory.getLogger(getClass()).debug("Collection issues for {}", filePath); 58 | final InputFile inputFile = findResource(filePath); 59 | if (fileExists(inputFile)) { 60 | LoggerFactory.getLogger(getClass()).debug("File {} was found in the project.", filePath); 61 | collectFileIssues(inputFile, file); 62 | } 63 | } 64 | 65 | private void collectFileIssues(final InputFile inputFile, final SMInputCursor file) throws XMLStreamException { 66 | 67 | final SMInputCursor line = file.childElementCursor("violation"); 68 | 69 | while (null != line.getNext()) { 70 | recordViolation(inputFile, line); 71 | } 72 | } 73 | 74 | private InputFile findResource(final String filePath) { 75 | 76 | File file = new File(filePath); 77 | return fileSystem.inputFile(fileSystem.predicates().hasAbsolutePath(file.getAbsolutePath())); 78 | 79 | } 80 | 81 | private void recordViolation(InputFile inputFile, final SMInputCursor line) throws XMLStreamException { 82 | 83 | Issuable issuable = resourcePerspectives.as(Issuable.class, inputFile); 84 | 85 | if (issuable != null) { 86 | 87 | Issue issue = issuable.newIssueBuilder() 88 | .ruleKey(RuleKey.of(OCLintRulesDefinition.REPOSITORY_KEY, line.getAttrValue("rule"))) 89 | .line(Integer.valueOf(line.getAttrValue("beginline"))) 90 | .message(line.getElemStringValue()) 91 | .build(); 92 | 93 | try { 94 | issuable.addIssue(issue); 95 | } catch (Exception e) { 96 | // Unable to add issue : probably because does not exist in the repository 97 | LOGGER.warn(e.getMessage()); 98 | } 99 | 100 | 101 | } 102 | } 103 | 104 | private boolean fileExists(InputFile file) { 105 | if (file == null) { 106 | return false; 107 | } 108 | 109 | return file.file().exists(); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/ObjectiveCConfiguration.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang; 19 | 20 | import org.sonar.squidbridge.api.SquidConfiguration; 21 | 22 | import java.nio.charset.Charset; 23 | 24 | public class ObjectiveCConfiguration extends SquidConfiguration { 25 | 26 | private boolean ignoreHeaderComments; 27 | 28 | public ObjectiveCConfiguration() { 29 | } 30 | 31 | public ObjectiveCConfiguration(Charset charset) { 32 | super(charset); 33 | } 34 | 35 | public boolean getIgnoreHeaderComments() { 36 | return ignoreHeaderComments; 37 | } 38 | 39 | public void setIgnoreHeaderComments(boolean ignoreHeaderComments) { 40 | this.ignoreHeaderComments = ignoreHeaderComments; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/api/ObjectiveCGrammar.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.api; 19 | 20 | import com.sonar.sslr.api.Grammar; 21 | import com.sonar.sslr.api.Rule; 22 | 23 | public class ObjectiveCGrammar extends Grammar { 24 | 25 | public Rule identifierName; 26 | 27 | // A.1 Lexical 28 | 29 | public Rule literal; 30 | public Rule nullLiteral; 31 | public Rule booleanLiteral; 32 | public Rule stringLiteral; 33 | 34 | public Rule program; 35 | 36 | public Rule sourceElements; 37 | public Rule sourceElement; 38 | 39 | @Override 40 | public Rule getRootRule() { 41 | return program; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/api/ObjectiveCMetric.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.api; 19 | 20 | import org.sonar.squidbridge.measures.CalculatedMetricFormula; 21 | import org.sonar.squidbridge.measures.MetricDef; 22 | 23 | public enum ObjectiveCMetric implements MetricDef { 24 | FILES, 25 | LINES, 26 | LINES_OF_CODE, 27 | COMMENT_LINES, 28 | STATEMENTS, 29 | COMPLEXITY, 30 | FUNCTIONS; 31 | 32 | public String getName() { 33 | return name(); 34 | } 35 | 36 | public boolean isCalculatedMetric() { 37 | return false; 38 | } 39 | 40 | public boolean aggregateIfThereIsAlreadyAValue() { 41 | return true; 42 | } 43 | 44 | public boolean isThereAggregationFormula() { 45 | return true; 46 | } 47 | 48 | public CalculatedMetricFormula getCalculatedMetricFormula() { 49 | return null; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/api/ObjectiveCPunctuator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.api; 19 | 20 | import com.sonar.sslr.api.AstNode; 21 | import com.sonar.sslr.api.TokenType; 22 | 23 | public enum ObjectiveCPunctuator implements TokenType { 24 | 25 | // these are really only c operators 26 | // http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B 27 | 28 | PLUSPLUS("++"), 29 | PLUSEQ("+="), 30 | PLUS("+"), 31 | 32 | MINUSMINUS("--"), 33 | MINUSEQ("-="), 34 | MINUS("-"), 35 | 36 | STAREQ("*="), 37 | STAR("*"), 38 | 39 | SLASHEQ("/="), 40 | SLASH("/"), 41 | 42 | LT("<"), 43 | LTLT("<<"), 44 | LTEQ("<="), 45 | LTLTEQ("<<="), 46 | 47 | GT(">"), 48 | GTGT(">>"), 49 | GTEQ(">="), 50 | GTGTEQ(">>="), 51 | 52 | EQ("="), 53 | EQEQ("=="), 54 | 55 | TILDE("~"), 56 | 57 | EXCL("!"), 58 | EXCLEQ("!="), 59 | 60 | AMP("&"), 61 | AMPAMP("&&"), 62 | AMPEQ("&="), 63 | AMPAMPEX("&&="), 64 | 65 | BAR("|"), 66 | BARBAR("||"), 67 | BAREQ("|="), 68 | BARBAREQ("||="), 69 | 70 | CARETEQ("^="), 71 | CARET("^"), 72 | 73 | PERCENT("%"), 74 | PERCENTEQ("%="), 75 | 76 | LCURLYBRACE("{"), 77 | RCURLYBRACE("}"), 78 | LPARENTHESIS("("), 79 | RPARENTHESIS(")"), 80 | LBRACKET("["), 81 | RBRACKET("]"), 82 | 83 | QUESTION("?"), 84 | COLON(":"), 85 | SEMICOLON(";"), 86 | COMMA(","), 87 | 88 | MINUSLT("->"), 89 | MINUSLTSTAR("->*"), 90 | DOTSTAR(".*"); 91 | 92 | private final String value; 93 | 94 | private ObjectiveCPunctuator(String word) { 95 | this.value = word; 96 | } 97 | 98 | public String getName() { 99 | return name(); 100 | } 101 | 102 | public String getValue() { 103 | return value; 104 | } 105 | 106 | public boolean hasToBeSkippedFromAst(AstNode node) { 107 | return false; 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/api/ObjectiveCTokenType.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.api; 19 | 20 | import com.sonar.sslr.api.AstNode; 21 | import com.sonar.sslr.api.TokenType; 22 | 23 | public enum ObjectiveCTokenType implements TokenType { 24 | 25 | NUMERIC_LITERAL; 26 | 27 | public String getName() { 28 | return name(); 29 | } 30 | 31 | public String getValue() { 32 | return name(); 33 | } 34 | 35 | public boolean hasToBeSkippedFromAst(AstNode node) { 36 | return false; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/checks/CheckList.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.checks; 19 | 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | public final class CheckList { 24 | 25 | public static final String REPOSITORY_KEY = "objectivec"; 26 | 27 | public static final String SONAR_WAY_PROFILE = "Sonar way"; 28 | 29 | private CheckList() { 30 | } 31 | 32 | public static List getChecks() { 33 | return Collections.emptyList(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/core/ObjectiveC.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.core; 19 | 20 | import com.backelite.sonarqube.objectivec.ObjectiveCConstants; 21 | import org.sonar.api.config.Configuration; 22 | import org.sonar.api.resources.AbstractLanguage; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | public class ObjectiveC extends AbstractLanguage { 28 | public static final String KEY = "objc"; 29 | private final Configuration config; 30 | 31 | public ObjectiveC(Configuration config) { 32 | super(KEY, "Objective-C"); 33 | this.config = config; 34 | } 35 | 36 | public String[] getFileSuffixes() { 37 | String[] suffixes = filterEmptyStrings(config.getStringArray(ObjectiveCConstants.FILE_SUFFIXES)); 38 | if (suffixes.length == 0) { 39 | suffixes = ObjectiveCConstants.FILE_SUFFIXES.split( ","); 40 | } 41 | return suffixes; 42 | } 43 | 44 | private String[] filterEmptyStrings(String[] stringArray) { 45 | List nonEmptyStrings = new ArrayList<>(); 46 | for (String string : stringArray) { 47 | if (string.trim().length() > 0) { 48 | nonEmptyStrings.add(string.trim()); 49 | } 50 | } 51 | return nonEmptyStrings.toArray(new String[nonEmptyStrings.size()]); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/lexer/ObjectiveCLexer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.lexer; 19 | 20 | import com.backelite.sonarqube.objectivec.lang.ObjectiveCConfiguration; 21 | import com.sonar.sslr.impl.Lexer; 22 | import com.sonar.sslr.impl.channel.BlackHoleChannel; 23 | 24 | import static com.sonar.sslr.api.GenericTokenType.LITERAL; 25 | import static com.sonar.sslr.impl.channel.RegexpChannelBuilder.commentRegexp; 26 | import static com.sonar.sslr.impl.channel.RegexpChannelBuilder.regexp; 27 | 28 | public class ObjectiveCLexer { 29 | 30 | private ObjectiveCLexer() { 31 | } 32 | 33 | public static Lexer create() { 34 | return create(new ObjectiveCConfiguration()); 35 | } 36 | 37 | public static Lexer create(ObjectiveCConfiguration conf) { 38 | return Lexer.builder() 39 | .withCharset(conf.getCharset()) 40 | 41 | .withFailIfNoChannelToConsumeOneCharacter(false) 42 | 43 | // Comments 44 | .withChannel(commentRegexp("//[^\\n\\r]*+")) 45 | .withChannel(commentRegexp("/\\*[\\s\\S]*?\\*/")) 46 | 47 | // All other tokens 48 | .withChannel(regexp(LITERAL, "[^\r\n\\s/]+")) 49 | 50 | .withChannel(new BlackHoleChannel("[\\s]")) 51 | 52 | .build(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/parser/ObjectiveCGrammarImpl.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.parser; 19 | 20 | import com.backelite.sonarqube.objectivec.lang.api.ObjectiveCGrammar; 21 | 22 | import static com.sonar.sslr.api.GenericTokenType.EOF; 23 | import static com.sonar.sslr.api.GenericTokenType.LITERAL; 24 | import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.o2n; 25 | 26 | public class ObjectiveCGrammarImpl extends ObjectiveCGrammar { 27 | 28 | public ObjectiveCGrammarImpl() { 29 | 30 | program.is(o2n(LITERAL), EOF); 31 | 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/lang/parser/ObjectiveCParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.parser; 19 | 20 | import com.backelite.sonarqube.objectivec.lang.ObjectiveCConfiguration; 21 | import com.backelite.sonarqube.objectivec.lang.api.ObjectiveCGrammar; 22 | import com.backelite.sonarqube.objectivec.lang.lexer.ObjectiveCLexer; 23 | import com.sonar.sslr.impl.Parser; 24 | 25 | public class ObjectiveCParser { 26 | 27 | private ObjectiveCParser() { 28 | } 29 | 30 | public static Parser create() { 31 | return create(new ObjectiveCConfiguration()); 32 | } 33 | 34 | public static Parser create(ObjectiveCConfiguration conf) { 35 | return Parser.builder((ObjectiveCGrammar) new ObjectiveCGrammarImpl()) 36 | .withLexer(ObjectiveCLexer.create(conf)) 37 | .build(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/surefire/ObjectiveCTestFileFinder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.surefire; 19 | 20 | import org.apache.commons.lang.StringUtils; 21 | import com.backelite.sonarqube.commons.TestFileFinder; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.sonar.api.batch.fs.FilePredicate; 25 | import org.sonar.api.batch.fs.FileSystem; 26 | import org.sonar.api.batch.fs.InputFile; 27 | 28 | /** 29 | * Created by gillesgrousset on 28/08/2018. 30 | */ 31 | public class ObjectiveCTestFileFinder implements TestFileFinder { 32 | private static final Logger LOGGER = LoggerFactory.getLogger(ObjectiveCTestFileFinder.class); 33 | 34 | @Override 35 | public InputFile getUnitTestResource(FileSystem fileSystem, String classname) { 36 | String fileName = classname.replace('.', '/') + ".m"; 37 | 38 | FilePredicate fp = fileSystem.predicates().hasPath(fileName); 39 | if(fileSystem.hasFiles(fp)){ 40 | return fileSystem.inputFile(fp); 41 | } 42 | 43 | /* 44 | * Most xcodebuild JUnit parsers don't include the path to the class in the class field, so search for it if it 45 | * wasn't found in the root. 46 | */ 47 | String lastFileNameComponents = StringUtils.substringAfterLast(fileName, "/"); 48 | 49 | if(StringUtils.isEmpty(lastFileNameComponents)) { 50 | lastFileNameComponents = fileName; 51 | } 52 | 53 | fp = fileSystem.predicates().and( 54 | fileSystem.predicates().hasType(InputFile.Type.TEST), 55 | fileSystem.predicates().matchesPathPattern("**/" + fileName.replace("_", "+")) 56 | ); 57 | 58 | if(fileSystem.hasFiles(fp)){ 59 | /* 60 | * Lazily get the first file, since we wouldn't be able to determine the correct one from just the 61 | * test class name in the event that there are multiple matches. 62 | */ 63 | return fileSystem.inputFiles(fp).iterator().next(); 64 | } 65 | 66 | LOGGER.info("Unable to locate Objective-C test source file for classname {}. Make sure your test class name matches its filename.", classname); 67 | return null; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /objclang/src/test/java/com/backelite/sonarqube/objectivec/lang/ObjectiveCAstScannerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang;/* 19 | * Sonar Objective-C Plugin 20 | * Copyright (C) 2012 OCTO Technology, Backelite 21 | * dev@sonar.codehaus.org 22 | * 23 | * This program is free software; you can redistribute it and/or 24 | * modify it under the terms of the GNU Lesser General Public 25 | * License as published by the Free Software Foundation; either 26 | * version 3 of the License, or (at your option) any later version. 27 | * 28 | * This program is distributed in the hope that it will be useful, 29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 31 | * Lesser General Public License for more details. 32 | * 33 | * You should have received a copy of the GNU Lesser General Public 34 | * License along with this program; if not, write to the Free Software 35 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 36 | */ 37 | 38 | import com.backelite.sonarqube.objectivec.lang.api.ObjectiveCMetric; 39 | import org.hamcrest.Matchers; 40 | import org.junit.Assert; 41 | import org.junit.Test; 42 | import org.sonar.squidbridge.api.SourceFile; 43 | 44 | import java.io.File; 45 | 46 | public class ObjectiveCAstScannerTest { 47 | 48 | @Test 49 | public void lines() { 50 | SourceFile file = ObjectiveCAstScanner.scanSingleFile(new File("src/test/resources/objcSample.h")); 51 | Assert.assertThat(file.getInt(ObjectiveCMetric.LINES), Matchers.is(17)); 52 | } 53 | 54 | @Test 55 | public void lines_of_code() { 56 | SourceFile file = ObjectiveCAstScanner.scanSingleFile(new File("src/test/resources/objcSample.h")); 57 | Assert.assertThat(file.getInt(ObjectiveCMetric.LINES_OF_CODE), Matchers.is(5)); 58 | } 59 | 60 | @Test 61 | public void comments() { 62 | SourceFile file = ObjectiveCAstScanner.scanSingleFile(new File("src/test/resources/objcSample.h")); 63 | Assert.assertThat(file.getInt(ObjectiveCMetric.COMMENT_LINES), Matchers.is(4)); 64 | Assert.assertThat(file.getNoSonarTagLines(), Matchers.hasItem(10)); 65 | Assert.assertThat(file.getNoSonarTagLines().size(), Matchers.is(1)); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /objclang/src/test/java/com/backelite/sonarqube/objectivec/lang/api/ObjectiveCPunctuatorTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.api; 19 | 20 | import org.hamcrest.Matchers; 21 | import org.junit.Assert; 22 | import org.junit.Test; 23 | 24 | public class ObjectiveCPunctuatorTest { 25 | 26 | @Test 27 | public void test() { 28 | Assert.assertThat(ObjectiveCPunctuator.values().length, Matchers.is(48)); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /objclang/src/test/java/com/backelite/sonarqube/objectivec/lang/lexer/ObjectiveCLexerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Objective-C module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.objectivec.lang.lexer; 19 | 20 | import com.sonar.sslr.api.GenericTokenType; 21 | import com.sonar.sslr.api.Token; 22 | import com.sonar.sslr.impl.Lexer; 23 | import com.sonar.sslr.test.lexer.LexerMatchers; 24 | import org.hamcrest.Matchers; 25 | import org.junit.Assert; 26 | import org.junit.BeforeClass; 27 | import org.junit.Test; 28 | 29 | import java.io.File; 30 | import java.util.List; 31 | 32 | public class ObjectiveCLexerTest { 33 | 34 | private static Lexer lexer; 35 | 36 | @BeforeClass 37 | public static void init() { 38 | lexer = ObjectiveCLexer.create(); 39 | } 40 | 41 | @Test 42 | public void lexMultiLinesComment() { 43 | Assert.assertThat(lexer.lex("/* My Comment \n*/"), LexerMatchers.hasComment("/* My Comment \n*/")); 44 | Assert.assertThat(lexer.lex("/**/"), LexerMatchers.hasComment("/**/")); 45 | } 46 | 47 | @Test 48 | public void lexInlineComment() { 49 | Assert.assertThat(lexer.lex("// My Comment \n new line"), LexerMatchers.hasComment("// My Comment ")); 50 | Assert.assertThat(lexer.lex("//"), LexerMatchers.hasComment("//")); 51 | } 52 | 53 | @Test 54 | public void lexEndOflineComment() { 55 | Assert.assertThat(lexer.lex("[self init]; // My Comment end of line"), LexerMatchers.hasComment("// My Comment end of line")); 56 | Assert.assertThat(lexer.lex("[self init]; //"), LexerMatchers.hasComment("//")); 57 | } 58 | 59 | @Test 60 | public void lexLineOfCode() { 61 | Assert.assertThat(lexer.lex("[self init];"), LexerMatchers.hasToken("[self", GenericTokenType.LITERAL)); 62 | } 63 | 64 | @Test 65 | public void lexEmptyLine() { 66 | List tokens = lexer.lex("\n"); 67 | Assert.assertThat(tokens.size(), Matchers.equalTo(1)); 68 | Assert.assertThat(tokens, LexerMatchers.hasToken(GenericTokenType.EOF)); 69 | } 70 | 71 | @Test 72 | public void lexSampleFile() { 73 | List tokens = lexer.lex(new File("src/test/resources/objcSample.h")); 74 | Assert.assertThat(tokens.size(), Matchers.equalTo(16)); 75 | Assert.assertThat(tokens, LexerMatchers.hasToken(GenericTokenType.EOF)); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /objclang/src/test/resources/Profile.m: -------------------------------------------------------------------------------- 1 | // 2 | // Profile.m 3 | // Stop-tabac 4 | // 5 | // Created by François HELG on 5/29/12. 6 | // Copyright (c) 2012 Université de Genève. All rights reserved. 7 | // 8 | 9 | #import "Profile.h" 10 | #import "Purchase.h" 11 | 12 | 13 | @implementation Profile 14 | 15 | @dynamic cigaretteCounter; 16 | @dynamic dailyCost; 17 | @dynamic facebookOff; 18 | @dynamic firstCigaretteAfterWakeUp; 19 | @dynamic godfatherId; 20 | @dynamic godfatherName; 21 | @dynamic hasQuitSmoking; 22 | @dynamic lifeCounter; 23 | @dynamic nbOfSmokedCigarettesPerDay; 24 | @dynamic nextCoachMessageToDisplay; 25 | @dynamic nextFailureMessageToDisplay; 26 | @dynamic nextCravingMessageToDisplay; 27 | @dynamic quitSmokingDate; 28 | @dynamic substitute; 29 | @dynamic purchase; 30 | @dynamic dependencyLevel; 31 | @dynamic deliverSubstituteMessages; 32 | @dynamic lastAchievementDayFilename; 33 | @dynamic lastAchievementAssiduityFilename; 34 | @dynamic lastAchievementWillingnessFilename; 35 | @dynamic numberOfConnexions; 36 | @dynamic numberOfAdvicesTaken; 37 | @dynamic numberOfFailures; 38 | 39 | @end -------------------------------------------------------------------------------- /objclang/src/test/resources/objcSample.h: -------------------------------------------------------------------------------- 1 | // 2 | // STWelcomeViewController.h 3 | // Stop-tabac 4 | // 5 | // Created by François HELG on 5/7/12. 6 | // Copyright (c) 2012 Université de Genève. All rights reserved. 7 | // 8 | 9 | #import 10 | // NOSONAR 11 | @class Profile; 12 | 13 | @interface StillSmokingViewController : UIViewController 14 | 15 | @property (strong, nonatomic) Profile *userProfile; 16 | 17 | @end -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/sonar-swift/a5e219515cd39701aa5c8d93f954a64acff3aa82/screenshot.png -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | # Copyright © 2015 Backelite (${email}) 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Lesser General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public License 16 | # along with this program. If not, see . 17 | # 18 | 19 | sonar.projectKey=prjKey 20 | sonar.projectName=prjName 21 | # Number version (can be found automatically in plist, just comment this line) 22 | sonar.projectVersion=1.0 23 | 24 | # Comment if you have a project with mixed ObjC / Swift 25 | sonar.language=swift 26 | 27 | # Project description 28 | sonar.projectDescription=prjDescription 29 | 30 | # Path to source directories 31 | sonar.sources=SourceDir 32 | # Path to test directories (comment if no test) 33 | sonar.tests=TestDir 34 | 35 | # Destination Simulator to run surefire 36 | # As string expected in destination argument of xcodebuild command 37 | # Example = sonar.swift.simulator=platform=iOS Simulator,name=iPhone 6,OS=9.2 38 | sonar.swift.simulator=platform=iOS Simulator,name=iPhone X,OS=latest 39 | 40 | # Xcode project configuration (.xcodeproj) 41 | # and use the later to specify which project(s) to include in the analysis (comma separated list) 42 | # Specify either xcodeproj or xcodeproj + xcworkspace 43 | #sonar.swift.project=MyPrj.xcodeproj 44 | #sonar.swift.workspace=MyWrkSpc.xcworkspace 45 | 46 | # Scheme to build your application 47 | sonar.swift.appScheme=MyScheme 48 | 49 | # Specify your appname when different from targeted scheme. 50 | # Or when slather fails with 'No product binary found' 51 | # You can also provide a list of framework names to analyse for coverage. 52 | # This will be something like "myApp" or "myApp,myFramework" 53 | # sonar.coverage.binaryNames=myApp,myFramework 54 | 55 | # Configuration to use for your scheme. if you do not specify that the default will be Debug 56 | sonar.swift.appConfiguration=MyConfiguration 57 | 58 | ########################## 59 | # Optional configuration # 60 | ########################## 61 | # Encoding of the source code 62 | sonar.sourceEncoding=UTF-8 63 | # SCM 64 | # sonar.scm.enabled=true 65 | # sonar.scm.url=scm:git:http://xxx 66 | 67 | # JUnit report generated by run-sonar.sh is stored in sonar-reports/TEST-report.xml 68 | # Change it only if you generate the file on your own 69 | # The XML files have to be prefixed by TEST- otherwise they are not processed 70 | # sonar.junit.reportsPath=sonar-reports/ 71 | 72 | # Lizard report generated by run-sonar.sh is stored in sonar-reports/lizard-report.xml 73 | # Change it only if you generate the file on your own 74 | # sonar.swift.lizard.report=sonar-reports/lizard-report.xml 75 | 76 | # Cobertura report generated by run-sonar.sh is stored in sonar-reports/coverage-swift.xml 77 | # Change it only if you generate the file on your own 78 | # sonar.swift.coverage.reportPattern=sonar-reports/coverage-swift*.xml 79 | 80 | # OCLint report generated by run-sonar.sh is stored in sonar-reports/oclint.xml 81 | # Change it only if you generate the file on your own 82 | # sonar.swift.swiftlint.report=sonar-reports/*swiftlint.txt 83 | 84 | # Change it only if you generate the file on your own 85 | # sonar.swift.tailor.report=sonar-reports/*tailor.txt 86 | 87 | # Paths to exclude from coverage report (surefire, 3rd party libraries etc.) 88 | # sonar.swift.excludedPathsFromCoverage=pattern1,pattern2 89 | sonar.swift.excludedPathsFromCoverage=.*Tests.* 90 | 91 | # Ability to skip tests (such as UI Tests running long time) 92 | # Example = sonar.swift.skipTests=UITests 93 | 94 | ########################## 95 | # Tailor configuration # 96 | ########################## 97 | # Tailor configuration 98 | # -l,--max-line-length=<0-999> maximum Line length (in characters) 99 | # --list-files display Swift source files to be analyzed 100 | # --max-class-length=<0-999> maximum Class length (in lines) 101 | # --max-closure-length=<0-999> maximum Closure length (in lines) 102 | # --max-file-length=<0-999> maximum File length (in lines) 103 | # --max-function-length=<0-999> maximum Function length (in lines) 104 | # --max-name-length=<0-999> maximum Identifier name length (in characters) 105 | # --max-severity= maximum severity 106 | # --max-struct-length=<0-999> maximum Struct length (in lines) 107 | # --min-name-length=<1-999> minimum Identifier name length (in characters) 108 | sonar.swift.tailor.config=--no-color --max-line-length=100 --max-file-length=500 --max-name-length=40 --max-name-length=40 --min-name-length=4 109 | -------------------------------------------------------------------------------- /sonar-swift-plugin/src/main/java/com/backelite/sonarqube/swift/complexity/LizardSensor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * backelite-sonar-swift-plugin - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.complexity; 19 | 20 | import com.backelite.sonarqube.commons.Constants; 21 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 22 | import com.backelite.sonarqube.swift.lang.core.Swift; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.sonar.api.batch.fs.InputFile; 26 | import org.sonar.api.batch.sensor.Sensor; 27 | import org.sonar.api.batch.sensor.SensorContext; 28 | import org.sonar.api.batch.sensor.SensorDescriptor; 29 | 30 | import java.io.File; 31 | import java.io.IOException; 32 | import java.nio.file.Files; 33 | import java.nio.file.Path; 34 | import java.nio.file.Paths; 35 | 36 | public class LizardSensor implements Sensor { 37 | private static final Logger LOGGER = LoggerFactory.getLogger(LizardSensor.class); 38 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".lizard.report"; 39 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/lizard-report.xml"; 40 | 41 | private final SensorContext context; 42 | 43 | public LizardSensor(final SensorContext context) { 44 | this.context = context; 45 | } 46 | 47 | private String reportPath() { 48 | return context.config() 49 | .get(REPORT_PATH_KEY) 50 | .orElse(DEFAULT_REPORT_PATH); 51 | } 52 | 53 | @Override 54 | public void describe(SensorDescriptor descriptor) { 55 | descriptor 56 | .name("Lizard") 57 | .onlyOnLanguages(Swift.KEY, ObjectiveC.KEY) 58 | .onlyOnFileType(InputFile.Type.MAIN); 59 | } 60 | 61 | @Override 62 | public void execute(SensorContext context) { 63 | File reportFile = new File(context.fileSystem().baseDir(), reportPath()); 64 | if (!reportFile.isFile()) { 65 | LOGGER.warn("Lizard report file not found at {}", reportFile.getAbsolutePath()); 66 | return; 67 | } 68 | 69 | LOGGER.info("Processing complexity report: {}", reportFile.getAbsolutePath()); 70 | LizardReportParser parser = new LizardReportParser(context); 71 | parser.parseReport(reportFile); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /sonar-swift-plugin/src/main/java/com/backelite/sonarqube/swift/coverage/CoberturaSensor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * backelite-sonar-swift-plugin - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.coverage; 19 | 20 | import com.backelite.sonarqube.commons.Constants; 21 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 22 | import com.backelite.sonarqube.swift.lang.core.Swift; 23 | import org.apache.tools.ant.DirectoryScanner; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.sonar.api.batch.fs.InputFile; 27 | import org.sonar.api.batch.sensor.Sensor; 28 | import org.sonar.api.batch.sensor.SensorContext; 29 | import org.sonar.api.batch.sensor.SensorDescriptor; 30 | 31 | import java.io.File; 32 | 33 | public class CoberturaSensor implements Sensor { 34 | private static final Logger LOGGER = LoggerFactory.getLogger(CoberturaSensor.class); 35 | public static final String REPORT_PATTERN_KEY = Constants.PROPERTY_PREFIX + ".coverage.reportPattern"; 36 | public static final String DEFAULT_REPORT_PATTERN = "sonar-reports/coverage*.xml"; 37 | private final SensorContext context; 38 | 39 | public CoberturaSensor(final SensorContext context) { 40 | this.context = context; 41 | } 42 | 43 | private String reportPath() { 44 | return context.config() 45 | .get(REPORT_PATTERN_KEY) 46 | .orElse(DEFAULT_REPORT_PATTERN); 47 | } 48 | 49 | @Override 50 | public void describe(SensorDescriptor descriptor) { 51 | descriptor 52 | .name("Cobertura") 53 | .onlyOnLanguages(Swift.KEY, ObjectiveC.KEY) 54 | .onlyOnFileType(InputFile.Type.MAIN); 55 | } 56 | 57 | @Override 58 | public void execute(SensorContext context) { 59 | CoberturaReportParser parser = new CoberturaReportParser(context); 60 | DirectoryScanner scanner = new DirectoryScanner(); 61 | scanner.setIncludes(new String[]{reportPath()}); 62 | scanner.setBasedir(context.fileSystem().baseDir().getAbsolutePath()); 63 | scanner.setCaseSensitive(false); 64 | scanner.scan(); 65 | String[] files = scanner.getIncludedFiles(); 66 | 67 | for (String filename : files) { 68 | LOGGER.info("Processing Cobertura report {}", filename); 69 | parser.parseReport(new File(filename)); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /sonar-swift-plugin/src/test/resources/coverage/dir1/cobertura.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/sonar-swift/a5e219515cd39701aa5c8d93f954a64acff3aa82/sonar-swift-plugin/src/test/resources/coverage/dir1/cobertura.xml -------------------------------------------------------------------------------- /sonar-swift-plugin/src/test/resources/coverage/dir2/cobertura.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/sonar-swift/a5e219515cd39701aa5c8d93f954a64acff3aa82/sonar-swift-plugin/src/test/resources/coverage/dir2/cobertura.xml -------------------------------------------------------------------------------- /sonar-swift-plugin/src/test/resources/coverage/dir3/cobertura.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Idean/sonar-swift/a5e219515cd39701aa5c8d93f954a64acff3aa82/sonar-swift-plugin/src/test/resources/coverage/dir3/cobertura.xml -------------------------------------------------------------------------------- /swiftlang/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 24 | 25 | backelite-swift 26 | com.backelite.sonarqube 27 | 0.4.7-SNAPSHOT 28 | 29 | 4.0.0 30 | 31 | swift-lang 32 | Swift SonarQube Plugin - Swift module 33 | 34 | 35 | 36 | 37 | com.backelite.sonarqube 38 | commons 39 | 0.4.7-SNAPSHOT 40 | 41 | 42 | 43 | org.sonarsource.sslr 44 | sslr-core 45 | 46 | 47 | org.sonarsource.sslr-squid-bridge 48 | sslr-squid-bridge 49 | 50 | 51 | ch.qos.logback 52 | logback-classic 53 | 54 | 55 | ant 56 | ant 57 | 58 | 59 | com.google.guava 60 | guava 61 | 62 | 63 | com.googlecode.json-simple 64 | json-simple 65 | 66 | 67 | 68 | 69 | junit 70 | junit 71 | compile 72 | 73 | 74 | org.mockito 75 | mockito-all 76 | compile 77 | 78 | 79 | org.assertj 80 | assertj-core 81 | 82 | 83 | org.sonarsource.sonarqube 84 | sonar-testing-harness 85 | 86 | 87 | org.sonarsource.sslr 88 | sslr-testing-harness 89 | compile 90 | 91 | 92 | org.sonarsource.sonarlint.core 93 | sonarlint-core 94 | 95 | 96 | org.sonarsource.orchestrator 97 | sonar-orchestrator 98 | 99 | 100 | org.sonarsource.sonarqube 101 | sonar-plugin-api 102 | 103 | 104 | org.slf4j 105 | slf4j-api 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/SwiftConstants.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift; 19 | 20 | public final class SwiftConstants { 21 | public static final String FILE_SUFFIXES = "swift"; 22 | } 23 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/SwiftProfile.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues; 19 | 20 | import com.backelite.sonarqube.swift.issues.swiftlint.SwiftLintProfile; 21 | import com.backelite.sonarqube.swift.issues.swiftlint.SwiftLintProfileImporter; 22 | import com.backelite.sonarqube.swift.issues.tailor.TailorProfileImporter; 23 | import com.backelite.sonarqube.swift.lang.core.Swift; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.sonar.api.profiles.RulesProfile; 27 | import org.sonar.api.rules.ActiveRule; 28 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 29 | import org.sonar.api.utils.ValidationMessages; 30 | 31 | import java.io.IOException; 32 | import java.io.InputStreamReader; 33 | import java.io.Reader; 34 | 35 | public class SwiftProfile implements BuiltInQualityProfilesDefinition { 36 | 37 | private static final Logger LOGGER = LoggerFactory.getLogger(SwiftProfile.class); 38 | 39 | private final SwiftLintProfileImporter swiftLintProfileImporter; 40 | private final TailorProfileImporter tailorProfileImporter; 41 | 42 | public SwiftProfile(final SwiftLintProfileImporter swiftLintProfileImporter, final TailorProfileImporter tailorProfileImporter) { 43 | this.swiftLintProfileImporter = swiftLintProfileImporter; 44 | this.tailorProfileImporter = tailorProfileImporter; 45 | } 46 | 47 | @Override 48 | public void define(BuiltInQualityProfilesDefinition.Context context) { 49 | LOGGER.info("Creating Swift Profile"); 50 | 51 | BuiltInQualityProfilesDefinition.NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile("Swift", Swift.KEY); 52 | nbiqp.setDefault(true); 53 | 54 | try (Reader config = new InputStreamReader(getClass().getResourceAsStream(SwiftLintProfile.PROFILE_PATH))) { 55 | RulesProfile ocLintRulesProfile = swiftLintProfileImporter.importProfile(config, ValidationMessages.create()); 56 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 57 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 58 | } 59 | } catch (IOException ex) { 60 | LOGGER.error("Error Creating Swift Profile", ex); 61 | } 62 | nbiqp.done(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/swiftlint/SwiftLintProfile.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.swiftlint; 19 | 20 | import com.backelite.sonarqube.swift.lang.core.Swift; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.sonar.api.profiles.RulesProfile; 24 | import org.sonar.api.rules.ActiveRule; 25 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 26 | import org.sonar.api.utils.ValidationMessages; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStreamReader; 30 | import java.io.Reader; 31 | 32 | /** 33 | * Created by gillesgrousset on 03/11/2015. 34 | */ 35 | 36 | public class SwiftLintProfile implements BuiltInQualityProfilesDefinition { 37 | public static final String PROFILE_PATH = "/org/sonar/plugins/swiftlint/profile-swiftlint.xml"; 38 | private static final Logger LOGGER = LoggerFactory.getLogger(SwiftLintProfile.class); 39 | 40 | private final SwiftLintProfileImporter profileImporter; 41 | 42 | public SwiftLintProfile(final SwiftLintProfileImporter importer) { 43 | profileImporter = importer; 44 | } 45 | 46 | @Override 47 | public void define(Context context) { 48 | LOGGER.info("Creating SwiftLint Profile"); 49 | NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile(SwiftLintRulesDefinition.REPOSITORY_KEY, Swift.KEY); 50 | 51 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(SwiftLintProfile.PROFILE_PATH))) { 52 | RulesProfile ocLintRulesProfile = profileImporter.importProfile(config, ValidationMessages.create()); 53 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 54 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 55 | } 56 | } catch (IOException ex){ 57 | LOGGER.error("Error Creating SwiftLint Profile",ex); 58 | } 59 | nbiqp.done(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/swiftlint/SwiftLintProfileImporter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.swiftlint; 19 | 20 | import com.backelite.sonarqube.swift.lang.core.Swift; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.sonar.api.profiles.ProfileImporter; 24 | import org.sonar.api.profiles.RulesProfile; 25 | import org.sonar.api.profiles.XMLProfileParser; 26 | import org.sonar.api.utils.ValidationMessages; 27 | 28 | import java.io.Reader; 29 | 30 | public class SwiftLintProfileImporter extends ProfileImporter { 31 | private static final Logger LOGGER = LoggerFactory.getLogger(SwiftLintProfileImporter.class); 32 | private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default SwiftLint profile"; 33 | 34 | private final XMLProfileParser profileParser; 35 | 36 | public SwiftLintProfileImporter(final XMLProfileParser xmlProfileParser) { 37 | super(SwiftLintRulesDefinition.REPOSITORY_KEY, SwiftLintRulesDefinition.REPOSITORY_KEY); 38 | setSupportedLanguages(Swift.KEY); 39 | this.profileParser = xmlProfileParser; 40 | } 41 | 42 | @Override 43 | public RulesProfile importProfile(Reader reader, ValidationMessages messages) { 44 | final RulesProfile profile = profileParser.parse(reader, messages); 45 | 46 | if (null == profile) { 47 | messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); 48 | LOGGER.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); 49 | } 50 | 51 | return profile; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/swiftlint/SwiftLintReportParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.swiftlint; 19 | 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.sonar.api.batch.fs.FilePredicate; 23 | import org.sonar.api.batch.fs.InputFile; 24 | import org.sonar.api.batch.sensor.SensorContext; 25 | import org.sonar.api.batch.sensor.issue.NewIssueLocation; 26 | import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation; 27 | import org.sonar.api.rule.RuleKey; 28 | 29 | import java.io.*; 30 | import java.nio.file.Files; 31 | import java.util.regex.Matcher; 32 | import java.util.regex.Pattern; 33 | import java.util.stream.Stream; 34 | 35 | public class SwiftLintReportParser { 36 | private static final Logger LOGGER = LoggerFactory.getLogger(SwiftLintReportParser.class); 37 | 38 | private final SensorContext context; 39 | 40 | public SwiftLintReportParser(final SensorContext context) { 41 | this.context = context; 42 | } 43 | 44 | public void parseReport(File reportFile) { 45 | try (Stream lines = Files.lines(reportFile.toPath())) { 46 | // Read and parse report 47 | lines.forEach(this::recordIssue); 48 | } catch (IOException e) { 49 | LOGGER.error("Failed to parse SwiftLint report file", e); 50 | } 51 | } 52 | 53 | private void recordIssue(final String line) { 54 | LOGGER.debug("record issue {}", line); 55 | 56 | Pattern pattern = Pattern.compile("(.*.swift):(\\w+):?(\\w+)?: (warning|error): (.*) \\((\\w+)"); 57 | Matcher matcher = pattern.matcher(line); 58 | while (matcher.find()) { 59 | String filePath = matcher.group(1); 60 | int lineNum = Integer.parseInt(matcher.group(2)); 61 | String message = matcher.group(5); 62 | String ruleId = matcher.group(6); 63 | 64 | FilePredicate fp = context.fileSystem().predicates().hasAbsolutePath(filePath); 65 | if (!context.fileSystem().hasFiles(fp)) { 66 | LOGGER.warn("file not included in sonar {}", filePath); 67 | continue; 68 | } 69 | 70 | InputFile inputFile = context.fileSystem().inputFile(fp); 71 | NewIssueLocation dil = new DefaultIssueLocation() 72 | .on(inputFile) 73 | .at(inputFile.selectLine(lineNum)) 74 | .message(message); 75 | context.newIssue() 76 | .forRule(RuleKey.of(SwiftLintRulesDefinition.REPOSITORY_KEY, ruleId)) 77 | .at(dil) 78 | .save(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/swiftlint/SwiftLintRulesDefinition.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.swiftlint; 19 | 20 | import com.backelite.sonarqube.swift.lang.core.Swift; 21 | import org.json.simple.JSONArray; 22 | import org.json.simple.JSONObject; 23 | import org.json.simple.JSONValue; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.sonar.api.server.rule.RulesDefinition; 27 | import org.sonar.squidbridge.rules.SqaleXmlLoader; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStreamReader; 31 | import java.io.Reader; 32 | import java.nio.charset.Charset; 33 | 34 | /** 35 | * Created by gillesgrousset on 27/11/2015. 36 | */ 37 | public class SwiftLintRulesDefinition implements RulesDefinition { 38 | private static final Logger LOGGER = LoggerFactory.getLogger(SwiftLintRulesDefinition.class); 39 | public static final String REPOSITORY_KEY = "SwiftLint"; 40 | public static final String REPOSITORY_NAME = REPOSITORY_KEY; 41 | private static final String RULES_FILE = "/org/sonar/plugins/swiftlint/rules.json"; 42 | 43 | @Override 44 | public void define(Context context) { 45 | NewRepository repository = context.createRepository(REPOSITORY_KEY, Swift.KEY).setName(REPOSITORY_NAME); 46 | 47 | try(Reader reader = new InputStreamReader(getClass().getResourceAsStream(RULES_FILE), Charset.forName("UTF-8"))){ 48 | JSONArray slRules = (JSONArray)JSONValue.parse(reader); 49 | if(slRules != null){ 50 | for (Object obj : slRules) { 51 | JSONObject slRule = (JSONObject) obj; 52 | repository.createRule((String) slRule.get("key")) 53 | .setName((String) slRule.get("name")) 54 | .setSeverity((String) slRule.get("severity")) 55 | .setHtmlDescription((String) slRule.get("description")); 56 | } 57 | } 58 | } catch (IOException e) { 59 | LOGGER.error("Failed to load SwiftLint rules", e); 60 | } 61 | SqaleXmlLoader.load(repository, "/com/sonar/sqale/swiftlint-model.xml"); 62 | repository.done(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/swiftlint/SwiftLintSensor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.swiftlint; 19 | 20 | import com.backelite.sonarqube.commons.Constants; 21 | import com.backelite.sonarqube.swift.lang.core.Swift; 22 | import org.apache.tools.ant.DirectoryScanner; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.sonar.api.batch.fs.InputFile; 26 | import org.sonar.api.batch.sensor.Sensor; 27 | import org.sonar.api.batch.sensor.SensorContext; 28 | import org.sonar.api.batch.sensor.SensorDescriptor; 29 | 30 | import java.io.File; 31 | 32 | 33 | public class SwiftLintSensor implements Sensor { 34 | private static final Logger LOGGER = LoggerFactory.getLogger(SwiftLintSensor.class); 35 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".swiftlint.report"; 36 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/*swiftlint.txt"; 37 | 38 | private final SensorContext context; 39 | 40 | public SwiftLintSensor(final SensorContext context) { 41 | this.context = context; 42 | } 43 | 44 | private String reportPath() { 45 | return context.config() 46 | .get(REPORT_PATH_KEY) 47 | .orElse(DEFAULT_REPORT_PATH); 48 | } 49 | 50 | @Override 51 | public void describe(SensorDescriptor descriptor) { 52 | descriptor 53 | .onlyOnLanguage(Swift.KEY) 54 | .name("SwiftLint") 55 | .onlyOnFileType(InputFile.Type.MAIN); 56 | } 57 | 58 | @Override 59 | public void execute(SensorContext context) { 60 | SwiftLintReportParser parser = new SwiftLintReportParser(context); 61 | DirectoryScanner scanner = new DirectoryScanner(); 62 | scanner.setIncludes(new String[]{reportPath()}); 63 | scanner.setBasedir(context.fileSystem().baseDir().getAbsolutePath()); 64 | scanner.setCaseSensitive(false); 65 | scanner.scan(); 66 | String[] files = scanner.getIncludedFiles(); 67 | 68 | for (String filename : files) { 69 | LOGGER.info("Processing SwiftLint report {}", filename); 70 | parser.parseReport(new File(filename)); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/tailor/TailorProfile.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.tailor; 19 | 20 | import com.backelite.sonarqube.swift.lang.core.Swift; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.sonar.api.profiles.RulesProfile; 24 | import org.sonar.api.rules.ActiveRule; 25 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 26 | import org.sonar.api.utils.ValidationMessages; 27 | 28 | import java.io.IOException; 29 | import java.io.InputStreamReader; 30 | import java.io.Reader; 31 | 32 | /** 33 | * Created by tzwickl on 22/11/2016. 34 | */ 35 | 36 | public class TailorProfile implements BuiltInQualityProfilesDefinition { 37 | private static final Logger LOGGER = LoggerFactory.getLogger(TailorProfile.class); 38 | public static final String PROFILE_PATH = "/org/sonar/plugins/tailor/profile-tailor.xml"; 39 | 40 | private final TailorProfileImporter profileImporter; 41 | 42 | public TailorProfile(final TailorProfileImporter importer) { 43 | this.profileImporter = importer; 44 | } 45 | 46 | @Override 47 | public void define(Context context) { 48 | LOGGER.info("Creating Tailor Profile"); 49 | NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile(TailorRulesDefinition.REPOSITORY_KEY, Swift.KEY); 50 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(PROFILE_PATH))) { 51 | RulesProfile ocLintRulesProfile = profileImporter.importProfile(config, ValidationMessages.create()); 52 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 53 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 54 | } 55 | } catch (IOException ex){ 56 | LOGGER.error("Error Creating Tailor Profile",ex); 57 | } 58 | nbiqp.done(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/tailor/TailorProfileImporter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.tailor; 19 | 20 | import com.backelite.sonarqube.swift.lang.core.Swift; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.sonar.api.profiles.ProfileImporter; 24 | import org.sonar.api.profiles.RulesProfile; 25 | import org.sonar.api.profiles.XMLProfileParser; 26 | import org.sonar.api.utils.ValidationMessages; 27 | 28 | import java.io.Reader; 29 | 30 | /** 31 | * Created by tzwickl on 22/11/2016. 32 | */ 33 | 34 | public class TailorProfileImporter extends ProfileImporter { 35 | private static final Logger LOGGER = LoggerFactory.getLogger(TailorProfileImporter.class); 36 | private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default tailor profile"; 37 | 38 | private final XMLProfileParser profileParser; 39 | 40 | public TailorProfileImporter(final XMLProfileParser xmlProfileParser) { 41 | super(TailorRulesDefinition.REPOSITORY_KEY, TailorRulesDefinition.REPOSITORY_KEY); 42 | setSupportedLanguages(Swift.KEY); 43 | this.profileParser = xmlProfileParser; 44 | } 45 | 46 | @Override 47 | public RulesProfile importProfile(Reader reader, ValidationMessages messages) { 48 | final RulesProfile profile = profileParser.parse(reader, messages); 49 | 50 | if (null == profile) { 51 | messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); 52 | LOGGER.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); 53 | } 54 | 55 | return profile; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/tailor/TailorReportParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.tailor; 19 | 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.sonar.api.batch.fs.FilePredicate; 23 | import org.sonar.api.batch.fs.InputFile; 24 | import org.sonar.api.batch.sensor.SensorContext; 25 | import org.sonar.api.batch.sensor.issue.NewIssueLocation; 26 | import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation; 27 | import org.sonar.api.rule.RuleKey; 28 | 29 | import java.io.*; 30 | import java.nio.file.Files; 31 | import java.util.regex.Matcher; 32 | import java.util.regex.Pattern; 33 | import java.util.stream.Stream; 34 | 35 | /** 36 | * Created by tzwickl on 22/11/2016. 37 | */ 38 | 39 | public class TailorReportParser { 40 | 41 | private static final Logger LOGGER = LoggerFactory.getLogger(TailorReportParser.class); 42 | 43 | private final SensorContext context; 44 | 45 | public TailorReportParser(final SensorContext context) { 46 | this.context = context; 47 | } 48 | 49 | public void parseReport(final File reportFile) { 50 | try (Stream lines = Files.lines(reportFile.toPath())) { 51 | // Read and parse report 52 | lines.forEach(this::recordIssue); 53 | } catch (IOException e) { 54 | LOGGER.error("Failed to parse SwiftLint report file", e); 55 | } 56 | } 57 | 58 | private void recordIssue(final String line) { 59 | LOGGER.debug("record issue {}", line); 60 | 61 | Pattern pattern = Pattern.compile("(.*.swift):(\\w+):(\\w+): (.*): \\[(.*)\\] (.*)"); 62 | Matcher matcher = pattern.matcher(line); 63 | while (matcher.find()) { 64 | String filePath = matcher.group(1); 65 | int lineNum = Integer.parseInt(matcher.group(2)); 66 | String ruleId = matcher.group(5); 67 | String message = matcher.group(6); 68 | 69 | FilePredicate fp = context.fileSystem().predicates().hasAbsolutePath(filePath); 70 | if (!context.fileSystem().hasFiles(fp)) { 71 | LOGGER.warn("file not included in sonar {}", filePath); 72 | continue; 73 | } 74 | 75 | InputFile inputFile = context.fileSystem().inputFile(fp); 76 | NewIssueLocation dil = new DefaultIssueLocation() 77 | .on(inputFile) 78 | .at(inputFile.selectLine(lineNum)) 79 | .message(message); 80 | context.newIssue() 81 | .forRule(RuleKey.of(TailorRulesDefinition.REPOSITORY_KEY, ruleId)) 82 | .at(dil) 83 | .save(); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/tailor/TailorRulesDefinition.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.tailor; 19 | 20 | import com.backelite.sonarqube.swift.lang.core.Swift; 21 | import org.json.simple.JSONArray; 22 | import org.json.simple.JSONObject; 23 | import org.json.simple.JSONValue; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.sonar.api.server.rule.RulesDefinition; 27 | import org.sonar.squidbridge.rules.SqaleXmlLoader; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStreamReader; 31 | import java.io.Reader; 32 | import java.nio.charset.Charset; 33 | 34 | /** 35 | * Created by tzwickl on 22/11/2016. 36 | */ 37 | 38 | public class TailorRulesDefinition implements RulesDefinition { 39 | private static final Logger LOGGER = LoggerFactory.getLogger(TailorRulesDefinition.class); 40 | public static final String REPOSITORY_KEY = "Tailor"; 41 | public static final String REPOSITORY_NAME = REPOSITORY_KEY; 42 | private static final String RULES_FILE = "/org/sonar/plugins/tailor/rules.json"; 43 | 44 | @Override 45 | public void define(final Context context) { 46 | NewRepository repository = context.createRepository(REPOSITORY_KEY, Swift.KEY).setName(REPOSITORY_NAME); 47 | 48 | try(Reader reader = new InputStreamReader(getClass().getResourceAsStream(RULES_FILE), Charset.forName("UTF-8"))){ 49 | JSONArray slRules = (JSONArray)JSONValue.parse(reader); 50 | if(slRules != null){ 51 | for (Object obj : slRules) { 52 | JSONObject slRule = (JSONObject) obj; 53 | repository.createRule((String) slRule.get("key")) 54 | .setName((String) slRule.get("name")) 55 | .setSeverity((String) slRule.get("severity")) 56 | .setHtmlDescription(slRule.get("description") + 57 | " (" + slRule.get("styleguide") + ")"); 58 | } 59 | } 60 | } catch (IOException e) { 61 | LOGGER.error("Failed to load tailor rules", e); 62 | } 63 | SqaleXmlLoader.load(repository, "/com/sonar/sqale/tailor-model.xml"); 64 | repository.done(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/issues/tailor/TailorSensor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.issues.tailor; 19 | 20 | import com.backelite.sonarqube.commons.Constants; 21 | import com.backelite.sonarqube.swift.lang.core.Swift; 22 | import org.apache.tools.ant.DirectoryScanner; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.sonar.api.batch.fs.InputFile; 26 | import org.sonar.api.batch.sensor.Sensor; 27 | import org.sonar.api.batch.sensor.SensorContext; 28 | import org.sonar.api.batch.sensor.SensorDescriptor; 29 | 30 | import java.io.File; 31 | 32 | /** 33 | * Created by tzwickl on 22/11/2016. 34 | */ 35 | 36 | public class TailorSensor implements Sensor { 37 | private static final Logger LOGGER = LoggerFactory.getLogger(TailorSensor.class); 38 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".tailor.report"; 39 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/*tailor.txt"; 40 | 41 | private final SensorContext context; 42 | 43 | public TailorSensor(SensorContext context) { 44 | this.context = context; 45 | } 46 | 47 | private String reportPath() { 48 | return context.config() 49 | .get(REPORT_PATH_KEY) 50 | .orElse(DEFAULT_REPORT_PATH); 51 | } 52 | 53 | @Override 54 | public void describe(SensorDescriptor descriptor) { 55 | descriptor 56 | .onlyOnLanguage(Swift.KEY) 57 | .name("Tailor") 58 | .onlyOnFileType(InputFile.Type.MAIN); 59 | } 60 | 61 | @Override 62 | public void execute(SensorContext context) { 63 | TailorReportParser parser = new TailorReportParser(context); 64 | DirectoryScanner scanner = new DirectoryScanner(); 65 | scanner.setIncludes(new String[]{reportPath()}); 66 | scanner.setBasedir(context.fileSystem().baseDir().getAbsolutePath()); 67 | scanner.setCaseSensitive(false); 68 | scanner.scan(); 69 | String[] files = scanner.getIncludedFiles(); 70 | 71 | for (String filename : files) { 72 | LOGGER.info("Processing Tailor report {}", filename); 73 | parser.parseReport(new File(filename)); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/SwiftAstScanner.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang; 19 | 20 | 21 | import com.backelite.sonarqube.swift.lang.api.SwiftGrammar; 22 | import com.backelite.sonarqube.swift.lang.api.SwiftMetric; 23 | import com.backelite.sonarqube.swift.lang.parser.SwiftParser; 24 | import com.sonar.sslr.impl.Parser; 25 | import org.sonar.squidbridge.AstScanner; 26 | import org.sonar.squidbridge.CommentAnalyser; 27 | import org.sonar.squidbridge.SquidAstVisitor; 28 | import org.sonar.squidbridge.SquidAstVisitorContextImpl; 29 | import org.sonar.squidbridge.api.SourceCode; 30 | import org.sonar.squidbridge.api.SourceFile; 31 | import org.sonar.squidbridge.api.SourceProject; 32 | import org.sonar.squidbridge.indexer.QueryByType; 33 | import org.sonar.squidbridge.metrics.CommentsVisitor; 34 | import org.sonar.squidbridge.metrics.LinesOfCodeVisitor; 35 | import org.sonar.squidbridge.metrics.LinesVisitor; 36 | 37 | import java.io.File; 38 | import java.util.Collection; 39 | 40 | public class SwiftAstScanner { 41 | 42 | private SwiftAstScanner() { 43 | 44 | } 45 | 46 | /** 47 | * Helper method for testing checks without having to deploy them on a Sonar instance. 48 | */ 49 | public static SourceFile scanSingleFile(File file, SquidAstVisitor... visitors) { 50 | if (!file.isFile()) { 51 | throw new IllegalArgumentException("File '" + file + "' not found."); 52 | } 53 | AstScanner scanner = create(new SwiftConfiguration(), visitors); 54 | scanner.scanFile(file); 55 | Collection sources = scanner.getIndex().search(new QueryByType(SourceFile.class)); 56 | 57 | if (sources.size() != 1) { 58 | throw new IllegalStateException("Only one SourceFile was expected whereas " + sources.size() + " has been returned."); 59 | } 60 | return (SourceFile) sources.iterator().next(); 61 | } 62 | 63 | public static AstScanner create(SwiftConfiguration conf, SquidAstVisitor... visitors) { 64 | final SquidAstVisitorContextImpl context = new SquidAstVisitorContextImpl(new SourceProject("Objective-C Project")); 65 | final Parser parser = SwiftParser.create(conf); 66 | 67 | AstScanner.Builder builder = AstScanner.builder(context).setBaseParser(parser); 68 | 69 | /* Metrics */ 70 | builder.withMetrics(SwiftMetric.values()); 71 | 72 | /* Comments */ 73 | builder.setCommentAnalyser( 74 | new CommentAnalyser() { 75 | @Override 76 | public boolean isBlank(String line) { 77 | for (int i = 0; i < line.length(); i++) { 78 | if (Character.isLetterOrDigit(line.charAt(i))) { 79 | return false; 80 | } 81 | } 82 | return true; 83 | } 84 | 85 | @Override 86 | public String getContents(String comment) { 87 | return comment.startsWith("//") ? comment.substring(2) : comment.substring(2, comment.length() - 2); 88 | } 89 | }); 90 | 91 | /* Files */ 92 | builder.setFilesMetric(SwiftMetric.FILES); 93 | if(visitors != null && visitors.length > 0) { 94 | for (SquidAstVisitor sv : visitors) { 95 | builder.withSquidAstVisitor(sv); 96 | } 97 | } else { 98 | /* Metrics */ 99 | builder.withSquidAstVisitor(new LinesVisitor(SwiftMetric.LINES)); 100 | builder.withSquidAstVisitor(new LinesOfCodeVisitor(SwiftMetric.LINES_OF_CODE)); 101 | builder.withSquidAstVisitor(CommentsVisitor.builder().withCommentMetric(SwiftMetric.COMMENT_LINES) 102 | .withNoSonar(true) 103 | .withIgnoreHeaderComment(conf.getIgnoreHeaderComments()) 104 | .build()); 105 | } 106 | return builder.build(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/SwiftConfiguration.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang; 19 | 20 | import org.sonar.squidbridge.api.SquidConfiguration; 21 | 22 | import java.nio.charset.Charset; 23 | 24 | public class SwiftConfiguration extends SquidConfiguration { 25 | 26 | private boolean ignoreHeaderComments; 27 | 28 | public SwiftConfiguration() { 29 | } 30 | 31 | public SwiftConfiguration(Charset charset) { 32 | super(charset); 33 | } 34 | 35 | public boolean getIgnoreHeaderComments() { 36 | return ignoreHeaderComments; 37 | } 38 | 39 | public void setIgnoreHeaderComments(boolean ignoreHeaderComments) { 40 | this.ignoreHeaderComments = ignoreHeaderComments; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/SwiftFileSystem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang; 19 | 20 | import com.backelite.sonarqube.swift.lang.core.Swift; 21 | import org.sonar.api.batch.ScannerSide; 22 | import org.sonar.api.batch.fs.FilePredicate; 23 | import org.sonar.api.batch.fs.FilePredicates; 24 | import org.sonar.api.batch.fs.FileSystem; 25 | import org.sonar.api.batch.fs.InputFile; 26 | 27 | import javax.annotation.CheckForNull; 28 | import java.io.File; 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | 32 | 33 | @ScannerSide 34 | public class SwiftFileSystem { 35 | 36 | private final FileSystem fileSystem; 37 | private final FilePredicates predicates; 38 | private final FilePredicate isSwiftLanguage; 39 | private final FilePredicate isMainTypeFile; 40 | 41 | public SwiftFileSystem(FileSystem fileSystem) { 42 | this.fileSystem = fileSystem; 43 | this.predicates = fileSystem.predicates(); 44 | this.isSwiftLanguage = predicates.hasLanguage(Swift.KEY); 45 | this.isMainTypeFile = predicates.hasType(InputFile.Type.MAIN); 46 | } 47 | 48 | public boolean hasSwiftFiles() { 49 | return fileSystem.hasFiles(isSwiftLanguage); 50 | } 51 | 52 | public List sourceFiles() { 53 | Iterable files = fileSystem.files(predicates.and(isSwiftLanguage, isMainTypeFile)); 54 | List list = new ArrayList<>(); 55 | files.iterator().forEachRemaining(list::add); 56 | return list; 57 | } 58 | 59 | public List swiftInputFiles() { 60 | Iterable inputFiles = fileSystem.inputFiles(isSwiftLanguage); 61 | List list = new ArrayList<>(); 62 | inputFiles.iterator().forEachRemaining(list::add); 63 | return list; 64 | } 65 | 66 | public List sourceInputFiles() { 67 | Iterable inputFiles = fileSystem.inputFiles(predicates.and(isSwiftLanguage, isMainTypeFile)); 68 | List list = new ArrayList<>(); 69 | inputFiles.iterator().forEachRemaining(list::add); 70 | return list; 71 | } 72 | 73 | @CheckForNull 74 | public InputFile sourceInputFileFromRelativePath(String relativePath) { 75 | return fileSystem.inputFile(predicates.and(predicates.matchesPathPattern("**/" + relativePath), isSwiftLanguage, isMainTypeFile)); 76 | } 77 | 78 | public File baseDir() { 79 | return fileSystem.baseDir(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/api/SwiftGrammar.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.api; 19 | 20 | import com.sonar.sslr.api.Grammar; 21 | import com.sonar.sslr.api.Rule; 22 | 23 | public class SwiftGrammar extends Grammar { 24 | 25 | public Rule identifierName; 26 | 27 | // A.1 Lexical 28 | 29 | public Rule literal; 30 | public Rule nullLiteral; 31 | public Rule booleanLiteral; 32 | public Rule stringLiteral; 33 | 34 | public Rule program; 35 | 36 | public Rule sourceElements; 37 | public Rule sourceElement; 38 | 39 | @Override 40 | public Rule getRootRule() { 41 | return program; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/api/SwiftKeyword.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.api; 19 | 20 | import com.sonar.sslr.api.AstNode; 21 | import com.sonar.sslr.api.TokenType; 22 | 23 | 24 | public enum SwiftKeyword implements TokenType { 25 | 26 | // Annotations 27 | UI_APPLICATION_MAIN_ANNOTATION("@UIApplicationMain"), 28 | IBACTION_ANNOTATION("@IBAction"), 29 | IBOUTLET_ANNOTATION("@IBOutlet"), 30 | 31 | // Declarations 32 | CLASS("class"), 33 | DEINIT("deinit"), 34 | ENUM("enum"), 35 | EXTENSION("extension"), 36 | FUNC("func"), 37 | IMPORT("import"), 38 | INIT("init"), 39 | LET("let"), 40 | PROTOCOL("protocol"), 41 | STATIC("static"), 42 | STRUCT("struct"), 43 | SUBSCRIPT("subscript"), 44 | TYPEALIAS("typealias"), 45 | VAR("var"), 46 | 47 | // Statments 48 | BREAK("break"), 49 | CASE("case"), 50 | CONTINUE("continue"), 51 | DEFAULT("default"), 52 | DO("do"), 53 | ELSE("else"), 54 | FALLTHROUGH("fallthrough"), 55 | IF("if"), 56 | IN("in"), 57 | FOR("for"), 58 | RETURN("return"), 59 | SWITCH("switch"), 60 | WHERE("where"), 61 | WHILE("while"), 62 | 63 | // Expressions and types 64 | AS("as"), 65 | DYNAMIC_TYPE("dynamicType"), 66 | IS("is"), 67 | NEW("new"), 68 | SUPER("super"), 69 | SELF("self"), 70 | SELF_UPPERCASE("Self"), 71 | TYPE("Type"), 72 | COLUMN("__COLUMN__"), 73 | FILE("__FILE__"), 74 | FUNCTION("__FUNCTION__"), 75 | AND("and"), 76 | LINE("__LINE__"), 77 | 78 | // Specials 79 | ASSOCIATIVITY("associativity"), 80 | DID_SET("didSet"), 81 | GET("get"), 82 | INFIX("infix"), 83 | INOUT("inout"), 84 | LEFT("left"), 85 | MUTATING("mutating"), 86 | NONE("none"), 87 | NONMUTATING("nonmutating"), 88 | OPERATOR("operator"), 89 | OVERRIDE("override"), 90 | POSTFIX("postfix"), 91 | PRECEDENCE("precedence"), 92 | PREFIX("prefix"), 93 | RIGHT("right"), 94 | SET("set"), 95 | UNOWNED("unowned"), 96 | UNOWNED_SAFE("unowned(safe)"), 97 | UNOWNED_UNSAFE("unowned(unsafe)"), 98 | WEAK("weak"), 99 | WILL_SET("willSet"), 100 | 101 | TRUE("true"), 102 | FALSE("true"); 103 | 104 | private final String value; 105 | 106 | SwiftKeyword(String value) { 107 | this.value = value; 108 | } 109 | 110 | public static String[] keywordValues() { 111 | SwiftKeyword[] keywordsEnum = SwiftKeyword.values(); 112 | String[] keywords = new String[keywordsEnum.length]; 113 | for (int i = 0; i < keywords.length; i++) { 114 | keywords[i] = keywordsEnum[i].getValue(); 115 | } 116 | return keywords; 117 | } 118 | 119 | public String getName() { 120 | return name(); 121 | } 122 | 123 | public String getValue() { 124 | return value; 125 | } 126 | 127 | public boolean hasToBeSkippedFromAst(AstNode node) { 128 | return false; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/api/SwiftMetric.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.api; 19 | 20 | 21 | import org.sonar.squidbridge.measures.CalculatedMetricFormula; 22 | import org.sonar.squidbridge.measures.MetricDef; 23 | 24 | public enum SwiftMetric implements MetricDef { 25 | 26 | FILES, 27 | LINES, 28 | LINES_OF_CODE, 29 | COMMENT_LINES, 30 | STATEMENTS, 31 | COMPLEXITY, 32 | FUNCTIONS; 33 | 34 | public String getName() { 35 | return name(); 36 | } 37 | 38 | public boolean isCalculatedMetric() { 39 | return false; 40 | } 41 | 42 | public boolean aggregateIfThereIsAlreadyAValue() { 43 | return true; 44 | } 45 | 46 | public boolean isThereAggregationFormula() { 47 | return true; 48 | } 49 | 50 | public CalculatedMetricFormula getCalculatedMetricFormula() { 51 | return null; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/checks/CheckList.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.checks; 19 | 20 | import java.util.Collections; 21 | import java.util.List; 22 | 23 | /** 24 | * Created by gillesgrousset on 27/10/2015. 25 | */ 26 | public final class CheckList { 27 | 28 | public static final String REPOSITORY_KEY = "swift"; 29 | 30 | public static final String SONAR_WAY_PROFILE = "Sonar way"; 31 | 32 | private CheckList() { 33 | } 34 | 35 | public static List getChecks() { 36 | return Collections.emptyList(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/core/Swift.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.core; 19 | 20 | import com.backelite.sonarqube.swift.SwiftConstants; 21 | import org.sonar.api.config.Configuration; 22 | import org.sonar.api.resources.AbstractLanguage; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | public class Swift extends AbstractLanguage { 28 | public static final String KEY = "swift"; 29 | private final Configuration config; 30 | 31 | public Swift(Configuration config) { 32 | super(KEY, "Swift"); 33 | this.config = config; 34 | } 35 | 36 | public String[] getFileSuffixes() { 37 | String[] suffixes = filterEmptyStrings(config.getStringArray(SwiftConstants.FILE_SUFFIXES)); 38 | if (suffixes.length == 0) { 39 | suffixes = SwiftConstants.FILE_SUFFIXES.split(","); 40 | } 41 | return suffixes; 42 | } 43 | 44 | private String[] filterEmptyStrings(String[] stringArray) { 45 | List nonEmptyStrings = new ArrayList<>(); 46 | for (String string : stringArray) { 47 | if (string.trim().length() > 0) { 48 | nonEmptyStrings.add(string.trim()); 49 | } 50 | } 51 | return nonEmptyStrings.toArray(new String[nonEmptyStrings.size()]); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/lexer/SwiftLexer.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.lexer; 19 | 20 | 21 | import com.backelite.sonarqube.swift.lang.SwiftConfiguration; 22 | import com.sonar.sslr.impl.Lexer; 23 | import com.sonar.sslr.impl.channel.BlackHoleChannel; 24 | 25 | import static com.sonar.sslr.api.GenericTokenType.LITERAL; 26 | import static com.sonar.sslr.impl.channel.RegexpChannelBuilder.commentRegexp; 27 | import static com.sonar.sslr.impl.channel.RegexpChannelBuilder.regexp; 28 | 29 | public class SwiftLexer { 30 | 31 | private SwiftLexer() { 32 | 33 | } 34 | 35 | public static Lexer create() { 36 | return create(new SwiftConfiguration()); 37 | } 38 | 39 | public static Lexer create(SwiftConfiguration conf) { 40 | return Lexer.builder() 41 | .withCharset(conf.getCharset()) 42 | 43 | .withFailIfNoChannelToConsumeOneCharacter(false) 44 | 45 | // Comments 46 | .withChannel(commentRegexp("//[^\\n\\r]*+")) 47 | .withChannel(commentRegexp("/\\*[\\s\\S]*?\\*/")) 48 | 49 | // All other tokens 50 | .withChannel(regexp(LITERAL, "[^\r\n\\s/]+")) 51 | 52 | .withChannel(new BlackHoleChannel("[\\s]")) 53 | 54 | .build(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/parser/SwiftGrammarImpl.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.parser; 19 | 20 | import com.backelite.sonarqube.swift.lang.api.SwiftGrammar; 21 | 22 | import static com.sonar.sslr.api.GenericTokenType.EOF; 23 | import static com.sonar.sslr.api.GenericTokenType.LITERAL; 24 | import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.o2n; 25 | 26 | public class SwiftGrammarImpl extends SwiftGrammar { 27 | 28 | public SwiftGrammarImpl() { 29 | program.is(o2n(LITERAL), EOF); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/lang/parser/SwiftParser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.parser; 19 | 20 | import com.backelite.sonarqube.swift.lang.SwiftConfiguration; 21 | import com.backelite.sonarqube.swift.lang.api.SwiftGrammar; 22 | import com.backelite.sonarqube.swift.lang.lexer.SwiftLexer; 23 | import com.sonar.sslr.impl.Parser; 24 | 25 | public class SwiftParser { 26 | 27 | private SwiftParser() { 28 | 29 | } 30 | 31 | public static Parser create() { 32 | return create(new SwiftConfiguration()); 33 | } 34 | 35 | public static Parser create(SwiftConfiguration conf) { 36 | return Parser.builder((SwiftGrammar) new SwiftGrammarImpl()) 37 | .withLexer(SwiftLexer.create(conf)) 38 | .build(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /swiftlang/src/main/java/com/backelite/sonarqube/swift/surefire/SwiftTestFileFinder.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.surefire; 19 | 20 | import org.apache.commons.lang.StringUtils; 21 | import com.backelite.sonarqube.commons.TestFileFinder; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.sonar.api.batch.fs.FilePredicate; 25 | import org.sonar.api.batch.fs.FileSystem; 26 | import org.sonar.api.batch.fs.InputFile; 27 | 28 | import java.util.List; 29 | 30 | /** 31 | * Created by gillesgrousset on 28/08/2018. 32 | */ 33 | public class SwiftTestFileFinder implements TestFileFinder { 34 | private static final Logger LOGGER = LoggerFactory.getLogger(SwiftTestFileFinder.class); 35 | 36 | @Override 37 | public InputFile getUnitTestResource(FileSystem fileSystem, String classname) { 38 | String fileName = classname.replace('.', '/') + ".swift"; 39 | FilePredicate fp = fileSystem.predicates().hasPath(fileName); 40 | 41 | if(fileSystem.hasFiles(fp)) { 42 | return fileSystem.inputFile(fp); 43 | } 44 | 45 | /* 46 | * Most xcodebuild JUnit parsers don't include the path to the class in the class field, so search for it if it 47 | * wasn't found in the root. 48 | */ 49 | String lastFileNameComponents = StringUtils.substringAfterLast(fileName, "/"); 50 | if(!StringUtils.isEmpty(lastFileNameComponents)) { 51 | fp = fileSystem.predicates().and( 52 | fileSystem.predicates().hasType(InputFile.Type.TEST), 53 | fileSystem.predicates().matchesPathPattern("**/" + lastFileNameComponents) 54 | ); 55 | 56 | if(fileSystem.hasFiles(fp)) { 57 | /* 58 | * Lazily get the first file, since we wouldn't be able to determine the correct one from just the 59 | * test class name in the event that there are multiple matches. 60 | */ 61 | return fileSystem.inputFiles(fp).iterator().next(); 62 | } 63 | } 64 | 65 | LOGGER.info("Unable to locate Swift test source file for classname {}. Make sure your test class name matches its filename.", classname); 66 | return null; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /swiftlang/src/main/resources/org/sonar/plugins/tailor/profile-tailor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tailor 4 | swift 5 | 6 | 7 | Tailor 8 | arrow-whitespace 9 | 10 | 11 | Tailor 12 | angle-bracket-whitespace 13 | 14 | 15 | Tailor 16 | brace-style 17 | 18 | 19 | Tailor 20 | colon-whitespace 21 | 22 | 23 | Tailor 24 | comma-whitespace 25 | 26 | 27 | Tailor 28 | comment-whitespace 29 | 30 | 31 | Tailor 32 | constant-k-prefix 33 | 34 | 35 | Tailor 36 | constant-naming 37 | 38 | 39 | Tailor 40 | forced-type-cast 41 | 42 | 43 | Tailor 44 | function-whitespace 45 | 46 | 47 | Tailor 48 | leading-whitespace 49 | 50 | 51 | Tailor 52 | lower-camel-case 53 | 54 | 55 | Tailor 56 | max-class-length 57 | 58 | 59 | Tailor 60 | max-closure-length 61 | 62 | 63 | Tailor 64 | max-file-length 65 | 66 | 67 | Tailor 68 | max-function-length 69 | 70 | 71 | Tailor 72 | max-line-length 73 | 74 | 75 | Tailor 76 | max-name-length 77 | 78 | 79 | Tailor 80 | max-struct-length 81 | 82 | 83 | Tailor 84 | min-name-length 85 | 86 | 87 | Tailor 88 | multiple-imports 89 | 90 | 91 | Tailor 92 | operator-whitespace 93 | 94 | 95 | Tailor 96 | parenthesis-whitespace 97 | 98 | 99 | Tailor 100 | redundant-parentheses 101 | 102 | 103 | Tailor 104 | terminating-newline 105 | 106 | 107 | Tailor 108 | terminating-semicolon 109 | 110 | 111 | Tailor 112 | todo-syntax 113 | 114 | 115 | Tailor 116 | trailing-closure 117 | 118 | 119 | Tailor 120 | trailing-whitespace 121 | 122 | 123 | Tailor 124 | upper-camel-case 125 | 126 | 127 | -------------------------------------------------------------------------------- /swiftlang/src/test/java/com/backelite/sonarqube/swift/lang/SwiftAstScannerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang; 19 | 20 | import com.backelite.sonarqube.swift.lang.api.SwiftMetric; 21 | import org.junit.Test; 22 | import org.sonar.squidbridge.api.SourceFile; 23 | 24 | import java.io.File; 25 | 26 | import static org.hamcrest.Matchers.is; 27 | import static org.junit.Assert.assertThat; 28 | 29 | public class SwiftAstScannerTest { 30 | 31 | @Test 32 | public void testTotalLineCount() { 33 | SourceFile file = SwiftAstScanner.scanSingleFile(new File("src/test/resources/Test.swift")); 34 | assertThat(file.getInt(SwiftMetric.LINES), is(21)); 35 | } 36 | 37 | @Test 38 | public void testLineOfCodeCount() { 39 | SourceFile file = SwiftAstScanner.scanSingleFile(new File("src/test/resources/Test.swift")); 40 | assertThat(file.getInt(SwiftMetric.LINES_OF_CODE), is(11)); 41 | } 42 | 43 | @Test 44 | public void testCommentLineCount() { 45 | SourceFile file = SwiftAstScanner.scanSingleFile(new File("src/test/resources/Test.swift")); 46 | assertThat(file.getInt(SwiftMetric.COMMENT_LINES), is(3)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /swiftlang/src/test/java/com/backelite/sonarqube/swift/lang/lexer/SwiftLexerTest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Swift module - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.backelite.sonarqube.swift.lang.lexer; 19 | 20 | import com.sonar.sslr.api.GenericTokenType; 21 | import com.sonar.sslr.api.Token; 22 | import com.sonar.sslr.impl.Lexer; 23 | import org.junit.BeforeClass; 24 | import org.junit.Test; 25 | 26 | import java.io.File; 27 | import java.util.List; 28 | 29 | import static com.sonar.sslr.test.lexer.LexerMatchers.hasComment; 30 | import static com.sonar.sslr.test.lexer.LexerMatchers.hasToken; 31 | import static org.hamcrest.Matchers.equalTo; 32 | import static org.junit.Assert.assertThat; 33 | 34 | public class SwiftLexerTest { 35 | 36 | private static Lexer lexer; 37 | 38 | @BeforeClass 39 | public static void init() { 40 | lexer = SwiftLexer.create(); 41 | } 42 | 43 | @Test 44 | public void testLexMultiLinesComment() { 45 | assertThat(lexer.lex("/* My Comment \n*/"), hasComment("/* My Comment \n*/")); 46 | assertThat(lexer.lex("/**/"), hasComment("/**/")); 47 | } 48 | 49 | @Test 50 | public void testLexInlineComment() { 51 | assertThat(lexer.lex("// My Comment \n new line"), hasComment("// My Comment ")); 52 | assertThat(lexer.lex("//"), hasComment("//")); 53 | } 54 | 55 | @Test 56 | public void testLexEndOflineComment() { 57 | assertThat(lexer.lex("self.hello() // My Comment end of line"), hasComment("// My Comment end of line")); 58 | assertThat(lexer.lex("self.hello() //"), hasComment("//")); 59 | } 60 | 61 | @Test 62 | public void testLexLineOfCode() { 63 | assertThat(lexer.lex("self.hello()"), hasToken("self.hello()", GenericTokenType.LITERAL)); 64 | } 65 | 66 | @Test 67 | public void testLexEmptyLine() { 68 | List tokens = lexer.lex("\n"); 69 | assertThat(tokens.size(), equalTo(1)); 70 | assertThat(tokens, hasToken(GenericTokenType.EOF)); 71 | } 72 | 73 | @Test 74 | public void testLexSampleFile() { 75 | List tokens = lexer.lex(new File("src/test/resources/Test.swift")); 76 | assertThat(tokens.size(), equalTo(34)); 77 | assertThat(tokens, hasToken(GenericTokenType.EOF)); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /swiftlang/src/test/resources/Test.swift: -------------------------------------------------------------------------------- 1 | // This is comment line #1 2 | // This is comment line #2 3 | 4 | import Foundation 5 | 6 | class Test { 7 | 8 | // This is comment line #3 9 | 10 | var name:String? 11 | 12 | func hello() -> String { 13 | if let name = name { 14 | return "Hello \(name) !" 15 | } else { 16 | return "Who are you ?" 17 | } 18 | 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /tools/updateFauxPasRules.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | // Update profile-fauxpas.xml from Faux Pas online rules documentation 19 | // Severity is determined from the category 20 | 21 | import groovy.json.JsonBuilder 22 | import groovy.xml.MarkupBuilder 23 | @Grab(group = 'org.codehaus.groovy.modules.http-builder', 24 | module = 'http-builder', version = '0.7') 25 | 26 | import groovyx.net.http.* 27 | @Grab(group = 'org.codehaus.groovy.modules.http-builder', 28 | module = 'http-builder', version = '0.7') 29 | 30 | import groovyx.net.http.* 31 | 32 | def parseRules(url, catMapping) { 33 | 34 | def result = [] 35 | 36 | def http = new HTTPBuilder(url) 37 | http.contentEncoding = ContentEncoding.Type.GZIP 38 | def html = http.get(contentType: 'text/html;charset=UTF-8') 39 | 40 | def categories = html."**".findAll { it.@class.toString().contains('tag-section') } 41 | categories.each { cat -> 42 | 43 | def rules = cat."**".findAll { it.@class.toString().contains('rule') } 44 | rules.each { r -> 45 | 46 | def k = r."**".find { it.@class.toString().contains("short-name") }.text() 47 | 48 | def rule = [ 49 | category : cat.H2.text(), 50 | key : k, 51 | name : (r.H3.text().trim().replaceAll('\\n', ' ') - k).trim(), 52 | description: r."**".find { 53 | it.@class.toString().contains("description") 54 | }.text().trim().replaceAll('\\n', ' '), 55 | severity : catMapping[cat.H2.text()] 56 | ] 57 | 58 | result.add(rule) 59 | } 60 | } 61 | 62 | 63 | 64 | return result 65 | } 66 | 67 | def writeProfileFauxPas(rls, file) { 68 | def writer = new StringWriter() 69 | def xml = new MarkupBuilder(writer) 70 | xml.profile() { 71 | name "FauxPas" 72 | language "objc" 73 | rules { 74 | rls.each { rl -> 75 | rule { 76 | repositoryKey "FauxPas" 77 | key rl.key 78 | } 79 | } 80 | } 81 | } 82 | 83 | file.text = "\n" + writer.toString() 84 | 85 | } 86 | 87 | def writeRules(rls, file) { 88 | 89 | def builder = new JsonBuilder() 90 | builder(rls) 91 | 92 | file.text = builder.toPrettyString() 93 | 94 | } 95 | 96 | // Files 97 | File rulesJson = new File('objclang/src/main/resources/org/sonar/plugins/fauxpas/rules.json') 98 | File profileXml = new File('objclang/src/main/resources/org/sonar/plugins/fauxpas/profile-fauxpas.xml') 99 | 100 | // Parse online documentation 101 | def rules = parseRules('http://fauxpasapp.com/rules/', [ 102 | BestPractice : 'MAJOR', 103 | Resources : 'MAJOR', 104 | Config : 'MINOR', 105 | Localization : 'MAJOR', 106 | APIUsage : 'CRITICAL', 107 | VCS : 'INFO', 108 | Style : 'MAJOR', 109 | Pedantic : 'MINOR', 110 | Miscellaneous: 'MINOR' 111 | ]) 112 | 113 | // Write profile 114 | writeProfileFauxPas(rules, profileXml) 115 | 116 | // Write rules 117 | writeRules(rules, rulesJson) -------------------------------------------------------------------------------- /tools/updateSwiftLintProfile.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | // Update profile-swiftlint.xml from local rules.txt 19 | // Severity is determined from ... 20 | 21 | import groovy.json.JsonBuilder 22 | import groovy.xml.MarkupBuilder 23 | 24 | def magicSerevityAttribution(rule) { 25 | 26 | if (rule.key.contains('variable_name')) return 'CRITICAL' 27 | if (rule.key.contains('nesting')) return 'CRITICAL' 28 | if (rule.key.contains('force')) return 'MAJOR' 29 | if (rule.key.contains('whitespace')) return 'MINOR' 30 | if (rule.key.contains('trailing')) return 'MINOR' 31 | if (rule.key.contains('length')) return 'MAJOR' 32 | if (rule.key.contains('cyclomatic')) return 'CRITICAL' 33 | 34 | return 'MINOR' 35 | 36 | } 37 | 38 | def readSwiftLintRules() { 39 | 40 | def result = [] 41 | 42 | def processRules = "swiftlint rules".execute() 43 | // Extract rule identifiers 44 | processRules.text.eachLine { line -> 45 | 46 | def rule = [:] 47 | 48 | 49 | if (!line.startsWith('+')) { 50 | 51 | def matcher = line =~ /\| (\w+)/ 52 | 53 | rule.key = matcher[0][1] 54 | 55 | if (rule.key != 'identifier') { 56 | result.add rule 57 | } 58 | } 59 | 60 | } 61 | 62 | // Get details of each rule 63 | result.each { rule -> 64 | def processRuleDetails = "swiftlint rules ${rule.key}".execute() 65 | def details = processRuleDetails.text.readLines().first() 66 | 67 | println "Processing rule ${rule.key}" 68 | 69 | def matcher = details =~ /(.*) \((\w+)\): (.*)/ 70 | rule.category = 'SwiftLint' 71 | rule.name = matcher[0][1] - ' Rule' 72 | rule.description = matcher[0][3] 73 | rule.severity = magicSerevityAttribution(rule) 74 | 75 | } 76 | 77 | result 78 | 79 | } 80 | 81 | def writeProfileSwiftLint(rls, file) { 82 | def writer = new StringWriter() 83 | def xml = new MarkupBuilder(writer) 84 | xml.profile() { 85 | name "SwiftLint" 86 | language "swift" 87 | rules { 88 | rls.each { rl -> 89 | rule { 90 | repositoryKey "SwiftLint" 91 | key rl.key 92 | } 93 | } 94 | } 95 | } 96 | 97 | file.text = "\n" + writer.toString() 98 | 99 | } 100 | 101 | def writeRules(rls, file) { 102 | 103 | def builder = new JsonBuilder() 104 | builder(rls) 105 | 106 | file.text = builder.toPrettyString() 107 | 108 | } 109 | 110 | // Files 111 | File rulesJson = new File('swiftlang/src/main/resources/org/sonar/plugins/swiftlint/rules.json') 112 | File profileXml = new File('swiftlang/src/main/resources/org/sonar/plugins/swiftlint/profile-swiftlint.xml') 113 | 114 | // Read rules from swiftlint_rules.txt 115 | def rules = readSwiftLintRules() 116 | 117 | // Write JSON rules 118 | writeRules(rules, rulesJson) 119 | 120 | // Write profile 121 | writeProfileSwiftLint(rules, profileXml) -------------------------------------------------------------------------------- /tools/updateTailorProfile.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube. 3 | * Copyright © 2015 Backelite (${email}) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with this program. If not, see . 17 | */ 18 | // Update profile-tailor.xml from local rules.txt 19 | // Severity is determined from ... 20 | 21 | import groovy.json.JsonBuilder 22 | import groovy.xml.MarkupBuilder 23 | 24 | def magicSerevityAttribution(rule) { 25 | 26 | if (rule.key.contains('lower-camel-case')) return 'CRITICAL' 27 | if (rule.key.contains('constant-naming')) return 'CRITICAL' 28 | if (rule.key.contains('upper-camel-case')) return 'CRITICAL' 29 | if (rule.key.contains('force')) return 'MAJOR' 30 | if (rule.key.contains('whitespace')) return 'MINOR' 31 | if (rule.key.contains('trailing')) return 'MINOR' 32 | if (rule.key.contains('length')) return 'MAJOR' 33 | if (rule.key.contains('cyclomatic')) return 'CRITICAL' 34 | 35 | return 'MINOR' 36 | 37 | } 38 | 39 | def readTailorRules() { 40 | 41 | def result = [] 42 | def descriptionKey = "Description: " 43 | def styleGuideKey = "Style Guide: " 44 | def linesToSkip = 2 45 | 46 | def processRules = "tailor --show-rules".execute() 47 | 48 | def rule = [:] 49 | 50 | // Extract rule identifiers 51 | processRules.text.eachLine { line -> 52 | 53 | // skip lines 54 | if (linesToSkip != 0) { 55 | linesToSkip-- 56 | return 57 | } 58 | 59 | if (line == "") { 60 | // skip blank lines 61 | result.add rule 62 | println "Added new rule ${rule.key}" 63 | rule = [:] 64 | return 65 | } 66 | 67 | if (line.startsWith(descriptionKey)) { 68 | // add description 69 | def desc = line.split(descriptionKey) 70 | rule.description = desc[1] 71 | } else if (line.startsWith(styleGuideKey)) { 72 | // add style guide 73 | def styleGuide = line.split(styleGuideKey) 74 | rule.styleguide = styleGuide[1] 75 | } else { 76 | // add key 77 | rule.key = line 78 | rule.category = "Tailor" 79 | 80 | // create a nice name for this rule 81 | def names = line.split("-") 82 | rule.name = names.collect { name -> 83 | 84 | def chars = name.toCharArray() 85 | chars[0] = Character.toUpperCase(chars[0]) 86 | chars.toString() 87 | 88 | }.join(" ") 89 | 90 | // set severity of this rule 91 | rule.severity = magicSerevityAttribution(rule) 92 | } 93 | } 94 | 95 | result 96 | 97 | } 98 | 99 | def writeProfileTailor(rls, file) { 100 | 101 | def writer = new StringWriter() 102 | def xml = new MarkupBuilder(writer) 103 | xml.profile() { 104 | name "Tailor" 105 | language "swift" 106 | rules { 107 | rls.each { rl -> 108 | rule { 109 | repositoryKey "Tailor" 110 | key rl.key 111 | } 112 | } 113 | } 114 | } 115 | 116 | file.text = "\n" + writer.toString() 117 | 118 | } 119 | 120 | def writeRules(rls, file) { 121 | 122 | def builder = new JsonBuilder() 123 | builder(rls) 124 | 125 | file.text = builder.toPrettyString() 126 | 127 | } 128 | 129 | // Files 130 | File rulesJson = new File('swiftlang/src/main/resources/org/sonar/plugins/tailor/rules.json') 131 | File profileXml = new File('swiftlang/src/main/resources/org/sonar/plugins/tailor/profile-tailor.xml') 132 | 133 | // Read rules from swiftlint_rules.txt 134 | def rules = readTailorRules() 135 | 136 | // Write JSON rules 137 | writeRules(rules, rulesJson) 138 | 139 | // Write profile 140 | writeProfileTailor(rules, profileXml) -------------------------------------------------------------------------------- /updateVersion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Swift SonarQube Plugin - Enables analysis of Swift and Objective-C projects into SonarQube. 4 | # Copyright © 2015 Backelite (${email}) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Lesser General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (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 14 | # GNU 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, see . 18 | # 19 | 20 | mvn versions:set -DgenerateBackupPoms=false 21 | --------------------------------------------------------------------------------