Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2014-11-14 15:24:00 +03:00
41 changed files with 570 additions and 343 deletions
@@ -78,7 +78,7 @@ public class JavaDebugProcess extends XDebugProcess {
return res;
}
private JavaDebugProcess(@NotNull final XDebugSession session, final DebuggerSession javaSession) {
protected JavaDebugProcess(@NotNull final XDebugSession session, final DebuggerSession javaSession) {
super(session);
myJavaSession = javaSession;
myEditorsProvider = new JavaDebuggerEditorsProvider();
@@ -29,6 +29,7 @@ import com.intellij.debugger.requests.Requestor;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.ui.breakpoints.Breakpoint;
import com.intellij.debugger.ui.breakpoints.FilteredRequestor;
import com.intellij.diagnostic.ThreadDumper;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -37,7 +38,6 @@ import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiClass;
import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.util.containers.HashMap;
import com.intellij.xdebugger.XDebugSession;
import com.sun.jdi.*;
import com.sun.jdi.event.ClassPrepareEvent;
import com.sun.jdi.request.*;
@@ -287,7 +287,11 @@ public class RequestManagerImpl extends DebugProcessAdapterImpl implements Reque
}
}
}
myEventRequestManager.deleteEventRequest(request);
try {
myEventRequestManager.deleteEventRequest(request);
} catch (Exception e) {
LOG.error("Exception in EventRequestManager.deleteEventRequest", e, ThreadDumper.dumpThreadsToString());
}
}
catch (InvalidRequestStateException ignored) {
// request is already deleted
@@ -37,6 +37,7 @@ import com.intellij.codeInspection.ex.JobDescriptor;
import com.intellij.codeInspection.reference.*;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
import com.intellij.codeInspection.util.RefFilter;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPoint;
@@ -44,12 +45,16 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.util.containers.HashMap;
import org.jdom.Element;
@@ -309,8 +314,9 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
ProgressManager.getInstance().runProcess(new Runnable() {
@Override
public void run() {
final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(globalContext.getRefManager().getProject());
globalContext.getRefManager().iterate(new RefJavaVisitor() {
final RefManager refManager = globalContext.getRefManager();
final PsiSearchHelper helper = PsiSearchHelper.SERVICE.getInstance(refManager.getProject());
refManager.iterate(new RefJavaVisitor() {
@Override
public void visitElement(@NotNull final RefEntity refEntity) {
if (refEntity instanceof RefClass && strictUnreferencedFilter.accepts((RefClass)refEntity)) {
@@ -325,18 +331,36 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool {
}
private void findExternalClassReferences(final RefClass refElement) {
PsiClass psiClass = refElement.getElement();
String qualifiedName = psiClass.getQualifiedName();
final PsiClass psiClass = refElement.getElement();
String qualifiedName = psiClass != null ? psiClass.getQualifiedName() : null;
if (qualifiedName != null) {
helper.processUsagesInNonJavaFiles(qualifiedName,
new PsiNonJavaFileReferenceProcessor() {
@Override
public boolean process(PsiFile file, int startOffset, int endOffset) {
getEntryPointsManager().addEntryPoint(refElement, false);
return false;
}
},
GlobalSearchScope.projectScope(globalContext.getProject()));
final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(globalContext.getProject());
final PsiNonJavaFileReferenceProcessor processor = new PsiNonJavaFileReferenceProcessor() {
@Override
public boolean process(PsiFile file, int startOffset, int endOffset) {
getEntryPointsManager().addEntryPoint(refElement, false);
return false;
}
};
final DelegatingGlobalSearchScope globalSearchScope = new DelegatingGlobalSearchScope(projectScope) {
@Override
public boolean contains(@NotNull VirtualFile file) {
return file.getFileType() != JavaFileType.INSTANCE && super.contains(file);
}
};
if (helper.processUsagesInNonJavaFiles(qualifiedName, processor, globalSearchScope)) {
final PsiReference reference = ReferencesSearch.search(psiClass, globalSearchScope).findFirst();
if (reference != null) {
getEntryPointsManager().addEntryPoint(refElement, false);
for (PsiMethod method : psiClass.getMethods()) {
final RefElement refMethod = refManager.getReference(method);
if (refMethod != null) {
getEntryPointsManager().addEntryPoint(refMethod, false);
}
}
}
}
}
}
});
@@ -0,0 +1,24 @@
import java.lang.System;
public class MyOwn {
public void run() {
int a = 2;
// my super comment
int c = 3;
Runnable a = null;
System.out.println("Hello!");
c += 3;
int re = 12;
re += 1;
c = re + c;
int q;
q = c * re + c;
c = q * 11 - 167;
System.out.println("Testing!");
System.out.println("Hello!");
c += 3;
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2000-2014 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.autodetect;
import com.intellij.JavaTestUtil;
import org.jetbrains.annotations.NotNull;
public class JavaAutoDetectIndentTest extends AbstractIndentAutoDetectionTest {
@NotNull
@Override
protected String getFileNameWithExtension() {
return getTestName(true) + ".java";
}
@NotNull
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() +
"/psi/autodetect/";
}
public void testNotIndentedComment() {
doTestIndentSize(3);
}
}
@@ -282,10 +282,10 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
}
}
public boolean finishCommit(@NotNull final Document document,
@NotNull final List<Processor<Document>> finishProcessors,
final boolean synchronously,
@NotNull final Object reason) {
boolean finishCommit(@NotNull final Document document,
@NotNull final List<Processor<Document>> finishProcessors,
final boolean synchronously,
@NotNull final Object reason) {
assert !myProject.isDisposed() : "Already disposed";
final boolean[] ok = {true};
ApplicationManager.getApplication().runWriteAction(new CommitToPsiFileAction(document, myProject) {
@@ -759,17 +759,17 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
@Override
public PsiElement getFirstChild() {
return SharedImplUtil.getFirstChild(calcTreeElement());
return SharedImplUtil.getFirstChild(getNode());
}
@Override
public PsiElement getLastChild() {
return SharedImplUtil.getLastChild(calcTreeElement());
return SharedImplUtil.getLastChild(getNode());
}
@Override
public void acceptChildren(@NotNull PsiElementVisitor visitor) {
SharedImplUtil.acceptChildren(visitor, calcTreeElement());
SharedImplUtil.acceptChildren(visitor, getNode());
}
@Override
@@ -128,7 +128,9 @@ public class ResolveCache {
boolean isPoly,
boolean isPhysical) {
ProgressIndicatorProvider.checkCanceled();
ApplicationManager.getApplication().assertReadAccessAllowed();
if (isPhysical) {
ApplicationManager.getApplication().assertReadAccessAllowed();
}
int index = getIndex(isPhysical, incompleteCode, isPoly);
ConcurrentMap<TRef, TResult> map = getMap(index);
@@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.CheckUtil;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.ElementBase;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
import com.intellij.psi.tree.IElementType;
@@ -40,7 +41,7 @@ public class SharedImplUtil {
}
public static PsiElement getParent(ASTNode thisElement) {
if (CHECK_FOR_READ_ACTION) {
if (CHECK_FOR_READ_ACTION && thisElement instanceof ElementBase) {
ApplicationManager.getApplication().assertReadAccessAllowed();
}
return SourceTreeToPsiMap.treeElementToPsi(thisElement.getTreeParent());
@@ -82,7 +83,7 @@ public class SharedImplUtil {
}
public static FileElement findFileElement(@NotNull ASTNode element) {
if (CHECK_FOR_READ_ACTION) {
if (CHECK_FOR_READ_ACTION && element instanceof ElementBase) {
ApplicationManager.getApplication().assertReadAccessAllowed();
}
ASTNode parent = element.getTreeParent();
@@ -180,8 +181,8 @@ public class SharedImplUtil {
return count;
}
public static void acceptChildren(PsiElementVisitor visitor, CompositeElement root) {
TreeElement childNode = root.getFirstChildNode();
public static void acceptChildren(PsiElementVisitor visitor, ASTNode root) {
ASTNode childNode = root.getFirstChildNode();
while (childNode != null) {
final PsiElement psi;
@@ -58,7 +58,7 @@ public class StubTreeBuilder {
CharSequence contentAsText = inputData.getContentAsText();
FileContentImpl fileContent = (FileContentImpl)inputData;
PsiFile psi = fileContent.getPsiFileAccountingForUnsavedDocument();
PsiFile psi = fileContent.getPsiFileForPsiDependentIndex();
psi = psi.getViewProvider().getStubBindingRoot();
psi.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, contentAsText);
@@ -82,7 +82,7 @@ public class StubTreeBuilder {
if (stubFileElementType != null) {
StubBuilder stubBuilder = stubFileElementType.getBuilder();
if (stubBuilder instanceof LightStubBuilder) {
LightStubBuilder.FORCED_AST.set(fileContent.getLighterAST());
LightStubBuilder.FORCED_AST.set(fileContent.getLighterASTForPsiDependentIndex());
}
data = stubBuilder.buildStubTree(psi);
}
@@ -79,10 +79,10 @@ public final class FileContentImpl extends UserDataHolderBase implements FileCon
return psi;
}
public @NotNull LighterAST getLighterAST() {
public @NotNull LighterAST getLighterASTForPsiDependentIndex() {
LighterAST lighterAST = getUserData(IndexingDataKeys.LIGHTER_AST_NODE_KEY);
if (lighterAST == null) {
lighterAST = getPsiFileAccountingForUnsavedDocument().getNode().getLighterAST();
lighterAST = getPsiFileForPsiDependentIndex().getNode().getLighterAST();
assert lighterAST != null;
putUserData(IndexingDataKeys.LIGHTER_AST_NODE_KEY, lighterAST);
}
@@ -229,7 +229,7 @@ public final class FileContentImpl extends UserDataHolderBase implements FileCon
myHash = hash;
}
public PsiFile getPsiFileAccountingForUnsavedDocument() {
public PsiFile getPsiFileForPsiDependentIndex() {
Document document = FileDocumentManager.getInstance().getCachedDocument(getFile());
PsiFile psi = null;
if (document != null) {
@@ -119,7 +119,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
if (profile instanceof LightDuplicateProfile && ourEnabledLightProfiles) {
final THashMap<Integer, TIntArrayList> result = new THashMap<Integer, TIntArrayList>();
LighterAST ast = fileContent.getLighterAST();
LighterAST ast = fileContent.getLighterASTForPsiDependentIndex();
assert ast != null;
((LightDuplicateProfile)profile).process(ast, new LightDuplicateProfile.Callback() {
@Override
@@ -134,7 +134,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
MyFragmentsCollector collector = new MyFragmentsCollector(profile, ((LanguageFileType)type).getLanguage());
DuplocateVisitor visitor = profile.createVisitor(collector, true);
visitor.visitNode(fileContent.getPsiFileAccountingForUnsavedDocument());
visitor.visitNode(fileContent.getPsiFileForPsiDependentIndex());
return collector.getMap();
}
@@ -29,20 +29,17 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.util.ui.tree.WideSelectionTreeUI;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.ui.VcsLogUiImpl;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.*;
import java.util.Collection;
import java.util.Collections;
import java.util.EventObject;
@@ -55,6 +52,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
private final ChangesBrowser myChangesBrowser;
private final CheckboxTree myTree;
private final MyTreeCellRenderer myTreeCellRenderer;
private final JScrollPane myScrollPane;
private boolean myShouldRepaint = false;
public PushLog(Project project, final CheckedTreeNode root) {
@@ -113,6 +111,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
}
}
};
myTree.setUI(new MyTreeUi());
myTree.setBorder(new EmptyBorder(2, 0, 0, 0)); //additional vertical indent
myTree.setEditable(true);
myTree.setHorizontalAutoScrollingEnabled(false);
@@ -164,7 +163,6 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
//override default tree behaviour.
myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "");
myTree.setRowHeight(0);
ToolTipManager.sharedInstance().registerComponent(myTree);
PopupHandler.installPopupHandler(myTree, VcsLogUiImpl.POPUP_ACTION_GROUP, COMMIT_MENU);
@@ -176,11 +174,15 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
setDefaultEmptyText();
Splitter splitter = new Splitter(false, 0.7f);
splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree));
myScrollPane = ScrollPaneFactory.createScrollPane(myTree);
myScrollPane.setOpaque(false);
splitter.setFirstComponent(myScrollPane);
splitter.setSecondComponent(myChangesBrowser);
setLayout(new BorderLayout());
add(splitter);
myTree.setMinimumSize(new Dimension(200, myTree.getPreferredSize().height));
myTree.setRowHeight(0);
}
private void updateChangesView() {
@@ -431,4 +433,59 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
}
}
}
private class MyTreeUi extends WideSelectionTreeUI {
private final ComponentListener myTreeSizeListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
// invalidate, revalidate etc may have no 'size' effects, you need to manually invalidateSizes before.
updateSizes();
}
};
private final AncestorListener myTreeAncestorListener = new AncestorListenerAdapter() {
@Override
public void ancestorMoved(AncestorEvent event) {
super.ancestorMoved(event);
updateSizes();
}
};
private void updateSizes() {
treeState.invalidateSizes();
tree.repaint();
}
@Override
protected void installListeners() {
super.installListeners();
tree.addComponentListener(myTreeSizeListener);
tree.addAncestorListener(myTreeAncestorListener);
}
@Override
protected void uninstallListeners() {
tree.removeComponentListener(myTreeSizeListener);
tree.removeAncestorListener(myTreeAncestorListener);
super.uninstallListeners();
}
@Override
protected AbstractLayoutCache.NodeDimensions createNodeDimensions() {
return new NodeDimensionsHandler() {
@Override
public Rectangle getNodeDimensions(Object value, int row, int depth, boolean expanded, Rectangle size) {
Rectangle dimensions = super.getNodeDimensions(value, row, depth, expanded, size);
dimensions.width = myScrollPane != null
? Math.max(myScrollPane.getViewport().getWidth() - getRowX(row, depth), dimensions.width)
: Math.max(myTree.getMinimumSize().width, dimensions.width);
return dimensions;
}
};
}
}
}
@@ -71,7 +71,7 @@ public interface BlockAlignmentProcessor {
@NotNull public final Map<AbstractBlockWrapper, Set<AbstractBlockWrapper>> alignmentMappings;
@NotNull public final Map<LeafBlockWrapper, Set<LeafBlockWrapper>> backwardShiftedAlignedBlocks;
@NotNull public final CommonCodeStyleSettings.IndentOptions indentOptions;
public int maxAlignmentSpaces;
public final int maxAlignmentSpaces;
public Context(@NotNull Document document,
@NotNull AlignmentImpl alignment,
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.codeStyle.autodetect;
import com.intellij.lang.Language;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
@@ -36,9 +37,11 @@ public class IndentOptionsDetectorImpl implements IndentOptionsDetector {
private final PsiFile myFile;
private final Project myProject;
private final Document myDocument;
private final Language myLanguage;
public IndentOptionsDetectorImpl(@NotNull PsiFile file) {
myFile = file;
myLanguage = file.getLanguage();
myProject = file.getProject();
myDocument = PsiDocumentManager.getInstance(myProject).getDocument(myFile);
}
@@ -49,7 +52,7 @@ public class IndentOptionsDetectorImpl implements IndentOptionsDetector {
IndentOptions indentOptions = (IndentOptions)CodeStyleSettingsManager.getSettings(myProject).getIndentOptions(myFile.getFileType()).clone();
if (myDocument != null) {
List<LineIndentInfo> linesInfo = new LineIndentInfoBuilder(myDocument.getCharsSequence()).build();
List<LineIndentInfo> linesInfo = new LineIndentInfoBuilder(myDocument.getCharsSequence(), myLanguage).build();
IndentUsageStatistics stats = new IndentUsageStatisticsImpl(linesInfo);
adjustIndentOptions(indentOptions, stats);
}
@@ -15,9 +15,13 @@
*/
package com.intellij.psi.codeStyle.autodetect;
import com.intellij.lang.Commenter;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageCommenters;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -26,10 +30,12 @@ public class LineIndentInfoBuilder {
private final CharSequence myText;
private final int myLength;
private final Commenter myCommenter;
public LineIndentInfoBuilder(@NotNull CharSequence text) {
public LineIndentInfoBuilder(@NotNull CharSequence text, @Nullable Language language) {
myText = text;
myLength = text.length();
myCommenter = language != null ? LanguageCommenters.INSTANCE.forLanguage(language) : null;
}
@NotNull
@@ -58,7 +64,7 @@ public class LineIndentInfoBuilder {
@NotNull
private LineIndentInfo createInfoFromWhiteSpaceRange(int lineStartOffset, int textStartOffset) {
if (myText.charAt(textStartOffset) == '*') {
if (startsWithComment(textStartOffset)) {
return LineIndentInfo.LINE_WITH_COMMENT;
}
else if (CharArrayUtil.indexOf(myText, "\t", lineStartOffset, textStartOffset) > 0) {
@@ -70,6 +76,25 @@ public class LineIndentInfoBuilder {
}
}
private boolean startsWithComment(int textStartOffset) {
if (myText.charAt(textStartOffset) == '*' || startsWithLineComment(textStartOffset)) {
return true;
}
return false;
}
private boolean startsWithLineComment(int textStartOffset) {
if (myCommenter == null) return false;
String lineCommentPrefix = myCommenter.getLineCommentPrefix();
if (lineCommentPrefix != null && CharArrayUtil.regionMatches(myText, textStartOffset, lineCommentPrefix)) {
return true;
}
return false;
}
private int getLineEndOffset(int lineStartOffset) {
int lineEndOffset = CharArrayUtil.indexOf(myText, "\n", lineStartOffset, myLength);
if (lineEndOffset < 0) {
@@ -567,7 +567,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
private Integer getHashOfContent(FileContent content) throws IOException {
if (myIsPsiBackedIndex && myHasSnapshotMapping && content instanceof FileContentImpl) {
// psi backed index should use existing psi to build index value (FileContentImpl.getPsiFileAccountingForUnsavedDocument())
// psi backed index should use existing psi to build index value (FileContentImpl.getPsiFileForPsiDependentIndex())
// so we should use different bytes to calculate hash(Id)
Integer previouslyCalculatedUncommittedHashId = content.getUserData(ourSavedUncommittedHashIdKey);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -15,14 +15,10 @@
*/
package com.intellij.internal.anomalies;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.objectTree.ObjectNode;
import com.intellij.openapi.util.objectTree.ObjectTree;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -31,7 +27,10 @@ import java.awt.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
/**
* User: Vassiliy.Kudryashov
@@ -169,49 +168,6 @@ public class TopAnomaliesAction extends ActionGroup {
}
};
private static final ResettableAction TOP_DISPOSABLE = new ResettableAction("Disposable") {
TreeSet<Pair<Object, Integer>> top = new TreeSet<Pair<Object, Integer>>(COMPARATOR);
TreeSet<Pair<Object, Integer>> old = new TreeSet<Pair<Object, Integer>>(COMPARATOR);
@Override
public void update(AnActionEvent e) {
e.getPresentation().setText("Top " + LIMIT + " disposables");
}
@Override
void reset() {
top.clear();
old.clear();
}
@Override
public void actionPerformed(AnActionEvent e) {
old = new TreeSet<Pair<Object, Integer>>(top);
top.clear();
ObjectTree<Disposable> tree = Disposer.getTree();
Set<Disposable> roots = tree.getRootObjects();
for (Disposable root : roots) {
checkDisposables(tree, root, top, LIMIT);
}
System.out.println("Top " + LIMIT + " disposables");
for (Pair<Object, Integer> pair : top) {
System.out.println(pair.first.getClass().getName() + " (" + pair.second + " related)" + getChange(old, pair.first, pair.second));
}
}
private void checkDisposables(ObjectTree tree, Object key, Set<Pair<Object, Integer>> top, int limit) {
ObjectNode node = tree.getNode(key);
if (node == null) {
return;
}
Collection children = node.getChildren();
top.add(Pair.create(key, children.size()));
trimToLimit(top, limit);
for (Object child : children) {
checkDisposables(tree, child, top, limit);
}
}
};
private static final ResettableAction RESET_THEM_ALL = new ResettableAction("Reset statistics") {
@Override
@@ -226,7 +182,7 @@ public class TopAnomaliesAction extends ActionGroup {
}
};
private static ResettableAction[] CHILDREN = {TOP_PARENTS, TOP_UI_PROPERTIES, TOP_DISPOSABLE, RESET_THEM_ALL};
private static ResettableAction[] CHILDREN = {TOP_PARENTS, TOP_UI_PROPERTIES, RESET_THEM_ALL};
@Override
public void update(AnActionEvent e) {
@@ -57,7 +57,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
public static boolean CHECK = ApplicationManager.getApplication().isUnitTestMode();
static final VirtualDirectoryImpl NULL_VIRTUAL_FILE =
private static final VirtualDirectoryImpl NULL_VIRTUAL_FILE =
new VirtualDirectoryImpl(-42, null, null, null, LocalFileSystem.getInstance()) {
@Override
public String toString() {
@@ -117,9 +117,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
// in this case we should remove it from there
removeFromArray(indexInReal);
}
if (CHECK) {
assertConsistency(ignoreCase, name);
}
assertConsistency(ignoreCase, name);
}
@Nullable // null if there can't be a child with this name, NULL_VIRTUAL_FILE
@@ -284,7 +282,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
final boolean ignoreCase = !delegate.isCaseSensitive();
synchronized (myData) {
if (allChildrenLoaded()) {
assertConsistency(ignoreCase);
assertConsistency(ignoreCase, "");
return getArraySafely();
}
@@ -333,7 +331,9 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
if (getId() > 0) {
myData.myChildrenIds = result;
assertConsistency(ignoreCase, childrenIds);
if (CHECK) {
assertConsistency(ignoreCase, Arrays.asList(childrenIds));
}
setChildrenLoaded();
}
@@ -341,7 +341,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
}
}
private void assertConsistency(boolean ignoreCase, @NotNull Object... details) {
private void assertConsistency(boolean ignoreCase, @NotNull Object details) {
if (!CHECK || ApplicationInfoImpl.isInPerformanceTest()) return;
int[] childrenIds = myData.myChildrenIds;
for (int i = 1; i < childrenIds.length; i++) {
@@ -595,7 +595,8 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
}
});
new UiNotifyConnector(((RootPaneContainer)frame).getContentPane(), myContainer);
UiNotifyConnector connector = new UiNotifyConnector(((RootPaneContainer)frame).getContentPane(), myContainer);
Disposer.register(myContainer, connector);
}
}
@@ -0,0 +1,107 @@
/*
* Copyright 2000-2014 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.autodetect;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.autodetect.*;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import com.intellij.testFramework.PlatformTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import java.util.List;
public abstract class AbstractIndentAutoDetectionTest extends LightPlatformCodeInsightTestCase {
static {
PlatformTestCase.autodetectPlatformPrefix();
}
@NotNull
protected abstract String getFileNameWithExtension();
@Override
@NotNull
protected abstract String getTestDataPath();
protected void doTestMaxUsedIndent(int indentExpected, int timesUsedExpected) {
IndentUsageInfo maxIndentExpected = new IndentUsageInfo(indentExpected, timesUsedExpected);
IndentUsageInfo indentInfo = getMaxUsedIndentInfo();
Assert.assertEquals("Indent size mismatch", maxIndentExpected.getIndentSize(), indentInfo.getIndentSize());
Assert.assertEquals("Indent size usage number mismatch", maxIndentExpected.getTimesUsed(), indentInfo.getTimesUsed());
}
protected void doTestMaxUsedIndent(int indentExpected) {
IndentUsageInfo indentInfo = getMaxUsedIndentInfo();
Assert.assertEquals("Indent size mismatch", indentExpected, indentInfo.getIndentSize());
}
protected void doTestTabsUsed() {
doTestTabsUsed(null);
}
protected void doTestIndentSize(int expectedIndent) {
doTestIndentSize(null, expectedIndent);
}
protected void doTestTabsUsed(@Nullable CommonCodeStyleSettings.IndentOptions defaultIndentOptions) {
configureByFile(getFileNameWithExtension());
if (defaultIndentOptions != null) {
setIndentOptions(defaultIndentOptions);
}
CommonCodeStyleSettings.IndentOptions options = detectIndentOptions();
Assert.assertTrue("Tab usage not detected", options.USE_TAB_CHARACTER);
}
private void doTestIndentSize(@Nullable CommonCodeStyleSettings.IndentOptions defaultIndentOptions, int expectedIndent) {
configureByFile(getFileNameWithExtension());
if (defaultIndentOptions != null) {
setIndentOptions(defaultIndentOptions);
}
CommonCodeStyleSettings.IndentOptions options = detectIndentOptions();
Assert.assertFalse("Tab usage detected: ", options.USE_TAB_CHARACTER);
Assert.assertEquals("Indent mismatch", expectedIndent, options.INDENT_SIZE);
}
private static void setIndentOptions(@NotNull CommonCodeStyleSettings.IndentOptions defaultIndentOptions) {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptions(myFile.getFileType());
indentOptions.copyFrom(defaultIndentOptions);
}
@NotNull
private static CommonCodeStyleSettings.IndentOptions detectIndentOptions() {
IndentOptionsDetector detector = new IndentOptionsDetectorImpl(myFile);
return detector.getIndentOptions();
}
@NotNull
private IndentUsageInfo getMaxUsedIndentInfo() {
configureByFile(getFileNameWithExtension());
Document document = getDocument(myFile);
List<LineIndentInfo> lines = new LineIndentInfoBuilder(document.getCharsSequence(), myFile.getLanguage()).build();
IndentUsageStatistics statistics = new IndentUsageStatisticsImpl(lines);
return statistics.getKMostUsedIndentInfo(0);
}
}
@@ -15,28 +15,38 @@
*/
package com.intellij.psi.autodetect;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.autodetect.*;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import com.intellij.psi.codeStyle.autodetect.LineIndentInfo;
import com.intellij.psi.codeStyle.autodetect.LineIndentInfoBuilder;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
import java.io.File;
import java.util.List;
public class IndentAutoDetectionTest extends LightPlatformCodeInsightTestCase {
private static final String BASE_PATH = "codeStyle/autodetect/";
public class IndentAutoDetectionTest extends AbstractIndentAutoDetectionTest {
static {
PlatformTestCase.initPlatformLangPrefix();
}
@NotNull
@Override
protected String getTestDataPath() {
return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/')
+ "/platform/platform-tests/testData/"
+ "codeStyle/autodetect/";
}
@NotNull
protected String getFileNameWithExtension() {
return getTestName(true) + ".java";
}
public void testBigFileWithIndent2() {
doTestIndentSize(2);
}
@@ -136,84 +146,12 @@ public class IndentAutoDetectionTest extends LightPlatformCodeInsightTestCase {
);
}
public void doTestMaxUsedIndent(int indentExpected, int timesUsedExpected) {
IndentUsageInfo maxIndentExpected = new IndentUsageInfo(indentExpected, timesUsedExpected);
IndentUsageInfo indentInfo = getMaxUsedIndentInfo();
Assert.assertEquals("Indent size mismatch", maxIndentExpected.getIndentSize(), indentInfo.getIndentSize());
Assert.assertEquals("Indent size usage number mismatch", maxIndentExpected.getTimesUsed(), indentInfo.getTimesUsed());
}
public void doTestMaxUsedIndent(int indentExpected) {
IndentUsageInfo indentInfo = getMaxUsedIndentInfo();
Assert.assertEquals("Indent size mismatch", indentExpected, indentInfo.getIndentSize());
}
private void doTestTabsUsed() {
doTestTabsUsed(null);
}
private void doTestTabsUsed(@Nullable CommonCodeStyleSettings.IndentOptions defaultIndentOptions) {
configureByFile(getTestName(true) + ".java");
if (defaultIndentOptions != null) {
setIndentOptions(defaultIndentOptions);
}
CommonCodeStyleSettings.IndentOptions options = detectIndentOptions();
Assert.assertTrue("Tab usage not detected", options.USE_TAB_CHARACTER);
}
private void doTestIndentSize(int expectedIndent) {
doTestIndentSize(null, expectedIndent);
}
private void doTestIndentSize(@Nullable CommonCodeStyleSettings.IndentOptions defaultIndentOptions, int expectedIndent) {
configureByFile(getTestName(true) + ".java");
if (defaultIndentOptions != null) {
setIndentOptions(defaultIndentOptions);
}
CommonCodeStyleSettings.IndentOptions options = detectIndentOptions();
Assert.assertFalse("Tab usage detected: ", options.USE_TAB_CHARACTER);
Assert.assertEquals("Indent mismatch", expectedIndent, options.INDENT_SIZE);
}
private static void setIndentOptions(@NotNull CommonCodeStyleSettings.IndentOptions defaultIndentOptions) {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
CommonCodeStyleSettings.IndentOptions indentOptions = settings.getIndentOptions(myFile.getFileType());
indentOptions.copyFrom(defaultIndentOptions);
}
@NotNull
private static CommonCodeStyleSettings.IndentOptions detectIndentOptions() {
IndentOptionsDetector detector = new IndentOptionsDetectorImpl(myFile);
return detector.getIndentOptions();
}
@NotNull
private IndentUsageInfo getMaxUsedIndentInfo() {
configureByFile(getTestName(true) + ".java");
Document document = getDocument(myFile);
List<LineIndentInfo> lines = new LineIndentInfoBuilder(document.getCharsSequence()).build();
IndentUsageStatistics statistics = new IndentUsageStatisticsImpl(lines);
return statistics.getKMostUsedIndentInfo(0);
}
private static void doTestLineToIndentMapping(@NotNull CharSequence text, int... spacesForLine) {
List<LineIndentInfo> list = new LineIndentInfoBuilder(text).build();
List<LineIndentInfo> list = new LineIndentInfoBuilder(text, PlainTextLanguage.INSTANCE).build();
Assert.assertEquals(list.size(), spacesForLine.length);
for (int i = 0; i < spacesForLine.length; i++) {
int indentSize = list.get(i).getIndentSize();
Assert.assertEquals("Mismatch on line " + i, spacesForLine[i], indentSize);
}
}
@Override
@NotNull
public String getTestDataPath() {
return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/')
+ "/platform/platform-tests/testData/"
+ BASE_PATH;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -26,24 +26,28 @@ import org.jetbrains.annotations.TestOnly;
import java.util.Collection;
import java.util.Collections;
import java.util.ListIterator;
import java.util.List;
public final class ObjectNode<T> {
final class ObjectNode<T> {
private static final ObjectNode[] EMPTY_ARRAY = new ObjectNode[0];
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.objectTree.ObjectNode");
private final ObjectTree<T> myTree;
private ObjectNode<T> myParent;
private ObjectNode<T> myParent; // guarded by myTree.treeLock
private final T myObject;
private SmartList<ObjectNode<T>> myChildren;
private List<ObjectNode<T>> myChildren; // guarded by myTree.treeLock
private final Throwable myTrace;
private final long myOwnModification;
public ObjectNode(@NotNull ObjectTree<T> tree, @Nullable ObjectNode<T> parentNode, @NotNull T object, long modification, @Nullable final Throwable trace) {
ObjectNode(@NotNull ObjectTree<T> tree,
@Nullable ObjectNode<T> parentNode,
@NotNull T object,
long modification,
@Nullable final Throwable trace) {
myTree = tree;
myParent = parentNode;
myObject = object;
@@ -55,43 +59,36 @@ public final class ObjectNode<T> {
@SuppressWarnings("unchecked")
@NotNull
private ObjectNode<T>[] getChildrenArray() {
synchronized (myTree.treeLock) {
if (myChildren == null || myChildren.isEmpty()) return EMPTY_ARRAY;
return myChildren.toArray(new ObjectNode[myChildren.size()]);
}
List<ObjectNode<T>> children = myChildren;
if (children == null || children.isEmpty()) return EMPTY_ARRAY;
return children.toArray(new ObjectNode[children.size()]);
}
void addChild(@NotNull ObjectNode<T> child) {
synchronized (myTree.treeLock) {
if (myChildren == null) {
myChildren = new SmartList<ObjectNode<T>>();
}
myChildren.add(child);
child.myParent = this;
List<ObjectNode<T>> children = myChildren;
if (children == null) {
myChildren = new SmartList<ObjectNode<T>>(child);
}
else {
children.add(child);
}
child.myParent = this;
}
void removeChild(@NotNull ObjectNode<T> child) {
synchronized (myTree.treeLock) {
assert myChildren != null: "No children to remove child: " + this + ' ' + child;
ListIterator<ObjectNode<T>> iterator = myChildren.listIterator(myChildren.size());
while (iterator.hasPrevious()) {
if (child.equals(iterator.previous())) {
iterator.remove();
return;
}
}
List<ObjectNode<T>> children = myChildren;
if (children != null) {
children.remove(child);
}
child.myParent = null;
}
public ObjectNode<T> getParent() {
synchronized (myTree.treeLock) {
return myParent;
}
ObjectNode<T> getParent() {
return myParent;
}
@NotNull
public Collection<ObjectNode<T>> getChildren() {
Collection<ObjectNode<T>> getChildren() {
synchronized (myTree.treeLock) {
if (myChildren == null) return Collections.emptyList();
return Collections.unmodifiableCollection(myChildren);
@@ -109,7 +106,10 @@ public final class ObjectNode<T> {
LOG.error(t);
}
ObjectNode<T>[] childrenArray = getChildrenArray();
ObjectNode<T>[] childrenArray;
synchronized (myTree.treeLock) {
childrenArray = getChildrenArray();
}
//todo: [kirillk] optimize
for (int i = childrenArray.length - 1; i >= 0; i--) {
childrenArray[i].execute(disposeTree, action);
@@ -145,8 +145,8 @@ public final class ObjectNode<T> {
}
private void remove() {
myTree.putNode(myObject, null);
synchronized (myTree.treeLock) {
myTree.putNode(myObject, null);
if (myParent == null) {
myTree.removeRootObject(myObject);
}
@@ -157,10 +157,11 @@ public final class ObjectNode<T> {
}
@NotNull
public T getObject() {
T getObject() {
return myObject;
}
@Override
@NonNls
public String toString() {
return "Node: " + myObject.toString();
@@ -196,11 +197,12 @@ public final class ObjectNode<T> {
<D extends Disposable> D findChildEqualTo(@NotNull D object) {
synchronized (myTree.treeLock) {
SmartList<ObjectNode<T>> children = myChildren;
List<ObjectNode<T>> children = myChildren;
if (children != null) {
for (ObjectNode<T> node : children) {
T nodeObject = node.getObject();
if (nodeObject.equals(object)) {
//noinspection unchecked
return (D)nodeObject;
}
}
@@ -34,28 +34,26 @@ public final class ObjectTree<T> {
private final List<ObjectTreeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
// identity used here to prevent problems with hashCode/equals overridden by not very bright minds
private final Set<T> myRootObjects = ContainerUtil.newIdentityTroveSet();
private final Map<T, ObjectNode<T>> myObject2NodeMap = ContainerUtil.newIdentityTroveMap();
private final Set<T> myRootObjects = ContainerUtil.newIdentityTroveSet(); // guarded by treeLock
private final Map<T, ObjectNode<T>> myObject2NodeMap = ContainerUtil.newIdentityTroveMap(); // guarded by treeLock
private final List<ObjectNode<T>> myExecutedNodes = new ArrayList<ObjectNode<T>>();
private final List<T> myExecutedUnregisteredNodes = new ArrayList<T>();
private final List<ObjectNode<T>> myExecutedNodes = new ArrayList<ObjectNode<T>>(); // guarded by myExecutedNodes
private final List<T> myExecutedUnregisteredNodes = new ArrayList<T>(); // guarded by myExecutedUnregisteredNodes
final Object treeLock = new Object();
private final AtomicLong myModification = new AtomicLong(0);
public ObjectNode<T> getNode(@NotNull T object) {
synchronized (treeLock) {
return myObject2NodeMap.get(object);
}
}
public ObjectNode<T> putNode(@NotNull T object, @Nullable("null means remove") ObjectNode<T> node) {
synchronized (treeLock) {
return node == null ? myObject2NodeMap.remove(object) : myObject2NodeMap.put(object, node);
}
ObjectNode<T> getNode(@NotNull T object) {
return myObject2NodeMap.get(object);
}
public final List<ObjectNode<T>> getNodesInExecution() {
ObjectNode<T> putNode(@NotNull T object, @Nullable("null means remove") ObjectNode<T> node) {
return node == null ? myObject2NodeMap.remove(object) : myObject2NodeMap.put(object, node);
}
@NotNull
final List<ObjectNode<T>> getNodesInExecution() {
return myExecutedNodes;
}
@@ -105,8 +103,7 @@ public final class ObjectTree<T> {
@NotNull
private ObjectNode<T> createNodeFor(@NotNull T object, @Nullable ObjectNode<T> parentNode, @Nullable final Throwable trace) {
final ObjectNode<T> newNode = new ObjectNode<T>(this, parentNode, object, getNextModification(),
trace);
final ObjectNode<T> newNode = new ObjectNode<T>(this, parentNode, object, getNextModification(), trace);
if (parentNode == null) {
myRootObjects.add(object);
}
@@ -114,12 +111,15 @@ public final class ObjectTree<T> {
return newNode;
}
public long getNextModification() {
private long getNextModification() {
return myModification.incrementAndGet();
}
public final boolean executeAll(@NotNull T object, boolean disposeTree, @NotNull ObjectTreeAction<T> action, boolean processUnregistered) {
ObjectNode<T> node = getNode(object);
ObjectNode<T> node;
synchronized (treeLock) {
node = getNode(object);
}
if (node == null) {
if (processUnregistered) {
executeUnregistered(object, action);
@@ -147,7 +147,7 @@ public final class ObjectTree<T> {
}
finally {
synchronized (recursiveGuard) {
int i = ArrayUtil.indexOf(recursiveGuard, object, Equality.IDENTITY);
int i = ArrayUtil.lastIndexOf(recursiveGuard, object, Equality.IDENTITY);
assert i != -1;
recursiveGuard.remove(i);
}
@@ -159,11 +159,12 @@ public final class ObjectTree<T> {
}
public final void executeChildAndReplace(@NotNull T toExecute, @NotNull T toReplace, boolean disposeTree, @NotNull ObjectTreeAction<T> action) {
final ObjectNode<T> toExecuteNode = getNode(toExecute);
assert toExecuteNode != null : "Object " + toExecute + " wasn't registered or already disposed";
final ObjectNode<T> toExecuteNode;
T parentObject;
synchronized (treeLock) {
toExecuteNode = getNode(toExecute);
assert toExecuteNode != null : "Object " + toExecute + " wasn't registered or already disposed";
final ObjectNode<T> parent = toExecuteNode.getParent();
assert parent != null : "Object " + toExecute + " is not connected to the tree - doesn't have parent";
parentObject = parent.getObject();
@@ -174,11 +175,13 @@ public final class ObjectTree<T> {
}
public boolean containsKey(@NotNull T object) {
return getNode(object) != null;
synchronized (treeLock) {
return getNode(object) != null;
}
}
@TestOnly
public void assertNoReferenceKeptInTree(@NotNull T disposable) {
void assertNoReferenceKeptInTree(@NotNull T disposable) {
synchronized (treeLock) {
Collection<ObjectNode<T>> nodes = myObject2NodeMap.values();
for (ObjectNode<T> node : nodes) {
@@ -187,57 +190,53 @@ public final class ObjectTree<T> {
}
}
public void removeRootObject(@NotNull T object) {
synchronized (treeLock) {
myRootObjects.remove(object);
}
void removeRootObject(@NotNull T object) {
myRootObjects.remove(object);
}
@SuppressWarnings({"UseOfSystemOutOrSystemErr", "HardCodedStringLiteral"})
public void assertIsEmpty(boolean throwError) {
for (T object : myRootObjects) {
if (object == null) continue;
final ObjectNode<T> objectNode = getNode(object);
if (objectNode == null) continue;
synchronized (treeLock) {
for (T object : myRootObjects) {
if (object == null) continue;
final ObjectNode<T> objectNode = getNode(object);
if (objectNode == null) continue;
final Throwable trace = objectNode.getTrace();
RuntimeException exception = new RuntimeException("Memory leak detected: " + object + " of class " + object.getClass()
+ "\nSee the cause for the corresponding Disposer.register() stacktrace:\n",
trace);
if (throwError) {
throw exception;
final Throwable trace = objectNode.getTrace();
RuntimeException exception = new RuntimeException("Memory leak detected: " + object + " of class " + object.getClass()
+ "\nSee the cause for the corresponding Disposer.register() stacktrace:\n",
trace);
if (throwError) {
throw exception;
}
LOG.error(exception);
}
LOG.error(exception);
}
}
@TestOnly
public boolean isEmpty() {
return myRootObjects.isEmpty();
}
@TestOnly
public void clearAll() {
myRootObjects.clear();
myExecutedNodes.clear();
myExecutedUnregisteredNodes.clear();
myObject2NodeMap.clear();
synchronized (treeLock) {
return myRootObjects.isEmpty();
}
}
@NotNull
public Set<T> getRootObjects() {
return myRootObjects;
Set<T> getRootObjects() {
synchronized (treeLock) {
return myRootObjects;
}
}
public void addListener(@NotNull ObjectTreeListener listener) {
void addListener(@NotNull ObjectTreeListener listener) {
myListeners.add(listener);
}
public void removeListener(@NotNull ObjectTreeListener listener) {
void removeListener(@NotNull ObjectTreeListener listener) {
myListeners.remove(listener);
}
void fireRegistered(@NotNull Object object) {
private void fireRegistered(@NotNull Object object) {
for (ObjectTreeListener each : myListeners) {
each.objectRegistered(object);
}
@@ -249,8 +248,10 @@ public final class ObjectTree<T> {
}
}
public int size() {
return myObject2NodeMap.size();
int size() {
synchronized (treeLock) {
return myObject2NodeMap.size();
}
}
@Nullable
@@ -262,7 +263,7 @@ public final class ObjectTree<T> {
}
}
public long getModification() {
long getModification() {
return myModification.get();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -160,7 +160,7 @@ public class PersistentHashMapValueStorage {
final PersistentHashMap.CompactionRecordInfo info = records.peek();
if (info.valueAddress >= readStartOffset) {
if (info.valueAddress >= lastReadOffset) {
throw new IOException("Value storage is corrupted: value file size:" + mySize + ", readStartOffset:"+ readStartOffset + ", record address:"+info.valueAddress);
throw new IOException("Value storage is corrupted: value file size:" + mySize + ", readStartOffset:"+ readStartOffset + ", record address:"+info.valueAddress+"; file: "+myPath);
}
// record start is inside our buffer
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.util;
package com.intellij.openapi.util.objectTree;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import junit.framework.TestCase;
import org.jetbrains.annotations.NonNls;
@@ -201,7 +201,7 @@ public class ChangesViewManager implements ChangesViewI, JDOMExternalizable, Pro
}
});
if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
myContent = ContentFactory.SERVICE.getInstance().createContent(createChangeViewComponent(), "Local", false);
myContent = ContentFactory.SERVICE.getInstance().createContent(createChangeViewComponent(), ChangesViewContentManager.LOCAL_CHANGES, false);
myContent.setCloseable(false);
myContentManager.addContent(myContent);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -53,7 +53,7 @@ public class SelectInChangesViewTarget implements SelectInTarget, DumbAware {
final VirtualFile file = context.getVirtualFile();
Runnable runnable = new Runnable() {
public void run() {
ChangesViewContentManager.getInstance(myProject).selectContent("Local");
ChangesViewContentManager.getInstance(myProject).selectContent(ChangesViewContentManager.LOCAL_CHANGES);
ChangesViewManager.getInstance(myProject).selectFile(file);
}
};
@@ -185,7 +185,7 @@ public class ShelvedChangesViewManager implements ProjectComponent {
if (changeLists.size() == 0) {
if (myContent != null) {
myContentManager.removeContent(myContent);
myContentManager.selectContent("Local");
myContentManager.selectContent(ChangesViewContentManager.LOCAL_CHANGES);
}
myContent = null;
}
@@ -283,7 +283,11 @@ public class ChangesViewContentManager extends AbstractProjectComponent implemen
}
}
private static final String[] ourPresetOrder = {"Local", "Repository", "Incoming", "Shelf"};
public static final String LOCAL_CHANGES = Registry.is("vcs.merge.toolwindows") ? "Local Changes" : "Local";
public static final String REPOSITORY = "Repository";
public static final String INCOMING = "Incoming";
public static final String SHELF = "Shelf";
private static final String[] ourPresetOrder = {LOCAL_CHANGES, REPOSITORY, INCOMING, SHELF};
private static List<Content> doPresetOrdering(final List<Content> contents) {
final List<Content> result = new ArrayList<Content>(contents.size());
for (final String preset : ourPresetOrder) {
@@ -91,7 +91,7 @@ class VisiblePackBuilder {
}
VisibleGraph<Integer> visibleGraph;
if (((matchingHeads != null) && matchingHeads.isEmpty()) || ((matchingCommits != null) && matchingCommits.isEmpty())) {
if (matchesNothing(matchingHeads) || matchesNothing(matchingCommits)) {
visibleGraph = EmptyVisibleGraph.getInstance();
}
else {
@@ -100,6 +100,10 @@ class VisiblePackBuilder {
return Pair.create(new VisiblePack(dataPack, visibleGraph, canRequestMore), commitCount);
}
private static <T> boolean matchesNothing(@Nullable Collection<T> matchingSet) {
return matchingSet != null && matchingSet.isEmpty();
}
private VisiblePack applyHashFilter(@NotNull DataPack dataPack,
@NotNull Collection<String> hashes,
@NotNull PermanentGraph.SortType sortType) {
@@ -160,25 +164,24 @@ class VisiblePackBuilder {
@NotNull final PermanentGraph<Integer> permanentGraph,
@NotNull List<VcsLogDetailsFilter> detailsFilters,
@Nullable final Set<Integer> matchingHeads) {
final int commitIndex = myHashMap.getCommitIndex(commit.getId());
return ContainerUtil.and(detailsFilters, new Condition<VcsLogDetailsFilter>() {
boolean matchesAllDetails = ContainerUtil.and(detailsFilters, new Condition<VcsLogDetailsFilter>() {
@Override
public boolean value(VcsLogDetailsFilter filter) {
if (!filter.matches(commit)) {
return false;
}
if (matchingHeads == null) {
return true;
}
Set<Integer> containingBranches = permanentGraph.getContainingBranches(commitIndex);
return ContainerUtil.exists(containingBranches, new Condition<Integer>() {
@Override
public boolean value(Integer integer) {
return matchingHeads.contains(integer);
}
});
return filter.matches(commit);
}
});
return matchesAllDetails && matchesAnyHead(permanentGraph, commit, matchingHeads);
}
private boolean matchesAnyHead(@NotNull PermanentGraph<Integer> permanentGraph,
@NotNull VcsCommitMetadata commit,
@Nullable Set<Integer> matchingHeads) {
if (matchingHeads == null) {
return true;
}
// TODO O(n^2)
int commitIndex = myHashMap.getCommitIndex(commit.getId());
return ContainerUtil.intersects(permanentGraph.getContainingBranches(commitIndex), matchingHeads);
}
@Nullable
@@ -16,11 +16,14 @@
package com.intellij.vcs.log.impl;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.DataOutputStream;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import java.io.*;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
@@ -30,7 +33,7 @@ public class HashSerializeTest {
public void full_hash() throws IOException {
HashImpl hash = (HashImpl)HashImpl.build("d35ee91fad4a04bce0ea91a762cc8f3bf3e1929f");
File file = writeToTempFile(hash);
HashImpl newHash = readFromFile(file);
HashImpl newHash = readFromFile(file).get(0);
assertEquals(hash, newHash);
}
@@ -38,16 +41,28 @@ public class HashSerializeTest {
public void short_hash() throws IOException {
HashImpl hash = (HashImpl)HashImpl.build("d35ee91");
File file = writeToTempFile(hash);
HashImpl newHash = readFromFile(file);
HashImpl newHash = readFromFile(file).get(0);
assertEquals(hash, newHash);
}
@Test
public void two_different_hashes() throws IOException {
HashImpl hash1 = (HashImpl)HashImpl.build("d35ee91");
HashImpl hash2 = (HashImpl)HashImpl.build("d35ee91fad4a04bce0ea91a762cc8f3bf3e1929f");
File file = writeToTempFile(hash1, hash2);
List<HashImpl> hashes = readFromFile(file);
assertEquals(Arrays.asList(hash1, hash2), hashes);
}
@NotNull
private static File writeToTempFile(@NotNull HashImpl hash) throws IOException {
private static File writeToTempFile(@NotNull HashImpl... hashes) throws IOException {
File file = FileUtil.createTempFile("", "");
DataOutputStream out = new DataOutputStream(new FileOutputStream(file));
try {
hash.write(out);
for (HashImpl hash : hashes) {
hash.write(out);
}
}
finally {
out.close();
@@ -56,15 +71,17 @@ public class HashSerializeTest {
}
@NotNull
private static HashImpl readFromFile(@NotNull File file) throws IOException {
HashImpl newHash;
private static List<HashImpl> readFromFile(@NotNull File file) throws IOException {
List<HashImpl> result = ContainerUtil.newArrayList();
DataInputStream in = new DataInputStream(new FileInputStream(file));
try {
newHash = (HashImpl)HashImpl.read(in);
while (in.available() > 0) {
result.add((HashImpl)HashImpl.read(in));
}
}
finally {
in.close();
}
return newHash;
return result;
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

+2 -2
View File
@@ -119,7 +119,7 @@ def _NormFile(filename):
if r[ind] == "!":
ind+=1
inner_path = r[ind:]
if inner_path.startswith('/'):
if inner_path.startswith('/') or inner_path.startswith('\\'):
inner_path = inner_path[1:]
r = zip_path + "/" + inner_path
@@ -152,7 +152,7 @@ def exists(file):
return None
try:
if inner_path.startswith('/'):
if inner_path.startswith('/') or inner_path.startswith('\\'):
inner_path = inner_path[1:]
info = zip.getinfo(inner_path)
@@ -1,5 +1,7 @@
package com.jetbrains.python.debugger.pydev;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -202,6 +204,17 @@ public class MultiProcessDebugger implements ProcessDebugger {
return debugger;
}
else {
// thread is not found in registry - lets search for it in attached debuggers
for (ProcessDebugger d : myOtherDebuggers) {
for (PyThreadInfo thread : d.getThreads()) {
if (threadId.equals(thread.getId())) {
return d;
}
}
}
//if not found then return main debugger
return myMainDebugger;
}
}
@@ -240,37 +253,48 @@ public class MultiProcessDebugger implements ProcessDebugger {
@Override
public Collection<PyThreadInfo> getThreads() {
List<PyThreadInfo> threads = Lists.newArrayList(myMainDebugger.getThreads());
List<PyThreadInfo> result = Lists.newArrayList();
cleanOtherDebuggers();
collectAndRegisterOtherDebuggersThreads(threads); //we don't register mainDebugger as it is default if there is no mapping
List<PyThreadInfo> threads = collectAllThreads();
if (myOtherDebuggers.size() > 0) {
//here we add process id to thread name in case there are more then one process
threads = addProcessIdToThreadName(threads, result);
return Collections.unmodifiableCollection(Collections2.transform(threads, new Function<PyThreadInfo, PyThreadInfo>() {
@Override
public PyThreadInfo apply(PyThreadInfo t) {
String threadName = ThreadRegistry.threadName(t.getName(), t.getId());
PyThreadInfo newThread =
new PyThreadInfo(t.getId(), threadName, t.getFrames(),
t.getStopReason(),
t.getMessage());
newThread.updateState(t.getState(), t.getFrames());
return newThread;
}
}));
}
else {
return Collections.unmodifiableCollection(threads);
}
return Collections.unmodifiableCollection(threads);
}
private static List<PyThreadInfo> addProcessIdToThreadName(List<PyThreadInfo> threads, List<PyThreadInfo> result) {
for (PyThreadInfo t : threads) {
String threadName = ThreadRegistry.threadName(t.getName(), t.getId());
PyThreadInfo newThread =
new PyThreadInfo(t.getId(), threadName, t.getFrames(),
t.getStopReason(),
t.getMessage());
newThread.updateState(t.getState(), t.getFrames());
result.add(newThread);
private List<PyThreadInfo> collectAllThreads() {
List<PyThreadInfo> result = Lists.newArrayList();
result.addAll(myMainDebugger.getThreads());
//collect threads and add them to registry to faster access
//we don't register mainDebugger as it is default if there is no mapping
for (RemoteDebugger d : myOtherDebuggers) {
result.addAll(d.getThreads());
for (PyThreadInfo t : d.getThreads()) {
myThreadRegistry.register(t.getId(), d);
}
}
threads = result;
return threads;
return result;
}
private void cleanOtherDebuggers() {
synchronized (myOtherDebuggers) {
removeDisconnected(getOtherDebuggers());
@@ -299,15 +323,6 @@ public class MultiProcessDebugger implements ProcessDebugger {
}
}
private void collectAndRegisterOtherDebuggersThreads(List<PyThreadInfo> threads) {
for (RemoteDebugger d : getOtherDebuggers()) {
threads.addAll(d.getThreads());
for (PyThreadInfo t : d.getThreads()) {
myThreadRegistry.register(t.getId(), d);
}
}
}
private ArrayList<RemoteDebugger> getOtherDebuggers() {
synchronized (myOtherDebuggers) {
return Lists.newArrayList(myOtherDebuggers);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 84 KiB

@@ -532,6 +532,8 @@ public class PydevConsoleCommunication extends AbstractConsoleCommunication impl
public void changeVariable(PyDebugValue variable, String value) throws PyDebuggerException {
if (myClient != null) {
try {
// NOTE: The actual change is being scheduled in the exec_queue in main thread
// This method is async now
Object ret = myClient.execute(CHANGE_VARIABLE, new Object[]{variable.getEvaluationExpression(), value});
checkError(ret);
}
@@ -122,8 +122,9 @@ public class PythonConsoleTest extends PyEnvTestCase {
setValue("x", "2");
assertTrue("Variable has wrong value",
hasValue("x", "2"));
exec("print(x)");
waitForOutput("2");
}
});
}