import org.sonar.xoo.lang.XooTokenizerSensor;
import org.sonar.xoo.rule.ChecksSensor;
import org.sonar.xoo.rule.CreateIssueByInternalKeySensor;
+import org.sonar.xoo.rule.DeprecatedResourceApiSensor;
import org.sonar.xoo.rule.OneIssueOnDirPerFileSensor;
import org.sonar.xoo.rule.OneIssuePerLineSensor;
import org.sonar.xoo.rule.RandomAccessSensor;
DependencySensor.class,
ChecksSensor.class,
RandomAccessSensor.class,
+ DeprecatedResourceApiSensor.class,
OneIssuePerLineSensor.class,
OneIssueOnDirPerFileSensor.class,
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.xoo.rule;
+
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.rule.ActiveRules;
+import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.issue.Issuable;
+import org.sonar.api.resources.Directory;
+import org.sonar.api.resources.Project;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.scan.filesystem.FileQuery;
+import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.xoo.Xoo;
+
+import java.io.File;
+
+public class DeprecatedResourceApiSensor implements Sensor {
+
+ public static final String RULE_KEY = "DeprecatedResourceApi";
+ private final ModuleFileSystem fileSystem;
+ private final ResourcePerspectives perspectives;
+ private final ActiveRules activeRules;
+
+ public DeprecatedResourceApiSensor(ModuleFileSystem fileSystem, ResourcePerspectives perspectives, ActiveRules activeRules) {
+ this.fileSystem = fileSystem;
+ this.perspectives = perspectives;
+ this.activeRules = activeRules;
+ }
+
+ @Override
+ public boolean shouldExecuteOnProject(Project project) {
+ return !fileSystem.files(FileQuery.onMain().onLanguage(Xoo.KEY)).isEmpty() && activeRules.find(RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY)) != null;
+ }
+
+ @Override
+ public void analyse(Project module, org.sonar.api.batch.SensorContext context) {
+ createIssueOnDir(new Directory(""));
+ File src = module.getFileSystem().getSourceDirs().get(0);
+
+ for (File f : fileSystem.files(FileQuery.onMain().onLanguage(Xoo.KEY))) {
+ String relativePathFromSourceDir = new PathResolver().relativePath(src, f);
+ org.sonar.api.resources.File sonarFile = new org.sonar.api.resources.File(relativePathFromSourceDir);
+ Issuable issuable = perspectives.as(Issuable.class, sonarFile);
+ issuable.addIssue(issuable.newIssueBuilder()
+ .ruleKey(RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY))
+ .message("Issue created using deprecated API")
+ .line(1)
+ .build());
+
+ sonarFile = context.getResource(sonarFile);
+ Directory parent = sonarFile.getParent();
+ createIssueOnDir(parent);
+ }
+
+ }
+
+ private Directory createIssueOnDir(Directory dir) {
+ Issuable issuable = perspectives.as(Issuable.class, dir);
+ issuable.addIssue(issuable.newIssueBuilder()
+ .ruleKey(RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, RULE_KEY))
+ .message("Issue created using deprecated API")
+ .build());
+ return dir;
+ }
+
+}
@Test
public void provide_extensions() {
- assertThat(new XooPlugin().getExtensions()).hasSize(20);
+ assertThat(new XooPlugin().getExtensions()).hasSize(21);
}
}
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.MeasuresFilters;
+import org.sonar.api.resources.Directory;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;
if (StringUtils.isNotBlank(reference.getKey())) {
return buckets.get(reference);
}
+ String relativePathFromSourceDir = null;
+ boolean isTest = false;
+ boolean isDir = false;
+ if (reference instanceof File) {
+ File referenceFile = (File) reference;
+ isTest = Qualifiers.UNIT_TEST_FILE.equals(referenceFile.getQualifier());
+ relativePathFromSourceDir = referenceFile.relativePathFromSourceDir();
+ } else if (reference instanceof Directory) {
+ isDir = true;
+ Directory referenceDir = (Directory) reference;
+ relativePathFromSourceDir = referenceDir.relativePathFromSourceDir();
+ if (Directory.ROOT.equals(relativePathFromSourceDir)) {
+ relativePathFromSourceDir = "";
+ }
+ }
+ if (relativePathFromSourceDir != null) {
+ // Resolve using deprecated key
+ List<java.io.File> dirs;
+ if (isTest) {
+ dirs = getProject().getFileSystem().getTestDirs();
+ } else {
+ dirs = getProject().getFileSystem().getSourceDirs();
+ }
+ for (java.io.File src : dirs) {
+ java.io.File abs = new java.io.File(src, relativePathFromSourceDir);
+ Bucket b = getBucket(isDir ? Directory.fromIOFile(abs, getProject()) : File.fromIOFile(abs, getProject()));
+ if (b != null) {
+ return b;
+ }
+ }
+
+ }
return null;
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 02110-1301, USA.
+ */
+package org.sonar.batch.mediumtest.deprecated;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.io.FileUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.batch.mediumtest.BatchMediumTester;
+import org.sonar.batch.mediumtest.TaskResult;
+import org.sonar.batch.protocol.input.ActiveRule;
+import org.sonar.xoo.XooPlugin;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DeprecatedApiMediumTest {
+
+ @org.junit.Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ public BatchMediumTester tester = BatchMediumTester.builder()
+ .registerPlugin("xoo", new XooPlugin())
+ .addDefaultQProfile("xoo", "Sonar Way")
+ .activateRule(new ActiveRule("xoo", "DeprecatedResourceApi", null, "One issue per line", "MAJOR", null, "xoo"))
+ .build();
+
+ @Before
+ public void prepare() {
+ tester.start();
+ }
+
+ @After
+ public void stop() {
+ tester.stop();
+ }
+
+ @Test
+ public void testIssueDetails() throws IOException {
+
+ File baseDir = temp.newFolder();
+ File srcDir = new File(baseDir, "src");
+ srcDir.mkdir();
+
+ File xooFileInRootDir = new File(srcDir, "sample.xoo");
+ FileUtils.write(xooFileInRootDir, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10");
+
+ File xooFileInAnotherDir = new File(srcDir, "package/sample.xoo");
+ FileUtils.write(xooFileInAnotherDir, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10");
+
+ TaskResult result = tester.newTask()
+ .properties(ImmutableMap.<String, String>builder()
+ .put("sonar.task", "scan")
+ .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
+ .put("sonar.projectKey", "com.foo.project")
+ .put("sonar.projectName", "Foo Project")
+ .put("sonar.projectVersion", "1.0-SNAPSHOT")
+ .put("sonar.projectDescription", "Description of Foo Project")
+ .put("sonar.sources", "src")
+ .build())
+ .start();
+
+ // 1 issue on root dir + 1 issue on each file + 1 issue on each file parent dir
+ assertThat(result.issues()).hasSize(5);
+ }
+
+}
public static final String SEPARATOR = "/";
public static final String ROOT = "[root]";
+ private final String relativePathFromSourceDir;
+
Directory() {
// Used by factory
+ this.relativePathFromSourceDir = null;
+ }
+
+ /**
+ * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)}
+ */
+ @Deprecated
+ public Directory(String relativePathFromSourceDir) {
+ this(relativePathFromSourceDir, null);
+ }
+
+ /**
+ * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)}
+ */
+ @Deprecated
+ public Directory(String relativePathFromSourceDir, Language language) {
+ this.relativePathFromSourceDir = parseKey(relativePathFromSourceDir);
+ }
+
+ /**
+ * Internal.
+ */
+ public String relativePathFromSourceDir() {
+ return relativePathFromSourceDir;
}
@Override
import javax.annotation.CheckForNull;
+import java.util.List;
+
/**
* This class is an implementation of a resource of type FILE
*
private Directory parent;
private String qualifier = Qualifiers.FILE;
+ private final String relativePathFromSourceDir;
+
private File() {
// Used by factory method
+ this.relativePathFromSourceDir = null;
+ }
+
+ /**
+ * @deprecated since 4.2 use {@link FileSystem#inputFile(org.sonar.api.batch.fs.FilePredicate)}
+ */
+ @Deprecated
+ public File(String relativePathFromSourceDir) {
+ if (relativePathFromSourceDir == null) {
+ throw new IllegalArgumentException("File key is null");
+ }
+ this.relativePathFromSourceDir = parseKey(relativePathFromSourceDir);
+ }
+
+ /**
+ * @deprecated since 4.2 use {@link FileSystem#inputFile(org.sonar.api.batch.fs.FilePredicate)}
+ */
+ @Deprecated
+ public File(String relativeDirectoryPathFromSourceDir, String filename) {
+ this.filename = StringUtils.trim(filename);
+ if (StringUtils.isBlank(relativeDirectoryPathFromSourceDir)) {
+ this.relativePathFromSourceDir = filename;
+ } else {
+ this.relativePathFromSourceDir = new StringBuilder().append(Directory.parseKey(relativeDirectoryPathFromSourceDir)).append(Directory.SEPARATOR).append(this.filename)
+ .toString();
+ }
+ }
+
+ /**
+ * @deprecated since 4.2 use {@link FileSystem#inputFile(org.sonar.api.batch.fs.FilePredicate)}
+ */
+ @Deprecated
+ public File(Language language, String relativePathFromSourceDir) {
+ this(relativePathFromSourceDir);
+ this.language = language;
+ }
+
+ /**
+ * Creates a File from language, directory and filename
+ * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)}
+ */
+ @Deprecated
+ public File(Language language, String relativeDirectoryPathFromSourceDir, String filename) {
+ this(relativeDirectoryPathFromSourceDir, filename);
+ this.language = language;
+ }
+
+ /**
+ * Internal.
+ */
+ public String relativePathFromSourceDir() {
+ return relativePathFromSourceDir;
}
/**
return matcher.match(getKey());
}
+ /**
+ * Creates a File from an io.file and a list of sources directories
+ * @deprecated since 4.2 use {@link #fromIOFile(java.io.File, Project)}
+ */
+ @Deprecated
+ @CheckForNull
+ public static File fromIOFile(java.io.File file, List<java.io.File> sourceDirs) {
+ PathResolver.RelativePath relativePath = new PathResolver().relativePath(sourceDirs, file);
+ if (relativePath != null) {
+ return new File(relativePath.path());
+ }
+ return null;
+ }
+
/**
* Creates a {@link File} from an absolute {@link java.io.File} and a module.
* The returned {@link File} can be then passed for example to