mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.intellij.lang.regexp;
|
||||
|
||||
import com.intellij.application.options.colors.InspectionColorSettingsPage;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
import com.intellij.openapi.options.colors.AttributesDescriptor;
|
||||
@@ -31,13 +30,20 @@ import java.util.Map;
|
||||
/**
|
||||
* @author traff
|
||||
*/
|
||||
public class RegExpColorsPage implements ColorSettingsPage, InspectionColorSettingsPage {
|
||||
public class RegExpColorsPage implements ColorSettingsPage {
|
||||
private static final AttributesDescriptor[] ATTRS = new AttributesDescriptor[] {
|
||||
new AttributesDescriptor("Keywords", RegExpHighlighter.META),
|
||||
new AttributesDescriptor("Escaped characters", RegExpHighlighter.ESC_CHARACTER),
|
||||
new AttributesDescriptor("Braces", RegExpHighlighter.BRACES),
|
||||
new AttributesDescriptor("Brackets", RegExpHighlighter.BRACKETS),
|
||||
new AttributesDescriptor("Keyword", RegExpHighlighter.META),
|
||||
new AttributesDescriptor("Escaped character", RegExpHighlighter.ESC_CHARACTER),
|
||||
new AttributesDescriptor("Invalid escape sequence", RegExpHighlighter.INVALID_CHARACTER_ESCAPE),
|
||||
new AttributesDescriptor("Redundant escape sequence", RegExpHighlighter.REDUNDANT_ESCAPE),
|
||||
new AttributesDescriptor("Brace", RegExpHighlighter.BRACES),
|
||||
new AttributesDescriptor("Bracket", RegExpHighlighter.BRACKETS),
|
||||
new AttributesDescriptor("Parenthesis", RegExpHighlighter.PARENTHS),
|
||||
new AttributesDescriptor("Comma", RegExpHighlighter.COMMA),
|
||||
new AttributesDescriptor("Bad character", RegExpHighlighter.BAD_CHARACTER),
|
||||
new AttributesDescriptor("Character class", RegExpHighlighter.CHAR_CLASS),
|
||||
new AttributesDescriptor("Quote character", RegExpHighlighter.QUOTE_CHARACTER),
|
||||
new AttributesDescriptor("Comment", RegExpHighlighter.COMMENT)
|
||||
};
|
||||
|
||||
@NonNls private static final HashMap<String,TextAttributesKey> ourTagToDescriptorMap = new HashMap<String, TextAttributesKey>();
|
||||
@@ -71,7 +77,7 @@ public class RegExpColorsPage implements ColorSettingsPage, InspectionColorSetti
|
||||
@NotNull
|
||||
public String getDemoText() {
|
||||
return
|
||||
"^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}$";
|
||||
"^[\\w\\.-]+@([\\w\\-]+\\.)+[A-Z]{2,4}\\x0g\\#\\p{alpha}\\Q\\E$";
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -78,10 +78,6 @@ class RegExpHighlighter extends SyntaxHighlighterBase {
|
||||
"REGEXP.QUOTE_CHARACTER",
|
||||
SyntaxHighlighterColors.VALID_STRING_ESCAPE.getDefaultAttributes()
|
||||
);
|
||||
static final TextAttributesKey CTRL_CHARACTER = TextAttributesKey.createTextAttributesKey(
|
||||
"REGEXP.CTRL_CHARACTER",
|
||||
SyntaxHighlighterColors.VALID_STRING_ESCAPE.getDefaultAttributes()
|
||||
);
|
||||
static final TextAttributesKey COMMENT = TextAttributesKey.createTextAttributesKey(
|
||||
"REGEXP.COMMENT",
|
||||
SyntaxHighlighterColors.LINE_COMMENT.getDefaultAttributes()
|
||||
@@ -108,7 +104,6 @@ class RegExpHighlighter extends SyntaxHighlighterBase {
|
||||
keys1.put(RegExpTT.BAD_HEX_VALUE, INVALID_CHARACTER_ESCAPE);
|
||||
keys1.put(RegExpTT.BAD_OCT_VALUE, INVALID_CHARACTER_ESCAPE);
|
||||
|
||||
keys1.put(RegExpTT.CTRL_CHARACTER, CTRL_CHARACTER);
|
||||
keys1.put(RegExpTT.PROPERTY, CHAR_CLASS);
|
||||
|
||||
keys1.put(RegExpTT.ESC_CHARACTER, ESC_CHARACTER);
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
:: ---------------------------------------------------------------------
|
||||
:: Before you run IntelliJ IDEA specify the location of the
|
||||
:: JDK 1.5 installation directory which will be used for running IDEA
|
||||
:: JDK 1.6 installation directory which will be used for running IDEA
|
||||
:: ---------------------------------------------------------------------
|
||||
IF "%IDEA_JDK%" == "" SET IDEA_JDK=%JDK_HOME%
|
||||
IF "%IDEA_JDK%" == "" goto error
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
IntelliJ IDEA
|
||||
|
||||
INSTALLATION INSTRUCTIONS
|
||||
===============================================================================
|
||||
|
||||
Linux Installation Instructions
|
||||
------------------------------------------------------------------------------
|
||||
1. Unpack the IntelliJ IDEA distribution file that you downloaded to
|
||||
where you wish to install the program. We will refer to this destination
|
||||
location as your {installation home} below.
|
||||
|
||||
2. Open a console and cd into "{installation home}/bin" and type:
|
||||
|
||||
./idea.sh
|
||||
|
||||
to start the application.
|
||||
|
||||
3. [OPTIONAL] Add the "{installation home}/bin" to your PATH environmental
|
||||
variable so that you may start IntelliJ IDEA from any directory.
|
||||
|
||||
4. [OPTIONAL] To adjust the value of JVM heap size open idea.vmoptions and
|
||||
modify the -Xms and -Xmx parameters.
|
||||
|
||||
|
||||
[OPTIONAL] Changing location of "config" and "system" directory
|
||||
------------------------------------------------------------------------------
|
||||
By default IDEA stores all your settings under ~/.IntelliJIdea10/config directory
|
||||
and stores data cache under ~/.IntelliJIdea10/system directory.
|
||||
If you want to change these settings,
|
||||
|
||||
1. Open a console and cd into "{installation home}/bin"
|
||||
|
||||
2. Open file "idea.properties" in an editor. You should find strings like
|
||||
|
||||
idea.system.path=~/.IntelliJIdea10/system
|
||||
|
||||
and
|
||||
|
||||
idea.config.path=~/.IntelliJIdea10/config
|
||||
|
||||
and change them.
|
||||
|
||||
3. Note that we recommend to store data cache ("system" directory) at a disk
|
||||
with at least 1G bytes free space
|
||||
|
||||
|
||||
|
||||
|
||||
Enjoy!
|
||||
|
||||
-IntelliJ IDEA Development Team
|
||||
@@ -198,6 +198,7 @@ def layoutLinux(Map args, String home, Paths paths) {
|
||||
fileset(dir: "$home/bin/nix")
|
||||
fileset(dir: "$home/build/images")
|
||||
}
|
||||
fileset(dir: "$home/build", includes: "Install-Linux-tar.txt")
|
||||
}
|
||||
|
||||
patchPropertiesFile(paths.distUnix)
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
<feedback eap-url="http://youtrack.jetbrains.net" release-url="http://www.jetbrains.com/feedback/feedback.jsp?product=IDEA&build=$BUILD&timezone=$TIMEZONE&eval=$EVAL"/>
|
||||
<plugins url="http://plugins.intellij.net"/>
|
||||
<whatsnew url="http://www.jetbrains.com/idea/whatsnew/index.html"/>
|
||||
<keymap win="http://www.jetbrains.com/idea/docs/IntelliJIDEA9_ReferenceCard.pdf"
|
||||
mac="http://www.jetbrains.com/idea/docs/IntelliJIDEA9_ReferenceCard_Mac.pdf"/>
|
||||
<keymap win="http://www.jetbrains.com/idea/docs/IntelliJIDEA_ReferenceCard.pdf"
|
||||
mac="http://www.jetbrains.com/idea/docs/IntelliJIDEA_ReferenceCard_Mac.pdf"/>
|
||||
|
||||
<plugins-page category="VCS Integration" title="Select VCS Integration Plugins"/>
|
||||
<plugins-page title="Select Other Plugins"/>
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.impl.ModuleRootManagerImpl;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryTableBase;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
@@ -427,7 +428,7 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
|
||||
new LibraryInvocationHandler((Library)result));
|
||||
}
|
||||
else if (result instanceof LibraryTable.ModifiableModel) {
|
||||
return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{LibraryTable.ModifiableModel.class},
|
||||
return Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{LibraryTableBase.ModifiableModelEx.class},
|
||||
new LibraryTableModelInvocationHandler((LibraryTable.ModifiableModel)result));
|
||||
}
|
||||
if (result instanceof Library[]) {
|
||||
|
||||
@@ -17,12 +17,15 @@ package com.intellij.psi.formatter.java;
|
||||
|
||||
import com.intellij.formatting.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.FormatterUtil;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaDocElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.impl.source.tree.StdTokenSets;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -30,6 +33,10 @@ import java.util.List;
|
||||
|
||||
public class BlockContainingJavaBlock extends AbstractJavaBlock{
|
||||
|
||||
private static final TokenSet TYPES_OF_STATEMENTS_WITH_OPTIONAL_BRACES = TokenSet.create(
|
||||
JavaElementType.IF_STATEMENT, JavaElementType.WHILE_STATEMENT, JavaElementType.FOR_STATEMENT
|
||||
);
|
||||
|
||||
private final static int BEFORE_FIRST = 0;
|
||||
private final static int BEFORE_BLOCK = 1;
|
||||
private final static int AFTER_ELSE = 2;
|
||||
@@ -207,12 +214,37 @@ public class BlockContainingJavaBlock extends AbstractJavaBlock{
|
||||
return new ChildAttributes(getCodeBlockExternalIndent(), null);
|
||||
}
|
||||
|
||||
boolean useExternalIndent = false;
|
||||
if (newChildIndex == getSubBlocks().size()) {
|
||||
useExternalIndent = true;
|
||||
}
|
||||
else if (TYPES_OF_STATEMENTS_WITH_OPTIONAL_BRACES.contains(myNode.getElementType())) {
|
||||
// There is a possible case that we have situation like below:
|
||||
// if (true) <enter was pressed here>
|
||||
// <caret>
|
||||
// System.out.println();
|
||||
// We would like to indent current caret position then because there is a high probability that the user starts
|
||||
// typing there (populating statement body). So, we perform dedicated check for that here and use 'external indent'
|
||||
// if necessary.
|
||||
Block prevBlock = getSubBlocks().get(newChildIndex - 1);
|
||||
Block nextBlock = getSubBlocks().get(newChildIndex);
|
||||
if (prevBlock instanceof ASTBlock && nextBlock instanceof ASTBlock) {
|
||||
ASTNode prevNode = ((ASTBlock)prevBlock).getNode();
|
||||
ASTNode nextNode = ((ASTBlock)nextBlock).getNode();
|
||||
if (prevNode != null && nextNode != null && prevNode.getElementType() == JavaTokenType.RPARENTH
|
||||
&& nextNode.getElementType() != JavaTokenType.LBRACE)
|
||||
{
|
||||
useExternalIndent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (useExternalIndent) {
|
||||
return new ChildAttributes(getCodeBlockChildExternalIndent(newChildIndex), null);
|
||||
}
|
||||
|
||||
return new ChildAttributes(myIndentsBefore.get(newChildIndex), null);
|
||||
|
||||
else {
|
||||
return new ChildAttributes(myIndentsBefore.get(newChildIndex), null);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInsideForParens(final int newChildIndex) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.unscramble;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationAdapter;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
@@ -32,8 +33,9 @@ public class UnscrambleListener extends ApplicationAdapter {
|
||||
final String clipboard = AnalyzeStacktraceUtil.getTextInClipboard();
|
||||
if (clipboard != null && clipboard.length() < MAX_STACKTRACE_SIZE && !clipboard.equals(stacktrace)) {
|
||||
stacktrace = clipboard;
|
||||
if (isStacktrace(stacktrace)) {
|
||||
final UnscrambleDialog dialog = new UnscrambleDialog(ideFrame.getProject());
|
||||
final Project project = ideFrame.getProject();
|
||||
if (project != null && isStacktrace(stacktrace)) {
|
||||
final UnscrambleDialog dialog = new UnscrambleDialog(project);
|
||||
dialog.createNormalizeTextAction().actionPerformed(null);
|
||||
dialog.doOKAction();
|
||||
}
|
||||
|
||||
+20
-15
@@ -15,29 +15,42 @@
|
||||
*/
|
||||
package com.intellij.rt.execution.junit.segments;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public abstract class OutputObjectRegistry {
|
||||
private final Hashtable myKnownKeys = new Hashtable();
|
||||
private int myLastIndex = 0;
|
||||
private PacketProcessor myMainTransport;
|
||||
private PacketProcessor myAuxilaryTransport;
|
||||
|
||||
public OutputObjectRegistry(PacketProcessor transport) {
|
||||
myMainTransport = transport;
|
||||
}
|
||||
|
||||
public OutputObjectRegistry(PacketProcessor mainTransport, PacketProcessor auxilaryTransport) {
|
||||
this(mainTransport);
|
||||
myAuxilaryTransport = auxilaryTransport;
|
||||
}
|
||||
|
||||
public String referenceTo(Object test) {
|
||||
if (myKnownKeys.containsKey(test))
|
||||
return (String) myKnownKeys.get(test);
|
||||
return sendObject(test);
|
||||
}
|
||||
|
||||
public String referenceTo(Object test, Collection packets) {
|
||||
if (myKnownKeys.containsKey(test))
|
||||
return (String) myKnownKeys.get(test);
|
||||
return sendObject(test, packets);
|
||||
}
|
||||
|
||||
private String sendObject(Object test, Collection packets) {
|
||||
String key = String.valueOf(myLastIndex++);
|
||||
myKnownKeys.put(test, key);
|
||||
final Packet packet = createPacket();
|
||||
packet.addString(PoolOfDelimiters.OBJECT_PREFIX).addReference(key);
|
||||
addStringRepresentation(test, packet);
|
||||
packet.addLong(getTestCont(test));
|
||||
packet.addString(PoolOfDelimiters.REFERENCE_END_STR);
|
||||
packets.add(packet);
|
||||
return key;
|
||||
}
|
||||
|
||||
public Packet createPacket() {
|
||||
return new Packet(myMainTransport, this);
|
||||
}
|
||||
@@ -48,21 +61,13 @@ public abstract class OutputObjectRegistry {
|
||||
Packet packet = createPacket().addString(PoolOfDelimiters.OBJECT_PREFIX).addReference(key);
|
||||
addStringRepresentation(test, packet);
|
||||
packet.addLong(getTestCont(test));
|
||||
sendViaAllTransports(packet);
|
||||
packet.send();
|
||||
return key;
|
||||
}
|
||||
|
||||
protected abstract int getTestCont(Object test);
|
||||
protected abstract void addStringRepresentation(Object test, Packet packet);
|
||||
|
||||
private void sendViaAllTransports(Packet packet) {
|
||||
packet.send();
|
||||
if (myAuxilaryTransport != null)
|
||||
packet.sendThrough(myAuxilaryTransport);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static void addTestClass(Packet packet, String className) {
|
||||
packet.
|
||||
addLimitedString(PoolOfTestTypes.TEST_CLASS).
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.rt.execution.junit.segments;
|
||||
import junit.runner.BaseTestRunner;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Vector;
|
||||
|
||||
public class Packet extends PacketWriter {
|
||||
@@ -36,6 +37,10 @@ public class Packet extends PacketWriter {
|
||||
return addReference(myRegistry.referenceTo(test));
|
||||
}
|
||||
|
||||
public Packet addObject(Object test, Collection packet) {
|
||||
return addReference(myRegistry.referenceTo(test, packet));
|
||||
}
|
||||
|
||||
public Packet addReference(String reference) {
|
||||
appendString(reference + PoolOfDelimiters.REFERENCE_END);
|
||||
return this;
|
||||
|
||||
@@ -20,6 +20,7 @@ package com.intellij.rt.execution.junit.segments;
|
||||
*/
|
||||
public interface PoolOfDelimiters {
|
||||
char REFERENCE_END = ':';
|
||||
String REFERENCE_END_STR = ":";
|
||||
char INTEGER_DELIMITER = ' ';
|
||||
|
||||
String OBJECT_PREFIX = "O";
|
||||
|
||||
@@ -240,8 +240,7 @@ public abstract class CodeInsightTestCase extends PsiTestCase {
|
||||
}
|
||||
}));
|
||||
|
||||
// grand VFS refresh significantly slows down local tests and generally not needed
|
||||
//VirtualFileManager.getInstance().refresh(false);
|
||||
toDir.refresh(false, true);
|
||||
}
|
||||
else {
|
||||
editorInfos = new LinkedHashMap<VirtualFile, EditorInfo>();
|
||||
|
||||
+37
-25
@@ -18,11 +18,14 @@ package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.ide.util.PsiElementListCellRenderer;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
|
||||
import com.intellij.psi.NavigatablePsiElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
@@ -34,35 +37,44 @@ public class PsiElementListNavigator {
|
||||
}
|
||||
|
||||
public static void openTargets(MouseEvent e, NavigatablePsiElement[] targets, String title, ListCellRenderer listRenderer) {
|
||||
if (targets.length == 0) return;
|
||||
if (targets.length == 1){
|
||||
JBPopup popup = navigateOrCreatePopup(targets, title, listRenderer);
|
||||
if (popup != null) popup.show(new RelativePoint(e));
|
||||
}
|
||||
|
||||
public static void openTargets(Editor e, NavigatablePsiElement[] targets, String title, ListCellRenderer listRenderer) {
|
||||
JBPopup popup = navigateOrCreatePopup(targets, title, listRenderer);
|
||||
if (popup != null) popup.showInBestPositionFor(e);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JBPopup navigateOrCreatePopup(NavigatablePsiElement[] targets, String title, ListCellRenderer listRenderer) {
|
||||
if (targets.length == 0) return null;
|
||||
if (targets.length == 1) {
|
||||
targets[0].navigate(true);
|
||||
return null;
|
||||
}
|
||||
else{
|
||||
final JList list = new JBList(targets);
|
||||
list.setCellRenderer(listRenderer);
|
||||
final JList list = new JBList(targets);
|
||||
list.setCellRenderer(listRenderer);
|
||||
|
||||
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
|
||||
if (listRenderer instanceof PsiElementListCellRenderer) {
|
||||
((PsiElementListCellRenderer)listRenderer).installSpeedSearch(builder);
|
||||
}
|
||||
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
|
||||
if (listRenderer instanceof PsiElementListCellRenderer) {
|
||||
((PsiElementListCellRenderer)listRenderer).installSpeedSearch(builder);
|
||||
}
|
||||
|
||||
builder.
|
||||
setTitle(title).
|
||||
setMovable(true).
|
||||
setItemChoosenCallback(new Runnable() {
|
||||
public void run() {
|
||||
int[] ids = list.getSelectedIndices();
|
||||
if (ids == null || ids.length == 0) return;
|
||||
Object [] selectedElements = list.getSelectedValues();
|
||||
for (Object element : selectedElements) {
|
||||
PsiElement selected = (PsiElement) element;
|
||||
LOG.assertTrue(selected.isValid());
|
||||
((NavigatablePsiElement)selected).navigate(true);
|
||||
}
|
||||
return builder.
|
||||
setTitle(title).
|
||||
setMovable(true).
|
||||
setItemChoosenCallback(new Runnable() {
|
||||
public void run() {
|
||||
int[] ids = list.getSelectedIndices();
|
||||
if (ids == null || ids.length == 0) return;
|
||||
Object[] selectedElements = list.getSelectedValues();
|
||||
for (Object element : selectedElements) {
|
||||
PsiElement selected = (PsiElement)element;
|
||||
LOG.assertTrue(selected.isValid());
|
||||
((NavigatablePsiElement)selected).navigate(true);
|
||||
}
|
||||
}).createPopup().
|
||||
show(new RelativePoint(e));
|
||||
}
|
||||
}
|
||||
}).createPopup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1668,11 +1668,28 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
nextAction.getTemplatePresentation().setText(getNextOccurenceActionName());
|
||||
|
||||
final AnAction switchSoftWrapsAction = new ToggleUseSoftWrapsToolbarAction(SoftWrapAppliancePlaces.CONSOLE) {
|
||||
|
||||
/**
|
||||
* There is a possible case that more than console is open and user toggles soft wraps mode at one of them. We want
|
||||
* to update another console(s) representation as well when they are switched on after that. Hence, we remember last
|
||||
* used soft wraps mode and perform update if we see that the current value differs from the stored.
|
||||
*/
|
||||
private boolean myLastIsSelected;
|
||||
|
||||
@Override
|
||||
protected Editor getEditor(AnActionEvent e) {
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
boolean result = super.isSelected(e);
|
||||
if (result ^ myLastIsSelected) {
|
||||
setSelected(null, result);
|
||||
}
|
||||
return myLastIsSelected = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, final boolean state) {
|
||||
super.setSelected(e, state);
|
||||
|
||||
+1
-2
@@ -139,8 +139,7 @@ public class FileReferenceSet {
|
||||
public FileReferenceSet(final @NotNull PsiElement element) {
|
||||
|
||||
myElement = element;
|
||||
final ElementManipulator<PsiElement> manipulator = ElementManipulators.getManipulator(element);
|
||||
final TextRange range = manipulator.getRangeInElement(element);
|
||||
TextRange range = ElementManipulators.getValueTextRange(element);
|
||||
myStartInElement = range.getStartOffset();
|
||||
final String s = range.substring(element.getText());
|
||||
myPathString = s.trim();
|
||||
|
||||
+1
-1
@@ -173,7 +173,7 @@ public abstract class ChooseLibrariesDialogBase extends DialogWrapper {
|
||||
myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER");
|
||||
myTree.getActionMap().put("ENTER", getOKAction());
|
||||
final JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree);
|
||||
pane.setMinimumSize(new Dimension(300, 80));
|
||||
pane.setPreferredSize(new Dimension(300, 80));
|
||||
return pane;
|
||||
}
|
||||
|
||||
|
||||
+16
-6
@@ -249,9 +249,14 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen
|
||||
|
||||
myContext.logicalLineData.update(foldRegion.getStartOffset());
|
||||
SoftWrap softWrap = registerSoftWrap(
|
||||
myContext.softWrapStartOffset, myContext.tokenStartOffset, myContext.tokenStartOffset, myContext.getSpaceWidth(), myContext.logicalLineData
|
||||
myContext.softWrapStartOffset, myContext.tokenStartOffset, myContext.tokenStartOffset, myContext.getSpaceWidth(),
|
||||
myContext.logicalLineData
|
||||
);
|
||||
assert softWrap != null; // We expect that it's always possible to wrap collapsed fold region placeholder text
|
||||
if (softWrap == null) {
|
||||
// If we're here that means that we can't find appropriate soft wrap offset before the fold region.
|
||||
// However, we expect that it's always possible to wrap collapsed fold region placeholder text
|
||||
softWrap = registerSoftWrap(myContext.tokenStartOffset, myContext.getSpaceWidth(), myContext.logicalLineData);
|
||||
}
|
||||
myContext.softWrapStartOffset = softWrap.getStart();
|
||||
if (softWrap.getStart() < myContext.tokenStartOffset) {
|
||||
revertListeners(softWrap.getStart(), myContext.currentPosition.visualLine);
|
||||
@@ -524,19 +529,24 @@ public class SoftWrapApplianceManager implements FoldingListener, DocumentListen
|
||||
return null;
|
||||
}
|
||||
|
||||
return registerSoftWrap(softWrapOffset, spaceSize, lineData);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SoftWrap registerSoftWrap(int offset, int spaceSize, LogicalLineData lineData) {
|
||||
int indentInColumns = 0;
|
||||
int indentInPixels = myPainter.getMinDrawingWidth(SoftWrapDrawingType.AFTER_SOFT_WRAP);
|
||||
if (myCustomIndentUsedLastTime) {
|
||||
indentInColumns = myCustomIndentValueUsedLastTime + lineData.indentInColumns;
|
||||
indentInPixels += lineData.indentInPixels + (myCustomIndentValueUsedLastTime * spaceSize);
|
||||
}
|
||||
SoftWrapImpl softWrap = new SoftWrapImpl(
|
||||
new TextChangeImpl("\n" + StringUtil.repeatSymbol(' ', indentInColumns), softWrapOffset, softWrapOffset),
|
||||
SoftWrapImpl result = new SoftWrapImpl(
|
||||
new TextChangeImpl("\n" + StringUtil.repeatSymbol(' ', indentInColumns), offset, offset),
|
||||
indentInColumns + 1/* for 'after soft wrap' drawing */,
|
||||
indentInPixels
|
||||
);
|
||||
myStorage.storeOrReplace(softWrap, true);
|
||||
return softWrap;
|
||||
myStorage.storeOrReplace(result, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,147 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ByteBufferIntObjectMap<V> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.ByteBufferMap");
|
||||
|
||||
private final RandomAccessDataInput myBuffer;
|
||||
private final int myStartOffset;
|
||||
private final ByteBufferMap.ValueProvider<V> myValueProvider;
|
||||
private int myMod;
|
||||
private final int myEndOffset;
|
||||
|
||||
public ByteBufferIntObjectMap(@NotNull MappedBufferWrapper buffer,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull ByteBufferMap.ValueProvider<V> valueProvider) {
|
||||
assert startOffset < endOffset;
|
||||
|
||||
myBuffer = new ByteBufferRADataInput(buffer);
|
||||
myStartOffset = startOffset;
|
||||
myEndOffset = endOffset;
|
||||
myValueProvider = valueProvider;
|
||||
|
||||
myBuffer.setPosition(startOffset);
|
||||
try {
|
||||
myMod = myBuffer.readInt();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public V get(int key) {
|
||||
int hash = hash(key);
|
||||
int keyGroupOffset = readKeyGroupOffset(hash);
|
||||
if (keyGroupOffset == -1) return null;
|
||||
if (!(myStartOffset < keyGroupOffset && keyGroupOffset < myEndOffset)){
|
||||
LOG.error("keyGroupOffset = " + keyGroupOffset + " myStartOffset = " + myStartOffset + " myEndOffset = " + myEndOffset);
|
||||
}
|
||||
|
||||
try {
|
||||
myBuffer.setPosition(keyGroupOffset);
|
||||
int keyGroupSize = myBuffer.readInt();
|
||||
assert (keyGroupSize > 0);
|
||||
for (int i = 0; i < keyGroupSize; i++) {
|
||||
if (key == myBuffer.readInt()) {
|
||||
int valueOffset = myBuffer.readInt();
|
||||
assert (valueOffset > 0);
|
||||
|
||||
myBuffer.setPosition(myStartOffset + valueOffset);
|
||||
return myValueProvider.get(myBuffer);
|
||||
}
|
||||
else {
|
||||
myBuffer.readInt(); //read offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public TIntArrayList getKeys() {
|
||||
TIntArrayList result = new TIntArrayList();
|
||||
getKeys(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void getKeys(TIntArrayList dst) {
|
||||
try {
|
||||
myBuffer.setPosition(myStartOffset + 4 /* mod */);
|
||||
|
||||
int firstKeyGroupOffset = -1;
|
||||
int lastKeyGroupOffset = -1;
|
||||
for (int i = 0; i < myMod; i++) {
|
||||
int value = myBuffer.readInt();
|
||||
if (value != -1) {
|
||||
int offset = value + myStartOffset;
|
||||
if (firstKeyGroupOffset == -1) firstKeyGroupOffset = offset;
|
||||
lastKeyGroupOffset = offset;
|
||||
}
|
||||
}
|
||||
if (firstKeyGroupOffset == -1) {
|
||||
return;
|
||||
}
|
||||
assert (firstKeyGroupOffset > myStartOffset);
|
||||
assert (lastKeyGroupOffset > myStartOffset);
|
||||
assert (lastKeyGroupOffset >= firstKeyGroupOffset);
|
||||
|
||||
int firstValueOffset = -1;
|
||||
|
||||
myBuffer.setPosition(firstKeyGroupOffset);
|
||||
while (myBuffer.getPosition() <= lastKeyGroupOffset) {
|
||||
int groupSize = myBuffer.readInt();
|
||||
for (int i = 0; i < groupSize; i++) {
|
||||
dst.add(myBuffer.readInt());
|
||||
|
||||
int valueOffset = myBuffer.readInt(); /* value offset */
|
||||
if( firstValueOffset == -1 ) firstValueOffset = valueOffset + myStartOffset;
|
||||
}
|
||||
}
|
||||
assert myBuffer.getPosition() == firstValueOffset;
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private int readKeyGroupOffset(int hash) {
|
||||
myBuffer.setPosition(myStartOffset + 4 /* mod */ + 4 * hash);
|
||||
int offset = -1;
|
||||
try {
|
||||
offset = myBuffer.readInt();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
if (offset == -1) return -1;
|
||||
return offset + myStartOffset;
|
||||
}
|
||||
|
||||
private int hash(int hashCode) {
|
||||
return Math.abs(hashCode) % myMod;
|
||||
}
|
||||
}
|
||||
@@ -1,199 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class ByteBufferMap<K,V> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.ByteBufferMap");
|
||||
|
||||
private final RandomAccessDataInput myBuffer;
|
||||
private final int myStartOffset;
|
||||
private final KeyProvider<K> myKeyProvider;
|
||||
private final ValueProvider<V> myValueProvider;
|
||||
private int myMod;
|
||||
private final int myEndOffset;
|
||||
|
||||
public static interface KeyProvider<K> {
|
||||
int hashCode(K key);
|
||||
|
||||
void write(DataOutput out, K key) throws IOException;
|
||||
|
||||
int length(K key);
|
||||
|
||||
K get(DataInput in) throws IOException;
|
||||
|
||||
/**
|
||||
* Should move the buffer pointer to the key end.
|
||||
*/
|
||||
boolean equals(DataInput in, K key) throws IOException;
|
||||
}
|
||||
|
||||
public static interface ValueProvider<V> {
|
||||
void write(DataOutput out, V value) throws IOException;
|
||||
|
||||
int length(V value);
|
||||
|
||||
V get(DataInput in) throws IOException;
|
||||
}
|
||||
|
||||
public static <V> void writeMap(DataOutput stream,
|
||||
ValueProvider<V> valueProvider,
|
||||
WriteableMap<V> map,
|
||||
double searchFactor) throws IOException {
|
||||
new ByteBufferMapWriteHandler<V>(stream, valueProvider, map, searchFactor).execute();
|
||||
}
|
||||
|
||||
public static <V> int calcMapLength(ValueProvider<V> valueProvider,
|
||||
WriteableMap<V> map,
|
||||
double searchFactor) throws IOException {
|
||||
return new ByteBufferMapWriteHandler<V>(null, valueProvider, map, searchFactor).calcLength();
|
||||
}
|
||||
|
||||
public ByteBufferMap(@NotNull MappedBufferWrapper holder,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull KeyProvider<K> keyProvider,
|
||||
@NotNull ValueProvider<V> valueProvider) {
|
||||
this(new ByteBufferRADataInput(holder), startOffset, endOffset, keyProvider, valueProvider);
|
||||
}
|
||||
|
||||
public ByteBufferMap(@NotNull RandomAccessDataInput buffer,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull KeyProvider<K> keyProvider,
|
||||
@NotNull ValueProvider<V> valueProvider) {
|
||||
assert startOffset < endOffset;
|
||||
|
||||
myBuffer = buffer;
|
||||
myStartOffset = startOffset;
|
||||
myEndOffset = endOffset;
|
||||
myKeyProvider = keyProvider;
|
||||
myValueProvider = valueProvider;
|
||||
|
||||
buffer.setPosition(startOffset);
|
||||
try {
|
||||
myMod = buffer.readInt();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public V get(K key) {
|
||||
int hash = hash(myKeyProvider.hashCode(key));
|
||||
int keyGroupOffset = readKeyGroupOffset(hash);
|
||||
if (keyGroupOffset == -1) return null;
|
||||
if (!(myStartOffset < keyGroupOffset && keyGroupOffset < myEndOffset)){
|
||||
LOG.error("keyGroupOffset = " + keyGroupOffset + " myStartOffset = " + myStartOffset + " myEndOffset = " + myEndOffset);
|
||||
}
|
||||
|
||||
try {
|
||||
myBuffer.setPosition(keyGroupOffset);
|
||||
int keyGroupSize = myBuffer.readInt();
|
||||
assert (keyGroupSize > 0);
|
||||
for (int i = 0; i < keyGroupSize; i++) {
|
||||
if (myKeyProvider.equals(myBuffer, key)) {
|
||||
int valueOffset = myBuffer.readInt();
|
||||
assert (valueOffset > 0);
|
||||
|
||||
myBuffer.setPosition(myStartOffset + valueOffset);
|
||||
return myValueProvider.get(myBuffer);
|
||||
}
|
||||
else {
|
||||
myBuffer.readInt(); //read offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public K[] getKeys(Class<K> keyClass) {
|
||||
ArrayList<K> result = new ArrayList<K>();
|
||||
getKeys(keyClass, result);
|
||||
return result.toArray((K[])Array.newInstance(keyClass, result.size()));
|
||||
}
|
||||
|
||||
public void getKeys(Class<K> keyClass, Collection<K> dst) {
|
||||
try {
|
||||
myBuffer.setPosition(myStartOffset + 4 /* mod */);
|
||||
|
||||
int firstKeyGroupOffset = -1;
|
||||
int lastKeyGroupOffset = -1;
|
||||
for (int i = 0; i < myMod; i++) {
|
||||
int value = myBuffer.readInt();
|
||||
if (value != -1) {
|
||||
int offset = value + myStartOffset;
|
||||
if (firstKeyGroupOffset == -1) firstKeyGroupOffset = offset;
|
||||
lastKeyGroupOffset = offset;
|
||||
}
|
||||
}
|
||||
if (firstKeyGroupOffset == -1) {
|
||||
return;
|
||||
}
|
||||
assert (firstKeyGroupOffset > myStartOffset);
|
||||
assert (lastKeyGroupOffset > myStartOffset);
|
||||
assert (lastKeyGroupOffset >= firstKeyGroupOffset);
|
||||
|
||||
int firstValueOffset = -1;
|
||||
|
||||
myBuffer.setPosition(firstKeyGroupOffset);
|
||||
while (myBuffer.getPosition() <= lastKeyGroupOffset) {
|
||||
int groupSize = myBuffer.readInt();
|
||||
for (int i = 0; i < groupSize; i++) {
|
||||
dst.add(myKeyProvider.get(myBuffer));
|
||||
|
||||
int valueOffset = myBuffer.readInt(); /* value offset */
|
||||
if( firstValueOffset == -1 ) firstValueOffset = valueOffset + myStartOffset;
|
||||
}
|
||||
}
|
||||
assert myBuffer.getPosition() == firstValueOffset;
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private int readKeyGroupOffset(int hash) {
|
||||
myBuffer.setPosition(myStartOffset + 4 /* mod */ + 4 * hash);
|
||||
int offset = -1;
|
||||
try {
|
||||
offset = myBuffer.readInt();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
if (offset == -1) return -1;
|
||||
return offset + myStartOffset;
|
||||
}
|
||||
|
||||
private int hash(int hashCode) {
|
||||
return Math.abs(hashCode) % myMod;
|
||||
}
|
||||
}
|
||||
@@ -1,112 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
class ByteBufferMapWriteHandler<V> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.ByteBufferMapWriteHandler");
|
||||
|
||||
private final ByteBufferMap.ValueProvider<V> myValueProvider;
|
||||
private final WriteableMap<V> myMap;
|
||||
|
||||
private final int[] myKeyHashes;
|
||||
private final int myMod;
|
||||
private final DataOutput myOut;
|
||||
|
||||
public ByteBufferMapWriteHandler(DataOutput stream, /*ByteBufferMap.KeyProvider keyProvider, */ByteBufferMap.ValueProvider<V> valueProvider, WriteableMap<V> map, double searchFactor) {
|
||||
myValueProvider = valueProvider;
|
||||
myMap = map;
|
||||
|
||||
myKeyHashes = myMap.getHashCodesArray();
|
||||
int mod = (int)(myKeyHashes.length / searchFactor);
|
||||
myMod = mod != 0 ? mod : 1;
|
||||
myOut = stream;
|
||||
}
|
||||
|
||||
public void execute() throws IOException {
|
||||
|
||||
executeImpl( true );
|
||||
}
|
||||
|
||||
public int calcLength() throws IOException {
|
||||
return executeImpl( false );
|
||||
}
|
||||
|
||||
public int executeImpl( boolean write ) throws IOException {
|
||||
if( write ) myOut.writeInt(myMod);
|
||||
int offset = 4;
|
||||
|
||||
int[] overflowList = new int[myKeyHashes.length];
|
||||
int[] firstOverflowElem = new int[myMod];
|
||||
int[] occurs = new int[myMod];
|
||||
Arrays.fill(firstOverflowElem, -1);
|
||||
|
||||
// Creating hash table and overflow lists
|
||||
for( int i = myKeyHashes.length-1; i >= 0; i-- ) {
|
||||
int hashhash = hash(myKeyHashes[i]);
|
||||
overflowList[i] = firstOverflowElem[hashhash];
|
||||
firstOverflowElem[hashhash] = i;
|
||||
occurs[hashhash]++;
|
||||
}
|
||||
|
||||
offset += 4 * myMod; // hash table size
|
||||
// writing hash table
|
||||
for( int i = 0; i < myMod; i++ ) {
|
||||
if( write ) myOut.writeInt( occurs[i] != 0 ? offset : -1 );
|
||||
if( occurs[i] != 0 ) offset += 4; // key group size, if key group present
|
||||
int occurs_i = 0;
|
||||
for( int j = firstOverflowElem[i]; j != -1; j = overflowList[j] ) {
|
||||
offset += myMap.getKeyLength( j ) + 4 /* value offset */;
|
||||
occurs_i++;
|
||||
}
|
||||
LOG.assertTrue( occurs_i == occurs[i] );
|
||||
}
|
||||
|
||||
// writing key table
|
||||
for( int i = 0; i < myMod; i++ ) {
|
||||
if( occurs[i] == 0 ) continue;
|
||||
|
||||
if( write ) myOut.writeInt( occurs[i] );
|
||||
for( int j = firstOverflowElem[i]; j != -1; j = overflowList[j] ) {
|
||||
if( write ) {
|
||||
myMap.writeKey( myOut, j );
|
||||
myOut.writeInt( offset );
|
||||
}
|
||||
V value = myMap.getValue(j);
|
||||
offset += myValueProvider.length(value);
|
||||
}
|
||||
}
|
||||
|
||||
// writing value table
|
||||
for( int i = 0; i < myMod; i++ ) {
|
||||
for( int j = firstOverflowElem[i]; j != -1; j = overflowList[j] ) {
|
||||
V value = myMap.getValue(j);
|
||||
if( write ) myValueProvider.write( myOut, value );
|
||||
}
|
||||
}
|
||||
|
||||
return offset; // total resulting length
|
||||
}
|
||||
|
||||
private int hash(int hashCode){
|
||||
return Math.abs(hashCode) % myMod;
|
||||
}
|
||||
}
|
||||
@@ -1,110 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class ByteBufferRADataInput implements RandomAccessDataInput {
|
||||
private static final Logger LOG = Logger.getInstance("com.intellij.util.io.ByteBufferRADataInput");
|
||||
|
||||
private final MappedBufferWrapper myBuffer;
|
||||
|
||||
public ByteBufferRADataInput(MappedBufferWrapper buffer) {
|
||||
myBuffer = buffer;
|
||||
}
|
||||
|
||||
public void setPosition(int pos) {
|
||||
getBuffer().position(pos);
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return getBuffer().position();
|
||||
}
|
||||
|
||||
public void readFully(byte[] b) throws IOException {
|
||||
getBuffer().get(b);
|
||||
}
|
||||
|
||||
public void readFully(byte[] b, int off, int len) throws IOException {
|
||||
getBuffer().get(b, off, len);
|
||||
}
|
||||
|
||||
public int skipBytes(int n) throws IOException {
|
||||
int newPos = getPosition() + n;
|
||||
setPosition(newPos);
|
||||
return newPos;
|
||||
}
|
||||
|
||||
public boolean readBoolean() throws IOException {
|
||||
return getBuffer().get() == 1;
|
||||
}
|
||||
|
||||
public byte readByte() throws IOException {
|
||||
return getBuffer().get();
|
||||
}
|
||||
|
||||
public int readUnsignedByte() throws IOException {
|
||||
return 0xFF & ((int)getBuffer().get());
|
||||
}
|
||||
|
||||
public short readShort() throws IOException {
|
||||
return getBuffer().getShort();
|
||||
}
|
||||
|
||||
public int readUnsignedShort() throws IOException {
|
||||
return 0xFFFF & ((int)getBuffer().getShort());
|
||||
}
|
||||
|
||||
public char readChar() throws IOException {
|
||||
return getBuffer().getChar();
|
||||
}
|
||||
|
||||
public int readInt() throws IOException {
|
||||
return getBuffer().getInt();
|
||||
}
|
||||
|
||||
public long readLong() throws IOException {
|
||||
return getBuffer().getLong();
|
||||
}
|
||||
|
||||
public float readFloat() throws IOException {
|
||||
return getBuffer().getFloat();
|
||||
}
|
||||
|
||||
public double readDouble() throws IOException {
|
||||
return getBuffer().getDouble();
|
||||
}
|
||||
|
||||
public String readLine() throws IOException {
|
||||
LOG.error("Not implemented");
|
||||
return null;
|
||||
}
|
||||
|
||||
public String readUTF() throws IOException {
|
||||
return DataInputStream.readUTF(this);
|
||||
}
|
||||
|
||||
public ByteBuffer getBuffer() {
|
||||
return myBuffer.buf();
|
||||
}
|
||||
}
|
||||
@@ -1,61 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class FileKeyProvider implements ByteBufferMap.KeyProvider<VirtualFile>{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.FileKeyProvider");
|
||||
|
||||
private final VirtualFile[] myFileIndex;
|
||||
private final TObjectIntHashMap<VirtualFile> myFileToIndexMap;
|
||||
|
||||
public FileKeyProvider(VirtualFile[] fileIndex, TObjectIntHashMap<VirtualFile> fileToIndexMap) {
|
||||
myFileIndex = fileIndex;
|
||||
myFileToIndexMap = fileToIndexMap;
|
||||
}
|
||||
|
||||
public int hashCode(VirtualFile key) {
|
||||
int index = myFileToIndexMap.get(key) - 1;
|
||||
return index;
|
||||
}
|
||||
|
||||
public void write(DataOutput out, VirtualFile key) throws IOException {
|
||||
int index = myFileToIndexMap.get(key) - 1;
|
||||
LOG.assertTrue(index >= 0);
|
||||
out.writeInt(index);
|
||||
}
|
||||
|
||||
public int length(VirtualFile key) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public VirtualFile get(DataInput in) throws IOException {
|
||||
int index = in.readInt();
|
||||
return myFileIndex[index];
|
||||
}
|
||||
|
||||
public boolean equals(DataInput in, VirtualFile key) throws IOException {
|
||||
int index = in.readInt();
|
||||
return key.equals(myFileIndex[index]);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IntArrayValueProvider implements ByteBufferMap.ValueProvider<int[]> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.IntArrayValueProvider");
|
||||
public static final IntArrayValueProvider INSTANCE = new IntArrayValueProvider(-1);
|
||||
|
||||
private final int myArraySize;
|
||||
|
||||
public IntArrayValueProvider(int arraySize) {
|
||||
myArraySize = arraySize;
|
||||
}
|
||||
|
||||
public void write(DataOutput out, int[] value) throws IOException {
|
||||
//if (value instanceof IntArrayList) {
|
||||
// IntArrayList list = (IntArrayList) value;
|
||||
// LOG.assertTrue(myArraySize == -1 || list.size() == myArraySize);
|
||||
// if (myArraySize == -1) out.writeInt(list.size());
|
||||
// for (int i = 0; i < list.size(); i++) {
|
||||
// out.writeInt(list.get(i));
|
||||
// }
|
||||
//} else if (value instanceof TIntArrayList) {
|
||||
// TIntArrayList list = (TIntArrayList) value;
|
||||
// LOG.assertTrue(myArraySize == -1 || list.size() == myArraySize);
|
||||
// if (myArraySize == -1) out.writeInt(list.size());
|
||||
// for (int i = 0; i < list.size(); i++) {
|
||||
// out.writeInt(list.get(i));
|
||||
// }
|
||||
//} else {
|
||||
int[] array = (int[])value;
|
||||
LOG.assertTrue(myArraySize == -1 || array.length == myArraySize);
|
||||
if (myArraySize == -1) out.writeInt(array.length);
|
||||
for(int i = 0; i < array.length; i++){
|
||||
out.writeInt(array[i]);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
public int length(int[] value) {
|
||||
//if (value instanceof IntArrayList) {
|
||||
// IntArrayList list = (IntArrayList) value;
|
||||
// LOG.assertTrue(myArraySize == -1 || list.size() == myArraySize);
|
||||
//
|
||||
// if (myArraySize == -1) return 4 * (list.size() + 1);
|
||||
//
|
||||
// return 4 * myArraySize;
|
||||
//} else if (value instanceof TIntArrayList) {
|
||||
// TIntArrayList list = (TIntArrayList) value;
|
||||
// LOG.assertTrue(myArraySize == -1 || list.size() == myArraySize);
|
||||
//
|
||||
// if (myArraySize == -1) return 4 * (list.size() + 1);
|
||||
//
|
||||
// return 4 * myArraySize;
|
||||
//} else {
|
||||
int[] array = (int[])value;
|
||||
LOG.assertTrue(myArraySize == -1 || array.length == myArraySize);
|
||||
|
||||
if (myArraySize == -1) return 4 * (array.length + 1);
|
||||
|
||||
return 4 * myArraySize;
|
||||
//}
|
||||
}
|
||||
|
||||
public int[] get(DataInput in) throws IOException {
|
||||
final int[] result;
|
||||
|
||||
if (myArraySize >= 0) {
|
||||
result = ArrayUtil.newIntArray(myArraySize);
|
||||
} else {
|
||||
result = ArrayUtil.newIntArray(in.readInt());
|
||||
}
|
||||
|
||||
for(int i = 0; i < result.length; i++){
|
||||
result[i] = in.readInt();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +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.util.io;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class IntValueProvider implements ByteBufferMap.ValueProvider<Integer> {
|
||||
public static IntValueProvider INSTANCE = new IntValueProvider();
|
||||
|
||||
private IntValueProvider() {
|
||||
}
|
||||
|
||||
public void write(DataOutput out, Integer value) throws IOException {
|
||||
out.writeInt(((Integer)value).intValue());
|
||||
}
|
||||
|
||||
public int length(Integer value) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public Integer get(DataInput in) throws IOException {
|
||||
return new Integer(in.readInt());
|
||||
}
|
||||
}
|
||||
@@ -1,54 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link ByteBufferIntObjectMap} instead
|
||||
*/
|
||||
public class IntegerKeyProvider implements ByteBufferMap.KeyProvider<Integer> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.StringKeyProvider");
|
||||
|
||||
public static final IntegerKeyProvider INSTANCE = new IntegerKeyProvider();
|
||||
|
||||
private IntegerKeyProvider() {
|
||||
}
|
||||
|
||||
public int hashCode(Integer key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
|
||||
public void write(DataOutput out, Integer key) throws IOException {
|
||||
out.writeInt(key.intValue());
|
||||
}
|
||||
|
||||
public int length(Integer key) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public Integer get(DataInput in) throws IOException {
|
||||
return new Integer(in.readInt());
|
||||
}
|
||||
|
||||
public boolean equals(DataInput in, Integer key) throws IOException {
|
||||
return key.intValue() == in.readInt();
|
||||
}
|
||||
}
|
||||
@@ -1,92 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
public class StringKeyProvider implements ByteBufferMap.KeyProvider<String>{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.StringKeyProvider");
|
||||
|
||||
public static final StringKeyProvider INSTANCE = new StringKeyProvider();
|
||||
@NonNls public static final String UTF_8_CHARSET_NAME = "UTF-8";
|
||||
|
||||
private StringKeyProvider() {
|
||||
}
|
||||
|
||||
public int hashCode(String key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
|
||||
public void write(DataOutput out, String key) throws IOException {
|
||||
String keyString = (String)key;
|
||||
byte[] keyBytes = keyString.getBytes(UTF_8_CHARSET_NAME);
|
||||
out.writeInt(keyBytes.length);
|
||||
out.write(keyBytes);
|
||||
}
|
||||
|
||||
public int length(String key) {
|
||||
try{
|
||||
String keyString = (String)key;
|
||||
byte[] keyBytes = keyString.getBytes(UTF_8_CHARSET_NAME);
|
||||
return 4 + keyBytes.length;
|
||||
}
|
||||
catch(UnsupportedEncodingException e){
|
||||
LOG.error(e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public String get(DataInput in) throws IOException {
|
||||
int length = in.readInt();
|
||||
byte[] bytes = new byte[length];
|
||||
in.readFully(bytes);
|
||||
try {
|
||||
return new String(bytes, UTF_8_CHARSET_NAME);
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(DataInput in, String key) throws IOException {
|
||||
try {
|
||||
String keyString = (String)key;
|
||||
byte[] keyBytes = keyString.getBytes(UTF_8_CHARSET_NAME);
|
||||
|
||||
int length = in.readInt();
|
||||
byte[] inputBytes = new byte[length];
|
||||
in.readFully(inputBytes);
|
||||
if (length != keyBytes.length) return false;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (keyBytes[i] != inputBytes[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
LOG.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +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.util.io;
|
||||
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class WriteableMapAdapter<K,V> implements WriteableMap<V> {
|
||||
private final Map<K,V> myMap;
|
||||
private final ByteBufferMap.KeyProvider myKeyProvider;
|
||||
private final K[] myKeys;
|
||||
|
||||
public WriteableMapAdapter(Map<K,V> map, ByteBufferMap.KeyProvider provider) {
|
||||
myMap = map;
|
||||
myKeyProvider = provider;
|
||||
myKeys = (K[]) myMap.keySet().toArray();
|
||||
}
|
||||
|
||||
public int[] getHashCodesArray() {
|
||||
int[] keyHashCodes = new int[ myKeys.length ];
|
||||
for( int i = 0; i < myKeys.length; i++ )
|
||||
keyHashCodes[i] = myKeyProvider.hashCode(myKeys[i]);
|
||||
return keyHashCodes;
|
||||
}
|
||||
|
||||
public V getValue( int n ) {
|
||||
return myMap.get( myKeys[n] );
|
||||
}
|
||||
|
||||
public int getKeyLength( int n ) {
|
||||
return myKeyProvider.length( myKeys[n] );
|
||||
}
|
||||
|
||||
public void writeKey( DataOutput out, int n ) throws IOException {
|
||||
myKeyProvider.write( out, myKeys[n] );
|
||||
}
|
||||
}
|
||||
+15
@@ -420,6 +420,21 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
|
||||
assertEquals(startOffset, myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(2, 0))));
|
||||
}
|
||||
|
||||
public void testFoldRegionThatStartsAtLineEnd() throws IOException {
|
||||
String text =
|
||||
"line1\n" +
|
||||
"line2\n" +
|
||||
"line3\n" +
|
||||
"line4\n" +
|
||||
"line5";
|
||||
|
||||
init(30, text);
|
||||
int start = text.indexOf("line3") - 1;
|
||||
addCollapsedFoldRegion(start, text.length(), "...");
|
||||
assertEquals(1, getSoftWrapModel().getRegisteredSoftWraps().size());
|
||||
assertEquals(start, getSoftWrapModel().getRegisteredSoftWraps().get(0).getStart());
|
||||
}
|
||||
|
||||
public void testHomeProcessing() throws IOException {
|
||||
String text =
|
||||
"class Test {\n" +
|
||||
|
||||
@@ -595,13 +595,6 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
|
||||
public static File createTempDir(@NonNls final String prefix) throws IOException {
|
||||
final File tempDirectory = FileUtil.createTempDirectory(TEST_DIR_PREFIX + prefix, null);
|
||||
myFilesToDelete.add(tempDirectory);
|
||||
// grand VFS refresh significantly slows down local tests and generally not needed
|
||||
//ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// VirtualFileManager.getInstance().refresh(false);
|
||||
// }
|
||||
//});
|
||||
return tempDirectory;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.MappedByteBuffer;
|
||||
@@ -48,7 +49,7 @@ public abstract class MappedBufferWrapper {
|
||||
myLength = length;
|
||||
}
|
||||
|
||||
protected abstract MappedByteBuffer map();
|
||||
protected abstract MappedByteBuffer map() throws IOException;
|
||||
|
||||
private static final int MAX_FORCE_ATTEMPTS = 10;
|
||||
|
||||
@@ -63,7 +64,7 @@ public abstract class MappedBufferWrapper {
|
||||
return myBuffer;
|
||||
}
|
||||
|
||||
public ByteBuffer buf() {
|
||||
public ByteBuffer buf() throws IOException {
|
||||
if (myBuffer == null) {
|
||||
myBuffer = map();
|
||||
}
|
||||
|
||||
@@ -1,355 +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.util.io;
|
||||
|
||||
import com.intellij.openapi.Forceable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.MappedByteBuffer;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class MappedFile implements Forceable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.io.MappedFile");
|
||||
|
||||
private MappedBufferWrapper myHolder;
|
||||
private final File myFile;
|
||||
|
||||
private long myRealSize;
|
||||
private long mySize;
|
||||
private long myPosition;
|
||||
private boolean myIsDirty = false;
|
||||
|
||||
@NonNls private static final String UTF_8_CHARSET_NAME = "UTF-8";
|
||||
@NonNls private static final String RW = "rw";
|
||||
private final byte[] buffer = new byte[8];
|
||||
|
||||
public MappedFile(File file, int initialSize) throws IOException {
|
||||
myFile = file;
|
||||
if (!file.exists() || file.length() == 0) {
|
||||
writeLength(0);
|
||||
}
|
||||
|
||||
myPosition = 0;
|
||||
map();
|
||||
|
||||
mySize = readLength();
|
||||
if (mySize == 0) {
|
||||
resize(initialSize);
|
||||
}
|
||||
}
|
||||
|
||||
private long readLength() {
|
||||
File lengthFile = getLengthFile();
|
||||
DataInputStream stream = null;
|
||||
try {
|
||||
stream = new DataInputStream(new FileInputStream(lengthFile));
|
||||
return stream.readLong();
|
||||
}
|
||||
catch (IOException e) {
|
||||
writeLength(myRealSize);
|
||||
return myRealSize;
|
||||
}
|
||||
finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private File getLengthFile() {
|
||||
return new File(myFile.getPath() + ".len");
|
||||
}
|
||||
|
||||
private void writeLength(final long len) {
|
||||
File lengthFile = getLengthFile();
|
||||
DataOutputStream stream = null;
|
||||
try {
|
||||
stream = new DataOutputStream(new FileOutputStream(lengthFile));
|
||||
stream.writeLong(len);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void map() {
|
||||
myHolder = new ReadWriteMappedBufferWrapper(myFile);
|
||||
myRealSize = myFile.length();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.assertTrue(myPosition > 0L && myPosition < myRealSize || myPosition == 0 && myRealSize == 0, "myPosition=" + myPosition + ", myRealSize=" + myRealSize);
|
||||
}
|
||||
myHolder.buf().position((int)myPosition);
|
||||
}
|
||||
|
||||
public short getShort(int index) throws IOException {
|
||||
seek(index);
|
||||
return readShort();
|
||||
}
|
||||
|
||||
public short readShort() throws IOException {
|
||||
get(buffer, 0, 2);
|
||||
|
||||
return Bits.getShort(buffer, 0);
|
||||
}
|
||||
|
||||
public void putShort(int index, short value) throws IOException {
|
||||
seek(index);
|
||||
writeShort(value);
|
||||
}
|
||||
|
||||
public void writeShort(int value) throws IOException {
|
||||
Bits.putShort(buffer, 0, (short)value);
|
||||
put(buffer, 0, 2);
|
||||
}
|
||||
|
||||
public int getInt(int index) throws IOException {
|
||||
seek(index);
|
||||
return readInt();
|
||||
}
|
||||
|
||||
public long getLong(final int index) throws IOException {
|
||||
seek(index);
|
||||
return readLong();
|
||||
}
|
||||
|
||||
public void putInt(int index, int value) throws IOException {
|
||||
seek(index);
|
||||
writeInt(value);
|
||||
}
|
||||
|
||||
public void putLong(final int index, final long value) throws IOException {
|
||||
seek(index);
|
||||
writeLong(value);
|
||||
}
|
||||
|
||||
public byte get(int index) throws IOException {
|
||||
seek(index);
|
||||
return readByte();
|
||||
}
|
||||
|
||||
public void put(int index, byte value) throws IOException {
|
||||
seek(index);
|
||||
writeByte(value);
|
||||
}
|
||||
|
||||
public void get(int index, byte[] dst, int offset, int length) throws IOException {
|
||||
seek(index);
|
||||
get(dst, offset, length);
|
||||
}
|
||||
|
||||
public void get(final byte[] dst, final int offset, final int length) throws IOException {
|
||||
if (myPosition + length > mySize) {
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
buf().get(dst, offset, length);
|
||||
myPosition += length;
|
||||
}
|
||||
|
||||
public void put(int index, byte[] src, int offset, int length) throws IOException {
|
||||
seek(index);
|
||||
put(src, offset, length);
|
||||
}
|
||||
|
||||
public void seek(long pos) throws IOException {
|
||||
ensureSize(pos);
|
||||
buf().position((int)pos);
|
||||
myPosition = pos;
|
||||
if (pos > mySize) {
|
||||
mySize = pos;
|
||||
}
|
||||
}
|
||||
|
||||
private ByteBuffer buf() {
|
||||
if (!isMapped()) {
|
||||
map();
|
||||
}
|
||||
|
||||
return myHolder.buf();
|
||||
}
|
||||
|
||||
private void ensureSize(final long pos) throws IOException {
|
||||
while (pos >= myRealSize) {
|
||||
expand();
|
||||
}
|
||||
}
|
||||
|
||||
private void expand() throws IOException {
|
||||
resize((int)((myRealSize + 1) * 13) >> 3);
|
||||
}
|
||||
|
||||
public void put(final byte[] src, final int offset, final int length) throws IOException {
|
||||
ensureSize(myPosition + length);
|
||||
myIsDirty = true;
|
||||
buf().put(src, offset, length);
|
||||
myPosition += length;
|
||||
if (myPosition > mySize) {
|
||||
mySize = myPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
if (myIsDirty) {
|
||||
writeLength(mySize);
|
||||
final ByteBuffer buf = buf();
|
||||
if (buf instanceof MappedByteBuffer) {
|
||||
MappedBufferWrapper.tryForce(buf);
|
||||
}
|
||||
myIsDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void force() {
|
||||
flush();
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return myIsDirty;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (myIsDirty) {
|
||||
writeLength(mySize);
|
||||
}
|
||||
unmap();
|
||||
}
|
||||
|
||||
public void resize(int size) throws IOException {
|
||||
final int current = (int)myRealSize;
|
||||
if (current == size) return;
|
||||
unmap();
|
||||
RandomAccessFile raf = new RandomAccessFile(myFile, RW);
|
||||
try {
|
||||
raf.setLength(size);
|
||||
}
|
||||
finally {
|
||||
raf.close();
|
||||
}
|
||||
map();
|
||||
}
|
||||
|
||||
public final long length() {
|
||||
return mySize;
|
||||
}
|
||||
|
||||
public long getFilePointer() {
|
||||
return myPosition;
|
||||
}
|
||||
|
||||
public int readInt() throws IOException {
|
||||
get(buffer, 0, 4);
|
||||
return Bits.getInt(buffer, 0);
|
||||
}
|
||||
|
||||
public long readLong() throws IOException {
|
||||
get(buffer, 0, 8);
|
||||
return Bits.getLong(buffer, 0);
|
||||
}
|
||||
|
||||
public void writeInt(int value) throws IOException {
|
||||
Bits.putInt(buffer, 0, value);
|
||||
put(buffer, 0, 4);
|
||||
}
|
||||
|
||||
public void writeLong(long value) throws IOException {
|
||||
Bits.putLong(buffer, 0, value);
|
||||
put(buffer, 0, 8);
|
||||
}
|
||||
|
||||
public String readUTF() throws IOException {
|
||||
try {
|
||||
int len = readInt();
|
||||
byte[] bytes = new byte[ len ];
|
||||
get(bytes, 0, len);
|
||||
return new String(bytes, UTF_8_CHARSET_NAME);
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
// Can't be
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public void writeUTF(String value) throws IOException {
|
||||
try {
|
||||
final byte[] bytes = value.getBytes(UTF_8_CHARSET_NAME);
|
||||
writeInt(bytes.length);
|
||||
put(bytes, 0, bytes.length);
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
// Can't be
|
||||
}
|
||||
}
|
||||
|
||||
public int readUnsignedShort() throws IOException {
|
||||
get(buffer, 0, 2);
|
||||
|
||||
int ch1 = buffer[0] & 0xff;
|
||||
int ch2 = buffer[1] & 0xff;
|
||||
return (ch1 << 8) + ch2;
|
||||
}
|
||||
|
||||
public char readChar() throws IOException {
|
||||
return (char)readUnsignedShort();
|
||||
}
|
||||
|
||||
public void writeChar(char value) throws IOException {
|
||||
writeShort(value);
|
||||
}
|
||||
|
||||
public byte readByte() throws IOException {
|
||||
get(buffer, 0, 1);
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
public void writeByte(byte value) throws IOException {
|
||||
buffer[0] = value;
|
||||
put(buffer, 0, 1);
|
||||
}
|
||||
|
||||
private void unmap() {
|
||||
if (myHolder != null) {
|
||||
/* flush(); TODO: Don't commit... */
|
||||
myHolder.unmap();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMapped() {
|
||||
return myHolder.isMapped();
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.util.io;
|
||||
|
||||
import com.intellij.openapi.Forceable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,7 +34,12 @@ import java.util.Set;
|
||||
* @author max
|
||||
*/
|
||||
public class PagedFileStorage implements Forceable {
|
||||
private final static int BUFFER_SIZE = 10 * 1024 * 1024; // 10M
|
||||
|
||||
protected static final Logger LOG = Logger.getInstance("#com.intellij.util.io.PagedFileStorage");
|
||||
private static final int MEGABYTE = 1024 * 1024;
|
||||
private final static int BUFFER_SIZE = 10 * MEGABYTE;
|
||||
private final static int UPPER_LIMIT = 200 * MEGABYTE;
|
||||
private final static int LOWER_LIMIT = 100 * MEGABYTE;
|
||||
|
||||
private final StorageLock myLock;
|
||||
|
||||
@@ -51,8 +57,9 @@ public class PagedFileStorage implements Forceable {
|
||||
final BuffersCache myBuffersCache = new BuffersCache();
|
||||
|
||||
private class BuffersCache extends MyCache {
|
||||
|
||||
public BuffersCache() {
|
||||
super(20 * BUFFER_SIZE);
|
||||
super(UPPER_LIMIT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -65,7 +72,40 @@ public class PagedFileStorage implements Forceable {
|
||||
if (off > key.owner.length()) {
|
||||
throw new IndexOutOfBoundsException("off=" + off + " key.owner.length()=" + key.owner.length());
|
||||
}
|
||||
return new ReadWriteMappedBufferWrapper(key.owner.myFile, off, Math.min((int)(key.owner.length() - off), BUFFER_SIZE));
|
||||
ReadWriteMappedBufferWrapper wrapper =
|
||||
new ReadWriteMappedBufferWrapper(key.owner.myFile, off, Math.min((int)(key.owner.length() - off), BUFFER_SIZE));
|
||||
IOException oome = null;
|
||||
while (true) {
|
||||
try {
|
||||
// ensure it's allocated
|
||||
wrapper.buf();
|
||||
if (oome != null) {
|
||||
LOG.error("Successfully recovered OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MEGABYTE + "MB " +
|
||||
"new size limit: " + mySizeLimit / MEGABYTE + "MB " +
|
||||
"trying to allocate " + wrapper.myLength + " block");
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (e.getCause() instanceof OutOfMemoryError) {
|
||||
oome = e;
|
||||
if (mySizeLimit > LOWER_LIMIT) {
|
||||
mySizeLimit -= BUFFER_SIZE;
|
||||
}
|
||||
long newSize = getSize() - BUFFER_SIZE;
|
||||
if (newSize >= 0) {
|
||||
ensureSize(newSize);
|
||||
continue; // next try
|
||||
}
|
||||
else {
|
||||
throw new MappingFailedException("Cannot recover from OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MEGABYTE + "MB " +
|
||||
"new size limit: " + mySizeLimit / MEGABYTE + "MB " +
|
||||
"trying to allocate " + wrapper.myLength + " block", e);
|
||||
}
|
||||
}
|
||||
throw new MappingFailedException("Cannot map buffer", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onDropFromCache(PageKey key, MappedBufferWrapper buf) {
|
||||
@@ -106,7 +146,7 @@ public class PagedFileStorage implements Forceable {
|
||||
private final byte[] myTypedIOBuffer = new byte[8];
|
||||
private boolean isDirty = false;
|
||||
private final File myFile;
|
||||
private long mySize = -1;
|
||||
protected long mySize = -1;
|
||||
@NonNls private static final String RW = "rw";
|
||||
|
||||
public PagedFileStorage(File file, StorageLock lock) throws IOException {
|
||||
@@ -133,6 +173,7 @@ public class PagedFileStorage implements Forceable {
|
||||
put(addr, myTypedIOBuffer, 0, 8);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void putByte(final int addr, final byte b) {
|
||||
myTypedIOBuffer[0] = b;
|
||||
put(addr, myTypedIOBuffer, 0, 1);
|
||||
@@ -277,7 +318,12 @@ public class PagedFileStorage implements Forceable {
|
||||
}
|
||||
|
||||
private ByteBuffer getBuffer(int page) {
|
||||
return myLock.myBuffersCache.get(new PageKey(this, page)).buf();
|
||||
try {
|
||||
return myLock.myBuffersCache.get(new PageKey(this, page)).buf();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MappingFailedException("Cannot map buffer", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void force() {
|
||||
@@ -296,7 +342,7 @@ public class PagedFileStorage implements Forceable {
|
||||
private static abstract class MyCache {
|
||||
|
||||
private final LinkedHashMap<PageKey, MappedBufferWrapper> myMap;
|
||||
private final long mySizeLimit;
|
||||
protected long mySizeLimit;
|
||||
private long mySize;
|
||||
|
||||
protected MyCache(long sizeLimit) {
|
||||
@@ -329,11 +375,19 @@ public class PagedFileStorage implements Forceable {
|
||||
wrapper = createValue(key);
|
||||
mySize += wrapper.myLength;
|
||||
myMap.put(key, wrapper);
|
||||
while (mySize > mySizeLimit) {
|
||||
ensureSize(mySizeLimit);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
protected void ensureSize(long sizeLimit) {
|
||||
while (mySize > sizeLimit) {
|
||||
// we still have to drop something
|
||||
myMap.doRemoveEldestEntry();
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
return mySize;
|
||||
}
|
||||
|
||||
public Set<Map.Entry<PageKey, MappedBufferWrapper>> entrySet() {
|
||||
|
||||
@@ -30,22 +30,15 @@ public class ReadOnlyMappedBufferWrapper extends MappedBufferWrapper {
|
||||
super(file, pos, file.length() - pos);
|
||||
}
|
||||
|
||||
public MappedByteBuffer map() {
|
||||
public MappedByteBuffer map() throws IOException {
|
||||
FileInputStream stream = new FileInputStream(myFile);
|
||||
FileChannel channel = stream.getChannel();
|
||||
try {
|
||||
FileInputStream stream = new FileInputStream(myFile);
|
||||
FileChannel channel = stream.getChannel();
|
||||
try {
|
||||
return channel.map(FileChannel.MapMode.READ_ONLY, myPosition, myLength);
|
||||
}
|
||||
finally {
|
||||
channel.close();
|
||||
stream.close();
|
||||
}
|
||||
return channel.map(FileChannel.MapMode.READ_ONLY, myPosition, myLength);
|
||||
}
|
||||
catch (IOException e) {
|
||||
final MappingFailedException mapFailed = new MappingFailedException("Mapping failed for: " + myFile.getPath(), e);
|
||||
LOG.error(mapFailed);
|
||||
throw mapFailed;
|
||||
finally {
|
||||
channel.close();
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,51 +30,25 @@ import java.nio.channels.FileChannel;
|
||||
public class ReadWriteMappedBufferWrapper extends MappedBufferWrapper {
|
||||
@NonNls private static final String RW = "rw";
|
||||
|
||||
public ReadWriteMappedBufferWrapper(final File file) {
|
||||
super(file, 0, file.length());
|
||||
}
|
||||
|
||||
public ReadWriteMappedBufferWrapper(final File file, int offset, int len) {
|
||||
super(file, offset, len);
|
||||
}
|
||||
|
||||
public MappedByteBuffer map() {
|
||||
MappedByteBuffer buf;
|
||||
public MappedByteBuffer map() throws IOException {
|
||||
RandomAccessFile raf = null;
|
||||
FileChannel channel = null;
|
||||
try {
|
||||
buf = null;
|
||||
RandomAccessFile raf = null;
|
||||
FileChannel channel = null;
|
||||
try {
|
||||
raf = new RandomAccessFile(myFile, RW);
|
||||
channel = raf.getChannel();
|
||||
buf = channel.map(FileChannel.MapMode.READ_WRITE, myPosition, myLength);
|
||||
raf = new RandomAccessFile(myFile, RW);
|
||||
channel = raf.getChannel();
|
||||
return channel.map(FileChannel.MapMode.READ_WRITE, myPosition, myLength);
|
||||
}
|
||||
finally {
|
||||
if (channel != null) {
|
||||
channel.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
final MappingFailedException mapFailed =
|
||||
new MappingFailedException("Mapping failed: " + myFile.getAbsolutePath() + ", position=" + myPosition + ", length=" + myLength, e);
|
||||
LOG.error(mapFailed);
|
||||
throw mapFailed;
|
||||
}
|
||||
finally {
|
||||
if (channel != null) {
|
||||
channel.close();
|
||||
}
|
||||
if (raf != null) {
|
||||
raf.close();
|
||||
}
|
||||
if (raf != null) {
|
||||
raf.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
buf = null;
|
||||
}
|
||||
|
||||
if (buf == null) {
|
||||
final MappingFailedException mapFailed =
|
||||
new MappingFailedException("Mapping failed: " + myFile.getAbsolutePath() + ", position=" + myPosition + ", length=" + myLength);
|
||||
LOG.error(mapFailed);
|
||||
throw mapFailed;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
@@ -16,16 +16,15 @@
|
||||
|
||||
package com.intellij.xdebugger;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
|
||||
import com.intellij.xdebugger.frame.XSuspendContext;
|
||||
import com.intellij.xdebugger.frame.XStackFrame;
|
||||
import com.intellij.xdebugger.stepping.XSmartStepIntoVariant;
|
||||
import com.intellij.xdebugger.frame.XSuspendContext;
|
||||
import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
|
||||
import com.intellij.xdebugger.stepping.XSmartStepIntoVariant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -64,6 +63,8 @@ public interface XDebugSession extends AbstractDebuggerSession {
|
||||
void pause();
|
||||
void resume();
|
||||
|
||||
void showExecutionPoint(XSourcePosition sourcePosition);
|
||||
|
||||
void showExecutionPoint();
|
||||
|
||||
void setCurrentStackFrame(@NotNull XStackFrame frame);
|
||||
|
||||
@@ -344,6 +344,12 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
myDispatcher.getMulticaster().sessionResumed();
|
||||
}
|
||||
|
||||
public void showExecutionPoint(XSourcePosition sourcePosition) {
|
||||
XExecutionStack activeExecutionStack = mySuspendContext.getActiveExecutionStack();
|
||||
boolean isTopFrame = activeExecutionStack != null && activeExecutionStack.getTopFrame() == myCurrentStackFrame;
|
||||
myDebuggerManager.setActiveSession(this, sourcePosition, !isTopFrame);
|
||||
}
|
||||
|
||||
public void showExecutionPoint() {
|
||||
if (mySuspendContext != null) {
|
||||
XExecutionStack executionStack = mySuspendContext.getActiveExecutionStack();
|
||||
|
||||
@@ -68,7 +68,6 @@ public class XDebuggerManagerImpl extends XDebuggerManager implements ProjectCom
|
||||
private final ExecutionPointHighlighter myExecutionPointHighlighter;
|
||||
private XDebugSessionImpl myActiveSession;
|
||||
|
||||
|
||||
public XDebuggerManagerImpl(final Project project, final StartupManager startupManager, MessageBus messageBus) {
|
||||
myProject = project;
|
||||
myBreakpointManager = new XBreakpointManagerImpl(project, this, startupManager);
|
||||
|
||||
@@ -1722,9 +1722,6 @@ junit4.test.method.in.class.extending.junit3.testcase.problem.descriptor=@Test a
|
||||
equals.called.on.enum.constant.display.name='equals()' called on Enum value
|
||||
equals.called.on.enum.constant.problem.descriptor=<code>#ref</code> called on Enum value #loc
|
||||
equals.called.on.enum.constant.quickfix=Replace 'equals()' with '=='
|
||||
unnecessary.annotation.parentheses.display.name=Unnecessary annotation parentheses
|
||||
unnecessary.annotation.parentheses.problem.descriptor=<code>#ref</code> has unnecessary parentheses #loc
|
||||
unnecessary.annotation.parameter.quickfix=Remove parentheses
|
||||
int.literal.may.be.long.literal.display.name=int literal cast to long could be long literal
|
||||
int.literal.may.be.long.literal.problem.descriptor=<code>#ref</code> could be replaced with ''{0}'' #loc
|
||||
int.literal.may.be.long.literal.quickfix=Replace with ''{0}''
|
||||
@@ -1817,4 +1814,8 @@ cast.conflicts.with.instanceof.quickfix2=Replace instanceof ''{0}'' with ''{1}''
|
||||
double.checked.locking.quickfix=Make ''{0}'' volatile
|
||||
double.literal.may.be.float.literal.display.name=double literal cast to long could be float literal
|
||||
double.literal.may.be.float.literal.problem.descriptor=<code>#ref</code> could be replaced with ''{0}'' #loc
|
||||
double.literal.may.be.float.literal.quickfix=Replace with ''{0}''
|
||||
double.literal.may.be.float.literal.quickfix=Replace with ''{0}''
|
||||
multiple.declaration.option=Ignore for loop declarations
|
||||
simplifiable.annotation.display.name=Simplifiable annotation
|
||||
simplifiable.annotation.problem.descriptor=Annotation <code>#ref</code> may be replaced with ''{0}''
|
||||
simplifiable.annotation.quickfix=Simplify annotation
|
||||
|
||||
@@ -729,10 +729,10 @@ public class InspectionGadgetsPlugin implements ApplicationComponent,
|
||||
m_inspectionClasses.add(RedundantFieldInitializationInspection.class);
|
||||
m_inspectionClasses.add(RedundantImplementsInspection.class);
|
||||
m_inspectionClasses.add(ReturnThisInspection.class);
|
||||
m_inspectionClasses.add(SimplifiableAnnotationInspection.class);
|
||||
m_inspectionClasses.add(TypeParameterExtendsObjectInspection.class);
|
||||
m_inspectionClasses.add(UnnecessarilyQualifiedInnerClassAccessInspection.class);
|
||||
m_inspectionClasses.add(UnnecessarilyQualifiedStaticUsageInspection.class);
|
||||
m_inspectionClasses.add(UnnecessaryAnnotationParenthesesInspection.class);
|
||||
m_inspectionClasses.add(UnnecessaryBlockStatementInspection.class);
|
||||
m_inspectionClasses.add(UnnecessaryCallToStringValueOfInspection.class);
|
||||
m_inspectionClasses.add(UnnecessaryConstructorInspection.class);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2005 Dave Griffith
|
||||
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,24 +17,99 @@ package com.siyeh.ig.fixes;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiVariable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class NormalizeDeclarationFix extends InspectionGadgetsFix{
|
||||
|
||||
@NotNull
|
||||
public String getName(){
|
||||
return InspectionGadgetsBundle.message("normalize.declaration.quickfix");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException{
|
||||
final PsiElement variableNameElement = descriptor.getPsiElement();
|
||||
final PsiVariable var = (PsiVariable) variableNameElement.getParent();
|
||||
assert var != null;
|
||||
var.normalizeDeclaration();
|
||||
final PsiVariable parent =
|
||||
(PsiVariable) variableNameElement.getParent();
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
final PsiElement grandParent = parent.getParent();
|
||||
if (!(grandParent instanceof PsiDeclarationStatement)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement greatGrandParent = grandParent.getParent();
|
||||
if (greatGrandParent instanceof PsiForStatement) {
|
||||
final PsiDeclarationStatement declarationStatement =
|
||||
(PsiDeclarationStatement) grandParent;
|
||||
splitMultipleDeclarationInForStatementInitialization(
|
||||
declarationStatement);
|
||||
return;
|
||||
}
|
||||
parent.normalizeDeclaration();
|
||||
}
|
||||
|
||||
private static void splitMultipleDeclarationInForStatementInitialization(
|
||||
PsiDeclarationStatement declarationStatement) {
|
||||
final PsiElement forStatement = declarationStatement.getParent();
|
||||
final PsiElement[] declaredElements =
|
||||
declarationStatement.getDeclaredElements();
|
||||
final Project project = forStatement.getProject();
|
||||
final PsiElementFactory factory =
|
||||
JavaPsiFacade.getElementFactory(project);
|
||||
final PsiElement greatGreatGrandParent = forStatement.getParent();
|
||||
final PsiBlockStatement blockStatement;
|
||||
final PsiCodeBlock codeBlock;
|
||||
if (!(greatGreatGrandParent instanceof PsiCodeBlock)) {
|
||||
blockStatement = (PsiBlockStatement)
|
||||
factory.createStatementFromText("{}", forStatement);
|
||||
codeBlock = blockStatement.getCodeBlock();
|
||||
} else {
|
||||
blockStatement = null;
|
||||
codeBlock = null;
|
||||
}
|
||||
for (int i = 1; i < declaredElements.length; i++) {
|
||||
final PsiElement declaredElement = declaredElements[i];
|
||||
if (!(declaredElement instanceof PsiVariable)) {
|
||||
continue;
|
||||
}
|
||||
final PsiVariable variable = (PsiVariable) declaredElement;
|
||||
final PsiType type = variable.getType();
|
||||
final String typeText = type.getCanonicalText();
|
||||
final StringBuilder newStatementText =
|
||||
new StringBuilder(typeText);
|
||||
newStatementText.append(' ');
|
||||
newStatementText.append(variable.getName());
|
||||
final PsiExpression initializer = variable.getInitializer();
|
||||
if (initializer != null) {
|
||||
newStatementText.append('=');
|
||||
newStatementText.append(initializer.getText());
|
||||
}
|
||||
newStatementText.append(';');
|
||||
final PsiStatement newStatement =
|
||||
factory.createStatementFromText(
|
||||
newStatementText.toString(), forStatement);
|
||||
if (codeBlock == null) {
|
||||
greatGreatGrandParent.addBefore(newStatement, forStatement);
|
||||
} else {
|
||||
codeBlock.add(newStatement);
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < declaredElements.length; i++) {
|
||||
final PsiElement declaredElement = declaredElements[i];
|
||||
if (!(declaredElement instanceof PsiVariable)) {
|
||||
continue;
|
||||
}
|
||||
declaredElement.delete();
|
||||
}
|
||||
if (codeBlock != null) {
|
||||
codeBlock.add(forStatement);
|
||||
forStatement.replace(blockStatement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
@@ -23,34 +24,51 @@ import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.fixes.NormalizeDeclarationFix;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class MultipleDeclarationInspection extends BaseInspection {
|
||||
|
||||
@SuppressWarnings({"PublicField"})
|
||||
public boolean ignoreForLoopDeclarations = true;
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"multiple.declaration.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getID() {
|
||||
return "MultipleVariablesInDeclaration";
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"multiple.declaration.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
|
||||
"multiple.declaration.option"),
|
||||
this, "ignoreForLoopDeclarations");
|
||||
}
|
||||
|
||||
@Override
|
||||
public InspectionGadgetsFix buildFix(Object... infos) {
|
||||
return new NormalizeDeclarationFix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new MultipleDeclarationVisitor();
|
||||
}
|
||||
|
||||
private static class MultipleDeclarationVisitor
|
||||
private class MultipleDeclarationVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
|
||||
@Override public void visitDeclarationStatement(
|
||||
@@ -60,19 +78,21 @@ public class MultipleDeclarationInspection extends BaseInspection {
|
||||
return;
|
||||
}
|
||||
final PsiElement parent = statement.getParent();
|
||||
if (parent instanceof PsiForStatement) {
|
||||
final PsiForStatement forStatement = (PsiForStatement)parent;
|
||||
final PsiStatement initialization =
|
||||
forStatement.getInitialization();
|
||||
if (statement.equals(initialization)) {
|
||||
return;
|
||||
}
|
||||
if (ignoreForLoopDeclarations &&
|
||||
parent instanceof PsiForStatement) {
|
||||
return;
|
||||
}
|
||||
final PsiElement[] declaredVars = statement.getDeclaredElements();
|
||||
for (int i = 1; i < declaredVars.length; i++) {
|
||||
final PsiElement[] declaredElements =
|
||||
statement.getDeclaredElements();
|
||||
for (int i = 1; i < declaredElements.length; i++) {
|
||||
//skip the first one;
|
||||
final PsiLocalVariable var = (PsiLocalVariable)declaredVars[i];
|
||||
registerVariableError(var);
|
||||
final PsiElement declaredElement = declaredElements[i];
|
||||
if (!(declaredElement instanceof PsiVariable)) {
|
||||
continue;
|
||||
}
|
||||
final PsiVariable variable =
|
||||
(PsiVariable) declaredElement;
|
||||
registerVariableError(variable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +107,7 @@ public class MultipleDeclarationInspection extends BaseInspection {
|
||||
registerFieldError(field);
|
||||
}
|
||||
|
||||
public static boolean childrenContainTypeElement(PsiElement field) {
|
||||
public boolean childrenContainTypeElement(PsiElement field) {
|
||||
final PsiElement[] children = field.getChildren();
|
||||
for (PsiElement aChildren : children) {
|
||||
if (aChildren instanceof PsiTypeElement) {
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2010 Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SimplifiableAnnotationInspection extends BaseInspection {
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"simplifiable.annotation.display.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String buildErrorString(Object... infos) {
|
||||
final String replacement = (String) infos[0];
|
||||
return InspectionGadgetsBundle.message(
|
||||
"simplifiable.annotation.problem.descriptor", replacement);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
final String replacement = (String) infos[0];
|
||||
return new SimplifiableAnnotationFix(replacement);
|
||||
}
|
||||
|
||||
private static class SimplifiableAnnotationFix
|
||||
extends InspectionGadgetsFix {
|
||||
|
||||
private final String replacement;
|
||||
|
||||
public SimplifiableAnnotationFix(String replacement) {
|
||||
super();
|
||||
this.replacement = replacement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"simplifiable.annotation.quickfix");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (!(element instanceof PsiAnnotation)) {
|
||||
return;
|
||||
}
|
||||
final PsiElementFactory factory =
|
||||
JavaPsiFacade.getElementFactory(project);
|
||||
final PsiAnnotation annotation =
|
||||
factory.createAnnotationFromText(replacement, element);
|
||||
element.replace(annotation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new SimplifiableAnnotationVisitor();
|
||||
}
|
||||
|
||||
private static class SimplifiableAnnotationVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitAnnotation(PsiAnnotation annotation) {
|
||||
super.visitAnnotation(annotation);
|
||||
final PsiAnnotationParameterList parameterList =
|
||||
annotation.getParameterList();
|
||||
final PsiJavaCodeReferenceElement nameReferenceElement =
|
||||
annotation.getNameReferenceElement();
|
||||
if (nameReferenceElement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiNameValuePair[] attributes = parameterList.getAttributes();
|
||||
|
||||
final PsiElement[] annotationChildren = annotation.getChildren();
|
||||
if (annotationChildren.length >= 2) {
|
||||
final PsiElement child = annotationChildren[1];
|
||||
if (child instanceof PsiWhiteSpace) {
|
||||
final String replacementText;
|
||||
if (attributes.length > 0) {
|
||||
replacementText = '@' + nameReferenceElement.getText() +
|
||||
parameterList.getText();
|
||||
} else {
|
||||
replacementText = '@' + nameReferenceElement.getText();
|
||||
}
|
||||
registerError(annotation, replacementText);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attributes.length == 0) {
|
||||
final PsiElement[] children = parameterList.getChildren();
|
||||
if (children.length <= 0) {
|
||||
return;
|
||||
}
|
||||
registerError(annotation, '@' + nameReferenceElement.getText());
|
||||
} else if (attributes.length == 1) {
|
||||
final PsiNameValuePair attribute = attributes[0];
|
||||
@NonNls final String name = attribute.getName();
|
||||
if (!"value".equals(name)) {
|
||||
return;
|
||||
}
|
||||
registerError(annotation, '@' + nameReferenceElement.getText() +
|
||||
'(' + attribute.getValue().getText() + ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright 2009 Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UnnecessaryAnnotationParenthesesInspection extends BaseInspection {
|
||||
|
||||
@Override
|
||||
@Nls
|
||||
@NotNull()
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"unnecessary.annotation.parentheses.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"unnecessary.annotation.parentheses.problem.descriptor");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
return new UnnecessaryAnnotationParenthesesFix();
|
||||
}
|
||||
|
||||
private static class UnnecessaryAnnotationParenthesesFix
|
||||
extends InspectionGadgetsFix {
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"unnecessary.annotation.parameter.quickfix");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (!(element instanceof PsiAnnotationParameterList)) {
|
||||
return;
|
||||
}
|
||||
final PsiElement[] children = element.getChildren();
|
||||
for (PsiElement child : children) {
|
||||
child.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new UnnecessaryAnnotatinoParenthesesVisitor();
|
||||
}
|
||||
|
||||
private static class UnnecessaryAnnotatinoParenthesesVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitAnnotation(PsiAnnotation annotation) {
|
||||
super.visitAnnotation(annotation);
|
||||
final PsiJavaCodeReferenceElement reference =
|
||||
annotation.getNameReferenceElement();
|
||||
if (reference == null) {
|
||||
return;
|
||||
}
|
||||
final PsiAnnotationParameterList parameterList =
|
||||
annotation.getParameterList();
|
||||
final PsiElement[] children = parameterList.getChildren();
|
||||
if (children.length == 0) {
|
||||
return;
|
||||
}
|
||||
final PsiNameValuePair[] nameValuePairs =
|
||||
parameterList.getAttributes();
|
||||
if (nameValuePairs.length > 0) {
|
||||
return;
|
||||
}
|
||||
final PsiElement target = reference.resolve();
|
||||
if (!(target instanceof PsiClass)) {
|
||||
return;
|
||||
}
|
||||
final PsiClass annotationClass = (PsiClass) target;
|
||||
final PsiMethod[] methods = annotationClass.getMethods();
|
||||
for (PsiMethod method : methods) {
|
||||
if (!(method instanceof PsiAnnotationMethod)) {
|
||||
continue;
|
||||
}
|
||||
final PsiAnnotationMethod annotationMethod =
|
||||
(PsiAnnotationMethod) method;
|
||||
final PsiAnnotationMemberValue defaultValue =
|
||||
annotationMethod.getDefaultValue();
|
||||
if (defaultValue == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
registerError(parameterList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<body><table> <tr> <td valign="top" height="150">
|
||||
<font face="verdana" size="-1">
|
||||
This inspection reports annotations which can be simplified to their 'single element'
|
||||
or 'marker' shorthand form. Annotation that contain whitespace between the @-sign and the name
|
||||
of the annotation are also reported.
|
||||
</font></td> </tr> <tr> <td height="20"> <font face="verdana" size="-2">New in 10.1, Powered by InspectionGadgets </font> </td> </tr> </table> </body>
|
||||
</html>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.siyeh.igtest.style.simplifiable_annotation;
|
||||
|
||||
public class SimplifiableAnnotation {
|
||||
|
||||
@ SuppressWarnings(value = "blabla")
|
||||
@ Deprecated()
|
||||
Object foo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>SimplifiableAnnotation.java</file>
|
||||
<line>5</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Simplifiable annotation</problem_class>
|
||||
<description>Annotation <code>@ SuppressWarnings(value = "blabla")</code> may be replaced with '@SuppressWarnings(value = "blabla")'</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>SimplifiableAnnotation.java</file>
|
||||
<line>6</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Simplifiable annotation</problem_class>
|
||||
<description>Annotation <code>@ Deprecated()</code> may be replaced with '@Deprecated'</description>
|
||||
</problem>
|
||||
</problems>
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package com.siyeh.igtest.style.unnecessary_annotation_parentheses;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UnnecessaryAnnotationParentheses {
|
||||
|
||||
@Deprecated()
|
||||
Object foo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings()
|
||||
String s;
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
<problem>
|
||||
<file>UnnecessaryAnnotationParentheses.java</file>
|
||||
<line>7</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unnecessary annotation parentheses</problem_class>
|
||||
<description><code>()</code> has unnecessary parentheses #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.siyeh.ig.style;
|
||||
|
||||
import com.IGInspectionTestCase;
|
||||
|
||||
public class SimplifiableAnnotationInspectionTest extends IGInspectionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
doTest("com/siyeh/igtest/style/simplifiable_annotation",
|
||||
new SimplifiableAnnotationInspection());
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
package com.siyeh.ig.style;
|
||||
|
||||
import com.IGInspectionTestCase;
|
||||
|
||||
public class UnnecessaryAnnotationParenthesesInspectionTest extends IGInspectionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
doTest("com/siyeh/igtest/style/unnecessary_annotation_parentheses",
|
||||
new UnnecessaryAnnotationParenthesesInspection());
|
||||
}
|
||||
}
|
||||
@@ -613,6 +613,29 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb
|
||||
return true;
|
||||
}
|
||||
|
||||
private class MyISyncProgressMonitor implements SyncService.ISyncProgressMonitor {
|
||||
@Override
|
||||
public void start(int totalWork) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCanceled() {
|
||||
return myStopped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startSubTask(String name) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void advance(int work) {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean uploadApp(IDevice device, String remotePath, String localPath) throws IOException {
|
||||
if (myStopped) return false;
|
||||
getProcessHandler().notifyTextAvailable("Uploading file\n\tlocal path: " + localPath + "\n\tremote path: " + remotePath + '\n', STDOUT);
|
||||
@@ -621,12 +644,57 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb
|
||||
getProcessHandler().notifyTextAvailable("Can't upload file: device is not available.\n", STDERR);
|
||||
return false;
|
||||
}
|
||||
SyncService.SyncResult result = service.pushFile(localPath, remotePath, SyncService.getNullProgressMonitor());
|
||||
if (result.getCode() != SyncService.RESULT_OK) {
|
||||
getProcessHandler().notifyTextAvailable("Can't upload file: " + result.getMessage() + ".\n", STDERR);
|
||||
return false;
|
||||
SyncService.SyncResult result = service.pushFile(localPath, remotePath, new MyISyncProgressMonitor());
|
||||
int code = result.getCode();
|
||||
String errorMessage;
|
||||
switch (code) {
|
||||
case SyncService.RESULT_OK:
|
||||
return true;
|
||||
case SyncService.RESULT_CANCELED:
|
||||
errorMessage = "Command canceled";
|
||||
break;
|
||||
case SyncService.RESULT_CONNECTION_ERROR:
|
||||
errorMessage = "Connection error";
|
||||
break;
|
||||
case SyncService.RESULT_CONNECTION_TIMEOUT:
|
||||
errorMessage = "Connection timeout";
|
||||
break;
|
||||
case SyncService.RESULT_FILE_READ_ERROR:
|
||||
errorMessage = "Cannot read the file";
|
||||
break;
|
||||
case SyncService.RESULT_FILE_WRITE_ERROR:
|
||||
errorMessage = "Cannot write the file";
|
||||
break;
|
||||
case SyncService.RESULT_LOCAL_IS_DIRECTORY:
|
||||
errorMessage = "Local is directory";
|
||||
break;
|
||||
case SyncService.RESULT_NO_DIR_TARGET:
|
||||
errorMessage = "Target directory not found";
|
||||
break;
|
||||
case SyncService.RESULT_NO_LOCAL_FILE:
|
||||
errorMessage = "Local file not found";
|
||||
break;
|
||||
case SyncService.RESULT_NO_REMOTE_OBJECT:
|
||||
errorMessage = "No remote object";
|
||||
break;
|
||||
case SyncService.RESULT_REMOTE_IS_FILE:
|
||||
errorMessage = "Remote is a file";
|
||||
break;
|
||||
case SyncService.RESULT_REMOTE_PATH_ENCODING:
|
||||
errorMessage = "Incorrect remote path encoding";
|
||||
break;
|
||||
case SyncService.RESULT_REMOTE_PATH_LENGTH:
|
||||
errorMessage = "Incorrect remote path length";
|
||||
break;
|
||||
case SyncService.RESULT_TARGET_IS_FILE:
|
||||
errorMessage = "Target is a file";
|
||||
break;
|
||||
default:
|
||||
errorMessage = "Can't upload file";
|
||||
}
|
||||
return true;
|
||||
getProcessHandler()
|
||||
.notifyTextAvailable(errorMessage + (result.getMessage() != null ? "\n" + result.getMessage() + "\n" : "\n"), STDERR);
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"DuplicateThrows"})
|
||||
@@ -676,13 +744,13 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb
|
||||
executeDeviceCommandAndWriteToConsole(device, "pm install -r \"" + remotePath + '\"', receiver);
|
||||
if (myStopped) return false;
|
||||
}*/
|
||||
if (!isSuccess(receiver)) {
|
||||
/*if (!isSuccess(receiver)) {
|
||||
getProcessHandler().notifyTextAvailable("Can't reinstall application. Installing from scratch.\n", STDOUT);
|
||||
executeDeviceCommandAndWriteToConsole(device, "pm uninstall \"" + remotePath + '\"', receiver);
|
||||
if (myStopped) return false;
|
||||
executeDeviceCommandAndWriteToConsole(device, "pm install \"" + remotePath + '\"', receiver);
|
||||
if (myStopped) return false;
|
||||
}
|
||||
}*/
|
||||
boolean success = isSuccess(receiver);
|
||||
getProcessHandler().notifyTextAvailable(receiver.output.toString(), success ? STDOUT : STDERR);
|
||||
return success;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.android.sdk;
|
||||
|
||||
import com.android.ddmlib.AndroidDebugBridge;
|
||||
import com.android.ddmlib.DdmPreferences;
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.ISdkLog;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
@@ -145,6 +146,7 @@ public abstract class AndroidSdk {
|
||||
String adbPath = getAdbPath();
|
||||
if (!myDdmLibInitialized) {
|
||||
myDdmLibInitialized = true;
|
||||
DdmPreferences.setTimeOut(AndroidUtils.TIMEOUT);
|
||||
AndroidDebugBridge.init(AndroidEnableDdmsAction.isDdmsEnabled());
|
||||
AndroidDebugBridge.createBridge(adbPath, true);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public class AndroidUtils {
|
||||
public static final String EXT_NATIVE_LIB = "so";
|
||||
@NonNls public static final String RES_OVERLAY_DIR_NAME = "res-overlay";
|
||||
|
||||
private static final int TIMEOUT = 30000;
|
||||
public static final int TIMEOUT = 30000;
|
||||
|
||||
private AndroidUtils() {
|
||||
}
|
||||
|
||||
@@ -104,6 +104,10 @@
|
||||
<projectService
|
||||
serviceInterface="git4idea.config.GitExecutableValidator"
|
||||
serviceImplementation="git4idea.config.GitExecutableValidator"/>
|
||||
<projectService
|
||||
serviceInterface="git4idea.branch.GitBranches"
|
||||
serviceImplementation="git4idea.branch.GitBranches"/>
|
||||
|
||||
<applicationService
|
||||
serviceInterface="git4idea.config.GitVcsApplicationSettings"
|
||||
serviceImplementation="git4idea.config.GitVcsApplicationSettings"/>
|
||||
|
||||
@@ -58,13 +58,14 @@ import com.intellij.util.containers.ComparatorDelegate;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.annotate.GitAnnotationProvider;
|
||||
import git4idea.branch.GitBranchWidget;
|
||||
import git4idea.branch.GitBranches;
|
||||
import git4idea.changes.GitChangeProvider;
|
||||
import git4idea.changes.GitChangeUtils;
|
||||
import git4idea.changes.GitCommittedChangeListProvider;
|
||||
import git4idea.changes.GitOutgoingChangesProvider;
|
||||
import git4idea.checkin.GitCheckinEnvironment;
|
||||
import git4idea.checkin.GitCommitAndPushExecutor;
|
||||
import git4idea.checkout.branches.GitCurrentBranchWidget;
|
||||
import git4idea.commands.GitCommand;
|
||||
import git4idea.commands.GitSimpleHandler;
|
||||
import git4idea.config.GitExecutableValidator;
|
||||
@@ -145,10 +146,14 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
private boolean isActivated; // If true, the vcs was activated
|
||||
private GitExecutableValidator myExecutableValidator;
|
||||
private RepositoryChangeListener myIndexChangeListener;
|
||||
private GitCurrentBranchWidget myCurrentBranchWidget;
|
||||
private GitBranchWidget myBranchWidget;
|
||||
|
||||
public static GitVcs getInstance(@NotNull Project project) {
|
||||
return (GitVcs)ProjectLevelVcsManager.getInstance(project).findVcsByName(NAME);
|
||||
@Nullable
|
||||
public static GitVcs getInstance(Project project) {
|
||||
if (project == null || project.isDisposed()) {
|
||||
return null;
|
||||
}
|
||||
return (GitVcs) ProjectLevelVcsManager.getInstance(project).findVcsByName(NAME);
|
||||
}
|
||||
|
||||
public GitVcs(@NotNull Project project,
|
||||
@@ -203,8 +208,11 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
*
|
||||
* @param task the task to run
|
||||
*/
|
||||
public void runInBackground(Task.Backgroundable task) {
|
||||
myTaskQueue.run(task);
|
||||
public static void runInBackground(Task.Backgroundable task) {
|
||||
GitVcs vcs = getInstance(task.getProject());
|
||||
if (vcs != null) {
|
||||
vcs.myTaskQueue.run(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,9 +439,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
protected void shutdown() throws VcsException {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void activate() {
|
||||
isActivated = true;
|
||||
@@ -456,17 +461,14 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
NewGitUsersComponent.getInstance(myProject).activate();
|
||||
GitProjectLogManager.getInstance(myProject).activate();
|
||||
|
||||
GitBranches.getInstance(myProject).activate(this);
|
||||
StatusBar statusBar = WindowManager.getInstance().getStatusBar(myProject);
|
||||
if (statusBar != null) {
|
||||
myCurrentBranchWidget = new GitCurrentBranchWidget(myProject);
|
||||
statusBar.addWidget(myCurrentBranchWidget, "after " + (SystemInfo.isMac ? "Encoding" : "InsertOverwrite"), myProject);
|
||||
addGitReferenceListener(myCurrentBranchWidget);
|
||||
myBranchWidget = new GitBranchWidget(myProject);
|
||||
statusBar.addWidget(myBranchWidget, "after " + (SystemInfo.isMac ? "Encoding" : "InsertOverwrite"), myProject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
isActivated = false;
|
||||
@@ -491,11 +493,11 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
NewGitUsersComponent.getInstance(myProject).deactivate();
|
||||
GitProjectLogManager.getInstance(myProject).deactivate();
|
||||
|
||||
GitBranches.getInstance(myProject).deactivate();
|
||||
StatusBar statusBar = WindowManager.getInstance().getStatusBar(myProject);
|
||||
if (statusBar != null && myCurrentBranchWidget != null) {
|
||||
statusBar.removeWidget(myCurrentBranchWidget.ID());
|
||||
removeGitReferenceListener(myCurrentBranchWidget);
|
||||
myCurrentBranchWidget = null;
|
||||
if (statusBar != null && myBranchWidget != null) {
|
||||
statusBar.removeWidget(myBranchWidget.ID());
|
||||
myBranchWidget = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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 git4idea.branch;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.StatusBarWidget;
|
||||
import com.intellij.openapi.wm.impl.status.EditorBasedWidget;
|
||||
import com.intellij.util.Consumer;
|
||||
import git4idea.GitBranch;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* Status bar widget which displays the current branch for the file currently open in the editor.
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidget.TextPresentation, StatusBarWidget.Multiframe,
|
||||
GitBranchesListener {
|
||||
|
||||
private volatile String myCurrentBranchName = "";
|
||||
private final GitBranches myBranches;
|
||||
|
||||
public GitBranchWidget(Project project) {
|
||||
super(project);
|
||||
myBranches = GitBranches.getInstance(project);
|
||||
myBranches.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatusBarWidget copy() {
|
||||
return new GitBranchWidget(getProject());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String ID() {
|
||||
return GitBranchWidget.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectionChanged(FileEditorManagerEvent event) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileOpened(FileEditorManager source, VirtualFile file) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileClosed(FileEditorManager source, VirtualFile file) {
|
||||
update();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
final String text = myCurrentBranchName;
|
||||
return StringUtil.isEmpty(text) ? "" : "Git: " + text;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getMaxPossibleText() {
|
||||
return "Git: abcdefghij";
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getAlignment() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltipText() {
|
||||
return "Current Git branch";
|
||||
}
|
||||
|
||||
@Override
|
||||
// Updates branch information on click
|
||||
public Consumer<MouseEvent> getClickConsumer() {
|
||||
return new Consumer<MouseEvent>() {
|
||||
public void consume(MouseEvent mouseEvent) {
|
||||
update();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void branchConfigurationChanged() {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
myBranches.removeListener(this);
|
||||
}
|
||||
|
||||
private void update() {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
final GitBranch currentBranch = myBranches.getCurrentBranch(getSelectedFile());
|
||||
String currentBranchName = currentBranch != null ? currentBranch.getName() : null;
|
||||
if (currentBranchName == null) {
|
||||
currentBranchName = "";
|
||||
}
|
||||
myCurrentBranchName = currentBranchName;
|
||||
myStatusBar.updateWidget(ID());
|
||||
}
|
||||
}, new Condition() {
|
||||
public boolean value(Object o) {
|
||||
Project project = getProject();
|
||||
return isDisposed() || (project != null) && ((!project.isOpen()) || project.isDisposed()) || myStatusBar == null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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 git4idea.branch;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.VcsRoot;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.vfs.GitReferenceListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Container and tracker of git branches information.
|
||||
* Listens to branch change and updates information here.
|
||||
* Subscribe a {@link GitBranchesListener} to get notified for current branch and other branch configuration changes.
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitBranches implements GitReferenceListener {
|
||||
private static final Logger LOG = Logger.getInstance(GitBranches.class.getName());
|
||||
private final Project myProject;
|
||||
private final ProjectLevelVcsManager myVcsManager;
|
||||
|
||||
private final EventDispatcher<GitBranchesListener> myListeners = EventDispatcher.create(GitBranchesListener.class);
|
||||
private Map<VirtualFile, GitBranch> myCurrentBranches = new HashMap<VirtualFile, GitBranch>();
|
||||
private final Object myCurrentBranchesLock = new Object();
|
||||
private ChangeListManager myChangeListManager;
|
||||
private GitVcs myVcs;
|
||||
|
||||
public GitBranches(Project project, ChangeListManager changeListManager, ProjectLevelVcsManager vcsManager) {
|
||||
myProject = project;
|
||||
myChangeListManager = changeListManager;
|
||||
myVcsManager = vcsManager;
|
||||
}
|
||||
|
||||
public static GitBranches getInstance(Project project) {
|
||||
return ServiceManager.getService(project, GitBranches.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void referencesChanged(VirtualFile root) {
|
||||
updateBranchesInfo(root);
|
||||
}
|
||||
|
||||
public void activate(GitVcs vcs) {
|
||||
myVcs = vcs;
|
||||
myVcs.addGitReferenceListener(this);
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
if (myVcs != null) {
|
||||
myVcs.removeGitReferenceListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns branch that is active (current) in the repository in which the given file resides.
|
||||
* @param file file to determine branch.
|
||||
* @return current branch or null if the file is null, not under git vcs, unversioned, or branch information is not available for it.
|
||||
*/
|
||||
@Nullable
|
||||
public GitBranch getCurrentBranch(VirtualFile file) {
|
||||
if (file == null) { return null; }
|
||||
final AbstractVcs vcs = myVcsManager.getVcsFor(file);
|
||||
if (vcs == null || !(vcs instanceof GitVcs)) { return null; }
|
||||
final VirtualFile vcsRoot = myVcsManager.getVcsRootFor(file);
|
||||
if (vcsRoot == null) { return null; }
|
||||
if (myChangeListManager.isUnversioned(file)) { return null; }
|
||||
|
||||
synchronized (myCurrentBranchesLock) {
|
||||
return myCurrentBranches.get(vcsRoot);
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(GitBranchesListener listener) {
|
||||
myListeners.addListener(listener);
|
||||
}
|
||||
|
||||
public void removeListener(GitBranchesListener listener) {
|
||||
myListeners.removeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates branch information for the given root.
|
||||
* If root is null, updates branch information for all Git roots in the project.
|
||||
* @see #fullyUpdateBranchesInfo(java.util.Collection)
|
||||
*/
|
||||
private void updateBranchesInfo(final VirtualFile root) {
|
||||
if (root == null) { // all roots may be affected
|
||||
Collection<VirtualFile> roots = new ArrayList<VirtualFile>(1);
|
||||
for (VcsRoot vcsRoot : myVcsManager.getAllVcsRoots()) {
|
||||
if (vcsRoot.vcs != null && vcsRoot.vcs instanceof GitVcs && vcsRoot.path != null) {
|
||||
roots.add(vcsRoot.path);
|
||||
}
|
||||
}
|
||||
fullyUpdateBranchesInfo(roots);
|
||||
return;
|
||||
}
|
||||
|
||||
final Task.Backgroundable task = new Task.Backgroundable(myProject, "") {
|
||||
@Override public void run(@NotNull ProgressIndicator indicator) {
|
||||
try {
|
||||
GitBranch currentBranch = GitBranch.current(myProject, root);
|
||||
synchronized (myCurrentBranchesLock) {
|
||||
myCurrentBranches.put(root, currentBranch);
|
||||
}
|
||||
notifyListeners();
|
||||
} catch (VcsException e) {
|
||||
LOG.info("Exception while trying to get current branch for root " + root, e);
|
||||
// doing nothing - null will be set to myCurrentBranchName
|
||||
}
|
||||
}
|
||||
};
|
||||
GitVcs.runInBackground(task);
|
||||
}
|
||||
|
||||
private void fullyUpdateBranchesInfo(final Collection<VirtualFile> roots) {
|
||||
if (roots == null) { return; }
|
||||
final Task.Backgroundable task = new Task.Backgroundable(myProject, "") {
|
||||
@Override public void run(@NotNull ProgressIndicator indicator) {
|
||||
Map<VirtualFile, GitBranch> currentBranches = new HashMap<VirtualFile, GitBranch>();
|
||||
for (VirtualFile root : roots) {
|
||||
try {
|
||||
GitBranch currentBranch = GitBranch.current(myProject, root);
|
||||
currentBranches.put(root, currentBranch);
|
||||
notifyListeners();
|
||||
} catch (VcsException e) {
|
||||
LOG.info("Exception while trying to get current branch for root " + root, e);
|
||||
// doing nothing - null will be set to myCurrentBranchName
|
||||
}
|
||||
}
|
||||
synchronized (myCurrentBranchesLock) {
|
||||
myCurrentBranches = currentBranches;
|
||||
}
|
||||
}
|
||||
};
|
||||
GitVcs.runInBackground(task);
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
myListeners.getMulticaster().branchConfigurationChanged();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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 git4idea.branch;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* GitBranchesListener listens to events related to Git branches.
|
||||
* Change of active branch, branch creation, etc.
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public interface GitBranchesListener extends EventListener {
|
||||
void branchConfigurationChanged();
|
||||
}
|
||||
@@ -19,8 +19,20 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.changes.*;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.VcsKey;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManagerGate;
|
||||
import com.intellij.openapi.vcs.changes.ChangeProvider;
|
||||
import com.intellij.openapi.vcs.changes.ChangelistBuilder;
|
||||
import com.intellij.openapi.vcs.changes.ChangesUtil;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScope;
|
||||
import com.intellij.openapi.vcs.changes.VcsModifiableDirtyScope;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitContentRevision;
|
||||
import git4idea.GitRevisionNumber;
|
||||
@@ -125,6 +137,10 @@ public class GitChangeProvider implements ChangeProvider {
|
||||
}
|
||||
|
||||
public void unversioned(final VirtualFile vf) {
|
||||
// NB: There was an exception that happened several times: vf == null.
|
||||
// Populating myUnversioned in the ChangeCollector makes nulls not possible in myUnversioned,
|
||||
// so proposing that the exception was fixed.
|
||||
// More detailed analysis will be needed in case the exception appears again. 2010-12-09.
|
||||
myDirty.remove(new FilePathImpl(vf));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
@@ -101,6 +102,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper {
|
||||
private JRadioButton myStashRadioButton; // Save files policy option
|
||||
private JRadioButton myShelveRadioButton;
|
||||
private GitVcs myVcs;
|
||||
private static final Logger LOG = Logger.getInstance(GitPushActiveBranchesDialog.class.getName());
|
||||
|
||||
/**
|
||||
* A modification of Runnable with the roots-parameter.
|
||||
@@ -232,6 +234,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper {
|
||||
final Task.Backgroundable rebaseAndPushTask = new Task.Backgroundable(myProject, GitBundle.getString("push.active.fetching")) {
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
List<VcsException> exceptions = new ArrayList<VcsException>();
|
||||
List<VcsException> pushExceptions = new ArrayList<VcsException>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
final RebaseInfo rebaseInfo = collectRebaseInfo();
|
||||
|
||||
@@ -251,6 +254,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper {
|
||||
"Pushed " + commitsNum + " " + StringUtil.pluralize("commit", commitsNum) + ".");
|
||||
return;
|
||||
}
|
||||
pushExceptions = new ArrayList<VcsException>(exceptions);
|
||||
exceptions.clear();
|
||||
}
|
||||
|
||||
@@ -270,7 +274,7 @@ public class GitPushActiveBranchesDialog extends DialogWrapper {
|
||||
GitUtil.refreshFiles(myProject, rebaseInfo.roots);
|
||||
}
|
||||
}
|
||||
notifyException("Failed to push", exceptions);
|
||||
notifyException("Failed to push", pushExceptions);
|
||||
}
|
||||
};
|
||||
myVcs.runInBackground(rebaseAndPushTask);
|
||||
@@ -280,11 +284,15 @@ public class GitPushActiveBranchesDialog extends DialogWrapper {
|
||||
* Notifies about errors during background rebase & push tasks.
|
||||
*/
|
||||
private void notifyException(String title, Collection<VcsException> exceptions) {
|
||||
final String content = StringUtil.join(exceptions, new Function<VcsException, String>() {
|
||||
String content = StringUtil.join(exceptions, new Function<VcsException, String>() {
|
||||
@Override public String fun(VcsException e) {
|
||||
return e.getLocalizedMessage();
|
||||
}
|
||||
}, "<br/>");
|
||||
if (StringUtil.isEmptyOrSpaces(content)) {
|
||||
content = title;
|
||||
}
|
||||
LOG.info(title + " || " + content);
|
||||
Notifications.Bus.notify(new Notification(GitVcs.IMPORTANT_ERROR_NOTIFICATION, title, content, NotificationType.ERROR),
|
||||
NotificationDisplayType.STICKY_BALLOON, myProject);
|
||||
}
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
*/
|
||||
package git4idea.checkout;
|
||||
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.CheckoutProvider;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
@@ -28,6 +26,8 @@ import git4idea.actions.BasicAction;
|
||||
import git4idea.commands.GitCommand;
|
||||
import git4idea.commands.GitHandlerUtil;
|
||||
import git4idea.commands.GitLineHandler;
|
||||
import git4idea.commands.GitTask;
|
||||
import git4idea.commands.GitTaskResult;
|
||||
import git4idea.config.GitVersion;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -74,26 +74,26 @@ public class GitCheckoutProvider implements CheckoutProvider {
|
||||
final String originName,
|
||||
final String parentDirectory) {
|
||||
final GitLineHandler handler = clone(project, sourceRepositoryURL, new File(parentDirectory), directoryName, originName);
|
||||
|
||||
handler.addLineListener(new GitHandlerUtil.GitLineHandlerListenerProgress(ProgressManager.getInstance().getProgressIndicator(), handler, "git clone", true));
|
||||
new Task.Backgroundable(project, GitBundle.message("cloning.repository", sourceRepositoryURL), true) {
|
||||
@Override public void run(@NotNull ProgressIndicator indicator) {
|
||||
GitHandlerUtil.runInCurrentThread(handler, indicator, true, "git clone");
|
||||
}
|
||||
|
||||
@Override public void onSuccess() {
|
||||
destinationParent.refresh(true, true, new Runnable() {
|
||||
public void run() {
|
||||
if (project.isOpen() && (! project.isDisposed()) && (! project.isDefault())) {
|
||||
final VcsDirtyScopeManager mgr = VcsDirtyScopeManager.getInstance(project);
|
||||
mgr.fileDirty(destinationParent);
|
||||
GitTask task = new GitTask(project, handler, GitBundle.message("cloning.repository", sourceRepositoryURL));
|
||||
task.executeAsync(new GitTask.ResultHandler() {
|
||||
@Override
|
||||
public void run(GitTaskResult result) {
|
||||
if (result == GitTaskResult.OK) {
|
||||
destinationParent.refresh(true, true, new Runnable() {
|
||||
public void run() {
|
||||
if (project.isOpen() && (!project.isDisposed()) && (!project.isDefault())) {
|
||||
final VcsDirtyScopeManager mgr = VcsDirtyScopeManager.getInstance(project);
|
||||
mgr.fileDirty(destinationParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
listener.directoryCheckedOut(new File(parentDirectory, directoryName));
|
||||
listener.checkoutCompleted();
|
||||
});
|
||||
listener.directoryCheckedOut(new File(parentDirectory, directoryName));
|
||||
listener.checkoutCompleted();
|
||||
}
|
||||
}
|
||||
}.queue();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,16 +17,24 @@ package git4idea.checkout;
|
||||
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.*;
|
||||
import com.intellij.openapi.ui.ComponentWithBrowseButton;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.TextComponentAccessor;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.commands.GitCommand;
|
||||
import git4idea.commands.GitHandlerUtil;
|
||||
import git4idea.commands.GitSimpleHandler;
|
||||
import git4idea.commands.GitTask;
|
||||
import git4idea.commands.GitTaskResult;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import git4idea.validators.GitBranchNameValidator;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
@@ -163,14 +171,17 @@ public class GitCloneDialog extends DialogWrapper {
|
||||
myTestButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(final ActionEvent e) {
|
||||
myTestURL = myRepositoryURL.getText();
|
||||
String output = GitHandlerUtil
|
||||
.doSynchronously(checkRepository(myProject, myTestURL), GitBundle.message("clone.testing", myTestURL), "connection test");
|
||||
if (output != null) {
|
||||
GitSimpleHandler handler = new GitSimpleHandler(myProject, new File("."), GitCommand.LS_REMOTE);
|
||||
handler.addParameters(myTestURL, "master");
|
||||
|
||||
GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", myTestURL));
|
||||
GitTaskResult result = task.execute();
|
||||
|
||||
if (result.isOK()) {
|
||||
Messages.showInfoMessage(myTestButton, GitBundle.message("clone.test.success.message", myTestURL),
|
||||
GitBundle.getString("clone.test.success"));
|
||||
myTestResult = Boolean.TRUE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
myTestResult = Boolean.FALSE;
|
||||
}
|
||||
updateOkButton();
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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 git4idea.checkout.branches;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.CalledInAwt;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.VcsRoot;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.StatusBarWidget;
|
||||
import com.intellij.openapi.wm.impl.status.EditorBasedWidget;
|
||||
import com.intellij.util.Consumer;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.vfs.GitReferenceListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Status bar widget which displays the current branch.
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitCurrentBranchWidget extends EditorBasedWidget implements StatusBarWidget.TextPresentation, GitReferenceListener, StatusBarWidget.Multiframe {
|
||||
|
||||
private ProjectLevelVcsManager myVcsManager;
|
||||
private AtomicReference<String> myCurrentBranchName = new AtomicReference<String>("");
|
||||
private static final Logger LOG = Logger.getInstance(GitCurrentBranchWidget.class.getName());
|
||||
private final Map<VirtualFile, GitBranch> myCurrentBranches = new HashMap<VirtualFile, GitBranch>();
|
||||
|
||||
public GitCurrentBranchWidget(Project project) {
|
||||
super(project);
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
updateBranchInfo(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatusBarWidget copy() {
|
||||
return new GitCurrentBranchWidget(getProject());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String ID() {
|
||||
return "git4idea.GitCurrentBranchWidget";
|
||||
}
|
||||
|
||||
@Override
|
||||
public WidgetPresentation getPresentation(@NotNull PlatformType type) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectionChanged(FileEditorManagerEvent event) {
|
||||
updateUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileOpened(FileEditorManager source, VirtualFile file) {
|
||||
updateUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileClosed(FileEditorManager source, VirtualFile file) {
|
||||
updateUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void referencesChanged(VirtualFile root) {
|
||||
updateBranchInfo(root);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
final String text = myCurrentBranchName.get();
|
||||
return StringUtil.isEmpty(text) ? "" : "Git: " + text;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getMaxPossibleText() {
|
||||
return "Git: abcdefghij";
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getAlignment() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltipText() {
|
||||
return "Current Git branch";
|
||||
}
|
||||
|
||||
@Override
|
||||
// Updates branch information on click
|
||||
public Consumer<MouseEvent> getClickConsumer() {
|
||||
return new Consumer<MouseEvent>() {
|
||||
public void consume(MouseEvent mouseEvent) {
|
||||
updateUI();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
private void updateUI() {
|
||||
final VirtualFile file = getSelectedFile();
|
||||
final Project project = getProject();
|
||||
if (file == null || project == null || isDisposed() || !project.isOpen() || project.isDisposed() || myStatusBar == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String currentBranchName = null;
|
||||
final AbstractVcs vcs = myVcsManager.getVcsFor(file);
|
||||
if (vcs != null && vcs instanceof GitVcs) {
|
||||
final VirtualFile root = myVcsManager.getVcsRootFor(file);
|
||||
if (root != null) {
|
||||
final GitBranch currentBranch = myCurrentBranches.get(root);
|
||||
if (currentBranch != null) {
|
||||
currentBranchName = currentBranch.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (currentBranchName == null) {
|
||||
currentBranchName = "";
|
||||
}
|
||||
myCurrentBranchName.set(currentBranchName);
|
||||
myStatusBar.updateWidget(ID());
|
||||
}
|
||||
|
||||
private void updateBranchInfo(VirtualFile root) {
|
||||
final Collection<VirtualFile> roots = new ArrayList<VirtualFile>(1);
|
||||
if (root == null) { // all roots may be affected
|
||||
for (VcsRoot vcsRoot : myVcsManager.getAllVcsRoots()) {
|
||||
if (vcsRoot.vcs != null && vcsRoot.vcs instanceof GitVcs && vcsRoot.path != null) {
|
||||
roots.add(vcsRoot.path);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
roots.add(root);
|
||||
}
|
||||
|
||||
final Project project = getProject();
|
||||
final Task.Backgroundable task = new Task.Backgroundable(project, "Loading Git branch info") {
|
||||
@Override public void run(@NotNull ProgressIndicator indicator) {
|
||||
for (VirtualFile root : roots) {
|
||||
try {
|
||||
GitBranch currentBranch = GitBranch.current(project, root);
|
||||
synchronized (myCurrentBranches) {
|
||||
myCurrentBranches.put(root, currentBranch);
|
||||
}
|
||||
} catch (VcsException e) {
|
||||
LOG.info("Exception while trying to get current branch for root " + root, e);
|
||||
}
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
updateUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
if (project != null) {
|
||||
GitVcs.getInstance(project).runInBackground(task);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.commands;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
@@ -82,6 +83,10 @@ public class GitBinaryHandler extends GitHandler {
|
||||
super(project, vcsRoot, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Process startProcess() throws ExecutionException {
|
||||
return myCommandLine.createProcess();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@@ -132,7 +137,7 @@ public class GitBinaryHandler extends GitHandler {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void destroyProcess() {
|
||||
public void destroyProcess() {
|
||||
myProcess.destroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.commands;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -397,7 +398,7 @@ public abstract class GitHandler {
|
||||
}
|
||||
myCommandLine.setEnvParams(myEnv);
|
||||
// start process
|
||||
myProcess = myCommandLine.createProcess();
|
||||
myProcess = startProcess();
|
||||
startHandlingStreams();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
@@ -410,8 +411,10 @@ public abstract class GitHandler {
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Process startProcess() throws ExecutionException;
|
||||
|
||||
/**
|
||||
* Start handling streams for the handler
|
||||
* Start handling process output streams for the handler.
|
||||
*/
|
||||
protected abstract void startHandlingStreams();
|
||||
|
||||
@@ -438,7 +441,7 @@ public abstract class GitHandler {
|
||||
/**
|
||||
* Destroy process
|
||||
*/
|
||||
protected abstract void destroyProcess();
|
||||
public abstract void destroyProcess();
|
||||
|
||||
/**
|
||||
* @return exit code for process if it is available
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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 git4idea.commands;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* A Task to run the given GitHandler with ability to cancel it.
|
||||
* Cancellation is implemented with a {@link java.util.Timer} which checks whether the ProgressIndicator was cancelled and kills
|
||||
* the GitHandler in that case.
|
||||
*
|
||||
* A GitTask may be executed synchronously ({@link #execute()} or asynchronously ({@link #executeAsync(GitTask.ResultHandler)}.
|
||||
* Result of the execution is encapsulated in {@link GitTaskResult}.
|
||||
*
|
||||
* @see {@link git4idea.commands.GitHandler#kill()}
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitTask {
|
||||
|
||||
private final Project myProject;
|
||||
private final GitHandler myHandler;
|
||||
private final String myTitle;
|
||||
private final AtomicReference<GitTaskResult> myResult = new AtomicReference<GitTaskResult>(GitTaskResult.INITIAL);
|
||||
|
||||
public interface ResultHandler {
|
||||
void run(GitTaskResult result);
|
||||
}
|
||||
|
||||
public GitTask(Project project, GitHandler handler, String title) {
|
||||
myProject = project;
|
||||
myHandler = handler;
|
||||
myTitle = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this task synchronously, with a modal progress dialog.
|
||||
* @return Result of the task execution.
|
||||
*/
|
||||
public GitTaskResult execute() {
|
||||
ModalTask task = new ModalTask(myProject, myHandler, myTitle) {
|
||||
public void execute(ProgressIndicator indicator) {
|
||||
GitHandlerUtil.runInCurrentThread(myHandler, indicator, true, myTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
if (!myHandler.errors().isEmpty()) {
|
||||
myResult.set(GitTaskResult.GIT_ERROR);
|
||||
} else {
|
||||
myResult.set(GitTaskResult.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
myResult.set(GitTaskResult.CANCELLED);
|
||||
}
|
||||
};
|
||||
|
||||
addListeners(task);
|
||||
ProgressManager.getInstance().run(task);
|
||||
return myResult.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this task asynchronously, in backgrond. Calls the resultHandler when finished.
|
||||
* @param resultHandler callback called after the task has finished or was cancelled by user or automatically.
|
||||
*/
|
||||
public void executeAsync(final ResultHandler resultHandler) {
|
||||
BackgroundableTask task = new BackgroundableTask(myProject, myHandler, myTitle) {
|
||||
public void execute(ProgressIndicator indicator) {
|
||||
GitHandlerUtil.runInCurrentThread(myHandler, indicator, true, myTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
if (!myHandler.errors().isEmpty()) { // TODO: handle errors smarter: an error may be not a complete failure.
|
||||
myResult.set(GitTaskResult.GIT_ERROR);
|
||||
} else {
|
||||
myResult.set(GitTaskResult.OK);
|
||||
}
|
||||
resultHandler.run(myResult.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
myResult.set(GitTaskResult.CANCELLED);
|
||||
resultHandler.run(GitTaskResult.CANCELLED);
|
||||
}
|
||||
};
|
||||
|
||||
addListeners(task);
|
||||
GitVcs.getInstance(myProject).runInBackground(task);
|
||||
}
|
||||
|
||||
private void addListeners(final TaskExecution task) {
|
||||
// When receives an error line, adds a VcsException to the GitHandler.
|
||||
final GitLineHandlerListener errorListener = new GitLineHandlerListener() {
|
||||
@Override
|
||||
public void processTerminated(int exitCode) {
|
||||
if (exitCode != 0 && !myHandler.isIgnoredErrorCode(exitCode)) {
|
||||
if (myHandler.errors().isEmpty()) {
|
||||
myHandler.addError(new VcsException(GitBundle.message("git.error.exit", exitCode)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFailed(Throwable exception) {
|
||||
myHandler.addError(new VcsException("Git start failed: " + exception.getMessage(), exception));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
if (GitHandlerUtil.isErrorLine(line.trim())) {
|
||||
myHandler.addError(new VcsException(line));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
myHandler.addListener(errorListener);
|
||||
if (myHandler instanceof GitLineHandler) {
|
||||
((GitLineHandler)myHandler).addLineListener(errorListener);
|
||||
}
|
||||
|
||||
// disposes the timer
|
||||
myHandler.addListener(new GitHandlerListener() {
|
||||
@Override
|
||||
public void processTerminated(int exitCode) {
|
||||
task.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFailed(Throwable exception) {
|
||||
task.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* We're using this interface here to work with Task, because standard {@link Task#run(com.intellij.openapi.progress.ProgressIndicator)}
|
||||
* is busy with timers.
|
||||
*/
|
||||
private interface TaskExecution {
|
||||
void execute(ProgressIndicator indicator);
|
||||
void dispose();
|
||||
}
|
||||
|
||||
// To add to {@link com.intellij.openapi.progress.BackgroundTaskQueue} a task must be {@link Task.Backgroundable},
|
||||
// so we can't have a single class representing a task: we have BackgroundableTask and ModalTask.
|
||||
// To minimize code duplication we use GitTaskDelegate.
|
||||
|
||||
private abstract class BackgroundableTask extends Task.Backgroundable implements TaskExecution {
|
||||
private GitTaskDelegate myDelegate;
|
||||
|
||||
public BackgroundableTask(@Nullable final Project project, @NotNull GitHandler handler, @NotNull final String processTitle) {
|
||||
super(project, processTitle, true);
|
||||
myDelegate = new GitTaskDelegate(myProject, handler, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run(@NotNull ProgressIndicator indicator) {
|
||||
myDelegate.run(indicator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Disposer.dispose(myDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class ModalTask extends Task.Modal implements TaskExecution {
|
||||
private GitTaskDelegate myDelegate;
|
||||
|
||||
public ModalTask(@Nullable final Project project, @NotNull GitHandler handler, @NotNull final String processTitle) {
|
||||
super(project, processTitle, true);
|
||||
myDelegate = new GitTaskDelegate(myProject, handler, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run(@NotNull ProgressIndicator indicator) {
|
||||
myDelegate.run(indicator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
Disposer.dispose(myDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the work which is common for BackgrounableTask and ModalTask.
|
||||
* Actually - starts a timer which checks if current progress indicator is cancelled.
|
||||
* If yes, kills the GitHandler.
|
||||
*/
|
||||
private static class GitTaskDelegate implements Disposable {
|
||||
private GitHandler myHandler;
|
||||
private ProgressIndicator myIndicator;
|
||||
private TaskExecution myTask;
|
||||
private Timer myTimer;
|
||||
private Project myProject;
|
||||
|
||||
public GitTaskDelegate(Project project, GitHandler handler, TaskExecution task) {
|
||||
myProject = project;
|
||||
myHandler = handler;
|
||||
myTask = task;
|
||||
Disposer.register(myProject, this);
|
||||
}
|
||||
|
||||
public void run(ProgressIndicator indicator) {
|
||||
myIndicator = indicator;
|
||||
myTimer = new Timer();
|
||||
myTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myIndicator != null && myIndicator.isCanceled()) {
|
||||
if (myHandler != null) {
|
||||
myHandler.destroyProcess();
|
||||
}
|
||||
Disposer.dispose(GitTaskDelegate.this);
|
||||
}
|
||||
}
|
||||
}, 0, 200);
|
||||
myTask.execute(indicator);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
myTimer.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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 git4idea.commands;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public enum GitTaskResult {
|
||||
INITIAL, WORKING, OK, EXCEPTION, GIT_ERROR, TIMEOUT, CANCELLED, TERMINATED;
|
||||
|
||||
public boolean isOK() {
|
||||
return this == OK;
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,13 @@
|
||||
*/
|
||||
package git4idea.commands;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.OSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.process.ProcessListener;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.execution.process.RunnerMediator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -31,44 +34,28 @@ import java.nio.charset.Charset;
|
||||
* The handler for git commands with text outputs
|
||||
*/
|
||||
public abstract class GitTextHandler extends GitHandler {
|
||||
/**
|
||||
* the logger
|
||||
*/
|
||||
private static final Logger log = Logger.getInstance(GitTextHandler.class.getName());
|
||||
|
||||
/**
|
||||
* wrapped process handler
|
||||
*/
|
||||
// note that access is safe because it accessed in unsynchronized block only after process is started, and it does not change after that
|
||||
@SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private OSProcessHandler myHandler;
|
||||
|
||||
/**
|
||||
* The constructor from super
|
||||
*
|
||||
* @param project the project
|
||||
* @param directory the command directory
|
||||
* @param command the command
|
||||
*/
|
||||
protected GitTextHandler(@NotNull Project project, @NotNull File directory, @NotNull GitCommand command) {
|
||||
super(project, directory, command);
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*
|
||||
* @param project the project
|
||||
* @param vcsRoot the vcs root
|
||||
* @param command the command to run
|
||||
*/
|
||||
protected GitTextHandler(final Project project, final VirtualFile vcsRoot, final GitCommand command) {
|
||||
super(project, vcsRoot, command);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Process startProcess() throws ExecutionException {
|
||||
final ProcessHandler processHandler = new MyRunnerMediator().createProcess(myCommandLine);
|
||||
myHandler = (MyOSProcessHandler)processHandler;
|
||||
return myHandler.getProcess();
|
||||
}
|
||||
|
||||
protected void startHandlingStreams() {
|
||||
myHandler = new MyOSProcessHandler(myProcess, myCommandLine.getCommandLineString(), getCharset());
|
||||
myHandler.addProcessListener(new ProcessListener() {
|
||||
public void startNotified(final ProcessEvent event) {
|
||||
// do nothing
|
||||
@@ -108,31 +95,28 @@ public abstract class GitTextHandler extends GitHandler {
|
||||
*/
|
||||
protected abstract void onTextAvailable(final String text, final Key outputType);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected void destroyProcess() {
|
||||
try {
|
||||
myHandler.destroyProcess();
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.warn("Exception during cancel", e);
|
||||
}
|
||||
public void destroyProcess() {
|
||||
myHandler.destroyProcess();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected void waitForProcess() {
|
||||
OSProcessHandler handler = myHandler;
|
||||
myHandler = null;
|
||||
handler.waitFor();
|
||||
myHandler.waitFor();
|
||||
}
|
||||
|
||||
private static class MyOSProcessHandler extends OSProcessHandler {
|
||||
/**
|
||||
* RunnerMediator that attaches our MyProcessHandler to the process instead of the standard CustomDestroyProcessHandler.
|
||||
*/
|
||||
private class MyRunnerMediator extends RunnerMediator {
|
||||
@Override
|
||||
protected ProcessHandler createProcessHandler(@NotNull Process process, @NotNull GeneralCommandLine commandLine) {
|
||||
return new MyOSProcessHandler(process, commandLine, getCharset());
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyOSProcessHandler extends RunnerMediator.CustomDestroyProcessHandler {
|
||||
private final Charset myCharset;
|
||||
|
||||
public MyOSProcessHandler(Process process, String commandLine, Charset charset) {
|
||||
public MyOSProcessHandler(Process process, GeneralCommandLine commandLine, Charset charset) {
|
||||
super(process, commandLine);
|
||||
myCharset = charset;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,12 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.AbstractVcsHelper;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.*;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManagerEx;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vcs.changes.InvokeAfterUpdateMode;
|
||||
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager;
|
||||
import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -47,7 +52,16 @@ import git4idea.ui.GitConvertFilesDialog;
|
||||
import git4idea.ui.GitUIUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
@@ -126,6 +140,7 @@ public abstract class GitBaseRebaseProcess {
|
||||
* @param roots the vcs roots
|
||||
*/
|
||||
public void doUpdate(ProgressIndicator progressIndicator, Set<VirtualFile> roots) {
|
||||
LOG.info("GitBaseRebaseProcess.doUpdate started");
|
||||
ProjectManagerEx projectManager = ProjectManagerEx.getInstanceEx();
|
||||
projectManager.blockReloadingProjectOnExternalChanges();
|
||||
this.myProgressIndicator = progressIndicator;
|
||||
@@ -244,6 +259,7 @@ public abstract class GitBaseRebaseProcess {
|
||||
* Restore project changes after update
|
||||
*/
|
||||
private void restoreProjectChangesAfterUpdate() {
|
||||
LOG.info("GitBaseRebaseProcess.restoreProjectChangesAfterUpdate update policy: " + getUpdatePolicy() + " myShelvedChangeList: " + myShelvedChangeList);
|
||||
if (mySkippedCommits.size() > 0) {
|
||||
GitSkippedCommits.showSkipped(myProject, mySkippedCommits);
|
||||
}
|
||||
@@ -259,6 +275,7 @@ public abstract class GitBaseRebaseProcess {
|
||||
final boolean isStash = getUpdatePolicy() == GitVcsSettings.UpdateChangesPolicy.STASH;
|
||||
HashSet<File> filesToRefresh = isStash ? new HashSet<File>() : null;
|
||||
for (LocalChangeList changeList : myListsCopy) {
|
||||
LOG.info("GitBaseRebaseProcess.restoreProjectChangesAfterUpdate refreshing files from changelist " + changeList);
|
||||
for (Change c : changeList.getChanges()) {
|
||||
ContentRevision after = c.getAfterRevision();
|
||||
if (after != null) {
|
||||
@@ -285,6 +302,7 @@ public abstract class GitBaseRebaseProcess {
|
||||
public void run() {
|
||||
for (LocalChangeList changeList : myListsCopy) {
|
||||
final Collection<Change> changes = changeList.getChanges();
|
||||
LOG.debug("restoreProjectChangesAfterUpdate.invokeAfterUpdate changeList: " + changeList.getName() + " changes: " + changes.size());
|
||||
if (!changes.isEmpty()) {
|
||||
LOG.debug("After restoring files: moving " + changes.size() + " changes to '" + changeList.getName() + "'");
|
||||
myChangeManager.moveChangesTo(changeList, changes.toArray(new Change[changes.size()]));
|
||||
@@ -351,12 +369,13 @@ public abstract class GitBaseRebaseProcess {
|
||||
* @return false, if update process needs to be aborted
|
||||
*/
|
||||
private boolean saveProjectChangesBeforeUpdate() {
|
||||
LOG.info("GitBaseRebaseProcess.saveProjectChangesBeforeUpdate update policy: " + getUpdatePolicy());
|
||||
if (getUpdatePolicy() == GitVcsSettings.UpdateChangesPolicy.STASH || getUpdatePolicy() == GitVcsSettings.UpdateChangesPolicy.SHELVE) {
|
||||
myStashMessage = makeStashMessage();
|
||||
myListsCopy = myChangeManager.getChangeListsCopy();
|
||||
for (LocalChangeList l : myListsCopy) {
|
||||
final Collection<Change> changeCollection = l.getChanges();
|
||||
LOG.debug("Stashing " + changeCollection.size() + " changes from '" + l.getName() + "'");
|
||||
LOG.info("Stashing " + changeCollection.size() + " changes from '" + l.getName() + "'");
|
||||
for (Change c : changeCollection) {
|
||||
ContentRevision after = c.getAfterRevision();
|
||||
if (after != null) {
|
||||
@@ -405,7 +424,9 @@ public abstract class GitBaseRebaseProcess {
|
||||
}
|
||||
if (changes.size() > 0) {
|
||||
myProgressIndicator.setText(GitBundle.getString("update.shelving.changes"));
|
||||
LOG.info("GitBaseRebaseProcess.saveProjectChangesBeforeUpdate shelving changes");
|
||||
myShelvedChangeList = GitStashUtils.shelveChanges(myProject, myShelveManager, changes, myStashMessage, myExceptions);
|
||||
LOG.info("GitBaseRebaseProcess.saveProjectChangesBeforeUpdate shelved changes to " + myShelvedChangeList);
|
||||
if (myShelvedChangeList == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package git4idea.update;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.FileStatus;
|
||||
@@ -42,7 +43,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The class contains utilities for creating and removing stashes.
|
||||
@@ -52,6 +57,7 @@ public class GitStashUtils {
|
||||
* The version when quiet stash supported
|
||||
*/
|
||||
private final static GitVersion QUIET_STASH_SUPPORTED = new GitVersion(1, 6, 4, 0);
|
||||
private static final Logger LOG = Logger.getInstance(GitStashUtils.class.getName());
|
||||
|
||||
private GitStashUtils() {
|
||||
}
|
||||
@@ -103,6 +109,7 @@ public class GitStashUtils {
|
||||
final ShelveChangesManager shelveManager,
|
||||
final ChangeListManagerEx changeManager,
|
||||
List<VcsException> exceptions) {
|
||||
LOG.info("doSystemUnshelve ");
|
||||
// The changes are temporary copied to the first local change list, the next operation will restore them back
|
||||
VirtualFile baseDir = project.getBaseDir();
|
||||
assert baseDir != null;
|
||||
@@ -126,15 +133,18 @@ public class GitStashUtils {
|
||||
}
|
||||
}
|
||||
LocalFileSystem.getInstance().refreshIoFiles(filesToRefresh);
|
||||
LOG.info("doSystemUnshelve files refreshed. unshelving in AWT thread.");
|
||||
// Do unshevle
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
GitVFSListener l = GitVcs.getInstance(project).getVFSListener();
|
||||
l.setEventsSuppressed(true);
|
||||
try {
|
||||
LOG.info("Unshelving in UI thread. shelvedChangeList: " + shelvedChangeList);
|
||||
shelveManager
|
||||
.unshelveChangeList(shelvedChangeList, shelvedChangeList.getChanges(), shelvedChangeList.getBinaryFiles(),
|
||||
changeManager.getDefaultChangeList(), false);
|
||||
LOG.info("Deleting change list");
|
||||
shelveManager.deleteChangeList(shelvedChangeList);
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
<action id="Github.Rebase" class="org.jetbrains.plugins.github.GithubRebaseAction">
|
||||
<add-to-group group-id="VcsGlobalGroup"/>
|
||||
</action>
|
||||
<action id="Github.Open.In.Browser" class="org.jetbrains.plugins.github.GithubOpenInBrowserAction">
|
||||
<add-to-group group-id="EditorPopupMenu"/>
|
||||
</action>
|
||||
<action id="Github.Rebase.Internal" class="org.jetbrains.plugins.github.GithubRebase"/>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2000-2010 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 org.jetbrains.plugins.github;
|
||||
|
||||
import com.intellij.ide.BrowserUtil;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitRemote;
|
||||
import git4idea.GitUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
*
|
||||
* @author oleg
|
||||
* @date 12/10/10
|
||||
*/
|
||||
public class GithubOpenInBrowserAction extends DumbAwareAction {
|
||||
public static final Icon ICON = IconLoader.getIcon("/icons/github.png");
|
||||
private static final Logger LOG = Logger.getInstance(GithubOpenInBrowserAction.class.getName());
|
||||
private static final String CANNOT_OPEN_IN_BROWSER = "Cannot open in browser";
|
||||
|
||||
protected GithubOpenInBrowserAction() {
|
||||
super("Open in browser", "Open corresponding GitHub link in browser", ICON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
final Project project = e.getData(PlatformDataKeys.PROJECT);
|
||||
final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE);
|
||||
if (project == null || project.isDefault() || virtualFile == null) {
|
||||
e.getPresentation().setEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (GithubUtil.getGithubBoundRepository(project) == null){
|
||||
e.getPresentation().setEnabled(false);
|
||||
return;
|
||||
}
|
||||
e.getPresentation().setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
final Project project = e.getData(PlatformDataKeys.PROJECT);
|
||||
|
||||
final VirtualFile[] roots = ProjectRootManager.getInstance(project).getContentRoots();
|
||||
if (roots.length == 0) {
|
||||
Messages.showErrorDialog(project, "Project doesn't have any project roots", CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
}
|
||||
final VirtualFile root = roots[0];
|
||||
// Check if git is already initialized and presence of remote branch
|
||||
final boolean gitDetected = GitUtil.isUnderGit(root);
|
||||
if (!gitDetected) {
|
||||
Messages.showErrorDialog(project, "Cannot find any git repository configured for the project", CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
}
|
||||
final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE);
|
||||
final String rootPath = root.getPath();
|
||||
final String path = virtualFile.getPath();
|
||||
if (!path.startsWith(rootPath)){
|
||||
Messages.showErrorDialog(project, "File is not under project root", CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// Check that given repository is properly configured git repository
|
||||
GitRemote githubRemote = null;
|
||||
final List<GitRemote> gitRemotes = GitRemote.list(project, root);
|
||||
if (gitRemotes.isEmpty()) {
|
||||
Messages.showErrorDialog(project, "Git repository doesn't have any remotes configured", CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
}
|
||||
for (GitRemote gitRemote : gitRemotes) {
|
||||
if (gitRemote.pushUrl().contains("git@github.com")) {
|
||||
githubRemote = gitRemote;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (githubRemote == null) {
|
||||
Messages.showErrorDialog(project, "Configured own github repository is not found", CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
}
|
||||
|
||||
final String pushUrl = githubRemote.pushUrl();
|
||||
final String login = GithubSettings.getInstance().getLogin();
|
||||
final int index = pushUrl.lastIndexOf(login);
|
||||
if (index == -1) {
|
||||
Messages.showErrorDialog(project, "Github remote repository doesn't seem to be your own repository: " + pushUrl,
|
||||
CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
}
|
||||
String repoName = pushUrl.substring(index + login.length() + 1);
|
||||
if (repoName.endsWith(".git")) {
|
||||
repoName = repoName.substring(0, repoName.length() - 4);
|
||||
}
|
||||
final RepositoryInfo repositoryInfo = GithubUtil.getDetailedRepositoryInfo(project, repoName);
|
||||
if (repositoryInfo == null) {
|
||||
Messages
|
||||
.showErrorDialog(project, "Github repository doesn't seem to be your own repository: " + pushUrl, CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
}
|
||||
// TODO[oleg] support custom branches here
|
||||
BrowserUtil.launchBrowser("https://github.com/" + login + "/" + repoName + "/blob/master" + path.substring(rootPath.length()));
|
||||
|
||||
} catch (VcsException e1){
|
||||
Messages.showErrorDialog(project, "Error happened during git operation: " + e1.getMessage(), CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitRemote;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.actions.BasicAction;
|
||||
@@ -45,6 +44,7 @@ import java.util.List;
|
||||
public class GithubRebaseAction extends DumbAwareAction {
|
||||
public static final Icon ICON = IconLoader.getIcon("/icons/github.png");
|
||||
private static final Logger LOG = Logger.getInstance(GithubRebaseAction.class.getName());
|
||||
private static final String CANNOT_PERFORM_GITHUB_REBASE = "Cannot perform github rebase";
|
||||
|
||||
public GithubRebaseAction() {
|
||||
super("Rebase my fork", "Rebase your forked repository relative to the origin", ICON);
|
||||
@@ -56,6 +56,10 @@ public class GithubRebaseAction extends DumbAwareAction {
|
||||
e.getPresentation().setEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (GithubUtil.getGithubBoundRepository(project) == null){
|
||||
e.getPresentation().setEnabled(false);
|
||||
return;
|
||||
}
|
||||
e.getPresentation().setEnabled(true);
|
||||
}
|
||||
|
||||
@@ -64,54 +68,29 @@ public class GithubRebaseAction extends DumbAwareAction {
|
||||
final Project project = e.getData(PlatformDataKeys.PROJECT);
|
||||
final VirtualFile[] roots = ProjectRootManager.getInstance(project).getContentRoots();
|
||||
if (roots.length == 0) {
|
||||
Messages.showErrorDialog(project, "Project doesn't have any project roots", "Cannot create new GitHub repository");
|
||||
Messages.showErrorDialog(project, "Project doesn't have any project roots", CANNOT_PERFORM_GITHUB_REBASE);
|
||||
return;
|
||||
}
|
||||
final VirtualFile root = roots[0];
|
||||
// Check if git is already initialized and presence of remote branch
|
||||
final boolean gitDetected = GitUtil.isUnderGit(root);
|
||||
if (!gitDetected) {
|
||||
Messages.showErrorDialog(project, "Cannot find any git repository configured for the project", "Cannot perform github rebase");
|
||||
Messages.showErrorDialog(project, "Cannot find any git repository configured for the project", CANNOT_PERFORM_GITHUB_REBASE);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Check current branch
|
||||
final GitBranch currentBranch = GitBranch.current(project, root);
|
||||
if (currentBranch == null) {
|
||||
Messages.showErrorDialog(project, "Cannot find current branch", "Cannot perform github rebase");
|
||||
return;
|
||||
}
|
||||
if (!"master".equals(currentBranch.getName())) {
|
||||
Messages.showErrorDialog(project, "Cannot perform rebase with '" + currentBranch.getName() + "' branch.\nPlease switch to master",
|
||||
"Cannot perform github rebase");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that given repository is properly configured git repository
|
||||
GitRemote githubRemote = null;
|
||||
final GitRemote githubRemote = GithubUtil.getGithubBoundRepository(project);
|
||||
final List<GitRemote> gitRemotes = GitRemote.list(project, root);
|
||||
if (gitRemotes.isEmpty()) {
|
||||
Messages.showErrorDialog(project, "Git repository doesn't have any remotes configured", "Cannot perform github rebase");
|
||||
return;
|
||||
}
|
||||
for (GitRemote gitRemote : gitRemotes) {
|
||||
if (gitRemote.pushUrl().contains("git@github.com")) {
|
||||
githubRemote = gitRemote;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (githubRemote == null) {
|
||||
Messages.showErrorDialog(project, "Configured own github repository is not found", "Cannot perform github rebase");
|
||||
return;
|
||||
}
|
||||
LOG.assertTrue(githubRemote != null);
|
||||
|
||||
final String pushUrl = githubRemote.pushUrl();
|
||||
final String login = GithubSettings.getInstance().getLogin();
|
||||
final int index = pushUrl.lastIndexOf(login);
|
||||
if (index == -1) {
|
||||
Messages.showErrorDialog(project, "Github remote repository doesn't seem to be your own repository: " + pushUrl,
|
||||
"Cannot perform github rebase");
|
||||
CANNOT_PERFORM_GITHUB_REBASE);
|
||||
return;
|
||||
}
|
||||
String repoName = pushUrl.substring(index + login.length() + 1);
|
||||
@@ -122,12 +101,12 @@ public class GithubRebaseAction extends DumbAwareAction {
|
||||
final RepositoryInfo repositoryInfo = GithubUtil.getDetailedRepositoryInfo(project, repoName);
|
||||
if (repositoryInfo == null) {
|
||||
Messages
|
||||
.showErrorDialog(project, "Github repository doesn't seem to be your own repository: " + pushUrl, "Cannot perform github rebase");
|
||||
.showErrorDialog(project, "Github repository doesn't seem to be your own repository: " + pushUrl, CANNOT_PERFORM_GITHUB_REBASE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!repositoryInfo.isFork()) {
|
||||
Messages.showErrorDialog(project, "Github repository '" + repoName + "' is not a forked one", "Cannot perform github rebase");
|
||||
Messages.showErrorDialog(project, "Github repository '" + repoName + "' is not a forked one", CANNOT_PERFORM_GITHUB_REBASE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -161,7 +140,7 @@ public class GithubRebaseAction extends DumbAwareAction {
|
||||
addRemoteHandler.addParameters("add", repoName, parentRepoUrl);
|
||||
addRemoteHandler.run();
|
||||
if (addRemoteHandler.getExitCode() != 0) {
|
||||
Messages.showErrorDialog("Failed to add GitHub remote: '" + parentRepoUrl + "'", "Failed to add GitHub remote");
|
||||
Messages.showErrorDialog("Failed to add GitHub remote: '" + parentRepoUrl + "'", CANNOT_PERFORM_GITHUB_REBASE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,7 +154,7 @@ public class GithubRebaseAction extends DumbAwareAction {
|
||||
action.actionPerformed(actionEvent);
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
Messages.showErrorDialog(project, "Error happened during git operation: " + e1.getMessage(), "Cannot perform github rebase");
|
||||
Messages.showErrorDialog(project, "Error happened during git operation: " + e1.getMessage(), CANNOT_PERFORM_GITHUB_REBASE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ public class GithubSettings implements PersistentStateComponent<Element> {
|
||||
return null;
|
||||
}
|
||||
final Element element = new Element(GITHUB_SETTINGS_TAG);
|
||||
element.setAttribute(LOGIN, myLogin);
|
||||
element.setAttribute(LOGIN, getLogin());
|
||||
element.setAttribute(PASSWORD, getEncodedPassword());
|
||||
element.setAttribute(CLONE_PATH, myClonePath);
|
||||
element.setAttribute(CLONE_PATH, getClonePath());
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,14 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitRemote;
|
||||
import git4idea.GitUtil;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.commons.httpclient.UsernamePasswordCredentials;
|
||||
@@ -236,4 +241,30 @@ public class GithubUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static GitRemote getGithubBoundRepository(final Project project){
|
||||
final VirtualFile[] roots = ProjectRootManager.getInstance(project).getContentRoots();
|
||||
if (roots.length == 0) {
|
||||
return null;
|
||||
}
|
||||
final VirtualFile root = roots[0];
|
||||
// Check if git is already initialized and presence of remote branch
|
||||
final boolean gitDetected = GitUtil.isUnderGit(root);
|
||||
if (!gitDetected) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// Check that given repository is properly configured git repository
|
||||
final List<GitRemote> gitRemotes = GitRemote.list(project, root);
|
||||
for (GitRemote gitRemote : gitRemotes) {
|
||||
if (gitRemote.pushUrl().contains("git@github.com")) {
|
||||
return gitRemote;
|
||||
}
|
||||
}
|
||||
} catch (VcsException e){
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ public class JUnit3IdeaTestRunner extends TestRunner implements IdeaTestRunner {
|
||||
|
||||
public void setStreams(SegmentedOutputStream segmentedOut, SegmentedOutputStream segmentedErr) {
|
||||
setPrinter(new TimeSender());
|
||||
myRegistry = new JUnit3OutputObjectRegistry(segmentedOut, segmentedErr);
|
||||
myTestsListener = new TestResultsSender(myRegistry, segmentedErr);
|
||||
myRegistry = new JUnit3OutputObjectRegistry(segmentedOut);
|
||||
myTestsListener = new TestResultsSender(myRegistry);
|
||||
}
|
||||
|
||||
protected TestResult createTestResult() {
|
||||
|
||||
@@ -28,12 +28,8 @@ import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
public class JUnit3OutputObjectRegistry extends OutputObjectRegistry {
|
||||
public JUnit3OutputObjectRegistry(PacketProcessor mainTransport, PacketProcessor auxilaryTransport) {
|
||||
super(mainTransport, auxilaryTransport);
|
||||
}
|
||||
|
||||
public JUnit3OutputObjectRegistry(PacketProcessor out) {
|
||||
super(out);
|
||||
public JUnit3OutputObjectRegistry(PacketProcessor mainTransport) {
|
||||
super(mainTransport);
|
||||
}
|
||||
|
||||
protected int getTestCont(Object test) {
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.intellij.junit3;
|
||||
import com.intellij.rt.execution.junit.*;
|
||||
import com.intellij.rt.execution.junit.segments.OutputObjectRegistry;
|
||||
import com.intellij.rt.execution.junit.segments.Packet;
|
||||
import com.intellij.rt.execution.junit.segments.PacketProcessor;
|
||||
import com.intellij.rt.execution.junit.states.PoolOfTestStates;
|
||||
import junit.framework.AssertionFailedError;
|
||||
import junit.framework.ComparisonFailure;
|
||||
@@ -27,13 +26,11 @@ import junit.framework.TestListener;
|
||||
|
||||
public class TestResultsSender implements TestListener {
|
||||
private final OutputObjectRegistry myRegistry;
|
||||
private final PacketProcessor myErr;
|
||||
private TestMeter myCurrentTestMeter;
|
||||
private Test myCurrentTest;
|
||||
|
||||
public TestResultsSender(OutputObjectRegistry packetFactory, PacketProcessor segmentedErr) {
|
||||
public TestResultsSender(OutputObjectRegistry packetFactory) {
|
||||
myRegistry = packetFactory;
|
||||
myErr = segmentedErr;
|
||||
}
|
||||
|
||||
public synchronized void addError(Test test, Throwable throwable) {
|
||||
@@ -93,7 +90,6 @@ public class TestResultsSender implements TestListener {
|
||||
|
||||
private void switchOutput(Packet switchPacket) {
|
||||
switchPacket.send();
|
||||
switchPacket.sendThrough(myErr);
|
||||
}
|
||||
|
||||
public synchronized void startTest(Test test) {
|
||||
|
||||
@@ -21,16 +21,15 @@ import com.intellij.rt.execution.junit.segments.Packet;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
|
||||
public class TreeSender {
|
||||
private static void sendNode(Test test, Packet packet) {
|
||||
private static void sendNode(Test test, Packet packet, Collection objects) {
|
||||
Vector testCases = getTestCasesOf(test);
|
||||
packet.addObject(test).addLong(testCases.size());
|
||||
packet.addObject(test, objects).addLong(testCases.size());
|
||||
for (int i = 0; i < testCases.size(); i++) {
|
||||
Test nextTest = (Test)testCases.get(i);
|
||||
sendNode(nextTest, packet);
|
||||
sendNode(nextTest, packet, objects);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +53,11 @@ public class TreeSender {
|
||||
public static void sendSuite(OutputObjectRegistry registry, Test suite) {
|
||||
Packet packet = registry.createPacket();
|
||||
packet.addString(PoolOfDelimiters.TREE_PREFIX);
|
||||
sendNode(suite, packet);
|
||||
Collection objects = new ArrayList();
|
||||
sendNode(suite, packet, objects);
|
||||
for (Iterator iterator = objects.iterator(); iterator.hasNext();) {
|
||||
((Packet)iterator.next()).send();
|
||||
}
|
||||
packet.addString("\n");
|
||||
packet.send();
|
||||
}
|
||||
|
||||
@@ -30,26 +30,29 @@ import org.junit.runner.manipulation.Filter;
|
||||
import org.junit.runner.notification.RunListener;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.*;
|
||||
|
||||
/** @noinspection UnusedDeclaration*/
|
||||
public class JUnit4IdeaTestRunner implements IdeaTestRunner {
|
||||
private RunListener myTestsListener;
|
||||
private OutputObjectRegistry myRegistry;
|
||||
|
||||
private static void sendNode(Description test, Packet packet) {
|
||||
private static void sendNode(Description test, Packet packet, Collection objectPackets) {
|
||||
final ArrayList children = test.getChildren();
|
||||
packet.addObject(test).addLong(children.size());
|
||||
packet.addObject(test, objectPackets).addLong(children.size());
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
sendNode((Description)children.get(i), packet);
|
||||
sendNode((Description)children.get(i), packet, objectPackets);
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendTree(OutputObjectRegistry registry, Description suite) {
|
||||
public void sendTree(OutputObjectRegistry registry, Description suite) {
|
||||
Packet packet = registry.createPacket();
|
||||
packet.addString(PoolOfDelimiters.TREE_PREFIX);
|
||||
sendNode(suite, packet);
|
||||
Set objects = new HashSet();
|
||||
sendNode(suite, packet, objects);
|
||||
for (Iterator iterator = objects.iterator(); iterator.hasNext();) {
|
||||
((Packet)iterator.next()).send();
|
||||
}
|
||||
packet.addString("\n");
|
||||
packet.send();
|
||||
}
|
||||
@@ -150,8 +153,8 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner {
|
||||
|
||||
|
||||
public void setStreams(SegmentedOutputStream segmentedOut, SegmentedOutputStream segmentedErr) {
|
||||
myRegistry = new JUnit4OutputObjectRegistry(segmentedOut, segmentedErr);
|
||||
myTestsListener = new JUnit4TestResultsSender(myRegistry, segmentedErr);
|
||||
myRegistry = new JUnit4OutputObjectRegistry(segmentedOut);
|
||||
myTestsListener = new JUnit4TestResultsSender(myRegistry);
|
||||
}
|
||||
|
||||
private class TimeSender extends ResultPrinter {
|
||||
|
||||
@@ -27,8 +27,8 @@ import org.junit.runner.Description;
|
||||
|
||||
|
||||
public class JUnit4OutputObjectRegistry extends OutputObjectRegistry {
|
||||
public JUnit4OutputObjectRegistry(PacketProcessor mainTransport, PacketProcessor auxilaryTransport) {
|
||||
super(mainTransport, auxilaryTransport);
|
||||
public JUnit4OutputObjectRegistry(PacketProcessor mainTransport) {
|
||||
super(mainTransport);
|
||||
}
|
||||
|
||||
protected int getTestCont(Object test) {
|
||||
|
||||
@@ -35,13 +35,11 @@ import java.util.regex.Pattern;
|
||||
|
||||
public class JUnit4TestResultsSender extends RunListener {
|
||||
private final OutputObjectRegistry myRegistry;
|
||||
private final PacketProcessor myErr;
|
||||
private Map myCurrentTestMeters = new HashMap();
|
||||
private Set myCurrentTests = new HashSet();
|
||||
|
||||
public JUnit4TestResultsSender(OutputObjectRegistry packetFactory, PacketProcessor segmentedErr) {
|
||||
public JUnit4TestResultsSender(OutputObjectRegistry packetFactory) {
|
||||
myRegistry = packetFactory;
|
||||
myErr = segmentedErr;
|
||||
}
|
||||
|
||||
public synchronized void testFailure(Failure failure) throws Exception {
|
||||
@@ -139,7 +137,6 @@ public class JUnit4TestResultsSender extends RunListener {
|
||||
|
||||
private void switchOutput(Packet switchPacket) {
|
||||
switchPacket.send();
|
||||
switchPacket.sendThrough(myErr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user