]> source.dussan.org Git - sonarqube.git/commitdiff
SONARJAVA-14,SONARJAVA-18 Grab violations directly from FindBugs
authorEvgeny Mandrikov <mandrikov@gmail.com>
Wed, 7 Nov 2012 10:08:54 +0000 (11:08 +0100)
committerEvgeny Mandrikov <mandrikov@gmail.com>
Wed, 7 Nov 2012 10:30:16 +0000 (11:30 +0100)
plugins/sonar-findbugs-plugin/src/main/java/org/sonar/plugins/findbugs/FindbugsExecutor.java
plugins/sonar-findbugs-plugin/src/main/java/org/sonar/plugins/findbugs/FindbugsSensor.java
plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsSensorTest.java
sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java

index 101ff5587fc65fb927b566271d1226774345d5ff..578a99cd7ce781d26aa3037467c7d906b65a7661 100644 (file)
 package org.sonar.plugins.findbugs;
 
 import com.google.common.collect.Lists;
-import edu.umd.cs.findbugs.DetectorFactoryCollection;
-import edu.umd.cs.findbugs.FindBugs;
-import edu.umd.cs.findbugs.FindBugs2;
-import edu.umd.cs.findbugs.Plugin;
-import edu.umd.cs.findbugs.PluginException;
-import edu.umd.cs.findbugs.Priorities;
-import edu.umd.cs.findbugs.Project;
-import edu.umd.cs.findbugs.XMLBugReporter;
+import edu.umd.cs.findbugs.*;
 import edu.umd.cs.findbugs.config.UserPreferences;
 import edu.umd.cs.findbugs.plugins.DuplicatePluginIdException;
 import org.apache.commons.io.FileUtils;
@@ -44,12 +37,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.net.URL;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -80,7 +68,7 @@ public class FindbugsExecutor implements BatchExtension {
     this.configuration = configuration;
   }
 
