diff --git a/.travis.yml b/.travis.yml index 122387cf..9bcf9994 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,3 @@ language: java jdk: - oraclejdk8 - - oraclejdk7 - - openjdk7 - - openjdk6 \ No newline at end of file diff --git a/README.md b/README.md old mode 100644 new mode 100755 index b621a656..f48319ae --- a/README.md +++ b/README.md @@ -1,88 +1,162 @@ -SonarQube Plugin for Objective C -================================ +# Important : this plugin is not maintained anymore. Please switch to our (Swift plugin)[https://github.com/Backelite/sonar-swift] which now supports Swift and Objective-C + -This repository hosts the Objective-C plugin for [SonarQube](http://www.sonarqube.org/). This plugin enables to analyze and track the quality of iOS (iPhone, iPad) and MacOS developments. -This plugin is not supported by SonarSource. SonarSource offers a [commercial SonarSource Objective-C plugin](http://www.sonarsource.com/products/plugins/languages/objective-c/) as well. Both plugins do not offer the same functionalities/support. +

+ +

-The development of this plugin has always been done thanks to the community. If you wish to contribute, check the [Contributing](https://github.com/octo-technology/sonar-objective-c/wiki/Contributing) wiki page. +| Branch | Status | +|----------|:------------------------------------------------------------------------------------------------------------------------------------------:| +| master | [![Build Status](https://travis-ci.org/Backelite/sonar-objective-c.svg?branch=master)](https://travis-ci.org/Backelite/sonar-objective-c) | +| develop| [![Build Status](https://travis-ci.org/Backelite/sonar-objective-c.svg?branch=develop)](https://travis-ci.org/Backelite/sonar-objective-c) | + +SonarQube Plugin for Objective-C +================================ -Find below an example of an iOS SonarQube dashboard: +This repository is a fork of the open source [SonarQube Plugin for Objective-C](https://github.com/octo-technology/sonar-objective-c). It provides modifications and extra features needed for our internal use. + +A SonarQube 5.0 dashboard of the iOS open source project [GreatReader](https://github.com/semweb/GreatReader):

- Example iOS SonarQube dashboard + Example iOS SonarQube dashboard

-###Features +### Features -- [ ] Complexity -- [ ] Design -- [x] Documentation -- [x] Duplications -- [x] Issues -- [x] Size -- [x] Tests +| Feature | Supported | Details | +|---------------|----------|:-----------:| +| Complexity |YES | Uses [Lizard](https://github.com/terryyin/lizard) | +| Design |NO | | +| Documentation |YES | | +| Duplications |YES | | +| Issues |YES | Uses [OCLint](http://docs.oclint.org/en/dev/intro/installation.html): 71 rules, and [Faux Pas](http://fauxpasapp.com/): 102 rules| +| Size |YES | | +| Tests |YES | Uses [xctool](https://github.com/facebook/xctool), will probably switch to xcodebuild + [xcpretty](https://github.com/supermarin/xcpretty) soon | +| Code coverage |YES | With [gcovr](http://gcovr.com) for project before Xcode 7, otherwise [slather](https://github.com/venmo/slather)| -For more details, see the list of [SonarQube metrics](https://github.com/octo-technology/sonar-objective-c/wiki/Features) implemented or pending. -###Compatibility +### Compatibility -- Use 0.3.x releases for SonarQube 3.x -- Use 0.4.x releases for SonarQube 4.x +Releases available from this repository are compliant with SonarQube 4.3.x and above. -###Download +In order not to break compatibility with the original plugin, plugin releases are numbered with 4 digits. -The latest version is the 0.4.x is not yet released and is available as a snapshot [here](https://rfelden.ci.cloudbees.com/job/sonar-objective-c/lastSuccessfulBuild/artifact/target/). -The latest SonarQube 3.x release is the 0.3.1, and it's available [here](http://bit.ly/1fSwd5I). - -You can also download the latest build of the plugin from [Cloudbees](https://rfelden.ci.cloudbees.com/job/sonar-objective-c/lastSuccessfulBuild/artifact/target/). - -In the worst case, the Maven repository with all snapshots and releases is available here: http://repository-rfelden.forge.cloudbees.com/ +### Faux Pas support + +[Faux Pas](http://fauxpasapp.com/) is a wonderful tool to analyse iOS or Mac applications source code, however it is not free. A 30 trial version is available [here](http://fauxpasapp.com/try/). + +The plugin runs fine even if Faux Pas is not installed (Faux Pas analysis will be skipped). + +### Download + +Binary packages are available in the release section. + + +### Release history + +### 0.6.3 +- SonarQube 7.0 support + +### 0.6.2 +- SonarQube 6.7 support +- FauxPas 1.7.2 support (4 new rules added) +- OCLint 0.13 support (1 new rule added) +- Update run-sonar.sh : xcodebuild optimization (see https://github.com/Backelite/sonar-objective-c/pull/26 thanks to [davidy4ng](https://github.com/davidy4ng)). +- Fix for properties with space (see https://github.com/Backelite/sonar-objective-c/pull/29 thanks to [Branlute](https://github.com/Branlute)) + + +### 0.6.1 +- Replaced oclint-xcodebuild by xcpretty (see https://github.com/Backelite/sonar-objective-c/pull/25 thanks to [davidy4ng](https://github.com/davidy4ng)). +- Added -nounittests and -usesonarscanner parameters to run-sonar.sh script (see https://github.com/Backelite/sonar-objective-c/pull/23 thanks to [davidy4ng](https://github.com/davidy4ng)). +- Sonar 6 fix for Faux Pas (see https://github.com/Backelite/sonar-objective-c/pull/20 thanks to [macostea](https://github.com/macostea)). + +### 0.6.0 +- SonarQube 6 support. Important : will work with SonarQube 5.x and above only. Will not work anymore with SonarQube 4.5.x anymore. -###Prerequisites +### 0.5.2 +- OCLint 0.11.0 support (see https://github.com/Backelite/sonar-objective-c/pull/13) +- Removed required gcovr check in run-sonar.sh (see https://github.com/Backelite/sonar-objective-c/pull/10) +- Fixed issued in run-sonar.sh (see https://github.com/Backelite/sonar-objective-c/pull/2) +- Better test file detection pattern (see https://github.com/Backelite/sonar-objective-c/pull/3/files) -- a Mac with Xcode... +#### 0.5.1 +- Complexity with Lizard ! + +#### 0.5.0 (detached from octo project) +- Detached from octo project (to hard to maintain compatibility) +- Removed deprecated API usages for Sonarube 5.3 support + +#### 0.4.0.3 (based on 0.4.0) +- Xcode 7 coverage support (profdata) + +#### 0.4.0.2 (based on 0.4.0) +- Faux Pas support for release 1.5 and 1.6 +- Support for multiple projects in a same workspace + +#### 0.4.0.1 (based on 0.4.0) +- Faux Pas support +- Moved OCLint long line threshold to 250 +- Add the `plain` reporter at build step to get more information in case of build failure +- Capitalized OCLint rule names + + +### Prerequisites + +- a Mac with Xcode - [SonarQube](http://docs.codehaus.org/display/SONAR/Setup+and+Upgrade) and [SonarQube Runner](http://docs.codehaus.org/display/SONAR/Installing+and+Configuring+SonarQube+Runner) installed ([HomeBrew](http://brew.sh) installed and ```brew install sonar-runner```) +- [xcpretty](https://github.com/supermarin/xcpretty) (see instructions below) - [xctool](https://github.com/facebook/xctool) ([HomeBrew](http://brew.sh) installed and ```brew install xctool```). If you are using Xcode 6, make sure to update xctool (```brew upgrade xctool```) to a version > 0.2.2. -- [OCLint](http://docs.oclint.org/en/dev/intro/installation.html) installed. Version 0.8.1 recommended ([HomeBrew](http://brew.sh) installed and ```brew install https://gist.githubusercontent.com/TonyAnhTran/e1522b93853c5a456b74/raw/157549c7a77261e906fb88bc5606afd8bd727a73/oclint.rb```). -- [gcovr](http://gcovr.com) installed +- [OCLint](http://oclint-docs.readthedocs.io/en/stable/) installed. Version 0.11.0 recommended (0.13.0 since Xcode 9). +- [gcovr](http://gcovr.com) installed for legacy (pre Xcode 7 coverage) +- [slather](https://github.com/SlatherOrg/slather) (```gem install slather```). Version 2.1.0 or above (2.4.4 since Xcode 9). +- [lizard](https://github.com/terryyin/lizard) ([PIP](https://pip.pypa.io/en/stable/installing/) installed and ```sudo pip install lizard```) +- [Faux Pas](http://fauxpasapp.com/) command line tools installed (optional) + +### Installation of xcpretty with JUnit reports fix + +At the time, xcpretty needs to be fixed to work with SonarQube. -###Installation (once for all your Objective-C projects) -- Install [the plugin](http://bit.ly/1fSwd5I) through the Update Center (of SonarQube) or download it into the $SONARQUBE_HOME/extensions/plugins directory -- Copy [run-sonar.sh](https://rawgithub.com/octo-technology/sonar-objective-c/master/src/main/shell/run-sonar.sh) somewhere in your PATH +To install the fixed version, follow those steps : + + git clone https://github.com/Backelite/xcpretty.git + cd xcpretty + git checkout fix/duration_of_failed_tests_workaround + gem build xcpretty.gemspec + sudo gem install --both xcpretty-0.2.2.gem + +### Code coverage data format + +Since Xcode 7, Apple changed its coverage data format to a new format called 'profdata'. +By default this format will be used by the plugin, except if you explicitly force it to legacy mode (for Xcode 6 and below) in your *sonar-project.properties* with this line: + + sonar.objectivec.coverageType=legacy + + +### Installation (once for all your Objective-C projects) +- Download the plugin binary into the $SONARQUBE_HOME/extensions/plugins directory +- Copy [run-sonar.sh](https://rawgithub.com/Backelite/sonar-objective-c/master/src/main/shell/run-sonar.sh) somewhere in your PATH - Restart the SonarQube server. -###Configuration (once per project) -- Copy [sonar-project.properties](https://rawgithub.com/octo-technology/sonar-objective-c/master/sample/sonar-project.properties) in your Xcode project root folder (along your .xcodeproj file) -- Edit the *sonar-project.properties* file to match your Xcode iOS/MacOS project +### Configuration (once per project) +- Copy [sonar-project.properties](https://rawgithub.com/Backelite/sonar-objective-c/master/sample/sonar-project.properties) in your Xcode project root folder (along your .xcodeproj file) +- Edit the ```sonar-project.properties``` file to match your Xcode iOS/MacOS project **The good news is that you don't have to modify your Xcode project to enable SonarQube!**. Ok, there might be one needed modification if you don't have a specific scheme for your test target, but that's all. -###Analysis +### Analysis - Run the script ```run-sonar.sh``` in your Xcode project root folder - Enjoy or file an issue! -###Update (once per plugin update) -- Install the [latest plugin](http://bit.ly/1fSwd5I) version -- Copy [run-sonar.sh](https://rawgithub.com/octo-technology/sonar-objective-c/master/src/main/shell/run-sonar.sh) somewhere in your PATH +### Update (once per plugin update) +- Install the lastest plugin version +- Copy ```run-sonar.sh``` somewhere in your PATH If you still have *run-sonar.sh* file in each of your project (not recommended), you will need to update all those files. -###Credits -* **Cyril Picat** -* **Denis Bregeon** -* **Gilles Grousset** -* **François Helg** -* **Romain Felden** -* **Mete Balci** - -###History -- v0.4.0 (SOON): support for SonarQube 4.x -- v0.3.1 (2013/10): fix release -- v0.3 (2013/10): added support for OCUnit tests and test coverage -- v0.2 (2013/10): added OCLint checks as SonarQube violations -- v0.0.1 (2012/09): v0 with basic metrics such as nb lines of code, nb lines of comment, nb of files, duplications - -###License - -SonarQube Plugin for Objective C is released under the GNU LGPL 3 license: -http://www.gnu.org/licenses/lgpl.txt +### Contributing + +Feel free to contribute to this plugin by issuing pull requests to this repository or to the [original one](https://github.com/octo-technology/sonar-objective-c). + +### License + +SonarQube Plugin for Objective-C is released under the [GNU LGPL 3 license](http://www.gnu.org/licenses/lgpl.txt). diff --git a/build-and-deploy.sh b/build-and-deploy.sh index f2e7c47b..687a5a60 100755 --- a/build-and-deploy.sh +++ b/build-and-deploy.sh @@ -8,17 +8,13 @@ if [ "$?" != 0 ]; then exit $? fi -# Run shell tests -#shelltest src/test/shell --execdir --diff -#if [ "$?" != 0 ]; then -# echo "ERROR - Shell tests failed!" 1>&2 -# exit $? -#fi - # Deploy new verion of plugin in Sonar dir -cp target/*.jar $SONARQUBE_HOME/extensions/plugins +rm -rf $SONARQUBE_HOME/extensions/plugins/*sonar-objective-c-* +cp sonar-objective-c-plugin/target/*.jar $SONARQUBE_HOME/extensions/plugins +rm $SONARQUBE_HOME/extensions/plugins/*sources.jar # Stop/start Sonar +unset GEM_PATH GEM_HOME $SONARQUBE_HOME/bin/macosx-universal-64/sonar.sh stop $SONARQUBE_HOME/bin/macosx-universal-64/sonar.sh start diff --git a/pom.xml b/pom.xml old mode 100644 new mode 100755 index 140dd4eb..a7ff4153 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,30 @@ + + 4.0.0 + + sonar-objective-c-plugin + @@ -16,21 +40,15 @@ - - org.codehaus.sonar-plugins - parent - 18 - - - org.codehaus.sonar-plugin.objectivec - sonar-objective-c-plugin - 0.4.0-SNAPSHOT + com.backelite.sonarqube + backelite-objective-c + 0.6.3 - sonar-plugin + pom Objective-C Sonar Plugin - Enables analysis of Objective-C projects into Sonar. - https://github.com/octo-technology/sonar-objective-c + Enables analysis of Objective-C projects into SonarQube. + https://github.com/Backelite/sonar-objective-c 2012 @@ -59,8 +77,8 @@ zippy1978 Gilles Grousset - https://github.com/zippy1978 - + Backelite + fhelg François Helg @@ -79,9 +97,9 @@ - scm:git:git@github.com:octo-technology/sonar-objective-c.git - scm:git:git@github.com:octo-technology/sonar-objective-c.git - https://github.com/octo-technology/sonar-objective-c + scm:git:git@github.com:Backelite/sonar-objective-c.git + scm:git:git@github.com:Backelite/sonar-objective-c.git + https://github.com/Backelite/sonar-objective-c @@ -90,99 +108,228 @@ - OCTO Technology + OCTO Technology, Backelite + contact@backelite.com Sonar Objective-C Plugin true - 4.3 - 1.20 + 5.6 - - org.sonar.plugins.objectivec.ObjectiveCPlugin - ObjectiveC + 3.5.2 + 2.5 + 2.6 + 17.0 + 4.10 + 1.0.13 + 1.9.0 + 1.7.21 + 5.6 + 3.13 + 2.5.0.36 + 1.22 + 2.6.1 + 2.6.2 + 1.6 + + - org.codehaus.sonar - sonar-plugin-api - ${sonar.version} - - - org.codehaus.sonar - sonar-testing-harness - ${sonar.version} + org.sonarsource.sslr + sslr-core + ${sslr.version} - org.codehaus.sonar - sonar-deprecated - ${sonar.version} + org.sonarsource.sslr-squid-bridge + sslr-squid-bridge + ${sslr-squid-bridge.version} + + + org.codehaus.sonar.sslr + sslr-core + + + org.codehaus.sonar.sslr + sslr-xpath + + + org.codehaus.sonar + sonar-plugin-api + + + org.picocontainer + picocontainer + + + org.slf4j + slf4j-api + + + org.slf4j + jcl-over-slf4j + + - - org.codehaus.sonar.sslr - sslr-core - ${sslr.version} + commons-lang + commons-lang + ${commons-lang.version} - org.codehaus.sonar.sslr - sslr-xpath - ${sslr.version} + commons-io + commons-io + ${commons-io.version} - org.codehaus.sonar.sslr - sslr-toolkit - ${sslr.version} + ch.qos.logback + logback-classic + ${logback.version} - org.codehaus.sonar.sslr - sslr-testing-harness - ${sslr.version} + com.google.guava + guava + ${guava.version} - org.codehaus.sonar.sslr-squid-bridge - sslr-squid-bridge - 2.4 + com.google.code.gson + gson + ${gson.version} ant ant - 1.6 + ${ant.version} + + + + com.googlecode.json-simple + json-simple + 1.1.1 + junit junit - 4.10 + ${junit.version} + test org.mockito mockito-all - 1.9.0 + ${mockito.version} + test - org.hamcrest - hamcrest-all - 1.1 + org.assertj + assertj-core + ${assertj.version} + test - org.easytesting - fest-assert - 1.4 + org.sonarsource.sonarqube + sonar-testing-harness + ${sonar.version} + test - ch.qos.logback - logback-classic - 0.9.30 + org.sonarsource.sslr + sslr-testing-harness + ${sslr.version} + test + + + org.sonarsource.sonarlint.core + sonarlint-core + ${sonarlint.version} + test + + + org.sonarsource.orchestrator + sonar-orchestrator + ${sonar-orchestrator.version} + test + + + com.oracle + ojdbc6 + + + + + + + org.sonarsource.sonarqube + sonar-plugin-api + ${sonar.version} + provided - org.codehaus.sonar.plugins - sonar-surefire-plugin - 2.7 + org.slf4j + slf4j-api + ${slf4j.version} + provided + + + + + org.sonarsource.sonar-packaging-maven-plugin + sonar-packaging-maven-plugin + 1.16 + true + + org.sonar.plugins.objectivec.ObjectiveCPlugin + ObjectiveC (Backelite) + + + + com.mycila + license-maven-plugin + 3.0 + +
com/mycila/maven/plugin/license/templates/LGPL-3.txt
+ + ${license.owner} + ${license.email} + ${license.title} + + + **/README + **/*/sh + src/test/resources/** + src/test/shell/** + src/main/resources/** + *.groovy + *.sh + **/*.properties + **/pom.xml + +
+ + + + check + + + +
+ + org.apache.maven.plugins + maven-compiler-plugin + 3.6.2 + + 1.8 + 1.8 + + +
+
+
diff --git a/sample/screen shot SonarQube dashboard.png b/sample/screen shot SonarQube dashboard.png index c2b72a7c..62f8ecf3 100644 Binary files a/sample/screen shot SonarQube dashboard.png and b/sample/screen shot SonarQube dashboard.png differ diff --git a/sample/sonar-project.properties b/sample/sonar-project.properties index 41ed559f..8e16e64a 100644 --- a/sample/sonar-project.properties +++ b/sample/sonar-project.properties @@ -15,6 +15,16 @@ sonar.sources=srcDir1,srcDir2 # Path to test directories (comment if no test) sonar.tests=testSrcDir +# Coverage type to expect from project +# can be 'legacy' (pre Xcode 7) or 'profdata' +# If not set : defaults to profdata +#sonar.objectivec.coverageType=profdata + +# Destination Simulator to run surefire +# As string expected in destination argument of xcodebuild command +# Example = sonar.swift.simulator=platform=iOS Simulator,name=iPhone 6,OS=9.2 +sonar.objectivec.simulator=platform=iOS Simulator,name=iPhone 6,OS=9.2 + # Xcode project configuration (.xcodeproj or .xcworkspace) # -> If you have a project: configure only sonar.objectivec.project @@ -25,7 +35,7 @@ sonar.objectivec.project=myApplication.xcodeproj # Scheme to build your application sonar.objectivec.appScheme=myApplication -# Scheme to build and run your tests (comment following line of you don't have any tests) +# Scheme to build and run your surefire (comment following line of you don't have any surefire) sonar.objectivec.testScheme=myApplicationTests ########################## @@ -48,9 +58,13 @@ sonar.sourceEncoding=UTF-8 # Change it only if you generate the file on your own # sonar.objectivec.oclint.report=sonar-reports/oclint.xml -# Paths to exclude from coverage report (tests, 3rd party libraries etc.) +# FauxPas report generated by run-sonar.sh is stored in sonar-reports/fauxpas.json +# Change it only if you generate the file on your own +# sonar.objectivec.fauxpas.report=sonar-reports/fauxpas.json + +# Paths to exclude from coverage report (surefire, 3rd party libraries etc.) # sonar.objectivec.excludedPathsFromCoverage=pattern1,pattern2 -sonar.objectivec.excludedPathsFromCoverage=.*Tests.* +sonar.objectivec.excludedPathsFromCoverage=.*Tests.*,.*Specs.* # Project SCM settings # sonar.scm.enabled=true diff --git a/sonar-objective-c-plugin/pom.xml b/sonar-objective-c-plugin/pom.xml new file mode 100644 index 00000000..d9fb4ef6 --- /dev/null +++ b/sonar-objective-c-plugin/pom.xml @@ -0,0 +1,39 @@ + + + + + com.backelite.sonarqube + backelite-objective-c + 0.6.3 + + 4.0.0 + + com.backelite.sonarqube + backelite-sonar-objective-c-plugin + 0.6.3 + + sonar-plugin + + + \ No newline at end of file diff --git a/src/main/java/org/sonar/objectivec/ObjectiveCAstScanner.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/ObjectiveCAstScanner.java similarity index 83% rename from src/main/java/org/sonar/objectivec/ObjectiveCAstScanner.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/ObjectiveCAstScanner.java index ae3b590e..9ae727ba 100644 --- a/src/main/java/org/sonar/objectivec/ObjectiveCAstScanner.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/ObjectiveCAstScanner.java @@ -1,30 +1,28 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec; +package com.sonar.objectivec; import java.io.File; import java.util.Collection; -import org.sonar.objectivec.api.ObjectiveCGrammar; -import org.sonar.objectivec.api.ObjectiveCMetric; -import org.sonar.objectivec.parser.ObjectiveCParser; +import com.sonar.objectivec.api.ObjectiveCGrammar; +import com.sonar.objectivec.api.ObjectiveCMetric; +import com.sonar.objectivec.parser.ObjectiveCParser; import org.sonar.squidbridge.AstScanner; import org.sonar.squidbridge.CommentAnalyser; import org.sonar.squidbridge.SquidAstVisitor; diff --git a/src/main/java/org/sonar/objectivec/ObjectiveCConfiguration.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/ObjectiveCConfiguration.java similarity index 54% rename from src/main/java/org/sonar/objectivec/ObjectiveCConfiguration.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/ObjectiveCConfiguration.java index cee56859..d525f0b2 100644 --- a/src/main/java/org/sonar/objectivec/ObjectiveCConfiguration.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/ObjectiveCConfiguration.java @@ -1,27 +1,25 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec; +package com.sonar.objectivec; import java.nio.charset.Charset; -import org.sonar.squid.api.SquidConfiguration; +import org.sonar.squidbridge.api.SquidConfiguration; public class ObjectiveCConfiguration extends SquidConfiguration { diff --git a/src/main/java/org/sonar/objectivec/api/ObjectiveCGrammar.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCGrammar.java similarity index 55% rename from src/main/java/org/sonar/objectivec/api/ObjectiveCGrammar.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCGrammar.java index f582eea1..95429be5 100644 --- a/src/main/java/org/sonar/objectivec/api/ObjectiveCGrammar.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCGrammar.java @@ -1,23 +1,21 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec.api; +package com.sonar.objectivec.api; import com.sonar.sslr.api.Grammar; import com.sonar.sslr.api.Rule; diff --git a/src/main/java/org/sonar/objectivec/api/ObjectiveCKeyword.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCKeyword.java similarity index 86% rename from src/main/java/org/sonar/objectivec/api/ObjectiveCKeyword.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCKeyword.java index df2c1a81..f86138d5 100644 --- a/src/main/java/org/sonar/objectivec/api/ObjectiveCKeyword.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCKeyword.java @@ -1,23 +1,21 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec.api; +package com.sonar.objectivec.api; import com.sonar.sslr.api.AstNode; import com.sonar.sslr.api.TokenType; diff --git a/src/main/java/org/sonar/objectivec/api/ObjectiveCMetric.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCMetric.java similarity index 61% rename from src/main/java/org/sonar/objectivec/api/ObjectiveCMetric.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCMetric.java index 23058102..20ddc812 100644 --- a/src/main/java/org/sonar/objectivec/api/ObjectiveCMetric.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCMetric.java @@ -1,23 +1,21 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec.api; +package com.sonar.objectivec.api; import org.sonar.squidbridge.measures.CalculatedMetricFormula; import org.sonar.squidbridge.measures.MetricDef; diff --git a/src/main/java/org/sonar/objectivec/api/ObjectiveCPunctuator.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCPunctuator.java similarity index 74% rename from src/main/java/org/sonar/objectivec/api/ObjectiveCPunctuator.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCPunctuator.java index d6bba1ad..2e7c7597 100644 --- a/src/main/java/org/sonar/objectivec/api/ObjectiveCPunctuator.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCPunctuator.java @@ -1,23 +1,21 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec.api; +package com.sonar.objectivec.api; import com.sonar.sslr.api.AstNode; import com.sonar.sslr.api.TokenType; diff --git a/src/main/java/org/sonar/objectivec/api/ObjectiveCTokenType.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCTokenType.java similarity index 51% rename from src/main/java/org/sonar/objectivec/api/ObjectiveCTokenType.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCTokenType.java index 553b7129..7cd60730 100644 --- a/src/main/java/org/sonar/objectivec/api/ObjectiveCTokenType.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/api/ObjectiveCTokenType.java @@ -1,23 +1,21 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec.api; +package com.sonar.objectivec.api; import com.sonar.sslr.api.AstNode; import com.sonar.sslr.api.TokenType; diff --git a/src/main/java/org/sonar/objectivec/checks/CheckList.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/checks/CheckList.java similarity index 52% rename from src/main/java/org/sonar/objectivec/checks/CheckList.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/checks/CheckList.java index be5d018f..eb5a51f0 100644 --- a/src/main/java/org/sonar/objectivec/checks/CheckList.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/checks/CheckList.java @@ -1,23 +1,21 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec.checks; +package com.sonar.objectivec.checks; import java.util.List; diff --git a/src/main/java/org/sonar/objectivec/lexer/ObjectiveCLexer.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/lexer/ObjectiveCLexer.java similarity index 66% rename from src/main/java/org/sonar/objectivec/lexer/ObjectiveCLexer.java rename to sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/lexer/ObjectiveCLexer.java index c0f72700..b90b1aa6 100644 --- a/src/main/java/org/sonar/objectivec/lexer/ObjectiveCLexer.java +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/lexer/ObjectiveCLexer.java @@ -1,29 +1,27 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.objectivec.lexer; +package com.sonar.objectivec.lexer; import static com.sonar.sslr.api.GenericTokenType.LITERAL; import static com.sonar.sslr.impl.channel.RegexpChannelBuilder.commentRegexp; import static com.sonar.sslr.impl.channel.RegexpChannelBuilder.regexp; -import org.sonar.objectivec.ObjectiveCConfiguration; +import com.sonar.objectivec.ObjectiveCConfiguration; import com.sonar.sslr.impl.Lexer; import com.sonar.sslr.impl.channel.BlackHoleChannel; diff --git a/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/parser/ObjectiveCGrammarImpl.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/parser/ObjectiveCGrammarImpl.java new file mode 100644 index 00000000..bf89b323 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/parser/ObjectiveCGrammarImpl.java @@ -0,0 +1,34 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package com.sonar.objectivec.parser; + +import static com.sonar.sslr.api.GenericTokenType.EOF; +import static com.sonar.sslr.api.GenericTokenType.LITERAL; +import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.o2n; + +import com.sonar.objectivec.api.ObjectiveCGrammar; + +public class ObjectiveCGrammarImpl extends ObjectiveCGrammar { + + public ObjectiveCGrammarImpl() { + + program.is(o2n(LITERAL), EOF); + + } + +} diff --git a/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/parser/ObjectiveCParser.java b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/parser/ObjectiveCParser.java new file mode 100644 index 00000000..880c2c90 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/com/sonar/objectivec/parser/ObjectiveCParser.java @@ -0,0 +1,41 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package com.sonar.objectivec.parser; + +import com.sonar.objectivec.ObjectiveCConfiguration; +import com.sonar.objectivec.api.ObjectiveCGrammar; +import com.sonar.objectivec.lexer.ObjectiveCLexer; + +import com.sonar.sslr.impl.Parser; + +public class ObjectiveCParser { + + private ObjectiveCParser() { + } + + public static Parser create() { + return create(new ObjectiveCConfiguration()); + } + + public static Parser create(ObjectiveCConfiguration conf) { + return Parser.builder((ObjectiveCGrammar) new ObjectiveCGrammarImpl()) + .withLexer(ObjectiveCLexer.create(conf)) + .build(); + } + +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/ObjectiveCPlugin.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/ObjectiveCPlugin.java new file mode 100644 index 00000000..a8fc9ac6 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/ObjectiveCPlugin.java @@ -0,0 +1,87 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec; + +import java.util.List; + +import org.sonar.api.Properties; +import org.sonar.api.Property; +import org.sonar.api.SonarPlugin; +import org.sonar.plugins.objectivec.complexity.LizardSensor; +import org.sonar.plugins.objectivec.surefire.SurefireSensor; +import org.sonar.plugins.objectivec.violations.ObjectiveCProfile; +import org.sonar.plugins.objectivec.violations.fauxpas.FauxPasProfile; +import org.sonar.plugins.objectivec.violations.fauxpas.FauxPasRulesDefinition; +import org.sonar.plugins.objectivec.violations.fauxpas.FauxPasSensor; +import org.sonar.plugins.objectivec.violations.oclint.OCLintProfile; +import org.sonar.plugins.objectivec.violations.oclint.OCLintRulesDefinition; +import org.sonar.plugins.objectivec.violations.oclint.OCLintSensor; +import org.sonar.plugins.objectivec.coverage.CoberturaSensor; +import org.sonar.plugins.objectivec.colorizer.ObjectiveCColorizerFormat; +import org.sonar.plugins.objectivec.core.ObjectiveC; +import org.sonar.plugins.objectivec.cpd.ObjectiveCCpdMapping; + +import com.google.common.collect.ImmutableList; + +import org.sonar.plugins.objectivec.violations.fauxpas.FauxPasProfileImporter; +import org.sonar.plugins.objectivec.violations.oclint.OCLintProfileImporter; + +@Properties({ + @Property(key = CoberturaSensor.REPORT_PATTERN_KEY, defaultValue = CoberturaSensor.DEFAULT_REPORT_PATTERN, name = "Path to unit test coverage report(s)", description = "Relative to projects' root. Ant patterns are accepted", global = false, project = true), + @Property(key = OCLintSensor.REPORT_PATH_KEY, defaultValue = OCLintSensor.DEFAULT_REPORT_PATH, name = "Path to oclint pmd formatted report", description = "Relative to projects' root.", global = false, project = true), + @Property(key = FauxPasSensor.REPORT_PATH_KEY, defaultValue = FauxPasSensor.DEFAULT_REPORT_PATH, name = "Path to fauxpas json formatted report", description = "Relative to projects' root.", global = false, project = true), + @Property(key = LizardSensor.REPORT_PATH_KEY, defaultValue = LizardSensor.DEFAULT_REPORT_PATH, name = "Path to lizard report", description = "Relative to projects' root.", global = false, project = true) +}) +public class ObjectiveCPlugin extends SonarPlugin { + + public List getExtensions() { + return ImmutableList.of(ObjectiveC.class, + + ObjectiveCCpdMapping.class, + + ObjectiveCSquidSensor.class, + ObjectiveCProfile.class, + SurefireSensor.class, + CoberturaSensor.class, + + OCLintRulesDefinition.class, + OCLintSensor.class, + OCLintProfile.class, + OCLintProfileImporter.class, + + FauxPasSensor.class, + FauxPasRulesDefinition.class, + FauxPasProfile.class, + FauxPasProfileImporter.class, + + LizardSensor.class + ); + } + + // Global Objective C constants + public static final String FALSE = "false"; + + public static final String FILE_SUFFIXES_KEY = "sonar.objectivec.file.suffixes"; + public static final String FILE_SUFFIXES_DEFVALUE = "h,m,mm"; + + public static final String PROPERTY_PREFIX = "sonar.objectivec"; + + public static final String TEST_FRAMEWORK_KEY = PROPERTY_PREFIX + ".testframework"; + public static final String TEST_FRAMEWORK_DEFAULT = "ghunit"; + +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/ObjectiveCSquidSensor.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/ObjectiveCSquidSensor.java new file mode 100644 index 00000000..750dcd19 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/ObjectiveCSquidSensor.java @@ -0,0 +1,160 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FilePredicate; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.rule.CheckFactory; +import org.sonar.api.batch.rule.Checks; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.issue.Issuable; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.scan.filesystem.PathResolver; +import com.sonar.objectivec.ObjectiveCAstScanner; +import com.sonar.objectivec.ObjectiveCConfiguration; +import com.sonar.objectivec.api.ObjectiveCGrammar; +import com.sonar.objectivec.api.ObjectiveCMetric; +import com.sonar.objectivec.checks.CheckList; +import org.sonar.plugins.objectivec.core.ObjectiveC; +import org.sonar.squidbridge.AstScanner; +import org.sonar.squidbridge.SquidAstVisitor; +import org.sonar.squidbridge.api.CheckMessage; +import org.sonar.squidbridge.api.SourceCode; +import org.sonar.squidbridge.api.SourceFile; +import org.sonar.squidbridge.checks.SquidCheck; +import org.sonar.squidbridge.indexer.QueryByType; + +import java.util.Collection; +import java.util.List; +import java.util.Locale; + + +public class ObjectiveCSquidSensor implements Sensor { + + private final Number[] FUNCTIONS_DISTRIB_BOTTOM_LIMITS = {1, 2, 4, 6, 8, 10, 12, 20, 30}; + private final Number[] FILES_DISTRIB_BOTTOM_LIMITS = {0, 5, 10, 20, 30, 60, 90}; + + private final FileSystem fileSystem; + private final PathResolver pathResolver; + private final ResourcePerspectives resourcePerspectives; + private final Checks> checks; + private final FilePredicate mainFilePredicates; + + + private Project project; + private SensorContext context; + private AstScanner scanner; + + public ObjectiveCSquidSensor(RulesProfile profile, FileSystem fileSystem, PathResolver pathResolver, ResourcePerspectives resourcePerspectives, CheckFactory checkFactory) { + + this.fileSystem = fileSystem; + this.pathResolver = pathResolver; + this.resourcePerspectives = resourcePerspectives; + this.checks = checkFactory.>create(CheckList.REPOSITORY_KEY).addAnnotatedChecks(CheckList.getChecks()); + this.mainFilePredicates = fileSystem.predicates().and(fileSystem.predicates().hasLanguage(ObjectiveC.KEY), fileSystem.predicates().hasType(InputFile.Type.MAIN)); + } + + public boolean shouldExecuteOnProject(Project project) { + + return project.isRoot() && fileSystem.hasFiles(fileSystem.predicates().hasLanguage(ObjectiveC.KEY)); + + } + + public void analyse(Project project, SensorContext context) { + this.project = project; + this.context = context; + + List> visitors = Lists.>newArrayList(checks.all()); + AstScanner scanner = ObjectiveCAstScanner.create(createConfiguration(), visitors.toArray(new SquidAstVisitor[visitors.size()])); + + + scanner.scanFiles(ImmutableList.copyOf(fileSystem.files(mainFilePredicates))); + + Collection squidSourceFiles = scanner.getIndex().search(new QueryByType(SourceFile.class)); + save(squidSourceFiles); + } + + private ObjectiveCConfiguration createConfiguration() { + + return new ObjectiveCConfiguration(fileSystem.encoding()); + } + + private void save(Collection squidSourceFiles) { + + for (SourceCode squidSourceFile : squidSourceFiles) { + SourceFile squidFile = (SourceFile) squidSourceFile; + + String relativePath = pathResolver.relativePath(fileSystem.baseDir(), new java.io.File(squidFile.getKey())); + InputFile inputFile = fileSystem.inputFile(fileSystem.predicates().hasRelativePath(relativePath)); + + saveMeasures(inputFile, squidFile); + saveIssues(inputFile, squidFile); + } + } + + private void saveMeasures(InputFile inputFile, SourceFile squidFile) { + context.saveMeasure(inputFile, CoreMetrics.FILES, squidFile.getDouble(ObjectiveCMetric.FILES)); + context.saveMeasure(inputFile, CoreMetrics.LINES, squidFile.getDouble(ObjectiveCMetric.LINES)); + context.saveMeasure(inputFile, CoreMetrics.NCLOC, squidFile.getDouble(ObjectiveCMetric.LINES_OF_CODE)); + context.saveMeasure(inputFile, CoreMetrics.STATEMENTS, squidFile.getDouble(ObjectiveCMetric.STATEMENTS)); + context.saveMeasure(inputFile, CoreMetrics.COMMENT_LINES, squidFile.getDouble(ObjectiveCMetric.COMMENT_LINES)); + } + + private void saveIssues(InputFile inputFile, SourceFile squidFile) { + + Collection messages = squidFile.getCheckMessages(); + + Resource resource = context.getResource(inputFile); + + if (messages != null && resource != null) { + for (CheckMessage message : messages) { + RuleKey ruleKey = checks.ruleKey((SquidCheck) message.getCheck()); + Issuable issuable = resourcePerspectives.as(Issuable.class, resource); + + if (issuable != null) { + Issuable.IssueBuilder issueBuilder = issuable.newIssueBuilder() + .ruleKey(ruleKey) + .line(message.getLine()) + .message(message.getText(Locale.ENGLISH)); + + if (message.getCost() != null) { + issueBuilder.effortToFix(message.getCost()); + } + + issuable.addIssue(issueBuilder.build()); + } + + } + } + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + +} diff --git a/src/main/java/org/sonar/plugins/objectivec/colorizer/ObjectiveCColorizerFormat.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/colorizer/ObjectiveCColorizerFormat.java similarity index 54% rename from src/main/java/org/sonar/plugins/objectivec/colorizer/ObjectiveCColorizerFormat.java rename to sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/colorizer/ObjectiveCColorizerFormat.java index 3f5ea9f8..69faded3 100644 --- a/src/main/java/org/sonar/plugins/objectivec/colorizer/ObjectiveCColorizerFormat.java +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/colorizer/ObjectiveCColorizerFormat.java @@ -1,36 +1,29 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ package org.sonar.plugins.objectivec.colorizer; +import java.util.ArrayList; import java.util.List; import org.sonar.api.web.CodeColorizerFormat; -import org.sonar.colorizer.CDocTokenizer; -import org.sonar.colorizer.CppDocTokenizer; -import org.sonar.colorizer.JavadocTokenizer; -import org.sonar.colorizer.KeywordsTokenizer; -import org.sonar.colorizer.StringTokenizer; import org.sonar.colorizer.Tokenizer; -import org.sonar.objectivec.api.ObjectiveCKeyword; +import com.sonar.objectivec.api.ObjectiveCKeyword; import org.sonar.plugins.objectivec.core.ObjectiveC; - import com.google.common.collect.ImmutableList; public class ObjectiveCColorizerFormat extends CodeColorizerFormat { @@ -41,12 +34,13 @@ public ObjectiveCColorizerFormat() { @Override public List getTokenizers() { - return ImmutableList.of( + /*return ImmutableList.of( new StringTokenizer("", ""), new CDocTokenizer("", ""), new JavadocTokenizer("", ""), new CppDocTokenizer("", ""), - new KeywordsTokenizer("", "", ObjectiveCKeyword.keywordValues())); + new KeywordsTokenizer("", "", ObjectiveCKeyword.keywordValues()));*/ + return new ArrayList(); } } diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardMeasurePersistor.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardMeasurePersistor.java new file mode 100644 index 00000000..692d4d1c --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardMeasurePersistor.java @@ -0,0 +1,87 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.complexity; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; + +import java.io.File; +import java.util.List; +import java.util.Map; + +/** + * This class is used to save the measures created by the lizardReportParser in the sonar database + * + * @author Andres Gil Herrera + * @since 28/05/15. + */ +public class LizardMeasurePersistor { + + private static final Logger LOGGER = LoggerFactory.getLogger(LizardMeasurePersistor.class); + + private final Project project; + private final SensorContext sensorContext; + private final FileSystem fileSystem; + + public LizardMeasurePersistor(final Project project, final SensorContext sensorContext, final FileSystem fileSystem) { + this.project = project; + this.sensorContext = sensorContext; + this.fileSystem = fileSystem; + } + + /** + * + * @param measures Map containing as key the name of the file and as value a list containing the measures for that file + */ + public void saveMeasures(final Map> measures) { + + if (measures == null) { + return; + } + + for (Map.Entry> entry : measures.entrySet()) { + File file = new File(fileSystem.baseDir(), entry.getKey()); + InputFile inputFile = fileSystem.inputFile(fileSystem.predicates().hasAbsolutePath(file.getAbsolutePath())); + + if (inputFile == null) { + LOGGER.warn("file not included in sonar {}", entry.getKey()); + continue; + } + + Resource resource = sensorContext.getResource(inputFile); + + if (resource != null) { + for (Measure measure : entry.getValue()) { + try { + LOGGER.debug("Save measure {} for file {}", measure.getMetric().getName(), file); + sensorContext.saveMeasure(resource, measure); + } catch (Exception e) { + LOGGER.error(" Exception -> {} -> {}", entry.getKey(), measure.getMetric().getName(), e); + } + } + } + } + } + +} \ No newline at end of file diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardReportParser.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardReportParser.java new file mode 100644 index 00000000..07b40d22 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardReportParser.java @@ -0,0 +1,250 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.complexity; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.measures.*; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class parses xml Reports form the tool Lizard in order to extract this measures: + * COMPLEXITY, FUNCTIONS, FUNCTION_COMPLEXITY, FUNCTION_COMPLEXITY_DISTRIBUTION, + * FILE_COMPLEXITY, FUNCTION_COMPLEXITY_DISTRIBUTION, COMPLEXITY_IN_FUNCTIONS + * + * @author Andres Gil Herrera + * @since 28/05/15 + */ +public class LizardReportParser { + + private static final Logger LOGGER = LoggerFactory.getLogger(LizardReportParser.class); + + private final Number[] FUNCTIONS_DISTRIB_BOTTOM_LIMITS = {1, 2, 4, 6, 8, 10, 12, 20, 30}; + private final Number[] FILES_DISTRIB_BOTTOM_LIMITS = {0, 5, 10, 20, 30, 60, 90}; + + private static final String MEASURE = "measure"; + private static final String MEASURE_TYPE = "type"; + private static final String MEASURE_ITEM = "item"; + private static final String FILE_MEASURE = "file"; + private static final String FUNCTION_MEASURE = "Function"; + private static final String NAME = "name"; + private static final String VALUE = "value"; + private static final int CYCLOMATIC_COMPLEXITY_INDEX = 2; + private static final int FUNCTIONS_INDEX = 3; + + /** + * + * @param xmlFile lizard xml report + * @return Map containing as key the name of the file and as value a list containing the measures for that file + */ + public Map> parseReport(final File xmlFile) { + Map> result = null; + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + + try { + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(xmlFile); + result = parseFile(document); + } catch (final FileNotFoundException e){ + LOGGER.error("Lizard Report not found {}", xmlFile, e); + } catch (final IOException e) { + LOGGER.error("Error processing file named {}", xmlFile, e); + } catch (final ParserConfigurationException e) { + LOGGER.error("Error parsing file named {}", xmlFile, e); + } catch (final SAXException e) { + LOGGER.error("Error processing file named {}", xmlFile, e); + } + + return result; + } + + /** + * + * @param document Document object representing the lizard report + * @return Map containing as key the name of the file and as value a list containing the measures for that file + */ + private Map> parseFile(Document document) { + final Map> reportMeasures = new HashMap>(); + final List functions = new ArrayList(); + + NodeList nodeList = document.getElementsByTagName(MEASURE); + + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) node; + if (element.getAttribute(MEASURE_TYPE).equalsIgnoreCase(FILE_MEASURE)) { + NodeList itemList = element.getElementsByTagName(MEASURE_ITEM); + addComplexityFileMeasures(itemList, reportMeasures); + } else if(element.getAttribute(MEASURE_TYPE).equalsIgnoreCase(FUNCTION_MEASURE)) { + NodeList itemList = element.getElementsByTagName(MEASURE_ITEM); + collectFunctions(itemList, functions); + } + } + } + + addComplexityFunctionMeasures(reportMeasures, functions); + + return reportMeasures; + } + + /** + * This method extracts the values for COMPLEXITY, FUNCTIONS, FILE_COMPLEXITY + * + * @param itemList list of all items from a + * @param reportMeasures map to save the measures for each file + */ + private void addComplexityFileMeasures(NodeList itemList, Map> reportMeasures){ + for (int i = 0; i < itemList.getLength(); i++) { + Node item = itemList.item(i); + + if (item.getNodeType() == Node.ELEMENT_NODE) { + Element itemElement = (Element) item; + String fileName = itemElement.getAttribute(NAME); + NodeList values = itemElement.getElementsByTagName(VALUE); + int complexity = Integer.parseInt(values.item(CYCLOMATIC_COMPLEXITY_INDEX).getTextContent()); + double fileComplexity = Double.parseDouble(values.item(CYCLOMATIC_COMPLEXITY_INDEX).getTextContent()); + int numberOfFunctions = Integer.parseInt(values.item(FUNCTIONS_INDEX).getTextContent()); + + reportMeasures.put(fileName, buildMeasureList(complexity, fileComplexity, numberOfFunctions)); + } + } + } + + /** + * + * @param complexity overall complexity of the file + * @param fileComplexity file complexity + * @param numberOfFunctions number of functions in the file + * @return returns a list of tree measures COMPLEXITY, FUNCTIONS, FILE_COMPLEXITY with the values specified + */ + private List buildMeasureList(int complexity, double fileComplexity, int numberOfFunctions){ + List list = new ArrayList(); + list.add(new Measure(CoreMetrics.COMPLEXITY).setIntValue(complexity)); + list.add(new Measure(CoreMetrics.FUNCTIONS).setIntValue(numberOfFunctions)); + list.add(new Measure(CoreMetrics.FILE_COMPLEXITY, fileComplexity)); + RangeDistributionBuilder complexityDistribution = new RangeDistributionBuilder(CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION, FILES_DISTRIB_BOTTOM_LIMITS); + complexityDistribution.add(fileComplexity); + return list; + } + + /** + * + * @param itemList NodeList of all items in a tag + * @param functions list to save the functions in the NodeList as ObjCFunction objects. + */ + private void collectFunctions(NodeList itemList, List functions) { + for (int i = 0; i < itemList.getLength(); i++) { + Node item = itemList.item(i); + if (item.getNodeType() == Node.ELEMENT_NODE) { + Element itemElement = (Element) item; + String name = itemElement.getAttribute(NAME); + String measure = itemElement.getElementsByTagName(VALUE).item(CYCLOMATIC_COMPLEXITY_INDEX).getTextContent(); + functions.add(new ObjCFunction(name, Integer.parseInt(measure))); + } + } + } + + /** + * + * @param reportMeasures map to save the measures for the different files + * @param functions list of ObjCFunction to extract the information needed to create + * FUNCTION_COMPLEXITY_DISTRIBUTION, FUNCTION_COMPLEXITY, COMPLEXITY_IN_FUNCTIONS + */ + private void addComplexityFunctionMeasures(Map> reportMeasures, List functions){ + for (Map.Entry> entry : reportMeasures.entrySet()) { + + RangeDistributionBuilder complexityDistribution = new RangeDistributionBuilder(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION, FUNCTIONS_DISTRIB_BOTTOM_LIMITS); + int count = 0; + int complexityInFunctions = 0; + + for (ObjCFunction func : functions) { + if (func.getName().contains(entry.getKey())) { + complexityDistribution.add(func.getCyclomaticComplexity()); + count++; + complexityInFunctions += func.getCyclomaticComplexity(); + } + } + + if (count != 0) { + double complex = 0; + for (Measure m : entry.getValue()){ + if (m.getMetric().getKey().equalsIgnoreCase(CoreMetrics.FILE_COMPLEXITY.getKey())){ + complex = m.getValue(); + break; + } + } + + double complexMean = complex/(double)count; + entry.getValue().addAll(buildFunctionMeasuresList(complexMean, complexityInFunctions, complexityDistribution)); + } + } + } + + /** + * + * @param complexMean average complexity per function in a file + * @param complexityInFunctions Entire complexity in functions + * @param builder Builder ready to build FUNCTION_COMPLEXITY_DISTRIBUTION + * @return list of Measures containing FUNCTION_COMPLEXITY_DISTRIBUTION, FUNCTION_COMPLEXITY and COMPLEXITY_IN_FUNCTIONS + */ + public List buildFunctionMeasuresList(double complexMean, int complexityInFunctions, RangeDistributionBuilder builder){ + List list = new ArrayList(); + list.add(new Measure(CoreMetrics.FUNCTION_COMPLEXITY, complexMean)); + list.add(new Measure(CoreMetrics.COMPLEXITY_IN_FUNCTIONS).setIntValue(complexityInFunctions)); + return list; + } + + /** + * helper class to process the information the functions contained in a Lizard report + */ + private class ObjCFunction { + private String name; + private int cyclomaticComplexity; + + public ObjCFunction(String name, int cyclomaticComplexity) { + this.name = name; + this.cyclomaticComplexity = cyclomaticComplexity; + } + + public String getName() { + return name; + } + + public int getCyclomaticComplexity() { + return cyclomaticComplexity; + } + + } +} \ No newline at end of file diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardSensor.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardSensor.java new file mode 100644 index 00000000..ea1c6f4b --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/complexity/LizardSensor.java @@ -0,0 +1,102 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.complexity; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.config.Settings; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.Project; +import org.sonar.plugins.objectivec.ObjectiveCPlugin; +import org.sonar.plugins.objectivec.core.ObjectiveC; + +import java.io.File; +import java.util.List; +import java.util.Map; + +/** + * This sensor searches for the report generated from the tool Lizard + * in order to save complexity metrics. + * + * @author Andres Gil Herrera + * @since 28/05/15 + */ +public class LizardSensor implements Sensor { + + private static final Logger LOGGER = LoggerFactory.getLogger(LizardSensor.class); + + public static final String REPORT_PATH_KEY = ObjectiveCPlugin.PROPERTY_PREFIX + ".lizard.report"; + public static final String DEFAULT_REPORT_PATH = "sonar-reports/lizard-report.xml"; + + private final Settings conf; + private final FileSystem fileSystem; + + public LizardSensor(final FileSystem moduleFileSystem, final Settings config) { + this.conf = config; + this.fileSystem = moduleFileSystem; + } + + /** + * + * @param project + * @return true if the project is root the root project and uses Objective-C + */ + public boolean shouldExecuteOnProject(Project project) { + return project.isRoot() && fileSystem.languages().contains(ObjectiveC.KEY); + } + + /** + * + * @param project + * @param sensorContext + */ + public void analyse(Project project, SensorContext sensorContext) { + final String projectBaseDir = fileSystem.baseDir().getPath(); + Map> measures = parseReportsIn(projectBaseDir, new LizardReportParser()); + LOGGER.info("Saving results of complexity analysis"); + new LizardMeasurePersistor(project, sensorContext, fileSystem).saveMeasures(measures); + } + + /** + * + * @param baseDir base directory of the project to search the report + * @param parser LizardReportParser to parse the report + * @return Map containing as key the name of the file and as value a list containing the measures for that file + */ + private Map> parseReportsIn(final String baseDir, LizardReportParser parser) { + final StringBuilder reportFileName = new StringBuilder(baseDir); + reportFileName.append("/").append(reportPath()); + LOGGER.info("Processing complexity report "); + return parser.parseReport(new File(reportFileName.toString())); + } + + /** + * + * @return the default report path or the one specified in the sonar-project.properties + */ + private String reportPath() { + String reportPath = conf.getString(REPORT_PATH_KEY); + if (reportPath == null) { + reportPath = DEFAULT_REPORT_PATH; + } + return reportPath; + } +} \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/objectivec/core/ObjectiveC.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/core/ObjectiveC.java similarity index 73% rename from src/main/java/org/sonar/plugins/objectivec/core/ObjectiveC.java rename to sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/core/ObjectiveC.java index 25e3904d..d5f901b7 100644 --- a/src/main/java/org/sonar/plugins/objectivec/core/ObjectiveC.java +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/core/ObjectiveC.java @@ -1,21 +1,19 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ package org.sonar.plugins.objectivec.core; diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaReportParser.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaReportParser.java new file mode 100644 index 00000000..e9e02eb1 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaReportParser.java @@ -0,0 +1,141 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.coverage; + + +import com.google.common.collect.Maps; +import org.apache.commons.lang.StringUtils; +import org.codehaus.staxmate.in.SMHierarchicCursor; +import org.codehaus.staxmate.in.SMInputCursor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.measures.CoverageMeasuresBuilder; +import org.sonar.api.measures.Measure; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Resource; +import org.sonar.api.utils.ParsingUtils; +import org.sonar.api.utils.StaxParser; +import org.sonar.api.utils.XmlParserException; + +import javax.xml.stream.XMLStreamException; +import java.io.File; +import java.text.ParseException; +import java.util.Locale; +import java.util.Map; + +final class CoberturaReportParser { + + private static final Logger LOGGER = LoggerFactory.getLogger(CoberturaReportParser.class); + + private final FileSystem fileSystem; + private final Project project; + private final SensorContext context; + + private CoberturaReportParser(FileSystem fileSystem, Project project, SensorContext context) { + this.fileSystem = fileSystem; + this.project = project; + this.context = context; + } + + /** + * Parse a Cobertura xml report and create measures accordingly + */ + public static void parseReport(File xmlFile, FileSystem fileSystem, Project project, SensorContext context) { + new CoberturaReportParser(fileSystem, project, context).parse(xmlFile); + } + + private void parse(File xmlFile) { + try { + StaxParser parser = new StaxParser(new StaxParser.XmlStreamHandler() { + + @Override + public void stream(SMHierarchicCursor rootCursor) throws XMLStreamException { + rootCursor.advance(); + collectPackageMeasures(rootCursor.descendantElementCursor("package")); + } + }); + parser.parse(xmlFile); + } catch (XMLStreamException e) { + throw new XmlParserException(e); + } + } + + private void collectPackageMeasures(SMInputCursor pack) throws XMLStreamException { + while (pack.getNext() != null) { + Map builderByFilename = Maps.newHashMap(); + collectFileMeasures(pack.descendantElementCursor("class"), builderByFilename); + for (Map.Entry entry : builderByFilename.entrySet()) { + String filePath = entry.getKey(); + File file = new File(fileSystem.baseDir(), filePath); + InputFile inputFile = fileSystem.inputFile(fileSystem.predicates().hasAbsolutePath(file.getAbsolutePath())); + + if (inputFile == null) { + LOGGER.warn("file not included in sonar {}", filePath); + continue; + } + + Resource resource = context.getResource(inputFile); + if (resourceExists(resource)) { + for (Measure measure : entry.getValue().createMeasures()) { + context.saveMeasure(resource, measure); + } + } + } + } + } + + private boolean resourceExists(Resource file) { + return context.getResource(file) != null; + } + + private static void collectFileMeasures(SMInputCursor clazz, + Map builderByFilename) throws XMLStreamException { + while (clazz.getNext() != null) { + String fileName = clazz.getAttrValue("filename"); + CoverageMeasuresBuilder builder = builderByFilename.get(fileName); + if (builder == null) { + builder = CoverageMeasuresBuilder.create(); + builderByFilename.put(fileName, builder); + } + collectFileData(clazz, builder); + } + } + + private static void collectFileData(SMInputCursor clazz, + CoverageMeasuresBuilder builder) throws XMLStreamException { + SMInputCursor line = clazz.childElementCursor("lines").advance().childElementCursor("line"); + while (line.getNext() != null) { + int lineId = Integer.parseInt(line.getAttrValue("number")); + try { + builder.setHits(lineId, (int) ParsingUtils.parseNumber(line.getAttrValue("hits"), Locale.ENGLISH)); + } catch (ParseException e) { + throw new XmlParserException(e); + } + + String isBranch = line.getAttrValue("branch"); + String text = line.getAttrValue("condition-coverage"); + if (StringUtils.equals(isBranch, "true") && StringUtils.isNotBlank(text)) { + String[] conditions = StringUtils.split(StringUtils.substringBetween(text, "(", ")"), "/"); + builder.setConditions(lineId, Integer.parseInt(conditions[1]), Integer.parseInt(conditions[0])); + } + } + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.java new file mode 100644 index 00000000..6122a318 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.java @@ -0,0 +1,77 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.coverage; + +import java.io.File; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.config.Settings; +import org.sonar.api.resources.Project; +import org.sonar.api.scan.filesystem.PathResolver; +import org.sonar.plugins.objectivec.ObjectiveCPlugin; +import org.sonar.plugins.objectivec.core.ObjectiveC; + + +public final class CoberturaSensor implements Sensor { + + private static final Logger LOGGER = LoggerFactory.getLogger(CoberturaSensor.class); + + public static final String REPORT_PATTERN_KEY = ObjectiveCPlugin.PROPERTY_PREFIX + + ".coverage.reportPattern"; + public static final String DEFAULT_REPORT_PATTERN = "sonar-reports/coverage*.xml"; + + private final ReportFilesFinder reportFilesFinder; + + private final Settings settings; + private final FileSystem fileSystem; + private final PathResolver pathResolver; + private Project project; + + public CoberturaSensor(final FileSystem fileSystem, final PathResolver pathResolver, final Settings settings) { + + this.settings = settings; + this.fileSystem = fileSystem; + this.pathResolver = pathResolver; + + reportFilesFinder = new ReportFilesFinder(settings, REPORT_PATTERN_KEY, DEFAULT_REPORT_PATTERN); + } + + public boolean shouldExecuteOnProject(final Project project) { + + this.project = project; + + return project.isRoot() && fileSystem.languages().contains(ObjectiveC.KEY); + } + + public void analyse(final Project project, final SensorContext context) { + + final String projectBaseDir = fileSystem.baseDir().getPath(); + + for (final File report : reportFilesFinder.reportsIn(projectBaseDir)) { + LOGGER.info("Processing coverage report {}", report); + CoberturaReportParser.parseReport(report, fileSystem, project, context); + } + + } + + +} diff --git a/src/main/java/org/sonar/plugins/objectivec/coverage/ReportFilesFinder.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/ReportFilesFinder.java similarity index 76% rename from src/main/java/org/sonar/plugins/objectivec/coverage/ReportFilesFinder.java rename to sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/ReportFilesFinder.java index 831327a9..8a509bd5 100644 --- a/src/main/java/org/sonar/plugins/objectivec/coverage/ReportFilesFinder.java +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/coverage/ReportFilesFinder.java @@ -1,21 +1,19 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ package org.sonar.plugins.objectivec.coverage; diff --git a/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCCpdMapping.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCCpdMapping.java similarity index 54% rename from src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCCpdMapping.java rename to sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCCpdMapping.java index 4cf0fc5b..04927ee0 100644 --- a/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCCpdMapping.java +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCCpdMapping.java @@ -1,21 +1,19 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ package org.sonar.plugins.objectivec.cpd; @@ -24,8 +22,8 @@ import net.sourceforge.pmd.cpd.Tokenizer; import org.sonar.api.batch.AbstractCpdMapping; +import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.resources.Language; -import org.sonar.api.resources.ProjectFileSystem; import org.sonar.plugins.objectivec.core.ObjectiveC; public class ObjectiveCCpdMapping extends AbstractCpdMapping { @@ -33,9 +31,9 @@ public class ObjectiveCCpdMapping extends AbstractCpdMapping { private final ObjectiveC language; private final Charset charset; - public ObjectiveCCpdMapping(ObjectiveC language, ProjectFileSystem fs) { + public ObjectiveCCpdMapping(ObjectiveC language, FileSystem fs) { this.language = language; - this.charset = fs.getSourceCharset(); + this.charset = fs.encoding(); } public Tokenizer getTokenizer() { diff --git a/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCTokenizer.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCTokenizer.java similarity index 68% rename from src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCTokenizer.java rename to sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCTokenizer.java index bf180f7c..ef19ec60 100644 --- a/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCTokenizer.java +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/cpd/ObjectiveCTokenizer.java @@ -1,21 +1,19 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ package org.sonar.plugins.objectivec.cpd; @@ -29,8 +27,8 @@ import net.sourceforge.pmd.cpd.Tokenizer; import net.sourceforge.pmd.cpd.Tokens; -import org.sonar.objectivec.ObjectiveCConfiguration; -import org.sonar.objectivec.lexer.ObjectiveCLexer; +import com.sonar.objectivec.ObjectiveCConfiguration; +import com.sonar.objectivec.lexer.ObjectiveCLexer; import com.sonar.sslr.api.Token; import com.sonar.sslr.impl.Lexer; diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/SurefireParser.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/SurefireParser.java new file mode 100644 index 00000000..a31508e6 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/SurefireParser.java @@ -0,0 +1,208 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.surefire; + +import com.google.common.collect.ImmutableList; +import org.apache.commons.lang.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Resource; +import org.sonar.api.test.MutableTestPlan; +import org.sonar.api.test.TestCase; +import org.sonar.api.utils.ParsingUtils; +import org.sonar.api.utils.StaxParser; +import org.sonar.api.utils.XmlParserException; +import org.sonar.plugins.objectivec.surefire.data.SurefireStaxHandler; +import org.sonar.plugins.objectivec.surefire.data.UnitTestClassReport; +import org.sonar.plugins.objectivec.surefire.data.UnitTestIndex; +import org.sonar.plugins.objectivec.surefire.data.UnitTestResult; + +import javax.annotation.Nullable; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.TransformerException; +import java.io.File; +import java.io.FilenameFilter; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created by gillesgrousset on 06/01/15. + */ +public class SurefireParser { + + private static final Logger LOGGER = LoggerFactory.getLogger(SurefireParser.class); + + private final Project project; + private final FileSystem fileSystem; + private final ResourcePerspectives perspectives; + private final SensorContext context; + + public SurefireParser(Project project, FileSystem fileSystem, ResourcePerspectives resourcePerspectives, SensorContext context) { + this.project = project; + this.fileSystem = fileSystem; + this.perspectives = resourcePerspectives; + this.context = context; + } + + public void collect(File reportsDir) { + + + File[] xmlFiles = getReports(reportsDir); + + if (xmlFiles.length == 0) { + insertZeroWhenNoReports(); + } else { + parseFiles(xmlFiles); + } + } + + private File[] getReports(File dir) { + if (dir == null || !dir.isDirectory() || !dir.exists()) { + return new File[0]; + } + + File[] list = dir.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.startsWith("TEST") && name.endsWith(".xml"); + } + }); + + return dir.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.startsWith("TEST") && name.endsWith(".xml"); + } + }); + } + + private void insertZeroWhenNoReports() { + context.saveMeasure(CoreMetrics.TESTS, 0.0); + } + + private void parseFiles(File[] reports) { + UnitTestIndex index = new UnitTestIndex(); + parseFiles(reports, index); + save(index); + } + + private static void parseFiles(File[] reports, UnitTestIndex index) { + SurefireStaxHandler staxParser = new SurefireStaxHandler(index); + StaxParser parser = new StaxParser(staxParser, false); + for (File report : reports) { + try { + parser.parse(report); + } catch (XMLStreamException e) { + throw new IllegalStateException("Fail to parse the Surefire report: " + report, e); + } + } + } + + private void save(UnitTestIndex index) { + long negativeTimeTestNumber = 0; + + for (Map.Entry entry : index.getIndexByClassname().entrySet()) { + UnitTestClassReport report = entry.getValue(); + if (report.getTests() > 0) { + negativeTimeTestNumber += report.getNegativeTimeTestNumber(); + Resource resource = getUnitTestResource(entry.getKey()); + if (resource != null) { + save(report, resource); + } else { + LOGGER.warn("Resource not found: {}", entry.getKey()); + } + } + } + if (negativeTimeTestNumber > 0) { + LOGGER.warn("There is {} test(s) reported with negative time by data, total duration may not be accurate.", negativeTimeTestNumber); + } + } + + private void save(UnitTestClassReport report, Resource resource) { + double testsCount = report.getTests() - report.getSkipped(); + saveMeasure(resource, CoreMetrics.SKIPPED_TESTS, report.getSkipped()); + saveMeasure(resource, CoreMetrics.TESTS, testsCount); + saveMeasure(resource, CoreMetrics.TEST_ERRORS, report.getErrors()); + saveMeasure(resource, CoreMetrics.TEST_FAILURES, report.getFailures()); + saveMeasure(resource, CoreMetrics.TEST_EXECUTION_TIME, report.getDurationMilliseconds()); + double passedTests = testsCount - report.getErrors() - report.getFailures(); + if (testsCount > 0) { + double percentage = passedTests * 100d / testsCount; + saveMeasure(resource, CoreMetrics.TEST_SUCCESS_DENSITY, ParsingUtils.scaleValue(percentage)); + } + saveResults(resource, report); + } + + protected void saveResults(Resource testFile, UnitTestClassReport report) { + for (UnitTestResult unitTestResult : report.getResults()) { + MutableTestPlan testPlan = perspectives.as(MutableTestPlan.class, testFile); + if (testPlan != null) { + testPlan.addTestCase(unitTestResult.getName()) + .setDurationInMs(Math.max(unitTestResult.getDurationMilliseconds(), 0)) + .setStatus(TestCase.Status.of(unitTestResult.getStatus())) + .setMessage(unitTestResult.getMessage()) + .setType(TestCase.TYPE_UNIT) + .setStackTrace(unitTestResult.getStackTrace()); + } + } + } + + @Nullable + public Resource getUnitTestResource(String classname) { + + String fileName = classname.replace('.', '/') + ".m"; + + InputFile inputFile = fileSystem.inputFile(fileSystem.predicates().hasPath(fileName)); + + /* + * Most xcodebuild JUnit parsers don't include the path to the class in the class field, so search for it if it + * wasn't found in the root. + */ + if (inputFile == null) { + List files = ImmutableList.copyOf(fileSystem.inputFiles(fileSystem.predicates().and( + fileSystem.predicates().hasType(InputFile.Type.TEST), + fileSystem.predicates().matchesPathPattern("**/" + fileName.replace("_", "+"))))); + + if (files.isEmpty()) { + LOGGER.info("Unable to locate test source file {}", fileName); + } else { + /* + * Lazily get the first file, since we wouldn't be able to determine the correct one from just the + * test class name in the event that there are multiple matches. + */ + inputFile = files.get(0); + } + } + + return inputFile == null ? null : context.getResource(inputFile); + } + + private void saveMeasure(Resource resource, Metric metric, double value) { + if (!Double.isNaN(value)) { + context.saveMeasure(resource, metric, value); + } + } +} diff --git a/src/main/java/org/sonar/plugins/objectivec/tests/SurefireSensor.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/SurefireSensor.java similarity index 65% rename from src/main/java/org/sonar/plugins/objectivec/tests/SurefireSensor.java rename to sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/SurefireSensor.java index 207a430f..80e4e55e 100644 --- a/src/main/java/org/sonar/plugins/objectivec/tests/SurefireSensor.java +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/SurefireSensor.java @@ -1,24 +1,21 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ - -package org.sonar.plugins.objectivec.tests; +package org.sonar.plugins.objectivec.surefire; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,6 +23,8 @@ import org.sonar.api.batch.DependsUpon; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.component.ResourcePerspectives; import org.sonar.api.config.Settings; import org.sonar.api.resources.Project; import org.sonar.plugins.objectivec.core.ObjectiveC; @@ -37,14 +36,15 @@ public class SurefireSensor implements Sensor { private static final Logger LOG = LoggerFactory.getLogger(SurefireSensor.class); public static final String REPORT_PATH_KEY = "sonar.junit.reportsPath"; public static final String DEFAULT_REPORT_PATH = "sonar-reports/"; - private final Settings conf; - public SurefireSensor() { - this(null); - } + private final Settings settings; + private final FileSystem fileSystem; + private final ResourcePerspectives resourcePerspectives; - public SurefireSensor(final Settings config) { - conf = config; + public SurefireSensor(final FileSystem fileSystem, final Settings config, final ResourcePerspectives resourcePerspectives) { + this.settings = config; + this.fileSystem = fileSystem; + this.resourcePerspectives = resourcePerspectives; } @DependsUpon @@ -53,7 +53,8 @@ public Class dependsUponCoverageSensors() { } public boolean shouldExecuteOnProject(Project project) { - return ObjectiveC.KEY.equals(project.getLanguageKey()); + + return project.isRoot() && fileSystem.hasFiles(fileSystem.predicates().hasLanguage(ObjectiveC.KEY)); } public void analyse(Project project, SensorContext context) { @@ -79,18 +80,17 @@ that is very different (and does not contain a matching method). protected void collect(Project project, SensorContext context, File reportsDir) { LOG.info("parsing {}", reportsDir); - SUREFIRE_PARSER.collect(project, context, reportsDir); + SurefireParser parser = new SurefireParser(project, fileSystem, resourcePerspectives, context); + parser.collect(reportsDir); } - private static final SurefireParser SUREFIRE_PARSER = new SurefireParser(); - @Override public String toString() { return "Objective-C SurefireSensor"; } private String reportPath() { - String reportPath = conf.getString(REPORT_PATH_KEY); + String reportPath = settings.getString(REPORT_PATH_KEY); if (reportPath == null) { reportPath = DEFAULT_REPORT_PATH; } diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/SurefireStaxHandler.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/SurefireStaxHandler.java new file mode 100644 index 00000000..4dea8147 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/SurefireStaxHandler.java @@ -0,0 +1,139 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.surefire.data; + +import org.apache.commons.lang.StringUtils; +import org.codehaus.staxmate.in.ElementFilter; +import org.codehaus.staxmate.in.SMEvent; +import org.codehaus.staxmate.in.SMHierarchicCursor; +import org.codehaus.staxmate.in.SMInputCursor; +import org.sonar.api.utils.ParsingUtils; +import org.sonar.api.utils.StaxParser.XmlStreamHandler; + +import javax.xml.stream.XMLStreamException; +import java.text.ParseException; +import java.util.Locale; + +public class SurefireStaxHandler implements XmlStreamHandler { + + private final UnitTestIndex index; + + public SurefireStaxHandler(UnitTestIndex index) { + this.index = index; + } + + public void stream(SMHierarchicCursor rootCursor) throws XMLStreamException { + SMInputCursor testSuite = rootCursor.constructDescendantCursor(new ElementFilter("testsuite")); + SMEvent testSuiteEvent; + for (testSuiteEvent = testSuite.getNext(); testSuiteEvent != null; testSuiteEvent = testSuite.getNext()) { + if (testSuiteEvent.compareTo(SMEvent.START_ELEMENT) == 0) { + String testSuiteClassName = testSuite.getAttrValue("name"); + if (StringUtils.contains(testSuiteClassName, "$")) { + // test suites for inner classes are ignored + return; + } + SMInputCursor testCase = testSuite.childCursor(new ElementFilter("testcase")); + SMEvent event; + for (event = testCase.getNext(); event != null; event = testCase.getNext()) { + if (event.compareTo(SMEvent.START_ELEMENT) == 0) { + String testClassName = getClassname(testCase, testSuiteClassName); + UnitTestClassReport classReport = index.index(testClassName); + parseTestCase(testCase, classReport); + } + } + } + } + } + + private static String getClassname(SMInputCursor testCaseCursor, + String defaultClassname) throws XMLStreamException { + String testClassName = testCaseCursor.getAttrValue("classname"); + if (StringUtils.isNotBlank(testClassName) && testClassName.endsWith(")")) { + testClassName = testClassName.substring(0, testClassName.indexOf("(")); + } + return StringUtils.defaultIfBlank(testClassName, defaultClassname); + } + + private static void parseTestCase(SMInputCursor testCaseCursor, + UnitTestClassReport report) throws XMLStreamException { + report.add(parseTestResult(testCaseCursor)); + } + + private static void setStackAndMessage(UnitTestResult result, + SMInputCursor stackAndMessageCursor) throws XMLStreamException { + result.setMessage(stackAndMessageCursor.getAttrValue("message")); + String stack = stackAndMessageCursor.collectDescendantText(); + result.setStackTrace(stack); + } + + private static UnitTestResult parseTestResult(SMInputCursor testCaseCursor) throws XMLStreamException { + UnitTestResult detail = new UnitTestResult(); + String name = getTestCaseName(testCaseCursor); + detail.setName(name); + + String status = UnitTestResult.STATUS_OK; + String time = testCaseCursor.getAttrValue("time"); + Long duration = null; + + SMInputCursor childNode = testCaseCursor.descendantElementCursor(); + if (childNode.getNext() != null) { + String elementName = childNode.getLocalName(); + if ("skipped".equals(elementName)) { + status = UnitTestResult.STATUS_SKIPPED; + // bug with data reporting wrong time for skipped surefire + duration = 0L; + + } else if ("failure".equals(elementName)) { + status = UnitTestResult.STATUS_FAILURE; + setStackAndMessage(detail, childNode); + + } else if ("error".equals(elementName)) { + status = UnitTestResult.STATUS_ERROR; + setStackAndMessage(detail, childNode); + } + } + while (childNode.getNext() != null) { + // make sure we loop till the end of the elements cursor + } + if (duration == null) { + duration = getTimeAttributeInMS(time); + } + detail.setDurationMilliseconds(duration); + detail.setStatus(status); + return detail; + } + + private static long getTimeAttributeInMS(String value) throws XMLStreamException { + // hardcoded to Locale.ENGLISH see http://jira.codehaus.org/browse/SONAR-602 + try { + Double time = ParsingUtils.parseNumber(value, Locale.ENGLISH); + return !Double.isNaN(time) ? (long) ParsingUtils.scaleValue(time * 1000, 3) : 0L; + } catch (ParseException e) { + throw new XMLStreamException(e); + } + } + + private static String getTestCaseName(SMInputCursor testCaseCursor) throws XMLStreamException { + String classname = testCaseCursor.getAttrValue("classname"); + String name = testCaseCursor.getAttrValue("name"); + if (StringUtils.contains(classname, "$")) { + return StringUtils.substringAfter(classname, "$") + "/" + name; + } + return name; + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestClassReport.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestClassReport.java new file mode 100644 index 00000000..a4f886fd --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestClassReport.java @@ -0,0 +1,100 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.surefire.data; + +import com.google.common.collect.Lists; + +import java.util.Collections; +import java.util.List; + +public final class UnitTestClassReport { + private long errors = 0L; + private long failures = 0L; + private long skipped = 0L; + private long tests = 0L; + private long durationMilliseconds = 0L; + + + private long negativeTimeTestNumber = 0L; + private List results = null; + + public UnitTestClassReport add(UnitTestClassReport other) { + for (UnitTestResult otherResult : other.getResults()) { + add(otherResult); + } + return this; + } + + public UnitTestClassReport add(UnitTestResult result) { + initResults(); + results.add(result); + if (result.getStatus().equals(UnitTestResult.STATUS_SKIPPED)) { + skipped += 1; + + } else if (result.getStatus().equals(UnitTestResult.STATUS_FAILURE)) { + failures += 1; + + } else if (result.getStatus().equals(UnitTestResult.STATUS_ERROR)) { + errors += 1; + } + tests += 1; + if (result.getDurationMilliseconds() < 0) { + negativeTimeTestNumber += 1; + } else { + durationMilliseconds += result.getDurationMilliseconds(); + } + return this; + } + + private void initResults() { + if (results == null) { + results = Lists.newArrayList(); + } + } + + public long getErrors() { + return errors; + } + + public long getFailures() { + return failures; + } + + public long getSkipped() { + return skipped; + } + + public long getTests() { + return tests; + } + + public long getDurationMilliseconds() { + return durationMilliseconds; + } + + public long getNegativeTimeTestNumber() { + return negativeTimeTestNumber; + } + + public List getResults() { + if (results == null) { + return Collections.emptyList(); + } + return results; + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestIndex.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestIndex.java new file mode 100644 index 00000000..563cc05f --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestIndex.java @@ -0,0 +1,78 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.surefire.data; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +import java.util.Map; +import java.util.Set; + +/** + * @since 2.8 + */ +public class UnitTestIndex { + + private Map indexByClassname; + + public UnitTestIndex() { + this.indexByClassname = Maps.newHashMap(); + } + + public UnitTestClassReport index(String classname) { + UnitTestClassReport classReport = indexByClassname.get(classname); + if (classReport == null) { + classReport = new UnitTestClassReport(); + indexByClassname.put(classname, classReport); + } + return classReport; + } + + public UnitTestClassReport get(String classname) { + return indexByClassname.get(classname); + } + + public Set getClassnames() { + return Sets.newHashSet(indexByClassname.keySet()); + } + + public Map getIndexByClassname() { + return indexByClassname; + } + + public int size() { + return indexByClassname.size(); + } + + public UnitTestClassReport merge(String classname, String intoClassname) { + UnitTestClassReport from = indexByClassname.get(classname); + if (from!=null) { + UnitTestClassReport to = index(intoClassname); + to.add(from); + indexByClassname.remove(classname); + return to; + } + return null; + } + + public void remove(String classname) { + indexByClassname.remove(classname); + } + + +} \ No newline at end of file diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestResult.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestResult.java new file mode 100644 index 00000000..501a4f21 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/surefire/data/UnitTestResult.java @@ -0,0 +1,84 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.surefire.data; + +public final class UnitTestResult { + public static final String STATUS_OK = "ok"; + public static final String STATUS_ERROR = "error"; + public static final String STATUS_FAILURE = "failure"; + public static final String STATUS_SKIPPED = "skipped"; + + private String name; + private String status; + private String stackTrace; + private String message; + private long durationMilliseconds = 0L; + + public String getName() { + return name; + } + + public UnitTestResult setName(String name) { + this.name = name; + return this; + } + + public String getStatus() { + return status; + } + + public UnitTestResult setStatus(String status) { + this.status = status; + return this; + } + + public String getStackTrace() { + return stackTrace; + } + + public UnitTestResult setStackTrace(String stackTrace) { + this.stackTrace = stackTrace; + return this; + } + + public String getMessage() { + return message; + } + + public UnitTestResult setMessage(String message) { + this.message = message; + return this; + } + + public long getDurationMilliseconds() { + return durationMilliseconds; + } + + public UnitTestResult setDurationMilliseconds(long l) { + this.durationMilliseconds = l; + return this; + } + + public boolean isErrorOrFailure() { + return STATUS_ERROR.equals(status) || STATUS_FAILURE.equals(status); + } + + public boolean isError() { + return STATUS_ERROR.equals(status); + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/ObjectiveCProfile.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/ObjectiveCProfile.java new file mode 100644 index 00000000..43411c0c --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/ObjectiveCProfile.java @@ -0,0 +1,79 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations; + +import com.google.common.io.Closeables; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.ActiveRule; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.plugins.objectivec.violations.oclint.OCLintProfile; +import org.sonar.plugins.objectivec.core.ObjectiveC; +import org.sonar.plugins.objectivec.violations.fauxpas.FauxPasProfile; +import org.sonar.plugins.objectivec.violations.fauxpas.FauxPasProfileImporter; +import org.sonar.plugins.objectivec.violations.oclint.OCLintProfileImporter; + +import java.io.InputStreamReader; +import java.io.Reader; + +public class ObjectiveCProfile extends ProfileDefinition { + + private static final Logger LOGGER = LoggerFactory.getLogger(ObjectiveCProfile.class); + + private final OCLintProfileImporter ocLintProfileImporter; + private final FauxPasProfileImporter fauxPasProfileImporter; + + public ObjectiveCProfile(final OCLintProfileImporter ocLintProfileImporter, final FauxPasProfileImporter fauxPasProfileImporter) { + this.ocLintProfileImporter = ocLintProfileImporter; + this.fauxPasProfileImporter = fauxPasProfileImporter; + } + + @Override + public RulesProfile createProfile(ValidationMessages messages) { + + + LOGGER.info("Creating Objective-C Profile"); + + Reader config = null; + final RulesProfile profile = RulesProfile.create("Objective-C", ObjectiveC.KEY); + profile.setDefaultProfile(true); + + try { + config = new InputStreamReader(getClass().getResourceAsStream(OCLintProfile.PROFILE_PATH)); + RulesProfile ocLintRulesProfile = ocLintProfileImporter.importProfile(config, messages); + for (ActiveRule rule : ocLintRulesProfile.getActiveRules()) { + profile.addActiveRule(rule); + } + + config = new InputStreamReader(getClass().getResourceAsStream(FauxPasProfile.PROFILE_PATH)); + RulesProfile fauxPasRulesProfile = fauxPasProfileImporter.importProfile(config, messages); + for (ActiveRule rule : fauxPasRulesProfile.getActiveRules()) { + profile.addActiveRule(rule); + } + + + return profile; + } finally { + + Closeables.closeQuietly(config); + } + } + +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasProfile.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasProfile.java new file mode 100644 index 00000000..f4a1b1b9 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasProfile.java @@ -0,0 +1,59 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.fauxpas; + +import com.google.common.io.Closeables; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.plugins.objectivec.core.ObjectiveC; + +import java.io.InputStreamReader; +import java.io.Reader; + +public class FauxPasProfile extends ProfileDefinition { + + public static final String PROFILE_PATH = "/org/sonar/plugins/fauxpas/profile-fauxpas.xml"; + private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasProfile.class); + + private final FauxPasProfileImporter profileImporter; + + public FauxPasProfile(final FauxPasProfileImporter importer) { + profileImporter = importer; + } + + @Override + public RulesProfile createProfile(ValidationMessages messages) { + LOGGER.info("Creating FauxPas Profile"); + Reader config = null; + + try { + config = new InputStreamReader(getClass().getResourceAsStream( + PROFILE_PATH)); + final RulesProfile profile = profileImporter.importProfile(config, messages); + profile.setName(FauxPasRulesDefinition.REPOSITORY_KEY); + profile.setLanguage(ObjectiveC.KEY); + + return profile; + } finally { + Closeables.closeQuietly(config); + } + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasProfileImporter.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasProfileImporter.java new file mode 100644 index 00000000..27665f53 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasProfileImporter.java @@ -0,0 +1,55 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.fauxpas; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.profiles.ProfileImporter; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.profiles.XMLProfileParser; +import org.sonar.api.utils.ValidationMessages; +import org.sonar.plugins.objectivec.core.ObjectiveC; + +import java.io.Reader; + +public class FauxPasProfileImporter extends ProfileImporter { + + private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default FauxPas profile"; + private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasProfileImporter.class); + + private final XMLProfileParser profileParser; + + public FauxPasProfileImporter(final XMLProfileParser xmlProfileParser) { + super(FauxPasRulesDefinition.REPOSITORY_KEY, FauxPasRulesDefinition.REPOSITORY_KEY); + setSupportedLanguages(ObjectiveC.KEY); + profileParser = xmlProfileParser; + } + + @Override + public RulesProfile importProfile(Reader reader, ValidationMessages messages) { + + final RulesProfile profile = profileParser.parse(reader, messages); + + if (null == profile) { + messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); + LOGGER.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); + } + + return profile; + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasReportParser.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasReportParser.java new file mode 100644 index 00000000..fc70fbd2 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasReportParser.java @@ -0,0 +1,121 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.fauxpas; + +import org.apache.commons.io.IOUtils; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.issue.Issuable; +import org.sonar.api.issue.Issue; +import org.sonar.api.resources.Project; +import org.sonar.api.rule.RuleKey; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; + +public class FauxPasReportParser { + + private final Project project; + private final SensorContext context; + private final ResourcePerspectives resourcePerspectives; + private final FileSystem fileSystem; + + private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasReportParser.class); + + public FauxPasReportParser(final Project p, final SensorContext c, final ResourcePerspectives resourcePerspectives, final FileSystem fileSystem) { + project = p; + context = c; + this.resourcePerspectives = resourcePerspectives; + this.fileSystem = fileSystem; + } + + public void parseReport(File reportFile) { + + try { + // Read and parse report + FileReader fr = new FileReader(reportFile); + Object reportObj = JSONValue.parse(fr); + IOUtils.closeQuietly(fr); + + // Record violations + if (reportObj != null) { + + JSONObject reportJson = (JSONObject)reportObj; + JSONArray diagnosticsJson = (JSONArray)reportJson.get("diagnostics"); + + for (Object obj : diagnosticsJson) { + recordIssue((JSONObject) obj); + + } + } + + } catch (FileNotFoundException e) { + LOGGER.error("Failed to parse FauxPas report file", e); + } + } + + private void recordIssue(final JSONObject diagnosticJson) { + + String filePath = (String)diagnosticJson.get("file"); + + if (filePath != null) { + + + InputFile inputFile = fileSystem.inputFile(fileSystem.predicates().hasAbsolutePath(filePath)); + Issuable issuable = resourcePerspectives.as(Issuable.class, inputFile); + + if (issuable != null && inputFile != null) { + + JSONObject extent = (JSONObject)diagnosticJson.get("extent"); + JSONObject start = (JSONObject)extent.get("start"); + + String info = (String)diagnosticJson.get("info"); + if (info == null) { + info = (String)diagnosticJson.get("ruleName"); + } + + // Prevent line num 0 case + int lineNum = Integer.parseInt(start.get("line").toString()); + if (lineNum == 0) { + lineNum++; + } + + Issue issue = issuable.newIssueBuilder() + .ruleKey(RuleKey.of(FauxPasRulesDefinition.REPOSITORY_KEY, (String) diagnosticJson.get("ruleShortName"))) + .line(lineNum) + .message(info) + .build(); + + issuable.addIssue(issue); + + + } + + } + + } + +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasRulesDefinition.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasRulesDefinition.java new file mode 100644 index 00000000..948df6a1 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasRulesDefinition.java @@ -0,0 +1,90 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.fauxpas; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.CharEncoding; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.plugins.objectivec.core.ObjectiveC; +import org.sonar.squidbridge.rules.SqaleXmlLoader; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; + +/** + * Created by gillesgrousset on 18/02/2016. + */ +public class FauxPasRulesDefinition implements RulesDefinition { + + private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasRulesDefinition.class); + + public static final String REPOSITORY_KEY = "FauxPas"; + public static final String REPOSITORY_NAME = REPOSITORY_KEY; + + private static final String RULES_FILE = "/org/sonar/plugins/fauxpas/rules.json"; + + @Override + public void define(Context context) { + + NewRepository repository = context + .createRepository(REPOSITORY_KEY, ObjectiveC.KEY) + .setName(REPOSITORY_NAME); + + try { + loadRules(repository); + } catch (IOException e) { + LOGGER.error("Failed to load FauxPas rules", e); + } + + SqaleXmlLoader.load(repository, "/com/sonar/sqale/fauxpas-model.xml"); + + repository.done(); + + } + + private void loadRules(NewRepository repository) throws IOException { + + Reader reader = new BufferedReader(new InputStreamReader(getClass() + .getResourceAsStream(RULES_FILE), CharEncoding.UTF_8)); + + String jsonString = IOUtils.toString(reader); + + Object rulesObj = JSONValue.parse(jsonString); + + if (rulesObj != null) { + JSONArray slRules = (JSONArray)rulesObj; + for (Object obj : slRules) { + JSONObject fpRule = (JSONObject)obj; + + RulesDefinition.NewRule rule = repository.createRule((String)fpRule.get("key")); + rule.setName((String) fpRule.get("name")); + rule.setSeverity((String)fpRule.get("severity")); + rule.setHtmlDescription((String) fpRule.get("description")); + + } + } + + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasSensor.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasSensor.java new file mode 100644 index 00000000..ba68d92e --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/fauxpas/FauxPasSensor.java @@ -0,0 +1,91 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.fauxpas; + +import org.apache.tools.ant.DirectoryScanner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.config.Settings; +import org.sonar.api.resources.Project; +import org.sonar.plugins.objectivec.ObjectiveCPlugin; +import org.sonar.plugins.objectivec.core.ObjectiveC; + +import java.io.File; + +public class FauxPasSensor implements Sensor { + + public static final String REPORT_PATH_KEY = ObjectiveCPlugin.PROPERTY_PREFIX + + ".fauxpas.report"; + public static final String DEFAULT_REPORT_PATH = "sonar-reports/*fauxpas.json"; + + private static final Logger LOGGER = LoggerFactory.getLogger(FauxPasSensor.class); + + private final Settings conf; + private final FileSystem fileSystem; + private final ResourcePerspectives resourcePerspectives; + + public FauxPasSensor(final FileSystem moduleFileSystem, final Settings config, final ResourcePerspectives resourcePerspectives) { + this.conf = config; + this.fileSystem = moduleFileSystem; + this.resourcePerspectives = resourcePerspectives; + } + + @Override + public boolean shouldExecuteOnProject(final Project project) { + + return project.isRoot() && fileSystem.languages().contains(ObjectiveC.KEY); + } + @Override + public void analyse(Project module, SensorContext context) { + + final String projectBaseDir = fileSystem.baseDir().getPath(); + + FauxPasReportParser parser = new FauxPasReportParser(module, context, resourcePerspectives, fileSystem); + parseReportIn(projectBaseDir, parser); + } + + + private void parseReportIn(final String baseDir, final FauxPasReportParser parser) { + + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setIncludes(new String[]{reportPath()}); + scanner.setBasedir(baseDir); + scanner.setCaseSensitive(false); + scanner.scan(); + String[] files = scanner.getIncludedFiles(); + + for(String filename : files) { + LOGGER.info("Processing FauxPas report {}", filename); + parser.parseReport(new File(filename)); + } + + } + + private String reportPath() { + String reportPath = conf.getString(REPORT_PATH_KEY); + if (reportPath == null) { + reportPath = DEFAULT_REPORT_PATH; + } + return reportPath; + } + +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintParser.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintParser.java new file mode 100644 index 00000000..f7d5500f --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintParser.java @@ -0,0 +1,72 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.oclint; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.stream.XMLStreamException; + +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.resources.Project; +import org.sonar.api.utils.StaxParser; + +final class OCLintParser { + + private final Project project; + private final SensorContext context; + private final ResourcePerspectives resourcePerspectives; + private final FileSystem fileSystem; + + public OCLintParser(final Project p, final SensorContext c, final ResourcePerspectives resourcePerspectives, final FileSystem fileSystem) { + project = p; + context = c; + this.resourcePerspectives = resourcePerspectives; + this.fileSystem = fileSystem; + } + + public void parseReport(final File file) { + + try { + final InputStream reportStream = new FileInputStream(file); + parseReport(reportStream); + reportStream.close(); + } catch (final IOException e) { + LoggerFactory.getLogger(getClass()).error("Error processing file named {}", file, e); + } + + } + + public void parseReport(final InputStream inputStream) { + + try { + final StaxParser parser = new StaxParser( + new OCLintXMLStreamHandler(project, context, resourcePerspectives, fileSystem)); + parser.parse(inputStream); + } catch (final XMLStreamException e) { + LoggerFactory.getLogger(getClass()).error( + "Error while parsing XML stream.", e); + } + } + +} diff --git a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintProfile.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintProfile.java similarity index 57% rename from src/main/java/org/sonar/plugins/objectivec/violations/OCLintProfile.java rename to sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintProfile.java index 1e5684d8..f2f67cc7 100644 --- a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintProfile.java +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintProfile.java @@ -1,27 +1,26 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.plugins.objectivec.violations; +package org.sonar.plugins.objectivec.violations.oclint; import java.io.InputStreamReader; import java.io.Reader; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.profiles.ProfileDefinition; import org.sonar.api.profiles.RulesProfile; @@ -32,7 +31,9 @@ public final class OCLintProfile extends ProfileDefinition { - private static final String DEFAULT_PROFILE = "/org/sonar/plugins/oclint/profile-oclint.xml"; + public static final String PROFILE_PATH = "/org/sonar/plugins/oclint/profile-oclint.xml"; + private static final Logger LOGGER = LoggerFactory.getLogger(OCLintProfile.class); + private final OCLintProfileImporter profileImporter; public OCLintProfile(final OCLintProfileImporter importer) { @@ -41,17 +42,16 @@ public OCLintProfile(final OCLintProfileImporter importer) { @Override public RulesProfile createProfile(final ValidationMessages messages) { - LoggerFactory.getLogger(getClass()).info("Creating OCLint Profile"); + LOGGER.info("Creating OCLint Profile"); Reader config = null; try { config = new InputStreamReader(getClass().getResourceAsStream( - DEFAULT_PROFILE)); + PROFILE_PATH)); final RulesProfile profile = profileImporter.importProfile(config, messages); - profile.setName(OCLintRuleRepository.REPOSITORY_KEY); + profile.setName(OCLintRulesDefinition.REPOSITORY_KEY); profile.setLanguage(ObjectiveC.KEY); - profile.setDefaultProfile(true); return profile; } finally { diff --git a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintProfileImporter.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintProfileImporter.java similarity index 59% rename from src/main/java/org/sonar/plugins/objectivec/violations/OCLintProfileImporter.java rename to sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintProfileImporter.java index ba174e58..742d127c 100644 --- a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintProfileImporter.java +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintProfileImporter.java @@ -1,26 +1,25 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . */ -package org.sonar.plugins.objectivec.violations; +package org.sonar.plugins.objectivec.violations.oclint; import java.io.Reader; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.profiles.ProfileImporter; import org.sonar.api.profiles.RulesProfile; @@ -29,12 +28,14 @@ import org.sonar.plugins.objectivec.core.ObjectiveC; public final class OCLintProfileImporter extends ProfileImporter { + private static final String UNABLE_TO_LOAD_DEFAULT_PROFILE = "Unable to load default OCLint profile"; + private static final Logger LOGGER = LoggerFactory.getLogger(OCLintProfileImporter.class); + private final XMLProfileParser profileParser; public OCLintProfileImporter(final XMLProfileParser xmlProfileParser) { - super(OCLintRuleRepository.REPOSITORY_KEY, - OCLintRuleRepository.REPOSITORY_KEY); + super(OCLintRulesDefinition.REPOSITORY_KEY, OCLintRulesDefinition.REPOSITORY_KEY); setSupportedLanguages(ObjectiveC.KEY); profileParser = xmlProfileParser; } @@ -46,8 +47,7 @@ public RulesProfile importProfile(final Reader reader, if (null == profile) { messages.addErrorText(UNABLE_TO_LOAD_DEFAULT_PROFILE); - LoggerFactory.getLogger(OCLintProfileImporter.class).error( - UNABLE_TO_LOAD_DEFAULT_PROFILE); + LOGGER.error(UNABLE_TO_LOAD_DEFAULT_PROFILE); } return profile; diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintRuleSeverity.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintRuleSeverity.java new file mode 100644 index 00000000..16d9fa21 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintRuleSeverity.java @@ -0,0 +1,37 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.oclint; + +/** + * Created by gillesgrousset on 18/02/2016. + */ +public enum OCLintRuleSeverity { + + // Rules are priority + // INFO = 0, MINOR = 1, MAJOR = 2, CRITICAL = 3, BLOCKER = 4 + + INFO, + MINOR, + MAJOR, + CRITICAL, + BLOCKER; + + public static OCLintRuleSeverity valueOfInt(int ordinal) { + return values()[ordinal]; + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintRulesDefinition.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintRulesDefinition.java new file mode 100644 index 00000000..f9cd192c --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintRulesDefinition.java @@ -0,0 +1,150 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.oclint; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.CharEncoding; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.server.rule.RulesDefinition; +import org.sonar.plugins.objectivec.core.ObjectiveC; +import org.sonar.squidbridge.rules.SqaleXmlLoader; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by gillesgrousset on 18/02/2016. + */ +public class OCLintRulesDefinition implements RulesDefinition { + + private static final Logger LOGGER = LoggerFactory.getLogger(OCLintRulesDefinition.class); + + public static final String REPOSITORY_KEY = "OCLint"; + public static final String REPOSITORY_NAME = REPOSITORY_KEY; + + private static final String RULES_FILE = "/org/sonar/plugins/oclint/rules.txt"; + + @Override + public void define(Context context) { + + NewRepository repository = context + .createRepository(REPOSITORY_KEY, ObjectiveC.KEY) + .setName(REPOSITORY_NAME); + + try { + loadRules(repository); + } catch (IOException e) { + LOGGER.error("Failed to load OCLint rules", e); + } + + SqaleXmlLoader.load(repository, "/com/sonar/sqale/oclint-model.xml"); + + repository.done(); + + } + + private void loadRules(NewRepository repository) throws IOException { + + Reader reader = new BufferedReader(new InputStreamReader(getClass() + .getResourceAsStream(RULES_FILE), CharEncoding.UTF_8)); + + final List listLines = IOUtils.readLines(reader); + + String previousLine = null; + Map rule = new HashMap(); + boolean inDescription = false; + for (String line : listLines) { + + if (isLineIgnored(line)) { + inDescription = false; + + } else if (line.matches("[\\-]{4,}.*")) { + LOGGER.debug("Rule found : {}", previousLine); + + // Remove the rule name from the description of the previous + // rule + if (rule.get("description") != null) { + String description = rule.get("description").toString(); + final int index = description.lastIndexOf(previousLine); + if (index > 0) { + rule.put("description", description.substring(0, index)); + } + + } + + rule.clear(); + + rule.put("name", StringUtils.capitalize(previousLine)); + rule.put("key", previousLine); + + + } else if (line.matches("Summary:.*")) { + inDescription = true; + rule.put("description", line.substring(line.indexOf(':') + 1)); + } else if (line.matches("Category:.*")) { + inDescription = true; + + // Create rule when last filed found + RulesDefinition.NewRule newRule = repository.createRule(rule.get("key").toString()); + newRule.setName(rule.get("name").toString()); + newRule.setSeverity(rule.get("severity").toString()); + newRule.setHtmlDescription(rule.get("description").toString()); + + } else if (line.matches("Severity:.*")) { + inDescription = false; + final String severity = line.substring("Severity: ".length()); + rule.put("severity", OCLintRuleSeverity.valueOfInt(Integer.valueOf(severity)).name()); + } else { + if (inDescription) { + line = ruleDescriptionLink(line); + String description = (String)rule.get("description"); + rule.put("description", description + "
" + line); + } + } + + previousLine = line; + } + + } + + private boolean isLineIgnored(String line) { + return line.matches("\\=.*") || line.matches("Priority:.*"); + } + + private String ruleDescriptionLink(final String line) { + String result = line; + final int indexOfLink = line.indexOf("http://"); + if (0 <= indexOfLink) { + final String link = line.substring(indexOfLink); + final StringBuilder htmlText = new StringBuilder(""); + htmlText.append(link); + htmlText.append(""); + result = htmlText.toString(); + } + return result; + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintSensor.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintSensor.java new file mode 100644 index 00000000..13bb0af9 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintSensor.java @@ -0,0 +1,83 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.oclint; + +import java.io.File; + +import org.apache.tools.ant.DirectoryScanner; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.Sensor; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.config.Settings; +import org.sonar.api.resources.Project; +import org.sonar.plugins.objectivec.ObjectiveCPlugin; +import org.sonar.plugins.objectivec.core.ObjectiveC; + +public final class OCLintSensor implements Sensor { + public static final String REPORT_PATH_KEY = ObjectiveCPlugin.PROPERTY_PREFIX + ".oclint.report"; + public static final String DEFAULT_REPORT_PATH = "sonar-reports/*oclint.xml"; + + private final Settings conf; + private final FileSystem fileSystem; + private final ResourcePerspectives resourcePerspectives; + + public OCLintSensor(final FileSystem fileSystem, final Settings config, final ResourcePerspectives resourcePerspectives) { + this.conf = config; + this.fileSystem = fileSystem; + this.resourcePerspectives = resourcePerspectives; + } + + public boolean shouldExecuteOnProject(final Project project) { + + return project.isRoot() && fileSystem.languages().contains(ObjectiveC.KEY); + + } + + public void analyse(final Project project, final SensorContext context) { + final String projectBaseDir = fileSystem.baseDir().getPath(); + final OCLintParser parser = new OCLintParser(project, context, resourcePerspectives, fileSystem); + + parseReportIn(projectBaseDir, parser); + + } + + private void parseReportIn(final String baseDir, final OCLintParser parser) { + + DirectoryScanner scanner = new DirectoryScanner(); + scanner.setIncludes(new String[]{reportPath()}); + scanner.setBasedir(baseDir); + scanner.setCaseSensitive(false); + scanner.scan(); + String[] files = scanner.getIncludedFiles(); + + for(String filename : files) { + LoggerFactory.getLogger(getClass()).info("Processing OCLint report {}", filename); + parser.parseReport(new File(filename)); + } + } + + private String reportPath() { + String reportPath = conf.getString(REPORT_PATH_KEY); + if (reportPath == null) { + reportPath = DEFAULT_REPORT_PATH; + } + return reportPath; + } +} diff --git a/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintXMLStreamHandler.java b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintXMLStreamHandler.java new file mode 100644 index 00000000..28c51030 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/java/org/sonar/plugins/objectivec/violations/oclint/OCLintXMLStreamHandler.java @@ -0,0 +1,112 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.violations.oclint; + +import java.io.File; + +import javax.xml.stream.XMLStreamException; + +import org.codehaus.staxmate.in.SMHierarchicCursor; +import org.codehaus.staxmate.in.SMInputCursor; +import org.slf4j.LoggerFactory; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.component.ResourcePerspectives; +import org.sonar.api.issue.Issuable; +import org.sonar.api.issue.Issue; +import org.sonar.api.resources.Project; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.utils.StaxParser.XmlStreamHandler; + +final class OCLintXMLStreamHandler implements XmlStreamHandler { + private static final int PMD_MINIMUM_PRIORITY = 5; + private final Project project; + private final SensorContext context; + private final ResourcePerspectives resourcePerspectives; + private final FileSystem fileSystem; + + public OCLintXMLStreamHandler(final Project p, final SensorContext c, final ResourcePerspectives resourcePerspectives, final FileSystem fileSystem) { + project = p; + context = c; + this.resourcePerspectives = resourcePerspectives; + this.fileSystem = fileSystem; + } + + public void stream(final SMHierarchicCursor rootCursor) throws XMLStreamException { + + final SMInputCursor file = rootCursor.advance().childElementCursor("file"); + while (null != file.getNext()) { + collectIssuesFor(file); + } + } + + private void collectIssuesFor(final SMInputCursor file) throws XMLStreamException { + + final String filePath = file.getAttrValue("name"); + LoggerFactory.getLogger(getClass()).debug("Collection violations for {}", filePath); + final InputFile inputFile = findResource(filePath); + if (fileExists(inputFile)) { + LoggerFactory.getLogger(getClass()).debug("File {} was found in the project.", filePath); + collectFileIssues(inputFile, file); + } + } + + private void collectFileIssues(final InputFile inputFile, final SMInputCursor file) throws XMLStreamException { + + final SMInputCursor line = file.childElementCursor("violation"); + + while (null != line.getNext()) { + recordViolation(inputFile, line); + } + } + + private InputFile findResource(final String filePath) { + + File file = new File(filePath); + return fileSystem.inputFile(fileSystem.predicates().hasAbsolutePath(file.getAbsolutePath())); + + } + + private void recordViolation(InputFile inputFile, final SMInputCursor line) throws XMLStreamException { + + Issuable issuable = resourcePerspectives.as(Issuable.class, inputFile); + + if (issuable != null) { + + Issue issue = issuable.newIssueBuilder() + .ruleKey(RuleKey.of(OCLintRulesDefinition.REPOSITORY_KEY, line.getAttrValue("rule"))) + .line(Integer.valueOf(line.getAttrValue("beginline"))) + .message(line.getElemStringValue()) + .build(); + + issuable.addIssue(issue); + + + } + } + + private boolean fileExists(InputFile file) { + if (file == null) { + return false; + } + + return context.getResource(file) != null; + } + +} diff --git a/sonar-objective-c-plugin/src/main/resources/com/sonar/sqale/fauxpas-model.xml b/sonar-objective-c-plugin/src/main/resources/com/sonar/sqale/fauxpas-model.xml new file mode 100644 index 00000000..0531ccea --- /dev/null +++ b/sonar-objective-c-plugin/src/main/resources/com/sonar/sqale/fauxpas-model.xml @@ -0,0 +1,1613 @@ + + + REUSABILITY + Reusability + + MODULARITY + Modularity + + + TRANSPORTABILITY + Transportability + + FauxPas + AbsPathInBuildSetting + + remediationFunction + linear + + + remediationFactor + 30 + mn + + + offset + 0.0 + d + + + + FauxPas + FileRefWithAbsPath + + remediationFunction + linear + + + remediationFactor + 30 + mn + + + offset + 0.0 + d + + + + FauxPas + StringsFileEncoding + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + FileRefOutsideVCS + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + FileRefIgnoredInVCS + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + + PORTABILITY + Portability + + COMPILER_RELATED_PORTABILITY + Compiler + + + HARDWARE_RELATED_PORTABILITY + Hardware + + + LANGUAGE_RELATED_PORTABILITY + Language + + FauxPas + HardcodedUIString + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + FixedFormatDateFormatter + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + OS_RELATED_PORTABILITY + OS + + FauxPas + APIAvailability + + remediationFunction + linear + + + remediationFactor + 30 + mn + + + offset + 0.0 + d + + + + + SOFTWARE_RELATED_PORTABILITY + Software + + + TIME_ZONE_RELATED_PORTABILITY + Time zone + + + + MAINTAINABILITY + Maintainability + + READABILITY + Readability + + FauxPas + SourceFileHeaderComment + + remediationFunction + CONSTANT_ISSUE + + + offset + 5 + min + + + + FauxPas + Spelling + + remediationFunction + CONSTANT_ISSUE + + + offset + 5 + min + + + + FauxPas + SuspiciousDateTimeFormat + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + RecommendedVCSIgnores + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnidiomaticAccessorNaming + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + IBOutletsInPublicInterface + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + PrivateCategory + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + PrefixHeaderIncludeSuggestion + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnusedErrorValue + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ArgumentModification + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + MacroBasedIncludeGuard + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + OldVerboseObjCSyntax + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + UNDERSTANDABILITY + Understandability + + FauxPas + CyclomaticComplexity + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + MissingAPIUsageDescription + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + + SECURITY + Security + + API_ABUSE + API abuse + + + ERRORS + Errors + + + INPUT_VALIDATION_AND_REPRESENTATION + Input validation and representation + + + SECURITY_FEATURES + Security features + + + + EFFICIENCY + Efficiency + + MEMORY_EFFICIENCY + Memory use + + FauxPas + StrongDelegate + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + LoadMethodWithoutAutoreleasePool + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UndetachedDelegate + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + MallocWithoutSizeof + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + BlockAPIRetainCycle + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + CPU_EFFICIENCY + Processor use + + FauxPas + NSLogUsed + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + + CHANGEABILITY + Changeability + + ARCHITECTURE_CHANGEABILITY + Architecture + + + DATA_CHANGEABILITY + Data + + + LOGIC_CHANGEABILITY + Logic + + + + RELIABILITY + Reliability + + ARCHITECTURE_RELIABILITY + Architecture + + + DATA_RELIABILITY + Data + + + EXCEPTION_HANDLING + Exception handling + + + FAULT_TOLERANCE + Fault tolerance + + + INSTRUCTION_RELIABILITY + Instruction + + FauxPas + ViewLayoutInXIB + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + FauxPas + CompleteNotificationCenterDetachment + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + AssociatedObjectOnValueType + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + HardcodedSelfClass + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + CategoryMethodConflict + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ZeroAssignmentToPointer + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + OrderedPointerToZeroComparison + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnnecessaryNibMethod + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnsupportedWeakReference + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UsedVariableMarkedUnused + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ReservedPrefix + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + MallocCast + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ReservedIdentifierNaming + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnusedMethod + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnnecessaryNullCheck + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + MacroLiteral + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + IdentifierNaming + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + DotSyntax + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnprefixedClass + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + NonTypedefBlockDeclaration + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + NewInitializer + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ThrowingObjCException + + remediationFunction + CONSTANT_ISSUE + + + offset + 30 + min + + + + FauxPas + OrderedComparisonOpDirection + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + StrongInsteadOfRetain + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + NullCoalescingOp + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + MissingNotificationCenterDetachment + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + LiteralStringKeyPath + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + IsEqualAndHash + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + RestrictedMethodOverride + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + RestrictedDirectMethodCall + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UIKitKVO + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + DylibInstallName + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ReleaseBuildConfig + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + BuildSettingPlacement + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + BuildSettingSelfReference + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + XcconfigOverwrites + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ReleaseBuildCompilerArgs + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ImplicitBundleId + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + BasicProjectSettings + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + CompilerWarnings + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + BuildSettingsSetInGUI + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ViewControllerInitWithNibName + + remediationFunction + CONSTANT_ISSUE + + + offset + 30 + min + + + + FauxPas + UnprefixedCategoryMethod + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + RedundantInclude + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ErrorConditionCheck + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + DiscardedOpaqueNotificationObserver + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + Swizzling + + remediationFunction + CONSTANT_ISSUE + + + offset + 30 + min + + + + FauxPas + AssigningDelegate + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ImplicitAtomicProperty + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + InitializeMethodCategoryOverride + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + TerminatingApp + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + InstanceMethodWritesToStaticVariable + + remediationFunction + CONSTANT_ISSUE + + + offset + 30 + min + + + + FauxPas + FastEnumElementOutside + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + SetterInvocationInInitOrDealloc + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + CopyingMutableProperty + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + ConstructorReturnType + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + RetainingImmutableProperty + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + InitializeSuperInvocation + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + AssertionSideEffects + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + LOGIC_RELIABILITY + Logic + + FauxPas + DefaultInExhaustiveSwitch + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + RESOURCE_RELIABILITY + Resource + + FauxPas + UncommentedLocalizedString + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + TranslationFormatMismatch + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + TranslationPunctuation + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + DuplicateTranslation + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + MissingTranslation + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + StringsdictWithoutStrings + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnusedTranslation + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + InvalidStringsFile + + remediationFunction + CONSTANT_ISSUE + + + offset + 30 + min + + + + FauxPas + RetinaImagesResolution + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + SuspiciousResources + + remediationFunction + CONSTANT_ISSUE + + + offset + 30 + min + + + + FauxPas + UnknownResourceCodeReference + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnusedResource + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + XIBUnknownClassReference + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + XIBRuntimeAttributeMismatch + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + MissingDeviceTypeResource + + remediationFunction + CONSTANT_ISSUE + + + offset + 30 + min + + + + FauxPas + MissingImageResolutionVariant + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + WeakReferenceToTopLevelXIBObject + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnknownResourceXIBReference + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + GlobalAndLocalizedResource + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + UnknownResourceModifier + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + SuspiciousMissingResources + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + FauxPas + DuplicateResource + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + + SYNCHRONIZATION_RELIABILITY + Synchronization + + FauxPas + ThreadUnsafeInstanceCaching + + remediationFunction + CONSTANT_ISSUE + + + offset + 1 + h + + + + + UNIT_TESTS + Unit tests coverage + + + + TESTABILITY + Testability + + INTEGRATION_TESTABILITY + Integration level + + + UNIT_TESTABILITY + Unit level + + + \ No newline at end of file diff --git a/src/main/resources/com/sonar/sqale/objectivec-model.xml b/sonar-objective-c-plugin/src/main/resources/com/sonar/sqale/oclint-model.xml old mode 100644 new mode 100755 similarity index 63% rename from src/main/resources/com/sonar/sqale/objectivec-model.xml rename to sonar-objective-c-plugin/src/main/resources/com/sonar/sqale/oclint-model.xml index 42c209fb..59ec3e95 --- a/src/main/resources/com/sonar/sqale/objectivec-model.xml +++ b/sonar-objective-c-plugin/src/main/resources/com/sonar/sqale/oclint-model.xml @@ -50,17 +50,12 @@ unused method parameter remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -68,53 +63,38 @@ unused local variable remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min OCLint - replace with number literal + use number literal remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min OCLint - replace with boxed expression + use boxed expression remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -122,17 +102,25 @@ unnecessary else statement remediationFunction - linear + CONSTANT_ISSUE - remediationFactor + offset 10 - mn + min + + + + OCLint + unnecessary null check for dealloc + + remediationFunction + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -140,17 +128,12 @@ redundant local variable remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -158,17 +141,12 @@ redundant if statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -176,35 +154,25 @@ redundant conditional operator remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min OCLint - replace with container literal + use container literal remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -212,17 +180,12 @@ long line remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -230,17 +193,12 @@ long method remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -248,17 +206,12 @@ for loop should be while loop remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -266,71 +219,51 @@ too many methods remediationFunction - linear + CONSTANT_ISSUE - remediationFactor + offset 1 h - - offset - 0.0 - d - OCLint long class remediationFunction - linear + CONSTANT_ISSUE - remediationFactor + offset 1 h - - offset - 0.0 - d - OCLint too many fields remediationFunction - linear + CONSTANT_ISSUE - remediationFactor + offset 1 h - - offset - 0.0 - d - OCLint collapsible if statements remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -338,17 +271,12 @@ deep nested block remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -356,17 +284,12 @@ high cyclomatic complexity remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -374,17 +297,12 @@ too few branches in switch statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -392,17 +310,12 @@ non case label in switch statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -410,17 +323,12 @@ short variable name remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -428,53 +336,51 @@ long variable name remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min OCLint - default label not last in switch statement + ill-placed default label in switch statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min OCLint - replace with object subscripting + unnecessary default statement in covered switch statement remediationFunction - linear + CONSTANT_ISSUE - remediationFactor + offset 10 - mn + min + + + + OCLint + use object subscripting + + remediationFunction + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -486,35 +392,25 @@ useless parentheses remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min OCLint - use early exits and continue + prefer early exits and continue remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -522,17 +418,12 @@ high npath complexity remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -540,17 +431,12 @@ inverted logic remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -558,17 +444,12 @@ multiple unary operator remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -576,17 +457,12 @@ redundant nil check remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -594,17 +470,12 @@ high ncss method remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -612,17 +483,12 @@ dead code remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -630,17 +496,12 @@ double negative remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -648,17 +509,12 @@ bitwise operator in conditional remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -666,17 +522,12 @@ empty if statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -684,17 +535,12 @@ empty while statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -702,17 +548,12 @@ empty else block remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -720,17 +561,12 @@ empty for statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -738,17 +574,12 @@ empty do/while statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -756,17 +587,12 @@ empty switch statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -774,17 +600,12 @@ too many parameters remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -792,17 +613,12 @@ switch statements don't need default when fully covered remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -813,6 +629,19 @@ API_ABUSE API abuse + + OCLint + calling prohibited method + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + ERRORS @@ -874,17 +703,12 @@ empty finally statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -892,17 +716,12 @@ return from finally block remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -910,17 +729,12 @@ empty catch statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -928,17 +742,12 @@ empty try statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -946,17 +755,12 @@ throw exception from finally block remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -972,35 +776,77 @@ must override hash with isEqual remediationFunction - linear + CONSTANT_ISSUE - remediationFactor - 10 - mn + offset + 5 + min + + + + OCLint + calling protected method + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + OCLint + missing abstract method implementation + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + + + OCLint + missing hash method + + remediationFunction + CONSTANT_ISSUE offset - 0.0 - d + 10 + min + + OCLint + missing call to base method + + remediationFunction + CONSTANT_ISSUE + + + offset + 10 + min + + OCLint parameter reassignment remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -1008,17 +854,12 @@ ivar assignment outside accessors or init remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1030,17 +871,12 @@ missing break in switch statement remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1048,35 +884,25 @@ avoid branching statement as last in loop remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min OCLint - switch statements should have default + missing default in switch statements remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1084,17 +910,12 @@ jumbled incrementer remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1102,17 +923,12 @@ broken null check remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1120,17 +936,12 @@ broken nil check remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1138,17 +949,12 @@ broken oddness check remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1156,17 +962,12 @@ misplaced nil check remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1174,17 +975,12 @@ misplaced null check remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1192,17 +988,12 @@ goto statement remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -1210,17 +1001,12 @@ goto statement remediationFunction - linear - - - remediationFactor - 30 - mn + CONSTANT_ISSUE offset - 0.0 - d + 30 + min @@ -1228,17 +1014,12 @@ constant if expression remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min @@ -1246,33 +1027,24 @@ constant conditional operator remediationFunction - linear - - - remediationFactor - 10 - mn + CONSTANT_ISSUE offset - 0.0 - d + 10 + min RESOURCE_RELIABILITY Resource - - - SYNCHRONIZATION_RELIABILITY - Synchronization - UNIT_TESTS Unit tests coverage + TESTABILITY Testability @@ -1285,4 +1057,4 @@ Unit level - \ No newline at end of file + diff --git a/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/fauxpas/profile-fauxpas.xml b/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/fauxpas/profile-fauxpas.xml new file mode 100644 index 00000000..e5b16df1 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/fauxpas/profile-fauxpas.xml @@ -0,0 +1,451 @@ + + + FauxPas + objc + + + FauxPas + UndetachedDelegate + + + FauxPas + MallocWithoutSizeof + + + FauxPas + AssertionSideEffects + + + FauxPas + LoadMethodWithoutAutoreleasePool + + + FauxPas + InitializeSuperInvocation + + + FauxPas + HardcodedSelfClass + + + FauxPas + MacroBasedIncludeGuard + + + FauxPas + RetainingImmutableProperty + + + FauxPas + CompleteNotificationCenterDetachment + + + FauxPas + OldVerboseObjCSyntax + + + FauxPas + StrongDelegate + + + FauxPas + ConstructorReturnType + + + FauxPas + SetterInvocationInInitOrDealloc + + + FauxPas + ArgumentModification + + + FauxPas + FastEnumElementOutside + + + FauxPas + UnusedErrorValue + + + FauxPas + CopyingMutableProperty + + + FauxPas + InstanceMethodWritesToStaticVariable + + + FauxPas + AssociatedObjectOnValueType + + + FauxPas + PrefixHeaderIncludeSuggestion + + + FauxPas + TerminatingApp + + + FauxPas + PrivateCategory + + + FauxPas + IBOutletsInPublicInterface + + + FauxPas + InitializeMethodCategoryOverride + + + FauxPas + ImplicitAtomicProperty + + + FauxPas + AssigningDelegate + + + FauxPas + Swizzling + + + FauxPas + DiscardedOpaqueNotificationObserver + + + FauxPas + ErrorConditionCheck + + + FauxPas + RedundantInclude + + + FauxPas + NSLogUsed + + + FauxPas + UnprefixedCategoryMethod + + + FauxPas + UnidiomaticAccessorNaming + + + FauxPas + ViewControllerInitWithNibName + + + FauxPas + RetinaImagesResolution + + + FauxPas + SuspiciousResources + + + FauxPas + UnknownResourceCodeReference + + + FauxPas + UnusedResource + + + FauxPas + XIBUnknownClassReference + + + FauxPas + XIBRuntimeAttributeMismatch + + + FauxPas + MissingDeviceTypeResource + + + FauxPas + MissingImageResolutionVariant + + + FauxPas + WeakReferenceToTopLevelXIBObject + + + FauxPas + UnknownResourceXIBReference + + + FauxPas + GlobalAndLocalizedResource + + + FauxPas + UnknownResourceModifier + + + FauxPas + SuspiciousMissingResources + + + FauxPas + DuplicateResource + + + FauxPas + BuildSettingsSetInGUI + + + FauxPas + CompilerWarnings + + + FauxPas + MissingAPIUsageDescription + + + FauxPas + ViewLayoutInXIB + + + FauxPas + BasicProjectSettings + + + FauxPas + ImplicitBundleId + + + FauxPas + ReleaseBuildCompilerArgs + + + FauxPas + XcconfigOverwrites + + + FauxPas + BuildSettingSelfReference + + + FauxPas + BuildSettingPlacement + + + FauxPas + AbsPathInBuildSetting + + + FauxPas + FileRefWithAbsPath + + + FauxPas + ReleaseBuildConfig + + + FauxPas + DylibInstallName + + + FauxPas + InvalidStringsFile + + + FauxPas + UnusedTranslation + + + FauxPas + StringsdictWithoutStrings + + + FauxPas + HardcodedUIString + + + FauxPas + MissingTranslation + + + FauxPas + DuplicateTranslation + + + FauxPas + TranslationPunctuation + + + FauxPas + TranslationFormatMismatch + + + FauxPas + UncommentedLocalizedString + + + FauxPas + UIKitKVO + + + FauxPas + APIAvailability + + + FauxPas + RestrictedDirectMethodCall + + + FauxPas + RestrictedMethodOverride + + + FauxPas + IsEqualAndHash + + + FauxPas + LiteralStringKeyPath + + + FauxPas + FixedFormatDateFormatter + + + FauxPas + SuspiciousDateTimeFormat + + + FauxPas + BlockAPIRetainCycle + + + FauxPas + MissingNotificationCenterDetachment + + + FauxPas + StringsFileEncoding + + + FauxPas + RecommendedVCSIgnores + + + FauxPas + FileRefOutsideVCS + + + FauxPas + FileRefIgnoredInVCS + + + FauxPas + StrongInsteadOfRetain + + + FauxPas + NullCoalescingOp + + + FauxPas + OrderedComparisonOpDirection + + + FauxPas + ThrowingObjCException + + + FauxPas + NewInitializer + + + FauxPas + NonTypedefBlockDeclaration + + + FauxPas + Spelling + + + FauxPas + SourceFileHeaderComment + + + FauxPas + UnprefixedClass + + + FauxPas + DotSyntax + + + FauxPas + IdentifierNaming + + + FauxPas + MacroLiteral + + + FauxPas + UnnecessaryNullCheck + + + FauxPas + UnusedMethod + + + FauxPas + ReservedIdentifierNaming + + + FauxPas + CyclomaticComplexity + + + FauxPas + DefaultInExhaustiveSwitch + + + FauxPas + MallocCast + + + FauxPas + ReservedPrefix + + + FauxPas + UsedVariableMarkedUnused + + + FauxPas + UnsupportedWeakReference + + + FauxPas + ThreadUnsafeInstanceCaching + + + FauxPas + UnnecessaryNibMethod + + + FauxPas + OrderedPointerToZeroComparison + + + FauxPas + ZeroAssignmentToPointer + + + FauxPas + CategoryMethodConflict + + + \ No newline at end of file diff --git a/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/fauxpas/rules.json b/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/fauxpas/rules.json new file mode 100644 index 00000000..b0329645 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/fauxpas/rules.json @@ -0,0 +1,779 @@ +[ + { + "category": "BestPractice", + "key": "UndetachedDelegate", + "name": "Undetached delegate or data source", + "description": "When an object sets itself as the delegate or data source of one of its members, it must detach that reference in its -[NSObject dealloc] method.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "MallocWithoutSizeof", + "name": "Memory allocation without using sizeof", + "description": "The sizeof operator should be used to obtain the correct size for any allocated structure or variable \u2014 the sizes of some data types vary between the 32-bit and 64-bit runtimes.This rule is na\u00efve and may produce false positives in many cases.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "AssertionSideEffects", + "name": "Potential assertion side effects", + "description": "Warns if assertion macro bodies contain invocations of non-getter methods or functions.Assertions should not have side effects because they are normally disabled in release builds \u2014 the program\u2019s behavior should not be dependent on whether assertions are enabled or not.This rule considers only Foundation assertion macros.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "LoadMethodWithoutAutoreleasePool", + "name": "+[NSObject load] method without an @autoreleasepool", + "description": "When the +[NSObject load] method is executed, there may not be an autorelease pool in place, so you must set one up yourself.This only applies to iOS 5 (and earlier) and OS X 10.7 (and earlier).", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "InitializeSuperInvocation", + "name": "Invocation of superclass implementation of +[NSObject initialize]", + "description": "Implementations of +[NSObject initialize] should not invoke the superclass implementation: this method is special in that the runtime invokes it separately for every subclass.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "HardcodedSelfClass", + "name": "Hardcoded self class reference", + "description": "Warns if an Objective-C class (or an instance of a class) sends a message to its own class object using a hardcoded reference to the class, e.g. [FOOThing alloc].It is recommended to use self instead (e.g. [self alloc] or [[self class] alloc]) so that the concrete class would receive the message, and subclassing behavior would not be impeded.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "MacroBasedIncludeGuard", + "name": "Macro-based include guard", + "description": "Simplify the header by replacing the macro definition check -based include guard with the \u2018once\u2019 pragma.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "RetainingImmutableProperty", + "name": "Non-copying property of immutable NSCopying type", + "description": "Warns if \u201cretaining\u201d semantics are specified in a @property declaration for a common immutable NSCopying class type that also has a mutable subclass variant (for example NSString).This rule helps avoid situations where the value of a property could change without the setter being invoked (i.e. the object gets mutated).", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "CompleteNotificationCenterDetachment", + "name": "Complete NSNotificationCenter detachment", + "description": "Warns when an object removes itself as an observer to all notifications (by invoking -[NSNotificationCenter removeObserver:] with self).This can be a problem if a superclass or a subclass wants to keep observing some notifications. The recommended way to handle this is to remove self as an observer only for the specific notifications that you have previously begun observing.This rule does not warn about such removals occuring in -dealloc.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "OldVerboseObjCSyntax", + "name": "Old, verbose Objective-C syntax", + "description": "Warns if Objective-C literals, boxed expressions and subscript notation are not used whenever possible.Note that Xcode can automatically fix your code to do this (see the Edit \u2192 Refactor \u2192 Convert To Modern Objective-C Syntax\u2026 menu item).", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "StrongDelegate", + "name": "Retaining or copying delegate", + "description": "To avoid retain cycles, delegate setter methods should not retain or copy the delegate object.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "ConstructorReturnType", + "name": "Constructor return type", + "description": "Warns if an init or factory method return type is anything other than instancetype.Properly specifying the return type for factory methods (e.g. +[NSArray arrayWithObject:]) allows the compiler to perform more type checking, which helps catch bugs. Even though the compiler automatically determines the return types of init methods (even if they are declared as id) it is still good to be explicit and use instancetype.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "SetterInvocationInInitOrDealloc", + "name": "Setter invocation in init or dealloc method", + "description": "It is recommended to avoid invoking setter methods on self in init methods, or in -[NSObject dealloc]. Doing so might trigger KVC notifications, which others might observe, and expect the object to be in a valid, consistent state.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "ArgumentModification", + "name": "Modifying the value of an argument variable", + "description": "Argument variable values should not be modified directly \u2014 code is easier to follow if you can always trust that argument variable values do not change.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "FastEnumElementOutside", + "name": "Element variable of fast enumeration loop declared outside the loop", + "description": "The element variable of a fast enumeration loop should not be used for anything other than holding the loop iteration element, so it follows that there is no reason for the variable to be visible outside the loop.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "UnusedErrorValue", + "name": "Unused error value", + "description": "Warns when NSError or CFErrorRef variable values are never used.If you are not interested in the error return value of a method or function, pass NULL for the error argument.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "CopyingMutableProperty", + "name": "Copying property of mutable NSCopying type", + "description": "Warns if \u201ccopying\u201d semantics are specified in a @property declaration for a common mutable NSCopying class type that has an immutable superclass (for example NSMutableArray).Invoking -[NSCopying copy] for such objects will in many cases return an immutable copy. This means that after assigning a mutable object value to such a property, it may in fact get an immutable copy of the assigned value (which will lead to crashes as soon as any attempt is made to mutate this immutable object).", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "InstanceMethodWritesToStaticVariable", + "name": "Instance method writes to static variable", + "description": "Writing to static variables (which is essentially global state) in instance methods is generally considered bad practice, because it easily leads to undesireable behavior when multiple instances are being manipulated.Warnings are suppressed for assignments occurring inside dispatch_once() blocks.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "AssociatedObjectOnValueType", + "name": "Associated object on value-like type", + "description": "Warns when associated objects are attached to value-like types such as NSNumber or UIFont.Instances of these classes may be shared and/or immortal due to de-duplication and tagged pointers.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "PrefixHeaderIncludeSuggestion", + "name": "Moving common inclusions into prefix header", + "description": "Moving commonly used header inclusion directives into a precompiled prefix header improves compilation time.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "TerminatingApp", + "name": "Terminating the app in a release build", + "description": "The iOS Human Interface Guidelines say that you should never quit an iOS app programmatically.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "PrivateCategory", + "name": "Category used for \u201cprivate\u201d declarations", + "description": "A class extension should be used instead, because they enable compiler warnings for detecting unimplemented methods.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "IBOutletsInPublicInterface", + "name": "IBOutlets in public interface", + "description": "IBOutlets are often private implementation details, and should thus be in a private class extension.This rule warns only about cases where the class is the \u201cFile\u2019s Owner\u201d of a XIB whose basename is the same as the class name, and that contains a connection to the outlet.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "InitializeMethodCategoryOverride", + "name": "Overridden +[NSObject initialize] method in a category", + "description": "The +[NSObject initialize] method should not be overridden in categories, because this will prevent the original implementation from being executed. In many cases, +[NSObject load] may be used instead \u2014 it will be executed separately for classes and categories.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "ImplicitAtomicProperty", + "name": "Implicitly atomic property", + "description": "Warns for implicitly atomic properties.If neither the atomic keyword nor the nonatomic keyword is specified, a property is synthesized as atomic by default.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "AssigningDelegate", + "name": "Assigning delegate property", + "description": "Delegate properties should be declared weak instead of assign. Weak references are safer because they become nil when the referenced object is deallocated.This rule only applies to code compiled with Automatic Reference Counting (ARC).", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "Swizzling", + "name": "Method swizzling", + "description": "Warns whenever there are calls to Objective-C runtime API functions that are used to change method implementations.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "DiscardedOpaqueNotificationObserver", + "name": "Discarded opaque NSNotificationCenter observer", + "description": "Warns if the return value of -[NSNotificationCenter addObserverForName:object:queue:usingBlock:] is not stored anywhere. This method returns an opaque observer object that is needed in order to stop observing.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "ErrorConditionCheck", + "name": "Fragile error condition check", + "description": "Methods that pass back NSError objects by reference return NO or nil to indicate an error condition. This rule warns if the NSError pointer is checked against nil without checking the return value.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "RedundantInclude", + "name": "Redundant inclusion directive", + "description": "If a header is included in the project\u2019s prefix header, it needn\u2019t be included anywhere else.This rule does not check header files that are themselves included in the precompiled prefix header.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "NSLogUsed", + "name": "NSLog() used in release build", + "description": "Logging should be disabled in release builds (except perhaps for fatal errors).", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "UnprefixedCategoryMethod", + "name": "Unprefixed category method", + "description": "Category methods on system classes must be prefixed in order to avoid name collisions.By default, this rule considers a method name prefixed if it begins with at least three lowercase characters (or the lowercase version of the \u2018Class Prefix\u2019 configured for the project), followed by an underscore.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "UnidiomaticAccessorNaming", + "name": "Unidiomatic accessor naming", + "description": "Warns if getter methods are named in the form getSomething instead of something.", + "severity": "MAJOR" + }, + { + "category": "BestPractice", + "key": "ViewControllerInitWithNibName", + "name": "Using -[UIViewController initWithNibName:bundle:] outside the UIViewController implementation", + "description": "It is not advisable to use -[UIViewController initWithNibName:bundle:] to instantiate UIViewController subclasses outside of the subclass implementation itself. This breaks encapsulation (the subclass should be the one to decide which NIB to use) and makes it more likely that a typo in the NIB name string will crash the app during runtime.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "RetinaImagesResolution", + "name": "Unexpected retina image resolution", + "description": "The retina (\u2018@2x\u2019 or \u2018@3x\u2019) version of an image resource must be exactly double or triple the size of the corresponding low-resolution image (assuming the point size of the presentation context remains the same regardless of screen resolution). Otherwise the effective resolution of the image will not match the effective resolution of its presentation context, which will lead to a blurry image, empty space at the edges, or overflow.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "SuspiciousResources", + "name": "Suspicious bundle resources", + "description": "Some files that are part of the project but only needed at build/development time (e.g. Xcode build configuration (.xcconfig) files) may be added as bundle resources by mistake.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "UnknownResourceCodeReference", + "name": "Code refers to unknown resource", + "description": "Resources loaded from disk at runtime should be included in the bundle resources under the correct path. Remember that unlike most Macs (and thus iOS simulators run on those Macs), iOS devices have a case sensitive filesystem.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "UnusedResource", + "name": "Possibly unused resource", + "description": "Warns about resource files that do not seem to be referred to in code or XIBs.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "XIBUnknownClassReference", + "name": "XIB Reference to unknown class", + "description": "Warns if an Interface Builder file refers to an unknown Objective-C class.This rule will warn about all references to classes that are not declared in the source code files that Faux Pas checks, or exported in linked libraries.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "XIBRuntimeAttributeMismatch", + "name": "XIB User-defined runtime attribute mismatch", + "description": "Warns when a XIB specifies user-defined runtime attributes that don\u2019t match the source code of the associated class.A key path that doesn\u2019t match any of the class properties or setter methods yields a diagnostic, as does a mismatch in the type of the assigned value and the value type declared for the property or setter.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "MissingDeviceTypeResource", + "name": "Missing device type resource", + "description": "Warns if a device type is not covered by the variants of a resource file. E.g. if image~iphone.png exists but image~ipad.png does not.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "MissingImageResolutionVariant", + "name": "Missing image resolution variant", + "description": "Warns when either the high-resolution (@2x or @3x) or the low-resolution variant of an image resource is missing.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "WeakReferenceToTopLevelXIBObject", + "name": "Weak reference to top-level XIB object", + "description": "IBOutlet references to top-level objects in XIBs should be strong, so as to ensure that the object is not deallocated prematurely.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "UnknownResourceXIBReference", + "name": "XIB refers to unknown resource", + "description": "Resources loaded from disk at runtime should be included in the bundle resources under the correct path. Remember that unlike most Macs (and thus iOS simulators run on those Macs), iOS devices have a case sensitive filesystem.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "GlobalAndLocalizedResource", + "name": "Global and localized resource", + "description": "There should never be both a global and localized version of a given resource, because global resources take precedence over language-specific resources. If a global version of a resource exists, language-specific versions of the same resource are never returned by the platform APIs.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "UnknownResourceModifier", + "name": "Unknown resource file name modifier", + "description": "Device type modifiers for device-specific resource files (like ~iphone or ~ipad), as well as the resolution modifier @2x, must be spelled correctly (and case sensitively, due to the case-sensitive filesystem on iOS devices).", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "SuspiciousMissingResources", + "name": "Suspicious missing bundle resources", + "description": "Warns when the project contains certain types of files that are not included into any target as resources, but probably should be.", + "severity": "MAJOR" + }, + { + "category": "Resources", + "key": "DuplicateResource", + "name": "Duplicate resource", + "description": "Warns if two resource files are equal.", + "severity": "MAJOR" + }, + { + "category": "Config", + "key": "BuildSettingsSetInGUI", + "name": "Build settings set in Xcode GUI", + "description": "Enable this rule if you want to set all of your build configuration values in .xcconfig files, and get warnings whenever something gets accidentally set in the GUI.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "CompilerWarnings", + "name": "Recommended compiler warning options", + "description": "Some compiler warnings and warning groups are so useful that they should be enabled at all times.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "MissingAPIUsageDescription", + "name": "Missing API usage description", + "description": "Some APIs (that access e.g. contacts or calendars) require a usage description (\u201cpurpose string\u201d) in the application metadata. This will be shown to the user when the system asks them to allow the application access to the related user data or system resource. This rule warns when some such APIs are used, but the associated usage description is missing.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "ViewLayoutInXIB", + "name": "Erroneous view layout in XIB", + "description": "Warns about views that are marked as \u2018misplaced\u2019 or \u2018ambiguous\u2019 in XIBs or storyboards that use autolayout.This rule relies on XIB annotations added by Xcode, which means that no diagnostics will be emitted for misplaced or ambiguous views that have not (yet) been annotated by Xcode.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "BasicProjectSettings", + "name": "Recommended project settings", + "description": "The \u2018Organization\u2019 and \u2018Class Prefix\u2019 settings should always be set. The expected values for other settings are configurable.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "ImplicitBundleId", + "name": "Implicit bundle identifier", + "description": "It is recommended to choose an explicit value for the bundle identifier: an explicit, matching value must be chosen in iTunes Connect before publishing in the App Store (Xcode by default makes the bundle ID dependent on the PRODUCT_NAME variable).", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "ReleaseBuildCompilerArgs", + "name": "Problematic release build compiler arguments", + "description": "For release builds, warns when some expected arguments are missing, or some unexpected arguments are present.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "XcconfigOverwrites", + "name": "Xcode build configuration file overwrites previously set value", + "description": "Overwriting a previously set value in a build configuration file is often a sign of a mistake somewhere.It is recommended to set custom intermediary settings in \u201cparent\u201d configuration files and then compose final values for actual build settings in leaf configuration files.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "BuildSettingSelfReference", + "name": "Xcode build setting refers to itself", + "description": "Build settings should not refer to themselves. The $(inherited) keyword should be used to append something to an inherited value, and custom intermediary build setting keys should be used to compose values from multiple definitions in an .xcconfig file.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "BuildSettingPlacement", + "name": "Incorrect placement of build setting value", + "description": "Warns if preprocessor definitions are defined explicitly using the -D argument instead of defining them in the GCC_PREPROCESSOR_DEFINITIONS (\u201cPreprocessor macros\u201d) build setting.Also warns if non-warning flags are defined in WARNING_CFLAGS (instead of OTHER_CFLAGS).", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "AbsPathInBuildSetting", + "name": "Absolute path in build setting value", + "description": "The project build configurations should not contain absolute path references. This will become a problem as soon as the project is moved to another developer\u2019s computer.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "FileRefWithAbsPath", + "name": "Project reference to file using absolute path", + "description": "The project should not contain references to files using absolute paths. This will become a problem as soon as the project is moved to another developer\u2019s computer.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "ReleaseBuildConfig", + "name": "Problematic release build settings", + "description": "Warns when certain problematic build setting values are used for release builds.For example, if program flow instrumentation is enabled, the compiler optimization level is too low, or if the static analyzer is not run.", + "severity": "MINOR" + }, + { + "category": "Config", + "key": "DylibInstallName", + "name": "Dynamic library install name", + "description": "Warns if the install names of dynamic libraries are absolute (@loader_path, @executable_path, or @rpath should be used instead.)You can use install_name_tool to change dynamic library install names.", + "severity": "MINOR" + }, + { + "category": "Localization", + "key": "InvalidStringsFile", + "name": "Invalid string resource file", + "description": "String resource files should be valid dictionary-format property lists.", + "severity": "MAJOR" + }, + { + "category": "Localization", + "key": "UnusedTranslation", + "name": "Unused translation", + "description": "Warns about entries in string resource files that are not directly loaded in code (using NSLocalizedString and its variants).", + "severity": "MAJOR" + }, + { + "category": "Localization", + "key": "StringsdictWithoutStrings", + "name": "Stringsdict file without matching string resource file", + "description": "If a .stringsdict file is included as a resource, a .strings file with the same name also needs to be included, even if empty \u2014 otherwise translations will not be read from the .stringsdict file.", + "severity": "MAJOR" + }, + { + "category": "Localization", + "key": "HardcodedUIString", + "name": "UI String not localized", + "description": "All strings that are given to APIs that display them in the user interface should be routed through NSLocalizedString() and friends.", + "severity": "MAJOR" + }, + { + "category": "Localization", + "key": "MissingTranslation", + "name": "Missing translation", + "description": "Warns if a translation is missing for a key that is used as argument to NSLocalizedString or its variants.", + "severity": "MAJOR" + }, + { + "category": "Localization", + "key": "DuplicateTranslation", + "name": "Duplicate translation", + "description": "Warns if a string resource file contains multiple entries with the same key.", + "severity": "MAJOR" + }, + { + "category": "Localization", + "key": "TranslationPunctuation", + "name": "Translation border punctuation mismatch", + "description": "Warns if the punctuation at the start or end of translation strings differs between languages.", + "severity": "MAJOR" + }, + { + "category": "Localization", + "key": "TranslationFormatMismatch", + "name": "Translation format mismatch", + "description": "Warns when different language translations for the same key contain mismatched format specifiers.", + "severity": "MAJOR" + }, + { + "category": "Localization", + "key": "UncommentedLocalizedString", + "name": "Uncommented localized string", + "description": "Warns if NSLocalizedString() or one of its variants is used without a non-empty comment argument.", + "severity": "MAJOR" + }, + { + "category": "APIUsage", + "key": "UIKitKVO", + "name": "Observing UIKit object using KVO", + "description": "The classes of the UIKit framework generally do not support Key-Value Observing (KVO). If KVO does happen to work for some properties, it is undefined behavior and thus not guaranteed to work in future versions.", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "APIAvailability", + "name": "Use of API not available in the minimum deployment target", + "description": "Warns about usages of system APIs that are not available in the minimum deployment target that your project target is configured to support.", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "RestrictedDirectMethodCall", + "name": "Restricted direct method call", + "description": "Some methods of system classes should not be called directly.This rule will not warn about overriding methods that call the superclass implementation.", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "RestrictedMethodOverride", + "name": "Restricted method override", + "description": "Some methods of system classes should not be overridden.", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "IsEqualAndHash", + "name": "Class implements -isEqual: but not -hash", + "description": "If -isEqual: determines that two objects are equal, they must have the same hash value.", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "LiteralStringKeyPath", + "name": "Literal string for key path", + "description": "Warns when literal strings are used to specify key paths.Something like NSStringFromSelector(@selector(foo)) is safer because it makes the compiler aware of the selector being specified \u2014 this helps find typos at compile time and allows automatic refactoring tools to make appropriate changes.", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "FixedFormatDateFormatter", + "name": "Fixed-format NSDateFormatter not using invariant (POSIX) locale", + "description": "Warns when an NSDateFormatter is used with fixed-format dates without using the invariant en_US_POSIX locale. If any other locale is used, the date format string may be overwritten, depending on system date and time settings.When working with user-visible dates, date and time styles should be used instead of setting a date format.", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "SuspiciousDateTimeFormat", + "name": "Suspicious date-time format", + "description": "Warns about date-time formats that are likely to have unintentional behavior, e.g. \u201cweek-year\u201d specifiers (uppercase Y) instead of normal calendar year specifiers (lowercase y).", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "BlockAPIRetainCycle", + "name": "Retain cycle in block API usage", + "description": "Warns if self is referenced in a block that is used in a context where it is known to cause a retain cycle.The Clang compiler\u2019s -Warc-retain-cycles warning implements generic retain cycle detection \u2014 this rule only considers specific known system framework APIs that the compiler warning does not warn about.", + "severity": "CRITICAL" + }, + { + "category": "APIUsage", + "key": "MissingNotificationCenterDetachment", + "name": "Missing NSNotificationCenter observer detachment", + "description": "You must invoke -[NSNotificationCenter removeObserver:] or -[NSNotificationCenter removeObserver:name:object:] before the observer object is deallocated.This rule only considers cases where the observer reference is self, or an instance variable or an Objective-C property in self.This only applies to iOS 8 (and earlier) and OS X 10.10 (and earlier).", + "severity": "CRITICAL" + }, + { + "category": "VCS", + "key": "StringsFileEncoding", + "name": "String resource file is not UTF-8", + "description": "Git prefers UTF-8 encoding, and doesn\u2019t handle some other encodings (e.g. UTF-16) very well. It thinks UTF-16 -encoded files are binary, and will thus not display line diffs for them.", + "severity": "INFO" + }, + { + "category": "VCS", + "key": "RecommendedVCSIgnores", + "name": "Recommended VCS ignores", + "description": "Warns whenever some files that are recommended to be ignored by the version control system are not ignored, or vice versa.", + "severity": "INFO" + }, + { + "category": "VCS", + "key": "FileRefOutsideVCS", + "name": "Project reference to file outside version control root", + "description": "The project should not contain references to files that are outside the version control working copy root.", + "severity": "INFO" + }, + { + "category": "VCS", + "key": "FileRefIgnoredInVCS", + "name": "Project reference to file ignored in the VCS", + "description": "The project should not contain references to files that are ignored by the version control system.", + "severity": "INFO" + }, + { + "category": "Style", + "key": "StrongInsteadOfRetain", + "name": "Usage of retain in ARC code", + "description": "In files compiled with ARC, warns if the retain property attribute is used. The strong and retain attributes are functionally equivalent, but the former could be considered more idiomatic with ARC.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "NullCoalescingOp", + "name": "Null coalescing operator usage", + "description": "Expressions of the form (obj ? obj : other) should be written as obj ?: other.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "OrderedComparisonOpDirection", + "name": "Direction of ordered comparison operators", + "description": "Warns if the > or >= operators are used (the < or <= operators should be used instead). This is based on the idea that it is easier to read comparisons where the smaller values are on the left.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "ThrowingObjCException", + "name": "Throwing an Objective-C exception", + "description": "Throwing exceptions in Objective-C is not very idiomatic, and should only be reserved for truly exceptional cases (if that,) and never for flow control.This rule can help you enforce a policy to never throw exceptions.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "NewInitializer", + "name": "Shortcut initializer", + "description": "Some people prefer [[NSObject alloc] init] instead of [NSObject new], or vice versa.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "NonTypedefBlockDeclaration", + "name": "Block-typed declaration without typedef", + "description": "It is recommended that typedef be used for all block-typed declarations, for readability.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "Spelling", + "name": "error Spelling", + "description": "Warns if some words in code symbol names are spelled incorrectly.This rule expects code symbol names to be in English (US and/or GB).", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "SourceFileHeaderComment", + "name": "Source file header comment format", + "description": "Warns about errors in source file header comments (that are formatted using the default Xcode template), for example if the file name in the comment does not match the actual file name, or if the placeholder __MyCompanyName__ is present.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "UnprefixedClass", + "name": "Unprefixed Objective-C class", + "description": "Warns when an Objective-C class name has no prefix (e.g. Thing instead of FPXThing).", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "DotSyntax", + "name": "Dot syntax usage", + "description": "Warns about [obj foo] or [obj setFoo:x] instead of obj.foo or obj.foo = x.Can also be configured to enforce dot syntax only for accessors declared with the @property syntax.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "IdentifierNaming", + "name": "Identifier naming", + "description": "This rule allows enforcing custom naming guidelines for different kinds of identifiers via regular expressions.", + "severity": "MAJOR" + }, + { + "category": "Style", + "key": "MacroLiteral", + "name": "Macro definition for literal value", + "description": "Instead of using a macro definition for a literal value that is used as a constant, define it as an actual constant.This makes the scope of the constant more explicit (it\u2019s not available in all imported files until undefined) and it cannot be redefined or undefined in some later part of the code. Macro definitions are also not available in the debugger.", + "severity": "MAJOR" + }, + { + "category": "Pedantic", + "key": "UnnecessaryNullCheck", + "name": "Unnecessary NULL check before free()", + "description": "Passing NULL to free() is a no-op.", + "severity": "MINOR" + }, + { + "category": "Pedantic", + "key": "UnusedMethod", + "name": "Possibly unused Objective-C method", + "description": "Warns about Objective-C methods to which no references are found.This rule will not warn about IBAction methods, initializer methods, or public methods (methods with a declaration in a header file, excluding header files named in the form *+Private.h). It also won\u2019t warn about unused getter methods whose setter is used, and vice versa.", + "severity": "MINOR" + }, + { + "category": "Pedantic", + "key": "ReservedIdentifierNaming", + "name": "Reserved identifier name", + "description": "Warns when identifiers are named using conventions reserved by the C standard or POSIX.", + "severity": "MINOR" + }, + { + "category": "Pedantic", + "key": "CyclomaticComplexity", + "name": "Cyclomatic complexity", + "description": "Warns if a routine has high cyclomatic complexity (that is, the number of linearly independent paths through the routine\u2019s source code).", + "severity": "MINOR" + }, + { + "category": "Pedantic", + "key": "DefaultInExhaustiveSwitch", + "name": "Unnecessary default case in exhaustive switch statement", + "description": "If a switch statement explicitly handles all possible values, then the default case is unnecessary dead code, and might even be misleading to people reading the code.If the intended purpose of the default case is to safeguard against enum fields that are added in the future but accidentally left unhandled in the switch, the compiler warning -Wswitch-enum is recommended for that purpose instead.", + "severity": "MINOR" + }, + { + "category": "Pedantic", + "key": "MallocCast", + "name": "Casting the return value of malloc()", + "description": "In C, it is not recommended to explicitly cast the return value of malloc() (and other related memory allocation functions.)This rule does not warn about casts that occur in compilation units compiled in C++ (or Objective-C++) mode.", + "severity": "MINOR" + }, + { + "category": "Pedantic", + "key": "ReservedPrefix", + "name": "Reserved symbol prefix", + "description": "Two-character prefixes (such as NS) are reserved for Apple\u2019s system frameworks. Your own code should use prefixes that are three characters long.", + "severity": "MINOR" + }, + { + "category": "Pedantic", + "key": "UsedVariableMarkedUnused", + "name": "Using a variable marked unused", + "description": "Warns when a variable is annotated with the \u201cunused\u201d attribute, but is actually used. This rule does not warn about cases where a variable is marked unused via a pragma directive.", + "severity": "MINOR" + }, + { + "category": "Miscellaneous", + "key": "UnsupportedWeakReference", + "name": "Assignment of weak-unavailable object to a weak property", + "description": "In OS X, you cannot create weak references to instances of some classes (see the full list from Apple\u2019s documentation.)The Clang compiler should warn about assignments of such objects to weak variables.", + "severity": "MINOR" + }, + { + "category": "Miscellaneous", + "key": "ThreadUnsafeInstanceCaching", + "name": "Globally caching a thread-unsafe class instance", + "description": "Warns about variables with global storage whose type is an object pointer to a known thread-unsafe class.-[NSThread threadDictionary] can be used to cache instances of thread-unsafe classes \u2014 one instance for each thread.This rule does not warn about code occuring in subclasses of (or categories on) UIKit or AppKit classes, because it can be assumed that these are always accessed solely from the main thread.", + "severity": "MINOR" + }, + { + "category": "Miscellaneous", + "key": "UnnecessaryNibMethod", + "name": "Unnecessary Nib method", + "description": "Warns if -[NSObject awakeFromNib] is implemented in a class that is not archived in any known XIB.", + "severity": "MINOR" + }, + { + "category": "Miscellaneous", + "key": "OrderedPointerToZeroComparison", + "name": "Ordered comparison of pointer and zero", + "description": "Warns whenever a pointer value is compared to zero using an ordered comparison operator.The Clang compiler should warn about similar comparisons to values other than zero.", + "severity": "MINOR" + }, + { + "category": "Miscellaneous", + "key": "ZeroAssignmentToPointer", + "name": "Assignment of literal zero to pointer", + "description": "Assigning the literal zero to a pointer value might be an indication of a mistake where the programmer actually wanted to assign to an integer-typed member of the pointer type value. Assigning NULL, nil, or Nil instead suppresses warnings from this rule.", + "severity": "MINOR" + }, + { + "category": "Miscellaneous", + "key": "CategoryMethodConflict", + "name": "Conflicting category methods", + "description": "If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime.", + "severity": "MINOR" + } +] \ No newline at end of file diff --git a/src/main/resources/org/sonar/plugins/oclint/profile-oclint.xml b/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/oclint/profile-oclint.xml old mode 100644 new mode 100755 similarity index 85% rename from src/main/resources/org/sonar/plugins/oclint/profile-oclint.xml rename to sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/oclint/profile-oclint.xml index 35fa35d4..5c9c3b76 --- a/src/main/resources/org/sonar/plugins/oclint/profile-oclint.xml +++ b/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/oclint/profile-oclint.xml @@ -3,10 +3,6 @@ OCLint objc - - OCLint - use early exits and continue - OCLint avoid branching statement as last in loop @@ -47,10 +43,6 @@ OCLint dead code - - OCLint - default label not last in switch statement - OCLint double negative @@ -163,22 +155,6 @@ OCLint high npath complexity - - OCLint - replace with boxed expression - - - OCLint - replace with container literal - - - OCLint - replace with number literal - - - OCLint - replace with object subscripting - OCLint parameter reassignment @@ -211,10 +187,6 @@ OCLint switch statements don't need default when fully covered - - OCLint - switch statements should have default - OCLint throw exception from finally block @@ -255,5 +227,61 @@ OCLint ivar assignment outside accessors or init + + OCLint + class + + + OCLint + unnecessary null check for dealloc + + + OCLint + unnecessary default statement in covered switch statement + + + OCLint + ill-placed default label in switch statement + + + OCLint + prefer early exits and continue + + + OCLint + missing default in switch statements + + + OCLint + use boxed expression + + + OCLint + use container literal + + + OCLint + use number literal + + + OCLint + use object subscripting + + + OCLint + missing hash method + + + OCLint + missing call to base method + + + OCLint + calling prohibited method + + + OCLint + missing abstract method implementation + \ No newline at end of file diff --git a/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/oclint/rules.txt b/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/oclint/rules.txt new file mode 100755 index 00000000..3304844d --- /dev/null +++ b/sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/oclint/rules.txt @@ -0,0 +1,565 @@ +Available issues: + +OCLint +====== + +avoid branching statement as last in loop +---------- + +Summary: Name: avoid branching statement as last in loop + +Severity: 2 +Category: OCLint + +bitwise operator in conditional +---------- + +Summary: Name: bitwise operator in conditional + +Severity: 3 +Category: OCLint + +broken null check +---------- + +Summary: Name: broken null check + +Severity: 3 +Category: OCLint + +broken nil check +---------- + +Summary: + +Severity: 4 +Category: OCLint + +broken oddness check +---------- + +Summary: Name: broken oddness check + +Severity: 3 +Category: OCLint + +collapsible if statements +---------- + +Summary: Name: collapsible if statements + +Severity: 3 +Category: OCLint + +constant conditional operator +---------- + +Summary: Name: constant conditional operator + +Severity: 3 +Category: OCLint + +constant if expression +---------- + +Summary: Name: constant if expression + +Severity: 3 +Category: OCLint + +high cyclomatic complexity +---------- + +Summary: + +Severity: 2 +Category: OCLint + +dead code +---------- + +Summary: Name: dead code + +Severity: 3 +Category: OCLint + +double negative +---------- + +Summary: Name: double negative + +Severity: 3 +Category: OCLint + +empty catch statement +---------- + +Summary: Name: empty catch statement + +Severity: 3 +Category: OCLint + +empty do/while statement +---------- + +Summary: Name: empty do/while statement + +Severity: 3 +Category: OCLint + +empty else block +---------- + +Summary: Name: empty else block + +Severity: 3 +Category: OCLint + +empty finally statement +---------- + +Summary: Name: empty finally statement + +Severity: 3 +Category: OCLint + +empty for statement +---------- + +Summary: Name: empty for statement + +Severity: 3 +Category: OCLint + +empty if statement +---------- + +Summary: Name: empty if statement + +Severity: 3 +Category: OCLint + +empty switch statement +---------- + +Summary: Name: empty switch statement + +Severity: 3 +Category: OCLint + +empty try statement +---------- + +Summary: Name: empty try statement + +Severity: 3 +Category: OCLint + +empty while statement +---------- + +Summary: + +Severity: 3 +Category: OCLint + +feature envy +---------- + +Summary: + +Severity: 3 +Category: OCLint + +for loop should be while loop +---------- + +Summary: Name: for loop should be while loop + +Severity: 3 +Category: OCLint + +goto statement +---------- + +Summary: + +Severity: 3 +Category: OCLint + +inverted logic +---------- + +Summary: Name: inverted logic + +Severity: 2 +Category: OCLint + +jumbled incrementer +---------- + +Summary: Name: jumbled incrementer + +Severity: 3 +Category: OCLint + +long class +---------- + +Summary: Name: long class + +Severity: 3 +Category: OCLint + +long line +---------- + +Summary: Name: long line + +Severity: 3 +Category: OCLint + +long method +---------- + +Summary: Name: long method + +Severity: 3 +Category: OCLint + +long variable name +---------- + +Summary: Name: long variable name + +Severity: 2 +Category: OCLint + +misplaced null check +---------- + +Summary: Name: misplaced null check + +Severity: 3 +Category: OCLint + +misplaced nil check +---------- + +Summary: + +Severity: 4 +Category: OCLint + +missing break in switch statement +---------- + +Summary: Name: missing break in switch statement + +Severity: 2 +Category: OCLint + +multiple unary operator +---------- + +Summary: Name: multiple unary operator + +Severity: 3 +Category: OCLint + +must override hash with isEqual +---------- + +Summary: + +Severity: 1 +Category: OCLint + +high ncss method +---------- + +Summary: Name: high ncss method + +Severity: 3 +Category: OCLint + +deep nested block +---------- + +Summary: Name: deep nested block + +Severity: 3 +Category: OCLint + +non case label in switch statement +---------- + +Summary: Name: non case label in switch statement + +Severity: 2 +Category: OCLint + +high npath complexity +---------- + +Summary: + +Severity: 2 +Category: OCLint + +parameter reassignment +---------- + +Summary: Name: parameter reassignment + +Severity: 2 +Category: OCLint + +redundant conditional operator +---------- + +Summary: Name: redundant conditional operator + +Severity: 1 +Category: OCLint + +redundant if statement +---------- + +Summary: Name: redundant if statement + +Severity: 1 +Category: OCLint + +redundant local variable +---------- + +Summary: Name: redundant local variable + +Severity: 1 +Category: OCLint + +redundant nil check +---------- + +Summary: Name: redundant nil check + +Severity: 1 +Category: OCLint + +return from finally block +---------- + +Summary: Name: return from finally block + +Severity: 3 +Category: OCLint + +short variable name +---------- + +Summary: + +Severity: 2 +Category: OCLint + +switch statements don't need default when fully covered +---------- + +Summary: + +Severity: 3 +Category: OCLint + +throw exception from finally block +---------- + +Summary: + +Severity: 3 +Category: OCLint + +too few branches in switch statement +---------- + +Summary: + +Severity: 2 +Category: OCLint + +too many fields +---------- + +Summary: Name: too many fields + +Severity: 3 +Category: OCLint + +too many methods +---------- + +Summary: Name: too many methods + +Severity: 3 +Category: OCLint + +too many parameters +---------- + +Summary: + +Severity: 3 +Category: OCLint + +unnecessary else statement +---------- + +Summary: Name: unnecessary else statement + +Severity: 1 +Category: OCLint + +unused local variable +---------- + +Summary: Name: unused local variable + +Severity: 0 +Category: OCLint + +unused method parameter +---------- + +Summary: + +Severity: 0 +Category: OCLint + +useless parentheses +---------- + +Summary: + +Severity: 1 +Category: OCLint + +ivar assignment outside accessors or init +---------- + +Summary: Name: ivar assignment outside accessors or init + +Severity: 2 +Category: OCLint + +class +---------- + +Summary: Name: destructor of virtual class + +Severity: 2 +Category: OCLint + +unnecessary null check for dealloc +---------- + +Summary: Name: unnecessary null check for dealloc + +Severity: 1 +Category: OCLint + +unnecessary default statement in covered switch statement +---------- + +Summary: Name: unnecessary default statement in covered switch statement + +Severity: 2 +Category: OCLint + +ill-placed default label in switch statement +---------- + +Summary: Name: ill-placed default label in switch statement + +Severity: 2 +Category: OCLint + +prefer early exits and continue +---------- + +Summary: Name: prefer early exits and continue + +Severity: 2 +Category: OCLint + +missing default in switch statements +---------- + +Summary: Name: missing default in switch statements + +Severity: 2 +Category: OCLint + +use boxed expression +---------- + +Summary: Name: use boxed expression + +Severity: 1 +Category: OCLint + +use container literal +---------- + +Summary: Name: use container literal + +Severity: 1 +Category: OCLint + +use number literal +---------- + +Summary: Name: use number literal + +Severity: 1 +Category: OCLint + +use object subscripting +---------- + +Summary: + +Severity: 1 +Category: OCLint + +missing hash method +---------- + +Summary: Name: missing hash method + +Severity: 1 +Category: OCLint + +missing call to base method +---------- + +Summary: Name: missing call to base method + +Severity: 1 +Category: OCLint + +calling prohibited method +---------- + +Summary: Name: calling prohibited method + +Severity: 1 +Category: OCLint + +missing abstract method implementation +---------- + +Summary: Name: missing abstract method implementation + +Severity: 1 +Category: OCLint + diff --git a/sonar-objective-c-plugin/src/main/shell/run-sonar.sh b/sonar-objective-c-plugin/src/main/shell/run-sonar.sh new file mode 100755 index 00000000..a97ac336 --- /dev/null +++ b/sonar-objective-c-plugin/src/main/shell/run-sonar.sh @@ -0,0 +1,499 @@ +#### run-sonar.sh #### +#!/bin/bash +# +# backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. +# Copyright © 2012 OCTO Technology, Backelite (${email}) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +## INSTALLATION: script to copy in your Xcode project in the same directory as the .xcodeproj file +## USAGE: ./run-sonar.sh +## DEBUG: ./run-sonar.sh -v +## WARNING: edit your project parameters in sonar-project.properties rather than modifying this script +# + +# Global parameters +XCODEBUILD_CMD=xcodebuild +SLATHER_CMD=slather +XCPRETTY_CMD=xcpretty +LIZARD_CMD=lizard + +trap "echo 'Script interrupted by Ctrl+C'; stopProgress; exit 1" SIGHUP SIGINT SIGTERM + +function startProgress() { + while true + do + echo -n "." + sleep 5 + done +} + +function stopProgress() { + if [ "$vflag" = "" -a "$nflag" = "" ]; then + kill $PROGRESS_PID &>/dev/null + fi +} + +function testIsInstalled() { + + hash $1 2>/dev/null + if [ $? -eq 1 ]; then + echo >&2 "ERROR - $1 is not installed or not in your PATH"; exit 1; + fi +} + +function testIsXcodeMinMajorVersionAvailable() { + + XCODE_VERSION="$($XCODEBUILD_CMD -version | grep -a -A 1 "Xcode" | head -n1 | sed "s/Xcode \([0-9]*\)\..*/\1/")" + if (( "$1" <= "$XCODE_VERSION" )); then + return 0 + else + return 1 + fi +} + +function readParameter() { + + variable=$1 + shift + parameter=$1 + shift + + eval $variable="\"$(sed '/^\#/d' sonar-project.properties | grep $parameter | tail -n 1 | cut -d '=' -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')\"" +} + +# Run a set of commands with logging and error handling +function runCommand() { + + # 1st arg: redirect stdout + # 2nd arg: command to run + # 3rd..nth arg: args + redirect=$1 + shift + + command=$1 + shift + + if [ "$nflag" = "on" ]; then + # don't execute command, just echo it + echo + if [ "$redirect" = "/dev/stdout" ]; then + if [ "$vflag" = "on" ]; then + echo "+" $command "$@" + else + echo "+" $command "$@" "> /dev/null" + fi + elif [ "$redirect" != "no" ]; then + echo "+" $command "$@" "> $redirect" + else + echo "+" $command "$@" + fi + + elif [ "$vflag" = "on" ]; then + echo + + if [ "$redirect" = "/dev/stdout" ]; then + set -x #echo on + $command "$@" + returnValue=$? + set +x #echo off + elif [ "$redirect" != "no" ]; then + set -x #echo on + $command "$@" > $redirect + returnValue=$? + set +x #echo off + else + set -x #echo on + $command "$@" + returnValue=$? + set +x #echo off + fi + + if [[ $returnValue != 0 && $returnValue != 5 ]] ; then + stopProgress + echo "ERROR - Command '$command $@' failed with error code: $returnValue" + exit $returnValue + fi + else + + if [ "$redirect" = "/dev/stdout" ]; then + $command "$@" > /dev/null + elif [ "$redirect" != "no" ]; then + $command "$@" > $redirect + else + $command "$@" + fi + + returnValue=$? + if [[ $returnValue != 0 && $returnValue != 5 ]] ; then + stopProgress + echo "ERROR - Command '$command $@' failed with error code: $returnValue" + exit $? + fi + + + echo + fi +} + +## COMMAND LINE OPTIONS +vflag="" +nflag="" +unittests="on" +oclint="on" +fauxpas="on" +lizard="on" +sonarscanner="" + +while [ $# -gt 0 ] +do + case "$1" in + -v) vflag=on;; + -n) nflag=on;; + -nounittests) unittests="";; + -nooclint) oclint="";; + -nofauxpas) fauxpas="";; + -usesonarscanner) sonarscanner="on";; + --) shift; break;; + -*) + echo >&2 "Usage: $0 [-v]" + exit 1;; + *) break;; # terminate while loop + esac + shift +done + +# Usage OK +echo "Running run-sonar.sh..." + +## CHECK PREREQUISITES + +# xctool, oclint installed +testIsInstalled $XCODEBUILD_CMD +testIsInstalled oclint + +# sonar-project.properties in current directory +if [ ! -f sonar-project.properties ]; then + echo >&2 "ERROR - No sonar-project.properties in current directory"; exit 1; +fi + +## READ PARAMETERS from sonar-project.properties + +# Read destination simulator +destinationSimulator=''; readParameter destinationSimulator 'sonar.objectivec.simulator' + +# Your .xcworkspace/.xcodeproj filename +workspaceFile=''; readParameter workspaceFile 'sonar.objectivec.workspace' +projectFile=''; readParameter projectFile 'sonar.objectivec.project' + +# Count projects +projectCount=$(echo $projectFile | sed -n 1'p' | tr ',' '\n' | wc -l | tr -d '[[:space:]]') +if [ "$vflag" = "on" ]; then + echo "Project count is [$projectCount]" +fi + +# Source directories for .h/.m files +srcDirs=''; readParameter srcDirs 'sonar.sources' +# The name of your application scheme in Xcode +appScheme=''; readParameter appScheme 'sonar.objectivec.appScheme' + +# The name of your test scheme in Xcode +testScheme=''; readParameter testScheme 'sonar.objectivec.testScheme' +# The file patterns to exclude from coverage report +excludedPathsFromCoverage=''; readParameter excludedPathsFromCoverage 'sonar.objectivec.excludedPathsFromCoverage' +# Read coverage type +coverageType=''; readParameter coverageType 'sonar.objectivec.coverageType' + + +# Check for mandatory parameters +if [ -z "$projectFile" -o "$projectFile" = " " ]; then + + if [ ! -z "$workspaceFile" -a "$workspaceFile" != " " ]; then + echo >&2 "ERROR - sonar.objectivec.project parameter is missing in sonar-project.properties. You must specify which projects (comma-separated list) are application code within the workspace $workspaceFile." + else + echo >&2 "ERROR - sonar.objectivec.project parameter is missing in sonar-project.properties (name of your .xcodeproj)" + fi + exit 1 +fi +if [ -z "$srcDirs" -o "$srcDirs" = " " ]; then + echo >&2 "ERROR - sonar.sources parameter is missing in sonar-project.properties. You must specify which directories contain your .h/.m source files (comma-separated list)." + exit 1 +fi +if [ -z "$appScheme" -o "$appScheme" = " " ]; then + echo >&2 "ERROR - sonar.objectivec.appScheme parameter is missing in sonar-project.properties. You must specify which scheme is used to build your application." + exit 1 +fi +if [ -z "$destinationSimulator" -o "$destinationSimulator" = " " ]; then + echo >&2 "ERROR - sonar.objectivec.simulator parameter is missing in sonar-project.properties. You must specify which simulator to use." + exit 1 +fi + +if [ "$vflag" = "on" ]; then + echo "Xcode workspace file is: $workspaceFile" + echo "Xcode project file is: $projectFile" + echo "Xcode application scheme is: $appScheme" + echo "Xcode test scheme is: $testScheme" + echo "Excluded paths from coverage are: $excludedPathsFromCoverage" +fi + +## SCRIPT + +# Start progress indicator in the background +if [ "$vflag" = "" -a "$nflag" = "" ]; then + startProgress & + # Save PID + PROGRESS_PID=$! +fi + +# Create sonar-reports/ for reports output +if [ "$vflag" = "on" ]; then + echo 'Creating directory sonar-reports/' +fi +rm -rf sonar-reports +mkdir sonar-reports + +# Extracting project information needed later +echo -n 'Extracting Xcode project information' +if [[ "$workspaceFile" != "" ]] ; then + buildCmdPrefix="-workspace $workspaceFile" +else + buildCmdPrefix="-project $projectFile" +fi +buildCmd=($XCODEBUILD_CMD clean build $buildCmdPrefix -scheme $appScheme) +if [[ ! -z "$destinationSimulator" ]]; then + buildCmd+=(-destination "$destinationSimulator" -destination-timeout 360 COMPILER_INDEX_STORE_ENABLE=NO) +fi +runCommand xcodebuild.log "${buildCmd[@]}" +#oclint-xcodebuild # Transform the xcodebuild.log file into a compile_command.json file +cat xcodebuild.log | $XCPRETTY_CMD -r json-compilation-database -o compile_commands.json + +# Unit surefire and coverage +if [ "$testScheme" = "" ] || [ "$unittests" = "" ]; then + echo 'Skipping surefire!' + + # Put default xml files with no surefire and no coverage... + echo "" > sonar-reports/TEST-report.xml + echo "" > sonar-reports/coverage.xml +else + + echo -n 'Running surefire' + + if [ "$coverageType" = "profdata" -o "$coverageType" = "" ]; then + # profdata + buildCmd=($XCODEBUILD_CMD test $buildCmdPrefix -scheme "$testScheme" -configuration Debug -enableCodeCoverage YES) + xcode8BuildForTestingCmd=($XCODEBUILD_CMD build-for-testing $buildCmdPrefix -scheme "$testScheme" -configuration Debug -enableCodeCoverage YES) + xcode8TestCmd=($XCODEBUILD_CMD test-without-building $buildCmdPrefix -scheme "$testScheme" -configuration Debug -enableCodeCoverage YES) + else + # Legacy coverage + buildCmd=($XCODEBUILD_CMD test $buildCmdPrefix -scheme "$testScheme" -configuration Debug) + xcode8BuildForTestingCmd=($XCODEBUILD_CMD build-for-testing $buildCmdPrefix -scheme "$testScheme" -configuration Debug) + xcode8TestCmd=($XCODEBUILD_CMD test-without-building $buildCmdPrefix -scheme "$testScheme" -configuration Debug) + fi + + if [[ ! -z "$destinationSimulator" ]]; then + buildCmd+=(-destination "$destinationSimulator" -destination-timeout 360) + xcode8BuildForTestingCmd+=(-destination "$destinationSimulator" -destination-timeout 360) + xcode8TestCmd+=(-destination "$destinationSimulator" -destination-timeout 360) + fi + + if testIsXcodeMinMajorVersionAvailable 8 ; then + echo "Running build-for-testing" + "${xcode8BuildForTestingCmd[@]}" | $XCPRETTY_CMD + echo "Running test-without-building" + "${xcode8TestCmd[@]}" | $XCPRETTY_CMD -t --report junit + else + echo "Testing" + "${buildCmd[@]}" | $XCPRETTY_CMD -t --report junit + fi + + mv build/reports/junit.xml sonar-reports/TEST-report.xml + + echo -n 'Computing coverage report' + + if [ "$coverageType" = "profdata" -o "$coverageType" = "" ]; then + + # profdata = use slather + + echo 'Using profdata' + + # Build the --exclude flags + excludedCommandLineFlags="" + if [ ! -z "$excludedPathsFromCoverage" -a "$excludedPathsFromCoverage" != " " ]; then + echo $excludedPathsFromCoverage | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh2 + while read word; do + excludedCommandLineFlags+=" -i $word" + done < tmpFileRunSonarSh2 + rm -rf tmpFileRunSonarSh2 + fi + if [ "$vflag" = "on" ]; then + echo "Command line exclusion flags for slather is:$excludedCommandLineFlags" + fi + + + firstProject=$(echo $projectFile | sed -n 1'p' | tr ',' '\n' | head -n 1) + + slatherCmd=($SLATHER_CMD coverage --input-format profdata $excludedCommandLineFlags --cobertura-xml --output-directory sonar-reports) + if [[ ! -z "$workspaceFile" ]]; then + slatherCmd+=( --workspace "$workspaceFile") + fi + slatherCmd+=( --scheme "$appScheme" "$firstProject") + + runCommand /dev/stdout "${slatherCmd[@]}" + mv sonar-reports/cobertura.xml sonar-reports/coverage.xml + + else + + # Legacy mode = use gcovr + + # Build the --exclude flags + excludedCommandLineFlags="" + if [ ! -z "$excludedPathsFromCoverage" -a "$excludedPathsFromCoverage" != " " ]; then + echo $excludedPathsFromCoverage | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh2 + while read word; do + excludedCommandLineFlags+=" --exclude $word" + done < tmpFileRunSonarSh2 + rm -rf tmpFileRunSonarSh2 + fi + if [ "$vflag" = "on" ]; then + echo "Command line exclusion flags for gcovr is:$excludedCommandLineFlags" + fi + + # Create symlink on the build directory to enable its access from the workspace + coverageFilesPath=$(grep 'command' compile_commands.json | sed 's#^.*-o \\/#\/#;s#",##' | grep "${projectName%%.*}.build" | awk 'NR<2' | sed 's/\\\//\//g' | sed 's/\\\\//g' | xargs -0 dirname) + splitIndex=$(awk -v a="$coverageFilesPath" -v b="/Intermediates" 'BEGIN{print index(a,b)}') + coverageFilesPath=$(echo ${coverageFilesPath:0:$splitIndex}Intermediates) + ln -s $coverageFilesPath sonar-reports/build + + # Run gcovr with the right options + runCommand "sonar-reports/coverage.xml" gcovr -r . $excludedCommandLineFlags --xml + + fi + + +fi + +if [ "$oclint" = "on" ]; then + + # OCLint + echo -n 'Running OCLint...' + + # Options + maxPriority=10000 + longLineThreshold=250 + + # Build the --include flags + currentDirectory=${PWD##*/} + echo "$srcDirs" | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh + while read word; do + + includedCommandLineFlags=" --include .*/${currentDirectory}/${word}" + if [ "$vflag" = "on" ]; then + echo + echo -n "Path included in oclint analysis is:$includedCommandLineFlags" + fi + # Run OCLint with the right set of compiler options + runCommand no oclint-json-compilation-database -v $includedCommandLineFlags -- -rc LONG_LINE=$longLineThreshold -max-priority-1 $maxPriority -max-priority-2 $maxPriority -max-priority-3 $maxPriority -report-type pmd -o sonar-reports/$(echo $word | sed 's/\//_/g')-oclint.xml + + done < tmpFileRunSonarSh + rm -rf tmpFileRunSonarSh + + +else + echo 'Skipping OCLint (test purposes only!)' +fi + +if [ "$fauxpas" = "on" ]; then + hash fauxpas 2>/dev/null + if [ $? -eq 0 ]; then + + #FauxPas + echo -n 'Running FauxPas...' + + if [ "$projectCount" = "1" ] + then + + fauxpas -o json check $projectFile --workspace $workspaceFile --scheme $appScheme > sonar-reports/fauxpas.json + + + else + + echo $projectFile | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh + while read projectName; do + + $XCODEBUILD_CMD -list -project $projectName | sed -n '/Schemes/,$p' | while read scheme + do + + if [ "$scheme" = "" ] + then + exit + fi + + if [ "$scheme" == "${scheme/Schemes/}" ] + then + if [ "$scheme" != "$testScheme" ] + then + projectBaseDir=$(dirname $projectName) + workspaceRelativePath=$(python -c "import os.path; print os.path.relpath('$workspaceFile', '$projectBaseDir')") + fauxpas -o json check $projectName --workspace $workspaceRelativePath --scheme $scheme > sonar-reports/$(basename $projectName .xcodeproj)-$scheme-fauxpas.json + fi + fi + + done + + done < tmpFileRunSonarSh + rm -rf tmpFileRunSonarSh + + fi + + else + echo 'Skipping FauxPas (not installed)' + fi +else + echo 'Skipping FauxPas' +fi + +# Lizard Complexity +if [ "$lizard" = "on" ]; then + if hash $LIZARD_CMD 2>/dev/null; then + echo -n 'Running Lizard...' + $LIZARD_CMD --xml "$srcDirs" > sonar-reports/lizard-report.xml + else + echo 'Skipping Lizard (not installed!)' + fi +else + echo 'Skipping Lizard (test purposes only!)' +fi + +# SonarQube +if [ "$sonarscanner" = "on" ]; then + echo -n 'Running SonarQube using SonarQube Scanner' + if hash /dev/stdout sonar-scanner 2>/dev/null; then + runCommand /dev/stdout sonar-scanner + else + echo 'Skipping sonar-scanner (not installed!)' + fi +else + echo -n 'Running SonarQube using SonarQube Runner' + if hash /dev/stdout sonar-runner 2>/dev/null; then + runCommand /dev/stdout sonar-runner + else + runCommand /dev/stdout sonar-scanner + fi +fi + +# Kill progress indicator +stopProgress + +exit 0 diff --git a/src/test/java/org/sonar/objectivec/ObjectiveCAstScannerTest.java b/sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/ObjectiveCAstScannerTest.java similarity index 50% rename from src/test/java/org/sonar/objectivec/ObjectiveCAstScannerTest.java rename to sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/ObjectiveCAstScannerTest.java index ea40f1f6..b4dfcd25 100644 --- a/src/test/java/org/sonar/objectivec/ObjectiveCAstScannerTest.java +++ b/sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/ObjectiveCAstScannerTest.java @@ -1,6 +1,23 @@ -/* +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package com.sonar.objectivec;/* * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology + * Copyright (C) 2012 OCTO Technology, Backelite * dev@sonar.codehaus.org * * This program is free software; you can redistribute it and/or @@ -17,7 +34,6 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ -package org.sonar.objectivec; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; @@ -25,8 +41,11 @@ import java.io.File; +import com.sonar.objectivec.ObjectiveCAstScanner; +import org.hamcrest.Matchers; +import org.junit.Assert; import org.junit.Test; -import org.sonar.objectivec.api.ObjectiveCMetric; +import com.sonar.objectivec.api.ObjectiveCMetric; import org.sonar.squidbridge.api.SourceFile; public class ObjectiveCAstScannerTest { @@ -34,21 +53,21 @@ public class ObjectiveCAstScannerTest { @Test public void lines() { SourceFile file = ObjectiveCAstScanner.scanSingleFile(new File("src/test/resources/objcSample.h")); - assertThat(file.getInt(ObjectiveCMetric.LINES), is(18)); + Assert.assertThat(file.getInt(ObjectiveCMetric.LINES), Matchers.is(17)); } @Test public void lines_of_code() { SourceFile file = ObjectiveCAstScanner.scanSingleFile(new File("src/test/resources/objcSample.h")); - assertThat(file.getInt(ObjectiveCMetric.LINES_OF_CODE), is(5)); + Assert.assertThat(file.getInt(ObjectiveCMetric.LINES_OF_CODE), Matchers.is(5)); } @Test public void comments() { SourceFile file = ObjectiveCAstScanner.scanSingleFile(new File("src/test/resources/objcSample.h")); - assertThat(file.getInt(ObjectiveCMetric.COMMENT_LINES), is(4)); - assertThat(file.getNoSonarTagLines(), hasItem(10)); - assertThat(file.getNoSonarTagLines().size(), is(1)); + Assert.assertThat(file.getInt(ObjectiveCMetric.COMMENT_LINES), Matchers.is(4)); + Assert.assertThat(file.getNoSonarTagLines(), Matchers.hasItem(10)); + Assert.assertThat(file.getNoSonarTagLines().size(), Matchers.is(1)); } } diff --git a/sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/api/ObjectiveCPunctuatorTest.java b/sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/api/ObjectiveCPunctuatorTest.java new file mode 100644 index 00000000..50eb80c8 --- /dev/null +++ b/sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/api/ObjectiveCPunctuatorTest.java @@ -0,0 +1,34 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package com.sonar.objectivec.api; + +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +public class ObjectiveCPunctuatorTest { + + @Test + public void test() { + Assert.assertThat(ObjectiveCPunctuator.values().length, Matchers.is(48)); + } + +} diff --git a/sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/lexer/ObjectiveCLexerTest.java b/sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/lexer/ObjectiveCLexerTest.java new file mode 100644 index 00000000..aa42c20f --- /dev/null +++ b/sonar-objective-c-plugin/src/test/java/com/sonar/objectivec/lexer/ObjectiveCLexerTest.java @@ -0,0 +1,84 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package com.sonar.objectivec.lexer; + +import static com.sonar.sslr.test.lexer.LexerMatchers.hasComment; +import static com.sonar.sslr.test.lexer.LexerMatchers.hasToken; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.util.List; + +import com.sonar.sslr.test.lexer.LexerMatchers; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.sonar.sslr.api.GenericTokenType; +import com.sonar.sslr.api.Token; +import com.sonar.sslr.impl.Lexer; + +public class ObjectiveCLexerTest { + + private static Lexer lexer; + + @BeforeClass + public static void init() { + lexer = ObjectiveCLexer.create(); + } + + @Test + public void lexMultiLinesComment() { + Assert.assertThat(lexer.lex("/* My Comment \n*/"), LexerMatchers.hasComment("/* My Comment \n*/")); + Assert.assertThat(lexer.lex("/**/"), LexerMatchers.hasComment("/**/")); + } + + @Test + public void lexInlineComment() { + Assert.assertThat(lexer.lex("// My Comment \n new line"), LexerMatchers.hasComment("// My Comment ")); + Assert.assertThat(lexer.lex("//"), LexerMatchers.hasComment("//")); + } + + @Test + public void lexEndOflineComment() { + Assert.assertThat(lexer.lex("[self init]; // My Comment end of line"), LexerMatchers.hasComment("// My Comment end of line")); + Assert.assertThat(lexer.lex("[self init]; //"), LexerMatchers.hasComment("//")); + } + + @Test + public void lexLineOfCode() { + Assert.assertThat(lexer.lex("[self init];"), LexerMatchers.hasToken("[self", GenericTokenType.LITERAL)); + } + + @Test + public void lexEmptyLine() { + List tokens = lexer.lex("\n"); + Assert.assertThat(tokens.size(), Matchers.equalTo(1)); + Assert.assertThat(tokens, LexerMatchers.hasToken(GenericTokenType.EOF)); + } + + @Test + public void lexSampleFile() { + List tokens = lexer.lex(new File("src/test/resources/objcSample.h")); + Assert.assertThat(tokens.size(), Matchers.equalTo(16)); + Assert.assertThat(tokens, LexerMatchers.hasToken(GenericTokenType.EOF)); + } + +} diff --git a/sonar-objective-c-plugin/src/test/java/org/sonar/plugins/objectivec/complexity/LizardReportParserTest.java b/sonar-objective-c-plugin/src/test/java/org/sonar/plugins/objectivec/complexity/LizardReportParserTest.java new file mode 100644 index 00000000..1efec585 --- /dev/null +++ b/sonar-objective-c-plugin/src/test/java/org/sonar/plugins/objectivec/complexity/LizardReportParserTest.java @@ -0,0 +1,224 @@ +/** + * backelite-sonar-objective-c-plugin - Enables analysis of Objective-C projects into SonarQube. + * Copyright © 2012 OCTO Technology, Backelite (${email}) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ +package org.sonar.plugins.objectivec.complexity;/* + * Sonar Objective-C Plugin + * Copyright (C) 2012 OCTO Technology, Backelite + * dev@sonar.codehaus.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.plugins.objectivec.complexity.LizardReportParser; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.*; + +/** + * @author Andres Gil Herrera + * @since 03/06/15. + */ +public class LizardReportParserTest { + + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + + private File correctFile; + private File incorrectFile; + + @Before + public void setup() throws IOException { + correctFile = createCorrectFile(); + incorrectFile = createIncorrectFile(); + } + + /** + * + * @return dummy lizard xml report to test the parser + * @throws IOException + */ + public File createCorrectFile() throws IOException { + File xmlFile = folder.newFile("correctFile.xml"); + BufferedWriter out = new BufferedWriter(new FileWriter(xmlFile)); + //header + out.write(""); + out.write(""); + //root object and measure + out.write(""); + //items for function + out.write(""); + out.write("2151"); + out.write(""); + out.write("3205"); + //average and close funciton measure + out.write(""); + out.write(""); + out.write(""); + //open file measure and add the labels + out.write(""); + //items for file + out.write(""); + out.write("1200"); + out.write(""); + out.write("286862"); + //add averages + out.write(""); + //add sum + out.write(""); + //close measures and root object + out.write(""); + + out.close(); + + return xmlFile; + } + + /** + * + * @return corrupted dummy lizard report to test the parser + * @throws IOException + */ + public File createIncorrectFile() throws IOException { + File xmlFile = folder.newFile("incorrectFile.xml"); + BufferedWriter out = new BufferedWriter(new FileWriter(xmlFile)); + //header + out.write(""); + out.write(""); + //root object and measure + out.write(""); + //items for function + out.write(""); + out.write("2151"); + out.write(""); + out.write("3205"); + //average and close funciton measure + out.write(""); + out.write(""); + out.write(""); + //open file measure and add the labels + out.write(""); + //items for file 3th value tag has no closing tag + out.write(""); + out.write("1200"); + out.write(""); + out.write("286862"); + //add averages + out.write(""); + //add sum + out.write(""); + //close measures and root object no close tag for measure + out.write(""); + + out.close(); + + return xmlFile; + } + + /** + * this test case test that the parser extract all measures right + */ + @Test + public void parseReportShouldReturnMapWhenXMLFileIsCorrect() { + LizardReportParser parser = new LizardReportParser(); + + Assert.assertNotNull("correct file is null", correctFile); + + Map> report = parser.parseReport(correctFile); + + Assert.assertNotNull("report is null", report); + + Assert.assertTrue("Key is not there", report.containsKey("App/Controller/Accelerate/AccelerationViewController.h")); + List list1 = report.get("App/Controller/Accelerate/AccelerationViewController.h"); + Assert.assertEquals(3, list1.size()); + + for (Measure measure : list1) { + String s = measure.getMetric().getKey(); + + if (s.equals(CoreMetrics.FUNCTIONS_KEY)) { + Assert.assertEquals("Header Functions has a wrong value", 0, measure.getIntValue().intValue()); + } else if (s.equals(CoreMetrics.COMPLEXITY_KEY)) { + Assert.assertEquals("Header Complexity has a wrong value", 0, measure.getIntValue().intValue()); + } else if (s.equals(CoreMetrics.FILE_COMPLEXITY_KEY)) { + Assert.assertEquals("Header File Complexity has a wrong value", 0.0d, measure.getValue().doubleValue(), 0.0d); + } else if (s.equals(CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY)) { + Assert.assertEquals("Header Complexity in Functions has a wrong value", 0, measure.getIntValue().intValue()); + } else if (s.equals(CoreMetrics.FUNCTION_COMPLEXITY_KEY)) { + Assert.assertEquals("Header Functions Complexity has a wrong value", 0.0d, measure.getValue().doubleValue(), 0.0d); + } + } + + Assert.assertTrue("Key is not there", report.containsKey("App/Controller/Accelerate/AccelerationViewController.m")); + + List list2 = report.get("App/Controller/Accelerate/AccelerationViewController.m"); + Assert.assertEquals(5, list2.size()); + for (Measure measure : list2) { + String s = measure.getMetric().getKey(); + + if (s.equals(CoreMetrics.FUNCTIONS_KEY)) { + Assert.assertEquals("MFile Functions has a wrong value", 2, measure.getIntValue().intValue()); + } else if (s.equals(CoreMetrics.COMPLEXITY_KEY)) { + Assert.assertEquals("MFile Complexity has a wrong value", 6, measure.getIntValue().intValue()); + } else if (s.equals(CoreMetrics.FILE_COMPLEXITY_KEY)) { + Assert.assertEquals("MFile File Complexity has a wrong value", 6.0d, measure.getValue().doubleValue(), 0.0d); + } else if (s.equals(CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY)) { + Assert.assertEquals("MFile Complexity in Functions has a wrong value", 6, measure.getIntValue().intValue()); + } else if (s.equals(CoreMetrics.FUNCTION_COMPLEXITY_KEY)) { + Assert.assertEquals("MFile Functions Complexity has a wrong value", 3.0d, measure.getValue().doubleValue(), 0.0d); + } + } + } + + /** + * this method test that the parser shoud not return anything if the xml report is corrupted + */ + @Test + public void parseReportShouldReturnNullWhenXMLFileIsIncorrect() { + LizardReportParser parser = new LizardReportParser(); + + Assert.assertNotNull("correct file is null", incorrectFile); + + Map> report = parser.parseReport(incorrectFile); + Assert.assertNull("report is not null", report); + + } + +} \ No newline at end of file diff --git a/sonar-objective-c-plugin/src/test/resources/Profile.m b/sonar-objective-c-plugin/src/test/resources/Profile.m new file mode 100644 index 00000000..8ae3d092 --- /dev/null +++ b/sonar-objective-c-plugin/src/test/resources/Profile.m @@ -0,0 +1,39 @@ +// +// Profile.m +// Stop-tabac +// +// Created by François HELG on 5/29/12. +// Copyright (c) 2012 Université de Genève. All rights reserved. +// + +#import "Profile.h" +#import "Purchase.h" + + +@implementation Profile + +@dynamic cigaretteCounter; +@dynamic dailyCost; +@dynamic facebookOff; +@dynamic firstCigaretteAfterWakeUp; +@dynamic godfatherId; +@dynamic godfatherName; +@dynamic hasQuitSmoking; +@dynamic lifeCounter; +@dynamic nbOfSmokedCigarettesPerDay; +@dynamic nextCoachMessageToDisplay; +@dynamic nextFailureMessageToDisplay; +@dynamic nextCravingMessageToDisplay; +@dynamic quitSmokingDate; +@dynamic substitute; +@dynamic purchase; +@dynamic dependencyLevel; +@dynamic deliverSubstituteMessages; +@dynamic lastAchievementDayFilename; +@dynamic lastAchievementAssiduityFilename; +@dynamic lastAchievementWillingnessFilename; +@dynamic numberOfConnexions; +@dynamic numberOfAdvicesTaken; +@dynamic numberOfFailures; + +@end \ No newline at end of file diff --git a/sonar-objective-c-plugin/src/test/resources/objcSample.h b/sonar-objective-c-plugin/src/test/resources/objcSample.h new file mode 100644 index 00000000..cb3ce09b --- /dev/null +++ b/sonar-objective-c-plugin/src/test/resources/objcSample.h @@ -0,0 +1,17 @@ +// +// STWelcomeViewController.h +// Stop-tabac +// +// Created by François HELG on 5/7/12. +// Copyright (c) 2012 Université de Genève. All rights reserved. +// + +#import +// NOSONAR +@class Profile; + +@interface StillSmokingViewController : UIViewController + +@property (strong, nonatomic) Profile *userProfile; + +@end \ No newline at end of file diff --git a/src/main/java/org/sonar/objectivec/parser/ObjectiveCGrammarImpl.java b/src/main/java/org/sonar/objectivec/parser/ObjectiveCGrammarImpl.java deleted file mode 100644 index 14bb779f..00000000 --- a/src/main/java/org/sonar/objectivec/parser/ObjectiveCGrammarImpl.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.objectivec.parser; - -import static com.sonar.sslr.api.GenericTokenType.EOF; -import static com.sonar.sslr.api.GenericTokenType.LITERAL; -import static com.sonar.sslr.impl.matcher.GrammarFunctions.Standard.o2n; - -import org.sonar.objectivec.api.ObjectiveCGrammar; - -public class ObjectiveCGrammarImpl extends ObjectiveCGrammar { - - public ObjectiveCGrammarImpl() { - - program.is(o2n(LITERAL), EOF); - - } - -} diff --git a/src/main/java/org/sonar/objectivec/parser/ObjectiveCParser.java b/src/main/java/org/sonar/objectivec/parser/ObjectiveCParser.java deleted file mode 100644 index 6f0d2c19..00000000 --- a/src/main/java/org/sonar/objectivec/parser/ObjectiveCParser.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.objectivec.parser; - -import org.sonar.objectivec.ObjectiveCConfiguration; -import org.sonar.objectivec.api.ObjectiveCGrammar; -import org.sonar.objectivec.lexer.ObjectiveCLexer; - -import com.sonar.sslr.impl.Parser; -import com.sonar.sslr.impl.events.ParsingEventListener; - -public class ObjectiveCParser { - - private ObjectiveCParser() { - } - - public static Parser create(ParsingEventListener... parsingEventListeners) { - return create(new ObjectiveCConfiguration(), parsingEventListeners); - } - - public static Parser create(ObjectiveCConfiguration conf, ParsingEventListener... parsingEventListeners) { - return Parser.builder((ObjectiveCGrammar) new ObjectiveCGrammarImpl()) - .withLexer(ObjectiveCLexer.create(conf)) - .setParsingEventListeners(parsingEventListeners).build(); - } - -} diff --git a/src/main/java/org/sonar/plugins/objectivec/ObjectiveCPlugin.java b/src/main/java/org/sonar/plugins/objectivec/ObjectiveCPlugin.java deleted file mode 100644 index 8fa3b673..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/ObjectiveCPlugin.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec; - -import java.util.List; - -import org.sonar.api.Extension; -import org.sonar.api.Properties; -import org.sonar.api.Property; -import org.sonar.api.SonarPlugin; -import org.sonar.plugins.objectivec.coverage.CoberturaSensor; -import org.sonar.plugins.objectivec.colorizer.ObjectiveCColorizerFormat; -import org.sonar.plugins.objectivec.core.ObjectiveC; -import org.sonar.plugins.objectivec.core.ObjectiveCSourceImporter; -import org.sonar.plugins.objectivec.cpd.ObjectiveCCpdMapping; - -import com.google.common.collect.ImmutableList; - -import org.sonar.plugins.objectivec.tests.SurefireSensor; -import org.sonar.plugins.objectivec.violations.OCLintProfile; -import org.sonar.plugins.objectivec.violations.OCLintProfileImporter; -import org.sonar.plugins.objectivec.violations.OCLintRuleRepository; -import org.sonar.plugins.objectivec.violations.OCLintSensor; - -@Properties({ - @Property(key = CoberturaSensor.REPORT_PATTERN_KEY, defaultValue = CoberturaSensor.DEFAULT_REPORT_PATTERN, name = "Path to unit test coverage report(s)", description = "Relative to projects' root. Ant patterns are accepted", global = false, project = true), - @Property(key = OCLintSensor.REPORT_PATH_KEY, defaultValue = OCLintSensor.DEFAULT_REPORT_PATH, name = "Path to oclint pmd formatted report", description = "Relative to projects' root.", global = false, project = true) -}) -public class ObjectiveCPlugin extends SonarPlugin { - - public List> getExtensions() { - return ImmutableList.of(ObjectiveC.class, - ObjectiveCSourceImporter.class, - ObjectiveCColorizerFormat.class, - ObjectiveCCpdMapping.class, - - ObjectiveCSquidSensor.class, - ObjectiveCProfile.class, - SurefireSensor.class, - CoberturaSensor.class, - OCLintRuleRepository.class, - OCLintSensor.class, OCLintProfile.class, - OCLintProfileImporter.class - ); - } - - // Global Objective C constants - public static final String FALSE = "false"; - - public static final String FILE_SUFFIXES_KEY = "sonar.objectivec.file.suffixes"; - public static final String FILE_SUFFIXES_DEFVALUE = "h,m"; - - public static final String PROPERTY_PREFIX = "sonar.objectivec"; - - public static final String TEST_FRAMEWORK_KEY = PROPERTY_PREFIX - + ".testframework"; - public static final String TEST_FRAMEWORK_DEFAULT = "ghunit"; - -} diff --git a/src/main/java/org/sonar/plugins/objectivec/ObjectiveCProfile.java b/src/main/java/org/sonar/plugins/objectivec/ObjectiveCProfile.java deleted file mode 100644 index e223a48c..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/ObjectiveCProfile.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec; - -import org.sonar.api.profiles.AnnotationProfileParser; -import org.sonar.api.profiles.ProfileDefinition; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.utils.ValidationMessages; -import org.sonar.objectivec.checks.CheckList; -import org.sonar.plugins.objectivec.core.ObjectiveC; - -public class ObjectiveCProfile extends ProfileDefinition { - - private final AnnotationProfileParser annotationProfileParser; - - public ObjectiveCProfile(AnnotationProfileParser annotationProfileParser) { - this.annotationProfileParser = annotationProfileParser; - } - - @Override - public RulesProfile createProfile(ValidationMessages validation) { - return annotationProfileParser.parse(CheckList.REPOSITORY_KEY, CheckList.SONAR_WAY_PROFILE, ObjectiveC.KEY, CheckList.getChecks(), validation); - } - -} diff --git a/src/main/java/org/sonar/plugins/objectivec/ObjectiveCSquidSensor.java b/src/main/java/org/sonar/plugins/objectivec/ObjectiveCSquidSensor.java deleted file mode 100644 index 43bbb5e9..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/ObjectiveCSquidSensor.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec; - -import java.util.Collection; -import java.util.Locale; - -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.checks.AnnotationCheckFactory; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.PersistenceMode; -import org.sonar.api.measures.RangeDistributionBuilder; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.resources.File; -import org.sonar.api.resources.InputFileUtils; -import org.sonar.api.resources.Project; -import org.sonar.api.rules.Violation; -import org.sonar.objectivec.ObjectiveCAstScanner; -import org.sonar.objectivec.ObjectiveCConfiguration; -import org.sonar.objectivec.api.ObjectiveCGrammar; -import org.sonar.objectivec.api.ObjectiveCMetric; -import org.sonar.objectivec.checks.CheckList; -import org.sonar.plugins.objectivec.core.ObjectiveC; -import org.sonar.squidbridge.AstScanner; -import org.sonar.squidbridge.api.CheckMessage; -import org.sonar.squidbridge.api.SourceCode; -import org.sonar.squidbridge.api.SourceFile; -import org.sonar.squidbridge.api.SourceFunction; -import org.sonar.squidbridge.checks.SquidCheck; -import org.sonar.squidbridge.indexer.QueryByParent; -import org.sonar.squidbridge.indexer.QueryByType; -import org.sonar.squidbridge.measures.Metric; - - -public class ObjectiveCSquidSensor implements Sensor { - - private final Number[] FUNCTIONS_DISTRIB_BOTTOM_LIMITS = {1, 2, 4, 6, 8, 10, 12, 20, 30}; - private final Number[] FILES_DISTRIB_BOTTOM_LIMITS = {0, 5, 10, 20, 30, 60, 90}; - - private final AnnotationCheckFactory annotationCheckFactory; - - private Project project; - private SensorContext context; - private AstScanner scanner; - - public ObjectiveCSquidSensor(RulesProfile profile) { - this.annotationCheckFactory = AnnotationCheckFactory.create(profile, CheckList.REPOSITORY_KEY, CheckList.getChecks()); - } - - public boolean shouldExecuteOnProject(Project project) { - return ObjectiveC.KEY.equals(project.getLanguageKey()); - } - - public void analyse(Project project, SensorContext context) { - this.project = project; - this.context = context; - - Collection squidChecks = annotationCheckFactory.getChecks(); - this.scanner = ObjectiveCAstScanner.create(createConfiguration(project), squidChecks.toArray(new SquidCheck[squidChecks.size()])); - scanner.scanFiles(InputFileUtils.toFiles(project.getFileSystem().mainFiles(ObjectiveC.KEY))); - - Collection squidSourceFiles = scanner.getIndex().search(new QueryByType(SourceFile.class)); - save(squidSourceFiles); - } - - private ObjectiveCConfiguration createConfiguration(Project project) { - return new ObjectiveCConfiguration(project.getFileSystem().getSourceCharset()); - } - - private void save(Collection squidSourceFiles) { - for (SourceCode squidSourceFile : squidSourceFiles) { - SourceFile squidFile = (SourceFile) squidSourceFile; - - File sonarFile = File.fromIOFile(new java.io.File(squidFile.getKey()), project); - - saveFilesComplexityDistribution(sonarFile, squidFile); - saveFunctionsComplexityDistribution(sonarFile, squidFile); - saveMeasures(sonarFile, squidFile); - saveViolations(sonarFile, squidFile); - } - } - - private void saveMeasures(File sonarFile, SourceFile squidFile) { - context.saveMeasure(sonarFile, CoreMetrics.FILES, squidFile.getDouble(ObjectiveCMetric.FILES)); - context.saveMeasure(sonarFile, CoreMetrics.LINES, squidFile.getDouble(ObjectiveCMetric.LINES)); - context.saveMeasure(sonarFile, CoreMetrics.NCLOC, squidFile.getDouble(ObjectiveCMetric.LINES_OF_CODE)); - context.saveMeasure(sonarFile, CoreMetrics.FUNCTIONS, squidFile.getDouble(ObjectiveCMetric.FUNCTIONS)); - context.saveMeasure(sonarFile, CoreMetrics.STATEMENTS, squidFile.getDouble(ObjectiveCMetric.STATEMENTS)); - context.saveMeasure(sonarFile, CoreMetrics.COMPLEXITY, squidFile.getDouble(ObjectiveCMetric.COMPLEXITY)); - context.saveMeasure(sonarFile, CoreMetrics.COMMENT_LINES, squidFile.getDouble(ObjectiveCMetric.COMMENT_LINES)); - } - - private void saveFunctionsComplexityDistribution(File sonarFile, SourceFile squidFile) { - Collection squidFunctionsInFile = scanner.getIndex().search(new QueryByParent(squidFile), new QueryByType(SourceFunction.class)); - RangeDistributionBuilder complexityDistribution = new RangeDistributionBuilder(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION, FUNCTIONS_DISTRIB_BOTTOM_LIMITS); - for (SourceCode squidFunction : squidFunctionsInFile) { - complexityDistribution.add(squidFunction.getDouble(ObjectiveCMetric.COMPLEXITY)); - } - context.saveMeasure(sonarFile, complexityDistribution.build().setPersistenceMode(PersistenceMode.MEMORY)); - } - - private void saveFilesComplexityDistribution(File sonarFile, SourceFile squidFile) { - RangeDistributionBuilder complexityDistribution = new RangeDistributionBuilder(CoreMetrics.FILE_COMPLEXITY_DISTRIBUTION, FILES_DISTRIB_BOTTOM_LIMITS); - complexityDistribution.add(squidFile.getDouble(ObjectiveCMetric.COMPLEXITY)); - context.saveMeasure(sonarFile, complexityDistribution.build().setPersistenceMode(PersistenceMode.MEMORY)); - } - - private void saveViolations(File sonarFile, SourceFile squidFile) { - Collection messages = squidFile.getCheckMessages(); - if (messages != null) { - for (CheckMessage message : messages) { - Violation violation = Violation.create(annotationCheckFactory.getActiveRule(message.getChecker()), sonarFile) - .setLineId(message.getLine()) - .setMessage(message.getText(Locale.ENGLISH)); - context.saveViolation(violation); - } - } - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - -} diff --git a/src/main/java/org/sonar/plugins/objectivec/core/ObjectiveCSourceImporter.java b/src/main/java/org/sonar/plugins/objectivec/core/ObjectiveCSourceImporter.java deleted file mode 100644 index f8776a20..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/core/ObjectiveCSourceImporter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.core; - -import org.sonar.api.batch.AbstractSourceImporter; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.InputFileUtils; -import org.sonar.api.resources.ProjectFileSystem; - -public class ObjectiveCSourceImporter extends AbstractSourceImporter { - - public ObjectiveCSourceImporter(ObjectiveC objectivec) { - super(objectivec); - } - - protected void analyse(ProjectFileSystem fileSystem, SensorContext context) { - parseDirs(context, InputFileUtils.toFiles(fileSystem.mainFiles(ObjectiveC.KEY)), fileSystem.getSourceDirs(), false, fileSystem.getSourceCharset()); - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaParser.java b/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaParser.java deleted file mode 100644 index cd333d32..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaParser.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.coverage; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.stream.XMLStreamException; - -import org.slf4j.LoggerFactory; -import org.sonar.api.measures.CoverageMeasuresBuilder; -import org.sonar.api.utils.StaxParser; - -final class CoberturaParser { - public Map parseReport(final File xmlFile) { - Map result = null; - try { - final InputStream reportStream = new FileInputStream(xmlFile); - result = parseReport(reportStream); - reportStream.close(); - } catch (final IOException e) { - LoggerFactory.getLogger(getClass()).error( - "Error processing file named {}", xmlFile, e); - result = new HashMap(); - } - return result; - } - - public Map parseReport( - final InputStream xmlFile) { - - final Map measuresForReport = new HashMap(); - try { - final StaxParser parser = new StaxParser( - new CoberturaXMLStreamHandler(measuresForReport)); - parser.parse(xmlFile); - } catch (final XMLStreamException e) { - LoggerFactory.getLogger(getClass()).error( - "Error while parsing XML stream.", e); - } - return measuresForReport; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.java b/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.java deleted file mode 100644 index 0a900b2b..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.coverage; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; - -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.config.Settings; -import org.sonar.api.measures.CoverageMeasuresBuilder; -import org.sonar.api.resources.Project; -import org.sonar.plugins.objectivec.ObjectiveCPlugin; -import org.sonar.plugins.objectivec.core.ObjectiveC; - - -public final class CoberturaSensor implements Sensor { - - public static final String REPORT_PATTERN_KEY = ObjectiveCPlugin.PROPERTY_PREFIX - + ".coverage.reportPattern"; - public static final String DEFAULT_REPORT_PATTERN = "sonar-reports/coverage*.xml"; - - private final ReportFilesFinder reportFilesFinder; - private final CoberturaParser parser = new CoberturaParser(); - - private final Settings conf; - private final FileSystem fileSystem; - - public CoberturaSensor(final FileSystem fileSystem, final Settings config) { - - this.conf = config; - this.fileSystem = fileSystem; - - reportFilesFinder = new ReportFilesFinder(config, REPORT_PATTERN_KEY, DEFAULT_REPORT_PATTERN); - } - - public boolean shouldExecuteOnProject(final Project project) { - - return project.isRoot() && fileSystem.languages().contains(ObjectiveC.KEY); - } - - public void analyse(final Project project, final SensorContext context) { - final CoverageMeasuresPersistor measuresPersistor = new CoverageMeasuresPersistor( - project, context); - final String projectBaseDir = project.getFileSystem().getBasedir() - .getPath(); - - measuresPersistor.saveMeasures(parseReportsIn(projectBaseDir)); - } - - private Map parseReportsIn( - final String baseDir) { - final Map measuresTotal = new HashMap(); - - for (final File report : reportFilesFinder.reportsIn(baseDir)) { - LoggerFactory.getLogger(getClass()).info( - "Processing coverage report {}", report); - measuresTotal.putAll(parser.parseReport(report)); - } - - return measuresTotal; - } - -} diff --git a/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.old b/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.old deleted file mode 100644 index 1cdb1303..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaSensor.old +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ - -package org.sonar.plugins.objectivec.coverage; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.AbstractCoverageExtension; -import org.sonar.api.batch.CoverageExtension; -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.plugins.cobertura.api.AbstractCoberturaParser; -import org.sonar.plugins.cobertura.api.CoberturaUtils; -import org.sonar.plugins.objectivec.core.ObjectiveC; - -import java.io.File; - -public class CoberturaSensor implements Sensor { - - private static final Logger LOG = LoggerFactory.getLogger(CoberturaSensor.class); - - public CoberturaSensor() { - } - - public boolean shouldExecuteOnProject(Project project) { - return ObjectiveC.KEY.equals(project.getLanguageKey()); - } - - public void analyse(Project project, SensorContext context) { - File report = CoberturaUtils.getReport(project); - if (report != null) { - parseReport(report, context); - } - } - - protected void parseReport(File xmlFile, final SensorContext context) { - LOG.info("parsing {}", xmlFile); - COBERTURA_PARSER.parseReport(xmlFile, context); - } - - private static final AbstractCoberturaParser COBERTURA_PARSER = new AbstractCoberturaParser() { - @Override - protected Resource getResource(String fileName) { - LOG.info("Analyzing {}", fileName); - fileName = fileName.replace(".", "/") + ".m"; - return new org.sonar.api.resources.File(fileName); - } - }; - - @Override - public String toString() { - return "Objective-C CoberturaSensor"; - } - -} \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaXMLStreamHandler.java b/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaXMLStreamHandler.java deleted file mode 100644 index 44501a4c..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/coverage/CoberturaXMLStreamHandler.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.coverage; - -import java.util.Map; - -import javax.xml.stream.XMLStreamException; - -import org.apache.commons.lang.StringUtils; -import org.codehaus.staxmate.in.SMHierarchicCursor; -import org.codehaus.staxmate.in.SMInputCursor; -import org.sonar.api.measures.CoverageMeasuresBuilder; -import org.sonar.api.utils.StaxParser; - -class CoberturaXMLStreamHandler implements StaxParser.XmlStreamHandler { - private final Map measuresForReport; - - public CoberturaXMLStreamHandler( - final Map data) { - measuresForReport = data; - } - - public void stream(final SMHierarchicCursor rootCursor) - throws XMLStreamException { - rootCursor.advance(); - collectPackageMeasures(rootCursor.descendantElementCursor("package")); - } - - private void collectPackageMeasures(final SMInputCursor pack) - throws XMLStreamException { - while (pack.getNext() != null) { - collectFileMeasures(pack.descendantElementCursor("class")); - } - } - - private void collectFileMeasures(final SMInputCursor clazz) - throws XMLStreamException { - while (clazz.getNext() != null) { - collectFileData(clazz); - } - } - - private void collectFileData(final SMInputCursor clazz) - throws XMLStreamException { - final CoverageMeasuresBuilder builder = builderFor(clazz); - final SMInputCursor line = clazz.childElementCursor("lines").advance() - .childElementCursor("line"); - - while (null != line.getNext()) { - recordCoverageFor(line, builder); - } - } - - private void recordCoverageFor(final SMInputCursor line, - final CoverageMeasuresBuilder builder) throws XMLStreamException { - final int lineId = Integer.parseInt(line.getAttrValue("number")); - final int noHits = (int) Math.min( - Long.parseLong(line.getAttrValue("hits")), Integer.MAX_VALUE); - final String isBranch = line.getAttrValue("branch"); - final String conditionText = line.getAttrValue("condition-coverage"); - - builder.setHits(lineId, noHits); - - if (StringUtils.equals(isBranch, "true") - && StringUtils.isNotBlank(conditionText)) { - final String[] conditions = StringUtils.split( - StringUtils.substringBetween(conditionText, "(", ")"), "/"); - builder.setConditions(lineId, Integer.parseInt(conditions[1]), - Integer.parseInt(conditions[0])); - } - } - - private CoverageMeasuresBuilder builderFor(final SMInputCursor clazz) - throws XMLStreamException { - final String fileName = clazz.getAttrValue("filename"); - CoverageMeasuresBuilder builder = measuresForReport.get(fileName); - if (builder == null) { - builder = CoverageMeasuresBuilder.create(); - measuresForReport.put(fileName, builder); - } - return builder; - } -} \ No newline at end of file diff --git a/src/main/java/org/sonar/plugins/objectivec/coverage/CoverageMeasuresPersistor.java b/src/main/java/org/sonar/plugins/objectivec/coverage/CoverageMeasuresPersistor.java deleted file mode 100644 index d46ee0fa..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/coverage/CoverageMeasuresPersistor.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.coverage; - -import java.io.File; -import java.util.List; -import java.util.Map; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.measures.CoverageMeasuresBuilder; -import org.sonar.api.measures.Measure; -import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.PathResolver; -import org.sonar.api.utils.PathUtils; - -final class CoverageMeasuresPersistor { - private final Project project; - private final SensorContext context; - - public CoverageMeasuresPersistor(final Project p, final SensorContext c) { - project = p; - context = c; - } - - public void saveMeasures(final Map coverageMeasures) { - - for (final Map.Entry entry : coverageMeasures.entrySet()) { - saveMeasuresForFile(entry.getValue(), entry.getKey()); - } - } - - private void saveMeasuresForFile(final CoverageMeasuresBuilder measureBuilder, final String filePath) { - - LoggerFactory.getLogger(getClass()).debug("Saving measures for {}", filePath); - final org.sonar.api.resources.File objcfile = org.sonar.api.resources.File.fromIOFile(new File(project.getFileSystem().getBasedir(), filePath), project); - - if (fileExists(context, objcfile)) { - LoggerFactory.getLogger(getClass()).debug( - "File {} was found in the project.", filePath); - saveMeasures(measureBuilder, objcfile); - } - } - - private void saveMeasures(final CoverageMeasuresBuilder measureBuilder, - final org.sonar.api.resources.File objcfile) { - for (final Measure measure : measureBuilder.createMeasures()) { - LoggerFactory.getLogger(getClass()).debug("Measure {}", - measure.getMetric().getName()); - context.saveMeasure(objcfile, measure); - } - } - - private boolean fileExists(final SensorContext context, - final org.sonar.api.resources.File file) { - return context.getResource(file) != null; - } -} diff --git a/src/main/java/org/sonar/plugins/objectivec/tests/SurefireParser.java b/src/main/java/org/sonar/plugins/objectivec/tests/SurefireParser.java deleted file mode 100644 index b566a92a..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/tests/SurefireParser.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ - -package org.sonar.plugins.objectivec.tests; - -import com.sun.swing.internal.plaf.metal.resources.metal_sv; -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Resource; -import org.sonar.api.utils.ParsingUtils; -import org.sonar.api.utils.StaxParser; -import org.sonar.api.utils.XmlParserException; -import org.sonar.plugins.surefire.TestCaseDetails; -import org.sonar.plugins.surefire.TestSuiteParser; -import org.sonar.plugins.surefire.TestSuiteReport; - -import javax.xml.transform.TransformerException; -import java.io.File; -import java.io.FilenameFilter; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * Created by gillesgrousset on 06/01/15. - */ -public class SurefireParser { - - public void collect(Project project, SensorContext context, File reportsDir) { - File[] xmlFiles = getReports(reportsDir); - - if (xmlFiles.length == 0) { - insertZeroWhenNoReports(project, context); - } else { - parseFiles(context, xmlFiles); - } - } - - private File[] getReports(File dir) { - if (dir == null || !dir.isDirectory() || !dir.exists()) { - return new File[0]; - } - - File[] list = dir.listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.startsWith("TEST") && name.endsWith(".xml"); - } - }); - - return dir.listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.startsWith("TEST") && name.endsWith(".xml"); - } - }); - } - - private void insertZeroWhenNoReports(Project pom, SensorContext context) { - if ( !StringUtils.equalsIgnoreCase("pom", pom.getPackaging())) { - context.saveMeasure(CoreMetrics.TESTS, 0.0); - } - } - - private void parseFiles(SensorContext context, File[] reports) { - Set analyzedReports = new HashSet(); - try { - for (File report : reports) { - TestSuiteParser parserHandler = new TestSuiteParser(); - StaxParser parser = new StaxParser(parserHandler, false); - parser.parse(report); - - for (TestSuiteReport fileReport : parserHandler.getParsedReports()) { - if ( !fileReport.isValid() || analyzedReports.contains(fileReport)) { - continue; - } - if (fileReport.getTests() > 0) { - double testsCount = fileReport.getTests() - fileReport.getSkipped(); - saveClassMeasure(context, fileReport, CoreMetrics.SKIPPED_TESTS, fileReport.getSkipped()); - saveClassMeasure(context, fileReport, CoreMetrics.TESTS, testsCount); - saveClassMeasure(context, fileReport, CoreMetrics.TEST_ERRORS, fileReport.getErrors()); - saveClassMeasure(context, fileReport, CoreMetrics.TEST_FAILURES, fileReport.getFailures()); - saveClassMeasure(context, fileReport, CoreMetrics.TEST_EXECUTION_TIME, fileReport.getTimeMS()); - double passedTests = testsCount - fileReport.getErrors() - fileReport.getFailures(); - if (testsCount > 0) { - double percentage = passedTests * 100d / testsCount; - saveClassMeasure(context, fileReport, CoreMetrics.TEST_SUCCESS_DENSITY, ParsingUtils.scaleValue(percentage)); - } - saveTestsDetails(context, fileReport); - analyzedReports.add(fileReport); - } - } - } - - } catch (Exception e) { - throw new XmlParserException("Can not parse surefire reports", e); - } - } - - private void saveTestsDetails(SensorContext context, TestSuiteReport fileReport) throws TransformerException { - StringBuilder testCaseDetails = new StringBuilder(256); - testCaseDetails.append(""); - List details = fileReport.getDetails(); - for (TestCaseDetails detail : details) { - testCaseDetails.append("") - .append(isError ? "") - .append("") - .append(isError ? "" : "").append(""); - } else { - testCaseDetails.append("/>"); - } - } - testCaseDetails.append(""); - context.saveMeasure(getUnitTestResource(fileReport.getClassKey()), new Measure(CoreMetrics.TEST_DATA, testCaseDetails.toString())); - } - - private void saveClassMeasure(SensorContext context, TestSuiteReport fileReport, Metric metric, double value) { - if ( !Double.isNaN(value)) { - - String basename = fileReport.getClassKey().replace('.', '/'); - - // .m file - context.saveMeasure(getUnitTestResource(basename + ".m"), metric, value); - - // Try .m file with + in name - try { - context.saveMeasure(getUnitTestResource(basename.replace('_', '+') + ".m"), metric, value); - } catch (Exception e) { - // Nothing : File was probably already registered successfully - } - } - } - - public Resource getUnitTestResource(String filename) { - - org.sonar.api.resources.File sonarFile = new org.sonar.api.resources.File(filename); - sonarFile.setQualifier(Qualifiers.UNIT_TEST_FILE); - return sonarFile; - } -} diff --git a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintParser.java b/src/main/java/org/sonar/plugins/objectivec/violations/OCLintParser.java deleted file mode 100644 index a16b9278..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintParser.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; - -import javax.xml.stream.XMLStreamException; - -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.api.rules.Violation; -import org.sonar.api.utils.StaxParser; - -final class OCLintParser { - private final Project project; - private final SensorContext context; - - public OCLintParser(final Project p, final SensorContext c) { - project = p; - context = c; - } - - public Collection parseReport(final File file) { - Collection result; - try { - final InputStream reportStream = new FileInputStream(file); - result = parseReport(reportStream); - reportStream.close(); - } catch (final IOException e) { - LoggerFactory.getLogger(getClass()).error( - "Error processing file named {}", file, e); - result = new ArrayList(); - } - return result; - } - - public Collection parseReport(final InputStream inputStream) { - final Collection violations = new ArrayList(); - try { - final StaxParser parser = new StaxParser( - new OCLintXMLStreamHandler(violations, project, context)); - parser.parse(inputStream); - LoggerFactory.getLogger(getClass()).error( - "Reporting {} violations.", violations.size()); - } catch (final XMLStreamException e) { - LoggerFactory.getLogger(getClass()).error( - "Error while parsing XML stream.", e); - } - return violations; - } - -} diff --git a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintRuleParser.java b/src/main/java/org/sonar/plugins/objectivec/violations/OCLintRuleParser.java deleted file mode 100644 index 427090c0..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintRuleParser.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import java.io.BufferedReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.ServerComponent; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RulePriority; - -/** - * Largely copied from AndroidLint's equivalent class whose authors are Stephane - * Nicolas and Jerome Van Der Linden according to the class Javadoc. - * - */ -final class OCLintRuleParser implements ServerComponent { - - private static final int OCLINT_MINIMUM_PRIORITY = 4; - private static final Logger LOGGER = LoggerFactory - .getLogger(OCLintRuleParser.class); - - public List parse(final BufferedReader reader) throws IOException { - final List rules = new ArrayList(); - - final List listLines = IOUtils.readLines(reader); - - String previousLine = null; - Rule rule = null; - boolean inDescription = false; - for (String line : listLines) { - if (isLineIgnored(line)) { - inDescription = false; - } else if (line.matches("[\\-]{4,}.*")) { - LOGGER.debug("Rule found : {}", previousLine); - - // remove the rule name from the description of the previous - // rule - if (rule != null) { - final int index = rule.getDescription().lastIndexOf( - previousLine); - if (index > 0) { - rule.setDescription(rule.getDescription().substring(0, - index)); - } - } - - rule = Rule.create(); - rules.add(rule); - rule.setName(previousLine); - rule.setKey(previousLine); - } else if (line.matches("Summary:.*")) { - inDescription = true; - rule.setDescription(line.substring(line.indexOf(':') + 1)); - } else if (line.matches("Category:.*")) { - inDescription = true; - } else if (line.matches("Severity:.*")) { - inDescription = false; - final String severity = line.substring("Severity: ".length()); - // Rules are priority 1, 2 or 3 in OCLint files. - rule.setSeverity(RulePriority.values()[Integer.valueOf(severity)]); - } else { - if (inDescription) { - line = ruleDescriptionLink(line); - rule.setDescription(rule.getDescription() + "
" + line); - } - } - previousLine = line; - } - return rules; - } - - private boolean isLineIgnored(String line) { - return line.matches("\\=.*") || line.matches("Priority:.*"); - } - - private String ruleDescriptionLink(final String line) { - String result = line; - final int indexOfLink = line.indexOf("http://"); - if (0 <= indexOfLink) { - final String link = line.substring(indexOfLink); - final StringBuilder htmlText = new StringBuilder(""); - htmlText.append(link); - htmlText.append(""); - result = htmlText.toString(); - } - return result; - } -} diff --git a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintRuleRepository.java b/src/main/java/org/sonar/plugins/objectivec/violations/OCLintRuleRepository.java deleted file mode 100644 index 47920cea..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintRuleRepository.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.List; - -import org.apache.commons.lang.CharEncoding; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleRepository; -import org.sonar.api.utils.SonarException; -import org.sonar.plugins.objectivec.core.ObjectiveC; - -import com.google.common.io.Closeables; - -public final class OCLintRuleRepository extends RuleRepository { - public static final String REPOSITORY_KEY = "OCLint"; - public static final String REPOSITORY_NAME = REPOSITORY_KEY; - - private static final String RULES_FILE = "/org/sonar/plugins/oclint/rules.txt"; - - private final OCLintRuleParser ocLintRuleParser = new OCLintRuleParser(); - - public OCLintRuleRepository() { - super(OCLintRuleRepository.REPOSITORY_KEY, ObjectiveC.KEY); - setName(OCLintRuleRepository.REPOSITORY_NAME); - } - - @Override - public List createRules() { - BufferedReader reader = null; - try { - reader = new BufferedReader(new InputStreamReader(getClass() - .getResourceAsStream(RULES_FILE), CharEncoding.UTF_8)); - return ocLintRuleParser.parse(reader); - } catch (final IOException e) { - throw new SonarException("Fail to load the default OCLint rules.", - e); - } finally { - Closeables.closeQuietly(reader); - } - } -} diff --git a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintSensor.java b/src/main/java/org/sonar/plugins/objectivec/violations/OCLintSensor.java deleted file mode 100644 index 4847905f..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintSensor.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import java.io.File; -import java.util.Collection; - -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; -import org.sonar.api.rules.Violation; -import org.sonar.plugins.objectivec.ObjectiveCPlugin; -import org.sonar.plugins.objectivec.core.ObjectiveC; - -public final class OCLintSensor implements Sensor { - public static final String REPORT_PATH_KEY = ObjectiveCPlugin.PROPERTY_PREFIX - + ".oclint.report"; - public static final String DEFAULT_REPORT_PATH = "sonar-reports/oclint.xml"; - - private final Settings conf; - private final FileSystem fileSystem; - - public OCLintSensor(final FileSystem moduleFileSystem, final Settings config) { - this.conf = config; - this.fileSystem = moduleFileSystem; - } - - public boolean shouldExecuteOnProject(final Project project) { - - return project.isRoot() && fileSystem.languages().contains(ObjectiveC.KEY); - - } - - public void analyse(final Project project, final SensorContext context) { - final String projectBaseDir = project.getFileSystem().getBasedir() - .getPath(); - final OCLintParser parser = new OCLintParser(project, context); - saveViolations(parseReportIn(projectBaseDir, parser), context); - - } - - private void saveViolations(final Collection violations, - final SensorContext context) { - for (final Violation violation : violations) { - context.saveViolation(violation); - } - } - - private Collection parseReportIn(final String baseDir, - final OCLintParser parser) { - final StringBuilder reportFileName = new StringBuilder(baseDir); - reportFileName.append("/").append(reportPath()); - - LoggerFactory.getLogger(getClass()).info("Processing OCLint report {}", - reportFileName); - return parser.parseReport(new File(reportFileName.toString())); - } - - private String reportPath() { - String reportPath = conf.getString(REPORT_PATH_KEY); - if (reportPath == null) { - reportPath = DEFAULT_REPORT_PATH; - } - return reportPath; - } -} diff --git a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintXMLStreamHandler.java b/src/main/java/org/sonar/plugins/objectivec/violations/OCLintXMLStreamHandler.java deleted file mode 100644 index 0847046b..00000000 --- a/src/main/java/org/sonar/plugins/objectivec/violations/OCLintXMLStreamHandler.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import java.io.File; -import java.util.Collection; - -import javax.xml.stream.XMLStreamException; - -import org.codehaus.staxmate.in.SMHierarchicCursor; -import org.codehaus.staxmate.in.SMInputCursor; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.rules.Violation; -import org.sonar.api.utils.StaxParser.XmlStreamHandler; - -final class OCLintXMLStreamHandler implements XmlStreamHandler { - private static final int PMD_MINIMUM_PRIORITY = 5; - private final Collection foundViolations; - private final Project project; - private final SensorContext context; - - public OCLintXMLStreamHandler(final Collection violations, - final Project p, final SensorContext c) { - foundViolations = violations; - project = p; - context = c; - } - - public void stream(final SMHierarchicCursor rootCursor) - throws XMLStreamException { - final SMInputCursor file = rootCursor.advance().childElementCursor( - "file"); - - while (null != file.getNext()) { - collectViolationsFor(file); - } - } - - private void collectViolationsFor(final SMInputCursor file) - throws XMLStreamException { - final String filePath = file.getAttrValue("name"); - LoggerFactory.getLogger(getClass()).debug( - "Collection violations for {}", filePath); - final org.sonar.api.resources.File resource = findResource(filePath); - if (fileExists(resource)) { - LoggerFactory.getLogger(getClass()).debug( - "File {} was found in the project.", filePath); - collectFileViolations(resource, file); - } - } - - private org.sonar.api.resources.File findResource(final String filePath) { - return org.sonar.api.resources.File.fromIOFile(new File(filePath), - project); - } - - private void collectFileViolations( - final org.sonar.api.resources.File resource, - final SMInputCursor file) throws XMLStreamException { - final SMInputCursor line = file.childElementCursor("violation"); - - while (null != line.getNext()) { - recordViolation(resource, line); - } - } - - private void recordViolation(final org.sonar.api.resources.File resource, - final SMInputCursor line) throws XMLStreamException { - final Rule rule = Rule.create(); - final Violation violation = Violation.create(rule, resource); - - // PMD Priorities are 1, 2, 3, 4, 5 RulePriority[0] is INFO - rule.setSeverity(RulePriority.values()[PMD_MINIMUM_PRIORITY - - Integer.valueOf(line.getAttrValue("priority"))]); - rule.setKey(line.getAttrValue("rule")); - rule.setRepositoryKey(OCLintRuleRepository.REPOSITORY_KEY); - - violation.setLineId(Integer.valueOf(line.getAttrValue("beginline"))); - - violation.setMessage(line.getElemStringValue()); - - foundViolations.add(violation); - } - - private boolean fileExists(final org.sonar.api.resources.File file) { - return context.getResource(file) != null; - } - -} diff --git a/src/main/resources/org/sonar/plugins/oclint/rules.txt b/src/main/resources/org/sonar/plugins/oclint/rules.txt deleted file mode 100644 index beb11d6b..00000000 --- a/src/main/resources/org/sonar/plugins/oclint/rules.txt +++ /dev/null @@ -1,509 +0,0 @@ -Available issues: - -OCLint -====== - -use early exits and continue ----------- - -Summary: - -Severity: 2 -Category: OCLint - -avoid branching statement as last in loop ----------- - -Summary: Having branching statement as the last statement inside a loop is very confusing, and could largely be forgetting of something and turning into a bug. - -Severity: 2 -Category: OCLint - -bitwise operator in conditional ----------- - -Summary: Checks for bitwise operations in conditionals. Although being written on purpose in some rare cases, bitwise operations are considered to be too “smart”. Smart code is not easy to understand. - -Severity: 3 -Category: OCLint - -broken null check ----------- - -Summary: The broken nil check in Objective-C in some cases returns just the opposite result. - -Severity: 4 -Category: OCLint - -broken nil check ----------- - -Summary: - -Severity: 4 -Category: OCLint - -broken oddness check ----------- - -Summary: Checking oddness by x%2==1 won’t work for negative numbers. Use x&1==1, or x%2!=0 instead. - -Severity: 3 -Category: OCLint - -collapsible if statements ----------- - -Summary: This rule detects instances where the conditions of two consecutive if statements can combined into one in order to increase code cleanness and readability. - -Severity: 3 -Category: OCLint - -constant conditional operator ----------- - -Summary: conditionaloperator whose conditionals are always true or always false are confusing. - -Severity: 3 -Category: OCLint - -constant if expression ----------- - -Summary: if statements whose conditionals are always true or always false are confusing. - -Severity: 3 -Category: OCLint - -high cyclomatic complexity ----------- - -Summary: - -Severity: 2 -Category: OCLint - -dead code ----------- - -Summary: Code after return, break, continue, and throw statements are unreachable and will never be executed. - -Severity: 3 -Category: OCLint - -default label not last in switch statement ----------- - -Summary: It is very confusing when default label is not the last label in a switch statement. - -Severity: 2 -Category: OCLint - -double negative ----------- - -Summary: There is no point in using a double negative, it is always positive. - -Severity: 3 -Category: OCLint - -empty catch statement ----------- - -Summary: This rule detects instances where an exception is caught, but nothing is done about it. - -Severity: 3 -Category: OCLint - -empty do/while statement ----------- - -Summary: This rule detects instances where a do-while statement does nothing. - -Severity: 3 -Category: OCLint - -empty else block ----------- - -Summary: - -Severity: 2 -Category: OCLint - -empty finally statement ----------- - -Summary: This rule detects instances where a finally statement does nothing. - -Severity: 3 -Category: OCLint - -empty for statement ----------- - -Summary: This rule detects instances where a for statement does nothing. - -Severity: 3 -Category: OCLint - -empty if statement ----------- - -Summary: This rule detects instances where a condition is checked, but nothing is done about it. - -Severity: 3 -Category: OCLint - -empty switch statement ----------- - -Summary: This rule detects instances where a switch statement does nothing. - -Severity: 3 -Category: OCLint - -empty try statement ----------- - -Summary: This rule detects instances where a try statement is empty. - -Severity: 3 -Category: OCLint - -empty while statement ----------- - -Summary: - -Severity: 3 -Category: OCLint - -feature envy ----------- - -Summary: - -Severity: 3 -Category: OCLint - -for loop should be while loop ----------- - -Summary: Under certain circumstances, some for loops can be simplified to while loops to make code more concise. - -Severity: 3 -Category: OCLint - -goto statement ----------- - -Summary: - -Severity: 3 -Category: OCLint - -inverted logic ----------- - -Summary: An inverted logic is hard to understand. - -Severity: 2 -Category: OCLint - -jumbled incrementer ----------- - -Summary: - -Severity: 2 -Category: OCLint - -long class ----------- - -Summary: Long class generally indicates that this class tries to so many things. Each class should do one thing and one thing well. - -Severity: 3 -Category: OCLint - -long line ----------- - -Summary: When number of characters for one line of code is very long, it largely harm the readability. Break long line of code into multiple lines. - -Severity: 2 -Category: OCLint - -long method ----------- - -Summary: Long method generally indicates that this method tries to so many things. Each method should do one thing and one thing well. - -Severity: 3 -Category: OCLint - -long variable name ----------- - -Summary: Variables with long names harm readability. - -Severity: 2 -Category: OCLint - -misplaced null check ----------- - -Summary: The nil check is misplaced. In Objective-C, sending a message to a nil pointer simply does nothing. But code readers may be confused about the misplaced nil check. - -Severity: 3 -Category: OCLint - -misplaced nil check ----------- - -Summary: - -Severity: 4 -Category: OCLint - -missing break in switch statement ----------- - -Summary: - -Severity: 2 -Category: OCLint - -multiple unary operator ----------- - -Summary: Multiple unary operator can always be confusing and should be simplified. - -Severity: 3 -Category: OCLint - -must override hash with isEqual ----------- - -Summary: - -Severity: 1 -Category: OCLint - -high ncss method ----------- - -Summary: This rule counts number of lines for a method by counting Non Commenting Source Statements (NCSS). NCSS only takes actual statements into consideration, in other words, ignores empty statements, empty blocks, closing brackets or semicolons after closing brackets. Meanwhile, statement that is break into multiple lines contribute only one count. - -Severity: 3 -Category: OCLint - -deep nested block ----------- - -Summary: This rule indicates blocks nested more deeply than the upper limit. - -Severity: 3 -Category: OCLint - -non case label in switch statement ----------- - -Summary: It is very confusing when default label is not the last label in a switch statement. - -Severity: 2 -Category: OCLint - -high npath complexity ----------- - -Summary: - -Severity: 2 -Category: OCLint - -replace with boxed expression ----------- - -Summary: This rule locates the places that can be migrated to the new Objective-C literals with boxed expressions. - -Severity: 1 -Category: OCLint - -replace with container literal ----------- - -Summary: This rule locates the places that can be migrated to the new Objective-C literals with container literals. - -Severity: 1 -Category: OCLint - -replace with number literal ----------- - -Summary: This rule locates the places that can be migrated to the new Objective-C literals with number literals. - -Severity: 1 -Category: OCLint - -replace with object subscripting ----------- - -Summary: - -Severity: 1 -Category: OCLint - -parameter reassignment ----------- - -Summary: Reassigning values to parameters is very problematic in most cases. - -Severity: 2 -Category: OCLint - -redundant conditional operator ----------- - -Summary: This rule detects three types of redundant conditional operators: - -Severity: 1 -Category: OCLint - -redundant if statement ----------- - -Summary: This rule detects unnecessary if statements. - -Severity: 1 -Category: OCLint - -redundant local variable ----------- - -Summary: This rule detects cases where a variable declaration immediately followed by a return of that variable. - -Severity: 1 -Category: OCLint - -redundant nil check ----------- - -Summary: - -Severity: 3 -Category: OCLint - -return from finally block ----------- - -Summary: Returning from a finally block is not recommended. - -Severity: 3 -Category: OCLint - -short variable name ----------- - -Summary: - -Severity: 2 -Category: OCLint - -switch statements don't need default when fully covered ----------- - -Summary: - -Severity: 3 -Category: OCLint - -switch statements should have default ----------- - -Summary: Switch statements should a default statement. - -Severity: 2 -Category: OCLint - -throw exception from finally block ----------- - -Summary: - -Severity: 3 -Category: OCLint - -too few branches in switch statement ----------- - -Summary: - -Severity: 2 -Category: OCLint - -too many fields ----------- - -Summary: A class with too many fields indicates it does too many things and is lack of proper abstraction. It can be resigned to have fewer fields. - -Severity: 3 -Category: OCLint - -too many methods ----------- - -Summary: A class with too many methods indicates it does too many things and hard to read and understand. It usually contains complicated code, and should be refactored. - -Severity: 3 -Category: OCLint - -too many parameters ----------- - -Summary: - -Severity: 3 -Category: OCLint - -unnecessary else statement ----------- - -Summary: When an if statement block ends with a return statement, or all branches in the if statement block end with return statements, then the else statement is unnecessary. The code in the else statement can be run without being in the block. - -Severity: 1 -Category: OCLint - -unused local variable ----------- - -Summary: This rule detects local variables that are declared, but not used. - -Severity: 0 -Category: OCLint - -unused method parameter ----------- - -Summary: - -Severity: 0 -Category: OCLint - -useless parentheses ----------- - -Summary: - -Severity: 1 -Category: OCLint - -ivar assignment outside accessors or init ----------- - -Summary: - -Severity: 2 -Category: OCLint - diff --git a/src/main/shell/run-sonar.sh b/src/main/shell/run-sonar.sh deleted file mode 100755 index fef70fd4..00000000 --- a/src/main/shell/run-sonar.sh +++ /dev/null @@ -1,307 +0,0 @@ -#!/bin/bash -## INSTALLATION: script to copy in your Xcode project in the same directory as the .xcodeproj file -## USAGE: ./run-sonar.sh -## DEBUG: ./run-sonar.sh -v -## WARNING: edit your project parameters in sonar-project.properties rather than modifying this script -# - -trap "echo 'Script interrupted by Ctrl+C'; stopProgress; exit 1" SIGHUP SIGINT SIGTERM - -function startProgress() { - while true - do - echo -n "." - sleep 5 - done -} - -function stopProgress() { - if [ "$vflag" = "" -a "$nflag" = "" ]; then - kill $PROGRESS_PID &>/dev/null - fi -} - -function testIsInstalled() { - - hash $1 2>/dev/null - if [ $? -eq 1 ]; then - echo >&2 "ERROR - $1 is not installed or not in your PATH"; exit 1; - fi -} - -function readParameter() { - - variable=$1 - shift - parameter=$1 - shift - - eval $variable="\"$(sed '/^\#/d' sonar-project.properties | grep $parameter | tail -n 1 | cut -d '=' -f2- | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')\"" -} - -# Run a set of commands with logging and error handling -function runCommand() { - - # 1st arg: redirect stdout - # 2nd arg: command to run - # 3rd..nth arg: args - redirect=$1 - shift - - command=$1 - shift - - if [ "$nflag" = "on" ]; then - # don't execute command, just echo it - echo - if [ "$redirect" = "/dev/stdout" ]; then - if [ "$vflag" = "on" ]; then - echo "+" $command "$@" - else - echo "+" $command "$@" "> /dev/null" - fi - elif [ "$redirect" != "no" ]; then - echo "+" $command "$@" "> $redirect" - else - echo "+" $command "$@" - fi - - elif [ "$vflag" = "on" ]; then - echo - - if [ "$redirect" = "/dev/stdout" ]; then - set -x #echo on - $command "$@" - returnValue=$? - set +x #echo off - elif [ "$redirect" != "no" ]; then - set -x #echo on - $command "$@" > $redirect - returnValue=$? - set +x #echo off - else - set -x #echo on - $command "$@" - returnValue=$? - set +x #echo off - fi - - if [[ $returnValue != 0 && $returnValue != 5 ]] ; then - stopProgress - echo "ERROR - Command '$command $@' failed with error code: $returnValue" - exit $returnValue - fi - else - - if [ "$redirect" = "/dev/stdout" ]; then - $command "$@" > /dev/null - elif [ "$redirect" != "no" ]; then - $command "$@" > $redirect - else - $command "$@" - fi - - returnValue=$? - if [[ $returnValue != 0 && $returnValue != 5 ]] ; then - stopProgress - echo "ERROR - Command '$command $@' failed with error code: $returnValue" - exit $? - fi - - - echo - fi -} - -## COMMAND LINE OPTIONS -vflag="" -nflag="" -oclint="on" -while [ $# -gt 0 ] -do - case "$1" in - -v) vflag=on;; - -n) nflag=on;; - -nooclint) oclint="";; - --) shift; break;; - -*) - echo >&2 "Usage: $0 [-v]" - exit 1;; - *) break;; # terminate while loop - esac - shift -done - -# Usage OK -echo "Running run-sonar.sh..." - -## CHECK PREREQUISITES - -# xctool, gcovr and oclint installed -testIsInstalled xctool -testIsInstalled gcovr -testIsInstalled oclint - -# sonar-project.properties in current directory -if [ ! -f sonar-project.properties ]; then - echo >&2 "ERROR - No sonar-project.properties in current directory"; exit 1; -fi - -## READ PARAMETERS from sonar-project.properties - -# Your .xcworkspace/.xcodeproj filename -workspaceFile=''; readParameter workspaceFile 'sonar.objectivec.workspace' -projectFile=''; readParameter projectFile 'sonar.objectivec.project' -if [[ "$workspaceFile" != "" ]] ; then - xctoolCmdPrefix="xctool -workspace $workspaceFile -sdk iphonesimulator ARCHS=i386 VALID_ARCHS=i386 CURRENT_ARCH=i386 ONLY_ACTIVE_ARCH=NO OBJROOT=./build" -else - xctoolCmdPrefix="xctool -project $projectFile -sdk iphonesimulator ARCHS=i386 VALID_ARCHS=i386 CURRENT_ARCH=i386 ONLY_ACTIVE_ARCH=NO OBJROOT=./build" -fi - -# Source directories for .h/.m files -srcDirs=''; readParameter srcDirs 'sonar.sources' -# The name of your application scheme in Xcode -appScheme=''; readParameter appScheme 'sonar.objectivec.appScheme' - -# The name of your test scheme in Xcode -testScheme=''; readParameter testScheme 'sonar.objectivec.testScheme' -# The file patterns to exclude from coverage report -excludedPathsFromCoverage=''; readParameter excludedPathsFromCoverage 'sonar.objectivec.excludedPathsFromCoverage' - -# Check for mandatory parameters -if [ -z "$projectFile" -o "$projectFile" = " " ]; then - - if [ ! -z "$workspaceFile" -a "$workspaceFile" != " " ]; then - echo >&2 "ERROR - sonar.objectivec.project parameter is missing in sonar-project.properties. You must specify which projects (comma-separated list) are application code within the workspace $workspaceFile." - else - echo >&2 "ERROR - sonar.objectivec.project parameter is missing in sonar-project.properties (name of your .xcodeproj)" - fi - exit 1 -fi -if [ -z "$srcDirs" -o "$srcDirs" = " " ]; then - echo >&2 "ERROR - sonar.sources parameter is missing in sonar-project.properties. You must specify which directories contain your .h/.m source files (comma-separated list)." - exit 1 -fi -if [ -z "$appScheme" -o "$appScheme" = " " ]; then - echo >&2 "ERROR - sonar.objectivec.appScheme parameter is missing in sonar-project.properties. You must specify which scheme is used to build your application." - exit 1 -fi - -if [ "$vflag" = "on" ]; then - echo "Xcode workspace file is: $workspaceFile" - echo "Xcode project file is: $projectFile" - echo "Xcode application scheme is: $appScheme" - echo "Xcode test scheme is: $testScheme" - echo "Excluded paths from coverage are: $excludedPathsFromCoverage" -fi - -## SCRIPT - -# Start progress indicator in the background -if [ "$vflag" = "" -a "$nflag" = "" ]; then - startProgress & - # Save PID - PROGRESS_PID=$! -fi - -# Create sonar-reports/ for reports output -if [[ ! (-d "sonar-reports") && ("$nflag" != "on") ]]; then - if [ "$vflag" = "on" ]; then - echo 'Creating directory sonar-reports/' - fi - mkdir sonar-reports - if [[ $? != 0 ]] ; then - stopProgress - exit $? - fi -fi - -# Extracting project information needed later -echo -n 'Extracting Xcode project information' -runCommand /dev/stdout $xctoolCmdPrefix -scheme "$appScheme" clean -runCommand /dev/stdout $xctoolCmdPrefix -scheme "$appScheme" -reporter json-compilation-database:compile_commands.json build - -# Unit tests and coverage -if [ "$testScheme" = "" ]; then - echo 'Skipping tests as no test scheme has been provided!' - - # Put default xml files with no tests and no coverage... - echo "" > sonar-reports/TEST-report.xml - echo "" > sonar-reports/coverage.xml -else - - echo -n 'Running tests using xctool' - # Not using runCommand function because xctool may return 1, even if everything is fine (maybe a xctool bug ?) - #runCommand /dev/null $xctoolCmdPrefix -scheme "$testScheme" GCC_PRECOMPILE_PREFIX_HEADER=NO GCC_GENERATE_TEST_COVERAGE_FILES=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES -reporter junit:sonar-reports/TEST-report.xml -reporter plain clean test - $xctoolCmdPrefix -scheme "$testScheme" GCC_PRECOMPILE_PREFIX_HEADER=NO GCC_GENERATE_TEST_COVERAGE_FILES=YES GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES -reporter junit:sonar-reports/TEST-report.xml -reporter plain clean test - - - echo -n 'Computing coverage report' - - # We do it for every xcodeproject (in case of workspaces) - - # Extract the path to the .gcno/.gcda coverage files - echo $projectFile | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh - while read projectName; do - - projectName=$(basename $projectFile .xcodeproj) - coverageFilesPath="build/$projectName.build/Debug-iphonesimulator/$appScheme.build/Objects-normal/i386" - if [ "$vflag" = "on" ]; then - echo - echo "Path for .gcno/.gcda coverage files is: $coverageFilesPath" - fi - - # Build the --exclude flags - excludedCommandLineFlags="" - if [ ! -z "$excludedPathsFromCoverage" -a "$excludedPathsFromCoverage" != " " ]; then - echo $excludedPathsFromCoverage | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh2 - while read word; do - excludedCommandLineFlags+=" --exclude $word" - done < tmpFileRunSonarSh2 - rm -rf tmpFileRunSonarSh2 - fi - if [ "$vflag" = "on" ]; then - echo "Command line exclusion flags for gcovr is:$excludedCommandLineFlags" - fi - - # Run gcovr with the right options - runCommand "sonar-reports/coverage-${projectName%%.*}.xml" gcovr -r . --object-directory "$coverageFilesPath" $excludedCommandLineFlags --xml - - done < tmpFileRunSonarSh - rm -rf tmpFileRunSonarSh - -fi - -if [ "$oclint" = "on" ]; then - - # OCLint - echo -n 'Running OCLint...' - - # Build the --include flags - currentDirectory=${PWD##*/} - includedCommandLineFlags="" - echo "$srcDirs" | sed -n 1'p' | tr ',' '\n' > tmpFileRunSonarSh - while read word; do - includedCommandLineFlags+=" --include .*/${currentDirectory}/${word}" - done < tmpFileRunSonarSh - rm -rf tmpFileRunSonarSh - if [ "$vflag" = "on" ]; then - echo - echo -n "Path included in oclint analysis is:$includedCommandLineFlags" - fi - - # Run OCLint with the right set of compiler options - maxPriority=10000 - runCommand no oclint-json-compilation-database $includedCommandLineFlags -- -max-priority-1 $maxPriority -max-priority-2 $maxPriority -max-priority-3 $maxPriority -report-type pmd -o sonar-reports/oclint.xml -else - echo 'Skipping OCLint (test purposes only!)' -fi - -# SonarQube -echo -n 'Running SonarQube using SonarQube Runner' -runCommand /dev/stdout sonar-runner - -# Kill progress indicator -stopProgress - -exit 0 diff --git a/src/test/java/org/sonar/objectivec/api/ObjectiveCPunctuatorTest.java b/src/test/java/org/sonar/objectivec/api/ObjectiveCPunctuatorTest.java deleted file mode 100644 index 052b19c2..00000000 --- a/src/test/java/org/sonar/objectivec/api/ObjectiveCPunctuatorTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.objectivec.api; - -import org.junit.Test; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -public class ObjectiveCPunctuatorTest { - - @Test - public void test() { - assertThat(ObjectiveCPunctuator.values().length, is(48)); - } - -} diff --git a/src/test/java/org/sonar/objectivec/lexer/ObjectiveCLexerTest.java b/src/test/java/org/sonar/objectivec/lexer/ObjectiveCLexerTest.java deleted file mode 100644 index 080c41cf..00000000 --- a/src/test/java/org/sonar/objectivec/lexer/ObjectiveCLexerTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.objectivec.lexer; - -import static com.sonar.sslr.test.lexer.LexerMatchers.hasComment; -import static com.sonar.sslr.test.lexer.LexerMatchers.hasToken; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; - -import java.io.File; -import java.util.List; - -import org.junit.BeforeClass; -import org.junit.Test; - -import com.sonar.sslr.api.GenericTokenType; -import com.sonar.sslr.api.Token; -import com.sonar.sslr.impl.Lexer; - -public class ObjectiveCLexerTest { - - private static Lexer lexer; - - @BeforeClass - public static void init() { - lexer = ObjectiveCLexer.create(); - } - - @Test - public void lexMultiLinesComment() { - assertThat(lexer.lex("/* My Comment \n*/"), hasComment("/* My Comment \n*/")); - assertThat(lexer.lex("/**/"), hasComment("/**/")); - } - - @Test - public void lexInlineComment() { - assertThat(lexer.lex("// My Comment \n new line"), hasComment("// My Comment ")); - assertThat(lexer.lex("//"), hasComment("//")); - } - - @Test - public void lexEndOflineComment() { - assertThat(lexer.lex("[self init]; // My Comment end of line"), hasComment("// My Comment end of line")); - assertThat(lexer.lex("[self init]; //"), hasComment("//")); - } - - @Test - public void lexLineOfCode() { - assertThat(lexer.lex("[self init];"), hasToken("[self", GenericTokenType.LITERAL)); - } - - @Test - public void lexEmptyLine() { - List tokens = lexer.lex("\n"); - assertThat(tokens.size(), equalTo(1)); - assertThat(tokens, hasToken(GenericTokenType.EOF)); - } - - @Test - public void lexSampleFile() { - List tokens = lexer.lex(new File("src/test/resources/objcSample.h")); - assertThat(tokens.size(), equalTo(16)); - assertThat(tokens, hasToken(GenericTokenType.EOF)); - } - -} diff --git a/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaMeasuresPersistorTest.java b/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaMeasuresPersistorTest.java deleted file mode 100644 index 8ac0339b..00000000 --- a/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaMeasuresPersistorTest.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.coverage; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Test; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.measures.CoverageMeasuresBuilder; -import org.sonar.api.measures.Measure; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.ProjectFileSystem; -import org.sonar.api.resources.Resource; - -public final class CoberturaMeasuresPersistorTest { - - @Test - public void shouldNotPersistMeasuresForUnknownFiles() { - final Project project = new Project("Test"); - - final SensorContext context = mock(SensorContext.class); - final ProjectFileSystem fileSystem = mock(ProjectFileSystem.class); - final Map measures = new HashMap(); - measures.put("DummyResource", CoverageMeasuresBuilder.create()); - - - when(fileSystem.getBasedir()).thenReturn(new File(".")); - - project.setFileSystem(fileSystem); - - final CoverageMeasuresPersistor testedPersistor = new CoverageMeasuresPersistor(project, context); - testedPersistor.saveMeasures(measures); - - verify(context, never()).saveMeasure(any(Resource.class), any(Measure.class)); - } - - @Test - public void shouldPersistMeasuresForKnownFiles() { - final Project project = new Project("Test"); - final org.sonar.api.resources.File dummyFile = new org.sonar.api.resources.File("dummy/test"); - final SensorContext context = mock(SensorContext.class); - final ProjectFileSystem fileSystem = mock(ProjectFileSystem.class); - final List sourceDirs = new ArrayList(); - final Map measures = new HashMap(); - final CoverageMeasuresBuilder measureBuilder = CoverageMeasuresBuilder.create(); - - sourceDirs.add(new File("/dummy")); - measures.put("/dummy/test", measureBuilder); - measureBuilder.setHits(99, 99); - measureBuilder.setConditions(99, 99, 1); - - when(fileSystem.getSourceDirs()).thenReturn(sourceDirs); - when(context.getResource(any(Resource.class))).thenReturn(dummyFile); - when(fileSystem.getBasedir()).thenReturn(new File(".")); - - project.setFileSystem(fileSystem); - - final CoverageMeasuresPersistor testedPersistor = new CoverageMeasuresPersistor(project, context); - testedPersistor.saveMeasures(measures); - - for (final Measure measure : measureBuilder.createMeasures()) { - verify(context, times(1)).saveMeasure(eq(org.sonar.api.resources.File.fromIOFile(new File(project.getFileSystem().getBasedir(), "dummy/test"), project)), eq(measure)); - } - } - -} diff --git a/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaParserTest.java b/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaParserTest.java deleted file mode 100644 index f3d6be1e..00000000 --- a/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaParserTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.coverage; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.util.Map; - -import org.apache.tools.ant.filters.StringInputStream; -import org.junit.Test; -import org.sonar.api.measures.CoverageMeasuresBuilder; - -public final class CoberturaParserTest { - private final String VALID_REPORT_FILE_PATH = "FILEPATH"; - private final String VALID_REPORT = "."; - - @Test - public void parseReportShouldReturnAnEmptyMapWhenTheReportIsInvalid() { - final CoberturaParser coberturaParser = new CoberturaParser(); - final Map measures = coberturaParser.parseReport(new StringInputStream("")); - - assertTrue(measures.isEmpty()); - } - - @Test - public void parseReportShouldReturnAnEmptyMapWhenTheFileIsInvalid() { - final CoberturaParser coberturaParser = new CoberturaParser(); - final Map measures = coberturaParser.parseReport(new File("")); - - assertTrue(measures.isEmpty()); - } - - @Test - public void parseReportShouldReturnAMapOfFileToMeasuresWhenTheReportIsValid() { - final CoberturaParser coberturaParser = new CoberturaParser(); - final Map measures = coberturaParser.parseReport(new StringInputStream(VALID_REPORT)); - - assertNotNull(measures.get(VALID_REPORT_FILE_PATH)); - } - -} diff --git a/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaSensorTest.java b/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaSensorTest.java deleted file mode 100644 index 84922956..00000000 --- a/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaSensorTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.coverage; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.ModuleFileSystem; -import org.sonar.plugins.objectivec.core.ObjectiveC; - -import java.util.SortedSet; -import java.util.TreeSet; - -public final class CoberturaSensorTest { - - private Settings settings; - - @Before - public void setUp() { - settings = new Settings(); - } - - @Test - public void shouldExecuteOnProjectShouldBeTrueWhenProjectIsObjc() { - final Project project = new Project("Test"); - - FileSystem fileSystem = mock(FileSystem.class); - SortedSet languages = new TreeSet(); - languages.add(ObjectiveC.KEY); - when(fileSystem.languages()).thenReturn(languages); - - final CoberturaSensor testedSensor = new CoberturaSensor(fileSystem, settings); - - assertTrue(testedSensor.shouldExecuteOnProject(project)); - } - - @Test - public void shouldExecuteOnProjectShouldBeFalseWhenProjectIsSomethingElse() { - final Project project = new Project("Test"); - settings.setProperty("sonar.language", "Test"); - - FileSystem fileSystem = mock(FileSystem.class); - SortedSet languages = new TreeSet(); - languages.add("Test"); - when(fileSystem.languages()).thenReturn(languages); - - final CoberturaSensor testedSensor = new CoberturaSensor(fileSystem, settings); - - assertFalse(testedSensor.shouldExecuteOnProject(project)); - } - -} diff --git a/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaXMLStreamHandlerTest.java b/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaXMLStreamHandlerTest.java deleted file mode 100644 index 1b9f3e6a..00000000 --- a/src/test/java/org/sonar/plugins/objectivec/coverage/CoberturaXMLStreamHandlerTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.coverage; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.HashMap; -import java.util.Map; - -import javax.xml.stream.XMLStreamException; - -import org.apache.tools.ant.filters.StringInputStream; -import org.junit.Test; -import org.sonar.api.measures.CoverageMeasuresBuilder; -import org.sonar.api.utils.StaxParser; - -public final class CoberturaXMLStreamHandlerTest { - private final String EMPTY_REPORT = "."; - private final String VALID_REPORT = "."; - private final String FILE_PATH = "FILEPATH"; - private final int NO_HIT_LINE = 25; - private final int NO_BRANCH_LINE = 29; - private final int BRANCH_LINE = 35; - - @Test - public void streamLeavesTheMapEmptyWhenNoLinesAreFound() throws XMLStreamException { - final Map parseResults = new HashMap(); - final StaxParser parser = new StaxParser(new CoberturaXMLStreamHandler(parseResults)); - - parser.parse(new StringInputStream(EMPTY_REPORT)); - - assertTrue(parseResults.isEmpty()); - } - - @Test - public void streamAddsACoverageMeasureBuilderForClassesInTheReport() throws XMLStreamException { - final Map parseResults = new HashMap(); - final StaxParser parser = new StaxParser(new CoberturaXMLStreamHandler(parseResults)); - - parser.parse(new StringInputStream(VALID_REPORT)); - - assertNotNull(parseResults.get(FILE_PATH)); - } - - @Test - public void streamRecords0HitsForLinesWithNoHits() throws XMLStreamException { - final Map parseResults = new HashMap(); - final StaxParser parser = new StaxParser(new CoberturaXMLStreamHandler(parseResults)); - - parser.parse(new StringInputStream(VALID_REPORT)); - - assertEquals(Integer.valueOf(0), parseResults.get(FILE_PATH).getHitsByLine().get(NO_HIT_LINE)); - } - - @Test - public void streamRecordsHitsForLinesWithNoBranch() throws XMLStreamException { - final Map parseResults = new HashMap(); - final StaxParser parser = new StaxParser(new CoberturaXMLStreamHandler(parseResults)); - - parser.parse(new StringInputStream(VALID_REPORT)); - - assertEquals(Integer.valueOf(1), parseResults.get(FILE_PATH).getHitsByLine().get(NO_BRANCH_LINE)); - } - - @Test - public void streamRecordsHitsForLinesWithBranch() throws XMLStreamException { - final Map parseResults = new HashMap(); - final StaxParser parser = new StaxParser(new CoberturaXMLStreamHandler(parseResults)); - - parser.parse(new StringInputStream(VALID_REPORT)); - - assertEquals(Integer.valueOf(10), parseResults.get(FILE_PATH).getHitsByLine().get(BRANCH_LINE)); - } - - @Test - public void streamRecordsConditionsForLinesWithBranch() throws XMLStreamException { - final Map parseResults = new HashMap(); - final StaxParser parser = new StaxParser(new CoberturaXMLStreamHandler(parseResults)); - - parser.parse(new StringInputStream(VALID_REPORT)); - - assertEquals(Integer.valueOf(2), parseResults.get(FILE_PATH).getConditionsByLine().get(BRANCH_LINE)); - } - - @Test - public void streamRecordsConditionsHitsForLinesWithBranch() throws XMLStreamException { - final Map parseResults = new HashMap(); - final StaxParser parser = new StaxParser(new CoberturaXMLStreamHandler(parseResults)); - - parser.parse(new StringInputStream(VALID_REPORT)); - - assertEquals(Integer.valueOf(1), parseResults.get(FILE_PATH).getCoveredConditionsByLine().get(BRANCH_LINE)); - } - -} diff --git a/src/test/java/org/sonar/plugins/objectivec/violations/OCLintParserTest.java b/src/test/java/org/sonar/plugins/objectivec/violations/OCLintParserTest.java deleted file mode 100644 index 12730013..00000000 --- a/src/test/java/org/sonar/plugins/objectivec/violations/OCLintParserTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.apache.tools.ant.filters.StringInputStream; -import org.junit.Test; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.ProjectFileSystem; -import org.sonar.api.resources.Resource; -import org.sonar.api.rules.Violation; - -public class OCLintParserTest { - private final String VALID_REPORT = "An operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself"; - - @Test - public void parseReportShouldReturnAnEmptyCollectionWhenTheReportIsInvalid() { - final OCLintParser testedParser = new OCLintParser(null, null); - final Collection violations = testedParser.parseReport(new StringInputStream("")); - - assertTrue(violations.isEmpty()); - } - - @Test - public void parseReportShouldReturnAnEmptyMapWhenTheFileIsInvalid() { - final OCLintParser testedParser = new OCLintParser(null, null); - final Collection violations = testedParser.parseReport(new File("")); - - assertTrue(violations.isEmpty()); - } - - @Test - public void parseReportShouldReturnACollectionOfViolationsWhenTheReportIsNotEmpty() { - final Project project = new Project("Test"); - final org.sonar.api.resources.File dummyFile = new org.sonar.api.resources.File("dummy/test"); - final SensorContext context = mock(SensorContext.class); - final ProjectFileSystem fileSystem = mock(ProjectFileSystem.class); - final List sourceDirs = new ArrayList(); - - final OCLintParser testedParser = new OCLintParser(project, context); - - sourceDirs.add(new File("/dummy")); - when(fileSystem.getSourceDirs()).thenReturn(sourceDirs); - when(fileSystem.getBasedir()).thenReturn(new File(".")); - when(context.getResource(any(Resource.class))).thenReturn(dummyFile); - project.setFileSystem(fileSystem); - - final Collection violations = testedParser.parseReport(new StringInputStream(VALID_REPORT)); - assertFalse(violations.isEmpty()); - } - - -} diff --git a/src/test/java/org/sonar/plugins/objectivec/violations/OCLintSensorTest.java b/src/test/java/org/sonar/plugins/objectivec/violations/OCLintSensorTest.java deleted file mode 100644 index 52bd2ec8..00000000 --- a/src/test/java/org/sonar/plugins/objectivec/violations/OCLintSensorTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.config.Settings; -import org.sonar.api.resources.Project; -import org.sonar.plugins.objectivec.core.ObjectiveC; - -import java.util.SortedSet; -import java.util.TreeSet; - -public final class OCLintSensorTest { - - private Settings settings; - - @Before - public void setUp() { - settings = new Settings(); - } - - @Test - public void shouldExecuteOnProjectShouldBeTrueWhenProjectIsObjc() { - final Project project = new Project("Test"); - - FileSystem fileSystem = mock(FileSystem.class); - SortedSet languages = new TreeSet(); - languages.add(ObjectiveC.KEY); - when(fileSystem.languages()).thenReturn(languages); - - final OCLintSensor testedSensor = new OCLintSensor(fileSystem, settings); - - assertTrue(testedSensor.shouldExecuteOnProject(project)); - } - - @Test - public void shouldExecuteOnProjectShouldBeFalseWhenProjectIsSomethingElse() { - final Project project = new Project("Test"); - - FileSystem fileSystem = mock(FileSystem.class); - SortedSet languages = new TreeSet(); - languages.add("Test"); - when(fileSystem.languages()).thenReturn(languages); - - final OCLintSensor testedSensor = new OCLintSensor(fileSystem, settings); - - assertFalse(testedSensor.shouldExecuteOnProject(project)); - } - -} diff --git a/src/test/java/org/sonar/plugins/objectivec/violations/OCLintXMLStreamHandlerTest.java b/src/test/java/org/sonar/plugins/objectivec/violations/OCLintXMLStreamHandlerTest.java deleted file mode 100644 index 888aeba1..00000000 --- a/src/test/java/org/sonar/plugins/objectivec/violations/OCLintXMLStreamHandlerTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import javax.xml.stream.XMLStreamException; - -import org.apache.tools.ant.filters.StringInputStream; -import org.junit.Test; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.batch.fs.FileSystem; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.ProjectFileSystem; -import org.sonar.api.resources.Resource; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.rules.Violation; -import org.sonar.api.utils.StaxParser; - -public class OCLintXMLStreamHandlerTest { - private static final String EMPTY_REPORT = ""; - private static final String DESCRIPTION = "TEST DESCRIPTION"; - private static final Integer VIOLATION_LINE = Integer.valueOf(99); - private static final String RULE_KEY = "TEST RULE"; - private static final String VALID_REPORT = "" + DESCRIPTION + ""; - private ProjectBuilder projectBuilder; - - @Test - public void streamLeavesTheCollectionEmptyWhenNoLinesAreFound() throws XMLStreamException { - final Collection parseResults = new ArrayList(); - final StaxParser parser = new StaxParser(new OCLintXMLStreamHandler(parseResults, null, null)); - - parser.parse(new StringInputStream(EMPTY_REPORT)); - - assertTrue(parseResults.isEmpty()); - } - - @Test - public void streamAddAviolationForALineInTheReport() throws XMLStreamException { - final org.sonar.api.resources.File dummyFile = new org.sonar.api.resources.File("test"); - givenAProject().containingSourceDirectory("dummy"); - final SensorContext context = mock(SensorContext.class); - - final Collection parseResults = new ArrayList(); - final StaxParser parser = new StaxParser(new OCLintXMLStreamHandler(parseResults, project(), context)); - - when(context.getResource(any(Resource.class))).thenReturn(dummyFile); - - parser.parse(new StringInputStream(VALID_REPORT)); - - assertFalse(parseResults.isEmpty()); - } - - private Project project() { - Project project = givenAProject().project(); - ProjectFileSystem fileSystem = mock(ProjectFileSystem.class); - project.setFileSystem(fileSystem); - when(fileSystem.getBasedir()).thenReturn(new File(".")); - return project; - } - - private ProjectBuilder givenAProject() { - projectBuilder = new ProjectBuilder(); - return projectBuilder; - } - -} diff --git a/src/test/java/org/sonar/plugins/objectivec/violations/ProjectBuilder.java b/src/test/java/org/sonar/plugins/objectivec/violations/ProjectBuilder.java deleted file mode 100644 index 9f6bbebb..00000000 --- a/src/test/java/org/sonar/plugins/objectivec/violations/ProjectBuilder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Sonar Objective-C Plugin - * Copyright (C) 2012 OCTO Technology - * dev@sonar.codehaus.org - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.objectivec.violations; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.sonar.api.resources.Project; -import org.sonar.api.resources.ProjectFileSystem; - -final class ProjectBuilder { - private final Project project = new Project("Test"); - private final ProjectFileSystem fileSystem = mock(ProjectFileSystem.class); - private final List sourceDirs = new ArrayList(); - - public ProjectBuilder() { - project.setFileSystem(fileSystem); - when(fileSystem.getSourceDirs()).thenReturn(sourceDirs); - when(fileSystem.getBasedir()).thenReturn(new File(".")); - } - - public Project project() { - return project; - } - - public void containingSourceDirectory(final String d) { - sourceDirs.add(new File(d)); - } -} diff --git a/updateFauxPasRules.groovy b/updateFauxPasRules.groovy new file mode 100644 index 00000000..c5774f71 --- /dev/null +++ b/updateFauxPasRules.groovy @@ -0,0 +1,113 @@ +/** + * Sonar Objective-C Plugin + * Copyright (C) 2012 OCTO Technology, Backelite + * dev@sonar.codehaus.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +// Update profile-fauxpas.xml from Faux Pas online rules documentation +// Severity is determined from the category + +@Grab(group='org.codehaus.groovy.modules.http-builder', + module='http-builder', version='0.7') + +import groovyx.net.http.* +import groovy.xml.MarkupBuilder +import groovy.json.JsonBuilder + +def parseRules(url, catMapping) { + + def result = [] + + def http = new HTTPBuilder(url) + http.contentEncoding = ContentEncoding.Type.GZIP + def html = http.get(contentType : 'text/html;charset=UTF-8') + + def categories = html."**".findAll {it.@class.toString().contains('tag-section')} + categories.each {cat -> + + def rules = cat."**".findAll {it.@class.toString().contains('rule')} + rules.each {r -> + + def k = r."**".find {it.@class.toString().contains("short-name")}.text() + + def rule = [ + category: cat.H2.text(), + key: k, + name: (r.H3.text().trim().replaceAll('\\n', ' ') - k).trim(), + description: r."**".find {it.@class.toString().contains("description")}.text().trim().replaceAll('\\n', ' '), + severity: catMapping[cat.H2.text()] + ] + + result.add(rule) + } + } + + + + return result +} + +def writeProfileFauxPas(rls, file) { + def writer = new StringWriter() + def xml = new MarkupBuilder(writer) + xml.profile() { + name "FauxPas" + language "objc" + rules { + rls.each {rl -> + rule { + repositoryKey "FauxPas" + key rl.key + } + } + } + } + + file.text = "\n" + writer.toString() + +} + +def writeRules(rls, file) { + + def builder = new JsonBuilder() + builder(rls) + + file.text = builder.toPrettyString() + +} + +// Files +File rulesJson = new File('sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/fauxpas/rules.json') +File profileXml = new File('sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/fauxpas/profile-fauxpas.xml') + +// Parse online documentation +def rules = parseRules('http://fauxpasapp.com/rules/', [ + BestPractice: 'MAJOR', + Resources: 'MAJOR', + Config: 'MINOR', + Localization: 'MAJOR', + APIUsage: 'CRITICAL', + VCS: 'INFO', + Style: 'MAJOR', + Pedantic: 'MINOR', + Miscellaneous: 'MINOR' +]) + +// Write profile +writeProfileFauxPas(rules, profileXml) + +// Write rules +writeRules(rules, rulesJson) \ No newline at end of file diff --git a/updateRules.groovy b/updateOCLintRules.groovy similarity index 72% rename from updateRules.groovy rename to updateOCLintRules.groovy index f3a86fda..bd5f4181 100644 --- a/updateRules.groovy +++ b/updateOCLintRules.groovy @@ -1,3 +1,22 @@ +/** + * Sonar Objective-C Plugin + * Copyright (C) 2012 OCTO Technology, Backelite + * dev@sonar.codehaus.org + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ // Update rules.txt and profile-clint.xml from OCLint documentation // Severity is determined from the category @@ -189,21 +208,21 @@ def mergeRules(existingRules, freshRules) { } // Files -File rulesTxt = new File('src/main/resources/org/sonar/plugins/oclint/rules.txt') -File profileXml = new File('src/main/resources/org/sonar/plugins/oclint/profile-oclint.xml') +File rulesTxt = new File('sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/oclint/rules.txt') +File profileXml = new File('sonar-objective-c-plugin/src/main/resources/org/sonar/plugins/oclint/profile-oclint.xml') // Parse OCLint online documentation def rules = [] -rules.addAll parseCategory("http://docs.oclint.org/en/dev/rules/basic.html", "basic", 3) -rules.addAll parseCategory("http://docs.oclint.org/en/dev/rules/convention.html", "convention", 2) -rules.addAll parseCategory("http://docs.oclint.org/en/dev/rules/empty.html", "empty", 3) -rules.addAll parseCategory("http://docs.oclint.org/en/dev/rules/migration.html", "migration", 1) -rules.addAll parseCategory("http://docs.oclint.org/en/dev/rules/naming.html", "naming", 2) -rules.addAll parseCategory("http://docs.oclint.org/en/dev/rules/redundant.html", "redundant", 1) -rules.addAll parseCategory("http://docs.oclint.org/en/dev/rules/size.html", "size", 3) -rules.addAll parseCategory("http://docs.oclint.org/en/dev/rules/unused.html", "unused", 0) +rules.addAll parseCategory("http://docs.oclint.org/en/stable/rules/basic.html", "basic", 3) +rules.addAll parseCategory("http://docs.oclint.org/en/stable/rules/convention.html", "convention", 2) +rules.addAll parseCategory("http://docs.oclint.org/en/stable/rules/empty.html", "empty", 3) +rules.addAll parseCategory("http://docs.oclint.org/en/stable/rules/migration.html", "migration", 1) +rules.addAll parseCategory("http://docs.oclint.org/en/stable/rules/naming.html", "naming", 2) +rules.addAll parseCategory("http://docs.oclint.org/en/stable/rules/redundant.html", "redundant", 1) +rules.addAll parseCategory("http://docs.oclint.org/en/stable/rules/size.html", "size", 3) +rules.addAll parseCategory("http://docs.oclint.org/en/stable/rules/unused.html", "unused", 0) println "${rules.size()} rules found"