summaryrefslogtreecommitdiff
path: root/platform/core-impl
diff options
context:
space:
mode:
Diffstat (limited to 'platform/core-impl')
-rw-r--r--platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java6
-rw-r--r--platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java79
-rw-r--r--platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java73
-rw-r--r--platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java58
-rw-r--r--platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java5
-rw-r--r--platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java59
-rw-r--r--platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java2
-rw-r--r--platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java17
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java2
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java8
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java9
-rw-r--r--platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java3
-rw-r--r--platform/core-impl/src/com/intellij/psi/text/BlockSupport.java2
13 files changed, 162 insertions, 161 deletions
diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
index 7f04b192c640..633c25a0145a 100644
--- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
+++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
@@ -68,10 +68,8 @@ import org.picocontainer.MutablePicoContainer;
import java.lang.reflect.Modifier;
import java.util.List;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
/**
* @author yole
@@ -210,12 +208,12 @@ public class CoreApplicationEnvironment {
}
@Override
- public Object get() throws InterruptedException, ExecutionException {
+ public Object get() {
return null;
}
@Override
- public Object get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ public Object get(long timeout, @NotNull TimeUnit unit) {
return null;
}
});
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java
deleted file mode 100644
index a6b957c0c508..000000000000
--- a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java
+++ /dev/null
@@ -1,79 +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.ide.plugins;
-
-import com.intellij.openapi.extensions.PluginId;
-import com.intellij.util.containers.HashMap;
-import gnu.trove.TObjectIntHashMap;
-
-import java.util.Comparator;
-import java.util.Map;
-import java.util.Stack;
-
-/**
- * @author Eugene Zhuravlev
- * Date: Aug 3, 2004
- */
-public class PluginDescriptorComparator implements Comparator<IdeaPluginDescriptor>{
- private final TObjectIntHashMap<PluginId> myIdToNumberMap = new TObjectIntHashMap<PluginId>();
- private int myAvailableNumber = 1;
-
- public PluginDescriptorComparator(IdeaPluginDescriptor[] descriptors){
- final Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap = new HashMap<PluginId, IdeaPluginDescriptor>();
- for (final IdeaPluginDescriptor descriptor : descriptors) {
- idToDescriptorMap.put(descriptor.getPluginId(), descriptor);
- }
- myIdToNumberMap.put(PluginId.getId(PluginManagerCore.CORE_PLUGIN_ID), 0);
-
- final Stack<PluginId> visited = new Stack<PluginId>();
- for (int idx = 0; idx < descriptors.length && myIdToNumberMap.size() != descriptors.length; idx++) {
- assignNumbers(descriptors[idx].getPluginId(), idToDescriptorMap, visited);
- visited.clear();
- }
- }
-
- private void assignNumbers(PluginId id, Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap, Stack<PluginId> visited){
- visited.push(id);
- try {
- final IdeaPluginDescriptor ideaPluginDescriptor = idToDescriptorMap.get(id);
- if (ideaPluginDescriptor == null || !ideaPluginDescriptor.isEnabled()) {
- // missing optional dependency or already disabled due to cycles
- return;
- }
- final PluginId[] parentIds = ideaPluginDescriptor.getDependentPluginIds();
- for (final PluginId parentId : parentIds) {
- if (visited.contains(parentId)) {
- //disable plugins in the cycle
- ideaPluginDescriptor.setEnabled(false);
- break;
- }
- }
- for (PluginId parentId1 : parentIds) {
- assignNumbers(parentId1, idToDescriptorMap, visited);
- }
- if (!myIdToNumberMap.contains(id)) {
- myIdToNumberMap.put(id, myAvailableNumber++);
- }
- }
- finally {
- visited.pop();
- }
- }
-
- public int compare(IdeaPluginDescriptor d1, IdeaPluginDescriptor d2) {
- return myIdToNumberMap.get(d1.getPluginId()) - myIdToNumberMap.get(d2.getPluginId());
- }
-}
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
index 8f4fd771ebdd..e834e33f0f42 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
@@ -30,10 +30,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.io.ZipFileCache;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
-import com.intellij.util.PlatformUtilsCore;
-import com.intellij.util.ReflectionUtil;
+import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.execution.ParametersListUtil;
@@ -43,6 +40,7 @@ import com.intellij.util.graph.Graph;
import com.intellij.util.graph.GraphGenerator;
import com.intellij.util.xmlb.XmlSerializationException;
import gnu.trove.THashMap;
+import gnu.trove.TIntProcedure;
import org.jdom.Document;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -498,26 +496,38 @@ public class PluginManagerCore {
}
}
- @Deprecated
- static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) {
+ static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(final Map<PluginId, ? extends IdeaPluginDescriptor> idToDescriptorMap) {
final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap);
final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph);
- /*
if (!builder.isAcyclic()) {
- final Pair<String,String> circularDependency = builder.getCircularDependency();
- throw new Exception("Cyclic dependencies between plugins are not allowed: \"" + circularDependency.getFirst() + "\" and \"" + circularDependency.getSecond() + "");
+ builder.getSCCs().forEach(new TIntProcedure() {
+ int myTNumber = 0;
+ public boolean execute(int size) {
+ if (size > 1) {
+ for (int j = 0; j < size; j++) {
+ idToDescriptorMap.get(builder.getNodeByTNumber(myTNumber + j)).setEnabled(false);
+ }
+ }
+ myTNumber += size;
+ return true;
+ }
+ });
}
- */
+
final Comparator<PluginId> idComparator = builder.comparator();
return new Comparator<IdeaPluginDescriptor>() {
@Override
public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) {
- return idComparator.compare(o1.getPluginId(), o2.getPluginId());
+ final PluginId pluginId1 = o1.getPluginId();
+ final PluginId pluginId2 = o2.getPluginId();
+ if (pluginId1.getIdString().equals(CORE_PLUGIN_ID)) return -1;
+ if (pluginId2.getIdString().equals(CORE_PLUGIN_ID)) return 1;
+ return idComparator.compare(pluginId1, pluginId2);
}
};
}
- private static Graph<PluginId> createPluginIdGraph(final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) {
+ private static Graph<PluginId> createPluginIdGraph(final Map<PluginId, ? extends IdeaPluginDescriptor> idToDescriptorMap) {
final List<PluginId> ids = new ArrayList<PluginId>(idToDescriptorMap.keySet());
// this magic ensures that the dependent plugins always follow their dependencies in lexicographic order
// needed to make sure that extensions are always in the same order
@@ -539,7 +549,7 @@ public class PluginManagerCore {
ArrayList<PluginId> plugins = new ArrayList<PluginId>();
for (PluginId dependentPluginId : descriptor.getDependentPluginIds()) {
// check for missing optional dependency
- IdeaPluginDescriptorImpl dep = idToDescriptorMap.get(dependentPluginId);
+ IdeaPluginDescriptor dep = idToDescriptorMap.get(dependentPluginId);
if (dep != null) {
plugins.add(dep.getPluginId());
}
@@ -901,7 +911,12 @@ public class PluginManagerCore {
loadDescriptorsFromClassPath(result, fromSources ? progress : null);
IdeaPluginDescriptorImpl[] pluginDescriptors = result.toArray(new IdeaPluginDescriptorImpl[result.size()]);
- Arrays.sort(pluginDescriptors, new PluginDescriptorComparator(pluginDescriptors));
+ final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap = new com.intellij.util.containers.HashMap<PluginId, IdeaPluginDescriptorImpl>();
+ for (final IdeaPluginDescriptorImpl descriptor : pluginDescriptors) {
+ idToDescriptorMap.put(descriptor.getPluginId(), descriptor);
+ }
+
+ Arrays.sort(pluginDescriptors, getPluginDescriptorComparator(idToDescriptorMap));
return pluginDescriptors;
}
@@ -1110,13 +1125,35 @@ public class PluginManagerCore {
final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap);
final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph);
if (!builder.isAcyclic()) {
- final Couple<PluginId> circularDependency = builder.getCircularDependency();
- final PluginId id = circularDependency.getFirst();
- final PluginId parentId = circularDependency.getSecond();
if (!StringUtil.isEmptyOrSpaces(errorMessage)) {
errorMessage += "<br>";
}
- errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + id + "->" + parentId + "->...->" + id;
+
+ final String cyclePresentation;
+ if (ApplicationManager.getApplication().isInternal()) {
+ final List<String> cycles = new ArrayList<String>();
+ builder.getSCCs().forEach(new TIntProcedure() {
+ int myTNumber = 0;
+ public boolean execute(int size) {
+ if (size > 1) {
+ String cycle = "";
+ for (int j = 0; j < size; j++) {
+ cycle += builder.getNodeByTNumber(myTNumber + j).getIdString() + " ";
+ }
+ cycles.add(cycle);
+ }
+ myTNumber += size;
+ return true;
+ }
+ });
+ cyclePresentation = ": " + StringUtil.join(cycles, ";");
+ } else {
+ final Couple<PluginId> circularDependency = builder.getCircularDependency();
+ final PluginId id = circularDependency.getFirst();
+ final PluginId parentId = circularDependency.getSecond();
+ cyclePresentation = id + "->" + parentId + "->...->" + id;
+ }
+ errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + cyclePresentation;
}
prepareLoadingPluginsErrorMessage(errorMessage);
diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
index 3338241e705a..b68fa936af23 100644
--- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
+++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
@@ -1152,64 +1152,66 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
}
private void balanceWhiteSpaces() {
- RelativeTokenTypesView wsTokens = null;
- RelativeTokenTextView tokenTextGetter = null;
+ RelativeTokenTypesView wsTokens = new RelativeTokenTypesView();
+ RelativeTokenTextView tokenTextGetter = new RelativeTokenTextView();
+ int lastIndex = 0;
for (int i = 1, size = myProduction.size() - 1; i < size; i++) {
- final ProductionMarker item = myProduction.get(i);
-
+ ProductionMarker item = myProduction.get(i);
if (item instanceof StartMarker && ((StartMarker)item).myDoneMarker == null) {
LOG.error(UNBALANCED_MESSAGE);
}
- final int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex;
- int idx = item.myLexemeIndex;
- while (idx > prevProductionLexIndex && whitespaceOrComment(myLexTypes[idx - 1])) idx--;
- final int wsStartIndex = idx;
-
+ int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex;
+ int wsStartIndex = Math.max(item.myLexemeIndex, lastIndex);
+ while (wsStartIndex > prevProductionLexIndex && whitespaceOrComment(myLexTypes[wsStartIndex - 1])) wsStartIndex--;
int wsEndIndex = item.myLexemeIndex;
while (wsEndIndex < myLexemeCount && whitespaceOrComment(myLexTypes[wsEndIndex])) wsEndIndex++;
- if (wsTokens == null) wsTokens = new RelativeTokenTypesView();
- wsTokens.configure(wsStartIndex, wsEndIndex);
- final boolean atEnd = wsStartIndex == 0 || wsEndIndex == myLexemeCount;
- if (tokenTextGetter == null) tokenTextGetter = new RelativeTokenTextView();
- tokenTextGetter.configure(wsStartIndex);
+ if (wsStartIndex != wsEndIndex) {
+ wsTokens.configure(wsStartIndex, wsEndIndex);
+ tokenTextGetter.configure(wsStartIndex);
+ boolean atEnd = wsStartIndex == 0 || wsEndIndex == myLexemeCount;
+ item.myLexemeIndex = wsStartIndex + item.myEdgeTokenBinder.getEdgePosition(wsTokens, atEnd, tokenTextGetter);
+ }
+ else if (item.myLexemeIndex < wsStartIndex) {
+ item.myLexemeIndex = wsStartIndex;
+ }
- item.myLexemeIndex = wsStartIndex + item.myEdgeTokenBinder.getEdgePosition(wsTokens, atEnd, tokenTextGetter);
+ lastIndex = item.myLexemeIndex;
}
}
private final class RelativeTokenTypesView extends AbstractList<IElementType> {
- private int start;
- private int size;
+ private int myStart;
+ private int mySize;
- private void configure(int _start, int _end) {
- size = _end - _start;
- start = _start;
+ private void configure(int start, int end) {
+ myStart = start;
+ mySize = end - start;
}
@Override
- public IElementType get(final int index) {
- return myLexTypes[start + index];
+ public IElementType get(int index) {
+ return myLexTypes[myStart + index];
}
@Override
public int size() {
- return size;
+ return mySize;
}
}
private final class RelativeTokenTextView implements WhitespacesAndCommentsBinder.TokenTextGetter {
- private int start;
+ private int myStart;
- private void configure(int _start) {
- start = _start;
+ private void configure(int start) {
+ myStart = start;
}
@Override
- public CharSequence get(final int i) {
- return myText.subSequence(myLexStarts[start + i], myLexStarts[start + i + 1]);
+ public CharSequence get(int i) {
+ return myText.subSequence(myLexStarts[myStart + i], myLexStarts[myStart + i + 1]);
}
}
diff --git a/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java b/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
index dd6d73f11b99..6df23d8edba0 100644
--- a/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
+++ b/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
@@ -74,6 +74,11 @@ public class MockFileIndexFacade extends FileIndexFacade {
}
@Override
+ public boolean isUnderIgnored(@NotNull VirtualFile file) {
+ return false;
+ }
+
+ @Override
public Module getModuleForFile(@NotNull VirtualFile file) {
return myModule;
}
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
index fa234e109d49..918ebaa22425 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
@@ -75,6 +75,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
private final List<EditReadOnlyListener> myReadOnlyListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private volatile boolean myMightContainTabs = true; // optimisation flag: when document contains no tabs it is dramatically easier to calculate positions in editor
+ private int myTabTrackingRequestors = 0;
+
private int myCheckGuardedBlocks = 0;
private boolean myGuardsSuppressed = false;
private boolean myEventsHandling = false;
@@ -171,14 +174,14 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
/**
* @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret being in the way
*
- * @deprecated should be replaced with {@link #stripTrailingSpaces(com.intellij.openapi.project.Project, boolean, boolean, java.util.List)}
+ * @deprecated should be replaced with {@link #stripTrailingSpaces(com.intellij.openapi.project.Project, boolean, boolean, int[])}
* once multicaret logic will become unconditional (not controlled by configuration flag)
*/
- public boolean stripTrailingSpaces(@Nullable final Project project,
- boolean inChangedLinesOnly,
- boolean virtualSpaceEnabled,
- int caretLine,
- int caretOffset) {
+ boolean stripTrailingSpaces(@Nullable final Project project,
+ boolean inChangedLinesOnly,
+ boolean virtualSpaceEnabled,
+ int caretLine,
+ int caretOffset) {
if (!isStripTrailingSpacesEnabled) {
return true;
}
@@ -230,24 +233,24 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
/**
* @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret(s) being in the way
*/
- public boolean stripTrailingSpaces(@Nullable final Project project,
- boolean inChangedLinesOnly,
- boolean virtualSpaceEnabled,
- @NotNull List<Integer> caretOffsets) {
+ boolean stripTrailingSpaces(@Nullable final Project project,
+ boolean inChangedLinesOnly,
+ boolean virtualSpaceEnabled,
+ @NotNull int[] caretOffsets) {
if (!isStripTrailingSpacesEnabled) {
return true;
}
boolean markAsNeedsStrippingLater = false;
CharSequence text = myText;
- TIntObjectHashMap<List<RangeMarker>> caretMarkers = new TIntObjectHashMap<List<RangeMarker>>(caretOffsets.size());
+ TIntObjectHashMap<List<RangeMarker>> caretMarkers = new TIntObjectHashMap<List<RangeMarker>>(caretOffsets.length);
try {
if (!virtualSpaceEnabled) {
- for (Integer caretOffset : caretOffsets) {
- if (caretOffset == null || caretOffset < 0 || caretOffset > getTextLength()) {
+ for (int caretOffset : caretOffsets) {
+ if (caretOffset < 0 || caretOffset > getTextLength()) {
continue;
}
- Integer line = getLineNumber(caretOffset);
+ int line = getLineNumber(caretOffset);
List<RangeMarker> markers = caretMarkers.get(line);
if (markers == null) {
markers = new ArrayList<RangeMarker>();
@@ -763,6 +766,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
if (LOG.isDebugEnabled()) LOG.debug(event.toString());
getLineSet().changedUpdate(event);
+ if (myTabTrackingRequestors > 0) {
+ updateMightContainTabs(event.getNewFragment());
+ }
setModificationStamp(newModificationStamp);
if (!ShutDownTracker.isShutdownHookRunning()) {
@@ -1051,4 +1057,29 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
public String toString() {
return "DocumentImpl[" + FileDocumentManager.getInstance().getFile(this) + "]";
}
+
+ public void requestTabTracking() {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ if (myTabTrackingRequestors++ == 0) {
+ myMightContainTabs = false;
+ updateMightContainTabs(myText);
+ }
+ }
+
+ public void giveUpTabTracking() {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ if (--myTabTrackingRequestors == 0) {
+ myMightContainTabs = true;
+ }
+ }
+
+ public boolean mightContainTabs() {
+ return myMightContainTabs;
+ }
+
+ private void updateMightContainTabs(CharSequence text) {
+ if (!myMightContainTabs) {
+ myMightContainTabs = StringUtil.contains(text, 0, text.length(), '\t');
+ }
+ }
}
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
index 975add0847a9..5ce1e2c2167b 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
@@ -123,7 +123,7 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
}
});
if (alive.get() > DUPLICATE_LIMIT) {
- return "Too many range markers (" + alive + ") registered in "+this+"\n";
+ return "Too many range markers (" + alive + ") registered for interval "+node+"\n";
}
return null;
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 ba5858c52993..2ca35e4227e9 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
@@ -301,15 +301,30 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel {
final PsiToDocumentSynchronizer synchronizer = manager.getSynchronizer();
final PsiElement changeScope = transaction.getChangeScope();
LOG.assertTrue(changeScope != null);
- BlockSupportImpl.sendBeforeChildrenChangeEvent((PsiManagerImpl)PsiManager.getInstance(myProject), changeScope, true);
+
final PsiFile containingFileByTree = getContainingFileByTree(changeScope);
+ if (changeScope.isPhysical() && synchronizer.toProcessPsiEvent() && isDocumentUncommitted(containingFileByTree)) {
+ // fail-fast to prevent any psi modifications that would cause psi/document text mismatch
+ // PsiToDocumentSynchronizer assertions happen inside event processing and are logged by PsiManagerImpl.fireEvent instead of being rethrown
+ // so it's important to throw something outside event processing
+ throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
+ }
+ BlockSupportImpl.sendBeforeChildrenChangeEvent((PsiManagerImpl)PsiManager.getInstance(myProject), changeScope, true);
Document document = containingFileByTree == null ? null : manager.getCachedDocument(containingFileByTree);
if(document != null) {
synchronizer.startTransaction(myProject, document, changeScope);
}
}
+ private boolean isDocumentUncommitted(@Nullable PsiFile file) {
+ if (file == null) return false;
+
+ PsiDocumentManager manager = PsiDocumentManager.getInstance(myProject);
+ Document cachedDocument = manager.getCachedDocument(file);
+ return cachedDocument != null && manager.isUncommited(cachedDocument);
+ }
+
@Nullable
private static PsiFile getContainingFileByTree(@NotNull final PsiElement changeScope) {
// there could be pseudo physical trees (JSPX/JSP/etc.) which must not translate
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 3583af212528..8a8f7221d962 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
@@ -699,7 +699,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
}
// we can end up outside write action here if the document has forUseInNonAWTThread=true
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ ApplicationManager.getApplication().runWriteAction(new ExternalChangeAction() {
@Override
public void run() {
psiFile.getViewProvider().beforeContentsSynchronized();
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 7611dd11162a..13c43571decb 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
@@ -74,10 +74,8 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter {
final PsiFile psiFile = event.getFile();
if (psiFile == null || psiFile.getNode() == null) return;
- final Document document = getCachedDocument(psiFile, force);
- if (document == null) return;
-
- if (myPsiDocumentManager.isUncommited(document)) {
+ final Document document = myPsiDocumentManager.getCachedDocument(psiFile);
+ if (document != null && myPsiDocumentManager.isUncommited(document)) {
throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
}
}
@@ -207,7 +205,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter {
return myIgnorePsiEvents;
}
- private boolean toProcessPsiEvent() {
+ public boolean toProcessPsiEvent() {
return !myIgnorePsiEvents && !ApplicationManager.getApplication().hasWriteAction(IgnorePsiEventsMarker.class);
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java b/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
index d41138043e95..386fb2dea0e9 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
@@ -39,8 +39,7 @@ import java.util.List;
* User: cdr
*/
public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
- public DiffLog() {
- }
+ public DiffLog() { }
private abstract static class LogEntry {
protected LogEntry() {
@@ -58,7 +57,6 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
entry.doActualPsiChange(file, astDiffBuilder);
}
file.subtreeChanged();
-
return astDiffBuilder.getEvent();
}
@@ -83,7 +81,6 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
@Override
public void nodeDeleted(@NotNull ASTNode oldParent, @NotNull ASTNode oldNode) {
myEntries.add(new DeleteEntry(oldParent, oldNode));
-
}
@Override
@@ -126,14 +123,12 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
astDiffBuilder.nodeReplaced(oldNode, newNode);
- /////////////////
((TreeElement)newNode).clearCaches();
if (!(newNode instanceof FileElement)) {
((CompositeElement)newNode.getTreeParent()).subtreeChanged();
}
DebugUtil.checkTreeStructure(parent);
-
}
}
@@ -168,7 +163,6 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
((CompositeElement)parent).subtreeChanged();
DebugUtil.checkTreeStructure(parent);
-
}
}
@@ -222,7 +216,6 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
DebugUtil.checkTreeStructure(myOldParent);
}
-
}
private static PsiElement getPsi(ASTNode node, PsiFile file) {
diff --git a/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java b/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
index 115b91a050fd..f21c241e966a 100644
--- a/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
public class ProjectScopeImpl extends GlobalSearchScope {
private final FileIndexFacade myFileIndex;
- public ProjectScopeImpl(Project project, FileIndexFacade fileIndex) {
+ public ProjectScopeImpl(@NotNull Project project, @NotNull FileIndexFacade fileIndex) {
super(project);
myFileIndex = fileIndex;
}
@@ -61,6 +61,7 @@ public class ProjectScopeImpl extends GlobalSearchScope {
return PsiBundle.message("psi.search.scope.project");
}
+ @Override
public String toString() {
return getDisplayName();
}
diff --git a/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java b/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
index c94921b7eaeb..581352cea35f 100644
--- a/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
+++ b/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
@@ -66,7 +66,7 @@ public abstract class BlockSupport {
// maximal tree depth for which incremental reparse is allowed
// if tree is deeper then it will be replaced completely - to avoid SOEs
- public static final int INCREMENTAL_REPARSE_DEPTH_LIMIT = Registry.intValue("psi.incremental.reparse.depth.limit", 1000);
+ public static final int INCREMENTAL_REPARSE_DEPTH_LIMIT = Registry.intValue("psi.incremental.reparse.depth.limit");
public static final Key<Boolean> TREE_DEPTH_LIMIT_EXCEEDED = Key.create("TREE_IS_TOO_DEEP");