Merge remote-tracking branch 'origin/master'

This commit is contained in:
Andrey Vlasovskikh
2014-11-12 21:18:35 +03:00
63 changed files with 796 additions and 428 deletions
@@ -671,14 +671,15 @@ public class DebuggerSession implements AbstractDebuggerSession {
@Override
public void evaluationFinished(final SuspendContextImpl context) {
myIsEvaluating = false;
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
@Override
public void run() {
if (context != getSuspendContext()) {
getContextManager().setState(DebuggerContextUtil.createDebuggerContext(DebuggerSession.this, context), STATE_PAUSED, EVENT_REFRESH, null);
}
}
});
// seems to be not required after move to xdebugger
//DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
// @Override
// public void run() {
// if (context != getSuspendContext()) {
// getContextManager().setState(DebuggerContextUtil.createDebuggerContext(DebuggerSession.this, context), STATE_PAUSED, EVENT_REFRESH, null);
// }
// }
//});
}
}
@@ -180,7 +180,9 @@ public class JavaQualifiedNameProvider implements QualifiedNameProvider {
toInsert = targetElement.getName();
if (targetElement instanceof PsiMethod) {
suffix = "()";
if (!fqn.contains("(")) {
suffix = "()";
}
if (((PsiMethod)targetElement).isConstructor()) {
targetElement = targetElement.getContainingClass();
}
@@ -30,6 +30,7 @@ import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchScopeUtil;
import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
@@ -89,19 +90,24 @@ public class DefaultSymbolNavigationContributor implements ChooseByNameContribut
return member.getContainingFile().getVirtualFile() != null;
}
private static boolean hasSuperMethod(PsiMethod method, GlobalSearchScope scope, Condition<PsiMember> qualifiedMatcher) {
PsiClass containingClass = method.getContainingClass();
private static boolean hasSuperMethod(final PsiMethod method, final GlobalSearchScope scope, final Condition<PsiMember> qualifiedMatcher) {
final PsiClass containingClass = method.getContainingClass();
if (containingClass == null) return false;
for (PsiMethod candidate : containingClass.findMethodsByName(method.getName(), true)) {
if (candidate.getContainingClass() != containingClass &&
PsiSearchScopeUtil.isInScope(scope, candidate) &&
qualifiedMatcher.value(candidate) &&
PsiSuperMethodImplUtil.isSuperMethodSmart(method, candidate)) {
// avoid using hierarchical findMethodsByName because we only want to check the given method hierarchy, without its siblings
return !InheritanceUtil.processSupers(containingClass, false, new Processor<PsiClass>() {
@Override
public boolean process(PsiClass superClass) {
if (PsiSearchScopeUtil.isInScope(scope, superClass)) {
for (PsiMethod candidate : superClass.findMethodsByName(method.getName(), false)) {
if (qualifiedMatcher.value(candidate) && PsiSuperMethodImplUtil.isSuperMethodSmart(method, candidate)) {
return false;
}
}
}
return true;
}
}
return false;
});
}
public void processNames(@NotNull Processor<String> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) {
@@ -74,6 +74,24 @@ class Foo {
performPaste()
myFixture.checkResult "/** Foo#foo(java.util.List)<caret> */"
}
public void "test paste overloaded signature to a comment"() {
myFixture.configureByText "a.java", """
class Foo {
void foo<caret>(int a) {} //
void foo(int a, int b) {}
}
"""
performCopy()
myFixture.editor.caretModel.moveToOffset(myFixture.editor.document.text.indexOf('//') + 2)
performPaste()
myFixture.checkResult """
class Foo {
void foo(int a) {} //Foo.foo(int)<caret>
void foo(int a, int b) {}
}
"""
}
public void testFqnInImport() {
myFixture.addClass("package foo; public class Foo {}")
@@ -23,6 +23,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
@@ -179,7 +180,16 @@ public class StubBasedPsiElementBase<T extends StubElement> extends ASTDelegateP
ApplicationManager.getApplication().assertReadAccessAllowed();
synchronized (PsiLock.LOCK) {
if (myStub != null) {
throw new PsiInvalidElementAccessException(this, "no psi for file stub " + stub + ", invalidation reason=" + ((PsiFileStubImpl<?>) stub).getInvalidationReason(), null);
String reason = ((PsiFileStubImpl<?>)stub).getInvalidationReason();
PsiInvalidElementAccessException exception =
new PsiInvalidElementAccessException(this, "no psi for file stub " + stub + ", invalidation reason=" + reason, null);
if (PsiFileImpl.STUB_PSI_MISMATCH.equals(reason)) {
// we're between finding stub-psi mismatch and the next EDT spot where the file is reparsed and stub rebuilt
// see com.intellij.psi.impl.source.PsiFileImpl.rebuildStub()
// most likely it's just another highlighting thread accessing the same PSI concurrently and not yet canceled, so cancel it
throw new ProcessCanceledException(exception);
}
throw exception;
}
}
}
@@ -23,7 +23,10 @@ import com.intellij.openapi.util.Ref;
import com.intellij.util.ExceptionUtil;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class ApplicationUtil {
// throws exception if can't grab read action right now
@@ -63,7 +66,7 @@ public class ApplicationUtil {
error.set(t);
return null;
}
};
}
});
while (true) {
@@ -43,6 +43,7 @@ import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
@@ -376,7 +377,7 @@ public final class LoadTextUtil {
CharSequence text;
Application app = ApplicationManager.getApplication();
if (app != null && app.isDispatchThread() && !app.isWriteAccessAllowed()) {
if (app != null && app.isDispatchThread() && !app.isWriteAccessAllowed() && !GraphicsEnvironment.isHeadless()) {
final Ref<CharSequence> result = Ref.create(ArrayUtil.EMPTY_CHAR_SEQUENCE);
final Ref<Throwable> error = Ref.create();
ProgressManager.getInstance().run(new Task.Modal(null, "Decompiling " + file.getName(), true) {
@@ -53,6 +53,7 @@ import com.intellij.psi.tree.ILazyParseableElementType;
import com.intellij.psi.tree.IStubFileElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.reference.SoftReference;
import com.intellij.util.FileContentUtilCore;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PatchedWeakReference;
import com.intellij.util.containers.ContainerUtil;
@@ -67,6 +68,7 @@ import java.util.*;
public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiFileWithStubSupport, Queryable {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiFileImpl");
public static final String STUB_PSI_MISMATCH = "stub-psi mismatch";
private IElementType myElementType;
protected IElementType myContentElementType;
@@ -299,7 +301,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
protected void reportStubAstMismatch(String message, StubTree stubTree, Document cachedDocument) {
rebuildStub();
clearStub("stub-psi mismatch");
clearStub(STUB_PSI_MISMATCH);
scheduleDropCachesWithInvalidStubPsi();
String msg = message;
@@ -1007,21 +1009,23 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
}
private void rebuildStub() {
final VirtualFile vFile = getVirtualFile();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myManager.dropResolveCaches();
if (vFile != null && vFile.isValid()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
final VirtualFile vFile = getVirtualFile();
if (vFile != null && vFile.isValid()) {
final Document doc = FileDocumentManager.getInstance().getCachedDocument(vFile);
if (doc != null) {
FileDocumentManager.getInstance().saveDocument(doc);
}
}
}, ModalityState.NON_MODAL);
StubTreeLoader.getInstance().rebuildStubTree(vFile);
}
FileContentUtilCore.reparseFiles(vFile);
StubTreeLoader.getInstance().rebuildStubTree(vFile);
}
}
}, ModalityState.NON_MODAL);
}
@Override
@@ -18,6 +18,7 @@ package com.intellij.refactoring.classMembers;
import com.intellij.psi.PsiElement;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.util.PsiUtilCore;
/**
* @author Dennis.Ushakov
@@ -66,7 +67,7 @@ public abstract class MemberInfoBase<T extends PsiElement> {
}
public T getMember() {
LOG.assertTrue(myMember.isValid(), myMember.getText() + " is invalid");
PsiUtilCore.ensureValid(myMember);
return myMember;
}
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
@@ -25,10 +26,13 @@ import com.intellij.util.ui.DialogUtil;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@@ -65,24 +69,32 @@ public class MnemonicHelper extends ComponentTreeWatcher {
abstractButton.addPropertyChangeListener(AbstractButton.TEXT_CHANGED_PROPERTY, TEXT_LISTENER);
DialogUtil.registerMnemonic(abstractButton);
checkForDuplicateMnemonics(abstractButton);
fixMacMnemonicKeyStroke(abstractButton, null);
} else if (parentComponent instanceof JTextComponent) {
if (SystemInfo.isMac) {
parentComponent.enableInputMethods(UISettings.getShadowInstance().DISABLE_MNEMONICS_IN_CONTROLS);
}
} else if (parentComponent instanceof JLabel) {
final JLabel jLabel = ((JLabel)parentComponent);
jLabel.addPropertyChangeListener(TEXT_CHANGED_PROPERTY, TEXT_LISTENER);
DialogUtil.registerMnemonic(jLabel, null);
checkForDuplicateMnemonics(jLabel);
if (SystemInfo.isMac) {
// hack to make Labels mnemonic work for ALT+KEY_CODE on Macs.
// Default implementation uses ALT+CTRL+KEY_CODE (see BasicLabelUI).
final InputMap inputMap = jLabel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
if (inputMap != null) {
final KeyStroke[] strokes = inputMap.allKeys();
if (strokes != null) {
for (KeyStroke stroke : strokes) {
final int m = stroke.getModifiers();
// to be sure if default mnemonic exist
if (((m & KeyEvent.ALT_MASK) == KeyEvent.ALT_MASK) && ((m & KeyEvent.CTRL_MASK) == KeyEvent.CTRL_MASK)) {
inputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(), KeyEvent.ALT_MASK), "release"); // "release" only is OK
}
fixMacMnemonicKeyStroke(jLabel, "release"); // "release" only is OK for labels
}
}
private static void fixMacMnemonicKeyStroke(JComponent component, String type) {
if (SystemInfo.isMac) {
// hack to make component's mnemonic work for ALT+KEY_CODE on Macs.
// Default implementation uses ALT+CTRL+KEY_CODE (see BasicLabelUI).
InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
if (inputMap != null) {
KeyStroke[] strokes = inputMap.allKeys();
if (strokes != null) {
int mask = KeyEvent.ALT_MASK | KeyEvent.CTRL_MASK;
for (KeyStroke stroke : strokes) {
if (mask == (mask & stroke.getModifiers())) {
inputMap.put(getKeyStrokeWithoutCtrlModifier(stroke), type != null ? type : inputMap.get(stroke));
}
}
}
@@ -90,6 +102,18 @@ public class MnemonicHelper extends ComponentTreeWatcher {
}
}
private static KeyStroke getKeyStrokeWithoutCtrlModifier(KeyStroke stroke) {
try {
Method method = AWTKeyStroke.class.getDeclaredMethod("getCachedStroke", char.class, int.class, int.class, boolean.class);
method.setAccessible(true);
int modifiers = stroke.getModifiers() & ~InputEvent.CTRL_MASK & ~InputEvent.CTRL_DOWN_MASK;
return (KeyStroke)method.invoke(null, stroke.getKeyChar(), stroke.getKeyCode(), modifiers, stroke.isOnKeyRelease());
}
catch (Exception exception) {
throw new IllegalStateException(exception);
}
}
protected void unprocessComponent(Component component) {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.net;
import com.intellij.Patches;
@@ -193,15 +192,17 @@ public class NetUtils {
* @throws com.intellij.openapi.progress.ProcessCanceledException if process was canceled.
*/
public static int copyStreamContent(@Nullable ProgressIndicator indicator,
InputStream inputStream,
OutputStream outputStream,
@NotNull InputStream inputStream,
@NotNull OutputStream outputStream,
int expectedContentSize) throws IOException, ProcessCanceledException {
if (indicator != null) {
indicator.checkCanceled();
if (expectedContentSize < 0) indicator.setIndeterminate(true);
if (expectedContentSize < 0) {
indicator.setIndeterminate(true);
}
}
final byte[] buffer = new byte[4 * 1024];
final byte[] buffer = new byte[8 * 1024];
int count;
int total = 0;
while ((count = inputStream.read(buffer)) > 0) {
@@ -46,7 +46,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardStep {
private static final int COLS = 3;
private static ScheduledExecutorService ourService = new ScheduledThreadPoolExecutor(4, ConcurrencyUtil.newNamedThreadFactory(
private static final ScheduledExecutorService ourService = new ScheduledThreadPoolExecutor(4, ConcurrencyUtil.newNamedThreadFactory(
"FeaturedPlugins", true, Thread.NORM_PRIORITY));
public final AtomicBoolean myCanceled = new AtomicBoolean(false);
@@ -119,7 +119,6 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
wrapperLayout.show(buttonWrapper, "button");
final ProgressIndicatorEx indicator = new AbstractProgressIndicatorExBase(true) {
@Override
public void start() {
myCanceled.set(false);
@@ -264,5 +263,5 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
+ " | " + "Plugins";
}
public static class OfflineException extends Exception {};
public static class OfflineException extends Exception {}
}
@@ -34,6 +34,7 @@ import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.util.ui.ColumnInfo;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -145,30 +146,29 @@ public class InstalledPluginsTableModel extends PluginTableModel {
updatePluginDependencies();
final Runnable runnable = new Runnable() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (!ApplicationManager.getApplication().isDisposed()) {
ProgressManager.getInstance().run(new Task.Backgroundable(null, "Load custom plugin repositories data...") {
@Override
public void run(@NotNull ProgressIndicator indicator) {
updateRepositoryPlugins();
updateRepositoryPlugins(indicator);
}
});
}
}
};
SwingUtilities.invokeLater(runnable);
});
}
public void updateRepositoryPlugins() {
private void updateRepositoryPlugins(@NotNull ProgressIndicator indicator) {
myPlugin2host.clear();
final List<String> pluginHosts = UpdateSettings.getInstance().getPluginHosts();
List<String> pluginHosts = UpdateSettings.getInstance().getPluginHosts();
ContainerUtil.addIfNotNull(ApplicationInfoEx.getInstanceEx().getBuiltinPluginsUrl(), pluginHosts);
for (String host : pluginHosts) {
try {
final Map<PluginId, PluginDownloader> downloaded = new HashMap<PluginId, PluginDownloader>();
UpdateChecker.checkPluginsHost(host, downloaded, false, null);
Map<PluginId, PluginDownloader> downloaded = new THashMap<PluginId, PluginDownloader>();
UpdateChecker.checkPluginsHost(host, downloaded, false, indicator);
for (PluginId pluginId : downloaded.keySet()) {
myPlugin2host.put(pluginId.getIdString(), host);
}
@@ -19,7 +19,9 @@ import com.intellij.ide.IdeBundle;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.options.BaseConfigurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.ui.InputValidator;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.NonEmptyInputValidator;
@@ -35,33 +37,37 @@ import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBList;
import com.intellij.util.ArrayUtil;
import com.intellij.util.io.URLUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
public class PluginHostsConfigurable extends BaseConfigurable {
private CustomPluginRepositoriesPanel myUpdatesSettingsPanel;
@Override
public JComponent createComponent() {
myUpdatesSettingsPanel = new CustomPluginRepositoriesPanel();
return myUpdatesSettingsPanel.myPanel;
}
@Override
public String getDisplayName() {
return "Custom Plugin Repositories";
}
@Override
public String getHelpTopic() {
return null;
}
@Override
public void apply() throws ConfigurationException {
UpdateSettings settings = UpdateSettings.getInstance();
@@ -69,27 +75,28 @@ public class PluginHostsConfigurable extends BaseConfigurable {
settings.myPluginHosts.addAll(myUpdatesSettingsPanel.getPluginsHosts());
}
@Override
public void reset() {
myUpdatesSettingsPanel.setPluginHosts(UpdateSettings.getInstance().myPluginHosts);
}
@Override
public boolean isModified() {
if (myUpdatesSettingsPanel == null) return false;
UpdateSettings settings = UpdateSettings.getInstance();
return !settings.myPluginHosts.equals(myUpdatesSettingsPanel.getPluginsHosts());
if (myUpdatesSettingsPanel == null) {
return false;
}
//noinspection EqualsBetweenInconvertibleTypes
return !UpdateSettings.getInstance().myPluginHosts.equals(myUpdatesSettingsPanel.getPluginsHosts());
}
@Override
public void disposeUIResources() {
myUpdatesSettingsPanel = null;
}
public Collection<? extends String> getPluginsHosts() {
return myUpdatesSettingsPanel.getPluginsHosts();
}
public static class CustomPluginRepositoriesPanel {
private JBList myUrlsList;
private JPanel myPanel;
private final JBList myUrlsList;
private final JPanel myPanel;
public CustomPluginRepositoriesPanel() {
myUrlsList = new JBList(new DefaultListModel());
@@ -109,6 +116,7 @@ public class PluginHostsConfigurable extends BaseConfigurable {
dlg.show();
String input = dlg.getInputString();
if (input != null) {
//noinspection unchecked
((DefaultListModel)myUrlsList.getModel()).addElement(correctRepositoryRule(input));
}
}
@@ -122,10 +130,12 @@ public class PluginHostsConfigurable extends BaseConfigurable {
Messages.getQuestionIcon(),
(String)myUrlsList.getSelectedValue(),
new InputValidator() {
@Override
public boolean checkInput(final String inputString) {
return inputString.length() > 0;
}
@Override
public boolean canClose(final String inputString) {
return checkInput(inputString);
}
@@ -133,6 +143,7 @@ public class PluginHostsConfigurable extends BaseConfigurable {
dlg.show();
final String input = dlg.getInputString();
if (input != null) {
//noinspection unchecked
((DefaultListModel)myUrlsList.getModel()).set(myUrlsList.getSelectedIndex(), input);
}
}
@@ -152,6 +163,7 @@ public class PluginHostsConfigurable extends BaseConfigurable {
final DefaultListModel model = (DefaultListModel)myUrlsList.getModel();
model.clear();
for (String host : pluginHosts) {
//noinspection unchecked
model.addElement(host);
}
}
@@ -177,35 +189,39 @@ public class PluginHostsConfigurable extends BaseConfigurable {
super(parentComponent, message, title, icon, initialValue, validator);
}
@Override
@NotNull
protected Action[] createActions() {
final Action[] actions = super.createActions();
final AbstractAction checkNowAction = new AbstractAction("Check Now") {
public void actionPerformed(final ActionEvent e) {
final boolean[] result = new boolean[1];
final Exception[] ex = new Exception[1];
if (ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void actionPerformed(@Nullable ActionEvent e) {
ProgressManager.getInstance().run(new Task.Modal(null, "Checking plugins repository...", true) {
boolean result;
Exception ex;
@Override
public void run() {
public void run(@NotNull ProgressIndicator indicator) {
try {
result[0] =
UpdateChecker.checkPluginsHost(correctRepositoryRule(getTextField().getText()), new HashMap<PluginId, PluginDownloader>(), true, ProgressManager.getInstance().getProgressIndicator());
result = UpdateChecker.checkPluginsHost(correctRepositoryRule(getTextField().getText()), new THashMap<PluginId, PluginDownloader>(), true, indicator);
}
catch (Exception e1) {
ex[0] = e1;
ex = e1;
}
}
}, "Checking plugins repository...", true, null, getPreferredFocusedComponent())) {
if (ex[0] != null) {
showErrorDialog(myField, "Connection failed: " + ex[0].getMessage());
@Override
public void onSuccess() {
if (ex != null) {
showErrorDialog(myField, "Connection failed: " + ex.getMessage());
}
else if (result) {
showInfoMessage(myField, "Plugins repository was successfully checked", "Check Plugins Repository");
}
else {
showErrorDialog(myField, "Plugin descriptions contain some errors. Please, check idea.log for details.");
}
}
else if (result[0]) {
showInfoMessage(myField, "Plugins repository was successfully checked", "Check Plugins Repository");
}
else {
showErrorDialog(myField, "Plugin descriptions contain some errors. Please, check idea.log for details.");
}
}
});
}
};
myField.getDocument().addDocumentListener(new DocumentAdapter() {
@@ -215,7 +231,7 @@ public class PluginHostsConfigurable extends BaseConfigurable {
}
});
checkNowAction.setEnabled(!StringUtil.isEmptyOrSpaces(myField.getText()));
return ArrayUtil.append(actions, checkNowAction);
return ArrayUtil.append(super.createActions(), checkNowAction);
}
}
}
@@ -54,6 +54,7 @@ import com.intellij.util.concurrency.SwingWorker;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.UiNotifyConnector;
import com.intellij.xml.util.XmlStringUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -213,6 +214,7 @@ public abstract class PluginManagerMain implements Disposable {
protected abstract JScrollPane createTable();
@Override
public void dispose() {
myDisposed = true;
}
@@ -227,6 +229,7 @@ public abstract class PluginManagerMain implements Disposable {
public void reset() {
UiNotifyConnector.doWhenFirstShown(getPluginTable(), new Runnable() {
@Override
public void run() {
requireShutdown = false;
TableUtil.ensureSelectionExists(getPluginTable());
@@ -245,6 +248,7 @@ public abstract class PluginManagerMain implements Disposable {
protected void installTableActions() {
pluginTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
refresh();
}
@@ -306,6 +310,7 @@ public abstract class PluginManagerMain implements Disposable {
List<IdeaPluginDescriptor> list = null;
List<String> errorMessages = new ArrayList<String>();
@Override
public Object construct() {
try {
list = RepositoryHelper.loadPluginsFromRepository(null);
@@ -325,8 +330,10 @@ public abstract class PluginManagerMain implements Disposable {
}
void processPluginHost(@NotNull String host, boolean builtIn) {
if (!acceptHost(host)) return;
final Map<PluginId, PluginDownloader> downloaded = new HashMap<PluginId, PluginDownloader>();
if (!acceptHost(host)) {
return;
}
Map<PluginId, PluginDownloader> downloaded = new THashMap<PluginId, PluginDownloader>();
try {
UpdateChecker.checkPluginsHost(host, downloaded, false, null);
for (PluginDownloader downloader : downloaded.values()) {
@@ -353,8 +360,10 @@ public abstract class PluginManagerMain implements Disposable {
}
}
@Override
public void finished() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
setDownloadStatus(false);
if (list != null) {
@@ -383,7 +392,7 @@ public abstract class PluginManagerMain implements Disposable {
}
protected void loadAvailablePlugins() {
ArrayList<IdeaPluginDescriptor> list;
List<IdeaPluginDescriptor> list;
try {
// If we already have a file with downloaded plugins from the last time,
// then read it, load into the list and start the updating process.
@@ -546,6 +555,7 @@ public abstract class PluginManagerMain implements Disposable {
}
public static class MyHyperlinkListener implements HyperlinkListener {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
JEditorPane pane = (JEditorPane)e.getSource();
@@ -574,18 +584,22 @@ public abstract class PluginManagerMain implements Disposable {
return getComponent().convertRowIndexToModel(viewIndex);
}
@Override
public int getSelectedIndex() {
return myComponent.getSelectedRow();
}
@Override
public Object[] getAllElements() {
return myComponent.getElements();
}
@Override
public String getElementText(Object element) {
return ((IdeaPluginDescriptor)element).getName();
}
@Override
public void selectElement(Object element, String selectedText) {
for (int i = 0; i < myComponent.getRowCount(); i++) {
if (myComponent.getObjectAt(i).getName().equals(((IdeaPluginDescriptor)element).getName())) {
@@ -678,6 +692,7 @@ public abstract class PluginManagerMain implements Disposable {
super("PLUGIN_FILTER", 5);
}
@Override
public void filter() {
getPluginTable().putClientProperty(SpeedSearchSupply.SEARCH_QUERY_KEY, getFilter());
pluginsModel.filter(getFilter().toLowerCase());
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,22 +16,17 @@
package com.intellij.ide.plugins;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.Stack;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: stathik
* Date: Mar 28, 2003
* Time: 12:57:45 AM
* To change this template use Options | File Templates.
*/
class RepositoryContentHandler extends DefaultHandler {
public class RepositoryContentHandler extends DefaultHandler {
@NonNls public static final String CATEGORY = "category";
@NonNls public static final String IDEA_PLUGIN = "idea-plugin";
@NonNls public static final String NAME = "name";
@@ -59,23 +54,25 @@ class RepositoryContentHandler extends DefaultHandler {
private Stack<String> categoriesStack;
@Override
public void startDocument() throws SAXException {
plugins = new ArrayList<IdeaPluginDescriptor>();
categoriesStack = new Stack<String>();
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
@Override
public void startElement(@NotNull String namespaceURI, @NotNull String localName, @NotNull String qName, @NotNull Attributes attributes) throws SAXException {
if (qName.equals(CATEGORY)) {
categoriesStack.push(atts.getValue(NAME));
categoriesStack.push(attributes.getValue(NAME));
}
else if (qName.equals(IDEA_PLUGIN)) {
String categoryName = constructCategoryTree();
currentPlugin = new PluginNode();
currentPlugin.setCategory(categoryName);
currentPlugin.setDownloads(atts.getValue(DOWNLOADS));
currentPlugin.setSize(atts.getValue(SIZE));
currentPlugin.setUrl(atts.getValue(URL));
final String dateString = atts.getValue(DATE);
currentPlugin.setDownloads(attributes.getValue(DOWNLOADS));
currentPlugin.setSize(attributes.getValue(SIZE));
currentPlugin.setUrl(attributes.getValue(URL));
final String dateString = attributes.getValue(DATE);
if (dateString != null) {
currentPlugin.setDate(dateString);
}
@@ -83,17 +80,18 @@ class RepositoryContentHandler extends DefaultHandler {
plugins.add(currentPlugin);
}
else if (qName.equals(IDEA_VERSION)) {
currentPlugin.setSinceBuild(atts.getValue(SINCE_BUILD));
currentPlugin.setUntilBuild(atts.getValue(UNTIL_BUILD));
currentPlugin.setSinceBuild(attributes.getValue(SINCE_BUILD));
currentPlugin.setUntilBuild(attributes.getValue(UNTIL_BUILD));
}
else if (qName.equals(VENDOR)) {
currentPlugin.setVendorEmail(atts.getValue(EMAIL));
currentPlugin.setVendorUrl(atts.getValue(URL));
currentPlugin.setVendorEmail(attributes.getValue(EMAIL));
currentPlugin.setVendorUrl(attributes.getValue(URL));
}
currentValue.setLength(0);
}
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
@Override
public void endElement(String namespaceURI, @NotNull String localName, @NotNull String qName) throws SAXException {
String currentValueString = currentValue.toString();
currentValue.setLength(0);
@@ -129,11 +127,12 @@ class RepositoryContentHandler extends DefaultHandler {
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
currentValue.append(ch, start, length);
}
public ArrayList<IdeaPluginDescriptor> getPluginsList() {
public List<IdeaPluginDescriptor> getPluginsList() {
return plugins;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,6 @@ import java.io.*;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.util.List;
import java.util.zip.GZIPInputStream;
/**
* @author stathik
@@ -52,24 +51,6 @@ public class RepositoryHelper {
return loadPluginsFromRepository(indicator, null);
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
@NotNull
public static InputStream getConnectionInputStream(@NotNull URLConnection connection) throws IOException {
InputStream inputStream = connection.getInputStream();
if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) {
try {
return new GZIPInputStream(inputStream);
}
catch (IOException e) {
inputStream.close();
throw e;
}
}
else {
return inputStream;
}
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
public static List<IdeaPluginDescriptor> loadPluginsFromRepository(@Nullable final ProgressIndicator indicator, @Nullable BuildNumber buildnumber) throws Exception {
final ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance();
@@ -83,6 +64,7 @@ public class RepositoryHelper {
final File pluginListFile = new File(PathManager.getPluginsPath(), PLUGIN_LIST_FILE);
if (pluginListFile.length() > 0) {
try {
//noinspection SpellCheckingInspection
url = url + "&crc32=" + Files.hash(pluginListFile, Hashing.crc32()).toString();
}
catch (NoSuchMethodError e) {
@@ -91,15 +73,12 @@ public class RepositoryHelper {
}
}
return HttpRequests.request(url).supportGzip(true).get(new ThrowableConvertor<URLConnection, List<IdeaPluginDescriptor>, Exception>() {
return HttpRequests.request(url).get(new ThrowableConvertor<URLConnection, List<IdeaPluginDescriptor>, Exception>() {
@Override
public List<IdeaPluginDescriptor> convert(URLConnection connection) throws Exception {
if (indicator != null) {
indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl()));
}
connection.connect();
if (indicator != null) {
indicator.checkCanceled();
indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl()));
}
if (connection instanceof HttpURLConnection && ((HttpURLConnection)connection).getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
@@ -107,6 +86,7 @@ public class RepositoryHelper {
}
if (indicator != null) {
indicator.checkCanceled();
indicator.setText2(IdeBundle.message("progress.downloading.list.of.plugins"));
}
return readPluginsStream(connection, indicator, PLUGIN_LIST_FILE);
@@ -114,11 +94,11 @@ public class RepositoryHelper {
});
}
private synchronized static List<IdeaPluginDescriptor> readPluginsStream(@NotNull URLConnection connection,
@Nullable ProgressIndicator indicator,
@NotNull String file) throws Exception {
public synchronized static List<IdeaPluginDescriptor> readPluginsStream(@NotNull URLConnection connection,
@Nullable ProgressIndicator indicator,
@NotNull String file) throws Exception {
File localFile;
InputStream input = getConnectionInputStream(connection);
InputStream input = HttpRequests.getInputStream(connection);
try {
localFile = createLocalPluginsDescriptions(file);
OutputStream output = new FileOutputStream(localFile);
@@ -159,10 +139,6 @@ public class RepositoryHelper {
return temp;
}
public static List<IdeaPluginDescriptor> loadPluginsFromDescription(@NotNull URLConnection connection, @Nullable ProgressIndicator indicator) throws Exception {
return readPluginsStream(connection, indicator, "host.xml");
}
public static String getDownloadUrl() {
return ApplicationInfoImpl.getShadowInstance().getPluginsDownloadUrl() + "?action=download&id=";
}
@@ -1,31 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ide.reporter;
public class ConnectionException extends Exception {
public ConnectionException(String message) {
super(message);
}
public ConnectionException(Throwable cause) {
super(cause);
}
public ConnectionException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -23,18 +23,17 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.util.Consumer;
import com.intellij.util.HttpRequests;
import com.intellij.util.PathUtil;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.ThrowableConvertor;
import com.intellij.util.io.ZipUtil;
import com.intellij.util.net.NetUtils;
import org.jetbrains.annotations.NonNls;
@@ -42,7 +41,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URLConnection;
import java.util.List;
@@ -89,17 +87,11 @@ public class PluginDownloader {
myBuildNumber = buildNumber;
}
@SuppressWarnings("UnusedDeclaration")
@Deprecated
public boolean prepareToInstall() throws IOException {
return prepareToInstall(new ProgressIndicatorBase());
public boolean prepareToInstall(@NotNull ProgressIndicator progressIndicator) throws IOException {
return prepareToInstall(progressIndicator, myBuildNumber);
}
public boolean prepareToInstall(ProgressIndicator pi) throws IOException {
return prepareToInstall(pi, myBuildNumber);
}
public boolean prepareToInstall(@Nullable ProgressIndicator progressIndicator, @Nullable BuildNumber forBuildNumber) throws IOException {
public boolean prepareToInstall(@NotNull ProgressIndicator progressIndicator, @Nullable BuildNumber forBuildNumber) throws IOException {
if (myFile != null) {
return true;
}
@@ -176,11 +168,7 @@ public class PluginDownloader {
if (file.getName().endsWith(".zip")) {
final File outputDir = FileUtil.createTempDirectory("plugin", "");
try {
ZipUtil.extract(file, outputDir, new FilenameFilter() {
public boolean accept(final File dir, final String name) {
return true;
}
});
ZipUtil.extract(file, outputDir, null);
final File[] files = outputDir.listFiles();
if (files != null && files.length == 1) {
descriptor = PluginManagerCore.loadDescriptor(files[0], PluginManagerCore.PLUGIN_XML);
@@ -237,69 +225,54 @@ public class PluginDownloader {
}
}
private File downloadPlugin(@Nullable final ProgressIndicator progressIndicator) throws IOException {
final File pluginsTemp = new File(PathManager.getPluginTempPath());
@NotNull
private File downloadPlugin(@NotNull final ProgressIndicator progressIndicator) throws IOException {
File pluginsTemp = new File(PathManager.getPluginTempPath());
if (!pluginsTemp.exists() && !pluginsTemp.mkdirs()) {
throw new IOException(IdeBundle.message("error.cannot.create.temp.dir", pluginsTemp));
}
final File file = FileUtil.createTempFile(pluginsTemp, "plugin_", "_download", true, false);
if (progressIndicator != null) {
progressIndicator.setText(IdeBundle.message("progress.connecting"));
}
progressIndicator.checkCanceled();
progressIndicator.setText(IdeBundle.message("progress.downloading.plugin", getPluginName()));
URLConnection connection = null;
try {
connection = openConnection(myPluginUrl);
final InputStream is = (ApplicationManager.getApplication() != null)
? UrlConnectionUtil.getConnectionInputStream(connection, progressIndicator)
: connection.getInputStream();
if (is == null) {
throw new IOException("Failed to open connection");
return HttpRequests.request(myPluginUrl).supportGzip(false).effectiveUrlConsumer(new Consumer<String>() {
@Override
public void consume(String url) {
myPluginUrl = url;
}
}).get(new ThrowableConvertor<URLConnection, File, IOException>() {
@Override
public File convert(URLConnection connection) throws IOException {
progressIndicator.checkCanceled();
if (progressIndicator != null && ApplicationManager.getApplication() != null) {
progressIndicator.setText(IdeBundle.message("progress.downloading.plugin", getPluginName()));
}
try {
final OutputStream fos = new BufferedOutputStream(new FileOutputStream(file, false));
InputStream input = HttpRequests.getInputStream(connection);
try {
NetUtils.copyStreamContent(progressIndicator, is, fos, connection.getContentLength());
OutputStream fileOut = new FileOutputStream(file);
try {
NetUtils.copyStreamContent(progressIndicator, input, fileOut, connection.getContentLength());
}
finally {
fileOut.close();
}
}
finally {
fos.close();
input.close();
}
}
finally {
is.close();
}
if (myFileName == null) {
myFileName = guessFileName(connection, file);
}
if (myFileName == null) {
myFileName = guessFileName(connection, file);
}
final File newFile = new File(file.getParentFile(), myFileName);
FileUtil.rename(file, newFile);
return newFile;
}
finally {
if (connection instanceof HttpURLConnection) {
((HttpURLConnection)connection).disconnect();
File newFile = new File(file.getParentFile(), myFileName);
FileUtil.rename(file, newFile);
return newFile;
}
}
}
private URLConnection openConnection(@NotNull String url) throws IOException {
Pair<URLConnection, String> result = HttpRequests.openConnection(url, false);
if (result.second != null) {
myPluginUrl = result.second;
}
return result.first;
});
}
@NotNull
private String guessFileName(final URLConnection connection, final File file) throws IOException {
private String guessFileName(@NotNull URLConnection connection, @NotNull File file) throws IOException {
String fileName = null;
final String contentDisposition = connection.getHeaderField("Content-Disposition");
@@ -22,6 +22,7 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.util.Ref;
import com.intellij.ui.TableUtil;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -67,21 +68,28 @@ class PluginUpdateInfoDialog extends AbstractUpdateDialog {
protected void doOKAction() {
super.doOKAction();
final Ref<Boolean> result = new Ref<Boolean>();
final Runnable runnable = new Runnable() {
public void run() {
final Consumer<ProgressIndicator> runnable = new Consumer<ProgressIndicator>() {
@Override
public void consume(@NotNull ProgressIndicator indicator) {
UpdateChecker.saveDisabledToUpdatePlugins();
result.set(UpdateChecker.install(myUploadedPlugins));
result.set(UpdateChecker.install(myUploadedPlugins, indicator));
}
};
final String progressTitle = "Download plugins...";
if (downloadModal()) {
ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, progressTitle, true, null);
} else {
ProgressManager.getInstance().run(new Task.Modal(null, progressTitle, true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
runnable.consume(indicator);
}
});
}
else {
ProgressManager.getInstance().run(new Task.Backgroundable(null, progressTitle, true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
runnable.run();
runnable.consume(indicator);
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package com.intellij.openapi.updateSettings.impl;
import com.intellij.diagnostic.IdeErrorsDialog;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.*;
import com.intellij.ide.reporter.ConnectionException;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.notification.*;
import com.intellij.openapi.application.ApplicationInfo;
@@ -30,13 +29,11 @@ import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.StandardFileSystems;
@@ -45,6 +42,7 @@ import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.net.NetUtils;
import com.intellij.util.ui.UIUtil;
import org.jdom.Document;
import org.jdom.Element;
@@ -55,15 +53,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* See XML file by {@link com.intellij.openapi.application.ex.ApplicationInfoEx#getUpdateUrls()} for reference.
@@ -130,7 +127,6 @@ public final class UpdateChecker {
ProgressManager.getInstance().run(new Task.Backgroundable(project, IdeBundle.message("updates.checking.progress"), true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
indicator.setIndeterminate(true);
doUpdateAndShowResult(project, !fromSettings, true, settings, indicator, null);
}
@@ -160,7 +156,9 @@ public final class UpdateChecker {
settings.setKnownChannelIds(result.getAllChannelsIds());
}
else if (result.getState() == UpdateStrategy.State.CONNECTION_ERROR) {
showErrorMessage(manualCheck, IdeBundle.message("updates.error.connection.failed"));
//noinspection ThrowableResultOfMethodCallIgnored
showErrorMessage(manualCheck,
result.getError() instanceof InterruptedIOException ? IdeBundle.message("updates.timeout.error") : IdeBundle.message("updates.error.connection.failed"));
return;
}
@@ -284,7 +282,7 @@ public final class UpdateChecker {
if (isReadyToUpdate(pluginId, pluginVersion)) {
descriptor = downloader.getDescriptor();
if (descriptor == null) {
if (downloader.prepareToInstall(indicator, buildNumber)) {
if (downloader.prepareToInstall(indicator == null ? new EmptyProgressIndicator() : indicator, buildNumber)) {
descriptor = downloader.getDescriptor();
}
ourUpdatedPlugins.put(pluginId, downloader);
@@ -341,52 +339,81 @@ public final class UpdateChecker {
}
}
public static boolean checkPluginsHost(final String host,
final Map<PluginId, PluginDownloader> downloaded,
final boolean collectToUpdate,
public static boolean checkPluginsHost(String host,
Map<PluginId, PluginDownloader> downloaded,
boolean collectToUpdate,
@Nullable ProgressIndicator indicator) throws Exception {
return checkPluginsHost(host, downloaded, null, collectToUpdate, indicator, null);
}
private static boolean checkPluginsHost(final String host,
private static boolean checkPluginsHost(@NotNull String host,
final Map<PluginId, PluginDownloader> downloaded,
final @Nullable Collection<IdeaPluginDescriptor> incompatiblePlugins,
final boolean collectToUpdate,
final @Nullable ProgressIndicator indicator,
boolean collectToUpdate,
@Nullable final ProgressIndicator indicator,
final BuildNumber buildNumber) throws Exception {
String url;
if (StandardFileSystems.FILE_PROTOCOL.equals(new URL(host).getProtocol())) {
url = host;
}
else {
url = host + (host.contains("?") ? '&' : '?') + "build=" + ApplicationInfo.getInstance().getBuild().asString();
}
BufferExposingByteArrayOutputStream bytes = HttpRequests.request(url)
.get(new ThrowableConvertor<URLConnection, BufferExposingByteArrayOutputStream, Exception>() {
@Override
public BufferExposingByteArrayOutputStream convert(URLConnection connection) throws Exception {
InputStream input = HttpRequests.getInputStream(connection);
try {
BufferExposingByteArrayOutputStream output = new BufferExposingByteArrayOutputStream();
try {
NetUtils.copyStreamContent(indicator, input, output, connection.getContentLength());
}
finally {
output.close();
}
return output;
}
finally {
input.close();
}
}
});
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes.getInternalBuffer(), 0, bytes.size());
final Document document;
try {
document = JDOMUtil.loadDocument(RepositoryHelper.getConnectionInputStream(loadVersionInfo(host)));
document = JDOMUtil.loadDocument(inputStream);
}
catch (JDOMException e) {
return false;
}
finally {
inputStream.reset();
}
final List<IdeaPluginDescriptor> descriptors = RepositoryHelper.loadPluginsFromDescription(loadVersionInfo(host), indicator);
for (IdeaPluginDescriptor descriptor : descriptors) {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
RepositoryContentHandler handler = new RepositoryContentHandler();
parser.parse(inputStream, handler);
for (IdeaPluginDescriptor descriptor : handler.getPluginsList()) {
((PluginNode)descriptor).setRepositoryName(host);
prepareToInstall(PluginDownloader.createDownloader(descriptor, buildNumber), buildNumber, downloaded, incompatiblePlugins, collectToUpdate,
indicator);
}
boolean success = true;
for (Object plugin : document.getRootElement().getChildren("plugin")) {
final Element pluginElement = (Element)plugin;
for (Element pluginElement : document.getRootElement().getChildren("plugin")) {
final String pluginId = pluginElement.getAttributeValue("id");
final String pluginUrl = pluginElement.getAttributeValue("url");
String pluginUrl = pluginElement.getAttributeValue("url");
final String pluginVersion = pluginElement.getAttributeValue("version");
final Element descriptionElement = pluginElement.getChild("description");
final String description;
if (descriptionElement != null) {
description = descriptionElement.getText();
} else {
description = null;
}
Element descriptionElement = pluginElement.getChild("description");
String description = descriptionElement != null ? descriptionElement.getText() : null;
final List<PluginId> dependsPlugins = new ArrayList<PluginId>();
final List depends = pluginElement.getChildren("depends");
for (Object depend : depends) {
dependsPlugins.add(PluginId.getId(((Element)depend).getText()));
List<PluginId> dependsPlugins = new SmartList<PluginId>();
for (Element depend : pluginElement.getChildren("depends")) {
dependsPlugins.add(PluginId.getId(depend.getText()));
}
if (pluginId == null) {
@@ -401,8 +428,10 @@ public final class UpdateChecker {
continue;
}
final VirtualFile pluginFile = PluginDownloader.findPluginFile(pluginUrl, host);
if (pluginFile == null) continue;
VirtualFile pluginFile = PluginDownloader.findPluginFile(pluginUrl, host);
if (pluginFile == null) {
continue;
}
if (collectToUpdate) {
final String finalPluginUrl = getPluginUrl(pluginFile);
@@ -433,7 +462,8 @@ public final class UpdateChecker {
String pluginVersion,
BuildNumber buildNumber,
Map<PluginId, PluginDownloader> downloaded,
Collection<IdeaPluginDescriptor> incompatiblePlugins, boolean collectToUpdate, ProgressIndicator indicator) {
Collection<IdeaPluginDescriptor> incompatiblePlugins, boolean collectToUpdate,
ProgressIndicator indicator) {
try {
if (indicator != null) {
indicator.setText2(finalPluginUrl);
@@ -460,7 +490,7 @@ public final class UpdateChecker {
}
@Nullable
private static UpdatesInfo loadUpdatesInfo(@Nullable final String updateUrl) throws Exception {
private static UpdatesInfo loadUpdatesInfo(@Nullable String updateUrl) throws Exception {
if (LOG.isDebugEnabled()) {
LOG.debug("load update xml (UPDATE_URL='" + updateUrl + "' )");
}
@@ -471,12 +501,10 @@ public final class UpdateChecker {
}
return HttpRequests.request(updateUrl.startsWith("file:") ? updateUrl : updateUrl + '?' + prepareUpdateCheckArgs())
.connectTimeout(5 * Time.SECOND)
.readTimeout(5 * Time.SECOND)
.get(new ThrowableConvertor<URLConnection, UpdatesInfo, Exception>() {
@Override
public UpdatesInfo convert(URLConnection connection) throws Exception {
InputStream inputStream = connection.getInputStream();
InputStream inputStream = HttpRequests.getInputStream(connection);
try {
return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement());
}
@@ -501,9 +529,6 @@ public final class UpdateChecker {
return new CheckForUpdateResult(UpdateStrategy.State.NOTHING_LOADED);
}
}
catch (InterruptedIOException e) {
return new CheckForUpdateResult(UpdateStrategy.State.CONNECTION_ERROR, new ConnectionException(IdeBundle.message("updates.timeout.error")));
}
catch (Exception e) {
return new CheckForUpdateResult(UpdateStrategy.State.CONNECTION_ERROR, e);
}
@@ -644,49 +669,6 @@ public final class UpdateChecker {
}
}
@NotNull
private static URLConnection loadVersionInfo(@NotNull final String url) throws Exception {
final Ref<URLConnection> connectionRef = Ref.create();
final Ref<Exception> exception = Ref.create();
Future<?> downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
try {
String urlToCheck;
if (!StandardFileSystems.FILE_PROTOCOL.equals(new URL(url).getProtocol())) {
urlToCheck = url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString();
}
else {
urlToCheck = url;
}
URLConnection connection = HttpRequests.openConnection(urlToCheck, true).first;
connection.connect();
connectionRef.set(connection);
}
catch (IOException e) {
exception.set(e);
}
}
});
try {
downloadThreadFuture.get(5, TimeUnit.SECONDS);
}
catch (TimeoutException ignored) {
}
if (!downloadThreadFuture.isDone()) {
downloadThreadFuture.cancel(true);
throw new ConnectionException(IdeBundle.message("updates.timeout.error"));
}
if (!exception.isNull()) {
throw exception.get();
}
return connectionRef.get();
}
public static String getInstallationUID(final PropertiesComponent propertiesComponent) {
if (SystemInfo.isWindows) {
String uid = getInstallationUIDOnWindows(propertiesComponent);
@@ -739,12 +721,12 @@ public final class UpdateChecker {
return "";
}
public static boolean install(Collection<PluginDownloader> downloaders) {
public static boolean install(@NotNull Collection<PluginDownloader> downloaders, @NotNull ProgressIndicator progressIndicator) {
boolean installed = false;
for (PluginDownloader downloader : downloaders) {
if (getDisabledToUpdatePlugins().contains(downloader.getPluginId())) continue;
try {
if (downloader.prepareToInstall(ProgressManager.getInstance().getProgressIndicator())) {
if (downloader.prepareToInstall(progressIndicator)) {
final IdeaPluginDescriptor descriptor = downloader.getDescriptor();
if (descriptor != null) {
InstalledPluginsTableModel.updateExistingPlugin(descriptor, PluginManager.getPlugin(descriptor.getPluginId()));
@@ -117,7 +117,9 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
// in this case we should remove it from there
removeFromArray(indexInReal);
}
assertConsistency(ignoreCase, name);
if (CHECK) {
assertConsistency(ignoreCase, name);
}
}
@Nullable // null if there can't be a child with this name, NULL_VIRTUAL_FILE
@@ -0,0 +1,196 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ui.components;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.Consumer;
import com.intellij.util.ui.SwingHelper;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* @author Irina.Chernushina on 11/12/2014.
*/
public class SliderSelectorAction extends DumbAwareAction {
@NotNull private final Configuration myConfiguration;
public SliderSelectorAction(@Nullable String text, @Nullable String description, @Nullable Icon icon,
@NotNull Configuration configuration) {
super(text, description, icon);
myConfiguration = configuration;
}
@Override
public void update(@NotNull AnActionEvent e) {
super.update(e);
final String tooltip = myConfiguration.getTooltip();
if (tooltip != null) {
e.getPresentation().setText(getTemplatePresentation().getText() + " (" + tooltip + ")");
e.getPresentation().setDescription(getTemplatePresentation().getDescription() + " (" + tooltip + ")");
}
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final JPanel result = new JPanel(new BorderLayout());
final JLabel label = new JLabel(myConfiguration.getSelectText());
label.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 0));
JPanel wrapper = new JPanel(new BorderLayout());
wrapper.add(label, BorderLayout.NORTH);
result.add(wrapper, BorderLayout.WEST);
final JSlider slider = new JSlider(SwingConstants.HORIZONTAL, myConfiguration.getMin(), myConfiguration.getMax(), myConfiguration.getSelected());
slider.setMinorTickSpacing(1);
slider.setPaintTicks(true);
slider.setPaintTrack(true);
slider.setSnapToTicks(true);
UIUtil.setSliderIsFilled(slider, true);
slider.setPaintLabels(true);
slider.setLabelTable(myConfiguration.getDictionary());
result.add(slider, BorderLayout.CENTER);
final Runnable[] closeMe = new Runnable[1];
if (myConfiguration.isShowOk()) {
final JButton done = new JButton("Done");
result.add(SwingHelper.wrapWithoutStretch(done), BorderLayout.SOUTH);
done.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (closeMe[0] != null) closeMe[0].run();
}
});
}
final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(result, slider).createPopup();
final Runnable finalRunnable = new Runnable() {
@Override
public void run() {
int value = slider.getModel().getValue();
myConfiguration.getResultConsumer().consume(value);
}
};
closeMe[0] = new Runnable() {
@Override
public void run() {
finalRunnable.run();
popup.closeOk(null);
}
};
popup.setFinalRunnable(finalRunnable);
InputEvent inputEvent = e.getInputEvent();
if (inputEvent instanceof MouseEvent) {
int width = result.getPreferredSize().width;
MouseEvent inputEvent1 = (MouseEvent)inputEvent;
Point point1 = new Point(inputEvent1.getX() - width / 2, inputEvent1.getY());
RelativePoint point = new RelativePoint(inputEvent1.getComponent(), point1);
popup.show(point);
} else {
popup.showInBestPositionFor(e.getDataContext());
}
}
public static class Configuration {
@NotNull
private final String mySelectText;
@NotNull
private final Dictionary myDictionary;
private final int mySelected;
private final int myMin;
private final int myMax;
@NotNull
private final Consumer<Integer> myResultConsumer;
private boolean showOk = false;
public Configuration(int selected, @NotNull Dictionary dictionary, @NotNull String selectText, @NotNull Consumer<Integer> consumer) {
mySelected = selected;
myDictionary = new Hashtable<Integer, JComponent>();
mySelectText = selectText;
myResultConsumer = consumer;
int min = 1;
int max = 0;
final Enumeration keys = dictionary.keys();
while (keys.hasMoreElements()) {
final Integer key = (Integer)keys.nextElement();
final String value = (String)dictionary.get(key);
myDictionary.put(key, markLabel(value));
min = Math.min(min, key);
max = Math.max(max, key);
}
myMin = min;
myMax = max;
}
private static JLabel markLabel(final String text) {
JLabel label = new JLabel(text);
label.setFont(UIUtil.getLabelFont());
return label;
}
@NotNull
public String getSelectText() {
return mySelectText;
}
@NotNull
public Dictionary getDictionary() {
return myDictionary;
}
@NotNull
public Consumer<Integer> getResultConsumer() {
return myResultConsumer;
}
public int getSelected() {
return mySelected;
}
public int getMin() {
return myMin;
}
public int getMax() {
return myMax;
}
public boolean isShowOk() {
return showOk;
}
public void setShowOk(boolean showOk) {
this.showOk = showOk;
}
public String getTooltip() {
return null;
}
}
}
@@ -16,6 +16,7 @@
package com.intellij.util;
import com.intellij.openapi.application.ApplicationManager;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@@ -72,23 +73,32 @@ public class BufferedListConsumer<T> implements Consumer<List<T>> {
synchronized (myFlushLock) {
if (myPendingFlush || myBuffer.isEmpty()) return;
myPendingFlush = true;
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
myTs = ts;
final List<T> list;
synchronized (myFlushLock) {
myPendingFlush = false;
if (myBuffer.isEmpty()) return;
list = myBuffer;
myBuffer = new ArrayList<T>(mySize);
}
myConsumer.consume(list);
}
});
invokeConsumer(createConsumerRunnable(ts));
}
}
protected void invokeConsumer(@NotNull Runnable consumerRunnable) {
ApplicationManager.getApplication().executeOnPooledThread(consumerRunnable);
}
@NotNull
private Runnable createConsumerRunnable(final long ts) {
return new Runnable() {
@Override
public void run() {
myTs = ts;
final List<T> list;
synchronized (myFlushLock) {
myPendingFlush = false;
if (myBuffer.isEmpty()) return;
list = myBuffer;
myBuffer = new ArrayList<T>(mySize);
}
myConsumer.consume(list);
}
};
}
public void flush() {
flushImpl(System.currentTimeMillis());
if (myFlushListener != null) {
@@ -17,25 +17,29 @@ package com.intellij.util;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.ClassLoaderUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.zip.GZIPInputStream;
/**
* GZip supported by default, so, you must use {@link #getInputStream(java.net.URLConnection)} to get connection input stream.
*/
public final class HttpRequests {
public static class HttpRequestBuilder {
private final String url;
private int connectTimeout = HttpConfigurable.CONNECTION_TIMEOUT;
private int readTimeout = HttpConfigurable.CONNECTION_TIMEOUT;
private boolean supportGzip;
private Consumer<String> effectiveUrlConsumer;
private boolean supportGzip = true;
private HttpRequestBuilder(@NotNull String url) {
this.url = url;
@@ -47,6 +51,7 @@ public final class HttpRequests {
return this;
}
@SuppressWarnings("unused")
@NotNull
public HttpRequestBuilder readTimeout(int value) {
readTimeout = value;
@@ -59,7 +64,13 @@ public final class HttpRequests {
return this;
}
public <T> T get(@NotNull final ThrowableConvertor<URLConnection, T, Exception> handler) throws Exception {
@NotNull
public HttpRequestBuilder effectiveUrlConsumer(Consumer<String> value) {
effectiveUrlConsumer = value;
return this;
}
public <T, E extends Throwable> T get(@NotNull final ThrowableConvertor<URLConnection, T, E> handler) throws E, IOException {
return loadData(this, handler);
}
}
@@ -69,30 +80,46 @@ public final class HttpRequests {
return new HttpRequestBuilder(url);
}
private static <T> T loadData(@NotNull final HttpRequestBuilder requestBuilder, @NotNull final ThrowableConvertor<URLConnection, T, Exception> handler) throws Exception {
return ClassLoaderUtil.runWithClassLoader(new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()), new ThrowableComputable<T, Exception>() {
@Override
public T compute() throws Exception {
URLConnection connection = openConnection(requestBuilder.url, requestBuilder.supportGzip).first;
try {
return handler.convert(connection);
}
finally {
if (connection instanceof HttpURLConnection) {
((HttpURLConnection)connection).disconnect();
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
@NotNull
public static InputStream getInputStream(@NotNull URLConnection connection) throws IOException {
InputStream inputStream = connection.getInputStream();
if ("gzip".equalsIgnoreCase(connection.getContentEncoding())) {
try {
return new GZIPInputStream(inputStream);
}
catch (IOException e) {
inputStream.close();
throw e;
}
}
else {
return inputStream;
}
}
private static <T, E extends Throwable> T loadData(@NotNull HttpRequestBuilder requestBuilder, @NotNull ThrowableConvertor<URLConnection, T, E> handler)
throws E, IOException {
ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[0], oldClassLoader));
try {
URLConnection connection = openConnection(requestBuilder);
try {
return handler.convert(connection);
}
finally {
if (connection instanceof HttpURLConnection) {
((HttpURLConnection)connection).disconnect();
}
}
});
}
finally {
Thread.currentThread().setContextClassLoader(oldClassLoader);
}
}
@NotNull
public static Pair<URLConnection, String> openConnection(@NotNull String initialUrl, boolean supportGzip) throws IOException {
return openConnection(request(initialUrl).supportGzip(supportGzip));
}
@NotNull
private static Pair<URLConnection, String> openConnection(@NotNull HttpRequestBuilder requestBuilder) throws IOException {
private static URLConnection openConnection(@NotNull HttpRequestBuilder requestBuilder) throws IOException {
int i = 0;
String url = requestBuilder.url;
while (i++ < 99) {
@@ -132,7 +159,11 @@ public final class HttpRequests {
}
}
}
return Pair.create(connection, url == requestBuilder.url ? null : url);
if (url != requestBuilder.url && requestBuilder.effectiveUrlConsumer != null) {
requestBuilder.effectiveUrlConsumer.consume(url);
}
return connection;
}
throw new IOException("Infinite redirection");
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.io;
import com.intellij.openapi.application.ApplicationManager;
@@ -36,11 +35,10 @@ public class UrlConnectionUtil {
private UrlConnectionUtil() {
}
public static
@Nullable
InputStream getConnectionInputStream(URLConnection connection, @Nullable ProgressIndicator pi) {
public static InputStream getConnectionInputStream(@NotNull URLConnection connection, @Nullable ProgressIndicator progressIndicator) {
try {
return getConnectionInputStreamWithException(connection, pi);
return getConnectionInputStreamWithException(connection, progressIndicator);
}
catch (ProcessCanceledException e) {
return null;
@@ -50,14 +48,17 @@ public class UrlConnectionUtil {
}
}
@NotNull
public static InputStream getConnectionInputStreamWithException(@NotNull URLConnection connection, @Nullable ProgressIndicator progressIndicator) throws IOException {
if (ApplicationManager.getApplication() == null) {
return connection.getInputStream();
}
public static InputStream getConnectionInputStreamWithException(@NotNull URLConnection connection, @Nullable ProgressIndicator pi)
throws IOException {
InputStreamGetter getter = new InputStreamGetter(connection);
final Future<?> getterFuture = ApplicationManager.getApplication().executeOnPooledThread(getter);
while (true) {
if (pi != null) {
pi.checkCanceled();
if (progressIndicator != null) {
progressIndicator.checkCanceled();
}
try {
@@ -67,9 +68,9 @@ public class UrlConnectionUtil {
catch (TimeoutException ignored) {
}
if (pi != null) {
pi.setIndeterminate(true);
pi.setText(pi.getText());
if (progressIndicator != null) {
progressIndicator.setIndeterminate(true);
progressIndicator.setText(progressIndicator.getText());
}
if (getterFuture.isDone()) {
@@ -531,7 +531,6 @@ button.http.proxy.settings=&HTTP Proxy Settings...
group.vendor=Vendor
plugin.status.installed=Installed
progress.waiting.for.reply.from.plugin.manager=Waiting for reply from {0}
progress.connecting=Connecting...
progress.downloading.plugin=Downloading plugin ''{0}''
error.cannot.create.temp.dir=Unable to create temp directory ''{0}''
error.connection.failed.with.http.code.N=Connection failed with HTTP code {0}
@@ -454,7 +454,7 @@ commonjs.complete.required.filename.with.extension=false
commonjs.complete.required.filename.with.extension.description=If checked, required filenames are completed with extension
fix.jdk7.alt.shortcuts=true
fix.jdk7.alt.shortcuts=false
fix.jdk7.alt.shortcuts.description=Allow to use alt for shortcuts on MacOSX with jdk7+
spy.js.realtime.evaluation=false
@@ -33,6 +33,7 @@ import com.intellij.ui.content.ContentManager;
import com.intellij.util.BufferedListConsumer;
import com.intellij.util.Consumer;
import com.intellij.util.ContentsUtil;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -63,8 +64,10 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar
myRepositoryPath = repositoryPath;
myVcs = vcs;
myRefresherI = refresherI;
myBuffer = new BufferedListConsumer<VcsFileRevision>(5, new Consumer<List<VcsFileRevision>>() {
Consumer<List<VcsFileRevision>> sessionRefresher = new Consumer<List<VcsFileRevision>>() {
public void consume(List<VcsFileRevision> vcsFileRevisions) {
// TODO: Logic should be revised to we could just append some revisions to history panel instead of creating and showing new history
// TODO: session
mySession.getRevisionList().addAll(vcsFileRevisions);
final VcsHistorySession copy = mySession.copyWithCachedRevision();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -73,7 +76,16 @@ public class FileHistorySessionPartner implements VcsAppendableHistorySessionPar
}
});
}
}, 1000);
};
myBuffer = new BufferedListConsumer<VcsFileRevision>(5, sessionRefresher, 1000) {
@Override
protected void invokeConsumer(@NotNull Runnable consumerRunnable) {
// Do not invoke in arbitrary background thread as due to parallel execution this could lead to cases when invokeLater() (from
// sessionRefresher) is scheduled at first for history session with (as an example) 10 revisions (new buffered list) and then with
// 5 revisions (previous buffered list). And so incorrect UI is shown to the user.
consumerRunnable.run();
}
};
}
public void acceptRevision(VcsFileRevision revision) {
@@ -190,7 +190,7 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
}
private void updateDetailsBorder(@Nullable VcsFullCommitDetails data) {
if (data == null) {
if (data == null || !myColorManager.isMultipleRoots()) {
myMainContentPanel.setBorder(BorderFactory.createEmptyBorder());
}
else {
@@ -244,8 +244,8 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
myMainText = null;
}
else {
String header = (myMultiRoot ? "[" + commit.getRoot().getName() + "] " : "") +
commit.getId().toShortString() + " " + getAuthorText(commit);
String header = commit.getId().toShortString() + " " + getAuthorText(commit) +
(myMultiRoot ? " [" + commit.getRoot().getName() + "]" : "");
String body = getMessageText(commit);
myMainText = header + "<br/>" + body;
}
@@ -16,7 +16,6 @@ public interface AnnotateClient extends SvnClient {
void annotate(@NotNull SvnTarget target,
@NotNull SVNRevision startRevision,
@NotNull SVNRevision endRevision,
@Nullable SVNRevision pegRevision,
boolean includeMergedRevisions,
@Nullable DiffOptions diffOptions,
@Nullable AnnotationConsumer handler) throws VcsException;
@@ -29,12 +29,11 @@ public class CmdAnnotateClient extends BaseSvnClient implements AnnotateClient {
public void annotate(@NotNull SvnTarget target,
@NotNull SVNRevision startRevision,
@NotNull SVNRevision endRevision,
@Nullable SVNRevision pegRevision,
boolean includeMergedRevisions,
@Nullable DiffOptions diffOptions,
@Nullable final AnnotationConsumer handler) throws VcsException {
List<String> parameters = new ArrayList<String>();
CommandUtil.put(parameters, target.getPathOrUrlString(), pegRevision);
CommandUtil.put(parameters, target);
parameters.add("--revision");
parameters.add(startRevision + ":" + endRevision);
CommandUtil.put(parameters, includeMergedRevisions, "--use-merge-history");
@@ -49,7 +49,10 @@ import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAnnotationProvider {
private static final Object MERGED_KEY = new Object();
@@ -135,9 +138,8 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
// TODO: only 2 elements will be in rp and for loop will be executed only once - probably rewrite with Pair
AnnotateClient annotateClient = myVcs.getFactory(ioFile).createAnnotateClient();
for (int i = 0; i < rp.size() - 1; i++) {
annotateClient.annotate(SvnTarget.fromFile(ioFile), rp.get(i + 1), rp.get(i), ((SvnFileRevision)revision).getPegRevision(),
calculateMergeinfo,
getLogClientOptions(myVcs), annotateHandler);
annotateClient.annotate(SvnTarget.fromFile(ioFile), rp.get(i + 1), rp.get(i), calculateMergeinfo, getLogClientOptions(myVcs),
annotateHandler);
}
if (rp.get(1).getNumber() > 0) {
@@ -254,8 +256,9 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate() &&
SvnUtil.checkRepositoryVersion15(myVcs, wasUrl.toString());
AnnotateClient client = myVcs.getFactory().createAnnotateClient();
client.annotate(SvnTarget.fromURL(wasUrl), SVNRevision.create(1), svnRevision, svnRevision, calculateMergeinfo,
getLogClientOptions(myVcs), annotateHandler);
client
.annotate(SvnTarget.fromURL(wasUrl, svnRevision), SVNRevision.create(1), svnRevision, calculateMergeinfo, getLogClientOptions(myVcs),
annotateHandler);
return result;
}
@@ -24,7 +24,6 @@ public class SvnKitAnnotateClient extends BaseSvnClient implements AnnotateClien
public void annotate(@NotNull SvnTarget target,
@NotNull SVNRevision startRevision,
@NotNull SVNRevision endRevision,
@Nullable SVNRevision pegRevision,
boolean includeMergedRevisions,
@Nullable DiffOptions diffOptions,
@Nullable AnnotationConsumer handler) throws VcsException {
@@ -34,13 +33,13 @@ public class SvnKitAnnotateClient extends BaseSvnClient implements AnnotateClien
client.setDiffOptions(toDiffOptions(diffOptions));
if (target.isFile()) {
client
.doAnnotate(target.getFile(), pegRevision, startRevision, endRevision, true, includeMergedRevisions, toAnnotateHandler(handler),
null);
.doAnnotate(target.getFile(), target.getPegRevision(), startRevision, endRevision, true, includeMergedRevisions,
toAnnotateHandler(handler), null);
}
else {
client
.doAnnotate(target.getURL(), pegRevision, startRevision, endRevision, true, includeMergedRevisions, toAnnotateHandler(handler),
null);
.doAnnotate(target.getURL(), target.getPegRevision(), startRevision, endRevision, true, includeMergedRevisions,
toAnnotateHandler(handler), null);
}
}
catch (SVNException e) {
@@ -42,7 +42,9 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.jetbrains.idea.svn.info.Info;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -171,8 +173,12 @@ public class SvnHistoryProvider
@Override
public void reportAppendableHistory(FilePath path, final VcsAppendableHistorySessionPartner partner) throws VcsException {
// we need + 1 rows to be reported to further detect that number of rows exceeded the limit
reportAppendableHistory(path, partner, null, null, VcsConfiguration.getInstance(myVcs.getProject()).MAXIMUM_HISTORY_ROWS + 1, null, false);
// request MAXIMUM_HISTORY_ROWS + 1 log entries to be able to detect if there are more log entries than it is configured to show -
// see LimitHistoryCheck
VcsConfiguration configuration = VcsConfiguration.getInstance(myVcs.getProject());
int limit = configuration.LIMIT_HISTORY ? configuration.MAXIMUM_HISTORY_ROWS + 1 : 0;
reportAppendableHistory(path, partner, null, null, limit, null, false);
}
public void reportAppendableHistory(FilePath path, final VcsAppendableHistorySessionPartner partner,
@@ -324,7 +330,7 @@ public class SvnHistoryProvider
target,
myFrom == null ? SVNRevision.HEAD : myFrom,
myTo == null ? SVNRevision.create(1) : myTo,
false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
false, true, myShowMergeSources && mySupport15, myLimit, null,
new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl,
createConsumerAdapter(myConsumer),
repoRootURL, myFile.getCharset()));
@@ -404,7 +410,7 @@ public class SvnHistoryProvider
myVcs.getFactory(target).createHistoryClient()
.doLog(target, operationalFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, myShowMergeSources && mySupport15,
myLimit + 1, null, handler);
myLimit, null, handler);
}
catch (SVNCancelException e) {
//
@@ -31,7 +31,6 @@ public class SvnKitHistoryClient extends BaseSvnClient implements HistoryClient
@Nullable String[] revisionProperties,
@Nullable LogEntryConsumer handler) throws VcsException {
try {
// TODO: a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
SVNLogClient client = myVcs.getSvnKitManager().createLogClient();
if (target.isFile()) {
@@ -622,9 +622,18 @@ public class RemoteDebugger implements ProcessDebugger {
@Override
protected void onTextAvailable(@NotNull String text) {
myTextBuilder.append(text);
if (text.endsWith("\n")) {
processResponse(myTextBuilder.toString());
if (text.contains("\n")) {
String[] lines = myTextBuilder.toString().split("\n");
myTextBuilder = new StringBuilder();
if (!text.endsWith("\n")) {
myTextBuilder.append(lines[lines.length - 1]);
lines = Arrays.copyOfRange(lines, 0, lines.length - 1);
}
for (String line : lines) {
processResponse(line + "\n");
}
}
}
}
@@ -95,7 +95,7 @@ public class ResolveImportUtil {
base = base.getOriginalFile(); // just to make sure
result = base.getContainingDirectory();
int count = 1;
while (result != null && result.findFile(PyNames.INIT_DOT_PY) != null) {
while (result != null && PyUtil.isPackage(result, base)) {
if (count >= depth) return result;
result = result.getParentDirectory();
count += 1;
@@ -23,15 +23,16 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
import com.intellij.refactoring.RefactoringSettings;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFileHandler;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.actions.CreatePackageAction;
import com.jetbrains.python.codeInsight.imports.PyImportOptimizer;
import com.jetbrains.python.psi.*;
import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.refactoring.PyRefactoringUtil;
import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
@@ -64,13 +65,26 @@ public class PyMoveFileHandler extends MoveFileHandler {
root = root.getParentDirectory();
}
final boolean searchForReferences = RefactoringSettings.getInstance().MOVE_SEARCH_FOR_REFERENCES_FOR_FILE;
if (moveDestination != root && root != null && searchForReferences) {
if (moveDestination != root && root != null && searchForReferences && !probablyNamespacePackage(file, moveDestination, root)) {
CreatePackageAction.createInitPyInHierarchy(moveDestination, root);
}
}
// TODO: Update relative imports
}
private static boolean probablyNamespacePackage(@NotNull PsiFile anchor, @NotNull PsiDirectory destination, @NotNull PsiDirectory root) {
if (!LanguageLevel.forElement(anchor).isAtLeast(LanguageLevel.PYTHON33)) {
return false;
}
while (destination != null && destination != root) {
if (destination.findFile(PyNames.INIT_DOT_PY) != null) {
return false;
}
destination = destination.getParent();
}
return true;
}
@Override
public List<UsageInfo> findUsages(PsiFile file, PsiDirectory newParent, boolean searchInComments, boolean searchInNonJavaFiles) {
if (file != null) {
@@ -0,0 +1 @@
from .nspkg2 import foo
@@ -0,0 +1 @@
from .nspkg2 import f<caret>
@@ -0,0 +1 @@
from . import foo
@@ -0,0 +1 @@
from . import f<caret>
@@ -0,0 +1,3 @@
import nssubpkg.a
print(nssubpkg.a.VAR)
@@ -0,0 +1,3 @@
import nspkg.nssubpkg.a
print(nspkg.nssubpkg.a.VAR)
@@ -0,0 +1 @@
VAR = 42
@@ -0,0 +1,3 @@
import a
print(a.VAR)
@@ -0,0 +1,3 @@
import nspkg.nssubpkg.a
print(nspkg.nssubpkg.a.VAR)
@@ -0,0 +1,3 @@
import nspkg.a
print(nspkg.a.VAR)
@@ -0,0 +1,3 @@
import nspkg.nssubpkg.a
print(nspkg.nssubpkg.a.VAR)
@@ -119,4 +119,21 @@ public class Py3CompletionTest extends PyTestCase {
public void testImportNestedQualifiedNamespacePackage() {
doMultiFileTest();
}
// PY-7376
public void testRelativeFromImportInNamespacePackage() {
doMultiFileTestInsideNamespacePackage();
}
// PY-7376
public void testRelativeFromImportInNamespacePackage2() {
doMultiFileTestInsideNamespacePackage();
}
private void doMultiFileTestInsideNamespacePackage() {
myFixture.copyDirectoryToProject("completion/" + getTestName(true), "");
myFixture.configureByFile("nspkg1/a.py");
myFixture.completeBasic();
myFixture.checkResultByFile("completion/" + getTestName(true) + "/nspkg1/a.after.py");
}
}
@@ -374,6 +374,7 @@ public class PyMultiFileResolveTest extends PyMultiFileResolveTestCase {
assertResolvesTo(PyTargetExpression.class, "_private_name");
}
// PY-7378
public void testModuleInDeeplyNestedNamespacePackage() {
runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() {
@Override
@@ -382,4 +383,4 @@ public class PyMultiFileResolveTest extends PyMultiFileResolveTestCase {
}
});
}
}
}
@@ -23,6 +23,7 @@ import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.SystemProperties;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
@@ -138,6 +139,37 @@ public class PyMoveTest extends PyTestCase {
doMoveFileTest("mod2.py", "pkg1");
}
// PY-7378
public void testMoveNamespacePackageTest1() {
runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() {
@Override
public void run() {
doMoveFileTest("nspkg/nssubpkg", "");
}
});
}
// PY-7378
public void testMoveNamespacePackageTest2() {
runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() {
@Override
public void run() {
doMoveFileTest("nspkg/nssubpkg/a.py", "");
}
});
}
// PY-7378
public void testMoveNamespacePackageTest3() {
runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() {
@Override
public void run() {
doMoveFileTest("nspkg/nssubpkg/a.py", "nspkg");
}
});
}
private void doMoveFileTest(String fileName, String toDirName) {
Project project = myFixture.getProject();
PsiManager manager = PsiManager.getInstance(project);
@@ -53,7 +53,10 @@ public class XmlUnusedNamespaceInspection extends XmlSuppressableInspectionTool
return new XmlElementVisitor() {
@Override
public void visitXmlAttribute(XmlAttribute attribute) {
XmlRefCountHolder refCountHolder = XmlRefCountHolder.getRefCountHolder((XmlFile)holder.getFile());
PsiFile file = holder.getFile();
if (!(file instanceof XmlFile)) return;
XmlRefCountHolder refCountHolder = XmlRefCountHolder.getRefCountHolder((XmlFile)file);
if (refCountHolder == null) return;
if (!attribute.isNamespaceDeclaration()) {
checkUnusedLocations(attribute, holder, refCountHolder);