diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java index cf9de36ab727..af49fce9504a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java @@ -32,7 +32,7 @@ public class GenerateDelegateHandler implements CodeInsightActionHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.GenerateDelegateHandler"); public void invoke(final Project project, final Editor editor, final PsiFile file) { - if (!file.isWritable() && !FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { + if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { return; } PsiDocumentManager.getInstance(project).commitAllDocuments(); diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersHandlerBase.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersHandlerBase.java index 03c80e103e18..1a417f844b5f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersHandlerBase.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersHandlerBase.java @@ -44,7 +44,7 @@ public abstract class GenerateMembersHandlerBase implements CodeInsightActionHan } public final void invoke(final Project project, final Editor editor, PsiFile file) { - if (!file.isWritable() && !FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { + if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { return; } final PsiClass aClass = OverrideImplementUtil.getContextClass(project, editor, file, false); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java index 6a3daf4dcff4..7f3f1ffbccbe 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ImplementAbstractMethodHandler.java @@ -100,7 +100,7 @@ public class ImplementAbstractMethodHandler { private void implementInClass(final PsiClass psiClass) { if (!psiClass.isValid()) return; - if (!psiClass.isWritable() && !FileDocumentManager.getInstance().requestWriting(PsiDocumentManager.getInstance(myProject).getDocument(psiClass.getContainingFile()), myProject)) { + if (!FileDocumentManager.getInstance().requestWriting(PsiDocumentManager.getInstance(myProject).getDocument(psiClass.getContainingFile()), myProject)) { MessagesEx.fileIsReadOnly(myProject, psiClass.getContainingFile().getVirtualFile()).showNow(); return; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java b/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java index fc6f4b123ebd..b1f9195567ef 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java @@ -73,13 +73,14 @@ public class CodeInsightUtilBase { public static boolean prepareFileForWrite(final PsiFile file) { if (file == null) return false; - if (!file.isWritable()) { - final Project project = file.getProject(); + final Project project = file.getProject(); + final Document document = PsiDocumentManager.getInstance(project).getDocument(file); + + if (!ReadonlyStatusHandler.getInstance(project).isWriteAccessAllowed(file.getVirtualFile())) { final Editor editor = FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file.getVirtualFile()), true); - final Document document = PsiDocumentManager.getInstance(project).getDocument(file); if (!FileDocumentManager.getInstance().requestWriting(document, project)) { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 415185be4ecc..01d0b8e9e4c0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -133,7 +133,6 @@ public abstract class AbstractLayoutCodeProcessor { return; } - if (!file.isWritable()){ if (!FileDocumentManager.getInstance().requestWriting(document, myProject)) { Messages.showMessageDialog(myProject, PsiBundle.message("cannot.modify.a.read.only.file", file.getName()), CodeInsightBundle.message("error.dialog.readonly.file.title"), @@ -141,7 +140,6 @@ public abstract class AbstractLayoutCodeProcessor { ); return; } - } final Runnable[] resultRunnable = new Runnable[1]; Runnable readAction = new Runnable() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 16d50ca19059..60d3870aaf9a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -81,7 +81,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { document.fireReadOnlyModificationAttempt(); return; } - if (!psiFile.isWritable() && !FileDocumentManager.getInstance().requestWriting(document, project)) { + if (!FileDocumentManager.getInstance().requestWriting(document, project)) { return; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EmacsStyleIndentAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EmacsStyleIndentAction.java index 92faea546928..3f65c03e1e1b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EmacsStyleIndentAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EmacsStyleIndentAction.java @@ -36,7 +36,7 @@ public class EmacsStyleIndentAction extends BaseCodeInsightAction implements Dum public void invoke(final Project project, final Editor editor, final PsiFile file) { PsiDocumentManager.getInstance(project).commitAllDocuments(); - if (!file.isWritable() && !FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { + if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { return; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java index 53708aa13a29..9a9b429c291c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java @@ -49,11 +49,9 @@ public class PasteHandler extends EditorActionHandler { public void execute(final Editor editor, final DataContext dataContext) { if (editor.isViewer()) return; - if (!editor.getDocument().isWritable()) { if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), PlatformDataKeys.PROJECT.getData(dataContext))){ return; } - } final Project project = editor.getProject(); if (project == null || editor.isColumnMode()) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/AutoIndentLinesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/AutoIndentLinesHandler.java index 89147bfb177b..5eeefe801073 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/AutoIndentLinesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/AutoIndentLinesHandler.java @@ -17,11 +17,9 @@ public class AutoIndentLinesHandler implements CodeInsightActionHandler { public void invoke(Project project, Editor editor, PsiFile file) { PsiDocumentManager.getInstance(project).commitAllDocuments(); - if (!file.isWritable()){ if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)){ return; } - } Document document = editor.getDocument(); int startOffset, endOffset; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByBlockCommentHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByBlockCommentHandler.java index ad2c96cf6ac5..ec1a10ab2e12 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByBlockCommentHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByBlockCommentHandler.java @@ -45,10 +45,8 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler { myDocument = editor.getDocument(); - if (!myFile.isWritable()) { - if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { - return; - } + if (!FileDocumentManager.getInstance().requestWriting(myDocument, project)) { + return; } FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.comment.block"); final Commenter commenter = findCommenter(myFile, myEditor); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java index d642c1acdbf9..5d8cee5afba2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java @@ -48,10 +48,8 @@ public class CommentByLineCommentHandler implements CodeInsightActionHandler { myDocument = editor.getDocument(); myEditor = editor; - if (!myFile.isWritable()) { - if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) { - return; - } + if (!FileDocumentManager.getInstance().requestWriting(myDocument, project)) { + return; } PsiDocumentManager.getInstance(project).commitDocument(myDocument); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/ImplementMethodsHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/ImplementMethodsHandler.java index 5a6f024db2e0..f80473d61859 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/ImplementMethodsHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/ImplementMethodsHandler.java @@ -12,10 +12,8 @@ import com.intellij.psi.util.PsiUtilBase; public class ImplementMethodsHandler implements CodeInsightActionHandler{ public final void invoke(final Project project, final Editor editor, PsiFile file) { - if (!file.isWritable()){ - if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)){ - return; - } + if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)){ + return; } Language language = PsiUtilBase.getLanguageAtOffset(file, editor.getCaretModel().getOffset()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/OverrideMethodsHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/OverrideMethodsHandler.java index a41e4c2841c1..6fe114e99045 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/OverrideMethodsHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/OverrideMethodsHandler.java @@ -12,10 +12,8 @@ import com.intellij.psi.util.PsiUtilBase; public class OverrideMethodsHandler implements CodeInsightActionHandler{ public final void invoke(final Project project, final Editor editor, PsiFile file) { - if (!file.isWritable()){ - if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)){ - return; - } + if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)){ + return; } Language language = PsiUtilBase.getLanguageAtOffset(file, editor.getCaretModel().getOffset()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java index b0e4a1e05c5d..665fd2c817e4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java @@ -88,10 +88,8 @@ public class SurroundWithHandler implements CodeInsightActionHandler{ static void doSurround(final Project project, final Editor editor, final Surrounder surrounder, final PsiElement[] elements) { final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); - if (!file.isWritable()){ - if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)){ - return; - } + if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)){ + return; } try { diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileDocumentManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileDocumentManager.java index 9d6946e8f63e..ed33c1f07c05 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileDocumentManager.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileDocumentManager.java @@ -61,11 +61,18 @@ public abstract class FileDocumentManager { public abstract String getLineSeparator(@Nullable VirtualFile file, @Nullable Project project); /** - * Requests writing access on given document + * @return true if writing access allowed + * @see #requestWriting(com.intellij.openapi.editor.Document, com.intellij.openapi.project.Project) + */ + public abstract boolean isWritingAllowed(@NotNull Document document, Project project); + + /** + * Requests writing access on given document, possibly involving interaction with user. * * @param document document * @param project project * @return true if writing access allowed + * @see com.intellij.openapi.vfs.ReadonlyStatusHandler#ensureFilesWritable(com.intellij.openapi.project.Project, com.intellij.openapi.vfs.VirtualFile...) */ public abstract boolean requestWriting(@NotNull Document document, Project project); diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java b/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java index 841fe3a1c8a1..007672065f03 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/ReadonlyStatusHandler.java @@ -18,15 +18,14 @@ package com.intellij.openapi.vfs; import com.intellij.CommonBundle; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; import java.util.Collection; public abstract class ReadonlyStatusHandler { - public static class UnsuccessfulOperation extends Exception { - public UnsuccessfulOperation(String message) { - super(message); - } + public static boolean ensureFilesWritable(Project project, @NotNull VirtualFile... files) { + return getInstance(project).ensureFilesWritable(files).hasReadonlyFiles(); } public static class OperationStatus { @@ -75,6 +74,8 @@ public abstract class ReadonlyStatusHandler { public abstract OperationStatus ensureFilesWritable(VirtualFile... files); + public abstract boolean isWriteAccessAllowed(VirtualFile... files); + public OperationStatus ensureFilesWritable(final Collection files) { return ensureFilesWritable(files.toArray(new VirtualFile[files.size()])); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java index eaf290c5d590..bc8acc46204a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java @@ -300,16 +300,20 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl } } + @Override + public boolean isWritingAllowed(@NotNull Document document, Project project) { + return document.isWritable(); + } + @Override public boolean requestWriting(@NotNull Document document, Project project) { - if (document.isWritable()) { + if (isWritingAllowed(document, project)) { return true; } if (project != null) { final VirtualFile file = getInstance().getFile(document); if (file != null && file.isValid()) { - final ReadonlyStatusHandler.OperationStatus operationStatus = ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(file); - return !operationStatus.hasReadonlyFiles(); + return ReadonlyStatusHandler.ensureFilesWritable(project, file); } } document.fireReadOnlyModificationAttempt(); diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/ReadonlyStatusHandlerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/ReadonlyStatusHandlerImpl.java index 48752934b5cc..efe19f26b243 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/ReadonlyStatusHandlerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/ReadonlyStatusHandlerImpl.java @@ -120,6 +120,16 @@ public class ReadonlyStatusHandlerImpl extends ReadonlyStatusHandler implements return createResultStatus(files, modificationStamps); } + @Override + public boolean isWriteAccessAllowed(VirtualFile... files) { + for (VirtualFile file : files) { + if (!file.isWritable()) { + return false; + } + } + return true; + } + private static OperationStatus createResultStatus(final VirtualFile[] files, final long[] modificationStamps) { List readOnlyFiles = new ArrayList(); List updatedFiles = new ArrayList(); diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/WritingAccessProvider.java b/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/WritingAccessProvider.java new file mode 100644 index 000000000000..ac9db2112d14 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/WritingAccessProvider.java @@ -0,0 +1,19 @@ +package com.intellij.openapi.vcs.readOnlyHandler; + +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.extensions.ExtensionPointName; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * @author Dmitry Avdeev + */ +public interface WritingAccessProvider { + + ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.writingAccessProvider"); + + boolean isWritingAllowed(@NotNull VirtualFile file); + + boolean requestWriting(Collection files); +} diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index 0413b84c8824..40efbc985958 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -97,4 +97,6 @@ + + diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java index ad4f4cdf55ce..ba166c56a9c8 100644 --- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java +++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java @@ -421,8 +421,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit Document propertiesFileDocument = documentManager.getDocument(propertiesFile); documentManager.commitDocument(propertiesFileDocument); - if (!propertiesFile.isWritable() && - !FileDocumentManager.getInstance().requestWriting(document, project)) { + if (!FileDocumentManager.getInstance().requestWriting(document, project)) { uninstallDocumentListeners(); try { document.replaceString(0, document.getTextLength(), oldText);