diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java index 33b32ac457cb..a35b87bad093 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java @@ -15,6 +15,8 @@ */ package com.intellij.openapi.vfs; +import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.roots.ContentIterator; import com.intellij.openapi.util.io.BufferExposingByteArrayInputStream; import com.intellij.openapi.util.io.FileUtil; @@ -26,6 +28,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.*; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -184,9 +187,8 @@ public class VfsUtilCore { return result.skipToParent != root; } + @SuppressWarnings("UnsafeVfsRecursion") public static VirtualFileVisitor.Result visitChildrenRecursively(@NotNull VirtualFile file, @NotNull VirtualFileVisitor visitor) { - if (!file.isValid()) return VirtualFileVisitor.CONTINUE; - visitor.pushFrame(); try { final boolean visited = visitor.allowVisitFile(file); @@ -195,22 +197,26 @@ public class VfsUtilCore { if (result.skipChildren) return result; } - if (!visitor.allowVisitChildren(file)) return VirtualFileVisitor.CONTINUE; + Iterable childrenIterable = null; - if (!visitor.depthLimitReached()) { - final Iterable iterable = visitor.getChildrenIterable(file); - if (iterable != null) { - for (VirtualFile child : iterable) { - VirtualFileVisitor.Result result = visitChildrenRecursively(child, visitor); - if (result.skipToParent != null && result.skipToParent != child) return result; + final AccessToken token = ApplicationManager.getApplication().acquireReadActionLock(); + try { + if (!file.isValid() || !visitor.allowVisitChildren(file)) return VirtualFileVisitor.CONTINUE; + if (!visitor.depthLimitReached()) { + childrenIterable = visitor.getChildrenIterable(file); + if (childrenIterable == null) { + childrenIterable = Arrays.asList(file.getChildren()); } } - else { - @SuppressWarnings("UnsafeVfsRecursion") VirtualFile[] children = file.getChildren(); - for (VirtualFile child : children) { - VirtualFileVisitor.Result result = visitChildrenRecursively(child, visitor); - if (result.skipToParent != null && result.skipToParent != child) return result; - } + } + finally { + token.finish(); + } + + if (childrenIterable != null) { + for (VirtualFile child : childrenIterable) { + VirtualFileVisitor.Result result = visitChildrenRecursively(child, visitor); + if (result.skipToParent != null && result.skipToParent != child) return result; } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFileVisitorTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFileVisitorTest.java index 1eb1a1e68d23..31228382a5a6 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFileVisitorTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VirtualFileVisitorTest.java @@ -19,6 +19,7 @@ import com.intellij.mock.MockVirtualFile; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.testFramework.PlatformUltraLiteTestFixture; import com.intellij.util.Function; import com.intellij.util.NullableFunction; import org.jetbrains.annotations.NotNull; @@ -32,10 +33,13 @@ import java.util.Collections; import static org.junit.Assert.assertEquals; public class VirtualFileVisitorTest { + private static PlatformUltraLiteTestFixture myFixture; private static VirtualFile myRoot; @BeforeClass public static void setUp() throws Exception { + myFixture = PlatformUltraLiteTestFixture.getFixture(); + myFixture.setUp(); myRoot = dir("/", dir("d1", @@ -54,6 +58,7 @@ public class VirtualFileVisitorTest { @AfterClass public static void tearDown() throws Exception { myRoot = null; + myFixture.tearDown(); } @Test diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformUltraLiteTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/PlatformUltraLiteTestFixture.java new file mode 100644 index 000000000000..5b01cf414149 --- /dev/null +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformUltraLiteTestFixture.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2012 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.testFramework; + +import com.intellij.mock.MockApplication; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; + +public class PlatformUltraLiteTestFixture { + @NotNull + public static PlatformUltraLiteTestFixture getFixture() { + return new PlatformUltraLiteTestFixture(); + } + + private Disposable myAppDisposable = null; + + private PlatformUltraLiteTestFixture() { } + + public void setUp() { + final Application application = ApplicationManager.getApplication(); + if (application == null) { + myAppDisposable = Disposer.newDisposable(); + ApplicationManager.setApplication(new MockApplication(myAppDisposable), myAppDisposable); + } + } + + public void tearDown() { + if (myAppDisposable != null) { + Disposer.dispose(myAppDisposable); + } + } +}