Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2016-09-12 20:34:10 +03:00
21 changed files with 170 additions and 45 deletions
@@ -20,14 +20,12 @@ import com.intellij.ide.projectView.PsiClassChildrenSource;
import com.intellij.ide.scopeView.nodes.ClassNode;
import com.intellij.ide.scopeView.nodes.FieldNode;
import com.intellij.ide.scopeView.nodes.MethodNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packageDependencies.ui.DependencyNodeComparator;
import com.intellij.packageDependencies.ui.DirectoryNode;
import com.intellij.packageDependencies.ui.FileNode;
import com.intellij.packageDependencies.ui.PackageDependenciesNode;
import com.intellij.psi.*;
import com.intellij.util.ui.tree.TreeUtil;
@@ -74,7 +72,7 @@ public class ClassesScopeTreeStructureExpander implements ScopeTreeStructureExpa
if (classNodes == null) {
classNodes = new HashSet<>();
}
commitDocument((PsiFile)file);
for (final PsiClass psiClass : psiClasses) {
if (psiClass != null && psiClass.isValid()) {
final ClassNode classNode = new ClassNode(psiClass);
@@ -155,9 +153,4 @@ public class ClassesScopeTreeStructureExpander implements ScopeTreeStructureExpa
return new DependencyNodeComparator(ProjectView.getInstance(myProject).isSortByType(ScopeViewPane.ID));
}
private void commitDocument(final PsiFile file) {
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
final Document document = documentManager.getDocument(file);
documentManager.commitDocument(document);
}
}
@@ -61,7 +61,7 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations
protected final PsiManager myPsiManager;
private final ConcurrentMap<VirtualFile, List<PsiFile>> myExternalAnnotations = ContainerUtil.createConcurrentSoftValueMap();
private final ConcurrentMap<VirtualFile, List<PsiFile>> myExternalAnnotations = ContainerUtil.createConcurrentWeakKeySoftValueMap();
private final Map<AnnotationData, AnnotationData> myAnnotationDataCache = new WeakKeyWeakValueHashMap<AnnotationData, AnnotationData>();
private final ConcurrentMap<PsiFile, Pair<MostlySingularMultiMap<String, AnnotationData>, Long>> myAnnotationFileToDataAndModStamp = ContainerUtil.createConcurrentSoftMap();
@@ -0,0 +1,90 @@
/*
* 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.psi;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.Key;
import com.intellij.testFramework.LeakHunter;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.intellij.util.GCUtil;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class LightVirtualFileLeaksTest extends LightCodeInsightFixtureTestCase {
private Key<Boolean> myKey;
private static final DefaultLightProjectDescriptor PROJECT_DESCRIPTOR = new DefaultLightProjectDescriptor() {
@Override
public Sdk getSdk() {
return PsiTestUtil.addJdkAnnotations(super.getSdk());
}
};
@Override
protected void setUp() throws Exception {
super.setUp();
myKey = Key.create(getName());
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return PROJECT_DESCRIPTOR;
}
public void testDoNotLeakViaDocument() {
createFileWithDocument();
checkLeak();
}
private void createFileWithDocument() {
Document document = FileDocumentManager.getInstance().getDocument(createLightFile());
assertNotNull(document);
PsiJavaFile psiFile = (PsiJavaFile)PsiDocumentManager.getInstance(getProject()).getPsiFile(document);
assertSame(document, PsiDocumentManager.getInstance(getProject()).getDocument(psiFile));
}
private void checkLeak() {
GCUtil.tryGcSoftlyReachableObjects();
LeakHunter.checkLeak(getProject(), LightVirtualFile.class, vf -> vf.getUserData(myKey) == Boolean.TRUE);
}
public void testDoNotLeakViaExternalAnnotations() {
queryExternalAnnotations();
checkLeak();
}
private void queryExternalAnnotations() {
LightVirtualFile vFile = createLightFile();
assertEmpty(AnnotationUtil.getAllAnnotations(((PsiJavaFile)getPsiManager().findFile(vFile)).getClasses()[0], true, null));
}
@NotNull
private LightVirtualFile createLightFile() {
LightVirtualFile vFile = new LightVirtualFile(getName() + ".java", JavaFileType.INSTANCE, "class Foo {}");
vFile.putUserData(myKey, Boolean.TRUE);
return vFile;
}
}
@@ -220,8 +220,12 @@ public class FileManagerImpl implements FileManager {
assert !file.isDirectory();
FileViewProvider viewProvider = findCachedViewProvider(file);
if (viewProvider != null) return viewProvider;
viewProvider = ConcurrencyUtil.cacheOrGet(myVFileToViewProviderMap, file, createFileViewProvider(file, true));
return viewProvider;
viewProvider = createFileViewProvider(file, true);
if (file instanceof LightVirtualFile) {
return file.putUserDataIfAbsent(myPsiHardRefKey, viewProvider);
}
return ConcurrencyUtil.cacheOrGet(myVFileToViewProviderMap, file, viewProvider);
}
@Override
@@ -1112,7 +1112,9 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myManager.dropResolveCaches();
if (!myManager.isDisposed()) {
myManager.dropResolveCaches();
}
final VirtualFile vFile = getVirtualFile();
if (vFile != null && vFile.isValid()) {
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.OptionAction;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.components.labels.ActionLink;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.components.BorderLayoutPanel;
@@ -52,7 +53,8 @@ public class VcsPushDialog extends DialogWrapper {
public VcsPushDialog(@NotNull Project project,
@NotNull List<? extends Repository> selectedRepositories,
@Nullable Repository currentRepo) {
super(project);
super(project, true, (Registry.is("ide.perProjectModality")) ? IdeModalityType.PROJECT : IdeModalityType.IDE);
myController = new PushController(project, this, selectedRepositories, currentRepo);
myAdditionalPanels = myController.createAdditionalPanels();
myListPanel = myController.getPushPanelLog();
@@ -31,7 +31,8 @@ import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.ResolveScopeManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.indexing.AdditionalIndexableFileSet;
import org.jetbrains.annotations.NotNull;
@@ -43,7 +44,13 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
private final ProjectRootManager myProjectRootManager;
private final PsiManager myManager;
private final Map<VirtualFile, GlobalSearchScope> myDefaultResolveScopesCache = new ConcurrentFactoryMap<VirtualFile, GlobalSearchScope>() {
private final Map<VirtualFile, GlobalSearchScope> myDefaultResolveScopesCache = new FactoryMap<VirtualFile, GlobalSearchScope>() {
@Override
protected Map<VirtualFile, GlobalSearchScope> createMap() {
return ContainerUtil.createConcurrentWeakKeySoftValueMap();
}
@Override
protected GlobalSearchScope create(@NotNull VirtualFile key) {
GlobalSearchScope scope = null;
@@ -27,6 +27,7 @@ import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.EmptyAction;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.editor.*;
@@ -108,7 +109,7 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons
public void focusGained(Editor editor) {
myCurrentEditor = (EditorEx)editor;
if (GeneralSettings.getInstance().isSaveOnFrameDeactivation()) {
FileDocumentManager.getInstance().saveAllDocuments(); // PY-12487
TransactionGuard.submitTransaction(LanguageConsoleImpl.this, () -> FileDocumentManager.getInstance().saveAllDocuments()); // PY-12487
}
}
@@ -259,7 +259,6 @@ public class GotoActionModel implements ChooseByNameModel, Comparator<Object>, E
public static AnActionEvent updateActionBeforeShow(@NotNull AnAction anAction, @NotNull DataContext dataContext) {
AnActionEvent event = AnActionEvent.createFromDataContext(ActionPlaces.ACTION_SEARCH, null, dataContext);
ActionUtil.performDumbAwareUpdate(anAction, event, false);
ActionUtil.performDumbAwareUpdate(anAction, event, true);
return event;
}
@@ -151,7 +151,7 @@ public class CommandLineProcessor {
try {
final String url = URLDecoder.decode(command, "UTF-8");
JetBrainsProtocolHandler.processJetBrainsLauncherParameters(url);
ApplicationManager.getApplication().invokeLater(() -> JBProtocolCommand.handleCurrentCommand(), ModalityState.any());
ApplicationManager.getApplication().invokeLater(() -> JBProtocolCommand.handleCurrentCommand());
}
catch (UnsupportedEncodingException e) {
LOG.error(e);
@@ -80,7 +80,7 @@ public final class CommandProcessor implements Runnable {
// definitely have some since runnables in command list may (and do) request some PSI activity
final boolean queueNext = myCommandCount > 0;
Application application = ApplicationManager.getApplication();
ModalityState modalityState = Registry.is("ide.perProjectModality") ? ModalityState.defaultModalityState() : ModalityState.NON_MODAL;
ModalityState modalityState = ModalityState.NON_MODAL;
application.getInvokator().invokeLater(command, modalityState, expire == null ? application.getDisposed() : expire).doWhenDone(() -> {
if (queueNext) {
this.run();
@@ -22,7 +22,7 @@ import org.apache.http.client.fluent.Request
import org.apache.http.entity.ContentType
private class StatsServerInfo(var status: String, var url: String) {
private class StatsServerInfo(@JvmField var status: String, @JvmField var url: String) {
fun isServiceAlive() = "ok" == status
}
@@ -271,7 +271,7 @@ public class CommitChangeListDialog extends DialogWrapper implements CheckinProj
final boolean isAlien,
final String comment,
@Nullable CommitResultHandler customResultHandler) {
super(project, true);
super(project, true, (Registry.is("ide.perProjectModality")) ? IdeModalityType.PROJECT : IdeModalityType.IDE);
myCommitContext = new CommitContext();
myProject = project;
myVcsConfiguration = ObjectUtils.assertNotNull(VcsConfiguration.getInstance(myProject));
@@ -93,7 +93,7 @@ public class VcsLogData implements Disposable, VcsLogDataProvider {
if (!(e instanceof ProcessCanceledException)) {
LOG.error(e);
}
}, RECENT_COMMITS_COUNT);
}, RECENT_COMMITS_COUNT, this);
myContainingBranchesGetter = new ContainingBranchesGetter(this, this);
}
@@ -26,12 +26,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
public class VcsLogProgress {
public class VcsLogProgress implements Disposable {
@NotNull private final Object myLock = new Object();
@NotNull private final List<ProgressListener> myListeners = ContainerUtil.newArrayList();
private int myRunningTasksCount = 0;
@NotNull private Set<ProgressIndicator> myRunningTasks = ContainerUtil.newHashSet();
@NotNull
public ProgressIndicator createProgressIndicator() {
@@ -59,21 +60,21 @@ public class VcsLogProgress {
public boolean isRunning() {
synchronized (myLock) {
return myRunningTasksCount > 0;
return !myRunningTasks.isEmpty();
}
}
private void started() {
private void started(@NotNull ProgressIndicator indicator) {
synchronized (myLock) {
myRunningTasksCount++;
if (myRunningTasksCount == 1) fireNotification(ProgressListener::progressStarted);
myRunningTasks.add(indicator);
if (myRunningTasks.size() == 1) fireNotification(ProgressListener::progressStarted);
}
}
private void stopped() {
private void stopped(@NotNull ProgressIndicator indicator) {
synchronized (myLock) {
myRunningTasksCount--;
if (myRunningTasksCount == 0) fireNotification(ProgressListener::progressStopped);
myRunningTasks.remove(indicator);
if (myRunningTasks.isEmpty()) fireNotification(ProgressListener::progressStopped);
}
}
@@ -84,17 +85,26 @@ public class VcsLogProgress {
}
}
@Override
public void dispose() {
synchronized (myLock) {
for (ProgressIndicator indicator : myRunningTasks) {
indicator.cancel();
}
}
}
private class VcsLogProgressIndicator extends AbstractProgressIndicatorBase {
@Override
public synchronized void start() {
super.start();
started();
started(this);
}
@Override
public synchronized void stop() {
super.stop();
stopped();
stopped(this);
}
}
@@ -15,11 +15,13 @@
*/
package com.intellij.vcs.log.data;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
@@ -65,7 +67,8 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
@NotNull TopCommitsCache topCommitsDetailsCache,
@NotNull Consumer<DataPack> dataPackUpdateHandler,
@NotNull Consumer<Exception> exceptionHandler,
int recentCommitsCount) {
int recentCommitsCount,
@NotNull Disposable parentDisposable) {
myProject = project;
myHashMap = hashMap;
myProviders = providers;
@@ -74,6 +77,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
myExceptionHandler = exceptionHandler;
myRecentCommitCount = recentCommitsCount;
myProgress = new VcsLogProgress();
Disposer.register(parentDisposable, myProgress);
mySingleTaskController = new SingleTaskController<RefreshRequest, DataPack>(dataPack -> {
myDataPack = dataPack;
@@ -17,6 +17,7 @@ package com.intellij.vcs.log.data;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
@@ -60,6 +61,7 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
@NotNull private final PersistentEnumeratorBase<CommitId> myCommitIdEnumerator;
@NotNull private final PersistentEnumeratorBase<VcsRef> myRefsEnumerator;
@NotNull private final Consumer<Exception> myExceptionReporter;
private volatile boolean myDisposed = false;
public VcsLogStorageImpl(@NotNull Project project,
@NotNull Map<VirtualFile, VcsLogProvider> logProviders,
@@ -94,6 +96,7 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
@Override
public int getCommitIndex(@NotNull Hash hash, @NotNull VirtualFile root) {
checkDisposed();
try {
return getOrPut(hash, root);
}
@@ -106,6 +109,7 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
@Override
@Nullable
public CommitId getCommitId(int commitIndex) {
checkDisposed();
try {
CommitId commitId = doGetCommitId(commitIndex);
if (commitId == null) {
@@ -122,6 +126,7 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
@Override
@Nullable
public CommitId findCommitId(@NotNull final Condition<CommitId> condition) {
checkDisposed();
try {
final Ref<CommitId> hashRef = Ref.create();
myCommitIdEnumerator.iterateData(new CommonProcessors.FindProcessor<CommitId>() {
@@ -144,6 +149,7 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
@Override
public int getRefIndex(@NotNull VcsRef ref) {
checkDisposed();
try {
return myRefsEnumerator.enumerate(ref);
}
@@ -156,6 +162,7 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
@Nullable
@Override
public VcsRef getVcsRef(int refIndex) {
checkDisposed();
try {
return myRefsEnumerator.valueOf(refIndex);
}
@@ -166,6 +173,7 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
}
public void flush() {
checkDisposed();
myCommitIdEnumerator.force();
myRefsEnumerator.force();
}
@@ -173,6 +181,7 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
@Override
public void dispose() {
try {
myDisposed = true;
myCommitIdEnumerator.close();
myRefsEnumerator.close();
}
@@ -181,6 +190,10 @@ public class VcsLogStorageImpl implements Disposable, VcsLogStorage {
}
}
private void checkDisposed() {
if (myDisposed) throw new ProcessCanceledException();
}
private static class MyCommitIdKeyDescriptor implements KeyDescriptor<CommitId> {
@NotNull private final List<VirtualFile> myRoots;
@NotNull private final TObjectIntHashMap<VirtualFile> myRootsReversed;
@@ -202,7 +202,8 @@ public class VcsLogRefresherTest extends VcsPlatformTest {
myLogData = new VcsLogData(myProject, myLogProviders, LOG::error);
Disposer.register(myProject, myLogData);
return new VcsLogRefresherImpl(myProject, myLogData.getHashMap(), myLogProviders, myLogData.getUserRegistry(),
myLogData.getTopCommitsCache(), dataPackConsumer, FAILING_EXCEPTION_HANDLER, RECENT_COMMITS_COUNT) {
myLogData.getTopCommitsCache(), dataPackConsumer, FAILING_EXCEPTION_HANDLER, RECENT_COMMITS_COUNT,
myLogData) {
@Override
protected void startNewBackgroundTask(@NotNull final Task.Backgroundable refreshTask) {
LOG.debug("Starting a background task...");
@@ -130,7 +130,7 @@ public abstract class TestObject extends JavaTestFrameworkRunnableState<JUnitCon
@Nullable
public SourceScope getSourceScope() {
return SourceScope.modulesWithDependencies(getConfiguration().getModules());
return SourceScope.modules(getConfiguration().getModules());
}
@Override
+8 -6
View File
@@ -17,6 +17,7 @@ package org.jetbrains.settingsRepository
import com.intellij.configurationStore.*
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.impl.ApplicationImpl
import com.intellij.openapi.components.StateStorage
import com.intellij.openapi.components.stateStore
@@ -24,10 +25,9 @@ import com.intellij.openapi.options.SchemeManagerFactory
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.runModalTask
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Computable
import com.intellij.openapi.util.Ref
import com.intellij.util.SmartList
import com.intellij.util.messages.MessageBus
import com.intellij.util.ui.UIUtil
import gnu.trove.THashSet
import org.eclipse.jgit.errors.NoRemoteRepositoryException
import java.util.*
@@ -168,7 +168,8 @@ internal fun updateStoragesFromStreamProvider(store: ComponentStoreImpl, updateR
return false
}
return UIUtil.invokeAndWaitIfNeeded(Computable {
val result = Ref.create(false)
ApplicationManager.getApplication().invokeAndWait(Runnable {
val notReloadableComponents: Collection<String>
updateStateStorage(changedComponentNames, changed, false)
updateStateStorage(changedComponentNames, deleted, true)
@@ -178,7 +179,7 @@ internal fun updateStoragesFromStreamProvider(store: ComponentStoreImpl, updateR
}
if (changedComponentNames.isEmpty()) {
return@Computable false
return@Runnable
}
notReloadableComponents = store.getNotReloadableComponents(changedComponentNames)
@@ -189,8 +190,9 @@ internal fun updateStoragesFromStreamProvider(store: ComponentStoreImpl, updateR
store.reinitComponents(changedComponentNames, changedStorageSet, notReloadableComponents)
}
!notReloadableComponents.isEmpty() && askToRestart(store, notReloadableComponents, null, true)
})
result.set(!notReloadableComponents.isEmpty() && askToRestart(store, notReloadableComponents, null, true))
}, ModalityState.defaultModalityState())
return result.get()
}
private fun updateStateStorage(changedComponentNames: MutableSet<String>, stateStorages: Collection<StateStorage>, deleted: Boolean) {
@@ -70,9 +70,6 @@ class BaseStdIn:
# which is not something we want.
return '\n'
def isatty(self):
return False # not really a file
def write(self, *args, **kwargs):
pass # not available StdIn (but it can be expected to be in the stream interface)