dispose leaking virtual file pointers in tests

This commit is contained in:
Alexey Kudravtsev
2017-09-18 13:35:28 +03:00
parent e0eba619c8
commit c6b1ec8ef3
7 changed files with 257 additions and 211 deletions
@@ -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<OrderRootType, VirtualFile> myRoots;
private final boolean myIsJre;
MockSdk(@NotNull String jdkName,
@NotNull String homePath,
@NotNull String versionString,
@NotNull MultiMap<OrderRootType, VirtualFile> 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> T getUserData(@NotNull Key<T> key) {
return null;
}
@Override
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
throwReadOnly();
}
@Override
public String toString() {
return "MockSDK[" + myJdkName + "]";
}
}
}
@@ -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 { }")
@@ -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);
});
});
@@ -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<OrderRootType, VirtualFile> myRoots;
private final SdkTypeId mySdkType;
public MockSdk(@NotNull String name,
@NotNull String homePath,
@NotNull String versionString,
@NotNull MultiMap<OrderRootType, VirtualFile> 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> T getUserData(@NotNull Key<T> key) {
return udh.getUserData(key);
}
@Override
public <T> void putUserData(@NotNull Key<T> 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> T getUserData(@NotNull Key<T> key) {
return null;
}
@Override
public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
throwReadOnly();
}
@Override
public String toString() {
return "MockSDK[" + myName + "]";
}
}
@@ -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);
}
}
@@ -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());
@@ -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<OrderRootType, VirtualFile> 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();
}
}