-  public File execute() {
+  public BugCollection execute() {
     TimeProfiler profiler = new TimeProfiler().start("Execute Findbugs " + FindbugsVersion.getVersion());
     // We keep a handle on the current security manager because FB plays with it and we need to restore it before shutting down the executor
     // service
@@ -140,7 +128,7 @@ public class FindbugsExecutor implements BatchExtension {
 
       profiler.stop();
 
-      return xmlReport;
+      return xmlBugReporter.getBugCollection();
     } catch (Exception e) {
       throw new SonarException("Can not execute Findbugs", e);
     } finally {
index d9ca6cecfe380fa0c6bbb8df3de5114f13204588..d56a470359ad8851eb7fa1db69abef05051cfb67 100644 (file)
  */
 package org.sonar.plugins.findbugs;
 
+import edu.umd.cs.findbugs.BugCollection;
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.SourceLineAnnotation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.Sensor;
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.profiles.RulesProfile;
@@ -32,9 +34,6 @@ import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.Violation;
 
-import java.io.File;
-import java.util.List;
-
 public class FindbugsSensor implements Sensor {
 
   private static final Logger LOG = LoggerFactory.getLogger(FindbugsSensor.class);
@@ -51,23 +50,19 @@ public class FindbugsSensor implements Sensor {
 
   public boolean shouldExecuteOnProject(Project project) {
     return Java.KEY.equals(project.getLanguageKey())
-      && !project.getFileSystem().mainFiles(Java.KEY).isEmpty()
-      && !profile.getActiveRulesByRepository(FindbugsConstants.REPOSITORY_KEY).isEmpty();
+        && !project.getFileSystem().mainFiles(Java.KEY).isEmpty()
+        && !profile.getActiveRulesByRepository(FindbugsConstants.REPOSITORY_KEY).isEmpty();
   }
 
   public void analyse(Project project, SensorContext context) {
     if (project.getReuseExistingRulesConfig()) {
       LOG.warn("Reusing existing Findbugs configuration not supported any more.");
     }
-    File report = getFindbugsReportFile(project);
-    if (report == null) {
-      report = executor.execute();
-    }
-    FindbugsXmlReportParser reportParser = new FindbugsXmlReportParser(report);
-    List<FindbugsXmlReportParser.XmlBugInstance> bugInstances = reportParser.getBugInstances();
 
-    for (FindbugsXmlReportParser.XmlBugInstance bugInstance : bugInstances) {
-      FindbugsXmlReportParser.XmlSourceLineAnnotation sourceLine = bugInstance.getPrimarySourceLine();
+    BugCollection collection = executor.execute();
+
+    for (BugInstance bugInstance : collection) {
+      SourceLineAnnotation sourceLine = bugInstance.getPrimarySourceLineAnnotation();
       if (sourceLine == null) {
         LOG.warn("No source line for " + bugInstance.getType());
         continue;
@@ -80,25 +75,30 @@ public class FindbugsSensor implements Sensor {
         continue;
       }
 
-      JavaFile resource = new JavaFile(sourceLine.getSonarJavaFileKey());
+      String longMessage = bugInstance.getMessageWithoutPrefix();
+      String className = bugInstance.getPrimarySourceLineAnnotation().getClassName();
+      int start = bugInstance.getPrimarySourceLineAnnotation().getStartLine();
+
+      JavaFile resource = new JavaFile(getSonarJavaFileKey(className));
       if (context.getResource(resource) != null) {
         Violation violation = Violation.create(rule, resource)
-            .setLineId(sourceLine.getStart())
-            .setMessage(bugInstance.getLongMessage());
+            .setLineId(start)
+            .setMessage(longMessage);
         context.saveViolation(violation);
       }
     }
   }
 
-  protected final File getFindbugsReportFile(Project project) {
-    if (project.getConfiguration().getString(CoreProperties.FINDBUGS_REPORT_PATH) != null) {
-      return new File(project.getConfiguration().getString(CoreProperties.FINDBUGS_REPORT_PATH));
+  private static String getSonarJavaFileKey(String className) {
+    if (className.indexOf('$') > -1) {
+      return className.substring(0, className.indexOf('$'));
     }
-    return null;
+    return className;
   }
 
   @Override
   public String toString() {
     return getClass().getSimpleName();
   }
+
 }
index 317b72e46d619c1d938741e17c9c6158bb357291..82379f3b1a70c0e9c1bc084251877b7bc4b5a69c 100644 (file)
 package org.sonar.plugins.findbugs;
 
 import com.google.common.collect.Lists;
-import org.apache.commons.configuration.Configuration;
+import edu.umd.cs.findbugs.*;
 import org.junit.Test;
-import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.SensorContext;
 import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.InputFile;
-import org.sonar.api.resources.InputFileUtils;
-import org.sonar.api.resources.JavaFile;
+import org.sonar.api.resources.*;
 import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectFileSystem;
-import org.sonar.api.resources.Resource;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.Violation;
 import org.sonar.api.test.IsViolation;
 
-import java.io.File;
 import java.util.ArrayList;
 
 import static org.fest.assertions.Assertions.assertThat;
@@ -99,52 +93,31 @@ public class FindbugsSensorTest extends FindbugsTests {
     Project project = createProject();
     FindbugsExecutor executor = mock(FindbugsExecutor.class);
     SensorContext context = mock(SensorContext.class);
-    Configuration conf = mock(Configuration.class);
-    // We assume that this report was generated during findbugs execution
-    File xmlFile = new File(getClass().getResource("/org/sonar/plugins/findbugs/findbugsReport.xml").toURI());
-    when(project.getConfiguration()).thenReturn(conf);
-    when(executor.execute()).thenReturn(xmlFile);
-    when(context.getResource(any(Resource.class))).thenReturn(new JavaFile("org.sonar.MyClass"));
-
-    FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FakeRuleFinder(), executor);
-    analyser.analyse(project, context);
-
-    verify(executor).execute();
-    verify(context, times(2)).saveViolation(any(Violation.class));
-
-    Violation wanted = Violation.create((Rule) null, new JavaFile("org.sonar.commons.ZipUtils")).setMessage(
-        "Empty zip file entry created in org.sonar.commons.ZipUtils._zip(String, File, ZipOutputStream)").setLineId(107);
-    verify(context).saveViolation(argThat(new IsViolation(wanted)));
 
-    wanted = Violation.create((Rule) null, new JavaFile("org.sonar.commons.resources.MeasuresDao")).setMessage(
-        "The class org.sonar.commons.resources.MeasuresDao$1 could be refactored into a named _static_ inner class").setLineId(56);
-    verify(context).saveViolation(argThat(new IsViolation(wanted)));
-  }
+    BugCollection collection = new SortedBugCollection();
+    BugInstance bugInstance = new BugInstance("AM_CREATES_EMPTY_ZIP_FILE_ENTRY", 2);
+    String className = "org.sonar.commons.ZipUtils";
+    String sourceFile = "org/sonar/commons/ZipUtils.java";
+    int startLine = 107;
+    ClassAnnotation classAnnotation = new ClassAnnotation(className, sourceFile);
+    bugInstance.add(classAnnotation);
+    MethodAnnotation methodAnnotation = new MethodAnnotation(className, "_zip", "(Ljava/lang/String;Ljava/io/File;Ljava/util/zip/ZipOutputStream;)V", true);
+    methodAnnotation.setSourceLines(new SourceLineAnnotation(className, sourceFile, startLine, 0, 0, 0));
+    bugInstance.add(methodAnnotation);
+    collection.add(bugInstance);
+    when(executor.execute()).thenReturn(collection);
 
-  @Test
-  public void shouldReuseReport() throws Exception {
-    Project project = createProject();
-    FindbugsExecutor executor = mock(FindbugsExecutor.class);
-    SensorContext context = mock(SensorContext.class);
-    Configuration conf = mock(Configuration.class);
-    File xmlFile = new File(getClass().getResource("/org/sonar/plugins/findbugs/findbugsReport.xml").toURI());
-    when(conf.getString(CoreProperties.FINDBUGS_REPORT_PATH)).thenReturn(xmlFile.getAbsolutePath());
-    when(project.getConfiguration()).thenReturn(conf);
     when(context.getResource(any(Resource.class))).thenReturn(new JavaFile("org.sonar.MyClass"));
 
     FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FakeRuleFinder(), executor);
     analyser.analyse(project, context);
 
-    verify(executor, never()).execute();
-    verify(context, times(2)).saveViolation(any(Violation.class));
+    verify(executor).execute();
+    verify(context, times(1)).saveViolation(any(Violation.class));
 
     Violation wanted = Violation.create((Rule) null, new JavaFile("org.sonar.commons.ZipUtils")).setMessage(
         "Empty zip file entry created in org.sonar.commons.ZipUtils._zip(String, File, ZipOutputStream)").setLineId(107);
     verify(context).saveViolation(argThat(new IsViolation(wanted)));
-
-    wanted = Violation.create((Rule) null, new JavaFile("org.sonar.commons.resources.MeasuresDao")).setMessage(
-        "The class org.sonar.commons.resources.MeasuresDao$1 could be refactored into a named _static_ inner class").setLineId(56);
-    verify(context).saveViolation(argThat(new IsViolation(wanted)));
   }
 
   @Test
@@ -152,12 +125,17 @@ public class FindbugsSensorTest extends FindbugsTests {
     Project project = createProject();
     FindbugsExecutor executor = mock(FindbugsExecutor.class);
     SensorContext context = mock(SensorContext.class);
-    Configuration conf = mock(Configuration.class);
-    File xmlFile = new File(getClass().getResource("/org/sonar/plugins/findbugs/findbugsReportWithUnknownRule.xml").toURI());
-    when(conf.getString(CoreProperties.FINDBUGS_REPORT_PATH)).thenReturn(xmlFile.getAbsolutePath());
-    when(project.getConfiguration()).thenReturn(conf);
     when(context.getResource(any(Resource.class))).thenReturn(new JavaFile("org.sonar.MyClass"));
 
+    BugCollection collection = new SortedBugCollection();
+    BugInstance bugInstance = new BugInstance("UNKNOWN", 2);
+    String className = "org.sonar.commons.ZipUtils";
+    String sourceFile = "org/sonar/commons/ZipUtils.java";
+    ClassAnnotation classAnnotation = new ClassAnnotation(className, sourceFile);
+    bugInstance.add(classAnnotation);
+    collection.add(bugInstance);
+    when(executor.execute()).thenReturn(collection);
+
     FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FakeRuleFinder(), executor);
     analyser.analyse(project, context);
 
index 43a10d9338d0c85ff12b11a2616b5f69330954f0..f94c6d7bc8a6c704f43a1c0a45a75757c88c3336 100644 (file)
@@ -273,10 +273,15 @@ public interface CoreProperties {
   String FINDBUGS_EFFORT_DEFAULT_VALUE = "Default";
   String FINDBUGS_CONFIDENCE_LEVEL_PROPERTY = "sonar.findbugs.confidenceLevel";
   String FINDBUGS_CONFIDENCE_LEVEL_DEFAULT_VALUE = "medium";
-  String FINDBUGS_REPORT_PATH = "sonar.findbugs.reportPath";
   String FINDBUGS_TIMEOUT_PROPERTY = "sonar.findbugs.timeout";
   long FINDBUGS_TIMEOUT_DEFAULT_VALUE = 600000;
 
+  /**
+   * @deprecated in 3.4
+   */
+  @Deprecated
+  String FINDBUGS_REPORT_PATH = "sonar.findbugs.reportPath";
+
   /* Google Analytics */
   String GOOGLE_ANALYTICS_PLUGIN = "google-analytics";
   String GOOGLE_ANALYTICS_ACCOUNT_PROPERTY = "sonar.google-analytics.account";