Turning off SonarLint for a project in Eclipse

Overall, I like using SonarLint in Eclipse. When I’m doing something like working on the CodeRanch forums, being informed of possible problems is great. When working on mock exam questions, not so much. Mock exam questions have lots of System.out.println statements. They also have a variety of poor coding practices for anywhere other a certification exam.

Luckily, turning off SonarLint for a project is a simple two part operation.

Part 1 – Turn off Sonar Lint for the project

  1. Just go to the project preferences and choose SonarLint.
  2. Then uncheck “Run SonarLint” automatically.

If you have the foresight to do this before you’ve opened any files in the project, you are done. If not, there is part 2.

Part 2 – Delete any issues thus far

  1. Open the SonarLint Issues view.
  2. Select all. (Ctrl-A is your friend).
  3. Right click and choose Delete.
  4. Choose yes when asked if you are sure.

That’s it. I’m glad I ddi this. Less than a couple of minutes of effort and now I don’t have blue squiggles in all my mock exam stuff!

sonarqube and the scm plugin

I tried enabling the SCM integration from our CodeRanch Sonar install to our SVN repository. It didn’t quite work out the way I was hoping. But I learned stuff so it makes for a good blog entry.

Wait? The SCM Activity Plugin is deprecated?

If you search for Sonar SCM plugin, you get to the plugin documentation page. Which appears to be useful. Except that it says the plugin has been deprecated since Sonar 5.0. I stopped reading at that point and puzzled over it. If you continue to read, it says “This plugin is deprecated since SonarQube 5.0 which has built-in support for SCM information and which relies on independent plugins to cover SCM providers.” Ah. So it is deprecated because it is now a core feature. That explains why the functionality shows up on our Sonar.

Time to enable

I generated another SVN user and set the username/password in Sonar. I then set “disable the SCM sensor” to false and ran our Jenkins build. And I got this. Well, it went on for pages, but you get the idea:

[sonar:sonar] Sensor SCM Sensor
[sonar:sonar] SCM provider for this project is: svn
[sonar:sonar] 1404 files to be analyzed
[sonar:sonar] 0/1404 files analyzed
[sonar:sonar] Missing blame information for the following files:
[sonar:sonar] * /data/vhost1/ciengine.javaranch.com/data/jobs/JForum/workspace/src/main/java/net/jforum/util/bbcode/BBCodeHandler.java
[sonar:sonar] * /data/vhost1/ciengine.javaranch.com/data/jobs/JForum/workspace/src/main/java/net/jforum/util/concurrent/Executor.java

Ok. So the credentials are good as Sonar can connect to see how many files there are.  Google and SVN plugin page both suggested the problem was not being on Subversion 1.5 or lower. I looked around and that didn’t appear to be the case.  svnadmin —version returned 1.7.8 and the repository was on 1.6. So I thought maybe the mismatch was the problem and tried to run svnadmin upgrade svn (svn is the name of the folder containing our repository on disk). Then this happened and I had to recover from it.

Then it worked

After I upgraded the Subversion repository (or whatever the hell I did by accident), I was able to commit and trigger another Jenkins/Sonar build. I saw the person who committed lines of code in each file. And what’s really cool is that it WENT BACK IN TIME. I see the committers that aren’t active on CodeRanch anymore and haven’t contributed code in years. That is really cool.

What I was hoping it would do vs what it actually does

I wanted to see the “scm blame” output when reviewing files in Sonar. That works and I see it as being useful. I can see if something came from me (or another current developer.) Or if it came from someone no longer involved in the code base.

I wanted to see coverage on new code. This works depending on how you define new code. If you define it as “touched” code, it works well. You also have to remember to use a differential view so Sonar knows how far back to consider “new” code. This makes sense. I typically use the last 7 days as my view so “new” means “touched in the last 7 days”. Unfortunately, we don’t currently run our integration tests in Jenkins so this isn’t useful for the back end layer. I had started dealing with that. Maybe I should finish :).

I had read about the “Developer Cockpit” and seeing a view of your own contributions. I hadn’t realized that was a paid enterprise feature so not helpful to us at CodeRanch.  Without the cockpit, you can still go to “My account” to see a table with “leaks” (issues you created in the past week) and a link to all of your issues. Unfortunately Sonar thinks half the issues are mine and the others aren’t assigned:

  1. I was the one who committed the initial JForum fork we made which means every single open source issue is treated as mine.  (I don’t remember if I did or not, but I led that project so I wouldn’t be surprised.)
  2. Most of the developers don’t have accounts on Sonar. Only the admins do. Everyone else has been using it anonymously. (It’s behind an Apache password wall so not public.)

On the bright side, you *can* filter issues by author now. Which is the last committer. But still helpful. If the code is new, the last committer is someone who might look at it. If the committer is someone who isn’t around anymore, that’s informative.

 

 

 

 

sonar plugins and why i had to fork the sonar web plugin to add a rule

Last weekend, a few of the CodeRanch moderators were discussing a Trac item that we’d like to get rid of the I18N messages from our HTML. It’s there at all because open source JForum had it. We haven’t been updating it and have been using it inconsistently. Also, we do want to externalize the ones in Java which is why we can’t just get rid of the file wholesale – someone could add more references from HTML. I suggested that this would be a good thing to set up a SonarQube rule and volunteered to create the rule. This was a far harder and more interesting task than I expected it to be when I said I’d do it.
webProps

