diff options
author | Janos Gyerik <janos.gyerik@sonarsource.com> | 2017-01-24 17:32:28 +0100 |
---|---|---|
committer | Duarte Meneses <duarte.meneses@sonarsource.com> | 2017-01-27 16:26:30 +0100 |
commit | 291382160309e0543067c59c193d126710370dee (patch) | |
tree | bacef8cf02968d4911360db95fd6375049bccf3e /sonar-plugin-api | |
parent | e606937326a6f2c9d83d7d2509d73bb237a94356 (diff) | |
download | sonarqube-291382160309e0543067c59c193d126710370dee.tar.gz sonarqube-291382160309e0543067c59c193d126710370dee.zip |
SONAR-8630 query by filename and ext (#1555)
Diffstat (limited to 'sonar-plugin-api')
9 files changed, 304 insertions, 0 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java index 72614539fad..1aa79288923 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FilePredicates.java @@ -56,6 +56,24 @@ public interface FilePredicates { FilePredicate hasRelativePath(String s); /** + * Predicate that matches files by filename, in any directory. + * For example, the parameter <code>Foo.java</code> will match both + * <code>some/path/Foo.java</code> and <code>other/path/Foo.java</code>. + * The parameter must match exactly, no patterns are allowed, + * and it must not be <code>null</code>. + */ + FilePredicate hasFilename(String s); + + /** + * Predicate that matches files by extension (case insensitive). + * For example, the parameter <code>java</code> will match + * <code>some/path/Foo.java</code> and <code>other/path/Foo.JAVA</code> + * but not <code>some/path/Foo.js</code>. + * The parameter must not be <code>null</code>. + */ + FilePredicate hasExtension(String s); + + /** * Predicate that gets the files which relative or absolute path matches a wildcard pattern. * <br> * If the parameter starts with <code>file:</code>, then absolute path is used, else relative path. Pattern diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java index 3243f8dcab5..2c9adee3092 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java @@ -165,5 +165,9 @@ public interface FileSystem { InputDir inputDir(String relativePath); InputModule module(); + + Iterable<InputFile> getFilesByName(String filename); + + Iterable<InputFile> getFilesByExtension(String extension); } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java index 864fde37b8e..1c503394418 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFilePredicates.java @@ -76,6 +76,15 @@ public class DefaultFilePredicates implements FilePredicates { } @Override + public FilePredicate hasFilename(String s) { + return new FilenamePredicate(s); + } + + @Override public FilePredicate hasExtension(String s) { + return new FileExtensionPredicate(s); + } + + @Override public FilePredicate matchesPathPattern(String inclusionPattern) { return new PathPatternPredicate(PathPattern.create(inclusionPattern)); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java index 7c7632df8d8..de2c28766de 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultFileSystem.java @@ -20,6 +20,8 @@ package org.sonar.api.batch.fs.internal; import com.google.common.collect.Iterables; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.SetMultimap; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; @@ -264,6 +266,8 @@ public class DefaultFileSystem implements FileSystem { private final Map<String, InputFile> fileMap = new HashMap<>(); private final Map<String, InputDir> dirMap = new HashMap<>(); private InputModule module; + private final SetMultimap<String, InputFile> filesByNameCache = LinkedHashMultimap.create(); + private final SetMultimap<String, InputFile> filesByExtensionCache = LinkedHashMultimap.create(); @Override public Iterable<InputFile> inputFiles() { @@ -286,8 +290,19 @@ public class DefaultFileSystem implements FileSystem { } @Override + public Iterable<InputFile> getFilesByName(String filename) { + return filesByNameCache.get(filename); + } + + @Override public Iterable<InputFile> getFilesByExtension(String extension) { + return filesByExtensionCache.get(extension); + } + + @Override protected void doAdd(InputFile inputFile) { fileMap.put(inputFile.relativePath(), inputFile); + filesByNameCache.put(FilenamePredicate.getFilename(inputFile), inputFile); + filesByExtensionCache.put(FileExtensionPredicate.getExtension(inputFile), inputFile); } @Override diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileExtensionPredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileExtensionPredicate.java new file mode 100644 index 00000000000..8eba8b00fc6 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileExtensionPredicate.java @@ -0,0 +1,62 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * 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 02110-1301, USA. + */ +package org.sonar.api.batch.fs.internal; + +import java.util.Locale; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; + +/** + * @since 6.3 + */ +public class FileExtensionPredicate extends AbstractFilePredicate { + + private final String extension; + + public FileExtensionPredicate(String extension) { + this.extension = lowercase(extension); + } + + @Override + public boolean apply(InputFile inputFile) { + return extension.equals(getExtension(inputFile)); + } + + @Override + public Iterable<InputFile> get(FileSystem.Index index) { + return index.getFilesByExtension(extension); + } + + public static String getExtension(InputFile inputFile) { + return getExtension(FilenamePredicate.getFilename(inputFile)); + } + + static String getExtension(String name) { + int index = name.lastIndexOf('.'); + if (index < 0) { + return ""; + } + return lowercase(name.substring(index + 1)); + } + + private static String lowercase(String extension) { + return extension.toLowerCase(Locale.ENGLISH); + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FilenamePredicate.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FilenamePredicate.java new file mode 100644 index 00000000000..16a66535720 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FilenamePredicate.java @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * 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 02110-1301, USA. + */ +package org.sonar.api.batch.fs.internal; + +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; + +/** + * @since 6.3 + */ +public class FilenamePredicate extends AbstractFilePredicate { + private final String filename; + + public FilenamePredicate(String filename) { + this.filename = filename; + } + + @Override + public boolean apply(InputFile inputFile) { + return filename.equals(getFilename(inputFile)); + } + + @Override + public Iterable<InputFile> get(FileSystem.Index index) { + return index.getFilesByName(filename); + } + + public static String getFilename(InputFile inputFile) { + return inputFile.file().getName(); + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java index b1befd9e62b..2d38624aa3f 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultFilePredicatesTest.java @@ -214,4 +214,14 @@ public class DefaultFilePredicatesTest { assertThat(predicates.or(new FilePredicate[] {predicates.all(), predicates.none()}).apply(javaFile)).isTrue(); assertThat(predicates.or(new FilePredicate[] {predicates.none(), predicates.none()}).apply(javaFile)).isFalse(); } + + @Test + public void hasFilename() { + assertThat(predicates.hasFilename("Action.java").apply(javaFile)).isTrue(); + } + + @Test + public void hasExtension() { + assertThat(predicates.hasExtension("java").apply(javaFile)).isTrue(); + } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FileExtensionPredicateTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FileExtensionPredicateTest.java new file mode 100644 index 00000000000..4de9de7723c --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FileExtensionPredicateTest.java @@ -0,0 +1,72 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * 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 02110-1301, USA. + */ +package org.sonar.api.batch.fs.internal; + +import java.io.File; +import java.io.IOException; +import org.junit.*; +import org.sonar.api.batch.fs.InputFile; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; +import static org.sonar.api.batch.fs.internal.FileExtensionPredicate.getExtension; + +public class FileExtensionPredicateTest { + + @Test + public void should_match_correct_extension() throws IOException { + FileExtensionPredicate predicate = new FileExtensionPredicate("bat"); + assertThat(predicate.apply(mockWithName("prog.bat"))).isTrue(); + assertThat(predicate.apply(mockWithName("prog.bat.bat"))).isTrue(); + } + + @Test + public void should_not_match_incorrect_extension() throws IOException { + FileExtensionPredicate predicate = new FileExtensionPredicate("bat"); + assertThat(predicate.apply(mockWithName("prog.batt"))).isFalse(); + assertThat(predicate.apply(mockWithName("prog.abat"))).isFalse(); + assertThat(predicate.apply(mockWithName("prog."))).isFalse(); + assertThat(predicate.apply(mockWithName("prog.bat."))).isFalse(); + assertThat(predicate.apply(mockWithName("prog.bat.batt"))).isFalse(); + assertThat(predicate.apply(mockWithName("prog"))).isFalse(); + } + + @Test + public void should_match_correct_extension_case_insensitively() throws IOException { + FileExtensionPredicate predicate = new FileExtensionPredicate("jAVa"); + assertThat(predicate.apply(mockWithName("Program.java"))).isTrue(); + assertThat(predicate.apply(mockWithName("Program.JAVA"))).isTrue(); + assertThat(predicate.apply(mockWithName("Program.Java"))).isTrue(); + assertThat(predicate.apply(mockWithName("Program.JaVa"))).isTrue(); + } + + @Test + public void test_empty_extension() { + assertThat(getExtension("prog")).isEmpty(); + assertThat(getExtension("prog.")).isEmpty(); + assertThat(getExtension(".")).isEmpty(); + } + + private InputFile mockWithName(String filename) throws IOException { + InputFile inputFile = mock(InputFile.class); + when(inputFile.file()).thenReturn(new File("dummy parent", filename)); + return inputFile; + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FilenamePredicateTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FilenamePredicateTest.java new file mode 100644 index 00000000000..edcaadd70fb --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FilenamePredicateTest.java @@ -0,0 +1,66 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * 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 02110-1301, USA. + */ +package org.sonar.api.batch.fs.internal; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import org.junit.*; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +public class FilenamePredicateTest { + @Test + public void should_match_file_by_filename() throws IOException { + String filename = "some name"; + InputFile inputFile = mock(InputFile.class); + when(inputFile.file()).thenReturn(newDummyFile(filename)); + + assertThat(new FilenamePredicate(filename).apply(inputFile)).isTrue(); + } + + @Test + public void should_not_match_file_by_different_filename() throws IOException { + String filename = "some name"; + InputFile inputFile = mock(InputFile.class); + when(inputFile.file()).thenReturn(newDummyFile(filename + "x")); + + assertThat(new FilenamePredicate(filename).apply(inputFile)).isFalse(); + } + + @Test + public void should_find_matching_file_in_index() throws IOException { + String filename = "some name"; + InputFile inputFile = mock(InputFile.class); + when(inputFile.file()).thenReturn(newDummyFile(filename)); + + FileSystem.Index index = mock(FileSystem.Index.class); + when(index.getFilesByName(filename)).thenReturn(Collections.singleton(inputFile)); + + assertThat(new FilenamePredicate(filename).get(index)).containsOnly(inputFile); + } + + private File newDummyFile(String filename) { + return new File("dummy parent", filename); + } +} |