From 85768fb0fb21b14e4387d9111ff98d4686868ca8 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Mon, 18 Jul 2016 20:26:27 +0300 Subject: [PATCH] Introduce TestSourcesFilter extension point --- .../com/intellij/analysis/AnalysisScope.java | 21 ++++---- .../psi/search/GlobalSearchScopesCore.java | 12 ++--- .../search/scope/ProjectProductionScope.java | 7 +-- .../intellij/psi/search/scope/TestsScope.java | 8 ++- .../scope/packageSet/PatternPackageSet.java | 10 ++-- .../index/DuplicatesInspectionBase.java | 18 ++++++- .../scopes/ModuleWithDependentsScope.java | 5 +- .../file/impl/ResolveScopeManagerImpl.java | 9 ++-- .../ide/hierarchy/HierarchyTreeStructure.java | 14 ++--- .../src/META-INF/LangExtensionPoints.xml | 1 + .../src/META-INF/LangExtensions.xml | 1 + .../com/intellij/openapi/roots/FileIndex.java | 5 +- .../openapi/roots/TestSourcesFilter.java | 52 +++++++++++++++++++ .../roots/ProjectRootTestSourcesFilter.java | 27 ++++++++++ .../impl/rules/UsageScopeGroupingRule.java | 10 ++-- .../coverage/SimpleCoverageAnnotator.java | 32 ++++++++---- 16 files changed, 173 insertions(+), 59 deletions(-) create mode 100644 platform/projectModel-api/src/com/intellij/openapi/roots/TestSourcesFilter.java create mode 100644 platform/projectModel-impl/src/com/intellij/openapi/roots/ProjectRootTestSourcesFilter.java diff --git a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java index bb818772286f..2b25cc0281b6 100644 --- a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java +++ b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,10 +39,12 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileFilter; import com.intellij.openapi.vfs.VirtualFileVisitor; import com.intellij.psi.*; -import com.intellij.psi.search.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.GlobalSearchScopesCore; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.SearchScope; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.ArrayUtil; -import com.intellij.util.Function; import com.intellij.util.Processor; import gnu.trove.THashSet; import org.intellij.lang.annotations.MagicConstant; @@ -192,7 +194,7 @@ public class AnalysisScope { if (myFilter != null && !myFilter.contains(virtualFile)) { return true; } - return !myIncludeTestSource && fileIndex.isInTestSourceContent(virtualFile); + return !myIncludeTestSource && TestSourcesFilter.isTestSources(virtualFile, myProject); } @NotNull @@ -512,7 +514,7 @@ public class AnalysisScope { return AnalysisScopeBundle.message("scope.option.module", myModule.getName()); case MODULES: - String modules = StringUtil.join(myModules, module -> module.getName(), ", "); + String modules = StringUtil.join(myModules, Module::getName, ", "); return AnalysisScopeBundle.message("scope.module.list", modules, Integer.valueOf(myModules.size())); case PROJECT: @@ -588,12 +590,12 @@ public class AnalysisScope { if (myElement instanceof PsiDirectory) { final VirtualFile directory = ((PsiFileSystemItem)myElement).getVirtualFile(); if (index.isInSourceContent(directory)) { - return isTest ? index.isInTestSourceContent(directory) : !index.isInTestSourceContent(directory); + return isTest == TestSourcesFilter.isTestSources(directory, myProject); } } else if (myElement instanceof PsiFile) { final VirtualFile file = ((PsiFileSystemItem)myElement).getVirtualFile(); if (file != null) { - return isTest ? index.isInTestSourceContent(file) : !index.isInTestSourceContent(file); + return isTest == TestSourcesFilter.isTestSources(file, myProject); } } } @@ -726,11 +728,10 @@ public class AnalysisScope { public boolean isAnalyzeTestsByDefault() { switch (myType) { case DIRECTORY: - return ProjectRootManager.getInstance(myElement.getProject()).getFileIndex() - .isInTestSourceContent(((PsiDirectory)myElement).getVirtualFile()); + return TestSourcesFilter.isTestSources(((PsiDirectory)myElement).getVirtualFile(), myElement.getProject()); case FILE: final PsiFile containingFile = myElement.getContainingFile(); - return ProjectRootManager.getInstance(containingFile.getProject()).getFileIndex().isInTestSourceContent(containingFile.getVirtualFile()); + return TestSourcesFilter.isTestSources(containingFile.getVirtualFile(), containingFile.getProject()); case MODULE: return isTestOnly(myModule); case MODULES: diff --git a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java index 5a88cc4aa779..23ec76fd38ba 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java +++ b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -28,7 +29,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.search.scope.packageSet.*; import com.intellij.util.ArrayUtil; -import com.intellij.util.Function; +import com.intellij.util.ObjectUtils; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -135,7 +136,7 @@ public class GlobalSearchScopesCore { @Override public boolean contains(@NotNull VirtualFile file) { - return myFileIndex.isInSourceContent(file) && !myFileIndex.isInTestSourceContent(file); + return myFileIndex.isInSourceContent(file) && !TestSourcesFilter.isTestSources(file, ObjectUtils.assertNotNull(getProject())); } @Override @@ -166,16 +167,13 @@ public class GlobalSearchScopesCore { } private static class TestScopeFilter extends GlobalSearchScope { - private final ProjectFileIndex myFileIndex; - private TestScopeFilter(@NotNull Project project) { super(project); - myFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); } @Override public boolean contains(@NotNull VirtualFile file) { - return myFileIndex.isInTestSourceContent(file); + return TestSourcesFilter.isTestSources(file, ObjectUtils.assertNotNull(getProject())); } @Override diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.java b/platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.java index 6aa1c933824c..4adf5a623cee 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.java +++ b/platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import com.intellij.ide.IdeBundle; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.scope.packageSet.AbstractPackageSet; import com.intellij.psi.search.scope.packageSet.NamedScope; @@ -44,9 +45,9 @@ public class ProjectProductionScope extends NamedScope { final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex(); return file != null && index.isInSource(file) - && !index.isInTestSourceContent(file) && !index.isInLibraryClasses(file) - && !index.isInLibrarySource(file); + && !index.isInLibrarySource(file) + && !TestSourcesFilter.isTestSources(file, project); } }); } diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/TestsScope.java b/platform/analysis-api/src/com/intellij/psi/search/scope/TestsScope.java index d52ab2d8cf45..c952df3fbd02 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/scope/TestsScope.java +++ b/platform/analysis-api/src/com/intellij/psi/search/scope/TestsScope.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,7 @@ package com.intellij.psi.search.scope; import com.intellij.ide.IdeBundle; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ProjectFileIndex; -import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.scope.packageSet.AbstractPackageSet; import com.intellij.psi.search.scope.packageSet.NamedScope; @@ -43,8 +42,7 @@ public class TestsScope extends NamedScope { @Override public boolean contains(VirtualFile file, @NotNull Project project, @Nullable NamedScopesHolder holder) { - final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex(); - return file != null && index.isInTestSourceContent(file); + return file != null && TestSourcesFilter.isTestSources(file, project); } }); } diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java index 41ff050b3ce5..7deb3e147c74 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java +++ b/platform/analysis-api/src/com/intellij/psi/search/scope/packageSet/PatternPackageSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -89,15 +89,15 @@ public class PatternPackageSet extends PatternBasedPackageSet { return fileIndex.isInContent(file) && FilePatternPackageSet.matchesModule(myModuleGroupPattern, myModulePattern, file, fileIndex); } if (myScope == SCOPE_SOURCE) { - return isSource && !fileIndex.isInTestSourceContent(file) && FilePatternPackageSet.matchesModule(myModuleGroupPattern, myModulePattern, - file, fileIndex); + return isSource && !TestSourcesFilter.isTestSources(file, project) + && FilePatternPackageSet.matchesModule(myModuleGroupPattern, myModulePattern, file, fileIndex); } if (myScope == SCOPE_LIBRARY) { return (fileIndex.isInLibraryClasses(file) || fileIndex.isInLibrarySource(file)) && matchesLibrary(myModulePattern, file, fileIndex); } if (myScope == SCOPE_TEST) { - return isSource && fileIndex.isInTestSourceContent(file) && FilePatternPackageSet.matchesModule(myModuleGroupPattern, myModulePattern, - file, fileIndex); + return isSource && TestSourcesFilter.isTestSources(file, project) && + FilePatternPackageSet.matchesModule(myModuleGroupPattern, myModulePattern, file, fileIndex); } if (myScope == SCOPE_PROBLEM) { return isSource && WolfTheProblemSolver.getInstance(project).isProblemFile(file) && diff --git a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesInspectionBase.java b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesInspectionBase.java index 48ebd2d23ed1..d405c66a752d 100644 --- a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesInspectionBase.java +++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesInspectionBase.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.dupLocator.index; import com.intellij.codeInspection.*; @@ -15,6 +30,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.FileIndex; import com.intellij.openapi.roots.GeneratedSourcesFilter; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VfsUtilCore; @@ -251,7 +267,7 @@ public class DuplicatesInspectionBase extends LocalInspectionTool { if (myFileIndex.isInSourceContent(virtualFile)) { if (!myFileIndex.isInSourceContent(file)) return true; - if (!myFileIndex.isInTestSourceContent(virtualFile) && myFileIndex.isInTestSourceContent(file)) return true; + if (!TestSourcesFilter.isTestSources(virtualFile, project) && TestSourcesFilter.isTestSources(file, project)) return true; if (mySkipGeneratedCode) { if (!myFileWithinGeneratedCode && GeneratedSourcesFilter.isGeneratedSourceByAnyFilter(file, project)) return true; } diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java index d7c1792277ec..fedbcfb378bc 100644 --- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java +++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,6 @@ import com.intellij.util.containers.Queue; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -109,7 +108,7 @@ class ModuleWithDependentsScope extends GlobalSearchScope { boolean contains(@NotNull VirtualFile file, boolean myOnlyTests) { Module moduleOfFile = myProjectFileIndex.getModuleForFile(file); if (moduleOfFile == null || !myModules.contains(moduleOfFile)) return false; - if (myOnlyTests && !myProjectFileIndex.isInTestSourceContent(file)) return false; + if (myOnlyTests && !TestSourcesFilter.isTestSources(file, moduleOfFile.getProject())) return false; return myProjectScope.contains(file); } diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java index 14b4949e282f..b99a71e5b44a 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,10 @@ import com.intellij.injected.editor.VirtualFileWindow; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.*; +import com.intellij.openapi.roots.OrderEntry; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.roots.impl.LibraryScopeCache; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileWithId; @@ -78,7 +81,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager { ProjectFileIndex projectFileIndex = myProjectRootManager.getFileIndex(); Module module = projectFileIndex.getModuleForFile(vFile); if (module != null) { - boolean includeTests = projectFileIndex.isInTestSourceContent(vFile); + boolean includeTests = TestSourcesFilter.isTestSources(vFile, myProject); return GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, includeTests); } diff --git a/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyTreeStructure.java b/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyTreeStructure.java index 551fd38b9dc2..d53565cba4de 100644 --- a/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyTreeStructure.java +++ b/platform/lang-impl/src/com/intellij/ide/hierarchy/HierarchyTreeStructure.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,13 +19,16 @@ package com.intellij.ide.hierarchy; import com.intellij.ide.util.treeView.AbstractTreeStructure; import com.intellij.ide.util.treeView.NodeDescriptor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.search.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.GlobalSearchScopesCore; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.scope.packageSet.NamedScope; import com.intellij.psi.search.scope.packageSet.NamedScopeManager; import com.intellij.psi.search.scope.packageSet.NamedScopesHolder; @@ -160,14 +163,13 @@ public abstract class HierarchyTreeStructure extends AbstractTreeStructure { } else if (HierarchyBrowserBaseEx.SCOPE_PROJECT.equals(scopeType)) { final VirtualFile virtualFile = srcElement.getContainingFile().getVirtualFile(); - if (virtualFile != null && ProjectRootManager.getInstance(myProject).getFileIndex().isInTestSourceContent(virtualFile)) { + if (virtualFile != null && TestSourcesFilter.isTestSources(virtualFile, myProject)) { return false; } } else if (HierarchyBrowserBaseEx.SCOPE_TEST.equals(scopeType)) { - final VirtualFile virtualFile = srcElement.getContainingFile().getVirtualFile(); - if (virtualFile != null && !ProjectRootManager.getInstance(myProject).getFileIndex().isInTestSourceContent(virtualFile)) { + if (virtualFile != null && !TestSourcesFilter.isTestSources(virtualFile, myProject)) { return false; } } else if (!HierarchyBrowserBaseEx.SCOPE_ALL.equals(scopeType)) { diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 513c8ff2367d..d25176856a70 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -697,6 +697,7 @@ interface="com.intellij.testIntegration.TestFinder"/> + diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 1603d66c139f..9ebe7af9091f 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -322,6 +322,7 @@ serviceImplementation="com.intellij.psi.impl.file.impl.ResolveScopeManagerImpl"/> + fileOrDir is a file or directory from the test content source * + * @see TestSourcesFilter#isTestSources(VirtualFile, Project) + * * @param fileOrDir the file or directory to check. * @return true if the file or directory belongs to a test source root, false otherwise. */ diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/TestSourcesFilter.java b/platform/projectModel-api/src/com/intellij/openapi/roots/TestSourcesFilter.java new file mode 100644 index 000000000000..66b9b617348a --- /dev/null +++ b/platform/projectModel-api/src/com/intellij/openapi/roots/TestSourcesFilter.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.roots; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +/** + * Implementations of this extension point can tell IDE whether some particular file is a test file despite project roots configuration. + *

+ * By default, IntelliJ Platform considers files as tests only if they are located under test + * sources root {@link FileIndex#isInTestSourceContent(VirtualFile)}. + *

+ * However there plenty frameworks and languages which keep test files just nearby production files. + * E.g. *_test.go files are test files in Go language and some js/dart files are test files depending + * on their content. The extensions allow IDE to highlight such files with a green background, + * properly check if they are included in built-in search scopes, etc. + * + * @see FileIndex#isInTestSourceContent(VirtualFile) + * @since 2016.3 + * @author zolotov + */ + +public abstract class TestSourcesFilter { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.testSourcesFilter"); + + public static boolean isTestSources(@NotNull VirtualFile file, @NotNull Project project) { + for (TestSourcesFilter filter : EP_NAME.getExtensions()) { + if (filter.isTestSource(file, project)) { + return true; + } + } + return false; + } + + public abstract boolean isTestSource(@NotNull VirtualFile file, @NotNull Project project); +} diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/ProjectRootTestSourcesFilter.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/ProjectRootTestSourcesFilter.java new file mode 100644 index 000000000000..345f557e4f29 --- /dev/null +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/ProjectRootTestSourcesFilter.java @@ -0,0 +1,27 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.roots; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +public class ProjectRootTestSourcesFilter extends TestSourcesFilter { + @Override + public boolean isTestSource(@NotNull VirtualFile file, @NotNull Project project) { + return ProjectFileIndex.SERVICE.getInstance(project).isInTestSourceContent(file); + } +} diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageScopeGroupingRule.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageScopeGroupingRule.java index b62d93533d12..80b216211e84 100644 --- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageScopeGroupingRule.java +++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageScopeGroupingRule.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,10 @@ package com.intellij.usages.impl.rules; import com.intellij.icons.AllIcons; import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; @@ -50,11 +52,11 @@ public class UsageScopeGroupingRule implements UsageGroupingRule, DumbAware { if (virtualFile == null) { return null; } - ProjectFileIndex fileIndex = ProjectRootManager.getInstance(element.getProject()).getFileIndex(); + Project project = element.getProject(); + ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); boolean isInLib = fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile); if (isInLib) return LIBRARY; - boolean isInTest = fileIndex.isInTestSourceContent(virtualFile); - return isInTest ? TEST : PRODUCTION; + return TestSourcesFilter.isTestSources(virtualFile, project) ? TEST : PRODUCTION; } private static final UsageScopeGroup TEST = new UsageScopeGroup(0) { diff --git a/plugins/coverage-common/src/com/intellij/coverage/SimpleCoverageAnnotator.java b/plugins/coverage-common/src/com/intellij/coverage/SimpleCoverageAnnotator.java index 8afe8628db3d..10c24d5596cb 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/SimpleCoverageAnnotator.java +++ b/plugins/coverage-common/src/com/intellij/coverage/SimpleCoverageAnnotator.java @@ -1,9 +1,24 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.coverage; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.Computable; +import com.intellij.openapi.roots.TestSourcesFilter; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtilCore; @@ -51,10 +66,7 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { @NotNull final CoverageSuitesBundle currentSuite) { final VirtualFile dir = directory.getVirtualFile(); - final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(directory.getProject()).getFileIndex(); - //final Module module = projectFileIndex.getModuleForFile(dir); - - final boolean isInTestContent = projectFileIndex.isInTestSourceContent(dir); + final boolean isInTestContent = TestSourcesFilter.isTestSources(dir, directory.getProject()); if (!currentSuite.isTrackTestFolders() && isInTestContent) { return null; } @@ -171,8 +183,7 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { @NotNull final ProjectFileIndex index, @NotNull final CoverageEngine coverageEngine, Set visitedDirs, - @NotNull final Map normalizedFiles2Files) - { + @NotNull final Map normalizedFiles2Files) { if (!index.isInContent(dir)) { return null; } @@ -188,15 +199,14 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { } visitedDirs.add(dir); - final boolean isInTestSrcContent = index.isInTestSourceContent(dir); + final boolean isInTestSrcContent = TestSourcesFilter.isTestSources(dir, getProject()); // Don't count coverage for tests folders if track test folders is switched off if (!trackTestFolders && isInTestSrcContent) { return null; } - final VirtualFile[] children = dataManager.doInReadActionIfProjectOpen(() -> dir.getChildren()); - + final VirtualFile[] children = dataManager.doInReadActionIfProjectOpen(dir::getChildren); if (children == null) { return null; } @@ -281,7 +291,7 @@ public abstract class SimpleCoverageAnnotator extends BaseCoverageAnnotator { suite.isTrackTestFolders(), index, suite.getCoverageEngine(), - ContainerUtil.newHashSet(), + ContainerUtil.newHashSet(), Collections.unmodifiableMap(normalizedFiles2Files)); }