The web plugin scans HTML files and has a bunch of pre-defined rules and templates for them. You can set any file extensions you’d like so I had set “.html,.html,.ftl” in Administration > Configuration > Web to hit both our HTML and Freemarker code. Alternatively, you can set this in your Sonar properties file.

Looking through the rules and rule templates in the web plugin, there wasn’t one for what I wanted – plain String or regular expression search. Nuts! There are a few existing rules that do what I want, however I couldn’t use them:

Rule Why can’t use
Some Java packages or classes should not be used in JSP files In web plugin, but only for jsp/jsp files
Disallowed methods should not be allowed In Java plugin so only works for Java code
XPath rule Only works for XML files
The text plugin regular expression rule So close! This does exactly what I need. Except (see next section)

Great, the text plugin meets my needs. But alas. You can only associate a file extension with one plugin for each Sonar run. The HTML/Freemarker files are already considered web files.

So what’s wrong with the text plugin?

The text plugin has a rule called “Simple Regex Match”. When configured with the proper regular expression, it does exactly what I want. Except for one huge problem. In order to use it, I have to associate the text plugin with HTML/Freemarker files. This is a two step procedure:

  • In the browser, Administration > Configuration > Web – set the web extensions to “foo”. Leaving it blank is insufficient as it defaults to include HTML and Sonar does not let the same file extension be associated with multiple plugins.
  • In sonar-project.properties, add the line: sonar-text-plugin.file.suffixes=.htm,.html,.ftl

You also have to run sonar-runner twice. Once with the HTML/Freemarker files associated with the web plugin to get those results and again with them associate with the text plugin to get the rule I’m trying to write. This means you need to have the code show up as two projects within SonarQube. (otherwise Sonar will tell you the rule violations were fixed for whichever analysis you run last.)

Extending the web plugin

Ok. I clearly need to extend the web plugin so that I can have a regular expression rule associated with the web plugin. The docs say the web plugin doesn’t support extending it with Java or XPath rules as does this post. I tried anyway hoping this was out of date. I was able to get my new rule to show up in Sonar, but not to run. Everything I’d need to do in order to get it to run was considered a duplicate and prevented Sonar from even starting up. For example, “org.sonar.api.utils.SonarException: Can not add the same measure twice” or “duplicate keys not allowed”. So I concede this path is a non-starter. It would have been nice to have my custom rule in a separate Maven project rather than having to fork the existing one.

Forking the web plugin

Sigh. Last resort. Time to fork. This newsgroup post pointed to a commit that shows how to add a rule to the web plugin. I wanted to add a rule template rather than a rule, but the idea is the same. It wasn’t hard to make the change within the project. It’s just that forking isn’t good in the long run as I’ll have to keep re-merging. What I needed to change in my fork:

  1. Add custom rule template class to org.sonar.plugins.web.checks.coding package. The code was pretty similar to the rule for illegal spaces:
    package org.sonar.plugins.web.checks.coding;
    
    import java.io.IOException;
    import java.nio.charset.Charset;
    import java.util.List;
    
    import org.sonar.api.utils.SonarException;
    import org.sonar.check.Priority;
    import org.sonar.check.Rule;
    import org.sonar.check.RuleProperty;
    import org.sonar.plugins.web.checks.AbstractPageCheck;
    import org.sonar.plugins.web.checks.RuleTags;
    import org.sonar.plugins.web.node.Node;
    import org.sonar.plugins.web.visitor.CharsetAwareVisitor;
    import org.sonar.squidbridge.annotations.NoSqale;
    import org.sonar.squidbridge.annotations.RuleTemplate;
    
    import com.google.common.io.Files;
    
    @Rule(
      key = "RegularExpressionNotAllowedOnLineCheck", 
      name = "Regular expression \"regex\" not allowed on web page", 
      priority = Priority.MAJOR, tags = {
      RuleTags.CONVENTION })
    @RuleTemplate
    @NoSqale
    public final class RegularExpressionNotAllowedOnLineCheck extends AbstractPageCheck implements CharsetAwareVisitor {
    
    	@RuleProperty(
          key = "regex", 
          description = "Single line regular expression to prohibit on web pages")
    	public String regex = "";
    	
    	private Charset charset;
    
    	@Override
    	public void setCharset(Charset charset) {
    	   this.charset = charset;
    	}
    
    	@Override
    	public void startDocument(List<Node> nodes) {
    		List<String> lines;
    		try {
    			lines = Files.readLines(getWebSourceCode().inputFile().file(), charset);
    		} catch (IOException e) {
    			throw new SonarException(e);
    		}
    		for (int i = 0; i < lines.size(); i++) {
    			// only support matching text within a single line to facilitate identifying line number
    			if (lines.get(i).matches("^.*" + regex + ".*$")) {
    				createViolation(i + 1, "Replace all instances of regular expression: " + regex);
    			}
    		}
    	}
    
    }
    
  2. Add the rule template to org.sonar.plugins.web.rules.CheckClasses so the web plugin knows about.
  3. Create a new HTML file in the resources localization directory.
  4. Write/update tests. I like that the sonar-web-plugin project uses JUnit tests to enforce some of there conventions like rules ending in “Check”.

Where is the code?

I’ve placed my fork on Github. It’s 2.5-SNAPSHOT because I didn’t see any need to version it. I also created a pull request for the sonar-web-plugin in hopes they are interested in merging it. The plugin was last released a year ago so I imagine I’ll be using my fork for along the foreseeable future in any case. Which is fine. CodeRanch is a volunteer run website so no rules against using forked software.