diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
index cfddc716f0a3..c271e27debc1 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
@@ -23,7 +23,6 @@ import com.intellij.codeInsight.daemon.impl.analysis.CustomHighlightInfoHolder;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager;
import com.intellij.codeInsight.problems.ProblemImpl;
-import com.intellij.concurrency.JobScheduler;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
@@ -50,6 +49,7 @@ import com.intellij.psi.search.TodoItem;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.NotNullProducer;
import com.intellij.util.SmartList;
+import com.intellij.util.concurrency.EdtExecutorService;
import com.intellij.util.containers.Stack;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -428,18 +428,10 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
private static void cancelAndRestartDaemonLater(@NotNull ProgressIndicator progress,
@NotNull final Project project) throws ProcessCanceledException {
progress.cancel();
- JobScheduler.getScheduler().schedule(new Runnable() {
- @Override
- public void run() {
- Application application = ApplicationManager.getApplication();
- if (!project.isDisposed() && !application.isDisposed() && !application.isUnitTestMode()) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- DaemonCodeAnalyzer.getInstance(project).restart();
- }
- }, project.getDisposed());
- }
+ EdtExecutorService.getScheduledExecutorInstance().schedule((Runnable)() -> {
+ Application application = ApplicationManager.getApplication();
+ if (!project.isDisposed() && !application.isDisposed() && !application.isUnitTestMode()) {
+ DaemonCodeAnalyzer.getInstance(project).restart();
}
}, RESTART_DAEMON_RANDOM.nextInt(100), TimeUnit.MILLISECONDS);
throw new ProcessCanceledException();
diff --git a/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java b/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java
index 423684a31408..bef6ce81aabd 100644
--- a/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java
+++ b/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java
@@ -94,7 +94,20 @@ public abstract class TransactionGuard {
* @param transaction code to execute inside a transaction.
*/
public static void submitTransaction(@NotNull Runnable transaction) {
- getInstance().submitMergeableTransaction(TransactionKind.NO_MERGE, transaction);
+ getInstance().submitMergeableTransaction(TransactionKind.ANY_CHANGE, transaction);
+ }
+
+ /**
+ * Runs the given code synchronously inside a transaction. Fails if transactions of given kind are not allowed at this moment.
+ * @see #startSynchronousTransaction(TransactionKind)
+ */
+ public static void syncTransaction(@NotNull TransactionKind kind, @NotNull Runnable transaction) {
+ AccessToken token = getInstance().startSynchronousTransaction(kind);
+ try {
+ transaction.run();
+ } finally {
+ token.finish();
+ }
}
/**
diff --git a/platform/core-api/src/com/intellij/openapi/application/TransactionKind.java b/platform/core-api/src/com/intellij/openapi/application/TransactionKind.java
index bc7d3be0da3b..6a666b98b0ad 100644
--- a/platform/core-api/src/com/intellij/openapi/application/TransactionKind.java
+++ b/platform/core-api/src/com/intellij/openapi/application/TransactionKind.java
@@ -27,11 +27,6 @@ public interface TransactionKind {
*/
TransactionKind TEXT_EDITING = Common.TEXT_EDITING;
- /**
- * Same as {@link Common#NO_MERGE}
- */
- TransactionKind NO_MERGE = Common.NO_MERGE;
-
/**
* Same as {@link Common#ANY_CHANGE}
*/
@@ -56,11 +51,7 @@ public interface TransactionKind {
*
Project root set change
* Dumb mode (reindexing) start/finish, (see {@link com.intellij.openapi.project.DumbService}).
*/
- ANY_CHANGE,
+ ANY_CHANGE
- /**
- * Transactions of this kind won't be merged into other transactions
- */
- NO_MERGE
}
}
diff --git a/platform/core-api/src/com/intellij/openapi/application/WrapInTransaction.java b/platform/core-api/src/com/intellij/openapi/application/WrapInTransaction.java
index b42f547b326f..63a839a91460 100644
--- a/platform/core-api/src/com/intellij/openapi/application/WrapInTransaction.java
+++ b/platform/core-api/src/com/intellij/openapi/application/WrapInTransaction.java
@@ -18,5 +18,5 @@ public @interface WrapInTransaction {
/**
* @return the kind of transaction to wrap the action into. By default, it's {@link TransactionKind#NO_MERGE}.
*/
- TransactionKind.Common value() default TransactionKind.Common.NO_MERGE;
+ TransactionKind.Common value() default TransactionKind.Common.ANY_CHANGE;
}
diff --git a/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java b/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java
index 43ca3fb43d63..0f2456282efd 100644
--- a/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java
@@ -41,7 +41,7 @@ public class TransactionGuardImpl extends TransactionGuard {
@NotNull
public AccessToken startSynchronousTransaction(@NotNull TransactionKind kind) throws IllegalStateException {
ApplicationManager.getApplication().assertIsDispatchThread();
- if (kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind)) {
+ if (myMergeableKinds.contains(kind)) {
return AccessToken.EMPTY_ACCESS_TOKEN;
}
if (myTransactionStartTrace != null) {
@@ -71,7 +71,7 @@ public class TransactionGuardImpl extends TransactionGuard {
Runnable next = myQueue.poll();
if (next != null) {
- runSyncTransaction(TransactionKind.NO_MERGE, next);
+ runSyncTransaction(TransactionKind.ANY_CHANGE, next);
}
}
}, app.getDisposed());
@@ -118,7 +118,7 @@ public class TransactionGuardImpl extends TransactionGuard {
}
protected boolean canRunTransactionNow(@NotNull TransactionKind kind) {
- return !isInsideTransaction() || kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind);
+ return !isInsideTransaction() || myMergeableKinds.contains(kind);
}
@Override
diff --git a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
index a45b88b060e9..d28b1c3241ed 100644
--- a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
+++ b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
@@ -251,7 +251,7 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel {
}
if (containingFileByTree != null) {
boolean isFromCommit = ApplicationManager.getApplication().isDispatchThread() &&
- ApplicationManager.getApplication().hasWriteAction(CommitToPsiFileAction.class);
+ ((PsiDocumentManagerBase)PsiDocumentManager.getInstance(myProject)).isCommitInProgress();
if (!isFromCommit && !synchronizer.isIgnorePsiEvents()) {
reparseParallelTrees(containingFileByTree);
if (docSynced) {
diff --git a/platform/core-impl/src/com/intellij/psi/impl/CommitToPsiFileAction.java b/platform/core-impl/src/com/intellij/psi/impl/CommitToPsiFileAction.java
deleted file mode 100644
index f3966bdbb38d..000000000000
--- a/platform/core-impl/src/com/intellij/psi/impl/CommitToPsiFileAction.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2000-2009 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.impl;
-
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.DocumentRunnable;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.IgnorePsiEventsMarker;
-
-
-public abstract class CommitToPsiFileAction extends DocumentRunnable implements IgnorePsiEventsMarker {
- protected CommitToPsiFileAction(Document document, Project project) {
- super(document,project);
- }
-}
-
-
-
-
diff --git a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
index 881e5a29bf49..cd50b88fb056 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
@@ -19,9 +19,7 @@ import com.intellij.diagnostic.ThreadDumper;
import com.intellij.lang.ASTNode;
import com.intellij.lang.FileASTNode;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationAdapter;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.*;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Attachment;
@@ -75,6 +73,8 @@ import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
public class DocumentCommitThread implements Runnable, Disposable, DocumentCommitProcessor {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.DocumentCommitThread");
@@ -471,14 +471,29 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
throw new RuntimeException(s);
}
- CommitTask task = createNewTaskAndCancelSimilar(project, document, getAllFileNodes(psiFile), "Sync commit", ModalityState.current());
- assert !task.indicator.isCanceled();
- Pair result = commitUnderProgress(task, true);
- Runnable finish = result.first;
- log(project, "Committed sync", task, finish, task.indicator);
- assert finish != null;
+ List> allFileNodes = getAllFileNodes(psiFile);
- finish.run();
+ Lock documentLock = getDocumentLock(document);
+
+ CommitTask task;
+ synchronized (lock) {
+ // synchronized to ensure no new similar tasks can start before we hold the document's lock
+ task = createNewTaskAndCancelSimilar(project, document, allFileNodes, "Sync commit", ModalityState.current());
+ documentLock.lock();
+ }
+
+ try {
+ assert !task.indicator.isCanceled();
+ Pair result = commitUnderProgress(task, true);
+ Runnable finish = result.first;
+ log(project, "Committed sync", task, finish, task.indicator);
+ assert finish != null;
+
+ finish.run();
+ }
+ finally {
+ documentLock.unlock();
+ }
// will wake itself up on write action end
}
@@ -525,29 +540,40 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
myApplication.assertReadAccessAllowed();
if (project.isDisposed()) return;
- if (documentManager.isCommitted(document)) return;
-
- if (!task.isStillValid()) {
- task.cancel("Task invalidated", DocumentCommitThread.this);
+ Lock lock = getDocumentLock(document);
+ if (!lock.tryLock()) {
+ task.cancel("Can't obtain document lock", DocumentCommitThread.this);
return;
}
- FileViewProvider viewProvider = documentManager.getCachedViewProvider(document);
- if (viewProvider == null) {
- finishProcessors.add(handleCommitWithoutPsi(documentManager, task));
- return;
- }
+ try {
+ if (documentManager.isCommitted(document)) return;
- for (Pair pair : task.myOldFileNodes) {
- PsiFileImpl file = pair.first;
- if (file.isValid()) {
- FileASTNode oldFileNode = pair.second;
- Processor finishProcessor = doCommit(task, file, oldFileNode);
- if (finishProcessor != null) {
- finishProcessors.add(finishProcessor);
+ if (!task.isStillValid()) {
+ task.cancel("Task invalidated", DocumentCommitThread.this);
+ return;
+ }
+
+ FileViewProvider viewProvider = documentManager.getCachedViewProvider(document);
+ if (viewProvider == null) {
+ finishProcessors.add(handleCommitWithoutPsi(documentManager, task));
+ return;
+ }
+
+ for (Pair pair : task.myOldFileNodes) {
+ PsiFileImpl file = pair.first;
+ if (file.isValid()) {
+ FileASTNode oldFileNode = pair.second;
+ Processor finishProcessor = doCommit(task, file, oldFileNode);
+ if (finishProcessor != null) {
+ finishProcessors.add(finishProcessor);
+ }
}
}
}
+ finally {
+ lock.unlock();
+ }
}
};
if (synchronously) {
@@ -742,7 +768,9 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
return new Processor() {
@Override
public boolean process(Document document) {
- ApplicationManager.getApplication().assertWriteAccessAllowed();
+ if (file.isPhysical()) {
+ ApplicationManager.getApplication().assertWriteAccessAllowed();
+ }
if (!task.isStillValid() ||
((PsiDocumentManagerBase)PsiDocumentManager.getInstance(file.getProject())).getCachedViewProvider(document) != file.getViewProvider()) {
return false; // optimistic locking failed
@@ -887,4 +915,13 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
}
}
}
+
+ /**
+ * @return an internal lock object to prevent read & write phases of commit from running simultaneously for free-threaded PSI
+ */
+ private static Lock getDocumentLock(Document document) {
+ Lock lock = document.getUserData(DOCUMENT_LOCK);
+ return lock != null ? lock : ((UserDataHolderEx)document).putUserDataIfAbsent(DOCUMENT_LOCK, new ReentrantLock());
+ }
+ private static final Key DOCUMENT_LOCK = Key.create("DOCUMENT_LOCK");
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
index b896505433a3..dbfb1a2909ce 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
@@ -27,6 +27,7 @@ import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.DocumentRunnable;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
@@ -153,6 +154,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
return ((PsiManagerEx)myPsiManager).getFileManager().findCachedViewProvider(virtualFile);
}
+ @Nullable
private static VirtualFile getVirtualFile(@NotNull Document document) {
final VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
if (virtualFile == null || !virtualFile.isValid()) return null;
@@ -261,7 +263,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
return true;
}
if (myUncommittedDocuments.isEmpty()) {
- if (!ApplicationManager.getApplication().hasWriteAction(CommitToPsiFileAction.class)) {
+ if (!isCommitInProgress()) {
// in case of fireWriteActionFinished() we didn't execute 'actionsWhenAllDocumentsAreCommitted' yet
assert actionsWhenAllDocumentsAreCommitted.isEmpty() : actionsWhenAllDocumentsAreCommitted;
}
@@ -300,12 +302,18 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
@NotNull final Object reason) {
assert !myProject.isDisposed() : "Already disposed";
final boolean[] ok = {true};
- ApplicationManager.getApplication().runWriteAction(new CommitToPsiFileAction(document, myProject) {
+ Runnable runnable = new DocumentRunnable(document, myProject) {
@Override
public void run() {
ok[0] = finishCommitInWriteAction(document, finishProcessors, synchronously);
}
- });
+ };
+ if (synchronously) {
+ runnable.run();
+ }
+ else {
+ ApplicationManager.getApplication().runWriteAction(runnable);
+ }
if (ok[0]) {
// otherwise changes maybe not synced to the document yet, and injectors will crash
@@ -408,7 +416,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
}
};
- if (Boolean.TRUE.equals(psiFile.getViewProvider().getVirtualFile().getUserData(SingleRootFileViewProvider.FREE_THREADED))) {
+ if (isFreeThreaded(psiFile.getViewProvider().getVirtualFile())) {
runnable.run();
}
else {
@@ -416,6 +424,14 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
}
}
+ private static boolean isFreeThreaded(@NotNull VirtualFile file) {
+ return Boolean.TRUE.equals(file.getUserData(SingleRootFileViewProvider.FREE_THREADED));
+ }
+
+ public boolean isCommitInProgress() {
+ return myIsCommitInProgress;
+ }
+
@Override
public T commitAndRunReadAction(@NotNull final Computable computation) {
final Ref ref = Ref.create(null);
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
index 5c34ed2c4b95..391df3ab683d 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
@@ -209,7 +209,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter {
}
public boolean toProcessPsiEvent() {
- return !myIgnorePsiEvents && !ApplicationManager.getApplication().hasWriteAction(IgnorePsiEventsMarker.class);
+ return !myIgnorePsiEvents && !myPsiDocumentManager.isCommitInProgress() && !ApplicationManager.getApplication().hasWriteAction(IgnorePsiEventsMarker.class);
}
@TestOnly
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java
index acfd41c2e9c4..55f0c1fa07ff 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/ex/DefaultColorSchemesManager.java
@@ -18,6 +18,9 @@ package com.intellij.openapi.editor.colors.ex;
import com.intellij.openapi.components.*;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme;
+import com.intellij.openapi.editor.colors.impl.EmptyColorScheme;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -26,6 +29,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
+import static com.intellij.openapi.editor.colors.impl.AbstractColorsScheme.NAME_ATTR;
+
@State(
name = "DefaultColorSchemesManager",
defaultStateAsResource = true,
@@ -51,25 +56,24 @@ public class DefaultColorSchemesManager implements PersistentStateComponent> content = presentation.getContent();
Map problems = presentation.getProblemElements();
- appendToolNodeContent(context, toolNode, parentNode, showStructure, content, problems, null);
+ appendToolNodeContent(context, toolNode, parentNode, showStructure, content, problems);
}
public abstract void appendToolNodeContent(@NotNull GlobalInspectionContextImpl context,
@@ -118,8 +118,7 @@ public abstract class InspectionRVContentProvider {
@NotNull InspectionTreeNode parentNode,
final boolean showStructure,
@NotNull Map> contents,
- @NotNull Map problems,
- @Nullable final DefaultTreeModel model);
+ @NotNull Map problems);
protected abstract void appendDescriptor(@NotNull GlobalInspectionContextImpl context,
@NotNull InspectionToolWrapper toolWrapper,
@@ -315,7 +314,7 @@ public abstract class InspectionRVContentProvider {
}
@SuppressWarnings({"ConstantConditions"}) //class cast suppression
- protected static void merge(@Nullable DefaultTreeModel model, InspectionTreeNode child, InspectionTreeNode parent, boolean merge) {
+ protected static void merge(InspectionTreeNode child, InspectionTreeNode parent, boolean merge) {
if (merge) {
for (int i = 0; i < parent.getChildCount(); i++) {
InspectionTreeNode current = (InspectionTreeNode)parent.getChildAt(i);
@@ -324,35 +323,31 @@ public abstract class InspectionRVContentProvider {
}
if (current instanceof InspectionPackageNode) {
if (((InspectionPackageNode)current).getPackageName().compareTo(((InspectionPackageNode)child).getPackageName()) == 0) {
- processDepth(model, child, current);
+ processDepth(child, current);
return;
}
}
else if (current instanceof RefElementNode) {
if (((RefElementNode)current).getElement().getName().compareTo(((RefElementNode)child).getElement().getName()) == 0 &&
((RefElementNode)current).getElement().getQualifiedName().compareTo(((RefElementNode)child).getElement().getQualifiedName()) == 0) {
- processDepth(model, child, current);
+ processDepth(child, current);
return;
}
}
else if (current instanceof InspectionNode) {
if (((InspectionNode)current).getToolWrapper().getShortName().compareTo(((InspectionNode)child).getToolWrapper().getShortName()) == 0) {
- processDepth(model, child, current);
+ processDepth(child, current);
return;
}
}
else if (current instanceof InspectionModuleNode) {
if (((InspectionModuleNode)current).getName().compareTo(((InspectionModuleNode)child).getName()) == 0) {
- processDepth(model, child, current);
+ processDepth(child, current);
return;
}
}
}
}
- add(model, child, parent);
- }
-
- protected static void add(@Nullable final DefaultTreeModel model, final InspectionTreeNode child, final InspectionTreeNode parent) {
insertByIndex(child, parent);
}
@@ -367,13 +362,13 @@ public abstract class InspectionRVContentProvider {
parent.insert(child, -i -1);
}
- private static void processDepth(@Nullable DefaultTreeModel model, final InspectionTreeNode child, final InspectionTreeNode current) {
+ private static void processDepth(final InspectionTreeNode child, final InspectionTreeNode current) {
InspectionTreeNode[] children = new InspectionTreeNode[child.getChildCount()];
for (int i = 0; i < children.length; i++) {
children[i] = (InspectionTreeNode)child.getChildAt(i);
}
for (InspectionTreeNode node : children) {
- merge(model, node, current, true);
+ merge(node, current, true);
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java
index ccbe14779db1..221af1f72403 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionRVContentProviderImpl.java
@@ -93,8 +93,7 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
@NotNull final InspectionTreeNode parentNode,
final boolean showStructure,
@NotNull final Map> contents,
- @NotNull final Map problems,
- DefaultTreeModel model) {
+ @NotNull final Map problems) {
final InspectionToolWrapper toolWrapper = toolNode.getToolWrapper();
Function> computeContainer = new Function>() {
@@ -114,7 +113,7 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
entities.addAll(moduleProblems);
}
buildTree(context, contents, false, toolWrapper, computeContainer, showStructure, node -> {
- merge(model, node, toolNode, true);
+ merge(node, toolNode, true);
});
if (presentation.isOldProblemsIncluded()) {
@@ -127,10 +126,10 @@ public class InspectionRVContentProviderImpl extends InspectionRVContentProvider
};
buildTree(context, presentation.getOldContent(), true, toolWrapper, computeContainer, showStructure, node -> {
- merge(model, node, toolNode, true);
+ merge(node, toolNode, true);
});
}
- merge(model, toolNode, parentNode, false);
+ merge(toolNode, parentNode, false);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineInspectionRVContentProvider.java b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineInspectionRVContentProvider.java
index b76f021f48c8..c074f366a8c4 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineInspectionRVContentProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineInspectionRVContentProvider.java
@@ -113,8 +113,7 @@ public class OfflineInspectionRVContentProvider extends InspectionRVContentProvi
@NotNull final InspectionTreeNode parentNode,
final boolean showStructure,
@NotNull final Map> contents,
- @NotNull final Map problems,
- final DefaultTreeModel model) {
+ @NotNull final Map problems) {
InspectionToolWrapper toolWrapper = toolNode.getToolWrapper();
final Map> filteredContent = getFilteredContent(context, toolWrapper);
if (filteredContent != null && !filteredContent.values().isEmpty()) {
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
index 089651efa15d..91a447042951 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
@@ -52,7 +52,6 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import javax.swing.tree.DefaultTreeModel;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
@@ -262,8 +261,8 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
content.add(refElement);
view.getProvider().appendToolNodeContent(context, toolNode,
- (InspectionTreeNode)toolNode.getParent(), context.getUIOptions().SHOW_STRUCTURE,
- contents, problems, (DefaultTreeModel)view.getTree().getModel());
+ (InspectionTreeNode)toolNode.getParent(), context.getUIOptions().SHOW_STRUCTURE,
+ contents, problems);
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleManagerComponent.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleManagerComponent.java
index 29bc57a56508..be5f57eb7291 100644
--- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleManagerComponent.java
+++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleManagerComponent.java
@@ -19,8 +19,7 @@ import com.intellij.ProjectTopics;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.*;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.diagnostic.Logger;
@@ -126,26 +125,15 @@ public class ModuleManagerComponent extends ModuleManagerImpl {
return;
}
- Runnable runnableWithProgress = new Runnable() {
- @Override
- public void run() {
- for (final Module module : myModuleModel.myModules.values()) {
- final Application app = ApplicationManager.getApplication();
- final Runnable swingRunnable = new Runnable() {
- @Override
- public void run() {
- fireModuleAddedInWriteAction(module);
- }
- };
- ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator();
- app.invokeAndWait(swingRunnable, pi.getModalityState());
- }
+ Runnable runnableWithProgress = () -> {
+ for (final Module module : myModuleModel.myModules.values()) {
+ TransactionGuard.getInstance().submitTransactionAndWait(TransactionKind.ANY_CHANGE, () -> fireModuleAddedInWriteAction(module));
}
};
ProgressIndicator progressIndicator = myProgressManager.getProgressIndicator();
if (progressIndicator == null) {
- myProgressManager.runProcessWithProgressSynchronously(runnableWithProgress, "Initializing modules...", false, myProject);
+ myProgressManager.runProcessWithProgressSynchronously(runnableWithProgress, "Initializing Modules...", false, myProject);
}
else {
runnableWithProgress.run();
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java
index 9ae229776484..47f392063e59 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdaterImpl.java
@@ -22,6 +22,7 @@ package com.intellij.openapi.roots.impl;
import com.intellij.ProjectTopics;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionException;
import com.intellij.openapi.extensions.Extensions;
@@ -49,7 +50,6 @@ import com.intellij.ui.GuiUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.indexing.FileBasedIndexProjectHandler;
-import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -408,20 +408,17 @@ public class PushedFilePropertiesUpdaterImpl extends PushedFilePropertiesUpdater
private static void reloadPsi(final VirtualFile file, final Project project) {
final FileManagerImpl fileManager = (FileManagerImpl)((PsiManagerEx)PsiManager.getInstance(project)).getFileManager();
if (fileManager.findCachedViewProvider(file) != null) {
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- if (project.isDisposed()) {
- return;
- }
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- fileManager.forceReload(file);
- }
- });
+ Runnable runnable = () -> {
+ if (project.isDisposed()) {
+ return;
}
- });
+ ApplicationManager.getApplication().runWriteAction(() -> fileManager.forceReload(file));
+ };
+ if (ApplicationManager.getApplication().isDispatchThread()) {
+ runnable.run();
+ } else {
+ TransactionGuard.submitTransaction(runnable);
+ }
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
index d60418926487..51c34633c526 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
@@ -136,7 +136,9 @@ public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements Se
protected boolean finishCommitInWriteAction(@NotNull Document document,
@NotNull List> finishProcessors,
boolean synchronously) {
- EditorWindowImpl.disposeInvalidEditors(); // in write action
+ if (ApplicationManager.getApplication().isWriteAccessAllowed()) { // can be false for non-physical PSI
+ EditorWindowImpl.disposeInvalidEditors();
+ }
return super.finishCommitInWriteAction(document, finishProcessors, synchronously);
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
index 7ae45e2d7b05..10ba085f3e92 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
@@ -23,6 +23,7 @@ import com.intellij.ide.IdeBundle;
import com.intellij.ide.caches.FileContent;
import com.intellij.ide.startup.StartupManagerEx;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.TransactionGuard;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileTypeManager;
@@ -80,15 +81,10 @@ public class FileBasedIndexProjectHandler extends AbstractProjectComponent imple
public void run() {
PushedFilePropertiesUpdater.getInstance(project).initializeProperties();
- // dumb mode should start before post-startup activities
- // only when queueTask is called from UI thread, we can guarantee that
- // when the method returns, the application has entered dumb mode
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- if (!project.isDisposed() && FileBasedIndex.getInstance() instanceof FileBasedIndexImpl) {
- DumbService.getInstance(project).queueTask(new UnindexedFilesUpdater(project, true));
- }
+ // schedule dumb mode start after the read action we're currently in
+ TransactionGuard.submitTransaction(() -> {
+ if (!project.isDisposed() && FileBasedIndex.getInstance() instanceof FileBasedIndexImpl) {
+ DumbService.getInstance(project).queueTask(new UnindexedFilesUpdater(project, true));
}
});
diff --git a/platform/platform-api/src/com/intellij/util/ui/Animator.java b/platform/platform-api/src/com/intellij/util/ui/Animator.java
index 67156c25fe57..6259307949d0 100644
--- a/platform/platform-api/src/com/intellij/util/ui/Animator.java
+++ b/platform/platform-api/src/com/intellij/util/ui/Animator.java
@@ -19,20 +19,15 @@ package com.intellij.util.ui;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.util.concurrency.AppExecutorUtil;
+import com.intellij.util.concurrency.EdtExecutorService;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import java.awt.*;
-import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
public abstract class Animator implements Disposable {
- // allow only one animation run at a time
- private final ScheduledExecutorService scheduler = AppExecutorUtil.createBoundedScheduledExecutorService(1);
-
private final String myName;
private final int myTotalFrames;
private final int myCycleDuration;
@@ -147,20 +142,10 @@ public abstract class Animator implements Disposable {
animationDone();
}
else if (myTicker == null) {
- myTicker = scheduler.scheduleWithFixedDelay(new Runnable() {
- private final AtomicBoolean scheduled = new AtomicBoolean(false);
-
+ myTicker = EdtExecutorService.getScheduledExecutorInstance().scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
- if (scheduled.compareAndSet(false, true) && !isDisposed()) {
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- scheduled.set(false);
- onTick();
- }
- });
- }
+ onTick();
}
@Override
@@ -183,8 +168,8 @@ public abstract class Animator implements Disposable {
@Override
public void dispose() {
- myDisposed = true;
stopTicker();
+ myDisposed = true;
}
public boolean isRunning() {
diff --git a/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java b/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java
index c03f12f5e6b3..c18de5266b3a 100644
--- a/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java
+++ b/platform/platform-impl/src/com/intellij/internal/ToggleDumbModeAction.java
@@ -15,12 +15,12 @@
*/
package com.intellij.internal;
-import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.application.WrapInTransaction;
import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.DumbModeTask;
import com.intellij.openapi.project.DumbServiceImpl;
import com.intellij.openapi.project.Project;
@@ -30,7 +30,8 @@ import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
-public class ToggleDumbModeAction extends AnAction implements DumbAware {
+@WrapInTransaction
+public class ToggleDumbModeAction extends DumbAwareAction {
private volatile boolean myDumb = false;
public void actionPerformed(final AnActionEvent e) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
index 1f9f0fcd1ded..235164eef87a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
@@ -308,12 +308,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
}
}
}
- runWriteAction(new Runnable() {
- @Override
- public void run() {
- Disposer.dispose(ApplicationImpl.this);
- }
- });
+ TransactionGuard.syncTransaction(TransactionKind.ANY_CHANGE, () -> runWriteAction(() -> Disposer.dispose(this)));
Disposer.assertIsEmpty();
return true;
@@ -376,6 +371,11 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
@Override
public Future> executeOnPooledThread(@NotNull final Runnable action) {
return ourThreadExecutorsService.submit(new Runnable() {
+ @Override
+ public String toString() {
+ return action.toString();
+ }
+
@Override
public void run() {
assert !isReadAccessAllowed(): describe(Thread.currentThread());
@@ -864,7 +864,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
}
private boolean doExit(boolean allowListenersToCancel, boolean restart) {
- saveSettings();
+ TransactionGuard.syncTransaction(TransactionKind.ANY_CHANGE, this::saveSettings);
if (allowListenersToCancel && !canExit()) {
return false;
@@ -1230,8 +1230,8 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
assertIsDispatchThread(getStatus(), "Write access is allowed from event dispatch thread only");
HeavyProcessLatch.INSTANCE.stopThreadPrioritizing(); // let non-cancellable read actions complete faster, if present
if (!TransactionGuard.getInstance().isInsideTransaction() && Registry.is("ide.require.transaction.for.model.changes", false)) {
+ // please assign exceptions that occur here to Peter
LOG.error("Write access is allowed from model transactions only, see TransactionGuard documentation for details");
- //todo throw new IllegalStateException("Write access is allowed from model transactions only, see TransactionGuard documentation for details");
}
boolean writeActionPending = myWriteActionPending;
myWriteActionPending = true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
index 229be3ac32a7..16f53f44e9f2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
@@ -51,9 +51,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.URL;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
+import java.util.*;
@State(
name = "EditorColorsManagerImpl",
@@ -233,8 +231,7 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Pers
@NotNull
@Override
public EditorColorsScheme[] getAllSchemes() {
- List schemes = mySchemeManager.getAllSchemes();
- EditorColorsScheme[] result = schemes.toArray(new EditorColorsScheme[schemes.size()]);
+ EditorColorsScheme[] result = getAllVisibleSchemes(mySchemeManager.getAllSchemes());
Arrays.sort(result, new Comparator() {
@Override
public int compare(@NotNull EditorColorsScheme s1, @NotNull EditorColorsScheme s2) {
@@ -248,6 +245,16 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Pers
return result;
}
+ private static EditorColorsScheme[] getAllVisibleSchemes(@NotNull Collection schemes) {
+ List visibleSchemes = new ArrayList<>(schemes.size() - 1);
+ for (EditorColorsScheme scheme : schemes) {
+ if (!(scheme instanceof EmptyColorScheme)) {
+ visibleSchemes.add(scheme);
+ }
+ }
+ return visibleSchemes.toArray(new EditorColorsScheme[visibleSchemes.size()]);
+ }
+
@Override
public void setGlobalScheme(@Nullable EditorColorsScheme scheme) {
mySchemeManager.setCurrent(scheme == null ? getDefaultScheme() : scheme);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
index 24f9196ea939..aa8ed9369eda 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
@@ -31,6 +31,7 @@ import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.dnd.*;
import com.intellij.ide.ui.customization.CustomActionsSchema;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.diagnostic.Logger;
@@ -1570,13 +1571,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
: renderer.getClickAction();
}
if (clickAction != null) {
- if (checkDumbAware(clickAction)) {
- performAction(clickAction, e, "ICON_NAVIGATION", myEditor.getDataContext());
- repaint();
- }
- else {
- notifyNotDumbAware();
- }
+ performAction(clickAction, e, "ICON_NAVIGATION", myEditor.getDataContext());
+ repaint();
e.consume();
}
else {
@@ -1608,7 +1604,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
private static void performAction(@NotNull AnAction action, @NotNull InputEvent e, @NotNull String place, @NotNull DataContext context) {
AnActionEvent actionEvent = AnActionEvent.createFromAnAction(action, e, place, context);
action.update(actionEvent);
- if (actionEvent.getPresentation().isEnabledAndVisible()) action.actionPerformed(actionEvent);
+ if (actionEvent.getPresentation().isEnabledAndVisible()) {
+ ActionUtil.performActionDumbAware(action, actionEvent);
+ }
}
@Nullable
@@ -1778,11 +1776,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
else {
AnAction rightButtonAction = renderer.getRightButtonClickAction();
if (rightButtonAction != null) {
- if (checkDumbAware(rightButtonAction)) {
- performAction(rightButtonAction, e, "ICON_NAVIGATION_SECONDARY_BUTTON", myEditor.getDataContext());
- } else {
- notifyNotDumbAware();
- }
+ performAction(rightButtonAction, e, "ICON_NAVIGATION_SECONDARY_BUTTON", myEditor.getDataContext());
e.consume();
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
index d56a23d4e629..a93c5b26c189 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.hint.DocumentFragmentTooltipRenderer;
import com.intellij.codeInsight.hint.EditorFragmentComponent;
import com.intellij.codeInsight.hint.TooltipController;
import com.intellij.codeInsight.hint.TooltipGroup;
-import com.intellij.concurrency.JobScheduler;
import com.intellij.diagnostic.Dumpable;
import com.intellij.diagnostic.LogMessageEx;
import com.intellij.ide.*;
@@ -31,8 +30,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.actionSystem.impl.MouseGestureManager;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.*;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.diagnostic.Logger;
@@ -75,6 +73,7 @@ import com.intellij.ui.components.JBLayeredPane;
import com.intellij.ui.components.JBScrollBar;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.*;
+import com.intellij.util.concurrency.EdtExecutorService;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.messages.MessageBusConnection;
@@ -990,8 +989,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (event.isConsumed()) {
return;
}
- if (processKeyTyped(event)) {
- event.consume();
+ try (AccessToken ignored = TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.TEXT_EDITING)) {
+ if (processKeyTyped(event)) {
+ event.consume();
+ }
}
}
@@ -4685,7 +4686,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (mySchedulerHandle != null) {
mySchedulerHandle.cancel(false);
}
- mySchedulerHandle = JobScheduler.getScheduler().scheduleWithFixedDelay(this, mySleepTime, mySleepTime, TimeUnit.MILLISECONDS);
+ mySchedulerHandle = EdtExecutorService.getScheduledExecutorInstance().scheduleWithFixedDelay(this, mySleepTime, mySleepTime, TimeUnit.MILLISECONDS);
}
private void setBlinkPeriod(int blinkPeriod) {
@@ -4716,7 +4717,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
if (toRepaint) {
- SwingUtilities.invokeLater(myRepaintRunnable);
+ activeCursor.repaint();
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java
index f6f39c1fcd08..3deb5359fdb1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java
@@ -556,7 +556,7 @@ public class ActionsTreeUtil {
final Shortcut[] actionShortcuts =
keymap.getShortcuts(action instanceof ActionStub ? ((ActionStub)action).getId() : actionManager.getId(action));
for (Shortcut actionShortcut : actionShortcuts) {
- if (shortcut.equals(actionShortcut)) {
+ if (actionShortcut != null && actionShortcut.startsWith(shortcut)) {
return true;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
index a1d1cc15b81e..a91b046ae8e6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
@@ -18,10 +18,7 @@ package com.intellij.openapi.project;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.startup.StartupManagerEx;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.AccessToken;
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.*;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
@@ -188,7 +185,7 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica
return;
}
- UIUtil.invokeLaterIfNeeded(new Runnable() {
+ Runnable runnable = new Runnable() {
@Override
public void run() {
if (myProject.isDisposed()) {
@@ -251,7 +248,13 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica
}, ModalityState.any(), myProject.getDisposed());
}
}
- });
+ };
+ if (application.isDispatchThread()) {
+ runnable.run();
+ } else {
+ //noinspection SSBasedInspection
+ SwingUtilities.invokeLater(() -> TransactionGuard.submitTransaction(runnable));
+ }
}
@Nullable
@@ -530,16 +533,25 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica
private static void invokeAndWaitIfNeeded(Runnable runnable) {
if (ApplicationManager.getApplication().isDispatchThread()) {
runnable.run();
+ return;
}
- else {
- try {
- SwingUtilities.invokeAndWait(runnable);
- }
- catch (InterruptedException ignore) {
- }
- catch (Exception e) {
- LOG.error(e);
- }
+
+ Semaphore semaphore = new Semaphore();
+ semaphore.down();
+ //todo remove invokeLater when transactions are executed in "any" modality state
+ //noinspection SSBasedInspection
+ SwingUtilities.invokeLater(
+ () -> TransactionGuard.getInstance().submitMergeableTransaction(TransactionKind.ANY_CHANGE, () -> {
+ try {
+ runnable.run();
+ } finally {
+ semaphore.up();
+ }
+ }));
+ try {
+ semaphore.waitFor();
+ }
+ catch (ProcessCanceledException ignore) {
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
index 03fd13d40ca8..0ad16a520d7e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java
@@ -28,10 +28,7 @@ import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.NotificationsManager;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ApplicationNamesInfo;
-import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.*;
import com.intellij.openapi.components.impl.stores.StorageUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -351,9 +348,8 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable {
}
fireProjectOpened(project);
- DumbService.allowStartingDumbModeInside(DumbModePermission.MAY_START_BACKGROUND, new Runnable() {
- @Override
- public void run() {
+ try (AccessToken ignored = TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.ANY_CHANGE)) {
+ DumbService.allowStartingDumbModeInside(DumbModePermission.MAY_START_BACKGROUND, () ->
DumbService.getInstance(project).queueTask(new DumbModeTask() {
@Override
public void performInDumbMode(@NotNull ProgressIndicator indicator) {
@@ -364,9 +360,9 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable {
public String toString() {
return "wait for file watcher";
}
- });
- }
- });
+ })
+ );
+ }
final StartupManagerImpl startupManager = (StartupManagerImpl)StartupManager.getInstance(project);
boolean ok = myProgressManager.runProcessWithProgressSynchronously(new Runnable() {
@@ -374,15 +370,10 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable {
public void run() {
startupManager.runStartupActivities();
- // dumb mode should start before post-startup activities
- // only when startCacheUpdate is called from UI thread, we can guarantee that
- // when the method returns, the application has entered dumb mode
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override
- public void run() {
- startupManager.startCacheUpdate();
- }
- });
+ // Startup activities (e.g. the one in FileBasedIndexProjectHandler) have scheduled dumb mode to begin "later"
+ // Now we schedule-and-wait to the same event queue to guarantee that the dumb mode really begins now:
+ // Post-startup activities should not ever see unindexed and at the same time non-dumb state
+ TransactionGuard.getInstance().submitTransactionAndWait(TransactionKind.ANY_CHANGE, startupManager::startCacheUpdate);
startupManager.runPostStartupActivitiesFromExtensions();
@@ -615,7 +606,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable {
if (checkCanClose && !canClose(project)) return false;
final ShutDownTracker shutDownTracker = ShutDownTracker.getInstance();
shutDownTracker.registerStopperThread(Thread.currentThread());
- try {
+ try (AccessToken ignored = TransactionGuard.getInstance().startSynchronousTransaction(TransactionKind.ANY_CHANGE)) {
if (save) {
FileDocumentManager.getInstance().saveAllDocuments();
project.save();
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
index 3e50443a24cd..1217a56b7ca1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
@@ -37,6 +37,7 @@ import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt;
import com.intellij.reference.SoftReference;
import com.intellij.ui.FocusTrackback;
+import com.intellij.util.concurrency.EdtExecutorService;
import com.intellij.util.containers.WeakValueHashMap;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntIntHashMap;
@@ -56,6 +57,7 @@ import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
+import java.util.concurrent.TimeUnit;
public class FocusManagerImpl extends IdeFocusManager implements Disposable {
private static final Logger LOG = Logger.getInstance(FocusManagerImpl.class);
@@ -85,8 +87,6 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
private final EdtAlarm myFocusedComponentAlarm;
private final EdtAlarm myForcedFocusRequestsAlarm;
- private final SimpleTimer myTimer = SimpleTimer.newInstance("FocusManager timer");
-
private final EdtAlarm myIdleAlarm;
private final Set myIdleRequests = new LinkedHashSet();
@@ -1040,7 +1040,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
}
- class EdtAlarm {
+ static class EdtAlarm {
private final Set myRequests = new HashSet();
public void cancelAllRequests() {
@@ -1052,7 +1052,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
public void addRequest(@NotNull EdtRunnable runnable, int delay) {
myRequests.add(runnable);
- myTimer.setUp(runnable, delay);
+ EdtExecutorService.getScheduledExecutorInstance().schedule(runnable, delay, TimeUnit.MILLISECONDS);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ClockPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ClockPanel.java
index 2378df42bc5d..1d109f616757 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ClockPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ClockPanel.java
@@ -15,8 +15,7 @@
*/
package com.intellij.openapi.wm.impl.status;
-import com.intellij.concurrency.JobScheduler;
-import com.intellij.util.ui.UIUtil;
+import com.intellij.util.concurrency.EdtExecutorService;
import javax.swing.*;
import java.awt.*;
@@ -71,12 +70,7 @@ public class ClockPanel extends JComponent {
myScheduledFuture.cancel(false);
}
myCalendar.setTimeInMillis(System.currentTimeMillis());
- myScheduledFuture = JobScheduler.getScheduler().schedule(new Runnable() {
- @Override
- public void run() {
- UIUtil.invokeLaterIfNeeded(myRepaintRunnable);
- }
- }, 60 - myCalendar.get(SECOND), TimeUnit.SECONDS);
+ myScheduledFuture = EdtExecutorService.getScheduledExecutorInstance().schedule(myRepaintRunnable, 60 - myCalendar.get(SECOND), TimeUnit.SECONDS);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java
index 50fc3c30e69c..724e2f43496e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java
@@ -15,7 +15,6 @@
*/
package com.intellij.openapi.wm.impl.status;
-import com.intellij.concurrency.JobScheduler;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.wm.CustomStatusBarWidget;
import com.intellij.openapi.wm.StatusBar;
@@ -23,6 +22,7 @@ import com.intellij.openapi.wm.StatusBarWidget;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.ui.UIBundle;
+import com.intellij.util.concurrency.EdtExecutorService;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.Activatable;
@@ -75,13 +75,8 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
@Override
public void showNotify() {
- myFuture = JobScheduler.getScheduler().scheduleWithFixedDelay(new Runnable() {
- public void run() {
- if (isDisplayable()) {
- updateState();
- }
- }
- }, 1, 5, TimeUnit.SECONDS);
+ myFuture = EdtExecutorService.getScheduledExecutorInstance().scheduleWithFixedDelay(MemoryUsagePanel.this::updateState,
+ 1, 5, TimeUnit.SECONDS);
}
@Override
@@ -231,12 +226,9 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
if (total != myLastTotal || used != myLastUsed) {
myLastTotal = total;
myLastUsed = used;
- //noinspection SSBasedInspection
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- myBufferedImage = null;
- repaint();
- }
+ UIUtil.invokeLaterIfNeeded(() -> {
+ myBufferedImage = null;
+ repaint();
});
setToolTipText(UIBundle.message("memory.usage.panel.statistics.message", total, used));
diff --git a/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java b/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java
index e9f5629de441..89cb0d6f4b77 100644
--- a/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java
@@ -660,4 +660,43 @@ public class PsiDocumentManagerImplTest extends PlatformTestCase {
System.out.println("i = " + i);
}
}
+
+ public void testCommitNonPhysicalPsiWithoutWriteAction() throws IOException {
+ assertFalse(ApplicationManager.getApplication().isWriteAccessAllowed());
+
+ PsiFile original = getPsiManager().findFile(getVirtualFile(createTempFile("X.txt", "")));
+ assertNotNull(original);
+ assertTrue(original.getViewProvider().isEventSystemEnabled());
+
+ long modCount = getPsiManager().getModificationTracker().getModificationCount();
+
+ PsiFile copy = (PsiFile)original.copy();
+ assertFalse(copy.getViewProvider().isEventSystemEnabled());
+
+ Document document = copy.getViewProvider().getDocument();
+ assertNotNull(document);
+ document.setText("class A{}");
+
+ PsiDocumentManager.getInstance(myProject).commitDocument(document);
+ assertEquals(modCount, getPsiManager().getModificationTracker().getModificationCount());
+ assertEquals(document.getText(), copy.getText());
+ assertTrue(PsiDocumentManager.getInstance(myProject).isCommitted(document));
+ }
+
+ public void testCommitNonPhysicalCopyOnPerformWhenAllCommitted() throws Exception {
+ assertFalse(ApplicationManager.getApplication().isWriteAccessAllowed());
+
+ PsiFile original = getPsiManager().findFile(getVirtualFile(createTempFile("X.txt", "")));
+ assertNotNull(original);
+ PsiFile copy = (PsiFile)original.copy();
+ assertEquals("", copy.getText());
+ Document document = copy.getViewProvider().getDocument();
+ assertNotNull(document);
+
+ document.setText("class A{}");
+ PsiDocumentManager.getInstance(myProject).performWhenAllCommitted(() -> assertEquals(document.getText(), copy.getText()));
+ DocumentCommitThread.getInstance().waitForAllCommits();
+ assertTrue(PsiDocumentManager.getInstance(myProject).isCommitted(document));
+ }
+
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictTracker.java
index 6dcdac914ac1..37608fe89e8d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictTracker.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictTracker.java
@@ -26,7 +26,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.ZipperUpdater;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FileStatusManager;
@@ -34,6 +33,7 @@ import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotifications;
+import com.intellij.util.Alarm;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
@@ -79,26 +79,18 @@ public class ChangelistConflictTracker {
myCheckSet = new HashSet();
final Application application = ApplicationManager.getApplication();
- final ZipperUpdater zipperUpdater = new ZipperUpdater(300, myProject);
- final Runnable runnable = new Runnable() {
- @Override
- public void run() {
- if (application.runReadAction(new Computable() {
- @Override
- public Boolean compute() {
- return application.isDisposed() || myProject.isDisposed() || !myProject.isOpen();
- }
- })) {
- return;
- }
- final Set localSet;
- synchronized (myCheckSetLock) {
- localSet = new HashSet();
- localSet.addAll(myCheckSet);
- myCheckSet.clear();
- }
- checkFiles(localSet);
+ final ZipperUpdater zipperUpdater = new ZipperUpdater(300, Alarm.ThreadToUse.SWING_THREAD, myProject);
+ final Runnable runnable = () -> {
+ if (application.isDisposed() || myProject.isDisposed() || !myProject.isOpen()) {
+ return;
}
+ final Set localSet;
+ synchronized (myCheckSetLock) {
+ localSet = new HashSet();
+ localSet.addAll(myCheckSet);
+ myCheckSet.clear();
+ }
+ checkFiles(localSet);
};
myDocumentListener = new DocumentAdapter() {
@Override
diff --git a/xml/tests/testData/completion/9.xml b/xml/tests/testData/completion/9.xml
deleted file mode 100644
index d7bca4b35741..000000000000
--- a/xml/tests/testData/completion/9.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
\ No newline at end of file