mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
+15
-9
@@ -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) {
|
||||
|
||||
+2
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
+36
-63
@@ -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");
|
||||
|
||||
+14
-6
@@ -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
|
||||
|
||||
+72
-90
@@ -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()));
|
||||
|
||||
+3
-1
@@ -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
|
||||
|
||||
+14
-2
@@ -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 @@
|
||||
VAR = 42
|
||||
@@ -0,0 +1,3 @@
|
||||
import nspkg.nssubpkg.a
|
||||
|
||||
print(nspkg.nssubpkg.a.VAR)
|
||||
+1
@@ -0,0 +1 @@
|
||||
VAR = 42
|
||||
@@ -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)
|
||||
+1
@@ -0,0 +1 @@
|
||||
VAR = 42
|
||||
@@ -0,0 +1,3 @@
|
||||
import nspkg.a
|
||||
|
||||
print(nspkg.a.VAR)
|
||||
@@ -0,0 +1 @@
|
||||
VAR = 42
|
||||
@@ -0,0 +1,3 @@
|
||||
import nspkg.nssubpkg.a
|
||||
|
||||
print(nspkg.nssubpkg.a.VAR)
|
||||
+1
@@ -0,0 +1 @@
|
||||
VAR = 42
|
||||
@@ -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);
|
||||
|
||||
+4
-1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user