├── .github ├── ISSUE_TEMPLATE │ ├── BUG_REPORT.md │ ├── FEATURE_REQUEST.md │ ├── QUESTION.md │ └── REGRESSION.md └── workflows │ ├── codeql-analysis.yml │ └── maven.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── README_OLD.md ├── README_en.md ├── SwitchProfiles.png ├── build-and-deploy.sh ├── commons ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── backelite │ └── sonarqube │ └── commons │ ├── Constants.java │ ├── DirectoryScanner.java │ ├── MeasureUtil.java │ ├── TestFileFinder.java │ ├── TestFileFinders.java │ ├── TokenLocation.java │ └── surefire │ ├── StaxParser.java │ ├── SurefireStaxHandler.java │ ├── UnitTestClassReport.java │ ├── UnitTestIndex.java │ └── UnitTestResult.java ├── docs ├── infer-bug.png ├── quality-profiles-infer.png ├── quality-profiles.png ├── rule.md └── sonarqube-fastlane.md ├── javalang ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── github │ │ │ └── sonar │ │ │ └── next │ │ │ └── sonarqube │ │ │ └── java │ │ │ ├── issues │ │ │ └── infer │ │ │ │ ├── InferProfile.java │ │ │ │ ├── InferProfileImporter.java │ │ │ │ ├── InferReportParser.java │ │ │ │ ├── InferRulesDefinition.java │ │ │ │ └── JavaInferSensor.java │ │ │ ├── lang │ │ │ ├── core │ │ │ │ └── Java.java │ │ │ └── package-info.java │ │ │ └── package-info.java │ └── resources │ │ ├── com │ │ └── sonar │ │ │ └── sqale │ │ │ └── java-infer-model.xml │ │ └── org │ │ └── sonar │ │ └── plugins │ │ └── infer │ │ ├── java-profile-infer.xml │ │ └── java-rules.json │ └── test │ ├── java │ └── com │ │ └── github │ │ └── sonar │ │ └── next │ │ └── sonarqube │ │ └── java │ │ └── issues │ │ └── infer │ │ └── InferReportParserTest.java │ └── resources │ ├── Hello.java │ └── report_java.json ├── objclang ├── pom.xml └── src │ ├── main │ ├── antlr │ │ ├── ObjectiveCLexer.g4 │ │ ├── ObjectiveCLexer.tokens │ │ ├── ObjectiveCParser.g4 │ │ └── ObjectiveCPreprocessorParser.g4 │ ├── java │ │ └── com │ │ │ └── backelite │ │ │ └── sonarqube │ │ │ └── objectivec │ │ │ ├── ObjectiveCConstants.java │ │ │ ├── ObjectiveCSquidSensor.java │ │ │ ├── cpd │ │ │ └── ObjectiveCCpdAnalyzer.java │ │ │ ├── internal │ │ │ ├── ObjectiveCLexer.interp │ │ │ ├── ObjectiveCLexer.java │ │ │ ├── ObjectiveCLexer.tokens │ │ │ ├── ObjectiveCParser.interp │ │ │ ├── ObjectiveCParser.java │ │ │ ├── ObjectiveCParser.tokens │ │ │ ├── ObjectiveCParserBaseListener.java │ │ │ ├── ObjectiveCParserBaseVisitor.java │ │ │ ├── ObjectiveCParserListener.java │ │ │ ├── ObjectiveCParserVisitor.java │ │ │ ├── ObjectiveCPreprocessorParser.interp │ │ │ ├── ObjectiveCPreprocessorParser.java │ │ │ ├── ObjectiveCPreprocessorParser.tokens │ │ │ ├── ObjectiveCPreprocessorParserBaseListener.java │ │ │ ├── ObjectiveCPreprocessorParserBaseVisitor.java │ │ │ ├── ObjectiveCPreprocessorParserListener.java │ │ │ ├── ObjectiveCPreprocessorParserVisitor.java │ │ │ └── package-info.java │ │ │ ├── issues │ │ │ ├── ObjectiveCProfile.java │ │ │ ├── antlr │ │ │ │ ├── AntlrContext.java │ │ │ │ ├── AntlrSensor.java │ │ │ │ ├── AntlrUtils.java │ │ │ │ ├── ClassMethodVisitor.java │ │ │ │ ├── NextProfile.java │ │ │ │ ├── NextProfileImporter.java │ │ │ │ ├── NextRulesDefinition.java │ │ │ │ ├── ParseTreeItemVisitor.java │ │ │ │ ├── SourceLine.java │ │ │ │ ├── SourceLinesProvider.java │ │ │ │ └── rule │ │ │ │ │ └── CustomTreeVisitor.java │ │ │ ├── fauxpas │ │ │ │ ├── FauxPasProfile.java │ │ │ │ ├── FauxPasProfileImporter.java │ │ │ │ ├── FauxPasReportParser.java │ │ │ │ ├── FauxPasRulesDefinition.java │ │ │ │ └── FauxPasSensor.java │ │ │ ├── infer │ │ │ │ ├── InferProfile.java │ │ │ │ ├── InferProfileImporter.java │ │ │ │ ├── InferReportParser.java │ │ │ │ ├── InferRulesDefinition.java │ │ │ │ └── InferSensor.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 │ │ │ │ ├── infer-model.xml │ │ │ │ ├── next-model.xml │ │ │ │ └── oclint-model.xml │ │ └── org │ │ │ └── sonar │ │ │ └── plugins │ │ │ ├── fauxpas │ │ │ ├── profile-fauxpas.xml │ │ │ └── rules.json │ │ │ ├── infer │ │ │ ├── profile-infer.xml │ │ │ └── rules.json │ │ │ ├── next │ │ │ ├── profile-next.xml │ │ │ └── rule.json │ │ │ └── oclint │ │ │ ├── profile-oclint.xml │ │ │ └── rules.txt │ └── shell │ │ └── run-sonar.sh │ └── test │ ├── java │ └── com │ │ └── backelite │ │ └── sonarqube │ │ └── objectivec │ │ └── lang │ │ ├── ObjectiveCAstScannerTest.java │ │ ├── api │ │ └── ObjectiveCPunctuatorTest.java │ │ ├── infer │ │ └── InferTest.java │ │ └── lexer │ │ ├── AntlrVisitTest.java │ │ └── ObjectiveCLexerTest.java │ └── resources │ ├── NetworkRequest.m │ ├── 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 │ │ │ ├── cpd │ │ │ └── SwiftCpdAnalyzer.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/tal-tech/sonar-swift/blob/master/CONTRIBUTING.md) 13 | - [ ] I read the [documentation](https://github.com/tal-tech/sonar-swift/wiki) 14 | - [ ] I searched for existing [GitHub issues](https://github.com/tal-tech/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/tal-tech/sonar-swift/blob/master/CONTRIBUTING.md) 11 | - [ ] I read the [documentation](https://github.com/tal-tech/sonar-swift/wiki) 12 | - [ ] I searched for existing [GitHub issues](https://github.com/tal-tech/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/tal-tech/sonar-swift/blob/master/CONTRIBUTING.md) 13 | - [ ] I read the [documentation](https://github.com/tal-tech/sonar-swift/wiki) 14 | - [ ] I searched for existing [GitHub issues](https://github.com/tal-tech/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 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '38 7 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'java' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven 3 | 4 | name: Java CI with Maven 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 8 20 | uses: actions/setup-java@v2 21 | with: 22 | java-version: '8' 23 | distribution: 'adopt' 24 | - name: Build with Maven 25 | run: mvn -B package -DskipTests --file pom.xml 26 | -------------------------------------------------------------------------------- /.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/tal-tech/sonar-swift/tree/develop/docs). 12 | - Check out the README and especially the usage guide. 13 | - Search for [existing GitHub issues](https://github.com/tal-tech/sonar-swift/issues). 14 | 15 | If the above doesn't help, please [submit an issue](https://github.com/tal-tech/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/tal-tech/sonar-swift#prerequisites). 24 | 25 | ### Checking out the repository 26 | 27 | - Make sure you are on the *develop* branch: https://github.com/tal-tech/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/tal-tech/sonar-swift). Again, make sure you submit your PR to the *develop* branch: https://github.com/tal-tech/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/sonar-next/sonar-swift/093be7fac38fd0cb8b36e2193b29e2282aa9fb48/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/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 | public static final String PROPERTY_JAVA_PREFIX = "sonar.java"; 27 | } 28 | -------------------------------------------------------------------------------- /commons/src/main/java/com/backelite/sonarqube/commons/DirectoryScanner.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.commons; 2 | 3 | import org.apache.commons.io.FileUtils; 4 | import org.apache.commons.io.FilenameUtils; 5 | import org.apache.commons.io.filefilter.IOFileFilter; 6 | import org.apache.commons.io.filefilter.TrueFileFilter; 7 | import org.sonar.api.utils.WildcardPattern; 8 | 9 | import java.io.File; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class DirectoryScanner { 14 | 15 | private final File baseDir; 16 | private final WildcardPattern pattern; 17 | 18 | public DirectoryScanner(File baseDir, WildcardPattern pattern) { 19 | this.baseDir = baseDir; 20 | this.pattern = pattern; 21 | } 22 | 23 | public List getIncludedFiles() { 24 | final String baseDirAbsolutePath = baseDir.getAbsolutePath(); 25 | IOFileFilter fileFilter = new IOFileFilter() { 26 | 27 | @Override 28 | public boolean accept(File dir, String name) { 29 | return accept(new File(dir, name)); 30 | } 31 | 32 | @Override 33 | public boolean accept(File file) { 34 | String path = file.getAbsolutePath(); 35 | path = path.substring(Math.min(baseDirAbsolutePath.length(), path.length())); 36 | return pattern.match(FilenameUtils.separatorsToUnix(path)); 37 | } 38 | }; 39 | return new ArrayList<>(FileUtils.listFiles(baseDir, fileFilter, TrueFileFilter.INSTANCE)); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /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/TokenLocation.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.commons; 2 | 3 | import com.sonar.sslr.api.Token; 4 | 5 | /** 6 | * @author magaofei 7 | * @date 2021/4/5 8 | */ 9 | public class TokenLocation { 10 | 11 | private final int startLine; 12 | private final int startCharacter; 13 | private final int endLine; 14 | private final int endCharacter; 15 | 16 | public TokenLocation(Token token) { 17 | this.startLine = token.getLine(); 18 | this.startCharacter = token.getColumn(); 19 | final String[] lines = token.getOriginalValue().split("\r\n|\n|\r", -1); 20 | if (lines.length > 1) { 21 | this.endLine = token.getLine() + lines.length - 1; 22 | this.endCharacter = lines[lines.length - 1].length(); 23 | } else { 24 | this.endLine = startLine; 25 | this.endCharacter = startCharacter + token.getOriginalValue().length(); 26 | } 27 | } 28 | 29 | public int startLine() { 30 | return startLine; 31 | } 32 | 33 | public int startCharacter() { 34 | return startCharacter; 35 | } 36 | 37 | public int endLine() { 38 | return endLine; 39 | } 40 | 41 | public int endCharacter() { 42 | return endCharacter; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /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/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/infer-bug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonar-next/sonar-swift/093be7fac38fd0cb8b36e2193b29e2282aa9fb48/docs/infer-bug.png -------------------------------------------------------------------------------- /docs/quality-profiles-infer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonar-next/sonar-swift/093be7fac38fd0cb8b36e2193b29e2282aa9fb48/docs/quality-profiles-infer.png -------------------------------------------------------------------------------- /docs/quality-profiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonar-next/sonar-swift/093be7fac38fd0cb8b36e2193b29e2282aa9fb48/docs/quality-profiles.png -------------------------------------------------------------------------------- /docs/rule.md: -------------------------------------------------------------------------------- 1 | 2 | # Rule (规则) 3 | 我们在公司内部对 Infer 扫描出来了规则进行了 Review ,以下是我们正在使用的规则列表。 4 | 5 | | 规则名 | 问题类型 | 是否正在使用 | 优先级 | 6 | | ------------------------------ | -------- | ------------ | ------ | 7 | | MULTIPLE_WEAKSELF | Bug | 否 | 主要 | 8 | | UNSAFE_CALL_TO_OPTIONAL_METHOD | Bug | 是 | 主要 | 9 | | DEAD_STORE | Bug | 是 | 主要 | 10 | | MIXED_SELF_WEAKSELF | Bug | 是 | 主要 | 11 | | NULL_DEREFERENCE | Bug | 是 | 严重 | 12 | | CAPTURED_STRONG_SELF | Bug | 是 | 主要 | 13 | | WEAK_SELF_IN_NO_ESCAPE_BLOCK | Bug | 是 | 主要 | 14 | | STRONG_SELF_NOT_CHECKED | Bug | 否 | 主要 | 15 | | RETAIN_CYCLE | Bug | 是 | 严重 | 16 | | RESOURCE_LEAK | Bug | 是 | 严重 | 17 | | UNINITIALIZED_VALUE | Bug | 是 | 严重 | 18 | 19 | 20 | 21 | | 规则名 | 问题类型 | 是否正在使用 | 优先级 | 22 | | ---------------------------------- | -------- | ------------ | ------ | 23 | | ASSIGN_POINTER_WARNING | 坏味道 | 否 | 主要 | 24 | | BAD_POINTER_COMPARISON | 坏味道 | 否 | 主要 | 25 | | PARAMETER_NOT_NULL_CHECKED | 坏味道 | 是 | 主要 | 26 | | POINTER_TO_CONST_OBJC_CLASS | 坏味道 | 否 | 主要 | 27 | | IVAR_NOT_NULL_CHECKED | 坏味道 | 是 | 主要 | 28 | | POINTER_TO_INTEGRAL_IMPLICIT_CAST | 坏味道 | 是 | 主要 | 29 | | DIRECT_ATOMIC_PROPERTY_ACCESS | 坏味道 | 是 | 主要 | 30 | | STRONG_DELEGATE_WARNING | 坏味道 | 是 | 主要 | 31 | | PREMATURE_NIL_TERMINATION_ARGUMENT | 坏味道 | 是 | 主要 | 32 | 33 | 34 | 35 | 36 | 37 | # Rule 38 | 39 | We reviewed the rules scanned by Infer within the company. The following is a list of rules we are using 40 | 41 | 42 | 43 | | Rule Key | Issue Type | use | priority | 44 | | ------------------------------ | ---------- | ---- | -------- | 45 | | MULTIPLE_WEAKSELF | Bug | No | major | 46 | | UNSAFE_CALL_TO_OPTIONAL_METHOD | Bug | Yes | major | 47 | | DEAD_STORE | Bug | Yes | major | 48 | | MIXED_SELF_WEAKSELF | Bug | Yes | major | 49 | | NULL_DEREFERENCE | Bug | Yes | critical | 50 | | CAPTURED_STRONG_SELF | Bug | Yes | major | 51 | | WEAK_SELF_IN_NO_ESCAPE_BLOCK | Bug | Yes | major | 52 | | STRONG_SELF_NOT_CHECKED | Bug | No | major | 53 | | RETAIN_CYCLE | Bug | Yes | critical | 54 | | RESOURCE_LEAK | Bug | Yes | critical | 55 | | UNINITIALIZED_VALUE | Bug | Yes | critical | 56 | 57 | 58 | 59 | | Rule Key | Issue Type | use | priority | 60 | | ---------------------------------- | ---------- | ---- | -------- | 61 | | ASSIGN_POINTER_WARNING | CodeSmell | No | major | 62 | | BAD_POINTER_COMPARISON | CodeSmell | No | major | 63 | | PARAMETER_NOT_NULL_CHECKED | CodeSmell | Yes | major | 64 | | POINTER_TO_CONST_OBJC_CLASS | CodeSmell | No | major | 65 | | IVAR_NOT_NULL_CHECKED | CodeSmell | Yes | major | 66 | | POINTER_TO_INTEGRAL_IMPLICIT_CAST | CodeSmell | Yes | major | 67 | | DIRECT_ATOMIC_PROPERTY_ACCESS | CodeSmell | Yes | major | 68 | | STRONG_DELEGATE_WARNING | CodeSmell | Yes | major | 69 | | PREMATURE_NIL_TERMINATION_ARGUMENT | CodeSmell | Yes | major | 70 | 71 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /javalang/src/main/java/com/github/sonar/next/sonarqube/java/issues/infer/InferProfile.java: -------------------------------------------------------------------------------- 1 | package com.github.sonar.next.sonarqube.java.issues.infer; 2 | 3 | import com.github.sonar.next.sonarqube.java.lang.core.Java; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.sonar.api.profiles.RulesProfile; 7 | import org.sonar.api.rules.ActiveRule; 8 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 9 | import org.sonar.api.utils.ValidationMessages; 10 | 11 | import java.io.IOException; 12 | import java.io.InputStreamReader; 13 | import java.io.Reader; 14 | 15 | /** 16 | * @author magaofei 17 | * @date 2021/04/11 18 | * infer 19 | */ 20 | public class InferProfile implements BuiltInQualityProfilesDefinition { 21 | 22 | private static final Logger logger = LoggerFactory.getLogger(InferProfile.class); 23 | 24 | public static final String PROFILE_PATH = "/org/sonar/plugins/infer/java-profile-infer.xml"; 25 | 26 | private final InferProfileImporter profileImporter; 27 | 28 | public InferProfile(final InferProfileImporter profileImporter) { 29 | this.profileImporter = profileImporter; 30 | } 31 | 32 | @Override 33 | public void define(Context context) { 34 | logger.info("Creating Infer Java Profile"); 35 | NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile(InferRulesDefinition.REPOSITORY_KEY, Java.KEY); 36 | 37 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(InferProfile.PROFILE_PATH))) { 38 | RulesProfile ocLintRulesProfile = profileImporter.importProfile(config, ValidationMessages.create()); 39 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 40 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 41 | } 42 | } catch (IOException ex){ 43 | logger.error("Error Creating Infer Profile",ex); 44 | } 45 | nbiqp.done(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /javalang/src/main/java/com/github/sonar/next/sonarqube/java/issues/infer/InferProfileImporter.java: -------------------------------------------------------------------------------- 1 | package com.github.sonar.next.sonarqube.java.issues.infer; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.sonar.api.profiles.ProfileImporter; 6 | import org.sonar.api.profiles.RulesProfile; 7 | import org.sonar.api.profiles.XMLProfileParser; 8 | import org.sonar.api.utils.ValidationMessages; 9 | 10 | import java.io.Reader; 11 | 12 | /** 13 | * @author magaofei 14 | * @date 2021/04/11 15 | */ 16 | public class InferProfileImporter extends ProfileImporter { 17 | 18 | private static final Logger logger = LoggerFactory.getLogger(InferProfileImporter.class); 19 | 20 | private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default infer profile"; 21 | 22 | private final XMLProfileParser profileParser; 23 | 24 | public InferProfileImporter(final XMLProfileParser xmlProfileParser) { 25 | super(InferRulesDefinition.REPOSITORY_KEY, InferRulesDefinition.REPOSITORY_KEY); 26 | setSupportedLanguages("java"); 27 | profileParser = xmlProfileParser; 28 | } 29 | 30 | @Override 31 | public RulesProfile importProfile(Reader reader, ValidationMessages messages) { 32 | final RulesProfile profile = profileParser.parse(reader, messages); 33 | 34 | if (null == profile) { 35 | messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); 36 | logger.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); 37 | } 38 | return profile; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /javalang/src/main/java/com/github/sonar/next/sonarqube/java/issues/infer/InferRulesDefinition.java: -------------------------------------------------------------------------------- 1 | package com.github.sonar.next.sonarqube.java.issues.infer; 2 | 3 | import com.github.sonar.next.sonarqube.java.lang.core.Java; 4 | import org.json.simple.JSONArray; 5 | import org.json.simple.JSONObject; 6 | import org.json.simple.JSONValue; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.sonar.api.SonarRuntime; 10 | import org.sonar.api.rules.RuleType; 11 | import org.sonar.api.server.rule.RulesDefinition; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStreamReader; 15 | import java.io.Reader; 16 | import java.nio.charset.StandardCharsets; 17 | import java.util.Optional; 18 | 19 | /** 20 | * @author magaofei 21 | * @date 2021/04/11 22 | */ 23 | public class InferRulesDefinition implements RulesDefinition { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(InferRulesDefinition.class); 26 | public static final String REPOSITORY_KEY = "infer-java"; 27 | public static final String REPOSITORY_NAME = "Infer Java"; 28 | private static final String RULES_FILE = "/org/sonar/plugins/infer/java-rules.json"; 29 | 30 | private final SonarRuntime sonarRuntime; 31 | public InferRulesDefinition(SonarRuntime sonarRuntime) { 32 | this.sonarRuntime = sonarRuntime; 33 | } 34 | 35 | @Override 36 | public void define(Context context) { 37 | NewRepository repository = context.createRepository(REPOSITORY_KEY, Java.KEY).setName(REPOSITORY_NAME); 38 | try (Reader reader = new InputStreamReader(getClass().getResourceAsStream(RULES_FILE), StandardCharsets.UTF_8)) { 39 | JSONArray slRules = (JSONArray) JSONValue.parse(reader); 40 | if (slRules != null) { 41 | for (Object obj : slRules) { 42 | JSONObject slRule = (JSONObject) obj; 43 | RuleType ruleType = Optional.of(RuleType.valueOf((String) slRule.get("type"))).orElse(RuleType.CODE_SMELL); 44 | repository.createRule((String) slRule.get("key")) 45 | .setName((String) slRule.get("name")) 46 | .setType(ruleType) 47 | .setSeverity((String) slRule.get("severity")) 48 | .setHtmlDescription((String) slRule.get("description")); 49 | } 50 | } 51 | } catch (IOException e) { 52 | logger.error("Failed to load infer rules", e); 53 | } 54 | 55 | repository.done(); 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /javalang/src/main/java/com/github/sonar/next/sonarqube/java/issues/infer/JavaInferSensor.java: -------------------------------------------------------------------------------- 1 | package com.github.sonar.next.sonarqube.java.issues.infer; 2 | 3 | import com.backelite.sonarqube.commons.Constants; 4 | import com.github.sonar.next.sonarqube.java.lang.core.Java; 5 | import org.apache.tools.ant.DirectoryScanner; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.sonar.api.batch.fs.InputFile; 9 | import org.sonar.api.batch.sensor.Sensor; 10 | import org.sonar.api.batch.sensor.SensorContext; 11 | import org.sonar.api.batch.sensor.SensorDescriptor; 12 | 13 | import java.io.File; 14 | 15 | /** 16 | * @author magaofei 17 | * @date 2021/04/11 18 | */ 19 | public class JavaInferSensor implements Sensor { 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(JavaInferSensor.class); 22 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_JAVA_PREFIX + ".infer.report"; 23 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/*infer_report.json"; 24 | 25 | private final SensorContext context; 26 | 27 | public JavaInferSensor(SensorContext context) { 28 | this.context = context; 29 | } 30 | 31 | @Override 32 | public void describe(SensorDescriptor descriptor) { 33 | descriptor 34 | .onlyOnLanguage(Java.KEY) 35 | .name("Infer Java") 36 | .onlyOnFileType(InputFile.Type.MAIN); 37 | } 38 | 39 | @Override 40 | public void execute(SensorContext context) { 41 | final String projectBaseDir = context.fileSystem().baseDir().getAbsolutePath(); 42 | 43 | InferReportParser parser = new InferReportParser(context); 44 | parseReportIn(projectBaseDir, parser); 45 | } 46 | 47 | 48 | private void parseReportIn(final String baseDir, final InferReportParser parser) { 49 | DirectoryScanner scanner = new DirectoryScanner(); 50 | scanner.setIncludes(new String[]{reportPath()}); 51 | scanner.setBasedir(baseDir); 52 | scanner.setCaseSensitive(false); 53 | scanner.scan(); 54 | String[] files = scanner.getIncludedFiles(); 55 | 56 | for (String filename : files) { 57 | logger.info("Processing Infer report {}", filename); 58 | parser.parseReport(new File(filename)); 59 | } 60 | } 61 | 62 | private String reportPath() { 63 | return context.config() 64 | .get(REPORT_PATH_KEY) 65 | .orElse(DEFAULT_REPORT_PATH); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /javalang/src/main/java/com/github/sonar/next/sonarqube/java/lang/core/Java.java: -------------------------------------------------------------------------------- 1 | package com.github.sonar.next.sonarqube.java.lang.core; 2 | 3 | public class Java { 4 | public static final String KEY = "java"; 5 | } 6 | -------------------------------------------------------------------------------- /javalang/src/main/java/com/github/sonar/next/sonarqube/java/lang/package-info.java: -------------------------------------------------------------------------------- 1 | package com.github.sonar.next.sonarqube.java.lang; -------------------------------------------------------------------------------- /javalang/src/main/java/com/github/sonar/next/sonarqube/java/package-info.java: -------------------------------------------------------------------------------- 1 | package com.github.sonar.next.sonarqube.java; -------------------------------------------------------------------------------- /javalang/src/test/java/com/github/sonar/next/sonarqube/java/issues/infer/InferReportParserTest.java: -------------------------------------------------------------------------------- 1 | package com.github.sonar.next.sonarqube.java.issues.infer; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.json.simple.parser.ParseException; 6 | import org.junit.Rule; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.rules.TemporaryFolder; 9 | import org.mockito.InjectMocks; 10 | import org.mockito.Mock; 11 | import org.mockito.MockitoAnnotations; 12 | import org.sonar.api.batch.fs.FilePredicate; 13 | import org.sonar.api.batch.fs.FilePredicates; 14 | import org.sonar.api.batch.fs.FileSystem; 15 | import org.sonar.api.batch.fs.InputFile; 16 | import org.sonar.api.batch.fs.internal.DefaultFilePredicates; 17 | import org.sonar.api.batch.fs.internal.DefaultFileSystem; 18 | import org.sonar.api.batch.fs.internal.TestInputFileBuilder; 19 | import org.sonar.api.batch.sensor.SensorContext; 20 | import org.sonar.api.batch.sensor.issue.NewIssueLocation; 21 | import org.sonar.api.batch.sensor.issue.internal.DefaultIssue; 22 | import org.sonar.api.rule.RuleKey; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | import java.nio.file.Files; 27 | import java.nio.file.Path; 28 | import java.util.ArrayList; 29 | import java.util.Objects; 30 | 31 | import static org.mockito.Mockito.*; 32 | 33 | class InferReportParserTest { 34 | 35 | @Rule 36 | public TemporaryFolder temp = new TemporaryFolder(); 37 | 38 | private DefaultFileSystem fs; 39 | private Path moduleBasePath; 40 | 41 | @Mock 42 | SensorContext sensorContext; 43 | 44 | @Mock 45 | FileSystem fileSystem; 46 | private InferReportParser self; 47 | 48 | 49 | @org.junit.jupiter.api.BeforeEach 50 | void setUp() throws IOException { 51 | moduleBasePath = temp.newFolder().toPath(); 52 | fs = new DefaultFileSystem(moduleBasePath); 53 | 54 | MockitoAnnotations.openMocks(this); 55 | self = new InferReportParser(sensorContext); 56 | } 57 | 58 | @org.junit.jupiter.api.AfterEach 59 | void tearDown() { 60 | } 61 | 62 | 63 | @Test 64 | void parseReport() throws IOException, ParseException { 65 | ClassLoader classLoader = getClass().getClassLoader(); 66 | File reportFile = new File(Objects.requireNonNull(classLoader.getResource("report_java.json")).getFile()); 67 | File file = new File(Objects.requireNonNull(classLoader.getResource("Hello.java")).getFile()); 68 | 69 | FilePredicates predicates = new DefaultFilePredicates(temp.newFolder().toPath()); 70 | InputFile javaFile = new TestInputFileBuilder("foo", "Hello.java") 71 | .setModuleBaseDir(moduleBasePath) 72 | .setLanguage("java") 73 | .setContents(new String(Files.readAllBytes(file.toPath()))) 74 | .setStatus(InputFile.Status.SAME) 75 | .build(); 76 | 77 | fs.add(javaFile); 78 | 79 | 80 | when(sensorContext.fileSystem()).thenReturn(fs); 81 | when(fileSystem.predicates()).thenReturn(predicates); 82 | 83 | DefaultIssue defaultIssue = mock(DefaultIssue.class); 84 | when(defaultIssue.addFlow(anyIterable())).thenReturn(defaultIssue); 85 | when(defaultIssue.forRule(any(RuleKey.class))).thenReturn(defaultIssue); 86 | when(defaultIssue.at(any(NewIssueLocation.class))).thenReturn(defaultIssue); 87 | when(sensorContext.newIssue()).thenReturn(defaultIssue); 88 | doNothing().when(defaultIssue).save(); 89 | 90 | self.parseReport(reportFile); 91 | 92 | verify(defaultIssue, times(1)).addFlow(anyIterable()); 93 | verify(defaultIssue, times(1)).forRule(any(RuleKey.class)); 94 | verify(defaultIssue, times(1)).at(any(NewIssueLocation.class)); 95 | verify(defaultIssue, times(1)).save(); 96 | 97 | 98 | } 99 | } -------------------------------------------------------------------------------- /javalang/src/test/resources/Hello.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | class Hello { 9 | int test() { 10 | String s = null; 11 | return s.length(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /javalang/src/test/resources/report_java.json: -------------------------------------------------------------------------------- 1 | [{"bug_type":"NULL_DEREFERENCE","qualifier":"object `s` last assigned on line 10 could be null and is dereferenced at line 11.","severity":"ERROR","line":11,"column":-1,"procedure":"Hello.test():int","procedure_start_line":9,"file":"Hello.java","bug_trace":[{"level":0,"filename":"Hello.java","line_number":9,"column_number":-1,"description":"start of procedure test()"},{"level":0,"filename":"Hello.java","line_number":10,"column_number":-1,"description":""},{"level":0,"filename":"Hello.java","line_number":11,"column_number":-1,"description":""}],"key":"Hello.java|test|NULL_DEREFERENCE","node_key":"c8c6b1f0f8892a67c957e59c27c08c9f","hash":"f21e4baf23b546897421c6f1f10c2e78","bug_type_hum":"Null Dereference"}] 2 | -------------------------------------------------------------------------------- /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/cpd/ObjectiveCCpdAnalyzer.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.cpd; 2 | 3 | import com.backelite.sonarqube.commons.TokenLocation; 4 | import com.backelite.sonarqube.objectivec.lang.api.ObjectiveCKeyword; 5 | import com.backelite.sonarqube.objectivec.lang.lexer.ObjectiveCLexer; 6 | import com.google.common.collect.Sets; 7 | import com.sonar.sslr.api.*; 8 | import com.sonar.sslr.impl.Lexer; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.sonar.api.batch.fs.InputFile; 12 | import org.sonar.api.batch.sensor.SensorContext; 13 | import org.sonar.api.batch.sensor.cpd.NewCpdTokens; 14 | 15 | import java.io.File; 16 | import java.util.Arrays; 17 | import java.util.Iterator; 18 | import java.util.Set; 19 | 20 | /** 21 | * @author magaofei 22 | * @date 2021/4/5 23 | */ 24 | public class ObjectiveCCpdAnalyzer { 25 | 26 | private static final Logger logger = LoggerFactory.getLogger(ObjectiveCCpdAnalyzer.class); 27 | 28 | private final SensorContext context; 29 | private final Lexer lexer; 30 | 31 | public ObjectiveCCpdAnalyzer(SensorContext context, Lexer lexer) { 32 | this.context = context; 33 | this.lexer = lexer; 34 | } 35 | 36 | public void pushCpdTokens(InputFile inputFile) { 37 | // NewHighlighting highlighting = context.newHighlighting(); 38 | 39 | File file = inputFile.file(); 40 | // highlighting.onFile(inputFile); 41 | 42 | // not support .h file 43 | if (inputFile.filename().endsWith(".h") || inputFile.filename().endsWith(".mm")) { 44 | return; 45 | } 46 | 47 | NewCpdTokens cpdTokens = context.newCpdTokens(); 48 | cpdTokens.onFile(inputFile); 49 | 50 | Iterator iterator = lexer.lex(file).iterator(); 51 | 52 | while (iterator.hasNext()) { 53 | Token token = iterator.next(); 54 | TokenType tokenType = token.getType(); 55 | 56 | if (!tokenType.equals(GenericTokenType.EOF)) { 57 | TokenLocation tokenLocation = new TokenLocation(token); 58 | cpdTokens.addToken(tokenLocation.startLine(), tokenLocation.startCharacter(), tokenLocation.endLine(), tokenLocation.endCharacter(), token.getValue()); 59 | } 60 | // if (tokenType.equals(GenericTokenType.LITERAL)) { 61 | // highlight(highlighting, token, TypeOfText.STRING); 62 | // } else if (KEYWORDS.contains(tokenType)) { 63 | // highlight(highlighting, token, TypeOfText.KEYWORD); 64 | // } 65 | // for (Trivia trivia : token.getTrivia()) { 66 | // highlight(highlighting, trivia.getToken(), TypeOfText.COMMENT); 67 | // } 68 | } 69 | 70 | // highlighting.save(); 71 | cpdTokens.save(); 72 | } 73 | 74 | // private static void highlight(NewHighlighting highlighting, Token token, TypeOfText typeOfText) { 75 | // TokenLocation tokenLocation = new TokenLocation(token); 76 | // highlighting.highlight(tokenLocation.startLine(), tokenLocation.startCharacter(), tokenLocation.endLine(), tokenLocation.endCharacter(), typeOfText); 77 | // } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/internal/package-info.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.internal; -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/AntlrContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube Flutter Plugin 3 | * Copyright (C) 2020 inside|app 4 | * contact@insideapp.fr 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package com.backelite.sonarqube.objectivec.issues.antlr; 21 | 22 | import com.backelite.sonarqube.objectivec.internal.ObjectiveCLexer; 23 | import com.backelite.sonarqube.objectivec.internal.ObjectiveCParser; 24 | import org.antlr.v4.runtime.CharStream; 25 | import org.antlr.v4.runtime.CharStreams; 26 | import org.antlr.v4.runtime.CommonTokenStream; 27 | import org.antlr.v4.runtime.Token; 28 | import org.antlr.v4.runtime.tree.ParseTree; 29 | import org.sonar.api.batch.fs.InputFile; 30 | 31 | import java.io.IOException; 32 | import java.io.InputStream; 33 | import java.nio.charset.Charset; 34 | 35 | public class AntlrContext { 36 | 37 | private final InputFile file; 38 | private final CommonTokenStream stream; 39 | private final ParseTree root; 40 | private SourceLine[] lines; 41 | 42 | public AntlrContext(InputFile file, CommonTokenStream stream, ParseTree root) { 43 | this.file = file; 44 | this.stream = stream; 45 | this.root = root; 46 | } 47 | 48 | public static AntlrContext fromInputFile(InputFile file, Charset charset) throws IOException { 49 | return fromStreams(file, file.inputStream(), file.inputStream(), charset); 50 | } 51 | 52 | public static AntlrContext fromStreams(InputFile inputFile, InputStream file, InputStream linesStream, 53 | Charset charset) throws IOException { 54 | // final SourceLinesProvider linesProvider = new SourceLinesProvider(); 55 | final CharStream charStream = CharStreams.fromStream(file, charset); 56 | final ObjectiveCLexer lexer = new ObjectiveCLexer(charStream); 57 | lexer.removeErrorListeners(); 58 | final CommonTokenStream stream = new CommonTokenStream(lexer); 59 | stream.fill(); 60 | final ObjectiveCParser parser = new ObjectiveCParser(stream); 61 | parser.removeErrorListeners(); 62 | final ParseTree root = parser.translationUnit(); 63 | // final SourceLine[] lines = linesProvider.getLines(linesStream, charset); 64 | return new AntlrContext(inputFile, stream, root); 65 | } 66 | 67 | public SourceLine[] getLines() { 68 | return lines; 69 | } 70 | 71 | public Token[] getTokens() { 72 | return this.stream.getTokens().toArray(new Token[0]); 73 | } 74 | 75 | public int[] getLineAndColumn(final int global) { 76 | 77 | for (final SourceLine line : this.lines) { 78 | if (line.getEnd() > global) { 79 | return new int[] { line.getLine(), global - line.getStart() }; 80 | } 81 | } 82 | return null; 83 | } 84 | 85 | public InputFile getFile() { 86 | return file; 87 | } 88 | 89 | public CommonTokenStream getStream() { 90 | return stream; 91 | } 92 | 93 | public ParseTree getRoot() { 94 | return root; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/AntlrSensor.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.antlr; 2 | 3 | import com.backelite.sonarqube.objectivec.issues.antlr.rule.CustomTreeVisitor; 4 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.sonar.api.batch.fs.FilePredicate; 8 | import org.sonar.api.batch.fs.InputFile; 9 | import org.sonar.api.batch.sensor.Sensor; 10 | import org.sonar.api.batch.sensor.SensorContext; 11 | import org.sonar.api.batch.sensor.SensorDescriptor; 12 | 13 | import java.io.IOException; 14 | import java.nio.charset.Charset; 15 | import java.util.concurrent.ExecutorService; 16 | import java.util.concurrent.Executors; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | public class AntlrSensor implements Sensor { 20 | 21 | private static final Logger LOGGER = LoggerFactory.getLogger(AntlrSensor.class); 22 | private static final int EXECUTOR_TIMEOUT = 10000; 23 | 24 | @Override 25 | public void describe(SensorDescriptor sensorDescriptor) { 26 | sensorDescriptor 27 | .onlyOnLanguage(ObjectiveC.KEY) 28 | .name("Objective-C sensor") 29 | .onlyOnFileType(InputFile.Type.MAIN); 30 | } 31 | 32 | @Override 33 | public void execute(SensorContext sensorContext) { 34 | 35 | FilePredicate hasDart = sensorContext.fileSystem().predicates().hasLanguage(ObjectiveC.KEY); 36 | FilePredicate isMain = sensorContext.fileSystem().predicates().hasType(InputFile.Type.MAIN); 37 | FilePredicate isTest = sensorContext.fileSystem().predicates().hasType(InputFile.Type.TEST); 38 | FilePredicate dartAndMain = sensorContext.fileSystem().predicates().and(hasDart, isMain); 39 | FilePredicate dartAndTest = sensorContext.fileSystem().predicates().and(hasDart, isTest); 40 | final Charset charset = sensorContext.fileSystem().encoding(); 41 | 42 | final ExecutorService executorService = Executors.newWorkStealingPool(); 43 | 44 | for(InputFile inf : sensorContext.fileSystem().inputFiles(dartAndMain)){ 45 | 46 | executorService.execute(() -> { 47 | // Visit source files 48 | try { 49 | final AntlrContext antlrContext = AntlrContext.fromInputFile(inf, charset); 50 | CustomTreeVisitor visitor = new CustomTreeVisitor(sensorContext); 51 | visitor.visit(antlrContext.getRoot()); 52 | // visitor.fillContext(sensorContext, antlrContext); 53 | } catch (IOException e) { 54 | LOGGER.warn("Unexpected error while analyzing file " + inf.filename(), e); 55 | } 56 | }); 57 | 58 | } 59 | 60 | for(InputFile inf : sensorContext.fileSystem().inputFiles(dartAndTest)){ 61 | 62 | executorService.execute(() -> { 63 | // Visit test files (for syntax highlighting only) 64 | try { 65 | final AntlrContext antlrContext = AntlrContext.fromInputFile(inf, charset); 66 | CustomTreeVisitor visitor = new CustomTreeVisitor(sensorContext); 67 | visitor.visit(antlrContext.getRoot()); 68 | // visitor.fillContext(sensorContext, antlrContext); 69 | } catch (IOException e) { 70 | LOGGER.warn("Unexpected error while analyzing file " + inf.filename(), e); 71 | } 72 | }); 73 | 74 | } 75 | 76 | try { 77 | executorService.shutdown(); 78 | executorService.awaitTermination(EXECUTOR_TIMEOUT, TimeUnit.SECONDS); 79 | executorService.shutdownNow(); 80 | } catch (final InterruptedException e) { 81 | LOGGER.warn("Unexpected error while running waiting for executor service to finish", e); 82 | } 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/AntlrUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube Flutter Plugin 3 | * Copyright (C) 2020 inside|app 4 | * contact@insideapp.fr 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package com.backelite.sonarqube.objectivec.issues.antlr; 21 | 22 | import org.apache.commons.io.IOUtils; 23 | 24 | import java.io.IOException; 25 | import java.nio.charset.Charset; 26 | 27 | public class AntlrUtils { 28 | 29 | public static AntlrContext getRequest(String text) throws IOException { 30 | return AntlrContext.fromStreams(null, IOUtils.toInputStream(text, Charset.defaultCharset()), 31 | IOUtils.toInputStream(text, Charset.defaultCharset()), Charset.defaultCharset()); 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/ClassMethodVisitor.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.antlr; 2 | 3 | import com.backelite.sonarqube.objectivec.internal.ObjectiveCParser; 4 | import org.antlr.v4.runtime.tree.ParseTree; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.sonar.api.batch.sensor.SensorContext; 8 | 9 | public class ClassMethodVisitor implements ParseTreeItemVisitor { 10 | 11 | private static final Logger logger = LoggerFactory.getLogger(ClassMethodVisitor.class); 12 | 13 | @Override 14 | public void apply(ParseTree tree) { 15 | logger.info("apply {}", tree.getText()); 16 | } 17 | 18 | @Override 19 | public void fillContext(SensorContext context, AntlrContext antlrContext) { 20 | logger.info("fill {}", antlrContext.getRoot()); 21 | } 22 | 23 | 24 | // @Override 25 | // public Object visitTranslationUnit(ObjectiveCParser.TranslationUnitContext ctx) { 26 | // logger.info("visitTranslationUnit {}", ctx.getText()); 27 | // return super.visitTranslationUnit(ctx); 28 | // } 29 | // 30 | // @Override 31 | // public Object visitMethodDeclaration(ObjectiveCParser.MethodDeclarationContext ctx) { 32 | // logger.info("visitMethodDeclaration {}", ctx.getText()); 33 | // return super.visitMethodDeclaration(ctx); 34 | // } 35 | // 36 | // @Override 37 | // public Object visitClassMethodDefinition(ObjectiveCParser.ClassMethodDefinitionContext ctx) { 38 | // logger.info("visitClassMethodDefinition {}", ctx.getText()); 39 | // return super.visitClassMethodDefinition(ctx); 40 | // } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/NextProfile.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.antlr; 2 | 3 | import com.backelite.sonarqube.objectivec.issues.infer.InferProfile; 4 | import com.backelite.sonarqube.objectivec.issues.infer.InferProfileImporter; 5 | import com.backelite.sonarqube.objectivec.issues.infer.InferRulesDefinition; 6 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.sonar.api.profiles.RulesProfile; 10 | import org.sonar.api.rules.ActiveRule; 11 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 12 | import org.sonar.api.utils.ValidationMessages; 13 | 14 | import java.io.IOException; 15 | import java.io.InputStreamReader; 16 | import java.io.Reader; 17 | 18 | public class NextProfile implements BuiltInQualityProfilesDefinition { 19 | 20 | private static final Logger logger = LoggerFactory.getLogger(InferProfile.class); 21 | 22 | public static final String PROFILE_PATH = "/org/sonar/plugins/next/profile-next.xml"; 23 | 24 | private final NextProfileImporter profileImporter; 25 | 26 | public NextProfile(final NextProfileImporter profileImporter) { 27 | this.profileImporter = profileImporter; 28 | } 29 | 30 | @Override 31 | public void define(Context context) { 32 | logger.info("Creating Next Profile"); 33 | NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile(InferRulesDefinition.REPOSITORY_KEY, ObjectiveC.KEY); 34 | 35 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(InferProfile.PROFILE_PATH))) { 36 | RulesProfile ocLintRulesProfile = profileImporter.importProfile(config, ValidationMessages.create()); 37 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 38 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 39 | } 40 | } catch (IOException ex){ 41 | logger.error("Error Creating Infer Profile",ex); 42 | } 43 | nbiqp.done(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/NextProfileImporter.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.antlr; 2 | 3 | import com.backelite.sonarqube.objectivec.issues.infer.InferRulesDefinition; 4 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.sonar.api.profiles.ProfileImporter; 8 | import org.sonar.api.profiles.RulesProfile; 9 | import org.sonar.api.profiles.XMLProfileParser; 10 | import org.sonar.api.utils.ValidationMessages; 11 | 12 | import java.io.Reader; 13 | 14 | /** 15 | * @author 16 | * @date 2020/10/27 17 | */ 18 | public class NextProfileImporter extends ProfileImporter { 19 | 20 | private static final Logger logger = LoggerFactory.getLogger(NextProfileImporter.class); 21 | 22 | private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default next profile"; 23 | 24 | private final XMLProfileParser profileParser; 25 | 26 | public NextProfileImporter(final XMLProfileParser xmlProfileParser) { 27 | super(InferRulesDefinition.REPOSITORY_KEY, InferRulesDefinition.REPOSITORY_KEY); 28 | setSupportedLanguages(ObjectiveC.KEY); 29 | profileParser = xmlProfileParser; 30 | } 31 | 32 | @Override 33 | public RulesProfile importProfile(Reader reader, ValidationMessages messages) { 34 | final RulesProfile profile = profileParser.parse(reader, messages); 35 | 36 | if (null == profile) { 37 | messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); 38 | logger.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); 39 | } 40 | return profile; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/NextRulesDefinition.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.antlr; 2 | 3 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 4 | import org.json.simple.JSONArray; 5 | import org.json.simple.JSONObject; 6 | import org.json.simple.JSONValue; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.sonar.api.SonarRuntime; 10 | import org.sonar.api.rules.RuleType; 11 | import org.sonar.api.server.rule.RulesDefinition; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStreamReader; 15 | import java.io.Reader; 16 | import java.nio.charset.StandardCharsets; 17 | import java.util.Optional; 18 | 19 | /** 20 | * @autho magaofei 21 | * @date 2020/10/27 22 | */ 23 | public class NextRulesDefinition implements RulesDefinition { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(NextRulesDefinition.class); 26 | public static final String REPOSITORY_KEY = "Next"; 27 | public static final String REPOSITORY_NAME = REPOSITORY_KEY; 28 | private static final String RULES_FILE = "/org/sonar/plugins/next/rules.json"; 29 | 30 | private final SonarRuntime sonarRuntime; 31 | public NextRulesDefinition(SonarRuntime sonarRuntime) { 32 | this.sonarRuntime = sonarRuntime; 33 | } 34 | 35 | @Override 36 | public void define(Context context) { 37 | NewRepository repository = context.createRepository(REPOSITORY_KEY, ObjectiveC.KEY).setName(REPOSITORY_NAME); 38 | try (Reader reader = new InputStreamReader(getClass().getResourceAsStream(RULES_FILE), StandardCharsets.UTF_8)) { 39 | JSONArray slRules = (JSONArray) JSONValue.parse(reader); 40 | if (slRules != null) { 41 | for (Object obj : slRules) { 42 | JSONObject slRule = (JSONObject) obj; 43 | RuleType ruleType = Optional.of(RuleType.valueOf((String) slRule.get("type"))).orElse(RuleType.CODE_SMELL); 44 | repository.createRule((String) slRule.get("key")) 45 | .setName((String) slRule.get("name")) 46 | .setType(ruleType) 47 | .setSeverity((String) slRule.get("severity")) 48 | .setHtmlDescription((String) slRule.get("description")); 49 | } 50 | } 51 | } catch (IOException e) { 52 | logger.error("Failed to load next rules", e); 53 | } 54 | 55 | repository.done(); 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/ParseTreeItemVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube Flutter Plugin 3 | * Copyright (C) 2020 inside|app 4 | * contact@insideapp.fr 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package com.backelite.sonarqube.objectivec.issues.antlr; 21 | 22 | import org.antlr.v4.runtime.tree.ParseTree; 23 | import org.sonar.api.batch.sensor.SensorContext; 24 | 25 | public interface ParseTreeItemVisitor { 26 | void apply(ParseTree tree); 27 | 28 | void fillContext(SensorContext context, AntlrContext antlrContext); 29 | } -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/SourceLine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube Flutter Plugin 3 | * Copyright (C) 2020 inside|app 4 | * contact@insideapp.fr 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package com.backelite.sonarqube.objectivec.issues.antlr; 21 | 22 | public final class SourceLine { 23 | 24 | private final int count; 25 | private final int start; 26 | private final int end; 27 | private final int line; 28 | 29 | public SourceLine(final int line, final int count, final int start, final int end) { 30 | this.line = line; 31 | this.count = count; 32 | this.start = start; 33 | this.end = end; 34 | 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "SourceLine [line=" + line + ", count=" + count + ", start=" + start + ", end=" + end + "]"; 40 | } 41 | 42 | public int getLine() { 43 | return line; 44 | } 45 | 46 | public int getCount() { 47 | return count; 48 | } 49 | 50 | public int getEnd() { 51 | return end; 52 | } 53 | 54 | public int getStart() { 55 | return start; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/SourceLinesProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * SonarQube Flutter Plugin 3 | * Copyright (C) 2020 inside|app 4 | * contact@insideapp.fr 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 3 of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, write to the Free Software Foundation, 18 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | package com.backelite.sonarqube.objectivec.issues.antlr; 21 | 22 | import org.apache.commons.io.input.BOMInputStream; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | import java.io.BufferedReader; 27 | import java.io.InputStream; 28 | import java.io.InputStreamReader; 29 | import java.nio.charset.Charset; 30 | import java.util.ArrayList; 31 | import java.util.List; 32 | 33 | public class SourceLinesProvider { 34 | private static final Logger LOGGER = LoggerFactory.getLogger(SourceLinesProvider.class); 35 | 36 | public SourceLine[] getLines(final InputStream inputStream, final Charset charset) { 37 | if (inputStream == null) { 38 | return new SourceLine[0]; 39 | } 40 | final List sourceLines = new ArrayList<>(); 41 | 42 | try (final BufferedReader bufferedReader = new BufferedReader( 43 | new InputStreamReader(new BOMInputStream(inputStream, false), charset))) { 44 | int totalLines = 1; 45 | int global = 0; 46 | int count = 0; 47 | 48 | int currentChar; 49 | while ((currentChar = bufferedReader.read()) != -1) { 50 | 51 | global++; 52 | count++; 53 | if (currentChar == 10) { 54 | sourceLines.add(new SourceLine(totalLines, count, global - count, global)); 55 | totalLines++; 56 | count = 0; 57 | } 58 | 59 | } 60 | sourceLines.add(new SourceLine(totalLines, count, global - count, global)); 61 | } catch (final Throwable e) { 62 | LOGGER.warn("Error occurred reading file", e); 63 | } 64 | 65 | return sourceLines.toArray(new SourceLine[0]); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/antlr/rule/CustomTreeVisitor.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.antlr.rule; 2 | 3 | import com.backelite.sonarqube.objectivec.internal.*; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.sonar.api.batch.sensor.SensorContext; 7 | import org.sonar.check.Rule; 8 | 9 | @Rule(key = "RSPEC-138") 10 | public class CustomTreeVisitor extends ObjectiveCParserBaseVisitor { 11 | 12 | private static final Logger logger = LoggerFactory.getLogger(CustomTreeVisitor.class); 13 | 14 | private static final int MAX_LENGTH = 12; 15 | 16 | private final SensorContext sensorContext; 17 | 18 | public CustomTreeVisitor(SensorContext sensorContext) { 19 | this.sensorContext = sensorContext; 20 | } 21 | 22 | @Override 23 | public Object visitClassMethodDefinition(ObjectiveCParser.ClassMethodDefinitionContext ctx) { 24 | logger.debug("visitClassMethodDefinition {}", ctx.getText()); 25 | logger.debug(" length = {}", ctx.getText().split(";").length); 26 | // String methodName = ctx.methodDefinition().methodSelector().getText(); 27 | return super.visitClassMethodDefinition(ctx); 28 | } 29 | 30 | static class StatementVisitor extends ObjectiveCParserBaseVisitor { 31 | 32 | private int length = 0; 33 | 34 | @Override 35 | public Object visitStatement(ObjectiveCParser.StatementContext ctx) { 36 | length += 1; 37 | return super.visitStatement(ctx); 38 | } 39 | } 40 | 41 | @Override 42 | public Object visitInstanceMethodDefinition(ObjectiveCParser.InstanceMethodDefinitionContext ctx) { 43 | StatementVisitor statementVisitor = new StatementVisitor(); 44 | ctx.methodDefinition().accept(statementVisitor); 45 | int length = statementVisitor.length; 46 | if (length > MAX_LENGTH) { 47 | logger.info("report issue {}, methodName = {}", length, ctx.methodDefinition().methodSelector().getText()); 48 | } 49 | // logger.info(" length = {}", ctx.getText().split(";").length); 50 | return super.visitInstanceMethodDefinition(ctx); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /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/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 | 28 | import java.io.IOException; 29 | import java.io.InputStreamReader; 30 | import java.io.Reader; 31 | import java.nio.charset.Charset; 32 | 33 | /** 34 | * Created by gillesgrousset on 18/02/2016. 35 | */ 36 | public class FauxPasRulesDefinition implements RulesDefinition { 37 | 38 | public static final String REPOSITORY_KEY = "FauxPas"; 39 | public static final String REPOSITORY_NAME = REPOSITORY_KEY; 40 | private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasRulesDefinition.class); 41 | private static final String RULES_FILE = "/org/sonar/plugins/fauxpas/rules.json"; 42 | 43 | 44 | @Override 45 | public void define(final Context context) { 46 | NewRepository repository = context.createRepository(REPOSITORY_KEY, ObjectiveC.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((String) slRule.get("description")); 57 | } 58 | } 59 | } catch (IOException e) { 60 | LOGGER.error("Failed to load FauxPas rules", e); 61 | } 62 | repository.done(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /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.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 class FauxPasSensor implements Sensor { 33 | private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasSensor.class); 34 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".fauxpas.report"; 35 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/*fauxpas.json"; 36 | 37 | private final SensorContext context; 38 | 39 | public FauxPasSensor(SensorContext context) { 40 | this.context = context; 41 | } 42 | 43 | private void parseReportIn(final String baseDir, final FauxPasReportParser parser) { 44 | DirectoryScanner scanner = new DirectoryScanner(); 45 | scanner.setIncludes(new String[]{reportPath()}); 46 | scanner.setBasedir(baseDir); 47 | scanner.setCaseSensitive(false); 48 | scanner.scan(); 49 | String[] files = scanner.getIncludedFiles(); 50 | 51 | for (String filename : files) { 52 | LOGGER.info("Processing FauxPas report {}", filename); 53 | parser.parseReport(new File(filename)); 54 | } 55 | } 56 | 57 | private String reportPath() { 58 | return context.config() 59 | .get(REPORT_PATH_KEY) 60 | .orElse(DEFAULT_REPORT_PATH); 61 | } 62 | 63 | @Override 64 | public void describe(SensorDescriptor descriptor) { 65 | descriptor 66 | .onlyOnLanguage(ObjectiveC.KEY) 67 | .name("FauxPas") 68 | .onlyOnFileType(InputFile.Type.MAIN); 69 | } 70 | 71 | @Override 72 | public void execute(SensorContext context) { 73 | final String projectBaseDir = context.fileSystem().baseDir().getAbsolutePath(); 74 | 75 | FauxPasReportParser parser = new FauxPasReportParser(context); 76 | parseReportIn(projectBaseDir, parser); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/infer/InferProfile.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.infer; 2 | 3 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.sonar.api.profiles.RulesProfile; 7 | import org.sonar.api.rules.ActiveRule; 8 | import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; 9 | import org.sonar.api.utils.ValidationMessages; 10 | 11 | import java.io.IOException; 12 | import java.io.InputStreamReader; 13 | import java.io.Reader; 14 | 15 | /** 16 | * @author wuwenguang magaofei 17 | * @date 2020/10/27 18 | * infer 19 | */ 20 | public class InferProfile implements BuiltInQualityProfilesDefinition { 21 | 22 | private static final Logger logger = LoggerFactory.getLogger(InferProfile.class); 23 | 24 | public static final String PROFILE_PATH = "/org/sonar/plugins/infer/profile-infer.xml"; 25 | 26 | private final InferProfileImporter profileImporter; 27 | 28 | public InferProfile(final InferProfileImporter profileImporter) { 29 | this.profileImporter = profileImporter; 30 | } 31 | 32 | @Override 33 | public void define(Context context) { 34 | logger.info("Creating Infer Profile"); 35 | NewBuiltInQualityProfile nbiqp = context.createBuiltInQualityProfile(InferRulesDefinition.REPOSITORY_KEY, ObjectiveC.KEY); 36 | 37 | try(Reader config = new InputStreamReader(getClass().getResourceAsStream(InferProfile.PROFILE_PATH))) { 38 | RulesProfile ocLintRulesProfile = profileImporter.importProfile(config, ValidationMessages.create()); 39 | for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { 40 | nbiqp.activateRule(rule.getRepositoryKey(), rule.getRuleKey()); 41 | } 42 | } catch (IOException ex){ 43 | logger.error("Error Creating Infer Profile",ex); 44 | } 45 | nbiqp.done(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/infer/InferProfileImporter.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.infer; 2 | 3 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.sonar.api.profiles.ProfileImporter; 7 | import org.sonar.api.profiles.RulesProfile; 8 | import org.sonar.api.profiles.XMLProfileParser; 9 | import org.sonar.api.utils.ValidationMessages; 10 | 11 | import java.io.Reader; 12 | 13 | /** 14 | * @author wuwenguang 15 | * @date 2020/10/27 16 | */ 17 | public class InferProfileImporter extends ProfileImporter { 18 | 19 | private static final Logger logger = LoggerFactory.getLogger(InferProfileImporter.class); 20 | 21 | private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default infer profile"; 22 | 23 | private final XMLProfileParser profileParser; 24 | 25 | public InferProfileImporter(final XMLProfileParser xmlProfileParser) { 26 | super(InferRulesDefinition.REPOSITORY_KEY, InferRulesDefinition.REPOSITORY_KEY); 27 | setSupportedLanguages(ObjectiveC.KEY); 28 | profileParser = xmlProfileParser; 29 | } 30 | 31 | @Override 32 | public RulesProfile importProfile(Reader reader, ValidationMessages messages) { 33 | final RulesProfile profile = profileParser.parse(reader, messages); 34 | 35 | if (null == profile) { 36 | messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); 37 | logger.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); 38 | } 39 | return profile; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/infer/InferRulesDefinition.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.infer; 2 | 3 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 4 | import org.json.simple.JSONArray; 5 | import org.json.simple.JSONObject; 6 | import org.json.simple.JSONValue; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.sonar.api.SonarRuntime; 10 | import org.sonar.api.rules.RuleType; 11 | import org.sonar.api.server.rule.RulesDefinition; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStreamReader; 15 | import java.io.Reader; 16 | import java.nio.charset.Charset; 17 | import java.nio.charset.StandardCharsets; 18 | import java.util.Optional; 19 | 20 | /** 21 | * @author wuwenguang magaofei 22 | * @date 2020/10/27 23 | */ 24 | public class InferRulesDefinition implements RulesDefinition { 25 | 26 | private static final Logger logger = LoggerFactory.getLogger(InferRulesDefinition.class); 27 | public static final String REPOSITORY_KEY = "Infer"; 28 | public static final String REPOSITORY_NAME = REPOSITORY_KEY; 29 | private static final String RULES_FILE = "/org/sonar/plugins/infer/rules.json"; 30 | 31 | private final SonarRuntime sonarRuntime; 32 | public InferRulesDefinition(SonarRuntime sonarRuntime) { 33 | this.sonarRuntime = sonarRuntime; 34 | } 35 | 36 | @Override 37 | public void define(Context context) { 38 | NewRepository repository = context.createRepository(REPOSITORY_KEY, ObjectiveC.KEY).setName(REPOSITORY_NAME); 39 | try (Reader reader = new InputStreamReader(getClass().getResourceAsStream(RULES_FILE), StandardCharsets.UTF_8)) { 40 | JSONArray slRules = (JSONArray) JSONValue.parse(reader); 41 | if (slRules != null) { 42 | for (Object obj : slRules) { 43 | JSONObject slRule = (JSONObject) obj; 44 | RuleType ruleType = Optional.of(RuleType.valueOf((String) slRule.get("type"))).orElse(RuleType.CODE_SMELL); 45 | NewRule newRule = repository.createRule((String) slRule.get("key")) 46 | .setName((String) slRule.get("name")) 47 | .setType(ruleType) 48 | .setSeverity((String) slRule.get("severity")) 49 | .setHtmlDescription((String) slRule.get("description")); 50 | newRule.setDebtRemediationFunction( 51 | newRule.debtRemediationFunctions().constantPerIssue("10min")); 52 | } 53 | } 54 | } catch (IOException e) { 55 | logger.error("Failed to load infer rules", e); 56 | } 57 | 58 | repository.done(); 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /objclang/src/main/java/com/backelite/sonarqube/objectivec/issues/infer/InferSensor.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.issues.infer; 2 | 3 | import com.backelite.sonarqube.commons.Constants; 4 | import com.backelite.sonarqube.objectivec.issues.fauxpas.FauxPasReportParser; 5 | import com.backelite.sonarqube.objectivec.lang.core.ObjectiveC; 6 | import org.apache.tools.ant.DirectoryScanner; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.sonar.api.batch.fs.InputFile; 10 | import org.sonar.api.batch.sensor.Sensor; 11 | import org.sonar.api.batch.sensor.SensorContext; 12 | import org.sonar.api.batch.sensor.SensorDescriptor; 13 | 14 | import java.io.File; 15 | 16 | /** 17 | * @author wuwenguang magaofei 18 | * @date 2020/10/27 19 | */ 20 | public class InferSensor implements Sensor { 21 | 22 | private static final Logger logger = LoggerFactory.getLogger(InferSensor.class); 23 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".infer.report"; 24 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/*infer_report.json"; 25 | 26 | private final SensorContext context; 27 | 28 | public InferSensor(SensorContext context) { 29 | this.context = context; 30 | } 31 | 32 | @Override 33 | public void describe(SensorDescriptor descriptor) { 34 | descriptor 35 | .onlyOnLanguage(ObjectiveC.KEY) 36 | .name("Infer") 37 | .onlyOnFileType(InputFile.Type.MAIN); 38 | } 39 | 40 | @Override 41 | public void execute(SensorContext context) { 42 | final String projectBaseDir = context.fileSystem().baseDir().getAbsolutePath(); 43 | 44 | InferReportParser parser = new InferReportParser(context); 45 | parseReportIn(projectBaseDir, parser); 46 | } 47 | 48 | 49 | private void parseReportIn(final String baseDir, final InferReportParser parser) { 50 | DirectoryScanner scanner = new DirectoryScanner(); 51 | scanner.setIncludes(new String[]{reportPath()}); 52 | scanner.setBasedir(baseDir); 53 | scanner.setCaseSensitive(false); 54 | scanner.scan(); 55 | String[] files = scanner.getIncludedFiles(); 56 | 57 | for (String filename : files) { 58 | logger.info("Processing Infer report {}", filename); 59 | parser.parseReport(new File(filename)); 60 | } 61 | } 62 | 63 | private String reportPath() { 64 | return context.config() 65 | .get(REPORT_PATH_KEY) 66 | .orElse(DEFAULT_REPORT_PATH); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /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/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 | @Override 49 | public CalculatedMetricFormula getCalculatedMetricFormula() { 50 | return null; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /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/main/resources/com/sonar/sqale/next-model.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MAINTAINABILITY 4 | Maintainability 5 | 6 | READABILITY 7 | Readability 8 | 9 | Next 10 | RSPEC-138 11 | 12 | remediationFunction 13 | CONSTANT_ISSUE 14 | 15 | 16 | offset 17 | 30 18 | min 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /objclang/src/main/resources/org/sonar/plugins/next/profile-next.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Next 4 | objc 5 | 6 | 7 | Next 8 | RSPEC-138 9 | 10 | 11 | -------------------------------------------------------------------------------- /objclang/src/main/resources/org/sonar/plugins/next/rule.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "category": "Next", 4 | "key": "RSPEC-138", 5 | "name": "Methods should not have too many lines", 6 | "description": "A method that grows too large tends to aggregate too many responsibilities. Such method inevitably become harder to understand and therefore harder to maintain.\n\nAbove a specific threshold, it is strongly advised to refactor into smaller methods which focus on well-defined tasks. Those smaller methods will not only be easier to understand, but also probably easier to test.", 7 | "severity": "MAJOR", 8 | "type": "CODE_SMELL" 9 | } 10 | ] -------------------------------------------------------------------------------- /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/infer/InferTest.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.lang.infer; 2 | 3 | import com.backelite.sonarqube.objectivec.issues.infer.InferRulesDefinition; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | import org.sonar.api.SonarQubeSide; 7 | import org.sonar.api.SonarRuntime; 8 | import org.sonar.api.internal.SonarRuntimeImpl; 9 | import org.sonar.api.server.rule.RulesDefinition; 10 | import org.sonar.api.utils.Version; 11 | 12 | /** 13 | * @author wuwenguang 14 | * @date 2020/10/28 15 | */ 16 | public class InferTest { 17 | 18 | @Test 19 | public void define() { 20 | SonarRuntime sonarRuntime = SonarRuntimeImpl.forSonarQube(Version.create(7, 3), SonarQubeSide.SERVER); 21 | InferRulesDefinition rulesDefinition = new InferRulesDefinition(sonarRuntime); 22 | RulesDefinition.Context context = new RulesDefinition.Context(); 23 | rulesDefinition.define(context); 24 | 25 | RulesDefinition.Repository inferRepository = context.repository("Infer"); 26 | Assert.assertNotNull(inferRepository); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /objclang/src/test/java/com/backelite/sonarqube/objectivec/lang/lexer/AntlrVisitTest.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.objectivec.lang.lexer; 2 | 3 | import com.backelite.sonarqube.objectivec.internal.ObjectiveCLexer; 4 | import com.backelite.sonarqube.objectivec.internal.ObjectiveCParser; 5 | import com.backelite.sonarqube.objectivec.issues.antlr.AntlrContext; 6 | import com.backelite.sonarqube.objectivec.issues.antlr.AntlrUtils; 7 | import com.backelite.sonarqube.objectivec.issues.antlr.rule.CustomTreeVisitor; 8 | import org.antlr.v4.runtime.CharStream; 9 | import org.antlr.v4.runtime.CharStreams; 10 | import org.antlr.v4.runtime.CommonTokenStream; 11 | import org.antlr.v4.runtime.tree.ParseTree; 12 | import org.apache.commons.io.IOUtils; 13 | import org.junit.Test; 14 | 15 | import java.io.IOException; 16 | import java.nio.charset.StandardCharsets; 17 | import java.util.Objects; 18 | 19 | import static org.assertj.core.api.Assertions.assertThat; 20 | 21 | public class AntlrVisitTest { 22 | 23 | @Test 24 | public void visit() throws IOException { 25 | 26 | final CharStream charStream = CharStreams.fromStream(Objects.requireNonNull(this.getClass().getResourceAsStream("/NetworkRequest.m"))); 27 | final ObjectiveCLexer lexer = new ObjectiveCLexer(charStream); 28 | lexer.removeErrorListeners(); 29 | final CommonTokenStream stream = new CommonTokenStream(lexer); 30 | stream.fill(); 31 | final ObjectiveCParser parser = new ObjectiveCParser(stream); 32 | parser.removeErrorListeners(); 33 | final ParseTree root = parser.translationUnit(); 34 | CustomTreeVisitor customTreeVisitor = new CustomTreeVisitor(null); 35 | customTreeVisitor.visit(root); 36 | AntlrContext antlrContext = AntlrUtils.getRequest(IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/NetworkRequest.m")), StandardCharsets.UTF_8)); 37 | // customTreeVisitor.fillContext(null, antlrContext); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /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/sonar-next/sonar-swift/093be7fac38fd0cb8b36e2193b29e2282aa9fb48/screenshot.png -------------------------------------------------------------------------------- /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 | 32 | public class LizardSensor implements Sensor { 33 | private static final Logger LOGGER = LoggerFactory.getLogger(LizardSensor.class); 34 | public static final String REPORT_PATH_KEY = Constants.PROPERTY_PREFIX + ".lizard.report"; 35 | public static final String DEFAULT_REPORT_PATH = "sonar-reports/lizard-report.xml"; 36 | 37 | private final SensorContext context; 38 | 39 | public LizardSensor(final SensorContext context) { 40 | this.context = context; 41 | } 42 | 43 | private String reportPath() { 44 | return context.config() 45 | .get(REPORT_PATH_KEY) 46 | .orElse(DEFAULT_REPORT_PATH); 47 | } 48 | 49 | @Override 50 | public void describe(SensorDescriptor descriptor) { 51 | descriptor 52 | .name("Lizard") 53 | .onlyOnLanguages(Swift.KEY, ObjectiveC.KEY) 54 | .onlyOnFileType(InputFile.Type.MAIN); 55 | } 56 | 57 | @Override 58 | public void execute(SensorContext context) { 59 | File reportFile = new File(context.fileSystem().baseDir(), reportPath()); 60 | if (!reportFile.isFile()) { 61 | LOGGER.warn("Lizard report file not found at {}", reportFile.getAbsolutePath()); 62 | return; 63 | } 64 | 65 | LOGGER.info("Processing complexity report: {}", reportFile.getAbsolutePath()); 66 | LizardReportParser parser = new LizardReportParser(context); 67 | parser.parseReport(reportFile); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /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/sonar-next/sonar-swift/093be7fac38fd0cb8b36e2193b29e2282aa9fb48/sonar-swift-plugin/src/test/resources/coverage/dir1/cobertura.xml -------------------------------------------------------------------------------- /sonar-swift-plugin/src/test/resources/coverage/dir2/cobertura.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonar-next/sonar-swift/093be7fac38fd0cb8b36e2193b29e2282aa9fb48/sonar-swift-plugin/src/test/resources/coverage/dir2/cobertura.xml -------------------------------------------------------------------------------- /sonar-swift-plugin/src/test/resources/coverage/dir3/cobertura.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sonar-next/sonar-swift/093be7fac38fd0cb8b36e2193b29e2282aa9fb48/sonar-swift-plugin/src/test/resources/coverage/dir3/cobertura.xml -------------------------------------------------------------------------------- /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/cpd/SwiftCpdAnalyzer.java: -------------------------------------------------------------------------------- 1 | package com.backelite.sonarqube.swift.cpd; 2 | 3 | import com.backelite.sonarqube.commons.TokenLocation; 4 | import com.sonar.sslr.api.GenericTokenType; 5 | import com.sonar.sslr.api.Token; 6 | import com.sonar.sslr.api.TokenType; 7 | import com.sonar.sslr.impl.Lexer; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.sonar.api.batch.fs.InputFile; 11 | import org.sonar.api.batch.sensor.SensorContext; 12 | import org.sonar.api.batch.sensor.cpd.NewCpdTokens; 13 | 14 | import java.io.File; 15 | import java.util.Iterator; 16 | 17 | /** 18 | * @author magaofei 19 | * @date 2021/4/5 20 | */ 21 | public class SwiftCpdAnalyzer { 22 | 23 | private static final Logger logger = LoggerFactory.getLogger(SwiftCpdAnalyzer.class); 24 | 25 | private final SensorContext context; 26 | private final Lexer lexer; 27 | 28 | public SwiftCpdAnalyzer(SensorContext context, Lexer lexer) { 29 | this.context = context; 30 | this.lexer = lexer; 31 | } 32 | 33 | public void pushCpdTokens(InputFile inputFile) { 34 | // NewHighlighting highlighting = context.newHighlighting(); 35 | 36 | File file = inputFile.file(); 37 | // highlighting.onFile(inputFile); 38 | 39 | if (inputFile.filename().endsWith(".swift")) { 40 | return; 41 | } 42 | 43 | NewCpdTokens cpdTokens = context.newCpdTokens(); 44 | cpdTokens.onFile(inputFile); 45 | 46 | Iterator iterator = lexer.lex(file).iterator(); 47 | 48 | while (iterator.hasNext()) { 49 | Token token = iterator.next(); 50 | TokenType tokenType = token.getType(); 51 | 52 | if (!tokenType.equals(GenericTokenType.EOF)) { 53 | TokenLocation tokenLocation = new TokenLocation(token); 54 | cpdTokens.addToken(tokenLocation.startLine(), tokenLocation.startCharacter(), tokenLocation.endLine(), tokenLocation.endCharacter(), token.getValue()); 55 | } 56 | // if (tokenType.equals(GenericTokenType.LITERAL)) { 57 | // highlight(highlighting, token, TypeOfText.STRING); 58 | // } else if (KEYWORDS.contains(tokenType)) { 59 | // highlight(highlighting, token, TypeOfText.KEYWORD); 60 | // } 61 | // for (Trivia trivia : token.getTrivia()) { 62 | // highlight(highlighting, trivia.getToken(), TypeOfText.COMMENT); 63 | // } 64 | } 65 | 66 | // highlighting.save(); 67 | cpdTokens.save(); 68 | } 69 | 70 | // private static void highlight(NewHighlighting highlighting, Token token, TypeOfText typeOfText) { 71 | // TokenLocation tokenLocation = new TokenLocation(token); 72 | // highlighting.highlight(tokenLocation.startLine(), tokenLocation.startCharacter(), tokenLocation.endLine(), tokenLocation.endCharacter(), typeOfText); 73 | // } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /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/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 | 28 | import java.io.IOException; 29 | import java.io.InputStreamReader; 30 | import java.io.Reader; 31 | import java.nio.charset.Charset; 32 | 33 | /** 34 | * Created by gillesgrousset on 27/11/2015. 35 | */ 36 | public class SwiftLintRulesDefinition implements RulesDefinition { 37 | private static final Logger LOGGER = LoggerFactory.getLogger(SwiftLintRulesDefinition.class); 38 | public static final String REPOSITORY_KEY = "SwiftLint"; 39 | public static final String REPOSITORY_NAME = REPOSITORY_KEY; 40 | private static final String RULES_FILE = "/org/sonar/plugins/swiftlint/rules.json"; 41 | 42 | @Override 43 | public void define(Context context) { 44 | NewRepository repository = context.createRepository(REPOSITORY_KEY, Swift.KEY).setName(REPOSITORY_NAME); 45 | 46 | try(Reader reader = new InputStreamReader(getClass().getResourceAsStream(RULES_FILE), Charset.forName("UTF-8"))){ 47 | JSONArray slRules = (JSONArray)JSONValue.parse(reader); 48 | if(slRules != null){ 49 | for (Object obj : slRules) { 50 | JSONObject slRule = (JSONObject) obj; 51 | NewRule newRule = repository.createRule((String) slRule.get("key")) 52 | .setName((String) slRule.get("name")) 53 | .setSeverity((String) slRule.get("severity")) 54 | .setHtmlDescription((String) slRule.get("description")); 55 | newRule.setDebtRemediationFunction( 56 | newRule.debtRemediationFunctions().constantPerIssue("5min")); 57 | } 58 | } 59 | } catch (IOException e) { 60 | LOGGER.error("Failed to load SwiftLint rules", e); 61 | } 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/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 | 28 | import java.io.IOException; 29 | import java.io.InputStreamReader; 30 | import java.io.Reader; 31 | import java.nio.charset.Charset; 32 | 33 | /** 34 | * Created by tzwickl on 22/11/2016. 35 | */ 36 | 37 | public class TailorRulesDefinition implements RulesDefinition { 38 | private static final Logger LOGGER = LoggerFactory.getLogger(TailorRulesDefinition.class); 39 | public static final String REPOSITORY_KEY = "Tailor"; 40 | public static final String REPOSITORY_NAME = REPOSITORY_KEY; 41 | private static final String RULES_FILE = "/org/sonar/plugins/tailor/rules.json"; 42 | 43 | @Override 44 | public void define(final 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 | NewRule newRule = repository.createRule((String) slRule.get("key")) 53 | .setName((String) slRule.get("name")) 54 | .setSeverity((String) slRule.get("severity")) 55 | .setHtmlDescription(slRule.get("description") + 56 | " (" + slRule.get("styleguide") + ")"); 57 | newRule.setDebtRemediationFunction( 58 | newRule.debtRemediationFunctions().constantPerIssue("10min")); 59 | } 60 | } 61 | } catch (IOException e) { 62 | LOGGER.error("Failed to load tailor rules", e); 63 | } 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/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/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/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/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 | --------------------------------------------------------------------------------
[REPLACE THIS WITH YOUR INFORMATION]
[INSERT OUTPUT HERE]