2 * Copyright 2000-2016 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.roots.impl;
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.command.WriteCommandAction;
20 import com.intellij.openapi.fileTypes.FileTypeManager;
21 import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
22 import com.intellij.openapi.module.ModifiableModuleModel;
23 import com.intellij.openapi.module.Module;
24 import com.intellij.openapi.module.ModuleManager;
25 import com.intellij.openapi.module.StdModuleTypes;
26 import com.intellij.openapi.project.Project;
27 import com.intellij.openapi.roots.*;
28 import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
29 import com.intellij.openapi.util.EmptyRunnable;
30 import com.intellij.openapi.util.io.FileUtil;
31 import com.intellij.openapi.vfs.*;
32 import com.intellij.testFramework.*;
33 import gnu.trove.THashSet;
34 import org.jetbrains.annotations.NotNull;
35 import org.jetbrains.annotations.Nullable;
36 import org.jetbrains.jps.model.java.JavaResourceRootType;
37 import org.jetbrains.jps.model.java.JavaSourceRootType;
38 import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
43 @PlatformTestCase.WrapInCommand
44 public class DirectoryIndexTest extends IdeaTestCase {
45 private DirectoryIndexImpl myIndex;
47 private Module myModule2, myModule3;
48 private VirtualFile myRootVFile;
49 private VirtualFile myModule1Dir, myModule2Dir, myModule3Dir;
50 private VirtualFile mySrcDir1, mySrcDir2;
51 private VirtualFile myTestSrc1;
52 private VirtualFile myPack1Dir, myPack2Dir;
53 private VirtualFile myFileLibDir, myFileLibSrc, myFileLibCls;
54 private VirtualFile myLibDir, myLibSrcDir, myLibAdditionalSrcDir, myLibClsDir;
55 private VirtualFile myCvsDir;
56 private VirtualFile myExcludeDir;
57 private VirtualFile myOutputDir;
58 private VirtualFile myModule1OutputDir;
59 private VirtualFile myResDir, myTestResDir;
60 private VirtualFile myExcludedLibSrcDir, myExcludedLibClsDir;
61 private ProjectFileIndex myFileIndex;
64 protected void setUp() throws Exception {
67 final File root = createTempDirectory();
69 ApplicationManager.getApplication().runWriteAction(() -> {
96 myRootVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(root);
97 assertNotNull(myRootVFile);
99 myFileLibDir = createChildDirectory(myRootVFile, "lib");
100 myFileLibSrc = createChildData(myFileLibDir, "file.src");
101 myFileLibCls = createChildData(myFileLibDir, "file.cls");
102 myModule1Dir = createChildDirectory(myRootVFile, "module1");
103 mySrcDir1 = createChildDirectory(myModule1Dir, "src1");
104 myPack1Dir = createChildDirectory(mySrcDir1, "pack1");
105 myTestSrc1 = createChildDirectory(mySrcDir1, "testSrc");
106 myPack2Dir = createChildDirectory(myTestSrc1, "pack2");
107 myResDir = createChildDirectory(myModule1Dir, "res");
108 myTestResDir = createChildDirectory(myModule1Dir, "testRes");
110 myLibDir = createChildDirectory(myModule1Dir, "lib");
111 myLibSrcDir = createChildDirectory(myLibDir, "src");
112 myExcludedLibSrcDir = createChildDirectory(myLibSrcDir, "exc");
113 myLibAdditionalSrcDir = createChildDirectory(myLibDir, "additional-src");
114 myLibClsDir = createChildDirectory(myLibDir, "cls");
115 myExcludedLibClsDir = createChildDirectory(myLibClsDir, "exc");
116 myModule2Dir = createChildDirectory(myModule1Dir, "module2");
117 mySrcDir2 = createChildDirectory(myModule2Dir, "src2");
118 myCvsDir = createChildDirectory(mySrcDir2, "CVS");
119 myExcludeDir = createChildDirectory(mySrcDir2, "excluded");
121 myModule3Dir = createChildDirectory(myRootVFile, "module3");
123 myOutputDir = createChildDirectory(myRootVFile, "out");
124 myModule1OutputDir = createChildDirectory(myOutputDir, "module1");
126 getCompilerProjectExtension().setCompilerOutputUrl(myOutputDir.getUrl());
127 ModuleManager moduleManager = ModuleManager.getInstance(myProject);
129 // fill roots of module1
131 ModuleRootModificationUtil.setModuleSdk(myModule, null);
132 PsiTestUtil.addContentRoot(myModule, myModule1Dir);
133 PsiTestUtil.addSourceRoot(myModule, mySrcDir1);
134 PsiTestUtil.addSourceRoot(myModule, myTestSrc1, true);
135 PsiTestUtil.addSourceRoot(myModule, myResDir, JavaResourceRootType.RESOURCE);
136 PsiTestUtil.addSourceRoot(myModule, myTestResDir, JavaResourceRootType.TEST_RESOURCE);
138 ModuleRootModificationUtil.addModuleLibrary(myModule, "lib.js",
139 Collections.singletonList(myFileLibCls.getUrl()), Collections
140 .singletonList(myFileLibSrc.getUrl()));
141 PsiTestUtil.addExcludedRoot(myModule, myExcludedLibClsDir);
142 PsiTestUtil.addExcludedRoot(myModule, myExcludedLibSrcDir);
145 // fill roots of module2
147 VirtualFile moduleFile = createChildData(myModule2Dir, "module2.iml");
148 myModule2 = moduleManager.newModule(moduleFile.getPath(), StdModuleTypes.JAVA.getId());
150 PsiTestUtil.addContentRoot(myModule2, myModule2Dir);
151 PsiTestUtil.addSourceRoot(myModule2, mySrcDir2);
152 PsiTestUtil.addExcludedRoot(myModule2, myExcludeDir);
153 ModuleRootModificationUtil.addModuleLibrary(myModule2, "lib",
154 Collections.singletonList(myLibClsDir.getUrl()), Collections.singletonList(myLibSrcDir.getUrl()),
155 Arrays.asList(myExcludedLibClsDir.getUrl(), myExcludedLibSrcDir.getUrl()), DependencyScope.COMPILE, true);
157 PlatformTestUtil.registerExtension(AdditionalLibraryRootsProvider.EP_NAME, new AdditionalLibraryRootsProvider() {
160 public Collection<VirtualFile> getAdditionalProjectLibrarySourceRoots(@NotNull Project project) {
161 return Collections.singletonList(myLibAdditionalSrcDir);
163 }, getTestRootDisposable());
165 // fill roots of module3
167 VirtualFile moduleFile = createChildData(myModule3Dir, "module3.iml");
168 myModule3 = moduleManager.newModule(moduleFile.getPath(), StdModuleTypes.JAVA.getId());
170 PsiTestUtil.addContentRoot(myModule3, myModule3Dir);
171 ModuleRootModificationUtil.addDependency(myModule3, myModule2);
175 myIndex = (DirectoryIndexImpl)DirectoryIndex.getInstance(myProject);
176 myFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
177 // to not interfere with previous test firing vfs events
178 VirtualFileManager.getInstance().syncRefresh();
181 private CompilerProjectExtension getCompilerProjectExtension() {
182 final CompilerProjectExtension instance = CompilerProjectExtension.getInstance(myProject);
183 assertNotNull(instance);
187 public void testDirInfos() {
188 assertNotInProject(myRootVFile);
190 // beware: files in directory index
191 checkInfo(myFileLibSrc, null, false, true, "", null, myModule);
192 checkInfo(myFileLibCls, null, true, false, "", null, myModule);
194 checkInfo(myModule1Dir, myModule, false, false, null, null);
195 checkInfo(mySrcDir1, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
196 checkInfo(myPack1Dir, myModule, false, false, "pack1", JavaSourceRootType.SOURCE, myModule);
197 checkInfo(myTestSrc1, myModule, false, false, "", JavaSourceRootType.TEST_SOURCE, myModule);
198 checkInfo(myPack2Dir, myModule, false, false, "pack2", JavaSourceRootType.TEST_SOURCE, myModule);
199 checkInfo(myResDir, myModule, false, false, "", JavaResourceRootType.RESOURCE, myModule);
200 checkInfo(myTestResDir, myModule, false, false, "", JavaResourceRootType.TEST_RESOURCE, myModule);
202 checkInfo(myLibDir, myModule, false, false, null, null);
203 checkInfo(myLibSrcDir, myModule, false, true, "", null, myModule2, myModule3);
204 checkInfo(myLibClsDir, myModule, true, false, "", null, myModule2, myModule3);
206 assertEquals(myLibSrcDir, assertInProject(myLibSrcDir).getSourceRoot());
208 checkInfo(myModule2Dir, myModule2, false, false, null, null);
209 checkInfo(mySrcDir2, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
210 assertNotInProject(myCvsDir);
211 assertExcluded(myExcludeDir, myModule2);
212 assertExcluded(myExcludedLibClsDir, myModule);
213 assertExcluded(myExcludedLibSrcDir, myModule);
215 assertEquals(myModule1Dir, assertInProject(myLibClsDir).getContentRoot());
217 checkInfo(myModule3Dir, myModule3, false, false, null, null);
219 VirtualFile cvs = createChildDirectory(myPack1Dir, "CVS");
220 assertNotInProject(cvs);
221 assertNull(myFileIndex.getPackageNameByDirectory(cvs));
224 public void testDirsByPackageName() {
225 checkPackage("", true, mySrcDir1, myTestSrc1, myResDir, myTestResDir, mySrcDir2, myLibSrcDir, myLibClsDir);
226 checkPackage("", false, mySrcDir1, myTestSrc1, myResDir, myTestResDir, mySrcDir2, myLibClsDir);
228 checkPackage("pack1", true, myPack1Dir);
229 checkPackage("pack1", false, myPack1Dir);
231 checkPackage("pack2", true, myPack2Dir);
232 checkPackage("pack2", false, myPack2Dir);
234 checkPackage(".pack2", false);
235 checkPackage(".pack2", true);
237 VirtualFile libClsPack = createChildDirectory(myLibClsDir, "pack1");
238 VirtualFile libSrcPack = createChildDirectory(myLibSrcDir, "pack1");
240 checkPackage("pack1", true, myPack1Dir, libSrcPack, libClsPack);
241 checkPackage("pack1", false, myPack1Dir, libClsPack);
244 public void testDirectoriesWithPackagePrefix() {
245 PsiTestUtil.addSourceRoot(myModule3, myModule3Dir);
246 WriteCommandAction.runWriteCommandAction(myProject, () -> {
247 final ModifiableRootModel model = ModuleRootManager.getInstance(myModule3).getModifiableModel();
248 model.getContentEntries()[0].getSourceFolders()[0].setPackagePrefix("pack1");
251 checkPackage("pack1", true, myPack1Dir, myModule3Dir);
254 public void testPackageDirectoriesWithDots() {
255 VirtualFile fooBar = createChildDirectory(mySrcDir1, "foo.bar");
256 VirtualFile goo1 = createChildDirectory(fooBar, "goo");
257 VirtualFile foo = createChildDirectory(mySrcDir2, "foo");
258 VirtualFile bar = createChildDirectory(foo, "bar");
259 VirtualFile goo2 = createChildDirectory(bar, "goo");
261 checkPackage("foo", false, foo);
262 checkPackage("foo.bar", false, bar, fooBar);
263 checkPackage("foo.bar.goo", false, goo2, goo1);
266 public void testCreateDir() {
267 String path = mySrcDir1.getPath().replace('/', File.separatorChar);
268 assertTrue(new File(path + File.separatorChar + "dir1" + File.separatorChar + "dir2").mkdirs());
269 assertTrue(new File(path + File.separatorChar + "CVS").mkdirs());
270 VirtualFileManager.getInstance().syncRefresh();
273 public void testDeleteDir() {
274 VirtualFile subdir1 = createChildDirectory(mySrcDir1, "subdir1");
275 VirtualFile subdir2 = createChildDirectory(subdir1, "subdir2");
276 createChildDirectory(subdir2, "subdir3");
278 VfsTestUtil.deleteFile(subdir1);
281 public void testMoveDir() {
282 VirtualFile subdir = createChildDirectory(mySrcDir2, "subdir1");
283 createChildDirectory(subdir, "subdir2");
285 move(subdir, mySrcDir1);
288 public void testRenameDir() {
289 VirtualFile subdir = createChildDirectory(mySrcDir2, "subdir1");
290 createChildDirectory(subdir, "subdir2");
292 rename(subdir, "abc.d");
295 public void testRenameRoot() {
296 rename(myModule1Dir, "newName");
299 public void testMoveRoot() {
300 move(myModule1Dir, myModule3Dir);
303 public void testAddProjectDir() {
304 new WriteCommandAction.Simple(getProject()) {
306 protected void run() throws Throwable {
307 VirtualFile newDir = createChildDirectory(myModule1Dir.getParent(), "newDir");
308 createChildDirectory(newDir, "subdir");
310 PsiTestUtil.addContentRoot(myModule, newDir);
312 }.execute().throwException();
315 public void testChangeIgnoreList() {
316 VirtualFile newDir = createChildDirectory(myModule1Dir, "newDir");
318 assertInProject(newDir);
320 final FileTypeManagerEx fileTypeManager = (FileTypeManagerEx)FileTypeManager.getInstance();
321 final String list = fileTypeManager.getIgnoredFilesList();
322 final String list1 = list + ";" + "newDir";
324 ApplicationManager.getApplication().runWriteAction(() -> fileTypeManager.setIgnoredFilesList(list1));
325 assertNotInProject(newDir);
328 ApplicationManager.getApplication().runWriteAction(() -> fileTypeManager.setIgnoredFilesList(list));
329 assertInProject(newDir);
333 public void testIgnoredFile() {
334 VirtualFile ignoredFile = createChildData(myModule1Dir, "CVS");
335 DirectoryInfo info = myIndex.getInfoForFile(ignoredFile);
336 assertTrue(info.isIgnored());
337 assertTrue(myFileIndex.isExcluded(ignoredFile));
338 assertTrue(myFileIndex.isUnderIgnored(ignoredFile));
339 assertNull(myFileIndex.getContentRootForFile(ignoredFile, false));
340 assertNull(myFileIndex.getModuleForFile(ignoredFile, false));
343 public void testAddModule() {
344 new WriteCommandAction.Simple(getProject()) {
346 protected void run() throws Throwable {
347 VirtualFile newModuleContent = createChildDirectory(myRootVFile, "newModule");
348 createChildDirectory(newModuleContent, "subDir");
349 ModuleManager moduleManager = ModuleManager.getInstance(myProject);
350 Module module = moduleManager.newModule(myRootVFile.getPath() + "/newModule.iml", StdModuleTypes.JAVA.getId());
351 PsiTestUtil.addContentRoot(module, newModuleContent);
353 }.execute().throwException();
356 public void testModuleUnderIgnoredDir() {
357 final VirtualFile ignored = createChildDirectory(myRootVFile, "RCS");
358 assertTrue(FileTypeManager.getInstance().isFileIgnored(ignored));
359 assertTrue(myFileIndex.isExcluded(ignored));
360 assertTrue(myFileIndex.isUnderIgnored(ignored));
361 final VirtualFile module4 = createChildDirectory(ignored, "module4");
362 assertFalse(FileTypeManager.getInstance().isFileIgnored(module4));
363 assertTrue(myFileIndex.isExcluded(module4));
364 assertTrue(myFileIndex.isUnderIgnored(module4));
366 new WriteCommandAction.Simple(getProject()) {
368 protected void run() throws Throwable {
369 ModuleManager moduleManager = ModuleManager.getInstance(myProject);
370 Module module = moduleManager.newModule(myRootVFile.getPath() + "/newModule.iml", StdModuleTypes.JAVA.getId());
371 PsiTestUtil.addContentRoot(module, module4);
372 assertNotInProject(ignored);
373 checkInfo(module4, module, false, false, null, null);
375 }.execute().throwException();
378 public void testModuleInIgnoredDir() {
379 final VirtualFile ignored = createChildDirectory(myRootVFile, "RCS");
380 assertTrue(FileTypeManager.getInstance().isFileIgnored(ignored));
382 new WriteCommandAction.Simple(getProject()) {
384 protected void run() throws Throwable {
385 ModuleManager moduleManager = ModuleManager.getInstance(myProject);
386 ModifiableModuleModel model = moduleManager.getModifiableModel();
387 model.disposeModule(myModule);
388 model.disposeModule(myModule2);
389 model.disposeModule(myModule3);
391 Module module = moduleManager.newModule(myRootVFile.getPath() + "/newModule.iml", StdModuleTypes.JAVA.getId());
392 PsiTestUtil.addContentRoot(module, ignored);
393 checkInfo(ignored, module, false, false, null, null);
395 }.execute().throwException();
398 public void testExcludedDirsInLibraries() {
399 assertFalse(myFileIndex.isInLibraryClasses(myExcludedLibClsDir));
400 assertTrue(myFileIndex.isExcluded(myExcludedLibClsDir));
401 assertFalse(myFileIndex.isUnderIgnored(myExcludedLibClsDir));
402 assertFalse(myFileIndex.isInLibrarySource(myExcludedLibSrcDir));
403 assertTrue(myFileIndex.isExcluded(myExcludedLibSrcDir));
404 assertFalse(myFileIndex.isUnderIgnored(myExcludedLibSrcDir));
407 public void testExplicitExcludeOfInner() {
408 PsiTestUtil.addExcludedRoot(myModule, myModule2Dir);
410 checkInfo(myModule2Dir, myModule2, false, false, null, null);
411 checkInfo(mySrcDir2, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
414 public void testResettingProjectOutputPath() {
415 VirtualFile output1 = createChildDirectory(myModule1Dir, "output1");
416 VirtualFile output2 = createChildDirectory(myModule1Dir, "output2");
418 assertInProject(output1);
419 assertInProject(output2);
421 getCompilerProjectExtension().setCompilerOutputUrl(output1.getUrl());
424 assertExcluded(output1, myModule);
425 assertInProject(output2);
427 getCompilerProjectExtension().setCompilerOutputUrl(output2.getUrl());
430 assertInProject(output1);
431 assertExcluded(output2, myModule);
434 private void fireRootsChanged() {
435 ApplicationManager.getApplication().runWriteAction(() -> ProjectRootManagerEx.getInstanceEx(getProject()).makeRootsChange(EmptyRunnable.getInstance(), false, true));
438 private static OrderEntry[] toArray(Collection<OrderEntry> orderEntries) {
439 return orderEntries.toArray(new OrderEntry[orderEntries.size()]);
442 public void testModuleSourceAsLibrarySource() {
443 ModuleRootModificationUtil.addModuleLibrary(myModule, "someLib", Collections.emptyList(), Collections.singletonList(mySrcDir1.getUrl()));
445 checkInfo(mySrcDir1, myModule, false, true, "", JavaSourceRootType.SOURCE, myModule, myModule);
446 Collection<OrderEntry> entriesResult = myIndex.getOrderEntries(myIndex.getInfoForFile(mySrcDir1));
447 OrderEntry[] entries = toArray(entriesResult);
449 assertInstanceOf(entries[0], LibraryOrderEntry.class);
450 assertInstanceOf(entries[1], ModuleSourceOrderEntry.class);
452 checkInfo(myTestSrc1, myModule, false, true, "testSrc", JavaSourceRootType.TEST_SOURCE, myModule, myModule);
453 entriesResult = myIndex.getOrderEntries(myIndex.getInfoForFile(myTestSrc1));
454 entries = toArray(entriesResult);
455 assertInstanceOf(entries[0], LibraryOrderEntry.class);
456 assertInstanceOf(entries[1], ModuleSourceOrderEntry.class);
459 public void testModuleSourceAsLibraryClasses() {
460 ModuleRootModificationUtil.addModuleLibrary(myModule, "someLib", Collections.singletonList(mySrcDir1.getUrl()), Collections.emptyList());
461 checkInfo(mySrcDir1, myModule, true, false, "", JavaSourceRootType.SOURCE, myModule);
462 assertInstanceOf(assertOneElement(toArray(myIndex.getOrderEntries(assertInProject(mySrcDir1)))), ModuleSourceOrderEntry.class);
465 public void testModulesWithSameSourceContentRoot() {
466 // now our API allows this (ReformatCodeActionTest), although UI doesn't. Maybe API shouldn't allow it as well?
467 PsiTestUtil.addContentRoot(myModule2, myModule1Dir);
468 PsiTestUtil.addSourceRoot(myModule2, mySrcDir1);
470 checkInfo(myModule1Dir, myModule, false, false, null, null);
471 checkInfo(mySrcDir1, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule3, myModule);
472 checkInfo(myTestSrc1, myModule, false, false, "", JavaSourceRootType.TEST_SOURCE, myModule3, myModule);
473 checkInfo(myResDir, myModule, false, false, "", JavaResourceRootType.RESOURCE, myModule);
475 checkInfo(mySrcDir2, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
476 assertEquals(myModule2Dir, myIndex.getInfoForFile(mySrcDir2).getContentRoot());
479 public void testModuleWithSameSourceRoot() {
480 PsiTestUtil.addSourceRoot(myModule2, mySrcDir1);
481 checkInfo(mySrcDir1, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
482 checkInfo(myTestSrc1, myModule2, false, false, "testSrc", JavaSourceRootType.SOURCE, myModule2, myModule3);
485 public void testModuleContentUnderSourceRoot() {
486 PsiTestUtil.addContentRoot(myModule2, myPack1Dir);
487 checkInfo(myPack1Dir, myModule2, false, false, null, null);
490 public void testSameSourceAndOutput() {
491 PsiTestUtil.setCompilerOutputPath(myModule, mySrcDir1.getUrl(), false);
492 assertExcluded(mySrcDir1, myModule);
495 public void testExcludedDirShouldBeExcludedRightAfterItsCreation() {
496 VirtualFile excluded = createChildDirectory(myModule1Dir, "excluded");
497 VirtualFile projectOutput = createChildDirectory(myModule1Dir, "projectOutput");
498 VirtualFile module2Output = createChildDirectory(myModule1Dir, "module2Output");
499 VirtualFile module2TestOutput = createChildDirectory(myModule2Dir, "module2TestOutput");
501 assertInProject(excluded);
502 assertInProject(projectOutput);
503 assertInProject(module2Output);
504 assertInProject(module2TestOutput);
506 getCompilerProjectExtension().setCompilerOutputUrl(projectOutput.getUrl());
508 PsiTestUtil.addExcludedRoot(myModule, excluded);
509 PsiTestUtil.setCompilerOutputPath(myModule2, module2Output.getUrl(), false);
510 PsiTestUtil.setCompilerOutputPath(myModule2, module2TestOutput.getUrl(), true);
511 PsiTestUtil.setExcludeCompileOutput(myModule2, true);
513 assertExcluded(excluded, myModule);
514 assertExcluded(projectOutput, myModule);
515 assertExcluded(module2Output, myModule);
516 assertExcluded(module2TestOutput, myModule2);
518 VfsTestUtil.deleteFile(excluded);
519 VfsTestUtil.deleteFile(projectOutput);
520 VfsTestUtil.deleteFile(module2Output);
521 VfsTestUtil.deleteFile(module2TestOutput);
523 final List<VirtualFile> created = new ArrayList<VirtualFile>();
524 VirtualFileListener l = new VirtualFileAdapter() {
526 public void fileCreated(@NotNull VirtualFileEvent e) {
527 VirtualFile file = e.getFile();
528 String fileName = e.getFileName();
529 assertExcluded(file, fileName.contains("module2TestOutput") ? myModule2 : myModule);
533 VirtualFileManager.getInstance().addVirtualFileListener(l, getTestRootDisposable());
535 excluded = createChildDirectory(myModule1Dir, excluded.getName());
536 assertExcluded(excluded, myModule);
538 projectOutput = createChildDirectory(myModule1Dir, projectOutput.getName());
539 assertExcluded(projectOutput, myModule);
541 module2Output = createChildDirectory(myModule1Dir, module2Output.getName());
542 assertExcluded(module2Output, myModule);
544 module2TestOutput = createChildDirectory(myModule2Dir, module2TestOutput.getName());
545 assertExcluded(module2TestOutput, myModule2);
547 assertEquals(created.toString(), 4, created.size());
550 public void testExcludesShouldBeRecognizedRightOnRefresh() {
551 final VirtualFile dir = createChildDirectory(myModule1Dir, "dir");
552 final VirtualFile excluded = createChildDirectory(dir, "excluded");
553 PsiTestUtil.addExcludedRoot(myModule, excluded);
554 VfsTestUtil.deleteFile(dir);
557 boolean created = new File(myModule1Dir.getPath(), "dir/excluded/foo").mkdirs();
560 VirtualFileListener l = new VirtualFileAdapter() {
562 public void fileCreated(@NotNull VirtualFileEvent e) {
563 assertEquals("dir", e.getFileName());
565 VirtualFile file = e.getFile();
566 assertInProject(file);
567 assertExcluded(file.findFileByRelativePath("excluded"), myModule);
568 assertExcluded(file.findFileByRelativePath("excluded/foo"), myModule);
572 VirtualFileManager.getInstance().addVirtualFileListener(l, getTestRootDisposable());
573 VirtualFileManager.getInstance().syncRefresh();
576 public void testProcessingNestedContentRootsOfExcludedDirsOnCreation() {
577 String rootPath = myModule1Dir.getPath();
578 final File f = new File(rootPath, "excludedDir/dir/anotherContentRoot");
579 ApplicationManager.getApplication().runWriteAction(() -> {
580 ModifiableRootModel rootModel = ModuleRootManager.getInstance(myModule).getModifiableModel();
581 rootModel.getContentEntries()[0]
582 .addExcludeFolder(VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(f.getParentFile().getParent())));
585 ModuleRootModificationUtil.addContentRoot(myModule2, FileUtil.toSystemIndependentName(f.getPath()));
587 assertTrue(f.getPath(), f.exists() || f.mkdirs());
588 LocalFileSystem.getInstance().refresh(false);
591 assertExcluded(LocalFileSystem.getInstance().findFileByIoFile(f.getParentFile().getParentFile()), myModule);
592 assertInProject(LocalFileSystem.getInstance().findFileByIoFile(f));
595 public void testLibraryDirInContent() {
596 ModuleRootModificationUtil.addModuleLibrary(myModule, myModule1Dir.getUrl());
598 checkInfo(myModule1Dir, myModule, true, false, "", null, myModule);
599 checkInfo(mySrcDir1, myModule, true, false, "", JavaSourceRootType.SOURCE, myModule);
601 checkInfo(myModule2Dir, myModule2, true, false, "module2", null, myModule);
602 checkInfo(mySrcDir2, myModule2, true, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
603 checkInfo(myExcludeDir, null, true, false, "module2.src2.excluded", null, myModule3);
605 checkInfo(myLibDir, myModule, true, false, "lib", null, myModule);
606 checkInfo(myLibClsDir, myModule, true, false, "", null, myModule2, myModule3);
608 //myModule is included into order entries instead of myModule2 because classes root for libraries dominates on source roots
609 checkInfo(myLibSrcDir, myModule, true, true, "", null, myModule, myModule3);
610 checkInfo(myLibAdditionalSrcDir, myModule, true, true, null, null, myModule);
612 checkInfo(myResDir, myModule, true, false, "", JavaResourceRootType.RESOURCE, myModule);
613 assertInstanceOf(assertOneElement(toArray(myIndex.getOrderEntries(assertInProject(myResDir)))), ModuleSourceOrderEntry.class);
615 checkInfo(myExcludedLibSrcDir, null, true, false, "lib.src.exc", null, myModule3, myModule);
616 checkInfo(myExcludedLibClsDir, null, true, false, "lib.cls.exc", null, myModule3);
618 checkPackage("lib.src.exc", true, myExcludedLibSrcDir);
619 checkPackage("lib.cls.exc", true, myExcludedLibClsDir);
621 checkPackage("lib.src", true);
622 checkPackage("lib.cls", true);
624 checkPackage("exc", false);
625 checkPackage("exc", true);
628 public void testExcludeCompilerOutputOutsideOfContentRoot() {
629 assertTrue(myFileIndex.isExcluded(myOutputDir));
630 assertFalse(myFileIndex.isUnderIgnored(myOutputDir));
631 assertTrue(myFileIndex.isExcluded(myModule1OutputDir));
632 assertFalse(myFileIndex.isExcluded(myOutputDir.getParent()));
633 assertExcludedFromProject(myOutputDir);
634 assertExcludedFromProject(myModule1OutputDir);
635 String moduleOutputUrl = myModule1OutputDir.getUrl();
637 VfsTestUtil.deleteFile(myOutputDir);
639 PsiTestUtil.setCompilerOutputPath(myModule, moduleOutputUrl, false);
640 myOutputDir = createChildDirectory(myRootVFile, "out");
641 myModule1OutputDir = createChildDirectory(myOutputDir, "module1");
643 assertExcludedFromProject(myOutputDir);
644 assertExcludedFromProject(myModule1OutputDir);
645 assertTrue(myFileIndex.isExcluded(myModule1OutputDir));
647 PsiTestUtil.setCompilerOutputPath(myModule, moduleOutputUrl, true);
648 PsiTestUtil.setCompilerOutputPath(myModule2, moduleOutputUrl, false);
649 PsiTestUtil.setCompilerOutputPath(myModule2, moduleOutputUrl, true);
650 PsiTestUtil.setCompilerOutputPath(myModule3, moduleOutputUrl, false);
651 PsiTestUtil.setCompilerOutputPath(myModule3, moduleOutputUrl, true);
653 // now no module inherits project output dir, but it still should be project-excluded
654 assertExcludedFromProject(myOutputDir);
656 // project output inside module content shouldn't be projectExcludeRoot
657 VirtualFile projectOutputUnderContent = createChildDirectory(myModule1Dir, "projectOutputUnderContent");
658 getCompilerProjectExtension().setCompilerOutputUrl(projectOutputUnderContent.getUrl());
661 assertNotExcluded(myOutputDir);
662 assertExcluded(projectOutputUnderContent, myModule);
664 VfsTestUtil.deleteFile(projectOutputUnderContent);
665 projectOutputUnderContent = createChildDirectory(myModule1Dir, "projectOutputUnderContent");
666 assertNotExcluded(myOutputDir);
667 assertExcluded(projectOutputUnderContent, myModule);
670 public void testFileContentAndSourceRoots() {
671 VirtualFile fileRoot = createChildData(myRootVFile, "fileRoot.txt");
672 VirtualFile fileSourceRoot = createChildData(myRootVFile, "fileSourceRoot.txt");
673 VirtualFile fileTestSourceRoot = createChildData(myRootVFile, "fileTestSourceRoot.txt");
675 assertNotInProject(fileRoot);
676 assertFalse(myFileIndex.isInContent(fileRoot));
677 assertIteratedContent(myFileIndex, null, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot));
679 ContentEntry contentEntry = PsiTestUtil.addContentRoot(myModule, fileRoot);
680 assertNotNull(contentEntry);
681 assertEquals(fileRoot, contentEntry.getFile());
682 checkInfo(fileRoot, myModule, false, false, "", null);
683 assertTrue(myFileIndex.isInContent(fileRoot));
684 assertFalse(myFileIndex.isInSource(fileRoot));
686 PsiTestUtil.addContentRoot(myModule, fileSourceRoot);
687 PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
688 checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
689 assertTrue(myFileIndex.isInContent(fileSourceRoot));
690 assertTrue(myFileIndex.isInSource(fileSourceRoot));
692 PsiTestUtil.addContentRoot(myModule, fileTestSourceRoot);
693 PsiTestUtil.addSourceRoot(myModule, fileTestSourceRoot, true);
694 checkInfo(fileTestSourceRoot, myModule, false, false, "", JavaSourceRootType.TEST_SOURCE, myModule);
695 assertTrue(myFileIndex.isInContent(fileTestSourceRoot));
696 assertTrue(myFileIndex.isInSource(fileTestSourceRoot));
698 assertIteratedContent(myFileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
700 // removing file source root
701 PsiTestUtil.removeSourceRoot(myModule, fileTestSourceRoot);
702 checkInfo(fileTestSourceRoot, myModule, false, false, "", null);
703 assertTrue(myFileIndex.isInContent(fileTestSourceRoot));
704 assertFalse(myFileIndex.isInSource(fileTestSourceRoot));
705 assertIteratedContent(myFileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
707 // removing file content root
708 PsiTestUtil.removeContentEntry(myModule, contentEntry.getFile());
709 assertNotInProject(fileRoot);
710 assertFalse(myFileIndex.isInContent(fileRoot));
711 assertFalse(myFileIndex.isInSource(fileRoot));
712 assertIteratedContent(myFileIndex, Arrays.asList(fileSourceRoot, fileTestSourceRoot), Collections.singletonList(fileRoot));
715 private static void assertIteratedContent(ProjectFileIndex fileIndex,
716 @Nullable List<VirtualFile> contains,
717 @Nullable List<VirtualFile> doesntContain) {
718 final Set<VirtualFile> collected = new THashSet<VirtualFile>();
719 fileIndex.iterateContent(new ContentIterator() {
721 public boolean processFile(VirtualFile fileOrDir) {
722 collected.add(fileOrDir);
726 if (contains != null) assertContainsElements(collected, contains);
727 if (doesntContain != null) assertDoesntContain(collected, doesntContain);
730 public void testFileSourceRootsUnderDirContentRoot() {
731 VirtualFile fileSourceRoot = createChildData(myModule1Dir, "fileSourceRoot.txt");
732 assertTrue(myFileIndex.isInContent(fileSourceRoot));
733 assertFalse(myFileIndex.isInSource(fileSourceRoot));
735 PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
736 assertTrue(myFileIndex.isInContent(fileSourceRoot));
737 assertTrue(myFileIndex.isInSource(fileSourceRoot));
738 checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
740 // removing file source root
741 PsiTestUtil.removeSourceRoot(myModule, fileSourceRoot);
742 assertTrue(myFileIndex.isInContent(fileSourceRoot));
743 assertFalse(myFileIndex.isInSource(fileSourceRoot));
746 public void testFileModuleExcludeRootUnderDirectoryRoot() {
747 VirtualFile fileExcludeRoot = createChildData(mySrcDir1, "fileExcludeRoot.txt");
748 assertTrue(myFileIndex.isInContent(fileExcludeRoot));
749 assertTrue(myFileIndex.isInSource(fileExcludeRoot));
750 assertIteratedContent(myFileIndex, Collections.singletonList(fileExcludeRoot), null);
752 PsiTestUtil.addExcludedRoot(myModule, fileExcludeRoot);
753 assertFalse(myFileIndex.isInContent(fileExcludeRoot));
754 assertFalse(myFileIndex.isInSource(fileExcludeRoot));
755 assertNull(myFileIndex.getContentRootForFile(fileExcludeRoot));
756 assertEquals(myModule1Dir, myFileIndex.getContentRootForFile(fileExcludeRoot, false));
757 assertNull(myFileIndex.getModuleForFile(fileExcludeRoot));
758 assertEquals(myModule, myFileIndex.getModuleForFile(fileExcludeRoot, false));
759 assertExcluded(fileExcludeRoot, myModule);
760 assertIteratedContent(myFileIndex, null, Collections.singletonList(fileExcludeRoot));
762 // removing file exclude root
763 PsiTestUtil.removeExcludedRoot(myModule, fileExcludeRoot);
764 assertTrue(myFileIndex.isInContent(fileExcludeRoot));
765 assertTrue(myFileIndex.isInSource(fileExcludeRoot));
766 assertIteratedContent(myFileIndex, Collections.singletonList(fileExcludeRoot), null);
769 public void testFileModuleExcludeRootUnderFileRoot() {
770 VirtualFile fileRoot = createChildData(myRootVFile, "fileRoot.txt");
771 PsiTestUtil.addContentRoot(myModule, fileRoot);
772 checkInfo(fileRoot, myModule, false, false, "", null);
773 assertTrue(myFileIndex.isInContent(fileRoot));
774 assertIteratedContent(myFileIndex, Collections.singletonList(fileRoot), null);
776 PsiTestUtil.addExcludedRoot(myModule, fileRoot);
777 assertFalse(myFileIndex.isInContent(fileRoot));
778 assertExcluded(fileRoot, myModule);
779 assertIteratedContent(myFileIndex, null, Collections.singletonList(fileRoot));
781 // removing file exclude root
782 PsiTestUtil.removeExcludedRoot(myModule, fileRoot);
783 checkInfo(fileRoot, myModule, false, false, "", null);
784 assertTrue(myFileIndex.isInContent(fileRoot));
785 assertIteratedContent(myFileIndex, Collections.singletonList(fileRoot), null);
788 public void testFileLibraryInsideFolderLibrary() {
789 VirtualFile file = createChildData(myLibSrcDir, "empty.txt");
790 ModuleRootModificationUtil.addModuleLibrary(myModule2, "lib2",
791 Collections.emptyList(), Collections.singletonList(file.getUrl()),
792 Collections.emptyList(), DependencyScope.COMPILE, true);
794 // same for the dir and for the file
795 checkInfo(file, myModule, false, true, "", null, myModule2, myModule3);
796 checkInfo(myLibSrcDir, myModule, false, true, "", null, myModule2, myModule3);
799 public void testFileContentRootsModifications() {
800 assertNotInProject(myRootVFile);
801 VirtualFile temp = createChildDirectory(myRootVFile, "temp");
803 VirtualFile fileSourceRoot = createChildData(myRootVFile, "fileSourceRoot.txt");
804 assertNotInProject(fileSourceRoot);
806 PsiTestUtil.addContentRoot(myModule, fileSourceRoot);
807 PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
808 checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
809 assertTrue(myFileIndex.isInContent(fileSourceRoot));
810 assertTrue(myFileIndex.isInSource(fileSourceRoot));
812 // delete and recreate
813 VfsTestUtil.deleteFile(fileSourceRoot);
814 assertNotInProject(fileSourceRoot);
815 assertFalse(myFileIndex.isInContent(fileSourceRoot));
816 assertFalse(myFileIndex.isInSource(fileSourceRoot));
817 fileSourceRoot = createChildData(myRootVFile, "fileSourceRoot.txt");
818 checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
819 assertTrue(myFileIndex.isInContent(fileSourceRoot));
820 assertTrue(myFileIndex.isInSource(fileSourceRoot));
822 // delete and move from another dir
823 VfsTestUtil.deleteFile(fileSourceRoot);
824 assertNotInProject(fileSourceRoot);
825 assertFalse(myFileIndex.isInContent(fileSourceRoot));
826 assertFalse(myFileIndex.isInSource(fileSourceRoot));
827 fileSourceRoot = createChildData(temp, "fileSourceRoot.txt");
828 assertNotInProject(fileSourceRoot);
829 move(fileSourceRoot, myRootVFile);
830 checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
831 assertTrue(myFileIndex.isInContent(fileSourceRoot));
832 assertTrue(myFileIndex.isInSource(fileSourceRoot));
834 // delete and copy from another dir
835 VfsTestUtil.deleteFile(fileSourceRoot);
836 assertNotInProject(fileSourceRoot);
837 assertFalse(myFileIndex.isInContent(fileSourceRoot));
838 assertFalse(myFileIndex.isInSource(fileSourceRoot));
839 fileSourceRoot = createChildData(temp, "fileSourceRoot.txt");
840 assertNotInProject(fileSourceRoot);
841 fileSourceRoot = copy(fileSourceRoot, myRootVFile, "fileSourceRoot.txt");
842 checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
843 assertTrue(myFileIndex.isInContent(fileSourceRoot));
844 assertTrue(myFileIndex.isInSource(fileSourceRoot));
846 // delete and rename from another file
847 VfsTestUtil.deleteFile(fileSourceRoot);
848 assertNotInProject(fileSourceRoot);
849 assertFalse(myFileIndex.isInContent(fileSourceRoot));
850 assertFalse(myFileIndex.isInSource(fileSourceRoot));
851 fileSourceRoot = createChildData(myRootVFile, "temp_file.txt");
852 assertNotInProject(fileSourceRoot);
853 rename(fileSourceRoot, "fileSourceRoot.txt");
854 checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
855 assertTrue(myFileIndex.isInContent(fileSourceRoot));
856 assertTrue(myFileIndex.isInSource(fileSourceRoot));
859 private void checkInfo(VirtualFile file,
860 @Nullable Module module,
862 boolean isInLibrarySource,
863 @Nullable String packageName,
864 @Nullable final JpsModuleSourceRootType<?> moduleSourceRootType,
865 Module... modulesOfOrderEntries) {
866 DirectoryInfo info = assertInProject(file);
867 assertEquals(module, info.getModule());
868 if (moduleSourceRootType != null) {
869 assertTrue("isInModuleSource", info.isInModuleSource());
870 assertEquals(moduleSourceRootType, myIndex.getSourceRootType(info));
873 assertFalse("isInModuleSource", info.isInModuleSource());
875 assertEquals(isInLibrary, info.hasLibraryClassRoot());
876 assertEquals(isInLibrarySource, info.isInLibrarySource());
878 if (file.isDirectory()) {
879 assertEquals(packageName, myFileIndex.getPackageNameByDirectory(file));
882 assertEquals(Arrays.toString(toArray(myIndex.getOrderEntries(info))), modulesOfOrderEntries.length, toArray(myIndex.getOrderEntries(info)).length);
883 for (Module aModule : modulesOfOrderEntries) {
884 OrderEntry found = ModuleFileIndexImpl.findOrderEntryWithOwnerModule(aModule, myIndex.getOrderEntries(info));
885 assertNotNull("not found: " + aModule + " in " + Arrays.toString(toArray(myIndex.getOrderEntries(info))), found);
889 private void assertNotInProject(VirtualFile file) {
890 DirectoryInfo info = myIndex.getInfoForFile(file);
891 assertFalse(info.toString(), info.isInProject());
892 assertFalse(info.toString(), info.isExcluded());
895 private void assertExcluded(VirtualFile file, Module module) {
896 DirectoryInfo info = myIndex.getInfoForFile(file);
897 assertTrue(info.toString(), info.isExcluded());
898 assertEquals(module, info.getModule());
901 private DirectoryInfo assertInProject(VirtualFile file) {
902 DirectoryInfo info = myIndex.getInfoForFile(file);
903 assertTrue(file.toString(), info.isInProject());
904 myIndex.assertConsistency(info);
908 private void assertNotExcluded(VirtualFile file) {
909 assertFalse(myIndex.getInfoForFile(file).isExcluded());
912 private void assertExcludedFromProject(VirtualFile file) {
913 assertExcluded(file, null);
916 private void checkPackage(String packageName, boolean includeLibrarySources, VirtualFile... expectedDirs) {
917 VirtualFile[] actualDirs = myIndex.getDirectoriesByPackageName(packageName, includeLibrarySources).toArray(VirtualFile.EMPTY_ARRAY);
918 assertNotNull(actualDirs);
919 assertOrderedEquals(actualDirs, expectedDirs);
921 for (VirtualFile dir : expectedDirs) {
922 String actualName = myIndex.getPackageName(dir);
923 assertEquals("Invalid package name for dir " + dir + ": " + packageName, packageName, actualName);