Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2014-06-16 14:26:04 +02:00
28 changed files with 711 additions and 487 deletions
@@ -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;
@@ -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);
@@ -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);
@@ -0,0 +1,11 @@
// "Remove redundant assignment" "true"
class Test {
void foo() {
String var;
this.bar("someString");
}
void bar(String arg) {
}
}
@@ -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();
}
}
}
@@ -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
@@ -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;
@@ -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() {
@@ -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;
}
}
@@ -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();
}
/**
@@ -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