From c6b1ec8ef3578c3eb4eec6893e06d27b76e99b3c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 18 Sep 2017 13:33:13 +0300 Subject: [PATCH] dispose leaking virtual file pointers in tests --- .../projectRoots/impl/JavaSdkImpl.java | 188 +------------- .../daemon/JavadocHtmlLintInspectionTest.kt | 6 + .../intellij/compiler/CompilerTestUtil.java | 2 +- .../openapi/projectRoots/impl/MockSdk.java | 231 ++++++++++++++++++ .../fxml/JavaFxSdkSetupNotificationTest.java | 3 +- .../com/jetbrains/python/PyIndexingTest.java | 3 + .../com/jetbrains/python/PythonMockSdk.java | 35 +-- 7 files changed, 257 insertions(+), 211 deletions(-) create mode 100644 platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/MockSdk.java diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index 13330c14052e..5a2afe6db2da 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -16,28 +16,20 @@ package com.intellij.openapi.projectRoots.impl; import com.intellij.icons.AllIcons; -import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.FileTypes; -import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; -import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.*; import com.intellij.openapi.roots.*; -import com.intellij.openapi.roots.ex.ProjectRootManagerEx; -import com.intellij.openapi.util.EmptyRunnable; -import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.jrt.JrtFileSystem; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; @@ -410,7 +402,7 @@ public class JavaSdkImpl extends JavaSdk { addClasses(jdkHomeFile, sdkModificator, isJre); addSources(jdkHomeFile, sdkModificator); - return new MockSdk(jdkName, homePath, jdkName, roots, isJre); + return new MockSdk(jdkName, homePath, jdkName, roots, this); } private static void addClasses(@NotNull File file, @NotNull SdkModificator sdkModificator, boolean isJre) { @@ -544,182 +536,4 @@ public class JavaSdkImpl extends JavaSdk { type == JavadocOrderRootType.getInstance() || type == AnnotationOrderRootType.getInstance(); } - - private class MockSdk implements Sdk, SdkModificator { - private String myJdkName; - private String myHomePath; - @NotNull private String myVersionString; - private final MultiMap myRoots; - private final boolean myIsJre; - - MockSdk(@NotNull String jdkName, - @NotNull String homePath, - @NotNull String versionString, - @NotNull MultiMap roots, - boolean isJre) { - myJdkName = jdkName; - myHomePath = homePath; - myVersionString = versionString; - myRoots = roots; - myIsJre = isJre; - } - - @NotNull - @Override - public SdkTypeId getSdkType() { - return JavaSdkImpl.this; - } - - @NotNull - @Override - public String getName() { - return myJdkName; - } - - @NotNull - @Override - public String getVersionString() { - return myVersionString; - } - - @Override - public String getHomePath() { - return myHomePath; - } - - @Nullable - @Override - public VirtualFile getHomeDirectory() { - return LocalFileSystem.getInstance().findFileByPath(myHomePath); - } - - @Nullable - @Override - public SdkAdditionalData getSdkAdditionalData() { - return null; - } - - @NotNull - @Override - public Sdk clone() { - return new MockSdk(myJdkName, myHomePath, myVersionString, new MultiMap<>(myRoots), myIsJre){ - @NotNull - @Override - public SdkModificator getSdkModificator() { - return this; - } - }; - } - - @NotNull - @Override - public SdkModificator getSdkModificator() { - throwReadOnly(); - return null; - } - - @NotNull - public VirtualFile[] getRoots(@NotNull OrderRootType rootType) { - return myRoots.get(rootType).toArray(VirtualFile.EMPTY_ARRAY); - } - - @Override - public void setName(String name) { - myJdkName = name; - } - - @Override - public void setHomePath(String path) { - myHomePath = path; - } - - @Override - public void setVersionString(@NotNull String versionString) { - myVersionString = versionString; - } - - @Override - public void setSdkAdditionalData(SdkAdditionalData data) { - throwReadOnly(); - } - - @Override - public void addRoot(@NotNull VirtualFile root, @NotNull OrderRootType rootType) { - myRoots.putValue(rootType, root); - } - - @Override - public void removeRoot(@NotNull VirtualFile root, @NotNull OrderRootType rootType) { - myRoots.remove(rootType, root); - } - - @Override - public void removeRoots(@NotNull OrderRootType rootType) { - myRoots.remove(rootType); - } - - @Override - public void removeAllRoots() { - myRoots.clear(); - } - - @Override - public void commitChanges() { - for (Project project : ProjectManager.getInstance().getOpenProjects()) { - WriteAction.run(() -> ((ProjectRootManagerEx)ProjectRootManager.getInstance(project)).makeRootsChange(EmptyRunnable.getInstance(), false, true)); - } - } - - @Override - public boolean isWritable() { - return true; - } - - @NotNull - @Override - public RootProvider getRootProvider() { - return new RootProvider() { - @NotNull - @Override - public String[] getUrls(@NotNull OrderRootType rootType) { - return ContainerUtil.map2Array(getFiles(rootType), String.class, VirtualFile::getUrl); - } - - @NotNull - @Override - public VirtualFile[] getFiles(@NotNull OrderRootType rootType) { - return getRoots(rootType); - } - - @Override - public void addRootSetChangedListener(@NotNull RootSetChangedListener listener) { } - - @Override - public void addRootSetChangedListener(@NotNull RootSetChangedListener listener, @NotNull Disposable parentDisposable) { } - - @Override - public void removeRootSetChangedListener(@NotNull RootSetChangedListener listener) { } - }; - } - - private void throwReadOnly() { - throw new IncorrectOperationException("Can't modify, MockJDK is read-only, consider calling .clone() first"); - } - - @Nullable - @Override - public T getUserData(@NotNull Key key) { - return null; - } - - @Override - public void putUserData(@NotNull Key key, @Nullable T value) { - throwReadOnly(); - } - - @Override - public String toString() { - return "MockSDK[" + myJdkName + "]"; - } - } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/JavadocHtmlLintInspectionTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/JavadocHtmlLintInspectionTest.kt index 8da63e0eedef..d02e4087647e 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/JavadocHtmlLintInspectionTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/JavadocHtmlLintInspectionTest.kt @@ -16,6 +16,9 @@ package com.intellij.java.codeInsight.daemon import com.intellij.codeInspection.javaDoc.JavadocHtmlLintInspection +import com.intellij.openapi.projectRoots.JavaSdk +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl +import com.intellij.openapi.roots.ModuleRootModificationUtil import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import com.intellij.util.PathUtil @@ -27,6 +30,9 @@ class JavadocHtmlLintInspectionTest : LightCodeInsightFixtureTestCase() { val javaHome = System.getProperty("java.home") val jdkHome = if (javaHome.endsWith("jre")) PathUtil.getParentPath(javaHome) else javaHome VfsRootAccess.allowRootAccess(myFixture.testRootDisposable, jdkHome) + + val jdk = (JavaSdk.getInstance() as JavaSdkImpl).createMockJdk("java version \"1.8.0\"", System.getProperty("java.home"), true) + ModuleRootModificationUtil.setModuleSdk(myModule, jdk); } fun testNoComment() = doTest("class C { }") diff --git a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java index a14473ef16cc..097467d2fc02 100644 --- a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java +++ b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java @@ -94,10 +94,10 @@ public class CompilerTestUtil { modulesToRestore.add(module); } } - table.removeJdk(internalJdk); for (Module module : modulesToRestore) { ModuleRootModificationUtil.setModuleSdk(module, internalJdk); } + table.removeJdk(internalJdk); BuildManager.getInstance().clearState(project); }); }); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/MockSdk.java b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/MockSdk.java new file mode 100644 index 000000000000..79f620afe286 --- /dev/null +++ b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/MockSdk.java @@ -0,0 +1,231 @@ +/* + * Copyright 2000-2017 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.projectRoots.impl; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.SdkAdditionalData; +import com.intellij.openapi.projectRoots.SdkModificator; +import com.intellij.openapi.projectRoots.SdkTypeId; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.RootProvider; +import com.intellij.openapi.roots.ex.ProjectRootManagerEx; +import com.intellij.openapi.util.EmptyRunnable; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolder; +import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.openapi.vfs.StandardFileSystems; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class MockSdk implements Sdk, SdkModificator { + private String myName; + private String myHomePath; + @NotNull private String myVersionString; + private final MultiMap myRoots; + private final SdkTypeId mySdkType; + + public MockSdk(@NotNull String name, + @NotNull String homePath, + @NotNull String versionString, + @NotNull MultiMap roots, + @NotNull SdkTypeId sdkType) { + myName = name; + myHomePath = homePath; + myVersionString = versionString; + myRoots = roots; + mySdkType = sdkType; + } + + @NotNull + @Override + public SdkTypeId getSdkType() { + return mySdkType; + } + + @NotNull + @Override + public String getName() { + return myName; + } + + @NotNull + @Override + public String getVersionString() { + return myVersionString; + } + + @Override + public String getHomePath() { + return myHomePath; + } + + @Nullable + @Override + public VirtualFile getHomeDirectory() { + return StandardFileSystems.local().findFileByPath(myHomePath); + } + + @Nullable + @Override + public SdkAdditionalData getSdkAdditionalData() { + return null; + } + + @NotNull + @Override + public Sdk clone() { + return new MockSdk(myName, myHomePath, myVersionString, new MultiMap<>(myRoots), mySdkType) { + private final UserDataHolder udh = new UserDataHolderBase(); + @NotNull + @Override + public SdkModificator getSdkModificator() { + return this; + } + + @Nullable + @Override + public T getUserData(@NotNull Key key) { + return udh.getUserData(key); + } + + @Override + public void putUserData(@NotNull Key key, @Nullable T value) { + udh.putUserData(key, value); + } + }; + } + + @NotNull + @Override + public SdkModificator getSdkModificator() { + throwReadOnly(); + return null; + } + + @NotNull + public VirtualFile[] getRoots(@NotNull OrderRootType rootType) { + return myRoots.get(rootType).toArray(VirtualFile.EMPTY_ARRAY); + } + + @Override + public void setName(String name) { + myName = name; + } + + @Override + public void setHomePath(String path) { + myHomePath = path; + } + + @Override + public void setVersionString(@NotNull String versionString) { + myVersionString = versionString; + } + + @Override + public void setSdkAdditionalData(SdkAdditionalData data) { + throwReadOnly(); + } + + @Override + public void addRoot(@NotNull VirtualFile root, @NotNull OrderRootType rootType) { + myRoots.putValue(rootType, root); + } + + @Override + public void removeRoot(@NotNull VirtualFile root, @NotNull OrderRootType rootType) { + myRoots.remove(rootType, root); + } + + @Override + public void removeRoots(@NotNull OrderRootType rootType) { + myRoots.remove(rootType); + } + + @Override + public void removeAllRoots() { + myRoots.clear(); + } + + @Override + public void commitChanges() { + for (Project project : ProjectManager.getInstance().getOpenProjects()) { + WriteAction + .run(() -> ((ProjectRootManagerEx)ProjectRootManager.getInstance(project)).makeRootsChange(EmptyRunnable.getInstance(), false, true)); + } + } + + @Override + public boolean isWritable() { + return true; + } + + @NotNull + @Override + public RootProvider getRootProvider() { + return new RootProvider() { + @NotNull + @Override + public String[] getUrls(@NotNull OrderRootType rootType) { + return ContainerUtil.map2Array(getFiles(rootType), String.class, VirtualFile::getUrl); + } + + @NotNull + @Override + public VirtualFile[] getFiles(@NotNull OrderRootType rootType) { + return getRoots(rootType); + } + + @Override + public void addRootSetChangedListener(@NotNull RootSetChangedListener listener) { } + + @Override + public void addRootSetChangedListener(@NotNull RootSetChangedListener listener, @NotNull Disposable parentDisposable) { } + + @Override + public void removeRootSetChangedListener(@NotNull RootSetChangedListener listener) { } + }; + } + + private void throwReadOnly() { + throw new IncorrectOperationException("Can't modify, MockJDK is read-only, consider calling .clone() first"); + } + + @Nullable + @Override + public T getUserData(@NotNull Key key) { + return null; + } + + @Override + public void putUserData(@NotNull Key key, @Nullable T value) { + throwReadOnly(); + } + + @Override + public String toString() { + return "MockSDK[" + myName + "]"; + } +} diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxSdkSetupNotificationTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxSdkSetupNotificationTest.java index 9b45dea38d79..8fd23aa207f9 100644 --- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxSdkSetupNotificationTest.java +++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxSdkSetupNotificationTest.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.javaFX.fxml; import com.intellij.java.codeInsight.daemon.impl.SdkSetupNotificationTestBase; import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.testFramework.IdeaTestUtil; import com.intellij.ui.EditorNotificationPanel; @@ -37,6 +38,6 @@ public class JavaFxSdkSetupNotificationTest extends SdkSetupNotificationTestBase @NotNull private static Sdk getTestJdk() { - return JavaSdk.getInstance().createJdk("testJdk", System.getProperty("java.home")); + return ((JavaSdkImpl)JavaSdk.getInstance()).createMockJdk("testJdk", System.getProperty("java.home"), true); } } diff --git a/python/testSrc/com/jetbrains/python/PyIndexingTest.java b/python/testSrc/com/jetbrains/python/PyIndexingTest.java index ee0dc0089f68..ac6824bd7a22 100644 --- a/python/testSrc/com/jetbrains/python/PyIndexingTest.java +++ b/python/testSrc/com/jetbrains/python/PyIndexingTest.java @@ -103,6 +103,9 @@ public class PyIndexingTest extends PyTestCase { assertFalse(indexFiles.stream().anyMatch((x) -> "smtpd.py".equals(x.getName()))); ModuleRootModificationUtil.addContentRoot(myFixture.getModule(), libsRoot); + // mock sdk doesn't fire events + FileBasedIndex.getInstance().requestRebuild(TodoIndex.NAME); + FileBasedIndex.getInstance().ensureUpToDate(TodoIndex.NAME, myFixture.getProject(), null); indexFiles = getTodoFiles(myFixture.getProject()); diff --git a/python/testSrc/com/jetbrains/python/PythonMockSdk.java b/python/testSrc/com/jetbrains/python/PythonMockSdk.java index 8b95f25015b1..cdac6b9d4051 100644 --- a/python/testSrc/com/jetbrains/python/PythonMockSdk.java +++ b/python/testSrc/com/jetbrains/python/PythonMockSdk.java @@ -17,13 +17,13 @@ package com.jetbrains.python; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.SdkModificator; import com.intellij.openapi.projectRoots.SdkType; -import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl; +import com.intellij.openapi.projectRoots.impl.MockSdk; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.stubs.StubUpdatingIndex; +import com.intellij.util.containers.MultiMap; import com.intellij.util.indexing.FileBasedIndex; import com.jetbrains.python.codeInsight.typing.PyTypeShed; import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil; @@ -52,53 +52,44 @@ public class PythonMockSdk { return sdk; } } - return create(version, additionalRoots); - } - - public static Sdk create(final String version, @NotNull final VirtualFile ... additionalRoots) { final String mock_path = PythonTestUtil.getTestDataPath() + "/MockSdk" + version + "/"; String sdkHome = new File(mock_path, "bin/python"+version).getPath(); SdkType sdkType = PythonSdkType.getInstance(); - - final Sdk sdk = new ProjectJdkImpl(MOCK_SDK_NAME + " " + version, sdkType) { - @Override - public String getVersionString() { - return "Python " + version + " Mock SDK"; - } - }; - final SdkModificator sdkModificator = sdk.getSdkModificator(); - sdkModificator.setHomePath(sdkHome); + MultiMap roots = MultiMap.create(); File libPath = new File(mock_path, "Lib"); if (libPath.exists()) { - sdkModificator.addRoot(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(libPath), OrderRootType.CLASSES); + roots.putValue(OrderRootType.CLASSES, LocalFileSystem.getInstance().refreshAndFindFileByIoFile(libPath)); } - sdkModificator.addRoot(PyUserSkeletonsUtil.getUserSkeletonsDirectory(), OrderRootType.CLASSES); + roots.putValue(OrderRootType.CLASSES, PyUserSkeletonsUtil.getUserSkeletonsDirectory()); + final LanguageLevel level = LanguageLevel.fromPythonVersion(version); final VirtualFile typeShedDir = PyTypeShed.INSTANCE.getDirectory(); PyTypeShed.INSTANCE.findRootsForLanguageLevel(level).forEach(path -> { final VirtualFile file = typeShedDir.findFileByRelativePath(path); if (file != null) { - sdkModificator.addRoot(file, OrderRootType.CLASSES); + roots.putValue(OrderRootType.CLASSES, file); } }); String mock_stubs_path = mock_path + PythonSdkType.SKELETON_DIR_NAME; - sdkModificator.addRoot(LocalFileSystem.getInstance().refreshAndFindFileByPath(mock_stubs_path), PythonSdkType.BUILTIN_ROOT_TYPE); + roots.putValue(PythonSdkType.BUILTIN_ROOT_TYPE, LocalFileSystem.getInstance().refreshAndFindFileByPath(mock_stubs_path)); for (final VirtualFile root : additionalRoots) { - sdkModificator.addRoot(root, OrderRootType.CLASSES); + roots.putValue(OrderRootType.CLASSES, root); } - sdkModificator.commitChanges(); + + MockSdk sdk = new MockSdk(MOCK_SDK_NAME + " " + version, sdkHome, "Python " + version + " Mock SDK", roots, sdkType); final FileBasedIndex index = FileBasedIndex.getInstance(); index.requestRebuild(StubUpdatingIndex.INDEX_ID); index.requestRebuild(PyModuleNameIndex.NAME); - return sdk; + // com.jetbrains.python.psi.resolve.PythonSdkPathCache.getInstance() corrupts SDK, so have to clone + return sdk.clone(); } }