Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Best practices

Developers of Sonar core should :

  • Build with maven before committing into SCM (Git or Subversion)
  • Commit frequently
  • Do not commit incomplete changes (SCM is not a backup system)
  • Do not commit IDE files (.settings, .project, .classpath, .idea, *.iml, *.ipr, *.iws)
  • Use meaningful comments when doing a commit, always with the JIRA key and title (e.g. "SONAR-6 Apply license LGPL") - see Note About Git Commit Messages
  • Subscribe to the mailing list dev@sonar.codehaus.org
  • Overuse unit JUnit tests (JUnit 4), with the help of hamcrest matchers FEST Assert and Mockito (mock objects)
  • Think IoC (Inversion of Control pattern)
  • Don't reinvent the wheel : use standard libraries like commons-lang, commons-io and guava (formerly known as google-collections). Commons-collections is deprecated since Sonar 1.10.
  • Use comments and javadocs only when necessary
  • API Javadoc - use "@since <version>" and "@deprecated in <version>"
  • Do not forget the license header on all the Java and Ruby files
  • Respect the code formatting described below
  • Follow error handling guidelines
  • Eat your own food : have a look at Sonar and Sonar plugins on Nemo.

...

Source Encoding

Source code encoding should be set to UTF-8 to prevent cross-platform encoding issues.

...

  • For Eclipse : go to "Preferences -> General -> Workspace" and force the "Text file encoding" to "UTF-8"
  • For IntelliJ IDEA : go to "Settings -> File Encodings" and force the "IDE Encoding" to "UTF-8"

Code

...

Style

  • Classes with acronyms are CamelCase : for example prefer PmdPlugin to PMDPlugin, or JavaNcssHandler to JavaNCSSHandler
  • Follow this template :

    Code Block
    if (i == 0) { // whitespace around operators
      doThis();
    } else {
      doThat();
      andThat();
    }
    
  • Replace :

    Code Block
    if (i == 0) doThis();
    

    by :

    Code Block
    if (i == 0) {
      doThis();
    }
    

The following sections show how to set up the code style for Sonar in IDEA and Eclipse. It is strongly preferred that patches use this style before they are supplied.

Configure IntelliJ IDEA

Download sonar-idea-codestyle.xml
Copy it to ~/.IntelliJIDEA/config/codestyles (on Windows, try C:\Documents and Settings\<username>\.IntelliJIDEA\config\codestyles).
After this, restart IDEA and open the settings to select the new code style.

Configure Eclipse

Download sonar-eclipse-codestyle.xml and sonar-eclipse-cleanup.xml
After this, select Window -> Preferences, and open up the configuration for Java -> Code Style:

  1. Open Formatter. Click on the button labeled "Import..." and select the first file you downloaded. Give the style a name, and click OK.
  2. Open Clean Up. Click on the button labeled "Import..." and select the second file you downloaded. Give the style a name, and click OK.

You should also configure the XML editor to indent with 2 spaces instead of 1 tab. To do so, open the XML -> XML Files -> Editor, select "Indent using spaces" and increment to 2.

Edit Ruby code

The development mode is used to edit Ruby on Rails code. The application is automatically reloaded when Ruby files are saved. It avoids restarting the server. Changes are reloaded on the fly. Execute one of the following commands from the sonar-server/ directory to start the server :

...

Then ruby code can be directly edited from sonar-server/src/main/webapp/WEB-INF/app.

Debug Maven

...

Analysis

  • Execute mvnDebug instead of mvn :

    Code Block
    mvnDebug sonar:sonar
    
  • Attach your IDE to the remote process (the listening port is 8000).

Example in Intellij Idea : Run -> Edit configurations -> Add new configuration -> Remote -> port 8000.

Profile Maven analysis with JProfiler

  • Clone $MAVEN_HOME/bin/mvnDebug to mvnJProfiler and replace the MAVEN_DEBUG_OPTS property by :
    MAVEN_DEBUG_OPTS="-Xint -agentlib:jprofilerti=port=8849 -Xbootclasspath/a:/Applications/jprofiler5/bin/agent.jar"
  • Start JProfiler -> Connect to an application on a remote computer

Tips and tricks

Connect to Derby from command line

  • download derby (the same version as used by sonar)
  • set the DERBY_HOME property
  • execute the command $DERBY_HOME/bin/ij
  • connect to the database :

    Code Block
    ij version 10.3
    ij> connect 'jdbc:derby://localhost:1527/sonar;user=sonar;password=sonar';
    ij> show tables;
    

Compare XML files in JUnit

Use XMLUnit. The dependency is already defined into maven.

Code Block
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;

XMLUnit.setIgnoreWhitespace(true);
Diff diff = XMLUnit.compareXML(xml1, xml2);
assertTrue(diff.similar());

Warning : There's a bug on the similar() method. Contrary to the documentation, it fails if nodes are not in the same order.

Freeze Ruby gems

Ruby gems are used in the webapp (directory src/main/webapp of the sonar-server module). They are delivered with the application. To install or upgrade a gem :

  • copy the gem from local ruby installation into WEB-INF/vendor/gems.
  • execute "jruby -S gem specification <gemname> > .specification" from WEB-INF/vendor/gems/<gemname>. It generates the .specification file.
  • commit the directory WEB-INF/vendor/gems

Log server-side SQL requests

Here is how to log all the SQL requests executed from server :

  1. Download log4jdbc4-1.2.jar from http://log4jdbc.googlecode.com/files/log4jdbc4-1.2.jar
  2. Copy this jar here : $SONAR_HOME/war/sonar-server/WEB-INF/lib/log4jdbc4-1.2.jar
  3. IMPORTANT: Change the configuration of logback.xml because if not modified everything will be logged (http://code.google.com/p/log4jdbc/#5._Set_up_your_loggers)

    Code Block
    languagehtml/xml
      <logger name="jdbc.sqltiming">
        <level value="OFF"/>
        <appender-ref ref="PROFILING_FILE"/>
      </logger>
      <logger name="jdbc.connection">
        <level value="INFO"/>
        <appender-ref ref="PROFILING_FILE"/>
      </logger>
      <logger name="jdbc.audit">
        <level value="OFF"/>
        <appender-ref ref="PROFILING_FILE"/>
      </logger>
      <logger name="jdbc.resultset">
        <level value="OFF"/>
        <appender-ref ref="PROFILING_FILE"/>
      </logger>
      <logger name="jdbc.sqlonly">
        <level value="OFF"/>
        <appender-ref ref="PROFILING_FILE"/>
      </logger>
  4. Restart sonar and you should be able to see :

    Code Block
    languagenone
     2012.07.02 16:04:06 INFO  jdbc.sqltiming  select params0_.rule_id as rule6_1_, params0_.id as id1_, params0_.id as id18_0_, params0_.default_value
      as default2_18_0_, params0_.description as descript3_18_0_, params0_.name as name18_0_, params0_.rule_id
      as rule6_18_0_, params0_.param_type as param5_18_0_ from rules_parameters params0_ where params0_.rule_id=679
      {executed in 0 msec}