Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Bas Leijdekkers
2009-10-28 19:09:00 +01:00
15 changed files with 241 additions and 144 deletions
@@ -49,10 +49,8 @@ import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ModuleRootListener;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileAdapter;
import com.intellij.openapi.vfs.VirtualFileManager;
@@ -68,6 +66,7 @@ import gnu.trove.THashSet;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -265,16 +264,19 @@ public class DaemonListeners implements Disposable {
if (file instanceof PsiCodeFragment) return true;
Project project = file.getProject();
if (!ModuleUtil.projectContainsFile(project, virtualFile, false)) return false;
FileEditor[] editors = FileEditorManager.getInstance(myProject).getEditors(virtualFile);
for (FileEditor editor : editors) {
if (!editor.isModified()) return false;
}
FilePath path = new FilePathImpl(virtualFile);
boolean vcsIsThinking = !VcsDirtyScopeManager.getInstance(myProject).whatFilesDirty(Arrays.asList(path)).isEmpty();
if (vcsIsThinking) return false;
AbstractVcs activeVcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(virtualFile);
if (activeVcs == null) return true;
FileStatus status = FileStatusManager.getInstance(project).getStatus(virtualFile);
if (status == FileStatus.MODIFIED || status == FileStatus.ADDED) return true;
FileEditor[] editors = FileEditorManager.getInstance(myProject).getEditors(virtualFile);
for (FileEditor editor : editors) {
if (editor.isModified()) return true;
}
return false;
return status == FileStatus.MODIFIED || status == FileStatus.ADDED;
}
private class MyApplicationListener extends ApplicationAdapter {
@@ -133,10 +133,6 @@ public class DefaultHighlightVisitor extends PsiElementVisitor implements Highli
HighlightInfo info;
if (offset < fileLength && text != null && !StringUtil.startsWithChar(text, '\n') && !StringUtil.startsWithChar(text, '\r')) {
int start = offset;
PsiElement prevElement = containingFile.findElementAt(offset - 1);
//if (offset > 0 && prevElement != null && prevElement.getText().equals("(") && StringUtil.startsWithChar(text, ')')) {
// start = offset - 1;
//}
int end = offset + 1;
info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, start, end, element.getErrorDescription());
info.navigationShift = offset - start;
@@ -351,6 +351,19 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe
}
}
public void cleanupMemoryStorage() {
for (UpdatableIndex index : myIndices.values()) {
final IndexStorage indexStorage = ((MapReduceIndex)index).getStorage();
index.getWriteLock().lock();
try {
((MemoryIndexStorage)indexStorage).clearMemoryMap();
}
finally {
index.getWriteLock().unlock();
}
}
}
public void clearAllIndices() {
for (UpdatableIndex index : myIndices.values()) {
@@ -217,6 +217,10 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
public void bufferingStateChanged(final boolean newState) {
((StubIndexImpl)StubIndexImpl.getInstance()).setDataBufferingEnabled(newState);
}
public void memoryStorageCleared() {
((StubIndexImpl)StubIndexImpl.getInstance()).cleanupMemoryStorage();
}
});
}
return new MyIndex(indexId, owner, storage, getIndexer());
@@ -42,8 +42,10 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.psi.PsiDocumentManager;
@@ -200,6 +202,20 @@ public class FileBasedIndex implements ApplicationComponent {
}
});
connection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
public void before(List<? extends VFileEvent> events) {
for (VFileEvent event : events) {
if (event.getRequestor() instanceof FileDocumentManager) {
cleanupMemoryStorage();
break;
}
}
}
public void after(List<? extends VFileEvent> events) {
}
});
ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() {
public void writeActionStarted(Object action) {
myUpToDateIndices.clear();
@@ -257,7 +273,7 @@ public class FileBasedIndex implements ApplicationComponent {
}
}
private String calcConfigPath(final String path) {
private static String calcConfigPath(final String path) {
try {
final String _path = FileUtil.toSystemIndependentName(new File(path).getCanonicalPath());
return _path.endsWith("/")? _path : _path + "/" ;
@@ -816,27 +832,35 @@ public class FileBasedIndex implements ApplicationComponent {
void process(final int inputId, V value);
}
public <K, V> void processAllValues(final ID<K, V> indexId, AllValuesProcessor<V> processor, @NotNull Project project) {
public <K, V> void processAllValues(final ID<K, V> indexId, final AllValuesProcessor<V> processor, @NotNull Project project) {
try {
ensureUpToDate(indexId, project, null);
final UpdatableIndex<K, V, FileContent> index = getIndex(indexId);
if (index == null) {
return;
}
try {
index.getReadLock().lock();
for (K dataKey : index.getAllKeys()) {
final ValueContainer<V> container = index.getData(dataKey);
for (final Iterator<V> it = container.getValueIterator(); it.hasNext();) {
final V value = it.next();
for (final ValueContainer.IntIterator inputsIt = container.getInputIdsIterator(value); inputsIt.hasNext();) {
processor.process(inputsIt.next(), value);
final Ref<StorageException> storageEx = new Ref<StorageException>(null);
index.processAllKeys(new Processor<K>() {
public boolean process(K dataKey) {
try {
final ValueContainer<V> container = index.getData(dataKey);
for (final Iterator<V> it = container.getValueIterator(); it.hasNext();) {
final V value = it.next();
for (final ValueContainer.IntIterator inputsIt = container.getInputIdsIterator(value); inputsIt.hasNext();) {
processor.process(inputsIt.next(), value);
}
}
return true;
}
catch (StorageException e) {
storageEx.set(e);
return false;
}
}
}
finally {
index.getReadLock().unlock();
});
final StorageException ex = storageEx.get();
if (ex != null) {
throw ex;
}
}
catch (StorageException e) {
@@ -1078,11 +1102,6 @@ public class FileBasedIndex implements ApplicationComponent {
private StorageGuard.Holder setDataBufferingEnabled(final boolean enabled) {
final StorageGuard.Holder holder = myStorageLock.enter(enabled);
if (!enabled) {
synchronized (myLastIndexedDocStamps) {
myLastIndexedDocStamps.clear();
}
}
for (ID<?, ?> indexId : myIndices.keySet()) {
final MapReduceIndex index = (MapReduceIndex)getIndex(indexId);
assert index != null;
@@ -1092,6 +1111,25 @@ public class FileBasedIndex implements ApplicationComponent {
return holder;
}
private void cleanupMemoryStorage() {
synchronized (myLastIndexedDocStamps) {
myLastIndexedDocStamps.clear();
}
for (ID<?, ?> indexId : myIndices.keySet()) {
final MapReduceIndex index = (MapReduceIndex)getIndex(indexId);
assert index != null;
final MemoryIndexStorage memStorage = (MemoryIndexStorage)index.getStorage();
index.getWriteLock().lock();
try {
memStorage.clearMemoryMap();
}
finally {
index.getWriteLock().unlock();
}
memStorage.fireMemoryStorageCleared();
}
}
private void dropUnregisteredIndices() {
final Set<String> indicesToDrop = readRegistsredIndexNames();
for (ID<?, ?> key : myIndices.keySet()) {
@@ -20,13 +20,14 @@ import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import java.io.Flushable;
import java.io.IOException;
import java.util.Collection;
/**
* @author Eugene Zhuravlev
* Date: Dec 10, 2007
*/
public interface IndexStorage<Key, Value> extends Flushable{
public interface IndexStorage<Key, Value> extends Flushable {
void addValue(Key key, int inputId, Value value) throws StorageException;
@@ -44,4 +45,6 @@ public interface IndexStorage<Key, Value> extends Flushable{
Collection<Key> getKeys() throws StorageException;
void close() throws StorageException;
void flush() throws IOException;
}
@@ -137,7 +137,7 @@ public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Valu
}
}
public synchronized void close() throws StorageException {
public void close() throws StorageException {
try {
flush();
myMap.close();
@@ -157,7 +157,7 @@ public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Valu
}
}
public synchronized void clear() throws StorageException{
public void clear() throws StorageException{
try {
myMap.close();
}
@@ -18,14 +18,12 @@ package com.intellij.util.indexing;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.concurrency.JBLock;
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
import com.intellij.util.concurrency.LockFactory;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* This storage is needed for indexing yet unsaved data without saving those changes to 'main' backend storage
@@ -36,14 +34,12 @@ import java.util.*;
public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value> {
private final Map<Key, UpdatableValueContainer<Value>> myMap = new HashMap<Key,UpdatableValueContainer<Value>>();
private final IndexStorage<Key, Value> myBackendStorage;
private boolean myBufferingEnabled = false;
private final List<BufferingStateListener> myListeners = ContainerUtil.createEmptyCOWList();
private final JBReentrantReadWriteLock myLock = LockFactory.createReadWriteLock();
private final JBLock r = myLock.readLock();
private final JBLock w = myLock.writeLock();
private final AtomicBoolean myBufferingEnabled = new AtomicBoolean(false);
public interface BufferingStateListener {
void bufferingStateChanged(boolean newState);
void memoryStorageCleared();
}
public MemoryIndexStorage(IndexStorage<Key, Value> backend) {
@@ -59,21 +55,21 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
}
public void setBufferingEnabled(boolean enabled) {
w.lock();
try {
final boolean wasEnabled = myBufferingEnabled;
myBufferingEnabled = enabled;
if (wasEnabled && !enabled) {
myMap.clear();
}
if (wasEnabled != enabled) {
for (BufferingStateListener listener : myListeners) {
listener.bufferingStateChanged(enabled);
}
final boolean wasEnabled = myBufferingEnabled.getAndSet(enabled);
if (wasEnabled != enabled) {
for (BufferingStateListener listener : myListeners) {
listener.bufferingStateChanged(enabled);
}
}
finally {
w.unlock();
}
public void clearMemoryMap() {
myMap.clear();
}
public void fireMemoryStorageCleared() {
for (BufferingStateListener listener : myListeners) {
listener.memoryStorageCleared();
}
}
@@ -82,14 +78,8 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
}
public void clear() throws StorageException {
w.lock();
try {
myMap.clear();
myBackendStorage.clear();
}
finally {
w.unlock();
}
clearMemoryMap();
myBackendStorage.clear();
}
public void flush() throws IOException {
@@ -103,75 +93,60 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
}
public boolean processKeys(final Processor<Key> processor) throws StorageException {
r.lock();
try {
if (myBufferingEnabled) {
final Set<Key> stopList = new HashSet<Key>();
final Set<Key> stopList = new HashSet<Key>();
Processor<Key> decoratingProcessor = new Processor<Key>() {
public boolean process(final Key key) {
if (stopList.contains(key)) return true;
Processor<Key> decoratingProcessor = new Processor<Key>() {
public boolean process(final Key key) {
if (stopList.contains(key)) return true;
final UpdatableValueContainer<Value> container = myMap.get(key);
if (container != null && container.size() == 0) return true;
return processor.process(key);
}
};
for (Key key : myMap.keySet()) {
if (!decoratingProcessor.process(key)) return false;
stopList.add(key);
}
return myBackendStorage.processKeys(decoratingProcessor);
final UpdatableValueContainer<Value> container = myMap.get(key);
if (container != null && container.size() == 0) return true;
return processor.process(key);
}
}
finally {
r.unlock();
}
};
return myBackendStorage.processKeys(processor);
for (Key key : myMap.keySet()) {
if (!decoratingProcessor.process(key)) return false;
stopList.add(key);
}
return myBackendStorage.processKeys(decoratingProcessor);
}
public void addValue(final Key key, final int inputId, final Value value) throws StorageException {
w.lock();
try {
if (myBufferingEnabled) {
getMemValueContainer(key).addValue(inputId, value);
return;
}
if (myBufferingEnabled.get()) {
getMemValueContainer(key).addValue(inputId, value);
return;
}
finally {
w.unlock();
final UpdatableValueContainer<Value> valueContainer = myMap.get(key);
if (valueContainer != null) {
valueContainer.addValue(inputId, value);
}
myBackendStorage.addValue(key, inputId, value);
}
public void removeValue(final Key key, final int inputId, final Value value) throws StorageException {
w.lock();
try {
if (myBufferingEnabled) {
getMemValueContainer(key).removeValue(inputId, value);
return;
}
if (myBufferingEnabled.get()) {
getMemValueContainer(key).removeValue(inputId, value);
return;
}
finally {
w.unlock();
final UpdatableValueContainer<Value> valueContainer = myMap.get(key);
if (valueContainer != null) {
valueContainer.removeValue(inputId, value);
}
myBackendStorage.removeValue(key, inputId, value);
}
public void removeAllValues(Key key, int inputId) throws StorageException {
w.lock();
try {
if (myBufferingEnabled) {
getMemValueContainer(key).removeAllValues(inputId);
return;
}
if (myBufferingEnabled.get()) {
getMemValueContainer(key).removeAllValues(inputId);
return;
}
finally {
w.unlock();
final UpdatableValueContainer<Value> valueContainer = myMap.get(key);
if (valueContainer != null) {
valueContainer.removeAllValues(inputId);
}
myBackendStorage.removeAllValues(key, inputId);
}
@@ -199,18 +174,9 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
@NotNull
public ValueContainer<Value> read(final Key key) throws StorageException {
r.lock();
try {
if (myBufferingEnabled) {
final ValueContainer<Value> valueContainer = myMap.get(key);
if (valueContainer != null) {
return valueContainer;
}
return myBackendStorage.read(key);
}
}
finally {
r.unlock();
final ValueContainer<Value> valueContainer = myMap.get(key);
if (valueContainer != null) {
return valueContainer;
}
return myBackendStorage.read(key);
@@ -3544,7 +3544,7 @@ public class AbstractTreeUi {
updater.setPassThroughMode(myPassthroughMode);
}
if (!isUnitTestingMode()) {
if (!isUnitTestingMode() && passthrough) {
LOG.error("Pass-through mode for TreeUi is allowed only for unit test mode");
}
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.ExtensionsArea;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Alarm;
@@ -31,6 +32,7 @@ import com.intellij.util.SystemProperties;
import com.intellij.util.ui.UIUtil;
import junit.framework.Assert;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
@@ -69,14 +71,33 @@ public class PlatformTestUtil {
}
public static String print(JTree tree, boolean withSelection) {
return print(tree, withSelection, null);
}
public static String print(JTree tree, boolean withSelection, Condition<String> nodePrintCondition) {
StringBuffer buffer = new StringBuffer();
Object root = tree.getModel().getRoot();
printImpl(tree, root, buffer, 0, withSelection);
printImpl(tree, root, buffer, 0, withSelection, nodePrintCondition);
return buffer.toString();
}
private static void printImpl(JTree tree, Object root, StringBuffer buffer, int level, boolean withSelection) {
private static void printImpl(JTree tree, Object root, StringBuffer buffer, int level, boolean withSelection, @Nullable Condition<String> nodePrintCondition) {
DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode)root;
final Object userObject = defaultMutableTreeNode.getUserObject();
String nodeText;
if (userObject != null) {
nodeText = toString(userObject);
}
else {
nodeText = defaultMutableTreeNode + "";
}
if (nodePrintCondition != null && !nodePrintCondition.value(nodeText)) return;
boolean expanded = tree.isExpanded(new TreePath(defaultMutableTreeNode.getPath()));
StringUtil.repeatSymbol(buffer, ' ', level);
if (expanded && !defaultMutableTreeNode.isLeaf()) {
@@ -93,13 +114,8 @@ public class PlatformTestUtil {
buffer.append("[");
}
final Object userObject = defaultMutableTreeNode.getUserObject();
if (userObject != null) {
buffer.append(toString(userObject));
}
else {
buffer.append(defaultMutableTreeNode);
}
buffer.append(nodeText);
if (withSelection && selected) {
buffer.append("]");
@@ -109,7 +125,7 @@ public class PlatformTestUtil {
int childCount = tree.getModel().getChildCount(root);
if (expanded) {
for (int i = 0; i < childCount; i++) {
printImpl(tree, tree.getModel().getChild(root, i), buffer, level + 1, withSelection);
printImpl(tree, tree.getModel().getChild(root, i), buffer, level + 1, withSelection, nodePrintCondition);
}
}
}
@@ -0,0 +1,55 @@
/*
* 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.testFramework;
import com.intellij.openapi.util.Condition;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public abstract class TreePrintCondition implements Condition<String> {
public abstract static class SetBased extends TreePrintCondition {
protected Set<String> mySet = new HashSet<String>();
public SetBased(String... elements) {
mySet.addAll(Arrays.asList(elements));
}
}
public static class Include extends SetBased {
public Include(String... elements) {
super(elements);
}
public boolean value(String s) {
return mySet.contains(s);
}
}
public static class Exclude extends SetBased {
public Exclude(String... elements) {
super(elements);
}
public boolean value(String s) {
return !mySet.contains(s);
}
}
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
@@ -84,7 +85,8 @@ public abstract class VcsDirtyScopeManager {
public abstract VcsInvalidated retrieveScopes();
public abstract Collection<FilePath> whatFilesDirty(final Collection<FilePath> files);
@NotNull
public abstract Collection<FilePath> whatFilesDirty(@NotNull Collection<FilePath> files);
/**
* Requests an asynchronous file status update for all files specified and under the specified directories
@@ -79,6 +79,10 @@ public class FilePathImpl implements FilePath {
myIsDirectory = isDirectory;
}
public FilePathImpl(@NotNull VirtualFile virtualFile) {
this(virtualFile.getParent(), virtualFile.getName(), virtualFile.isDirectory(), virtualFile, false);
}
public int hashCode() {
return StringUtil.stringHashCodeInsensitive(myFile.getPath());
}
@@ -92,10 +96,6 @@ public class FilePathImpl implements FilePath {
}
}
public FilePathImpl(@NotNull VirtualFile virtualFile) {
this(virtualFile.getParent(), virtualFile.getName(), virtualFile.isDirectory(), virtualFile, false);
}
public void refresh() {
if (!myNonLocal) {
if (myVirtualParent == null) {
@@ -34,7 +34,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
/**
* @author max
@@ -357,9 +356,10 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
});
}
@NotNull
@Override
public Collection<FilePath> whatFilesDirty(final Collection<FilePath> files) {
final Collection<FilePath> result = new LinkedList<FilePath>();
public Collection<FilePath> whatFilesDirty(@NotNull final Collection<FilePath> files) {
final Collection<FilePath> result = new ArrayList<FilePath>();
final Ref<MyProgressHolder> inProgressHolderRef = new Ref<MyProgressHolder>();
final Ref<MyProgressHolder> currentHolderRef = new Ref<MyProgressHolder>();
@@ -372,7 +372,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
final VcsInvalidated inProgressInvalidated = inProgressHolderRef.get().calculateInvalidated();
final VcsInvalidated currentInvalidated = currentHolderRef.get().calculateInvalidated();
for (FilePath fp : files) {
if (((inProgressInvalidated != null) && inProgressInvalidated.isFileDirty(fp)) || currentInvalidated.isFileDirty(fp)) {
if (inProgressInvalidated != null && inProgressInvalidated.isFileDirty(fp) || currentInvalidated.isFileDirty(fp)) {
result.add(fp);
}
}
@@ -17,6 +17,7 @@ package com.intellij.openapi.vcs.changes;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
@@ -77,8 +78,9 @@ class VcsDirtyScopeManagerProxy extends VcsDirtyScopeManager {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public Collection<FilePath> whatFilesDirty(Collection<FilePath> files) {
public Collection<FilePath> whatFilesDirty(@NotNull Collection<FilePath> files) {
throw new UnsupportedOperationException();
}