diff --git a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
index 60b05dae04a7..aa1a1a98f93a 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
@@ -537,22 +538,20 @@ public abstract class BaseRefactoringProcessor implements Runnable {
public final void run() {
if (ApplicationManager.getApplication().isUnitTestMode()) {
ApplicationManager.getApplication().assertIsDispatchThread();
- doRun();
+ NonProjectFileWritingAccessProvider.disableChecksDuring(this::doRun);
+
+ //noinspection TestOnlyProblems
UIUtil.dispatchAllInvocationEvents();
+ //noinspection TestOnlyProblems
UIUtil.dispatchAllInvocationEvents();
return;
}
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
LOG.error("Refactorings should not be started inside write action\n because they start progress inside and any read action from the progress task would cause the deadlock", new Exception());
- DumbService.getInstance(myProject).smartInvokeLater(new Runnable() {
- @Override
- public void run() {
- doRun();
- }
- });
+ DumbService.getInstance(myProject).smartInvokeLater(() -> NonProjectFileWritingAccessProvider.disableChecksDuring(this::doRun));
}
else {
- doRun();
+ NonProjectFileWritingAccessProvider.disableChecksDuring(this::doRun);
}
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java
index ede322cb6ef4..2b1f9761b7c2 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java
@@ -142,7 +142,7 @@ public class PsiElementRenameHandler implements RenameHandler {
if (!PsiManager.getInstance(project).isInProject(element)) {
if (element.isPhysical()) {
VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element);
- if (!(virtualFile != null && NonProjectFileWritingAccessProvider.isWriteAccessAllowedExplicitly(virtualFile, project))) {
+ if (!(virtualFile != null && NonProjectFileWritingAccessProvider.isWriteAccessAllowed(virtualFile, project))) {
String message = RefactoringBundle.message("error.out.of.project.element", UsageViewUtil.getType(element));
return RefactoringBundle.getCannotRefactorMessage(message);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java b/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
index 542fb8d3f780..06bd381c3f96 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorProvider;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
+import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.ex.FileTypeChooser;
import com.intellij.openapi.project.DumbAware;
@@ -126,6 +127,8 @@ public class OpenFileAction extends AnAction implements DumbAware {
return;
}
+ NonProjectFileWritingAccessProvider.allowWriting(file);
+
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file);
FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.form b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.form
index 01173794cbeb..edb8c4e4be4e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.form
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.form
@@ -8,39 +8,48 @@
-
+
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
-
+
+
-
+
-
+
@@ -64,6 +73,7 @@
+
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.java
index 397ff73da184..79965dd52221 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessDialog.java
@@ -17,33 +17,87 @@ package com.intellij.openapi.fileEditor.impl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.readOnlyHandler.FileListRenderer;
+import com.intellij.openapi.vcs.readOnlyHandler.ReadOnlyStatusDialog;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.CollectionListModel;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
import java.util.List;
public class NonProjectFileWritingAccessDialog extends DialogWrapper {
private JPanel myPanel;
+ private JLabel myListTitle;
private JList myFileList;
+ private JRadioButton myUnlockOneButton;
+ private JRadioButton myUnlockDirButton;
private JRadioButton myUnlockAllButton;
- protected NonProjectFileWritingAccessDialog(@NotNull Project project, @NotNull List nonProjectFiles) {
- super(project);
- setTitle("Non-Project Files Access");
+ public NonProjectFileWritingAccessDialog(@NotNull Project project, @NotNull List nonProjectFiles) {
+ this(project, nonProjectFiles, "Non-Project Files");
+ }
+ public NonProjectFileWritingAccessDialog(@NotNull Project project,
+ @NotNull List nonProjectFiles,
+ @NotNull String filesType) {
+ super(project);
+ setTitle(filesType + " Protection");
+
+ myFileList.setPreferredSize(ReadOnlyStatusDialog.getDialogPreferredSize());
+
myFileList.setCellRenderer(new FileListRenderer());
myFileList.setModel(new CollectionListModel(nonProjectFiles));
+
+ String theseFilesMessage = ReadOnlyStatusDialog.getTheseFilesMessage(nonProjectFiles);
+ myListTitle.setText(StringUtil.capitalize(theseFilesMessage)
+ + " " + (nonProjectFiles.size() > 1 ? "do" : "does")
+ + " not belong to the project:");
+
+
+ myUnlockOneButton.setSelected(true);
+ setTextAndMnemonicAndListeners(myUnlockOneButton, "I want to edit " + theseFilesMessage + " anyway", "edit");
+
+ int dirs = ContainerUtil.map2Set(nonProjectFiles, VirtualFile::getParent).size();
+ setTextAndMnemonicAndListeners(myUnlockDirButton, "I want to edit all files in "
+ + StringUtil.pluralize("this", dirs)
+ + " " + StringUtil.pluralize("directory", dirs), "dir");
+
+ setTextAndMnemonicAndListeners(myUnlockAllButton, "I want to edit any non-project file in the current session", "any");
+
+ // disable default button to avoid accidental pressing, if user typed something, missed the dialog and pressed 'enter'.
getOKAction().putValue(DEFAULT_ACTION, null);
- getCancelAction().putValue(DEFAULT_ACTION, true);
-
+ getCancelAction().putValue(DEFAULT_ACTION, null);
+
+ getRootPane().registerKeyboardAction(e -> doOKAction(), KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK),
+ JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+ getRootPane().registerKeyboardAction(e -> doOKAction(), KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.META_DOWN_MASK),
+ JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
+
init();
}
+ private void setTextAndMnemonicAndListeners(JRadioButton button, String text, String mnemonic) {
+ button.setText(text);
+ button.setMnemonic(mnemonic.charAt(0));
+ button.setDisplayedMnemonicIndex(button.getText().indexOf(mnemonic));
+
+ // enabled OK button when user selects an option
+ button.addActionListener(e -> button.getRootPane().setDefaultButton(getButton(getOKAction())));
+ button.addItemListener(e -> button.getRootPane().setDefaultButton(getButton(getOKAction())));
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myUnlockOneButton;
+ }
@Nullable
@Override
@@ -53,8 +107,9 @@ public class NonProjectFileWritingAccessDialog extends DialogWrapper {
@NotNull
public NonProjectFileWritingAccessProvider.UnlockOption getUnlockOption() {
- return myUnlockAllButton.isSelected() ? NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK_ALL
- : NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK;
+ if (myUnlockAllButton.isSelected()) return NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK_ALL;
+ if (myUnlockDirButton.isSelected()) return NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK_DIR;
+ return NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK;
}
protected String getHelpId() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessExtension.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessExtension.java
index 3955916923d4..ffc0c59dc877 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessExtension.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessExtension.java
@@ -23,5 +23,17 @@ public interface NonProjectFileWritingAccessExtension {
ExtensionPointName EP_NAME =
ExtensionPointName.create("com.intellij.nonProjectFileWritingAccessExtension");
- boolean isWritable(@NotNull VirtualFile file);
+ /**
+ * @return true if the file should not be protected from accidental writing. false to use default logic.
+ */
+ default boolean isWritable(@NotNull VirtualFile file) {
+ return false;
+ }
+
+ /**
+ * @return true if the file should be protected from accidental writing. false to use default logic.
+ */
+ default boolean isNotWritable(@NotNull VirtualFile file) {
+ return false;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
index 0b5992e80796..5b8913c91258 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
@@ -15,8 +15,9 @@
*/
package com.intellij.openapi.fileEditor.impl;
-import com.intellij.ProjectTopics;
import com.intellij.ide.impl.ProjectUtil;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceKt;
import com.intellij.openapi.components.impl.stores.IProjectStore;
@@ -25,29 +26,37 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectEx;
-import com.intellij.openapi.roots.ModuleRootAdapter;
-import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NotNullLazyKey;
+import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.util.NullableFunction;
-import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
-import java.util.*;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
- public enum AccessStatus {REQUESTED, ALLOWED}
-
private static final Key ENABLE_IN_TESTS = Key.create("NON_PROJECT_FILE_ACCESS_ENABLE_IN_TESTS");
- private static final Key ALL_ACCESS_ALLOWED = Key.create("NON_PROJECT_FILE_ALL_ACCESS_STATUS");
- private static final NotNullLazyKey
-
+
-
+
-
+
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictDialog.java
index cba973307ca5..e8d9b2a96312 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictDialog.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictDialog.java
@@ -18,11 +18,13 @@ package com.intellij.openapi.vcs.changes.conflicts;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.changes.ChangeList;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ChangeListManagerImpl;
import com.intellij.openapi.vcs.readOnlyHandler.FileListRenderer;
+import com.intellij.openapi.vcs.readOnlyHandler.ReadOnlyStatusDialog;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.CollectionListModel;
import org.jetbrains.annotations.NotNull;
@@ -42,6 +44,7 @@ public class ChangelistConflictDialog extends DialogWrapper {
private JRadioButton myMoveChangesToActiveRadioButton;
private JRadioButton mySwitchToChangelistRadioButton;
private JRadioButton myIgnoreRadioButton;
+ private JLabel myListTitle;
private JList myFileList;
private final Project myProject;
@@ -51,6 +54,10 @@ public class ChangelistConflictDialog extends DialogWrapper {
myProject = project;
setTitle("Resolve Changelist Conflict");
+
+ myListTitle.setText(StringUtil.capitalize(ReadOnlyStatusDialog.getTheseFilesMessage(conflicts))
+ + " " + (conflicts.size() > 1 ? "do" : "does")
+ + " not belong to the active changelist:");
myFileList.setCellRenderer(new FileListRenderer());
myFileList.setModel(new CollectionListModel(conflicts));
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java
index 08d8a137a00a..00ab88ec6225 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXRenameTest.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.application.PluginPathManager;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
+import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.RenameRefactoring;
import com.intellij.refactoring.openapi.impl.JavaRenameRefactoringImpl;
import com.intellij.refactoring.rename.PsiElementRenameHandler;
@@ -181,8 +182,7 @@ public class JavaFXRenameTest extends AbstractJavaFXRenameTest {
}
public void testStaticPropertyFromLibrary() throws Exception {
- doTestErrorHint("Foo", "Cannot perform refactoring.\n" +
- "Selected method is not located inside the project");
+ doTestErrorHint("Foo", RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("error.cannot.be.renamed")));
}
public void testControllerMethod() throws Exception {