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:
@@ -332,7 +332,7 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
|
||||
private final ModifiableRootModel myDelegateModel;
|
||||
@NonNls private final Set<String> myCheckedNames = new HashSet<String>(
|
||||
Arrays.asList("addOrderEntry", "addLibraryEntry", "addInvalidLibrary", "addModuleOrderEntry", "addInvalidModuleEntry",
|
||||
"removeOrderEntry", "setSdk", "inheritSdk", "inheritCompilerOutputPath", "setExcludeOutput", "replaceEntryOfType"));
|
||||
"removeOrderEntry", "setSdk", "inheritSdk", "inheritCompilerOutputPath", "setExcludeOutput", "replaceEntryOfType", "rearrangeOrderEntries"));
|
||||
|
||||
ModifiableRootModelInvocationHandler(ModifiableRootModel model) {
|
||||
myDelegateModel = model;
|
||||
|
||||
+1
-1
@@ -103,7 +103,7 @@ public abstract class ChangeLibraryLevelActionBase extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
final Library copied = ((LibraryTableBase.ModifiableModelEx)provider.getModifiableModel()).createLibrary(dialog.getLibraryName(), library.getKind());
|
||||
final Library copied = ((LibraryTableBase.ModifiableModelEx)provider.getModifiableModel()).createLibrary(StringUtil.nullize(dialog.getLibraryName()), library.getKind());
|
||||
final LibraryEx.ModifiableModelEx model = (LibraryEx.ModifiableModelEx)copied.getModifiableModel();
|
||||
LibraryEditingUtil.copyLibrary(library, copiedFiles, model);
|
||||
|
||||
|
||||
+7
-3
@@ -18,6 +18,7 @@ package com.intellij.openapi.roots.ui.configuration.classpath;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.impl.OrderEntryUtil;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryTableImplUtil;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
@@ -43,15 +44,18 @@ class ChangeLibraryLevelInClasspathAction extends ChangeLibraryLevelActionBase {
|
||||
public void actionPerformed(AnActionEvent event) {
|
||||
final OrderEntry entry = myPanel.getSelectedEntry();
|
||||
if (!(entry instanceof LibraryOrderEntry)) return;
|
||||
final LibraryEx library = (LibraryEx)((LibraryOrderEntry)entry).getLibrary();
|
||||
LibraryOrderEntry libraryEntry = (LibraryOrderEntry)entry;
|
||||
final LibraryEx library = (LibraryEx)libraryEntry.getLibrary();
|
||||
if (library == null) return;
|
||||
|
||||
final Library copied = doCopy(library);
|
||||
if (copied == null) return;
|
||||
|
||||
myPanel.getRootModel().removeOrderEntry(entry);
|
||||
if (!isConvertingToModuleLibrary()) {
|
||||
myPanel.getRootModel().addLibraryEntry(copied);
|
||||
OrderEntryUtil.replaceLibrary(myPanel.getRootModel(), library, copied);
|
||||
}
|
||||
else {
|
||||
OrderEntryUtil.replaceLibraryEntryByAdded(myPanel.getRootModel(), libraryEntry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class RemoveAssignmentFix extends RemoveInitializerFix {
|
||||
if (!(parent instanceof PsiAssignmentExpression)) return;
|
||||
final PsiExpression rExpression = ((PsiAssignmentExpression)parent).getRExpression();
|
||||
final PsiElement gParent = parent.getParent();
|
||||
if (gParent instanceof PsiExpression && rExpression != null) {
|
||||
if ((gParent instanceof PsiExpression || gParent instanceof PsiExpressionList) && rExpression != null) {
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(gParent.getContainingFile())) return;
|
||||
if (gParent instanceof PsiParenthesizedExpression) {
|
||||
gParent.replace(rExpression);
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Remove redundant assignment" "true"
|
||||
class Test {
|
||||
void foo() {
|
||||
String var;
|
||||
this.bar("someString");
|
||||
}
|
||||
|
||||
void bar(String arg) {
|
||||
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Remove redundant assignment" "true"
|
||||
class Test {
|
||||
void foo() {
|
||||
String var;
|
||||
this.bar(v<caret>ar = "someString");
|
||||
}
|
||||
|
||||
void bar(String arg) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -216,6 +216,9 @@ public abstract class ProjectWizardTestCase<T extends AbstractProjectWizard> ext
|
||||
}
|
||||
});
|
||||
SelectTemplateSettings.getInstance().setLastTemplate(null, null);
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
Thread.sleep(2000); //wait for JBCardLayout release timers
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
|
||||
@@ -611,5 +611,10 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
visitor.visitComponentAdapter(this);
|
||||
myDelegate.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ComponentConfigAdapter[" + getComponentKey() + "]: implementation=" + getComponentImplementation() + ", plugin=" + myConfig.getPluginId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -191,4 +191,9 @@ public class ExtensionComponentAdapter implements LoadingOrder.Orderable, Assign
|
||||
public void setNotificationSent(boolean notificationSent) {
|
||||
myNotificationSent = notificationSent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ExtensionComponentAdapter[" + myImplementationClassName + "]: plugin=" + myPluginDescriptor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -13,14 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.ide.actions;
|
||||
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -32,58 +32,48 @@ import com.intellij.psi.PsiManager;
|
||||
public class ReloadFromDiskAction extends AnAction implements DumbAware {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
DataContext dataContext = e.getDataContext();
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
|
||||
if (editor == null) return;
|
||||
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
if (psiFile == null) return;
|
||||
final Project project = e.getProject();
|
||||
final Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
|
||||
if (project == null || editor == null) return;
|
||||
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
if (file == null) return;
|
||||
|
||||
int res = Messages.showOkCancelDialog(
|
||||
project,
|
||||
IdeBundle.message("prompt.reload.file.from.disk", psiFile.getVirtualFile().getPresentableUrl()),
|
||||
IdeBundle.message("title.reload.file"),
|
||||
Messages.getWarningIcon()
|
||||
);
|
||||
String message = IdeBundle.message("prompt.reload.file.from.disk", file.getVirtualFile().getPresentableUrl());
|
||||
int res = Messages.showOkCancelDialog(project, message, IdeBundle.message("title.reload.file"), Messages.getWarningIcon());
|
||||
if (res != Messages.OK) return;
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
project, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PsiManager.getInstance(project).reloadFromDisk(psiFile);
|
||||
Runnable command = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!project.isDisposed()) {
|
||||
file.getVirtualFile().refresh(false, false);
|
||||
PsiManager.getInstance(project).reloadFromDisk(file);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
IdeBundle.message("command.reload.from.disk"),
|
||||
null
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
CommandProcessor.getInstance().executeCommand(project, command, IdeBundle.message("command.reload.from.disk"), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent event){
|
||||
Presentation presentation = event.getPresentation();
|
||||
DataContext dataContext = event.getDataContext();
|
||||
Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (project == null){
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
|
||||
if (editor == null){
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
Document document = editor.getDocument();
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (psiFile == null || psiFile.getVirtualFile() == null){
|
||||
presentation.setEnabled(false);
|
||||
public void update(AnActionEvent event) {
|
||||
boolean enabled = false;
|
||||
|
||||
Project project = event.getProject();
|
||||
Editor editor = CommonDataKeys.EDITOR.getData(event.getDataContext());
|
||||
if (project != null && editor != null) {
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
|
||||
if (file != null && file.getVirtualFile() != null) {
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
event.getPresentation().setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -152,21 +153,45 @@ public class OrderEntryUtil {
|
||||
rootModel.commit();
|
||||
}
|
||||
|
||||
public static void replaceLibrary(@NotNull ModifiableRootModel model, @NotNull Library oldLibrary, @NotNull Library newLibrary) {
|
||||
OrderEntry[] entries = model.getOrderEntries();
|
||||
private static int findLibraryOrderEntry(@NotNull OrderEntry[] entries, @NotNull Library library) {
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
OrderEntry orderEntry = entries[i];
|
||||
if (orderEntry instanceof LibraryOrderEntry && oldLibrary.equals(((LibraryOrderEntry)orderEntry).getLibrary())) {
|
||||
model.removeOrderEntry(orderEntry);
|
||||
final LibraryOrderEntry newEntry = model.addLibraryEntry(newLibrary);
|
||||
final OrderEntry[] newEntries = new OrderEntry[entries.length];
|
||||
System.arraycopy(entries, 0, newEntries, 0, i);
|
||||
newEntries[i] = newEntry;
|
||||
System.arraycopy(entries, i, newEntries, i+1, entries.length - i - 1);
|
||||
model.rearrangeOrderEntries(newEntries);
|
||||
return;
|
||||
OrderEntry entry = entries[i];
|
||||
if (entry instanceof LibraryOrderEntry && library.equals(((LibraryOrderEntry)entry).getLibrary())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void replaceLibrary(@NotNull ModifiableRootModel model, @NotNull Library oldLibrary, @NotNull Library newLibrary) {
|
||||
int i = findLibraryOrderEntry(model.getOrderEntries(), oldLibrary);
|
||||
if (i == -1) return;
|
||||
|
||||
model.addLibraryEntry(newLibrary);
|
||||
replaceLibraryByAdded(model, i);
|
||||
}
|
||||
|
||||
public static void replaceLibraryEntryByAdded(@NotNull ModifiableRootModel model, @NotNull LibraryOrderEntry entry) {
|
||||
int i = ArrayUtil.indexOf(model.getOrderEntries(), entry);
|
||||
if (i == -1) return;
|
||||
|
||||
replaceLibraryByAdded(model, i);
|
||||
}
|
||||
|
||||
private static void replaceLibraryByAdded(ModifiableRootModel model, int toReplace) {
|
||||
OrderEntry[] entries = model.getOrderEntries();
|
||||
LibraryOrderEntry newEntry = (LibraryOrderEntry)entries[entries.length - 1];
|
||||
LibraryOrderEntry libraryEntry = (LibraryOrderEntry)entries[toReplace];
|
||||
boolean exported = libraryEntry.isExported();
|
||||
DependencyScope scope = libraryEntry.getScope();
|
||||
model.removeOrderEntry(libraryEntry);
|
||||
newEntry.setExported(exported);
|
||||
newEntry.setScope(scope);
|
||||
final OrderEntry[] newEntries = new OrderEntry[entries.length-1];
|
||||
System.arraycopy(entries, 0, newEntries, 0, toReplace);
|
||||
newEntries[toReplace] = newEntry;
|
||||
System.arraycopy(entries, toReplace + 1, newEntries, toReplace + 1, entries.length - toReplace - 2);
|
||||
model.rearrangeOrderEntries(newEntries);
|
||||
}
|
||||
|
||||
public static <T extends OrderEntry> void processOrderEntries(@NotNull Module module,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.ide;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.LogUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
@@ -24,13 +25,21 @@ import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileAttributes;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.VirtualFileSystem;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import com.intellij.ui.EditorNotifications;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class FileChangedNotificationProvider extends EditorNotifications.Provider<EditorNotificationPanel> {
|
||||
private static final Logger LOG = Logger.getInstance(FileChangedNotificationProvider.class);
|
||||
private static final Key<EditorNotificationPanel> KEY = Key.create("file.changed.notification.panel");
|
||||
@@ -51,6 +60,23 @@ public class FileChangedNotificationProvider extends EditorNotifications.Provide
|
||||
}
|
||||
}
|
||||
}, project);
|
||||
|
||||
MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(myProject);
|
||||
connection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
if (!myProject.isDisposed() && !GeneralSettings.getInstance().isSyncOnFrameActivation()) {
|
||||
Set<VirtualFile> openFiles = ContainerUtil.newHashSet(FileEditorManager.getInstance(myProject).getSelectedFiles());
|
||||
EditorNotifications notifications = EditorNotifications.getInstance(myProject);
|
||||
for (VFileEvent event : events) {
|
||||
VirtualFile file = event.getFile();
|
||||
if (openFiles.contains(file)) {
|
||||
notifications.updateNotifications(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+89
-63
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.ide.plugins;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -73,9 +74,9 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
final MyPluginManagerColumnInfo infoColumn = new MyPluginManagerColumnInfo();
|
||||
final EnabledPluginInfo enabledColumn = new EnabledPluginInfo();
|
||||
final Spacer spacer = new Spacer();
|
||||
super.columns = SystemInfo.isMac ? new ColumnInfo[]{infoColumn, enabledColumn, spacer}
|
||||
columns = SystemInfo.isMac ? new ColumnInfo[]{infoColumn, enabledColumn, spacer}
|
||||
:new ColumnInfo[]{infoColumn, enabledColumn};
|
||||
view = new ArrayList<IdeaPluginDescriptor>(Arrays.asList(PluginManager.getPlugins()));
|
||||
view = new ArrayList<IdeaPluginDescriptor>(Arrays.asList(PluginManagerCore.getPlugins()));
|
||||
view.addAll(myInstalled);
|
||||
reset(view);
|
||||
|
||||
@@ -122,11 +123,12 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNameColumn() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void reset(final List<IdeaPluginDescriptor> list) {
|
||||
private void reset(@NotNull List<IdeaPluginDescriptor> list) {
|
||||
for (IdeaPluginDescriptor ideaPluginDescriptor : list) {
|
||||
setEnabled(ideaPluginDescriptor);
|
||||
}
|
||||
@@ -134,13 +136,16 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
updatePluginDependencies();
|
||||
|
||||
final Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(null, "Load custom plugin repositories data...") {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
updateRepositoryPlugins();
|
||||
}
|
||||
});
|
||||
if (!ApplicationManager.getApplication().isDisposed()) {
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(null, "Load custom plugin repositories data...") {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
updateRepositoryPlugins();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
SwingUtilities.invokeLater(runnable);
|
||||
@@ -168,7 +173,7 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
|
||||
private void setEnabled(IdeaPluginDescriptor ideaPluginDescriptor,
|
||||
final boolean enabled) {
|
||||
final Collection<String> disabledPlugins = PluginManager.getDisabledPlugins();
|
||||
final Collection<String> disabledPlugins = PluginManagerCore.getDisabledPlugins();
|
||||
final PluginId pluginId = ideaPluginDescriptor.getPluginId();
|
||||
if (!enabled && !disabledPlugins.contains(pluginId.toString())) {
|
||||
myEnabled.put(pluginId, null);
|
||||
@@ -192,37 +197,40 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
if (descriptor instanceof IdeaPluginDescriptorImpl && ((IdeaPluginDescriptorImpl)descriptor).isDeleted()) continue;
|
||||
final Boolean enabled = myEnabled.get(pluginId);
|
||||
if (enabled == null || enabled.booleanValue()) {
|
||||
PluginManager.checkDependants(descriptor, new Function<PluginId, IdeaPluginDescriptor>() {
|
||||
@Nullable
|
||||
public IdeaPluginDescriptor fun(final PluginId pluginId) {
|
||||
return PluginManager.getPlugin(pluginId);
|
||||
}
|
||||
}, new Condition<PluginId>() {
|
||||
public boolean value(final PluginId dependantPluginId) {
|
||||
final Boolean enabled = myEnabled.get(dependantPluginId);
|
||||
if ((enabled == null && !updatedPlugins.contains(dependantPluginId)) ||
|
||||
(enabled != null && !enabled.booleanValue())) {
|
||||
Set<PluginId> required = myDependentToRequiredListMap.get(pluginId);
|
||||
if (required == null) {
|
||||
required = new HashSet<PluginId>();
|
||||
myDependentToRequiredListMap.put(pluginId, required);
|
||||
}
|
||||
PluginManagerCore.checkDependants(descriptor, new Function<PluginId, IdeaPluginDescriptor>() {
|
||||
@Override
|
||||
@Nullable
|
||||
public IdeaPluginDescriptor fun(final PluginId pluginId) {
|
||||
return PluginManager.getPlugin(pluginId);
|
||||
}
|
||||
}, new Condition<PluginId>() {
|
||||
@Override
|
||||
public boolean value(final PluginId dependantPluginId) {
|
||||
final Boolean enabled = myEnabled.get(dependantPluginId);
|
||||
if ((enabled == null && !updatedPlugins.contains(dependantPluginId)) ||
|
||||
(enabled != null && !enabled.booleanValue())) {
|
||||
Set<PluginId> required = myDependentToRequiredListMap.get(pluginId);
|
||||
if (required == null) {
|
||||
required = new HashSet<PluginId>();
|
||||
myDependentToRequiredListMap.put(pluginId, required);
|
||||
}
|
||||
|
||||
required.add(dependantPluginId);
|
||||
//return false;
|
||||
}
|
||||
required.add(dependantPluginId);
|
||||
//return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
if (enabled == null && !myDependentToRequiredListMap.containsKey(pluginId) && !PluginManager.isIncompatible(descriptor)) {
|
||||
if (enabled == null && !myDependentToRequiredListMap.containsKey(pluginId) && !PluginManagerCore.isIncompatible(descriptor)) {
|
||||
myEnabled.put(pluginId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePluginsList(List<IdeaPluginDescriptor> list) {
|
||||
// For each downloadable plugin we need to know whether its counterpart
|
||||
// is already installed, and if yes compare the difference in versions:
|
||||
@@ -277,7 +285,7 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
installedPlugins.add(idString);
|
||||
}
|
||||
final PluginManagerUISettings updateSettings = PluginManagerUISettings.getInstance();
|
||||
if (state > 0 && !PluginManager.isIncompatible(descr) && !updatedPlugins.contains(descr.getPluginId())) {
|
||||
if (state > 0 && !PluginManagerCore.isIncompatible(descr) && !updatedPlugins.contains(descr.getPluginId())) {
|
||||
NewVersions2Plugins.put(pluginId, 1);
|
||||
if (!updateSettings.myOutdatedPlugins.contains(idString)) {
|
||||
updateSettings.myOutdatedPlugins.add(idString);
|
||||
@@ -312,6 +320,7 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
private void hideNotApplicablePlugins(Boolean value, final IdeaPluginDescriptor... ideaPluginDescriptors) {
|
||||
if (!value && ENABLED.equals(myEnabledFilter) || (value && DISABLED.equals(myEnabledFilter))) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (IdeaPluginDescriptor ideaPluginDescriptor : ideaPluginDescriptors) {
|
||||
view.remove(ideaPluginDescriptor);
|
||||
@@ -375,10 +384,12 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
super("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object valueOf(IdeaPluginDescriptor ideaPluginDescriptor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(final IdeaPluginDescriptor ideaPluginDescriptor) {
|
||||
return false;
|
||||
}
|
||||
@@ -389,6 +400,7 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
return new DefaultTableCellRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getColumnClass() {
|
||||
return Spacer.class;
|
||||
}
|
||||
@@ -400,22 +412,27 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
super(/*IdeBundle.message("plugin.manager.enable.column.title")*/"");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean valueOf(IdeaPluginDescriptor ideaPluginDescriptor) {
|
||||
return myEnabled.get(ideaPluginDescriptor.getPluginId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(final IdeaPluginDescriptor ideaPluginDescriptor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getColumnClass() {
|
||||
return Boolean.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellEditor getEditor(final IdeaPluginDescriptor o) {
|
||||
return new BooleanTableCellEditor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellRenderer getRenderer(final IdeaPluginDescriptor ideaPluginDescriptor) {
|
||||
return new BooleanTableCellRenderer() {
|
||||
@Override
|
||||
@@ -430,6 +447,7 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(final IdeaPluginDescriptor ideaPluginDescriptor, Boolean value) {
|
||||
final PluginId currentPluginId = ideaPluginDescriptor.getPluginId();
|
||||
final Boolean enabled = myEnabled.get(currentPluginId) == null ? Boolean.FALSE : value;
|
||||
@@ -439,8 +457,10 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
hideNotApplicablePlugins(value, ideaPluginDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<IdeaPluginDescriptor> getComparator() {
|
||||
return new Comparator<IdeaPluginDescriptor>() {
|
||||
@Override
|
||||
public int compare(final IdeaPluginDescriptor o1, final IdeaPluginDescriptor o2) {
|
||||
final Boolean enabled1 = myEnabled.get(o1.getPluginId());
|
||||
final Boolean enabled2 = myEnabled.get(o2.getPluginId());
|
||||
@@ -486,34 +506,39 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
}
|
||||
|
||||
for (final IdeaPluginDescriptor ideaPluginDescriptor : descriptorsToCheckDependencies) {
|
||||
PluginManager.checkDependants(ideaPluginDescriptor, new Function<PluginId, IdeaPluginDescriptor>() {
|
||||
@Nullable
|
||||
public IdeaPluginDescriptor fun(final PluginId pluginId) {
|
||||
return PluginManager.getPlugin(pluginId);
|
||||
}
|
||||
}, new Condition<PluginId>() {
|
||||
public boolean value(final PluginId pluginId) {
|
||||
Boolean enabled = myEnabled.get(pluginId);
|
||||
if (enabled == null) {
|
||||
return false;
|
||||
}
|
||||
if (newVal && !enabled.booleanValue()) {
|
||||
deps.add(pluginId);
|
||||
}
|
||||
PluginManagerCore.checkDependants(ideaPluginDescriptor, new Function<PluginId, IdeaPluginDescriptor>() {
|
||||
@Override
|
||||
@Nullable
|
||||
public IdeaPluginDescriptor fun(final PluginId pluginId) {
|
||||
return PluginManager.getPlugin(pluginId);
|
||||
}
|
||||
}, new Condition<PluginId>() {
|
||||
@Override
|
||||
public boolean value(final PluginId pluginId) {
|
||||
Boolean enabled = myEnabled.get(pluginId);
|
||||
if (enabled == null) {
|
||||
return false;
|
||||
}
|
||||
if (newVal && !enabled.booleanValue()) {
|
||||
deps.add(pluginId);
|
||||
}
|
||||
|
||||
if (!newVal) {
|
||||
if (ideaPluginDescriptor instanceof IdeaPluginDescriptorImpl && ((IdeaPluginDescriptorImpl)ideaPluginDescriptor).isDeleted()) return true;
|
||||
final PluginId pluginDescriptorId = ideaPluginDescriptor.getPluginId();
|
||||
for (IdeaPluginDescriptor descriptor : ideaPluginDescriptors) {
|
||||
if (pluginId.equals(descriptor.getPluginId())) {
|
||||
deps.add(pluginDescriptorId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!newVal) {
|
||||
if (ideaPluginDescriptor instanceof IdeaPluginDescriptorImpl &&
|
||||
((IdeaPluginDescriptorImpl)ideaPluginDescriptor).isDeleted()) {
|
||||
return true;
|
||||
}
|
||||
final PluginId pluginDescriptorId = ideaPluginDescriptor.getPluginId();
|
||||
for (IdeaPluginDescriptor descriptor : ideaPluginDescriptors) {
|
||||
if (pluginId.equals(descriptor.getPluginId())) {
|
||||
deps.add(pluginDescriptorId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (!deps.isEmpty()) {
|
||||
@@ -525,6 +550,7 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
}, ", ");
|
||||
final Set<IdeaPluginDescriptor> pluginDependencies = new HashSet<IdeaPluginDescriptor>();
|
||||
final String listOfDependencies = StringUtil.join(deps, new Function<PluginId, String>() {
|
||||
@Override
|
||||
public String fun(final PluginId pluginId) {
|
||||
final IdeaPluginDescriptor pluginDescriptor = PluginManager.getPlugin(pluginId);
|
||||
assert pluginDescriptor != null;
|
||||
@@ -564,13 +590,13 @@ public class InstalledPluginsTableModel extends PluginTableModel {
|
||||
|
||||
@Override
|
||||
public Comparator<IdeaPluginDescriptor> getComparator() {
|
||||
final Comparator<IdeaPluginDescriptor> comparator = super.getColumnComparator();
|
||||
final Comparator<IdeaPluginDescriptor> comparator = getColumnComparator();
|
||||
return new Comparator<IdeaPluginDescriptor>() {
|
||||
@Override
|
||||
public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) {
|
||||
if (isSortByStatus()) {
|
||||
final boolean incompatible1 = PluginManager.isIncompatible(o1);
|
||||
final boolean incompatible2 = PluginManager.isIncompatible(o2);
|
||||
final boolean incompatible1 = PluginManagerCore.isIncompatible(o1);
|
||||
final boolean incompatible2 = PluginManagerCore.isIncompatible(o2);
|
||||
if (incompatible1) {
|
||||
if (incompatible2) return comparator.compare(o1, o2);
|
||||
return -1;
|
||||
|
||||
@@ -90,7 +90,7 @@ public class IdeaApplication {
|
||||
}
|
||||
|
||||
if (Main.isCommandLine()) {
|
||||
new CommandLineApplication(isInternal, false, headless);
|
||||
new CommandLineApplication(isInternal, isUnitTest, headless);
|
||||
}
|
||||
else {
|
||||
Splash splash = null;
|
||||
|
||||
+186
-145
@@ -19,6 +19,7 @@ import com.intellij.BundleBase;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.diagnostic.PerformanceWatcher;
|
||||
import com.intellij.diagnostic.PluginException;
|
||||
import com.intellij.diagnostic.ThreadDumper;
|
||||
import com.intellij.ide.*;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
@@ -80,7 +81,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"})
|
||||
public class ApplicationImpl extends PlatformComponentManagerImpl implements ApplicationEx {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.application.impl.ApplicationImpl");
|
||||
private final ModalityState MODALITY_STATE_NONE = ModalityState.NON_MODAL;
|
||||
@@ -96,7 +96,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
private IApplicationStore myComponentStore;
|
||||
|
||||
private boolean myTestModeFlag;
|
||||
private final boolean myTestModeFlag;
|
||||
private final boolean myHeadlessMode;
|
||||
private final boolean myCommandLineMode;
|
||||
|
||||
@@ -107,12 +107,12 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
private volatile Runnable myExceptionalThreadWithReadAccessRunnable;
|
||||
|
||||
private int myInEditorPaintCounter = 0;
|
||||
private long myStartTime = 0;
|
||||
private int myInEditorPaintCounter; // EDT only
|
||||
private final long myStartTime;
|
||||
@Nullable
|
||||
private final Splash mySplash;
|
||||
private boolean myDoNotSave;
|
||||
private volatile boolean myDisposeInProgress = false;
|
||||
private volatile boolean myDisposeInProgress;
|
||||
|
||||
private final Disposable myLastDisposable = Disposer.newDisposable(); // will be disposed last
|
||||
|
||||
@@ -171,7 +171,30 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
private Boolean myActive;
|
||||
|
||||
private static final ThreadLocal<Integer> ourEdtSafe = new ThreadLocal<Integer>();
|
||||
private static final int IS_EDT_FLAG = 1<<30; // we don't mess with sign bit since we want to do arithmetic
|
||||
private static final int IS_READ_LOCK_ACQUIRED_FLAG = 1<<29;
|
||||
private static final int IS_EXCEPTIONAL_THREAD_FLAG = 1<<28;
|
||||
private static class Status {
|
||||
// higher three bits are for IS_* flags
|
||||
// lower bits are for edtSafe counter
|
||||
private int flags;
|
||||
}
|
||||
|
||||
private static final ThreadLocal<Status> status = new ThreadLocal<Status>(){
|
||||
@Override
|
||||
protected Status initialValue() {
|
||||
Status status = new Status();
|
||||
status.flags = BitUtil.set(status.flags, IS_EDT_FLAG, EventQueue.isDispatchThread());
|
||||
return status;
|
||||
}
|
||||
};
|
||||
private static Status getStatus() {
|
||||
return status.get();
|
||||
}
|
||||
private static void setReadLockAcquired(Status status, boolean acquired) {
|
||||
status.flags = BitUtil.set(status.flags, IS_READ_LOCK_ACQUIRED_FLAG, acquired);
|
||||
}
|
||||
|
||||
@NonNls private static final ModalityState ANY = new ModalityState() {
|
||||
@Override
|
||||
public boolean dominates(@NotNull ModalityState anotherState) {
|
||||
@@ -201,7 +224,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeComponent(Object component, boolean service) {
|
||||
public void initializeComponent(@NotNull Object component, boolean service) {
|
||||
getStateStore().initComponent(component, service);
|
||||
}
|
||||
|
||||
@@ -233,7 +256,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
myHeadlessMode = isHeadless;
|
||||
myCommandLineMode = isCommandLine;
|
||||
|
||||
myDoNotSave = myTestModeFlag || myHeadlessMode;
|
||||
myDoNotSave = isUnitTestMode || isHeadless;
|
||||
|
||||
loadApplicationComponents();
|
||||
|
||||
@@ -353,7 +376,11 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
@Override
|
||||
public boolean holdsReadLock() {
|
||||
return myLock.getReadHoldCount() != 0;
|
||||
return holdsReadLock(getStatus());
|
||||
}
|
||||
|
||||
private static boolean holdsReadLock(Status status) {
|
||||
return BitUtil.isSet(status.flags, IS_READ_LOCK_ACQUIRED_FLAG);
|
||||
}
|
||||
|
||||
private void loadApplicationComponents() {
|
||||
@@ -367,7 +394,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized Object createComponent(Class componentInterface) {
|
||||
protected synchronized Object createComponent(@NotNull Class componentInterface) {
|
||||
Object component = super.createComponent(componentInterface);
|
||||
if (mySplash != null) {
|
||||
mySplash.showProgress("", 0.65f + getPercentageOfComponentsLoaded() * 0.35f);
|
||||
@@ -375,6 +402,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
return component;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected MutablePicoContainer createPicoContainer() {
|
||||
return Extensions.getRootArea().getPicoContainer();
|
||||
@@ -395,10 +423,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
return myTestModeFlag;
|
||||
}
|
||||
|
||||
public void setUnitTestMode(boolean testModeFlag) {
|
||||
myTestModeFlag = testModeFlag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHeadlessEnvironment() {
|
||||
return myHeadlessMode;
|
||||
@@ -415,6 +439,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
return ourThreadExecutorsService.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isReadAccessAllowed()) {
|
||||
assert false : describe(Thread.currentThread());
|
||||
}
|
||||
try {
|
||||
action.run();
|
||||
}
|
||||
@@ -427,6 +454,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
finally {
|
||||
//ReflectionUtil.resetThreadLocals();
|
||||
Thread.interrupted(); // reset interrupted status
|
||||
if (isReadAccessAllowed()) {
|
||||
assert false : describe(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -438,6 +468,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
return ourThreadExecutorsService.submit(new Callable<T>() {
|
||||
@Override
|
||||
public T call() {
|
||||
if (isReadAccessAllowed()) {
|
||||
assert false : describe(Thread.currentThread());
|
||||
}
|
||||
try {
|
||||
return action.call();
|
||||
}
|
||||
@@ -450,17 +483,22 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
finally {
|
||||
//ReflectionUtil.resetThreadLocals();
|
||||
Thread.interrupted(); // reset interrupted status
|
||||
if (isReadAccessAllowed()) {
|
||||
assert false : describe(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Thread ourDispatchThread = null;
|
||||
|
||||
@Override
|
||||
public boolean isDispatchThread() {
|
||||
return EventQueue.isDispatchThread();
|
||||
return isDispatchThread(getStatus());
|
||||
}
|
||||
|
||||
private static boolean isDispatchThread(Status status) {
|
||||
return BitUtil.isSet(status.flags, IS_EDT_FLAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -535,7 +573,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> T getComponentFromContainer(final Class<T> interfaceClass) {
|
||||
protected <T> T getComponentFromContainer(@NotNull final Class<T> interfaceClass) {
|
||||
if (myIsFiringLoadingEvent) {
|
||||
return null;
|
||||
}
|
||||
@@ -567,13 +605,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
Disposer.dispose(myLastDisposable); // dispose it last
|
||||
}
|
||||
|
||||
private final Object lock = new Object();
|
||||
private void makeChangesVisibleToEDT() {
|
||||
synchronized (lock) {
|
||||
lock.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runProcessWithProgressSynchronously(@NotNull final Runnable process,
|
||||
@NotNull String progressTitle,
|
||||
@@ -629,7 +660,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
@Override
|
||||
public void run() {
|
||||
if (myExceptionalThreadWithReadAccessRunnable != process) {
|
||||
LOG.error("myExceptionalThreadWithReadAccessRunnable != process, process = " + myExceptionalThreadWithReadAccessRunnable);
|
||||
LOG.error("myExceptionalThreadWithReadAccessRunnable != process, process = " + myExceptionalThreadWithReadAccessRunnable);
|
||||
}
|
||||
|
||||
executeOnPooledThread(new Runnable() {
|
||||
@@ -639,9 +670,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
LOG.error("myExceptionalThreadWithReadAccessRunnable != process, process = " + myExceptionalThreadWithReadAccessRunnable);
|
||||
}
|
||||
|
||||
final boolean old = setExceptionalThreadWithReadAccessFlag(true);
|
||||
LOG.assertTrue(isReadAccessAllowed());
|
||||
setExceptionalThreadWithReadAccessFlag(true);
|
||||
try {
|
||||
LOG.assertTrue(isReadAccessAllowed());
|
||||
ProgressManager.getInstance().runProcess(process, progress);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
@@ -653,8 +684,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
setExceptionalThreadWithReadAccessFlag(old);
|
||||
makeChangesVisibleToEDT();
|
||||
setExceptionalThreadWithReadAccessFlag(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -669,7 +699,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
}
|
||||
finally {
|
||||
myExceptionalThreadWithReadAccessRunnable = null;
|
||||
makeChangesVisibleToEDT();
|
||||
}
|
||||
|
||||
return !progress.isCanceled();
|
||||
@@ -677,12 +706,13 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
@Override
|
||||
public void invokeAndWait(@NotNull Runnable runnable, @NotNull ModalityState modalityState) {
|
||||
if (isDispatchThread()) {
|
||||
Status status = getStatus();
|
||||
if (isDispatchThread(status)) {
|
||||
runnable.run();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isExceptionalThreadWithReadAccess() && holdsReadLock()) {
|
||||
if (!isExceptionalThreadWithReadAccess(status) && holdsReadLock(status)) {
|
||||
LOG.error("Calling invokeAndWait from read-action leads to possible deadlock.");
|
||||
}
|
||||
|
||||
@@ -712,13 +742,11 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
@Override
|
||||
@NotNull
|
||||
public ModalityState getDefaultModalityState() {
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
if (isDispatchThread()) {
|
||||
return getCurrentModalityState();
|
||||
}
|
||||
else {
|
||||
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
return progress == null ? getNoneModalityState() : progress.getModalityState();
|
||||
}
|
||||
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
return progress == null ? getNoneModalityState() : progress.getModalityState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -769,7 +797,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
private static volatile boolean exiting = false;
|
||||
|
||||
public void exit(final boolean force, final boolean allowListenersToCancel, final boolean restart) {
|
||||
|
||||
if (exiting) return;
|
||||
|
||||
exiting = true;
|
||||
@@ -788,19 +815,19 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
getMessageBus().syncPublisher(AppLifecycleListener.TOPIC).appClosing();
|
||||
myDisposeInProgress = true;
|
||||
if (!doExit(allowListenersToCancel, restart)) {
|
||||
myDisposeInProgress = false;
|
||||
}
|
||||
doExit(allowListenersToCancel, restart);
|
||||
myDisposeInProgress = false;
|
||||
}
|
||||
};
|
||||
|
||||
if (!isDispatchThread()) {
|
||||
invokeLater(runnable, ModalityState.NON_MODAL);
|
||||
}
|
||||
else {
|
||||
if (isDispatchThread()) {
|
||||
runnable.run();
|
||||
}
|
||||
} finally {
|
||||
else {
|
||||
invokeLater(runnable, ModalityState.NON_MODAL);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
exiting = false;
|
||||
}
|
||||
}
|
||||
@@ -857,6 +884,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDoNotShowMessage() {
|
||||
return "Do not ask me again";
|
||||
@@ -896,13 +924,15 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
@Override
|
||||
public void runReadAction(@NotNull final Runnable action) {
|
||||
if (isReadAccessAllowed()) {
|
||||
Status status = getStatus();
|
||||
if (isReadAccessAllowed(status)) {
|
||||
action.run();
|
||||
}
|
||||
else {
|
||||
assertReadActionAllowed();
|
||||
assertNoPsiLock();
|
||||
try {
|
||||
myLock.readLock().lockInterruptibly();
|
||||
setReadLockAcquired(status, true);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeInterruptedException(e);
|
||||
@@ -911,70 +941,66 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
action.run();
|
||||
}
|
||||
finally {
|
||||
setReadLockAcquired(status, false);
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public <T> T runReadAction(@NotNull final Computable<T> computation) {
|
||||
if (isReadAccessAllowed()) {
|
||||
Status status = getStatus();
|
||||
if (isReadAccessAllowed(status)) {
|
||||
return computation.compute();
|
||||
}
|
||||
else {
|
||||
assertReadActionAllowed();
|
||||
try {
|
||||
myLock.readLock().lockInterruptibly();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeInterruptedException(e);
|
||||
}
|
||||
try {
|
||||
return computation.compute();
|
||||
}
|
||||
finally {
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
assertNoPsiLock();
|
||||
try {
|
||||
myLock.readLock().lockInterruptibly();
|
||||
setReadLockAcquired(status, true);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeInterruptedException(e);
|
||||
}
|
||||
try {
|
||||
return computation.compute();
|
||||
}
|
||||
finally {
|
||||
setReadLockAcquired(status, false);
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, E extends Throwable> T runReadAction(@NotNull ThrowableComputable<T, E> computation) throws E {
|
||||
if (isReadAccessAllowed()) {
|
||||
Status status = getStatus();
|
||||
if (isReadAccessAllowed(status)) {
|
||||
return computation.compute();
|
||||
}
|
||||
else {
|
||||
assertReadActionAllowed();
|
||||
try {
|
||||
myLock.readLock().lockInterruptibly();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeInterruptedException(e);
|
||||
}
|
||||
try {
|
||||
return computation.compute();
|
||||
}
|
||||
finally {
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
assertNoPsiLock();
|
||||
try {
|
||||
myLock.readLock().lockInterruptibly();
|
||||
setReadLockAcquired(status, true);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeInterruptedException(e);
|
||||
}
|
||||
try {
|
||||
return computation.compute();
|
||||
}
|
||||
finally {
|
||||
setReadLockAcquired(status, false);
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static final ThreadLocal<Boolean> exceptionalThreadWithReadAccessFlag = new ThreadLocal<Boolean>();
|
||||
|
||||
private static boolean isExceptionalThreadWithReadAccess() {
|
||||
Boolean flag = exceptionalThreadWithReadAccessFlag.get();
|
||||
return flag == Boolean.TRUE;
|
||||
private static boolean isExceptionalThreadWithReadAccess(Status status) {
|
||||
return BitUtil.isSet(status.flags, IS_EXCEPTIONAL_THREAD_FLAG);
|
||||
}
|
||||
|
||||
public static boolean setExceptionalThreadWithReadAccessFlag(boolean flag) {
|
||||
boolean old = isExceptionalThreadWithReadAccess();
|
||||
if (flag) {
|
||||
exceptionalThreadWithReadAccessFlag.set(Boolean.TRUE);
|
||||
}
|
||||
else {
|
||||
exceptionalThreadWithReadAccessFlag.remove();
|
||||
}
|
||||
return old;
|
||||
public static void setExceptionalThreadWithReadAccessFlag(boolean flag) {
|
||||
Status status = getStatus();
|
||||
assert !isDispatchThread(status) : "exceptional thread must not be EDT";
|
||||
assert flag != isReadAccessAllowed(status) : "must not start exceptional thread from inside read action";
|
||||
status.flags = BitUtil.set(status.flags, IS_EXCEPTIONAL_THREAD_FLAG, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1012,7 +1038,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
@Override
|
||||
public boolean hasWriteAction(@Nullable Class<?> actionClass) {
|
||||
assertCanRunWriteAction();
|
||||
assertCanRunWriteAction(getStatus());
|
||||
|
||||
for (int i = myWriteActionsStack.size() - 1; i >= 0; i--) {
|
||||
Class action = myWriteActionsStack.get(i);
|
||||
@@ -1028,7 +1054,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
LOG.error(
|
||||
"Read access is allowed from event dispatch thread or inside read-action only" +
|
||||
" (see com.intellij.openapi.application.Application.runReadAction())",
|
||||
"Current thread: " + describe(Thread.currentThread()), "Our dispatch thread:" + describe(ourDispatchThread),
|
||||
"Current thread: " + describe(Thread.currentThread()), "; dispatch thread: " + EventQueue.isDispatchThread() +"; isDispatchThread(): "+isDispatchThread(),
|
||||
"SystemEventQueueThread: " + describe(getEventQueueThread()));
|
||||
}
|
||||
}
|
||||
@@ -1039,7 +1065,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
return o + " " + System.identityHashCode(o);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Thread getEventQueueThread() {
|
||||
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
||||
try {
|
||||
@@ -1047,63 +1072,63 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
method.setAccessible(true);
|
||||
return (Thread)method.invoke(eventQueue);
|
||||
}
|
||||
catch (Exception e1) {
|
||||
// ok
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadAccessAllowed() {
|
||||
Thread currentThread = Thread.currentThread();
|
||||
return ourDispatchThread == currentThread ||
|
||||
isExceptionalThreadWithReadAccess() ||
|
||||
holdsReadLock() ||
|
||||
isDispatchThread();
|
||||
return isReadAccessAllowed(getStatus());
|
||||
}
|
||||
|
||||
private static void assertCanRunWriteAction() {
|
||||
assertIsDispatchThread("Write access is allowed from event dispatch thread only");
|
||||
private static boolean isReadAccessAllowed(Status status) {
|
||||
return (status.flags & (IS_EDT_FLAG | IS_EXCEPTIONAL_THREAD_FLAG | IS_READ_LOCK_ACQUIRED_FLAG)) != 0;
|
||||
}
|
||||
|
||||
private static void assertCanRunWriteAction(Status status) {
|
||||
assertIsDispatchThread(status, "Write access is allowed from event dispatch thread only");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertIsDispatchThread() {
|
||||
if (ShutDownTracker.isShutdownHookRunning()) return;
|
||||
Integer safeCounter = ourEdtSafe.get();
|
||||
if (safeCounter != null && safeCounter > 0) return;
|
||||
assertIsDispatchThread("Access is allowed from event dispatch thread only.");
|
||||
assertIsDispatchThread(getStatus());
|
||||
}
|
||||
|
||||
private static void assertIsDispatchThread(@NotNull String message) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
if (ourDispatchThread == currentThread) return;
|
||||
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
ourDispatchThread = currentThread;
|
||||
private static void assertIsDispatchThread(Status status) {
|
||||
if (isDispatchThread(status)) return;
|
||||
if (ShutDownTracker.isShutdownHookRunning()) return;
|
||||
int safeCounter = getSafeCounter(status);
|
||||
if (safeCounter == 0) {
|
||||
assertIsDispatchThread(status, "Access is allowed from event dispatch thread only.");
|
||||
}
|
||||
if (ourDispatchThread == currentThread) return;
|
||||
}
|
||||
|
||||
private static int getSafeCounter(Status status) {
|
||||
return status.flags & 0x1fffffff;
|
||||
}
|
||||
|
||||
private static void assertIsDispatchThread(Status status, @NotNull String message) {
|
||||
if (isDispatchThread(status)) return;
|
||||
LOG.error(message,
|
||||
"EventQueue.isDispatchThread()="+EventQueue.isDispatchThread(),
|
||||
"isDispatchThread()="+isDispatchThread(getStatus()),
|
||||
"Toolkit.getEventQueue()="+Toolkit.getDefaultToolkit().getSystemEventQueue(),
|
||||
"Current thread: " + describe(Thread.currentThread()),
|
||||
"Our dispatch thread:" + describe(ourDispatchThread),
|
||||
"SystemEventQueueThread: " + describe(getEventQueueThread()));
|
||||
"SystemEventQueueThread: " + describe(getEventQueueThread()) +"\n"+ ThreadDumper.dumpThreadsToString()+"\n-----------");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runEdtSafeAction(@NotNull Runnable runnable) {
|
||||
Integer value = ourEdtSafe.get();
|
||||
if (value == null) {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
ourEdtSafe.set(value + 1);
|
||||
Status status = getStatus();
|
||||
LOG.assertTrue(getSafeCounter(status) < 1<<26);
|
||||
status.flags++;
|
||||
|
||||
try {
|
||||
runnable.run();
|
||||
}
|
||||
finally {
|
||||
int newValue = ourEdtSafe.get() - 1;
|
||||
ourEdtSafe.set(newValue >= 1 ? newValue : null);
|
||||
status.flags--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1111,19 +1136,19 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
public void assertIsDispatchThread(@Nullable final JComponent component) {
|
||||
if (component == null) return;
|
||||
|
||||
Thread curThread = Thread.currentThread();
|
||||
if (ourDispatchThread == curThread) {
|
||||
Status status = getStatus();
|
||||
if (isDispatchThread(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Boolean.TRUE.equals(component.getClientProperty(WAS_EVER_SHOWN))) {
|
||||
assertIsDispatchThread();
|
||||
assertIsDispatchThread(status);
|
||||
}
|
||||
else {
|
||||
final JRootPane root = component.getRootPane();
|
||||
if (root != null) {
|
||||
component.putClientProperty(WAS_EVER_SHOWN, Boolean.TRUE);
|
||||
assertIsDispatchThread();
|
||||
assertIsDispatchThread(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1136,14 +1161,16 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
@Override
|
||||
public boolean tryRunReadAction(@NotNull Runnable action) {
|
||||
//if we are inside read action, do not try to acquire read lock again since it will deadlock if there is a pending writeAction
|
||||
boolean mustAcquire = !isReadAccessAllowed();
|
||||
Status status = getStatus();
|
||||
//if we are inside read action, do not try to acquire read lock again since it will deadlock if there is a pending writeAction
|
||||
boolean mustAcquire = !isReadAccessAllowed(status);
|
||||
|
||||
if (mustAcquire) {
|
||||
LOG.assertTrue(myTestModeFlag || !Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing readAction");
|
||||
assertNoPsiLock();
|
||||
try {
|
||||
// timed version of tryLock() respects fairness unlike the no-args method
|
||||
if (!myLock.readLock().tryLock(0, TimeUnit.MILLISECONDS)) return false;
|
||||
setReadLockAcquired(status, true);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new RuntimeInterruptedException(e);
|
||||
@@ -1155,6 +1182,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
}
|
||||
finally {
|
||||
if (mustAcquire) {
|
||||
setReadLockAcquired(status, false);
|
||||
myLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
@@ -1167,7 +1195,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
if (frame instanceof IdeFrame) {
|
||||
final IdeFrame ideFrame = (IdeFrame)frame;
|
||||
if (isActive() != active) {
|
||||
myActive = Boolean.valueOf(active);
|
||||
myActive = active;
|
||||
System.setProperty("idea.active", myActive.toString());
|
||||
ApplicationActivationListener publisher = getMessageBus().syncPublisher(ApplicationActivationListener.TOPIC);
|
||||
if (active) {
|
||||
@@ -1198,10 +1226,11 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
@NotNull
|
||||
@Override
|
||||
public AccessToken acquireReadActionLock() {
|
||||
Status status = getStatus();
|
||||
// if we are inside read action, do not try to acquire read lock again since it will deadlock if there is a pending writeAction
|
||||
if (isReadAccessAllowed()) return AccessToken.EMPTY_ACCESS_TOKEN;
|
||||
if (isReadAccessAllowed(status)) return AccessToken.EMPTY_ACCESS_TOKEN;
|
||||
|
||||
return new ReadAccessToken();
|
||||
return new ReadAccessToken(status);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -1215,13 +1244,16 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
public WriteAccessToken(Class _clazz) {
|
||||
clazz = _clazz;
|
||||
assertCanRunWriteAction();
|
||||
assertCanRunWriteAction(getStatus());
|
||||
|
||||
ActivityTracker.getInstance().inc();
|
||||
fireBeforeWriteActionStart(_clazz);
|
||||
final AtomicBoolean stopped = new AtomicBoolean(false);
|
||||
|
||||
LOG.assertTrue(isWriteAccessAllowed() || !Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing writeAction");
|
||||
if (!isWriteAccessAllowed()) {
|
||||
assertNoPsiLock();
|
||||
}
|
||||
|
||||
try {
|
||||
if (!myLock.writeLock().tryLock()) {
|
||||
if (ourDumpThreadsOnLongWriteActionWaiting > 0) {
|
||||
@@ -1304,10 +1336,14 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
}
|
||||
|
||||
private class ReadAccessToken extends AccessToken {
|
||||
private ReadAccessToken() {
|
||||
assertReadActionAllowed();
|
||||
private final Status myStatus;
|
||||
|
||||
private ReadAccessToken(Status status) {
|
||||
myStatus = status;
|
||||
assertNoPsiLock();
|
||||
try {
|
||||
myLock.readLock().lockInterruptibly();
|
||||
setReadLockAcquired(myStatus, true);
|
||||
acquired();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
@@ -1317,13 +1353,18 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
setReadLockAcquired(myStatus, false);
|
||||
myLock.readLock().unlock();
|
||||
released();
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertReadActionAllowed() {
|
||||
LOG.assertTrue(!Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing readAction");
|
||||
private final boolean myExtraChecks = isUnitTestMode();
|
||||
|
||||
private void assertNoPsiLock() {
|
||||
if (myExtraChecks) {
|
||||
LOG.assertTrue(!Thread.holdsLock(PsiLock.LOCK), "Thread must not hold PsiLock while performing readAction");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1334,12 +1375,12 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
|
||||
@Override
|
||||
public boolean isWriteAccessAllowed() {
|
||||
return myLock.writeLock().isHeldByCurrentThread();
|
||||
return myLock.isWriteLockedByCurrentThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteActionInProgress() {
|
||||
return myLock.writeLock().getHoldCount() != 0;
|
||||
return myLock.getWriteHoldCount() != 0;
|
||||
}
|
||||
|
||||
public void editorPaintStart() {
|
||||
|
||||
+5
@@ -190,5 +190,10 @@ public class ServiceManagerImpl implements BaseComponent {
|
||||
public String getAssignableToClassName() {
|
||||
return myDescriptor.getInterface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServiceComponentAdapter[" + myDescriptor.getInterface() + "]: implementation=" + myDescriptor.getImplementation() + ", plugin=" + myPluginDescriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,12 @@ import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.editor.impl.AbstractEditorTest;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManagerImpl;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.testFramework.LeakHunter;
|
||||
import com.intellij.testFramework.TestFileType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.picocontainer.ComponentAdapter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -69,6 +71,12 @@ public class BookmarkManagerTest extends AbstractEditorTest {
|
||||
}
|
||||
|
||||
public void testBookmarkLineRemove() throws IOException {
|
||||
List<ComponentAdapter> adapters = getProject().getPicoContainer().getComponentAdaptersOfType(ChangeListManagerImpl.class);
|
||||
System.out.println(adapters.size() + " adapters:");
|
||||
for (ComponentAdapter adapter : adapters) {
|
||||
System.out.println(adapter);
|
||||
}
|
||||
|
||||
@NonNls String text =
|
||||
"public class Test {\n" +
|
||||
" public void test() {\n" +
|
||||
|
||||
@@ -19,13 +19,10 @@ import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.diagnostic.PerformanceWatcher;
|
||||
import com.intellij.mock.MockApplication;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.command.impl.StartMarkAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.impl.DocumentImpl;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -38,14 +35,10 @@ import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSchemes;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.refactoring.rename.PsiElementRenameHandler;
|
||||
import com.intellij.refactoring.rename.RenameHandler;
|
||||
import com.intellij.refactoring.rename.RenameHandlerRegistry;
|
||||
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
|
||||
import com.intellij.rt.execution.junit.FileComparisonFailure;
|
||||
import com.intellij.testFramework.exceptionCases.AbstractExceptionCase;
|
||||
@@ -64,6 +57,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.junit.Assert;
|
||||
|
||||
import javax.swing.Timer;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -75,6 +69,9 @@ import java.lang.reflect.Modifier;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.DelayQueue;
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@@ -178,13 +175,14 @@ public abstract class UsefulTestCase extends TestCase {
|
||||
private static final Set<String> DELETE_ON_EXIT_HOOK_DOT_FILES;
|
||||
private static final Class DELETE_ON_EXIT_HOOK_CLASS;
|
||||
static {
|
||||
Class<?> aClass = null;
|
||||
Set<String> files = null;
|
||||
Class<?> aClass;
|
||||
try {
|
||||
aClass = Class.forName("java.io.DeleteOnExitHook");
|
||||
files = ReflectionUtil.getField(aClass, null, Set.class, "files");
|
||||
}
|
||||
catch (Exception ignored) { }
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Set<String> files = ReflectionUtil.getField(aClass, null, Set.class, "files");
|
||||
DELETE_ON_EXIT_HOOK_CLASS = aClass;
|
||||
DELETE_ON_EXIT_HOOK_DOT_FILES = files;
|
||||
}
|
||||
@@ -777,26 +775,51 @@ public abstract class UsefulTestCase extends TestCase {
|
||||
}
|
||||
|
||||
protected static void checkAllTimersAreDisposed() {
|
||||
Field firstTimerF;
|
||||
Object timerQueue;
|
||||
Object timer;
|
||||
try {
|
||||
Class<?> aClass = Class.forName("javax.swing.TimerQueue");
|
||||
Class<?> TimerQueueC = Class.forName("javax.swing.TimerQueue");
|
||||
Method sharedInstance = TimerQueueC.getDeclaredMethod("sharedInstance");
|
||||
sharedInstance.setAccessible(true);
|
||||
|
||||
Method inst = aClass.getDeclaredMethod("sharedInstance");
|
||||
inst.setAccessible(true);
|
||||
Object queue = inst.invoke(null);
|
||||
Field field = aClass.getDeclaredField("firstTimer");
|
||||
field.setAccessible(true);
|
||||
Object firstTimer = field.get(queue);
|
||||
if (firstTimer != null) {
|
||||
try {
|
||||
fail("Not disposed Timer: " + firstTimer.toString() + "; queue:" + queue);
|
||||
}
|
||||
finally {
|
||||
field.set(queue, null);
|
||||
}
|
||||
firstTimerF = ReflectionUtil.getDeclaredField(TimerQueueC, "firstTimer");
|
||||
timerQueue = sharedInstance.invoke(null);
|
||||
if (firstTimerF == null) {
|
||||
// jdk 8
|
||||
DelayQueue delayQueue = ReflectionUtil.getField(TimerQueueC, timerQueue, DelayQueue.class, "queue");
|
||||
timer = delayQueue.peek();
|
||||
}
|
||||
else {
|
||||
// ancient jdk
|
||||
firstTimerF.setAccessible(true);
|
||||
timer = firstTimerF.get(timerQueue);
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {
|
||||
// Ignore
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (timer != null) {
|
||||
if (firstTimerF != null) {
|
||||
ReflectionUtil.resetField(timerQueue, firstTimerF);
|
||||
}
|
||||
String text = "";
|
||||
if (timer instanceof Delayed) {
|
||||
long delay = ((Delayed)timer).getDelay(TimeUnit.MILLISECONDS);
|
||||
text = "(delayed for "+delay+"ms)";
|
||||
Method getTimer = ReflectionUtil.getDeclaredMethod(timer.getClass(), "getTimer");
|
||||
getTimer.setAccessible(true);
|
||||
try {
|
||||
timer = getTimer.invoke(timer);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
Timer t = (Timer)timer;
|
||||
text = "Timer (listeners: "+Arrays.asList(t.getActionListeners()) + ") "+text;
|
||||
|
||||
fail("Not disposed Timer: " + text + "; queue:" + timerQueue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -886,12 +909,11 @@ public abstract class UsefulTestCase extends TestCase {
|
||||
while (aClass != null && aClass != Object.class) {
|
||||
if (aClass.getAnnotation(annotationClass) != null) return true;
|
||||
if (!methodChecked) {
|
||||
try {
|
||||
Method method = aClass.getDeclaredMethod(methodName);
|
||||
Method method = ReflectionUtil.getDeclaredMethod(aClass, methodName);
|
||||
if (method != null) {
|
||||
if (method.getAnnotation(annotationClass) != null) return true;
|
||||
methodChecked = true;
|
||||
}
|
||||
catch (NoSuchMethodException ignored) { }
|
||||
}
|
||||
aClass = aClass.getSuperclass();
|
||||
}
|
||||
|
||||
@@ -272,6 +272,16 @@ public class ReflectionUtil {
|
||||
return findMethod(getClassDeclaredMethods(aClass, false), name, parameters);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Field getDeclaredField(@NotNull Class aClass, @NonNls @NotNull final String name) {
|
||||
return processFields(aClass, new Condition<Field>() {
|
||||
@Override
|
||||
public boolean value(Field field) {
|
||||
return name.equals(field.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static List<Method> getClassPublicMethods(@NotNull Class aClass) {
|
||||
return getClassPublicMethods(aClass, false);
|
||||
}
|
||||
@@ -284,11 +294,17 @@ public class ReflectionUtil {
|
||||
public static List<Method> getClassDeclaredMethods(@NotNull Class aClass) {
|
||||
return getClassDeclaredMethods(aClass, false);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public static List<Method> getClassDeclaredMethods(@NotNull Class aClass, boolean includeSynthetic) {
|
||||
Method[] methods = aClass.getDeclaredMethods();
|
||||
return includeSynthetic ? Arrays.asList(methods) : filterRealMethods(methods);
|
||||
}
|
||||
@NotNull
|
||||
public static List<Field> getClassDeclaredFields(@NotNull Class aClass) {
|
||||
Field[] fields = aClass.getDeclaredFields();
|
||||
return Arrays.asList(fields);
|
||||
}
|
||||
|
||||
private static List<Method> filterRealMethods(Method[] methods) {
|
||||
List<Method> result = ContainerUtil.newArrayList();
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.util.messages.impl;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
@@ -39,6 +35,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class MessageBusImpl implements MessageBus {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.messages.impl.MessageBusImpl");
|
||||
private static final Comparator<MessageBusImpl> MESSAGE_BUS_COMPARATOR = new Comparator<MessageBusImpl>() {
|
||||
@@ -224,7 +223,7 @@ public class MessageBusImpl implements MessageBus {
|
||||
}
|
||||
|
||||
private void checkNotDisposed() {
|
||||
LOG.assertTrue(!myDisposed, "Already disposed: " + myOwner);
|
||||
if (myDisposed) LOG.error("Already disposed: " + myOwner);
|
||||
}
|
||||
|
||||
private void calcSubscribers(Topic topic, List<MessageBusConnectionImpl> result) {
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.diff.FilesTooBigForDiffException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -50,14 +51,14 @@ import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* author: lesya
|
||||
* author: lesya
|
||||
*/
|
||||
public class LineStatusTracker {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.ex.LineStatusTracker");
|
||||
private static final Key<CanNotCalculateDiffPanel> PANEL_KEY = new Key<CanNotCalculateDiffPanel>("LineStatusTracker.CanNotCalculateDiffPanel");
|
||||
private static final Key<CanNotCalculateDiffPanel> PANEL_KEY =
|
||||
new Key<CanNotCalculateDiffPanel>("LineStatusTracker.CanNotCalculateDiffPanel");
|
||||
|
||||
private final Object myLock = new Object();
|
||||
// true -> have contents
|
||||
private BaseLoadState myBaseLoaded;
|
||||
|
||||
private final Document myDocument;
|
||||
@@ -71,15 +72,17 @@ public class LineStatusTracker {
|
||||
|
||||
private boolean myBulkUpdate;
|
||||
private final Application myApplication;
|
||||
@Nullable
|
||||
private RevisionPack myBaseRevisionNumber;
|
||||
@Nullable private RevisionPack myBaseRevisionNumber;
|
||||
private String myPreviousBaseRevision;
|
||||
private boolean myAnathemaThrown;
|
||||
private FileEditorManager myFileEditorManager;
|
||||
private final VirtualFile myVirtualFile;
|
||||
private boolean myReleased = false;
|
||||
|
||||
private LineStatusTracker(final Document document, final Document upToDateDocument, final Project project, final VirtualFile virtualFile) {
|
||||
private LineStatusTracker(@NotNull final Document document,
|
||||
@NotNull final Document upToDateDocument,
|
||||
final Project project,
|
||||
@Nullable final VirtualFile virtualFile) {
|
||||
myVirtualFile = virtualFile;
|
||||
myApplication = ApplicationManager.getApplication();
|
||||
myDocument = document;
|
||||
@@ -156,7 +159,7 @@ public class LineStatusTracker {
|
||||
}
|
||||
|
||||
private void removeAnathema() {
|
||||
if (! myAnathemaThrown) return;
|
||||
if (!myAnathemaThrown) return;
|
||||
myAnathemaThrown = false;
|
||||
final FileEditor[] editors = myFileEditorManager.getEditors(myVirtualFile);
|
||||
for (FileEditor editor : editors) {
|
||||
@@ -286,8 +289,6 @@ public class LineStatusTracker {
|
||||
|
||||
private class MyDocumentListener extends DocumentAdapter {
|
||||
private int myFirstChangedLine;
|
||||
private int myUpToDateFirstLine;
|
||||
private int myUpToDateLastLine;
|
||||
private int myLastChangedLine;
|
||||
private int myLinesBeforeChange;
|
||||
private final VcsDirtyScopeManager myVcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
|
||||
@@ -302,50 +303,14 @@ public class LineStatusTracker {
|
||||
try {
|
||||
myFirstChangedLine = myDocument.getLineNumber(e.getOffset());
|
||||
myLastChangedLine = myDocument.getLineNumber(e.getOffset() + e.getOldLength());
|
||||
myLinesBeforeChange = myLastChangedLine - myFirstChangedLine;
|
||||
if (StringUtil.endsWithChar(e.getOldFragment(), '\n')) myLastChangedLine++;
|
||||
|
||||
myLinesBeforeChange = myDocument.getLineNumber(e.getOffset() + e.getOldLength()) - myDocument.getLineNumber(e.getOffset());
|
||||
|
||||
Range firstChangedRange = getLastRangeBeforeLine(myFirstChangedLine);
|
||||
|
||||
if (firstChangedRange == null) {
|
||||
myUpToDateFirstLine = myFirstChangedLine;
|
||||
}
|
||||
else if (firstChangedRange.containsLine(myFirstChangedLine)) {
|
||||
myFirstChangedLine = firstChangedRange.getOffset1();
|
||||
myUpToDateFirstLine = firstChangedRange.getUOffset1();
|
||||
}
|
||||
else {
|
||||
myUpToDateFirstLine = firstChangedRange.getUOffset2() + myFirstChangedLine - firstChangedRange.getOffset2();
|
||||
}
|
||||
|
||||
Range myLastChangedRange = getLastRangeBeforeLine(myLastChangedLine);
|
||||
|
||||
if (myLastChangedRange == null) {
|
||||
myUpToDateLastLine = myLastChangedLine;
|
||||
}
|
||||
else if (myLastChangedRange.containsLine(myLastChangedLine)) {
|
||||
myUpToDateLastLine = myLastChangedRange.getUOffset2();
|
||||
myLastChangedLine = myLastChangedRange.getOffset2();
|
||||
}
|
||||
else {
|
||||
myUpToDateLastLine = myLastChangedRange.getUOffset2() + myLastChangedLine - myLastChangedRange.getOffset2();
|
||||
}
|
||||
} catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Range getLastRangeBeforeLine(int line) {
|
||||
Range result = null;
|
||||
for (Range range : myRanges) {
|
||||
if (range.isAfter(line)) return result;
|
||||
result = range;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void documentChanged(final DocumentEvent e) {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
@@ -354,27 +319,40 @@ public class LineStatusTracker {
|
||||
if (myReleased) return;
|
||||
if (myBulkUpdate || myAnathemaThrown || BaseLoadState.LOADED != myBaseLoaded) return;
|
||||
try {
|
||||
int upToDateFirstLine;
|
||||
int upToDateLastLine;
|
||||
|
||||
int line = myDocument.getLineNumber(e.getOffset() + e.getNewLength());
|
||||
int linesAfterChange = line - myDocument.getLineNumber(e.getOffset());
|
||||
int linesAfterChange = myDocument.getLineNumber(e.getOffset() + e.getNewLength()) - myDocument.getLineNumber(e.getOffset());
|
||||
int linesShift = linesAfterChange - myLinesBeforeChange;
|
||||
|
||||
List<Range> rangesAfterChange = getRangesAfter(myRanges, myLastChangedLine);
|
||||
List<Range> rangesBeforeChange = getRangesBefore(myRanges, myFirstChangedLine);
|
||||
List<Range> rangesBeforeChange = new ArrayList<Range>();
|
||||
List<Range> rangesAfterChange = new ArrayList<Range>();
|
||||
List<Range> changedRanges = new ArrayList<Range>();
|
||||
sortRanges(myRanges, myFirstChangedLine, myLastChangedLine, rangesBeforeChange, changedRanges, rangesAfterChange);
|
||||
|
||||
List<Range> changedRanges = getChangedRanges(myFirstChangedLine, myLastChangedLine);
|
||||
Range firstChangedRange = ContainerUtil.getFirstItem(changedRanges);
|
||||
Range lastChangedRange = ContainerUtil.getLastItem(changedRanges);
|
||||
Range lastRangeBefore = ContainerUtil.getLastItem(rangesBeforeChange);
|
||||
|
||||
int newSize = rangesBeforeChange.size() + changedRanges.size() + rangesAfterChange.size();
|
||||
if (myRanges.size() != newSize) {
|
||||
LOG.info("Ranges: " + myRanges + "; first changed line: " + myFirstChangedLine + "; last changed line: " + myLastChangedLine);
|
||||
LOG.assertTrue(false);
|
||||
if (firstChangedRange != null && firstChangedRange.getOffset1() < myFirstChangedLine) {
|
||||
myFirstChangedLine = firstChangedRange.getOffset1();
|
||||
}
|
||||
if (lastChangedRange != null && lastChangedRange.getOffset2() > myLastChangedLine) {
|
||||
myLastChangedLine = lastChangedRange.getOffset2();
|
||||
}
|
||||
|
||||
upToDateFirstLine = getUpToDateLine(lastRangeBefore, myFirstChangedLine);
|
||||
|
||||
if (lastChangedRange == null) {
|
||||
upToDateLastLine = getUpToDateLine(lastRangeBefore, myLastChangedLine);
|
||||
}
|
||||
else {
|
||||
upToDateLastLine = getUpToDateLine(lastChangedRange, myLastChangedLine);
|
||||
}
|
||||
|
||||
myLastChangedLine += linesShift;
|
||||
|
||||
|
||||
List<Range> newChangedRanges = getNewChangedRanges();
|
||||
List<Range> newChangedRanges = getNewChangedRanges(upToDateFirstLine, upToDateLastLine);
|
||||
|
||||
shiftRanges(rangesAfterChange, linesShift);
|
||||
|
||||
@@ -410,22 +388,28 @@ public class LineStatusTracker {
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (ProcessCanceledException ignore) {
|
||||
} catch (FilesTooBigForDiffException e1) {
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
catch (FilesTooBigForDiffException e1) {
|
||||
installAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Range> getNewChangedRanges() throws FilesTooBigForDiffException {
|
||||
List<String> lines = new DocumentWrapper(myDocument).getLines(myFirstChangedLine, myLastChangedLine);
|
||||
List<String> uLines = new DocumentWrapper(myUpToDateDocument)
|
||||
.getLines(myUpToDateFirstLine, myUpToDateLastLine);
|
||||
return new RangesBuilder(lines, uLines, myFirstChangedLine, myUpToDateFirstLine).getRanges();
|
||||
private int getUpToDateLine(@Nullable Range range, int line) {
|
||||
return range == null ? line : line + range.getUOffset2() - range.getOffset2();
|
||||
}
|
||||
|
||||
private List<Range> mergeRanges(List<Range> ranges) {
|
||||
private List<Range> getNewChangedRanges(int upToDateFirstLine, int upToDateLastLine) throws FilesTooBigForDiffException {
|
||||
List<String> lines = new DocumentWrapper(myDocument).getLines(myFirstChangedLine, myLastChangedLine);
|
||||
List<String> uLines = new DocumentWrapper(myUpToDateDocument).getLines(upToDateFirstLine, upToDateLastLine);
|
||||
return new RangesBuilder(lines, uLines, myFirstChangedLine, upToDateFirstLine).getRanges();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<Range> mergeRanges(@NotNull List<Range> ranges) {
|
||||
ArrayList<Range> result = new ArrayList<Range>();
|
||||
Iterator<Range> iterator = ranges.iterator();
|
||||
if (!iterator.hasNext()) return result;
|
||||
@@ -450,9 +434,11 @@ public class LineStatusTracker {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void replaceRanges(List<Range> rangesInChange, List<Range> newRangesInChange) {
|
||||
private void replaceRanges(@NotNull List<Range> rangesInChange, @NotNull List<Range> newRangesInChange) {
|
||||
for (Range range : rangesInChange) {
|
||||
range.getHighlighter().dispose();
|
||||
if (range.getHighlighter() != null) {
|
||||
range.getHighlighter().dispose();
|
||||
}
|
||||
range.setHighlighter(null);
|
||||
}
|
||||
for (Range range : newRangesInChange) {
|
||||
@@ -460,25 +446,33 @@ public class LineStatusTracker {
|
||||
}
|
||||
}
|
||||
|
||||
private void shiftRanges(List<Range> rangesAfterChange, int shift) {
|
||||
private void shiftRanges(@NotNull List<Range> rangesAfterChange, int shift) {
|
||||
for (final Range aRangesAfterChange : rangesAfterChange) {
|
||||
aRangesAfterChange.shift(shift);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<Range> getChangedRanges(int from, int to) {
|
||||
return getChangedRanges(myRanges, from, to);
|
||||
}
|
||||
|
||||
public static List<Range> getChangedRanges(List<Range> ranges, int from, int to) {
|
||||
ArrayList<Range> result = new ArrayList<Range>();
|
||||
public static void sortRanges(@NotNull List<Range> ranges,
|
||||
int firstChangedLine,
|
||||
int lastChangedLine,
|
||||
@NotNull List<Range> rangesBeforeChange,
|
||||
@NotNull List<Range> changedRanges,
|
||||
@NotNull List<Range> rangesAfterChange) {
|
||||
for (Range range : ranges) {
|
||||
if (range.getOffset1() <= to && range.getOffset2() >= from) result.add(range);
|
||||
// if (range.getOffset1() > to) break;
|
||||
int offset1 = range.getType() == Range.DELETED ? range.getOffset1() - 1 : range.getOffset1();
|
||||
int offset2 = range.getOffset2();
|
||||
|
||||
if (offset2 < firstChangedLine) {
|
||||
rangesBeforeChange.add(range);
|
||||
}
|
||||
else if (offset1 > lastChangedLine) {
|
||||
rangesAfterChange.add(range);
|
||||
}
|
||||
else {
|
||||
changedRanges.add(range);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -525,7 +519,7 @@ public class LineStatusTracker {
|
||||
return getPrevRange(currentRange);
|
||||
}
|
||||
|
||||
for (ListIterator<Range> iterator = myRanges.listIterator(myRanges.size()); iterator.hasPrevious();) {
|
||||
for (ListIterator<Range> iterator = myRanges.listIterator(myRanges.size()); iterator.hasPrevious(); ) {
|
||||
final Range range = iterator.previous();
|
||||
if (range.getOffset1() > line) {
|
||||
continue;
|
||||
@@ -536,24 +530,6 @@ public class LineStatusTracker {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Range> getRangesBefore(List<Range> ranges, int line) {
|
||||
ArrayList<Range> result = new ArrayList<Range>();
|
||||
|
||||
for (Range range : ranges) {
|
||||
if (range.getOffset2() < line) result.add(range);
|
||||
//if (range.getOffset2() > line) break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<Range> getRangesAfter(List<Range> ranges, int line) {
|
||||
ArrayList<Range> result = new ArrayList<Range>();
|
||||
for (Range range : ranges) {
|
||||
if (range.getOffset1() > line) result.add(range);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Range getRangeForLine(final int line) {
|
||||
synchronized (myLock) {
|
||||
@@ -573,25 +549,33 @@ public class LineStatusTracker {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
|
||||
synchronized (myLock) {
|
||||
TextRange currentTextRange = getCurrentTextRange(range);
|
||||
TextRange currentTextRange = getCurrentTextRangeWithMagic(range);
|
||||
|
||||
int offset1 = currentTextRange.getStartOffset();
|
||||
int offset2 = Math.min(currentTextRange.getEndOffset() + 1, myDocument.getTextLength());
|
||||
if (range.getType() == Range.INSERTED) {
|
||||
myDocument
|
||||
.replaceString(currentTextRange.getStartOffset(), Math.min(currentTextRange.getEndOffset() + 1, myDocument.getTextLength()), "");
|
||||
myDocument.replaceString(offset1, offset2, "");
|
||||
}
|
||||
else if (range.getType() == Range.DELETED) {
|
||||
String upToDateContent = getUpToDateContent(range);
|
||||
myDocument.insertString(currentTextRange.getStartOffset(), upToDateContent);
|
||||
String upToDateContent = getUpToDateContentWithMagic(range);
|
||||
myDocument.insertString(offset1, upToDateContent);
|
||||
}
|
||||
else {
|
||||
|
||||
String upToDateContent = getUpToDateContent(range);
|
||||
myDocument.replaceString(currentTextRange.getStartOffset(), Math.min(currentTextRange.getEndOffset() + 1, myDocument.getTextLength()),
|
||||
upToDateContent);
|
||||
String upToDateContent = getUpToDateContentWithMagic(range);
|
||||
myDocument.replaceString(offset1, offset2, upToDateContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getUpToDateContentWithMagic(Range range) {
|
||||
synchronized (myLock) {
|
||||
TextRange textRange = getUpToDateRangeWithMagic(range);
|
||||
final int startOffset = textRange.getStartOffset();
|
||||
final int endOffset = Math.min(textRange.getEndOffset() + 1, myUpToDateDocument.getTextLength());
|
||||
return myUpToDateDocument.getCharsSequence().subSequence(startOffset, endOffset).toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String getUpToDateContent(Range range) {
|
||||
synchronized (myLock) {
|
||||
TextRange textRange = getUpToDateRange(range);
|
||||
@@ -605,25 +589,28 @@ public class LineStatusTracker {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
TextRange getCurrentTextRange(Range range) {
|
||||
return getRange(range.getType(), range.getOffset1(), range.getOffset2(), Range.DELETED, myDocument, false);
|
||||
@NotNull
|
||||
TextRange getCurrentTextRangeWithMagic(@NotNull Range range) {
|
||||
return getRangeWithMagic(range.getType(), range.getOffset1(), range.getOffset2(), Range.DELETED, myDocument);
|
||||
}
|
||||
|
||||
TextRange getUpToDateRange(Range range) {
|
||||
return getRange(range.getType(), range.getUOffset1(), range.getUOffset2(), Range.INSERTED, myUpToDateDocument, false);
|
||||
@NotNull
|
||||
TextRange getUpToDateRangeWithMagic(@NotNull Range range) {
|
||||
return getRangeWithMagic(range.getType(), range.getUOffset1(), range.getUOffset2(), Range.INSERTED, myUpToDateDocument);
|
||||
}
|
||||
|
||||
TextRange getCurrentTextRangeWithEndSymbol(Range range) {
|
||||
return getRange(range.getType(), range.getOffset1(), range.getOffset2(), Range.DELETED, myDocument, true);
|
||||
@NotNull
|
||||
TextRange getCurrentTextRange(@NotNull Range range) {
|
||||
return getRange(range.getType(), range.getOffset1(), range.getOffset2(), Range.DELETED, myDocument);
|
||||
}
|
||||
|
||||
// a hack
|
||||
TextRange getUpToDateRangeWithEndSymbol(Range range) {
|
||||
return getRange(range.getType(), range.getUOffset1(), range.getUOffset2(), Range.INSERTED, myUpToDateDocument, true);
|
||||
@NotNull
|
||||
TextRange getUpToDateRange(@NotNull Range range) {
|
||||
return getRange(range.getType(), range.getUOffset1(), range.getUOffset2(), Range.INSERTED, myUpToDateDocument);
|
||||
}
|
||||
|
||||
private static TextRange getRange(byte rangeType, int offset1, int offset2, byte emptyRangeCondition, Document document,
|
||||
final boolean keepEnd) {
|
||||
@NotNull
|
||||
private static TextRange getRangeWithMagic(byte rangeType, int offset1, int offset2, byte emptyRangeCondition, Document document) {
|
||||
if (rangeType == emptyRangeCondition) {
|
||||
int lineStartOffset;
|
||||
if (offset1 == 0) {
|
||||
@@ -634,23 +621,33 @@ public class LineStatusTracker {
|
||||
}
|
||||
//if (lineStartOffset > 0) lineStartOffset--;
|
||||
return new TextRange(lineStartOffset, lineStartOffset);
|
||||
|
||||
}
|
||||
else {
|
||||
int startOffset = document.getLineStartOffset(offset1);
|
||||
int endOffset = document.getLineEndOffset(offset2 - 1);
|
||||
if (startOffset > 0) {
|
||||
-- startOffset;
|
||||
if (! keepEnd) {
|
||||
-- endOffset;
|
||||
}
|
||||
--startOffset;
|
||||
--endOffset;
|
||||
}
|
||||
return new TextRange(startOffset, endOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public static LineStatusTracker createOn(@Nullable VirtualFile virtualFile, final Document doc, final Project project) {
|
||||
final Document document = new DocumentImpl("",true);
|
||||
@NotNull
|
||||
private static TextRange getRange(byte rangeType, int offset1, int offset2, byte emptyRangeCondition, Document document) {
|
||||
if (rangeType == emptyRangeCondition) {
|
||||
int lineStartOffset = offset1 < document.getLineCount() ? document.getLineStartOffset(offset1) : document.getTextLength();
|
||||
return new TextRange(lineStartOffset, lineStartOffset);
|
||||
}
|
||||
else {
|
||||
int startOffset = document.getLineStartOffset(offset1);
|
||||
int endOffset = document.getLineEndOffset(offset2 - 1);
|
||||
return new TextRange(startOffset, endOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public static LineStatusTracker createOn(@Nullable VirtualFile virtualFile, @NotNull final Document doc, final Project project) {
|
||||
final Document document = new DocumentImpl("", true);
|
||||
return new LineStatusTracker(doc, document, project, virtualFile);
|
||||
}
|
||||
|
||||
|
||||
@@ -154,22 +154,4 @@ public class Range {
|
||||
public RangeHighlighter getHighlighter() {
|
||||
return myRangeHighlighter;
|
||||
}
|
||||
|
||||
public boolean contains(int offset1, int offset2) {
|
||||
return getOffset1() <= offset1 && getOffset2() >= offset2;
|
||||
}
|
||||
|
||||
public boolean containsLine(int line) {
|
||||
if (myType == DELETED) return (myOffset1 - 1) <= line
|
||||
&& (myOffset2) >= line;
|
||||
return myOffset1 <= line && myOffset2 >= line;
|
||||
}
|
||||
|
||||
public boolean isAfter(int line) {
|
||||
if (myType == DELETED)
|
||||
return (getOffset1() - 1) > line;
|
||||
else
|
||||
return getOffset1() > line;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -56,10 +56,10 @@ public class ShowLineStatusRangeDiffAction extends BaseLineStatusRangeAction {
|
||||
public DiffContent[] getContents() {
|
||||
return new DiffContent[]{
|
||||
createDiffContent(myLineStatusTracker.getUpToDateDocument(),
|
||||
myLineStatusTracker.getUpToDateRangeWithEndSymbol(myRange),
|
||||
myLineStatusTracker.getUpToDateRange(myRange),
|
||||
null),
|
||||
createDiffContent(myLineStatusTracker.getDocument(),
|
||||
myLineStatusTracker.getCurrentTextRangeWithEndSymbol(myRange),
|
||||
myLineStatusTracker.getCurrentTextRange(myRange),
|
||||
myLineStatusTracker.getVirtualFile())};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.
|
||||
@@ -48,7 +48,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Collects information to push and performs the push.
|
||||
@@ -478,9 +478,7 @@ public final class GitPusher {
|
||||
// and don't show the dialog again if user has chosen not to ask again
|
||||
updateSettings = readUpdateSettings();
|
||||
if (!mySettings.autoUpdateIfPushRejected()) {
|
||||
final GitRejectedPushUpdateDialog dialog = new GitRejectedPushUpdateDialog(myProject, rejectedPushesForCurrentBranch.keySet(), updateSettings);
|
||||
final int exitCode = showDialogAndGetExitCode(dialog);
|
||||
updateSettings = new UpdateSettings(dialog.shouldUpdateAll(), getUpdateMethodFromDialogExitCode(exitCode));
|
||||
updateSettings = showDialogAndGetExitCode(rejectedPushesForCurrentBranch, updateSettings);
|
||||
saveUpdateSettings(updateSettings);
|
||||
}
|
||||
}
|
||||
@@ -519,20 +517,23 @@ public final class GitPusher {
|
||||
return new UpdateSettings(updateAllRoots, updateMethod);
|
||||
}
|
||||
|
||||
private int showDialogAndGetExitCode(@NotNull final GitRejectedPushUpdateDialog dialog) {
|
||||
final AtomicInteger exitCode = new AtomicInteger();
|
||||
private UpdateSettings showDialogAndGetExitCode(final Map<GitRepository, GitBranch> rejectedPushesForCurrentBranch,
|
||||
final UpdateSettings initialSettings) {
|
||||
final AtomicReference<UpdateSettings> updateSettings = new AtomicReference<UpdateSettings>();
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final GitRejectedPushUpdateDialog dialog = new GitRejectedPushUpdateDialog(myProject, rejectedPushesForCurrentBranch.keySet(), initialSettings);
|
||||
dialog.show();
|
||||
exitCode.set(dialog.getExitCode());
|
||||
}
|
||||
final int exitCode = dialog.getExitCode();
|
||||
if (exitCode != DialogWrapper.CANCEL_EXIT_CODE) {
|
||||
mySettings.setAutoUpdateIfPushRejected(dialog.shouldAutoUpdateInFuture());
|
||||
}
|
||||
updateSettings.set(new UpdateSettings(dialog.shouldUpdateAll(), getUpdateMethodFromDialogExitCode(exitCode)));
|
||||
|
||||
}
|
||||
});
|
||||
int code = exitCode.get();
|
||||
if (code != DialogWrapper.CANCEL_EXIT_CODE) {
|
||||
mySettings.setAutoUpdateIfPushRejected(dialog.shouldAutoUpdateInFuture());
|
||||
}
|
||||
return code;
|
||||
return updateSettings.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+16
@@ -15,17 +15,21 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.gradle.execution.test.runner;
|
||||
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.execution.testframework.TestConsoleProperties;
|
||||
import com.intellij.execution.testframework.TestFrameworkRunningModel;
|
||||
import com.intellij.execution.testframework.ToggleModelAction;
|
||||
import com.intellij.execution.testframework.ToggleModelActionProvider;
|
||||
import com.intellij.ide.BrowserUtil;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration;
|
||||
import com.intellij.util.config.AbstractProperty;
|
||||
import com.intellij.util.config.BooleanProperty;
|
||||
import icons.GradleIcons;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.gradle.util.GradleBundle;
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -42,6 +46,9 @@ public class OpenGradleTestResultActionProvider implements ToggleModelActionProv
|
||||
}
|
||||
|
||||
private static class MyToggleModelAction extends ToggleModelAction {
|
||||
@Nullable
|
||||
private ProjectSystemId mySystemId;
|
||||
|
||||
public MyToggleModelAction(TestConsoleProperties properties) {
|
||||
super(GradleBundle.message("gradle.test.runner.ui.tests.actions.open.gradle.report.text"),
|
||||
GradleBundle.message("gradle.test.runner.ui.tests.actions.open.gradle.report.desc"),
|
||||
@@ -50,6 +57,10 @@ public class OpenGradleTestResultActionProvider implements ToggleModelActionProv
|
||||
|
||||
@Override
|
||||
public void setModel(TestFrameworkRunningModel model) {
|
||||
final RunConfiguration runConfiguration = model.getProperties().getConfiguration();
|
||||
if(runConfiguration instanceof ExternalSystemRunConfiguration) {
|
||||
mySystemId = ((ExternalSystemRunConfiguration)runConfiguration).getSettings().getExternalSystemId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,6 +77,11 @@ public class OpenGradleTestResultActionProvider implements ToggleModelActionProv
|
||||
return reportFilePath != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisible() {
|
||||
return GradleConstants.SYSTEM_ID.equals(mySystemId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getReportFilePath() {
|
||||
final AbstractProperty.AbstractPropertyContainer properties = getProperties();
|
||||
|
||||
@@ -239,6 +239,8 @@ public class PyPIPackageUtil {
|
||||
if (connection instanceof HttpsURLConnection) {
|
||||
((HttpsURLConnection)connection).setSSLSocketFactory(sslContext.getSocketFactory());
|
||||
}
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
InputStream is = connection.getInputStream();
|
||||
Reader reader = new InputStreamReader(is);
|
||||
try{
|
||||
|
||||
@@ -15,11 +15,14 @@
|
||||
*/
|
||||
package com.jetbrains.python.psi.impl;
|
||||
|
||||
import com.intellij.facet.Facet;
|
||||
import com.intellij.facet.FacetManager;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
@@ -37,6 +40,8 @@ import com.intellij.util.containers.WeakHashMap;
|
||||
import com.intellij.util.io.DataInputOutputUtil;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.PythonModuleTypeBase;
|
||||
import com.jetbrains.python.facet.PythonFacetSettings;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -61,11 +66,13 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher<LanguageLev
|
||||
final Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
Set<Sdk> usedSdks = new HashSet<Sdk>();
|
||||
for (Module module : modules) {
|
||||
final Sdk sdk = PythonSdkType.findPythonSdk(module);
|
||||
myModuleSdks.put(module, sdk);
|
||||
if (sdk != null && !usedSdks.contains(sdk)) {
|
||||
usedSdks.add(sdk);
|
||||
updateSdkLanguageLevel(project, sdk);
|
||||
if (isPythonModule(module)) {
|
||||
final Sdk sdk = PythonSdkType.findPythonSdk(module);
|
||||
myModuleSdks.put(module, sdk);
|
||||
if (sdk != null && !usedSdks.contains(sdk)) {
|
||||
usedSdks.add(sdk);
|
||||
updateSdkLanguageLevel(project, sdk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,17 +174,19 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher<LanguageLev
|
||||
final Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
boolean needReparseOpenFiles = false;
|
||||
for (Module module : modules) {
|
||||
Sdk newSdk = PythonSdkType.findPythonSdk(module);
|
||||
if (myModuleSdks.containsKey(module)) {
|
||||
Sdk oldSdk = myModuleSdks.get(module);
|
||||
if ((newSdk != null || oldSdk != null) && newSdk != oldSdk) {
|
||||
needReparseOpenFiles = true;
|
||||
if (isPythonModule(module)) {
|
||||
Sdk newSdk = PythonSdkType.findPythonSdk(module);
|
||||
if (myModuleSdks.containsKey(module)) {
|
||||
Sdk oldSdk = myModuleSdks.get(module);
|
||||
if ((newSdk != null || oldSdk != null) && newSdk != oldSdk) {
|
||||
needReparseOpenFiles = true;
|
||||
}
|
||||
}
|
||||
myModuleSdks.put(module, newSdk);
|
||||
if (newSdk != null && !updatedSdks.contains(newSdk)) {
|
||||
updatedSdks.add(newSdk);
|
||||
updateSdkLanguageLevel(project, newSdk);
|
||||
}
|
||||
}
|
||||
myModuleSdks.put(module, newSdk);
|
||||
if (newSdk != null && !updatedSdks.contains(newSdk)) {
|
||||
updatedSdks.add(newSdk);
|
||||
updateSdkLanguageLevel(project, newSdk);
|
||||
}
|
||||
}
|
||||
if (needReparseOpenFiles) {
|
||||
@@ -185,6 +194,18 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher<LanguageLev
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPythonModule(@NotNull final Module module) {
|
||||
final ModuleType moduleType = ModuleType.get(module);
|
||||
if (moduleType instanceof PythonModuleTypeBase) return true;
|
||||
final Facet[] allFacets = FacetManager.getInstance(module).getAllFacets();
|
||||
for (Facet facet : allFacets) {
|
||||
if (facet.getConfiguration() instanceof PythonFacetSettings) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateSdkLanguageLevel(final Project project, final Sdk sdk) {
|
||||
final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
|
||||
final VirtualFile[] files = sdk.getRootProvider().getFiles(OrderRootType.CLASSES);
|
||||
@@ -240,4 +261,8 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher<LanguageLev
|
||||
LanguageLevel.FORCE_LANGUAGE_LEVEL = languageLevel;
|
||||
pushLanguageLevel(project);
|
||||
}
|
||||
|
||||
public void flushLanguageLevelCache() {
|
||||
myModuleSdks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
package com.jetbrains.python.fixtures;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.module.EmptyModuleType;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.impl.FilePropertyPusher;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -39,6 +40,7 @@ import com.intellij.testFramework.fixtures.TestFixtureBuilder;
|
||||
import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
import com.jetbrains.python.PythonMockSdk;
|
||||
import com.jetbrains.python.PythonModuleTypeBase;
|
||||
import com.jetbrains.python.PythonTestUtil;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
@@ -92,6 +94,8 @@ public abstract class PyTestCase extends UsefulTestCase {
|
||||
setLanguageLevel(null);
|
||||
myFixture.tearDown();
|
||||
myFixture = null;
|
||||
final PythonLanguageLevelPusher levelPusher = Extensions.findExtension(FilePropertyPusher.EP_NAME, PythonLanguageLevelPusher.class);
|
||||
levelPusher.flushLanguageLevelCache();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@@ -149,7 +153,7 @@ public abstract class PyTestCase extends UsefulTestCase {
|
||||
|
||||
@Override
|
||||
public ModuleType getModuleType() {
|
||||
return EmptyModuleType.getInstance();
|
||||
return PythonModuleTypeBase.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user