Platform: IDEA-125330 Warning about non-project file modification should be merged with Read-only warning and shown in a modal dialog

This commit is contained in:
Anton Makeev
2014-05-25 13:39:48 +04:00
parent b3afb57c96
commit 6c0132db48
7 changed files with 213 additions and 206 deletions
@@ -1,54 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.fileEditor.impl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.ui.HyperlinkLabel;
import org.jetbrains.annotations.NotNull;
public class NonProjectFileNotificationPanel extends EditorNotificationPanel {
private final HyperlinkLabel myUnlockAction;
private final HyperlinkLabel myUnlockAllLabel;
public NonProjectFileNotificationPanel(@NotNull final Project project, @NotNull final VirtualFile file) {
setText("This file is not in the project, please unlock it to continue editing");
myUnlockAction = createActionLabel("Unlock", new Runnable() {
@Override
public void run() {
NonProjectFileWritingAccessProvider.allowAccess(project, file);
}
});
myUnlockAllLabel = createActionLabel("Unlock all in current session", new Runnable() {
@Override
public void run() {
NonProjectFileWritingAccessProvider.allowAccessForAll(project, file);
}
});
}
@NotNull
public HyperlinkLabel getUnlockAction() {
return myUnlockAction;
}
@NotNull
public HyperlinkLabel getUnlockAllLabel() {
return myUnlockAllLabel;
}
}
@@ -1,44 +0,0 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.fileEditor.impl;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotifications;
import org.jetbrains.annotations.NotNull;
public class NonProjectFileNotificationProvider extends EditorNotifications.Provider<NonProjectFileNotificationPanel> {
private static final Key<NonProjectFileNotificationPanel> KEY = Key.create("NonProjectFileNotificationPanel");
@NotNull private final Project myProject;
public NonProjectFileNotificationProvider(@NotNull Project project) {
myProject = project;
}
public Key<NonProjectFileNotificationPanel> getKey() {
return KEY;
}
public NonProjectFileNotificationPanel createNotificationPanel(VirtualFile file, FileEditor fileEditor) {
NonProjectFileWritingAccessProvider.AccessStatus status = NonProjectFileWritingAccessProvider.getAccessStatus(myProject, file);
if (status != NonProjectFileWritingAccessProvider.AccessStatus.REQUESTED) return null;
return new NonProjectFileNotificationPanel(myProject, file);
}
}
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessDialog">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="441" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="2f133" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="2" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="etched"/>
<children>
<component id="e62df" class="javax.swing.JRadioButton" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
<text value="Unlock files"/>
</properties>
</component>
<component id="592c9" class="javax.swing.JRadioButton" binding="myUnlockAllButton" default-binding="true">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Unlock all non-project files in current session"/>
</properties>
</component>
</children>
</grid>
<component id="dbd63" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="These files do not belong to the project"/>
</properties>
</component>
<scrollpane id="6c540" class="com.intellij.ui.components.JBScrollPane">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="3aa3b" class="com.intellij.ui.components.JBList" binding="myFileList">
<constraints/>
<properties/>
</component>
</children>
</scrollpane>
</children>
</grid>
<buttonGroups>
<group name="resolution">
<member id="592c9"/>
<member id="e62df"/>
<member id="25953"/>
<member id="16741"/>
</group>
</buttonGroups>
</form>
@@ -0,0 +1,59 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.fileEditor.impl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vcs.readOnlyHandler.FileListRenderer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.CollectionListModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
public class NonProjectFileWritingAccessDialog extends DialogWrapper {
private JPanel myPanel;
private JList myFileList;
private JRadioButton myUnlockAllButton;
protected NonProjectFileWritingAccessDialog(@NotNull Project project, @NotNull List<VirtualFile> nonProjectFiles) {
super(project);
setTitle("Non-Project Files Access");
myFileList.setCellRenderer(new FileListRenderer());
myFileList.setModel(new CollectionListModel<VirtualFile>(nonProjectFiles));
init();
}
@Nullable
@Override
protected JComponent createCenterPanel() {
return myPanel;
}
@NotNull
public NonProjectFileWritingAccessProvider.UnlockOption getUnlockOption() {
return myUnlockAllButton.isSelected() ? NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK_ALL
: NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK;
}
protected String getHelpId() {
return "readOnlyHandler.nonProjectFilesDialog";
}
}
@@ -30,8 +30,8 @@ import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NotNullLazyKey;
import com.intellij.openapi.vfs.*;
import com.intellij.ui.EditorNotifications;
import com.intellij.util.NotNullFunction;
import com.intellij.util.NullableFunction;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,6 +54,12 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
});
@NotNull private final Project myProject;
@Nullable private static NullableFunction<List<VirtualFile>, UnlockOption> ourCustomUnlocker;
@TestOnly
public static void setCustomUnlocker(@Nullable NullableFunction<List<VirtualFile>, UnlockOption> unlocker) {
ourCustomUnlocker = unlocker;
}
public NonProjectFileWritingAccessProvider(@NotNull final Project project) {
myProject = project;
@@ -73,7 +79,6 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
for (VirtualFile each : new ArrayList<VirtualFile>(files.keySet())) {
if (isProjectFile(each)) {
files.remove(each);
EditorNotifications.getInstance(myProject).updateNotifications(each);
}
}
}
@@ -98,18 +103,40 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
if (!(each.getFileSystem() instanceof LocalFileSystem)) continue; // do not block e.g., HttpFileSystem, LightFileSystem etc.
if (isProjectFile(each)) {
if (statuses.remove(each) != null) {
EditorNotifications.getInstance(myProject).updateNotifications(each);
}
statuses.remove(each);
continue;
}
statuses.put(each, AccessStatus.REQUESTED);
deniedFiles.add(each);
EditorNotifications.getInstance(myProject).updateNotifications(each);
}
return deniedFiles;
if (deniedFiles.isEmpty()) return Collections.emptyList();
UnlockOption unlockOption = askToUnlock(deniedFiles);
if (unlockOption == null) return deniedFiles;
switch (unlockOption) {
case UNLOCK:
for (VirtualFile eachAllowed : deniedFiles) {
statuses.put(eachAllowed, AccessStatus.ALLOWED);
}
break;
case UNLOCK_ALL:
myProject.putUserData(ALL_ACCESS_ALLOWED, Boolean.TRUE);
break;
}
return Collections.emptyList();
}
@Nullable
private UnlockOption askToUnlock(@NotNull List<VirtualFile> files) {
if (ourCustomUnlocker != null) return ourCustomUnlocker.fun(files);
NonProjectFileWritingAccessDialog dialog = new NonProjectFileWritingAccessDialog(myProject, files);
if (!dialog.showAndGet()) return null;
return dialog.getUnlockOption();
}
private boolean isProjectFile(@NotNull VirtualFile file) {
@@ -156,28 +183,10 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
return allAccessAllowed(project) ? AccessStatus.ALLOWED : getRegisteredFiles(project).get(file);
}
public static void allowAccessForAll(@NotNull Project project, @NotNull VirtualFile file) {
project.putUserData(ALL_ACCESS_ALLOWED, Boolean.TRUE);
// unlock the current file as well
ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(file);
EditorNotifications.getInstance(project).updateAllNotifications();
}
public static void allowAccess(@NotNull Project project, @NotNull VirtualFile file) {
// Ask other access provides to remove read-only status
Map<VirtualFile, AccessStatus> statuses = getRegisteredFiles(project);
statuses.put(file, AccessStatus.ALLOWED);
if (ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(file).hasReadonlyFiles()) {
// If failed, do not change the status
statuses.put(file, AccessStatus.REQUESTED);
}
EditorNotifications.getInstance(project).updateNotifications(file);
}
@NotNull
private static Map<VirtualFile, AccessStatus> getRegisteredFiles(@NotNull Project project) {
return ACCESS_STATUS.getValue(project);
}
public enum UnlockOption {UNLOCK, UNLOCK_ALL}
}
@@ -285,7 +285,6 @@
<postStartupActivity implementation="com.intellij.openapi.actionSystem.impl.ActionPreloader"/>
<postStartupActivity id="OpenFilesActivity" implementation="com.intellij.openapi.fileEditor.impl.OpenFilesActivity"/>
<editorNotificationProvider implementation="com.intellij.openapi.fileEditor.impl.NonProjectFileNotificationProvider"/>
<writingAccessProvider implementation="com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider" order="first"/>
<patch.extension implementation="com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP"/>
@@ -26,11 +26,8 @@ import com.intellij.openapi.components.impl.ComponentManagerImpl;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileEditor.impl.NonProjectFileNotificationPanel;
import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessExtension;
import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.module.EmptyModuleType;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
@@ -47,9 +44,10 @@ import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.ui.EditorNotifications;
import com.intellij.ui.EditorNotificationsImpl;
import com.intellij.util.NullableFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase {
@@ -64,6 +62,7 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase {
@Override
protected void tearDown() throws Exception {
NonProjectFileWritingAccessProvider.setCustomUnlocker(null);
NonProjectFileWritingAccessProvider.enableChecksInTests(getProject(), false);
super.tearDown();
}
@@ -80,15 +79,10 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase {
VirtualFile nonProjectFile = createNonProjectFile();
typeAndCheck(nonProjectFile, false);
NonProjectFileNotificationPanel panel = typeAndCheck(nonProjectFile, false);// still not allowed
typeAndCheck(nonProjectFile, false);// still not allowed
panel.getUnlockAction().doClick();
assertNull(getNotificationPanel(projectFile));
assertNull(getNotificationPanel(nonProjectFile));
typeAndCheck(nonProjectFile, true);
assertNull(getNotificationPanel(projectFile));
assertNull(getNotificationPanel(nonProjectFile));
typeAndCheck(nonProjectFile, NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK, true);
typeAndCheck(nonProjectFile, null, true); // still allowed after previous Unlock
}
public void testAccessToProjectSystemFiles() throws Exception {
@@ -158,77 +152,59 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase {
VirtualFile nonProjectFile1 = createNonProjectFile();
VirtualFile nonProjectFile2 = createNonProjectFile();
NonProjectFileNotificationPanel panel1 = typeAndCheck(nonProjectFile1, false);
NonProjectFileNotificationPanel panel2 = typeAndCheck(nonProjectFile2, false);
typeAndCheck(nonProjectFile1, NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK, true);
typeAndCheck(nonProjectFile2, null, false);
panel1.getUnlockAction().doClick();
assertNull(getNotificationPanel(nonProjectFile1));
assertNotNull(getNotificationPanel(nonProjectFile2));
typeAndCheck(nonProjectFile1, null, true);
typeAndCheck(nonProjectFile2, NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK, true);
typeAndCheck(nonProjectFile1, true);
typeAndCheck(nonProjectFile2, false);
panel2.getUnlockAction().doClick();
assertNull(getNotificationPanel(nonProjectFile1));
assertNull(getNotificationPanel(nonProjectFile2));
typeAndCheck(nonProjectFile1, true);
typeAndCheck(nonProjectFile2, true);
// let's check both files one more time to make sure unlock option doesn't have eny unexpected effect
typeAndCheck(nonProjectFile1, null, true);
typeAndCheck(nonProjectFile2, null, true);
}
public void testAllowEditingInAllFiles() throws Exception {
VirtualFile nonProjectFile1 = createNonProjectFile();
VirtualFile nonProjectFile2 = createNonProjectFile();
VirtualFile nonProjectFile3 = createNonProjectFile();
NonProjectFileNotificationPanel panel1 = typeAndCheck(nonProjectFile1, false);
typeAndCheck(nonProjectFile1, false);
typeAndCheck(nonProjectFile2, false);
typeAndCheck(nonProjectFile3, false);
assertNotNull(getNotificationPanel(nonProjectFile1));
assertNotNull(getNotificationPanel(nonProjectFile2));
panel1.getUnlockAllLabel().doClick();
assertNull(getNotificationPanel(nonProjectFile1));
assertNull(getNotificationPanel(nonProjectFile2));
typeAndCheck(nonProjectFile1, true);
typeAndCheck(nonProjectFile1, NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK_ALL, true);
// affects other files
typeAndCheck(nonProjectFile2, true);
typeAndCheck(nonProjectFile3, true);
}
public void testCheckingOtherWriteAccessProvidersOnUnlock() throws Exception {
final VirtualFile nonProjectFile1 = createNonProjectFile();
final VirtualFile nonProjectFile2 = createNonProjectFile();
final List<VirtualFile> requested = registerWriteAccessProvider(nonProjectFile1);
final Set<VirtualFile> requested = registerWriteAccessProvider(nonProjectFile1);
NonProjectFileNotificationPanel panel1 = typeAndCheck(nonProjectFile1, false);
panel1.getUnlockAction().doClick();
typeAndCheck(nonProjectFile1, false);
assertSameElements(requested); // not called since non-project file access is denied
typeAndCheck(nonProjectFile1, NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK, false);
assertSameElements(requested, nonProjectFile1);
typeAndCheck(nonProjectFile1, false); // leave file locked if other provides denied access
requested.clear();
NonProjectFileNotificationPanel panel2 = typeAndCheck(nonProjectFile2, false);
panel2.getUnlockAction().doClick();
typeAndCheck(nonProjectFile2, NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK, true);
assertSameElements(requested, nonProjectFile2);
typeAndCheck(nonProjectFile2, true);
}
public void testCheckingOtherWriteAccessProvidersOnUnlockAll() throws Exception {
final VirtualFile nonProjectFile1 = createNonProjectFile();
final VirtualFile nonProjectFile2 = createNonProjectFile();
final List<VirtualFile> requested = registerWriteAccessProvider(nonProjectFile1);
registerWriteAccessProvider(nonProjectFile1);
NonProjectFileNotificationPanel panel = typeAndCheck(nonProjectFile1, false);
typeAndCheck(nonProjectFile2, false);
assertNotNull(getNotificationPanel(nonProjectFile1));
assertNotNull(getNotificationPanel(nonProjectFile2));
panel.getUnlockAllLabel().doClick();
assertSameElements(requested, nonProjectFile1);
typeAndCheck(nonProjectFile1, false, false); // can't write, but access panel is not shown
typeAndCheck(nonProjectFile1, NonProjectFileWritingAccessProvider.UnlockOption.UNLOCK_ALL,
false); // can't write since denied by another write-access provider
typeAndCheck(nonProjectFile2, true);
}
@@ -260,8 +236,8 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase {
typeAndCheck(nonProjectFile1, false);
typeAndCheck(nonProjectFile2, false);
assertNotNull(getNotificationPanel(nonProjectFile1));
assertNotNull(getNotificationPanel(nonProjectFile2));
assertNotNull(NonProjectFileWritingAccessProvider.getAccessStatus(getProject(), nonProjectFile1));
assertNotNull(NonProjectFileWritingAccessProvider.getAccessStatus(getProject(), nonProjectFile2));
ContentEntry contextRoot = PsiTestUtil.addContentRoot(myModule, nonProjectFile2.getParent());
@@ -309,8 +285,8 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase {
typeAndCheck(nonProjectFile2, false);
}
private List<VirtualFile> registerWriteAccessProvider(final VirtualFile... filesToDeny) {
final List<VirtualFile> requested = new ArrayList<VirtualFile>();
private Set<VirtualFile> registerWriteAccessProvider(final VirtualFile... filesToDeny) {
final Set<VirtualFile> requested = new LinkedHashSet<VirtualFile>();
PlatformTestUtil.registerExtension(Extensions.getArea(getProject()), WritingAccessProvider.EP_NAME, new WritingAccessProvider() {
@NotNull
@Override
@@ -361,41 +337,34 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase {
}.execute().getResultObject();
}
private NonProjectFileNotificationPanel typeAndCheck(VirtualFile file, boolean fileHasBeenChanged) {
return typeAndCheck(file, fileHasBeenChanged, !fileHasBeenChanged);
private void typeAndCheck(VirtualFile file, boolean fileHasBeenChanged) {
typeAndCheck(file, null, fileHasBeenChanged);
}
private NonProjectFileNotificationPanel typeAndCheck(VirtualFile file, boolean changed, boolean hasWarningPanel) {
private void typeAndCheck(VirtualFile file,
@Nullable final NonProjectFileWritingAccessProvider.UnlockOption option,
boolean fileHasBeenChanged) {
Editor editor = getEditor(file);
NullableFunction<List<VirtualFile>, NonProjectFileWritingAccessProvider.UnlockOption> unlocker =
new NullableFunction<List<VirtualFile>, NonProjectFileWritingAccessProvider.UnlockOption>() {
@Nullable
@Override
public NonProjectFileWritingAccessProvider.UnlockOption fun(List<VirtualFile> files) {
return option;
}
};
NonProjectFileWritingAccessProvider.setCustomUnlocker(unlocker);
String before = editor.getDocument().getText();
typeInChar(editor, 'a');
NonProjectFileNotificationPanel panel = getNotificationPanel(file);
if (changed) {
if (fileHasBeenChanged) {
assertEquals("Text should be changed", 'a' + before, editor.getDocument().getText());
}
else {
assertEquals("Text should not be changed", before, editor.getDocument().getText());
}
assertEquals(hasWarningPanel, panel != null);
return panel;
}
private NonProjectFileNotificationPanel getNotificationPanel(VirtualFile file) {
Editor editor = getEditor(file);
FileEditorManagerImpl manager = (FileEditorManagerImpl)FileEditorManager.getInstance(getProject());
List<JComponent> topComponents = manager.getTopComponents(getFileEditor(editor));
if (topComponents.isEmpty()) return null;
JComponent panel = topComponents.get(0);
assertTrue(panel instanceof NonProjectFileNotificationPanel);
return (NonProjectFileNotificationPanel)panel;
}
protected FileEditor getFileEditor(Editor e) {
return e == null ? null : TextEditorProvider.getInstance().getTextEditor(e);
}
private Editor getEditor(VirtualFile file) {