import com.intellij.compiler.ProblemsView;
import com.intellij.icons.AllIcons;
import com.intellij.ide.errorTreeView.ErrorTreeElement;
+import com.intellij.ide.errorTreeView.ErrorTreeElementKind;
import com.intellij.ide.errorTreeView.ErrorViewStructure;
import com.intellij.ide.errorTreeView.GroupingElement;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import org.jetbrains.ide.PooledThreadExecutor;
import javax.swing.*;
+import java.util.EnumSet;
import java.util.UUID;
/**
*/
public class ProblemsViewImpl extends ProblemsView{
private static final String PROBLEMS_TOOLWINDOW_ID = "Problems";
-
+ private static final EnumSet<ErrorTreeElementKind> ALL_MESSAGE_KINDS = EnumSet.allOf(ErrorTreeElementKind.class);
+
private final ProblemsViewPanel myPanel;
private final SequentialTaskExecutor myViewUpdater = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
private final Icon myActiveIcon = AllIcons.Toolwindows.Problems;
return;
}
final ToolWindow tw = wm.registerToolWindow(PROBLEMS_TOOLWINDOW_ID, false, ToolWindowAnchor.BOTTOM, project, true);
- updateIcon(false);
final Content content = ContentFactory.SERVICE.getInstance().createContent(myPanel, "", false);
// todo: setup content?
tw.getContentManager().addContent(content);
tw.getContentManager().removeAllContents(true);
}
});
+ updateIcon();
}
});
}
myViewUpdater.execute(new Runnable() {
@Override
public void run() {
- updateIcon(!cleanupChildrenRecursively(myPanel.getErrorViewStructure().getRootElement(), scope, currentSessionId));
+ cleanupChildrenRecursively(myPanel.getErrorViewStructure().getRootElement(), scope, currentSessionId);
+ updateIcon();
myPanel.reload();
}
});
}
- private boolean cleanupChildrenRecursively(@NotNull final Object fromElement, final @Nullable CompileScope scope, @NotNull UUID currentSessionId) {
+ private void cleanupChildrenRecursively(@NotNull final Object fromElement, final @Nullable CompileScope scope, @NotNull UUID currentSessionId) {
final ErrorViewStructure structure = myPanel.getErrorViewStructure();
- ErrorTreeElement[] elements = structure.getChildElements(fromElement);
- if (elements.length ==0) return true;
-
- boolean result = false;
- for (ErrorTreeElement element : elements) {
+ for (ErrorTreeElement element : structure.getChildElements(fromElement)) {
if (element instanceof GroupingElement) {
if (scope != null) {
final VirtualFile file = ((GroupingElement)element).getFile();
}
if (!currentSessionId.equals(element.getData())) {
structure.removeElement(element);
- result = true;
}
else {
- result |= cleanupChildrenRecursively(element, scope, currentSessionId);
+ cleanupChildrenRecursively(element, scope, currentSessionId);
}
}
else {
if (!currentSessionId.equals(element.getData())) {
structure.removeElement(element);
- result = true;
}
}
}
- return result;
}
@Override
public void run() {
final ErrorViewStructure structure = myPanel.getErrorViewStructure();
final GroupingElement group = structure.lookupGroupingElement(groupName);
- if (group != null && !sessionId.equals(group.getData())) {
+ if (group != null && sessionId != null && !sessionId.equals(group.getData())) {
structure.removeElement(group);
}
if (navigatable != null) {
else {
myPanel.addMessage(type, text, null, -1, -1, sessionId);
}
- updateIcon(true);
+ updateIcon();
}
});
}
- private void updateIcon(final boolean active) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ private void updateIcon() {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
- final ToolWindow tw = ToolWindowManager.getInstance(myProject).getToolWindow(PROBLEMS_TOOLWINDOW_ID);
- if (tw != null) {
- tw.setIcon(active ? myActiveIcon : myPassiveIcon);
+ if (!myProject.isDisposed()) {
+ final ToolWindow tw = ToolWindowManager.getInstance(myProject).getToolWindow(PROBLEMS_TOOLWINDOW_ID);
+ if (tw != null) {
+ final boolean active = myPanel.getErrorViewStructure().hasMessages(ALL_MESSAGE_KINDS);
+ tw.setIcon(active ? myActiveIcon : myPassiveIcon);
+ }
}
}
- }, myProject.getDisposed());
+ });
}
@Override
public class ProblemsViewPanel extends NewErrorTreeViewPanel {
public ProblemsViewPanel(Project project) {
- super(project, null, false, true, null);
+ super(project, "reference.problems.tool.window", false, true, null);
myTree.getEmptyText().setText("No compilation problems found");
}
});
myLanguageLevelCombo.insertItemAt(LanguageLevelCombo.USE_PROJECT_LANGUAGE_LEVEL, 0);
- myPanel.add(new JLabel(ProjectBundle.message("module.module.language.level")),
+ JLabel label = new JLabel(ProjectBundle.message("module.module.language.level"));
+ label.setLabelFor(myLanguageLevelCombo);
+ myPanel.add(label,
new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(12, 6, 12, 0), 0, 0));
myPanel.add(myLanguageLevelCombo,
new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(6, 6, 12, 0), 0, 0));
import com.intellij.openapi.projectRoots.JdkVersionUtil;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.*;
+import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
+import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiFile;
}
else {
LanguageLevelProjectExtension.getInstance(project).setLanguageLevel(myLevel);
+ ProjectRootManagerEx.getInstanceEx(project).makeRootsChange(EmptyRunnable.INSTANCE, false, true);
}
}
--- /dev/null
+package com.intellij.codeInspection;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.util.ThreeState;
+
+/**
+ * This kind of suppression fix allows to clients to specify whether the fix should
+ * be invoked on injected elements or on elements of host files.
+ * <p/>
+ * By default suppression fixes on injected elements are able to make suppression inside injection only.
+ * Whereas implementation of this interface will be provided for suppressing inside injection and in injection host.
+ * See {@link InspectionProfileEntry#getBatchSuppressActions(PsiElement)} for details.
+ */
+public interface InjectionAwareSuppressQuickFix extends SuppressQuickFix {
+ ThreeState isShouldBeAppliedToInjectionHost();
+
+ void setShouldBeAppliedToInjectionHost(ThreeState shouldBeAppliedToInjectionHost);
+}
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.lang.Language;
+import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
import com.intellij.util.ResourceUtil;
+import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.SerializationFilter;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
/**
* @author anna
* @since 28-Nov-2005
*/
-@SuppressWarnings("JavadocReference")
-public abstract class InspectionProfileEntry implements BatchSuppressableTool{
+public abstract class InspectionProfileEntry implements BatchSuppressableTool {
public static final String GENERAL_GROUP_NAME = InspectionsBundle.message("inspection.general.tools.group.name");
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.InspectionProfileEntry");
Set<SuppressQuickFix> fixes = new THashSet<SuppressQuickFix>(new TObjectHashingStrategy<SuppressQuickFix>() {
@Override
public int computeHashCode(SuppressQuickFix object) {
- return object.getName().hashCode();
+ int result = object instanceof InjectionAwareSuppressQuickFix
+ ? ((InjectionAwareSuppressQuickFix)object).isShouldBeAppliedToInjectionHost().hashCode()
+ : 0;
+ return 31 * result + object.getName().hashCode();
}
@Override
public boolean equals(SuppressQuickFix o1, SuppressQuickFix o2) {
+ if (o1 instanceof InjectionAwareSuppressQuickFix && o2 instanceof InjectionAwareSuppressQuickFix) {
+ if (((InjectionAwareSuppressQuickFix)o1).isShouldBeAppliedToInjectionHost() != ((InjectionAwareSuppressQuickFix)o2).isShouldBeAppliedToInjectionHost()) {
+ return false;
+ }
+ }
return o1.getName().equals(o2.getName());
}
});
+
Set<InspectionSuppressor> suppressors = getSuppressors(element);
+ final PsiLanguageInjectionHost injectionHost = InjectedLanguageManager.getInstance(element.getProject()).getInjectionHost(element);
+ if (injectionHost != null) {
+ Set<InspectionSuppressor> injectionHostSuppressors = getSuppressors(injectionHost);
+ for (InspectionSuppressor suppressor : injectionHostSuppressors) {
+ addAllSuppressActions(fixes, injectionHost, suppressor, ThreeState.YES, getShortName());
+ }
+ }
+
for (InspectionSuppressor suppressor : suppressors) {
- SuppressQuickFix[] actions = suppressor.getSuppressActions(element, getShortName());
- fixes.addAll(Arrays.asList(actions));
+ addAllSuppressActions(fixes, element, suppressor, injectionHost != null ? ThreeState.NO : ThreeState.UNSURE, getShortName());
}
return fixes.toArray(new SuppressQuickFix[fixes.size()]);
}
+ private static void addAllSuppressActions(Set<SuppressQuickFix> fixes,
+ PsiElement element,
+ InspectionSuppressor suppressor,
+ ThreeState appliedToInjectionHost,
+ String toolShortName) {
+ final SuppressQuickFix[] actions = suppressor.getSuppressActions(element, toolShortName);
+ for (SuppressQuickFix action : actions) {
+ if (action instanceof InjectionAwareSuppressQuickFix) {
+ ((InjectionAwareSuppressQuickFix)action).setShouldBeAppliedToInjectionHost(appliedToInjectionHost);
+ }
+ fixes.add(action);
+ }
+ }
+
private boolean isSuppressed(@NotNull String toolId,
@NotNull InspectionSuppressor suppressor,
@NotNull PsiElement element) {
ContainerUtil.addIfNotNull(suppressors, elementLanguageSuppressor);
return suppressors;
}
- return elementLanguageSuppressor != null ? Collections.singleton(elementLanguageSuppressor) : Collections.<InspectionSuppressor>emptySet();
+ return elementLanguageSuppressor != null
+ ? Collections.singleton(elementLanguageSuppressor)
+ : Collections.<InspectionSuppressor>emptySet();
}
public void cleanup(Project project) {
protected volatile DefaultNameProvider myNameProvider = null;
/**
- * @see com.intellij.codeInspection.InspectionEP#groupDisplayName
- * @see com.intellij.codeInspection.InspectionEP#groupKey
- * @see com.intellij.codeInspection.InspectionEP#groupBundle
+ * @see InspectionEP#groupDisplayName
+ * @see InspectionEP#groupKey
+ * @see InspectionEP#groupBundle
*/
@Nls
@NotNull
}
/**
- * @see com.intellij.codeInspection.InspectionEP#groupPath
+ * @see InspectionEP#groupPath
*/
@NotNull
public String[] getGroupPath() {
}
/**
- * @see com.intellij.codeInspection.InspectionEP#displayName
- * @see com.intellij.codeInspection.InspectionEP#key
- * @see com.intellij.codeInspection.InspectionEP#bundle
+ * @see InspectionEP#displayName
+ * @see InspectionEP#key
+ * @see InspectionEP#bundle
*/
@Nls
@NotNull
/**
* DO NOT OVERRIDE this method.
*
- * @see com.intellij.codeInspection.InspectionEP#shortName
+ * @see InspectionEP#shortName
*/
@NonNls
@NotNull
@NotNull
public static String getShortName(@NotNull String className) {
- return StringUtil.trimEnd(StringUtil.trimEnd(className, "Inspection"),"InspectionBase");
+ return StringUtil.trimEnd(StringUtil.trimEnd(className, "Inspection"), "InspectionBase");
}
/**
* DO NOT OVERRIDE this method.
*
- * @see com.intellij.codeInspection.InspectionEP#level
+ * @see InspectionEP#level
*/
@NotNull
public HighlightDisplayLevel getDefaultLevel() {
/**
* DO NOT OVERRIDE this method.
*
- * @see com.intellij.codeInspection.InspectionEP#enabledByDefault
+ * @see InspectionEP#enabledByDefault
*/
public boolean isEnabledByDefault() {
return false;
/**
* This method is called each time UI is shown.
+ *
* @return null if no UI options required.
*/
@Nullable
* Initialize inspection with project. Is called on project opened for all profiles as well as on profile creation.
*
* @param project to be associated with this entry
- * @deprecated this won't work for inspections configured via {@link com.intellij.codeInspection.InspectionEP}
+ * @deprecated this won't work for inspections configured via {@link InspectionEP}
*/
public void projectOpened(@NotNull Project project) {
}
* Cleanup inspection settings corresponding to the project. Is called on project closed for all profiles as well as on profile deletion.
*
* @param project to be disassociated from this entry
- * @deprecated this won't work for inspections configured via {@link com.intellij.codeInspection.InspectionEP}
+ * @deprecated this won't work for inspections configured via {@link InspectionEP}
*/
public void projectClosed(@NotNull Project project) {
}
if (descriptionUrl == null) return null;
return ResourceUtil.loadText(descriptionUrl);
}
- catch (IOException ignored) { }
+ catch (IOException ignored) {
+ }
return null;
}
package com.intellij.codeInsight.daemon.impl.actions;
import com.intellij.codeInsight.FileModificationService;
+import com.intellij.codeInspection.InjectionAwareSuppressQuickFix;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.SuppressQuickFix;
import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.icons.AllIcons;
import com.intellij.lang.Language;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
* @author Roman.Chernyatchik
* @date Aug 13, 2009
*/
-public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements SuppressQuickFix, Iconable {
+public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements InjectionAwareSuppressQuickFix, Iconable {
@NotNull protected final String myID;
private final boolean myReplaceOtherSuppressionIds;
+ private ThreeState myShouldBeAppliedToInjectionHost = ThreeState.UNSURE;
@Nullable
public abstract PsiElement getContainer(final PsiElement context);
myReplaceOtherSuppressionIds = replaceOtherSuppressionIds;
}
+ public void setShouldBeAppliedToInjectionHost(ThreeState shouldBeAppliedToInjectionHost) {
+ myShouldBeAppliedToInjectionHost = shouldBeAppliedToInjectionHost;
+ }
+
+ @Override
+ public ThreeState isShouldBeAppliedToInjectionHost() {
+ return myShouldBeAppliedToInjectionHost;
+ }
+
@NotNull
@Override
public String getName() {
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
}
}
+ public ThreeState isShouldBeAppliedToInjectionHost() {
+ return myFix instanceof InjectionAwareSuppressQuickFix
+ ? ((InjectionAwareSuppressQuickFix)myFix).isShouldBeAppliedToInjectionHost()
+ : ThreeState.UNSURE;
+ }
+
public PsiElement getContainer(PsiElement element) {
return myFix instanceof AbstractBatchSuppressByNoInspectionCommentFix
- ? ((AbstractBatchSuppressByNoInspectionCommentFix )myFix).getContainer(element) : null;
+ ? ((AbstractBatchSuppressByNoInspectionCommentFix)myFix).getContainer(element) : null;
}
@Override
@NotNull
@Override
public String getText() {
- return myFix.getName();
+ return myFix.getName() + (isShouldBeAppliedToInjectionHost() == ThreeState.NO ? " in injection" : "");
}
@NotNull
public void actionPerformed(@NotNull AnActionEvent e) {
stopEditing();
StringBuilder sb = new StringBuilder();
- List<EnvironmentVariable> variables = getEnvironmentVariables();
+ List<EnvironmentVariable> variables = getSelection();
for (EnvironmentVariable environmentVariable : variables) {
if (environmentVariable.getIsPredefined() || isEmpty(environmentVariable)) continue;
if (sb.length() > 0) sb.append('\n');
}
CopyPasteManager.getInstance().setContents(new StringSelection(sb.toString()));
}
+
+ @Override
+ public boolean isEnabled() {
+ return super.isEnabled() && !getSelection().isEmpty();
+ }
};
AnActionButton pasteButton = new AnActionButton(ActionsBundle.message("action.EditorPaste.text"), AllIcons.Actions.Menu_paste) {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
+ removeSelected();
stopEditing();
String content = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
if (content == null || !content.contains("=")) return;
StringUtil.unescapeStringCharacters(line.substring(pos + 1)),
false));
}
- List<EnvironmentVariable> variables =
- new ArrayList<EnvironmentVariable>(ContainerUtil.filter(getEnvironmentVariables(), new Condition<EnvironmentVariable>() {
- @Override
- public boolean value(EnvironmentVariable variable) {
- return variable.getIsPredefined();
- }
- }));
+ List<EnvironmentVariable> variables = new ArrayList<EnvironmentVariable>(getEnvironmentVariables());
variables.addAll(parsed);
setValues(variables);
}
package com.intellij.execution.util;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.util.Condition;
import com.intellij.ui.*;
import com.intellij.ui.table.TableView;
import com.intellij.util.containers.ContainerUtil;
import javax.swing.table.TableCellRenderer;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observable;
}).setRemoveAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
- myTableView.stopEditing();
- setModified();
- T selected = getSelection();
- if (selected != null) {
- int selectedIndex = myElements.indexOf(selected);
- myTableView.scrollRectToVisible(myTableView.getCellRect(selectedIndex, 0, true));
- myElements.remove(selected);
- myTableView.getTableViewModel().setItems(myElements);
-
- int prev = selectedIndex - 1;
- if (prev >= 0) {
- myTableView.getComponent().getSelectionModel().setSelectionInterval(prev, prev);
- }
- else if (selectedIndex < myElements.size()) {
- myTableView.getComponent().getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex);
- }
- }
+ removeSelected();
}
}).disableUpDownActions().addExtraActions(createExtraActions()).createPanel();
ToolbarDecorator.findRemoveButton(myPanel).addCustomUpdater(new AnActionButtonUpdater() {
@Override
public boolean isEnabled(AnActionEvent e) {
- T selection = getSelection();
- return selection != null && myIsEnabled && canDeleteElement(selection);
+ List<T> selection = getSelection();
+ if (selection.isEmpty() || !myIsEnabled) return false;
+ for (T t : selection) {
+ if (!canDeleteElement(t)) return false;
+ }
+ return true;
}
});
ToolbarDecorator.findAddButton(myPanel).addCustomUpdater(new AnActionButtonUpdater() {
myActionsPanel = decorator.getActionsPanel();
- myTableView.getComponent().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ myTableView.getComponent().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ }
+
+ protected void removeSelected() {
+ List<T> selected = getSelection();
+ if (!selected.isEmpty()) {
+ myTableView.stopEditing();
+ setModified();
+ int selectedIndex = myTableView.getSelectionModel().getLeadSelectionIndex();
+ myTableView.scrollRectToVisible(myTableView.getCellRect(selectedIndex, 0, true));
+ selected = ContainerUtil.filter(selected, new Condition<T>() {
+ @Override
+ public boolean value(T t) {
+ return canDeleteElement(t);
+ }
+ });
+ myElements.removeAll(selected);
+ myTableView.getTableViewModel().setItems(myElements);
+
+ int prev = selectedIndex - 1;
+ if (prev >= 0) {
+ myTableView.getComponent().getSelectionModel().setSelectionInterval(prev, prev);
+ }
+ else if (selectedIndex < myElements.size()) {
+ myTableView.getComponent().getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex);
+ }
+ }
}
@NotNull
}
protected void editSelection(int column) {
- int row = myElements.indexOf(getSelection());
+ List<T> selection = getSelection();
+ if (selection.size() != 1) return;
+ int row = myElements.indexOf(selection.get(0));
if (row != -1) {
TableUtil.editCellAt(myTableView, row, column);
}
}
- protected T getSelection() {
- int selIndex = myTableView.getComponent().getSelectionModel().getMinSelectionIndex();
- if (selIndex < 0) {
- return null;
+ @NotNull
+ protected List<T> getSelection() {
+ int[] selection = myTableView.getComponent().getSelectedRows();
+ if (selection.length == 0) {
+ return Collections.emptyList();
}
else {
- return myElements.get(selIndex);
+ List<T> result = new ArrayList<T>(selection.length);
+ for (int row : selection) {
+ result.add(myElements.get(row));
+ }
+ return result;
}
}
import com.intellij.codeInsight.intention.impl.config.IntentionActionWrapper;
import com.intellij.codeInsight.intention.impl.config.IntentionManagerSettings;
import com.intellij.codeInsight.intention.impl.config.IntentionSettingsConfigurable;
+import com.intellij.codeInsight.unwrap.ScopeHighlighter;
+import com.intellij.codeInspection.SuppressIntentionActionFromFix;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.refactoring.BaseRefactoringIntentionAction;
import com.intellij.ui.HintHint;
import com.intellij.ui.LightweightHint;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.Alarm;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.EmptyIcon;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.Border;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.util.Collections;
import java.util.List;
/**
Disposer.dispose(myPopup);
}
myPopup = JBPopupFactory.getInstance().createListPopup(step);
+
+ final PsiFile injectedFile = InjectedLanguageUtil.findInjectedPsiNoCommit(myFile, myEditor.getCaretModel().getOffset());
+ final Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(myEditor, injectedFile);
+
+ final ScopeHighlighter highlighter = new ScopeHighlighter(myEditor);
+ final ScopeHighlighter injectionHighlighter = new ScopeHighlighter(injectedEditor);
+
myPopup.addListener(new JBPopupListener.Adapter() {
@Override
public void onClosed(LightweightWindowEvent event) {
+ highlighter.dropHighlight();
+ injectionHighlighter.dropHighlight();
myPopupShown = false;
}
});
+ myPopup.addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ final Object source = e.getSource();
+ highlighter.dropHighlight();
+ injectionHighlighter.dropHighlight();
+
+ if (source instanceof DataProvider) {
+ final Object selectedItem = PlatformDataKeys.SELECTED_ITEM.getData((DataProvider)source);
+ if (selectedItem instanceof IntentionActionWithTextCaching) {
+ final IntentionAction action = ((IntentionActionWithTextCaching)selectedItem).getAction();
+ if (action instanceof SuppressIntentionActionFromFix) {
+ if (injectedFile != null && ((SuppressIntentionActionFromFix)action).isShouldBeAppliedToInjectionHost() == ThreeState.NO) {
+ final PsiElement at = injectedFile.findElementAt(injectedEditor.getCaretModel().getOffset());
+ final PsiElement container = ((SuppressIntentionActionFromFix)action).getContainer(at);
+ if (container != null) {
+ injectionHighlighter.highlight(container, Collections.singletonList(container));
+ }
+ }
+ else {
+ final PsiElement at = myFile.findElementAt(myEditor.getCaretModel().getOffset());
+ final PsiElement container = ((SuppressIntentionActionFromFix)action).getContainer(at);
+ if (container != null) {
+ highlighter.highlight(container, Collections.singletonList(container));
+ }
+ }
+ }
+ }
+ }
+ }
+ });
if (myEditor.isOneLineMode()) {
// hide popup on combobox popup show
import com.intellij.codeInsight.intention.impl.config.IntentionManagerSettings;
import com.intellij.codeInspection.IntentionWrapper;
import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.SuppressIntentionActionFromFix;
import com.intellij.codeInspection.ex.QuickFixWrapper;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.util.PsiUtilBase;
+import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
if (a instanceof LowPriorityAction) {
return group - 3;
}
+ if (a instanceof SuppressIntentionActionFromFix) {
+ if (((SuppressIntentionActionFromFix)a).isShouldBeAppliedToInjectionHost() == ThreeState.NO) {
+ return group - 1;
+ }
+ }
if (a instanceof QuickFixWrapper) {
final LocalQuickFix quickFix = ((QuickFixWrapper)a).getFix();
if (quickFix instanceof HighPriorityAction) {
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
+import com.intellij.codeInspection.SuppressIntentionActionFromFix;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.featureStatistics.FeatureUsageTrackerImpl;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PairProcessor;
+import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
private static boolean isAvailableHere(Editor editor, PsiFile psiFile, PsiElement psiElement, boolean inProject, IntentionAction action) {
try {
Project project = psiFile.getProject();
+ if (action instanceof SuppressIntentionActionFromFix) {
+ final ThreeState shouldBeAppliedToInjectionHost = ((SuppressIntentionActionFromFix)action).isShouldBeAppliedToInjectionHost();
+ if (editor instanceof EditorWindow && shouldBeAppliedToInjectionHost == ThreeState.YES) {
+ return false;
+ }
+ if (!(editor instanceof EditorWindow) && shouldBeAppliedToInjectionHost == ThreeState.NO) {
+ return false;
+ }
+ }
+
if (action instanceof PsiElementBaseIntentionAction) {
if (!inProject || psiElement == null || !((PsiElementBaseIntentionAction)action).isAvailable(project, editor, psiElement)) return false;
}
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
-import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
/**
* @author gregsh
*/
-public class RunIdeConsoleAction extends ActionGroup implements DumbAware {
+public class RunIdeConsoleAction extends DumbAwareAction {
private static final String DEFAULT_FILE_NAME = "ide-scripting";
private static final Key<WeakReference<ConsoleView>> CONSOLE_VIEW_KEY = Key.create("CONSOLE_VIEW_KEY");
runConsole(e, ourEngines.values().iterator().next());
}
else {
- super.actionPerformed(e);
- }
- }
-
- @NotNull
- @Override
- public AnAction[] getChildren(@Nullable AnActionEvent e) {
- if (e == null) return EMPTY_ARRAY;
- return ContainerUtil.map2Array(ourEngines.values(), AnAction.class, new NotNullFunction<ScriptEngineFactory, AnAction>() {
- @NotNull
- @Override
- public AnAction fun(final ScriptEngineFactory engine) {
- return new AnAction(engine.getLanguageName()) {
+ DefaultActionGroup actions = new DefaultActionGroup(
+ ContainerUtil.map(ourEngines.values(), new NotNullFunction<ScriptEngineFactory, AnAction>() {
+ @NotNull
@Override
- public void actionPerformed(@NotNull AnActionEvent e) {
- runConsole(e, engine);
+ public AnAction fun(final ScriptEngineFactory engine) {
+ return new AnAction(engine.getLanguageName()) {
+ @Override
+ public void actionPerformed(@NotNull AnActionEvent e) {
+ runConsole(e, engine);
+ }
+ };
}
- };
- }
- });
+ })
+ );
+ JBPopupFactory.getInstance().createActionGroupPopup("Script Engine", actions, e.getDataContext(), JBPopupFactory.ActionSelectionAid.NUMBERING, false).
+ showInBestPositionFor(e.getDataContext());
+ }
}
protected void runConsole(@NotNull AnActionEvent e, @NotNull ScriptEngineFactory engine) {
}
}
- private static class MyFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile, InternalFileType {
+ private static class MyFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile {
MyFileType() {
super(PlainTextLanguage.INSTANCE);
return myRoot;
}
+ public boolean hasMessages(@NotNull Set<ErrorTreeElementKind> kinds) {
+ synchronized (myLock) {
+ for (Map.Entry<ErrorTreeElementKind, List<ErrorTreeElement>> entry : mySimpleMessages.entrySet()) {
+ if (kinds.contains(entry.getKey())) {
+ final List<ErrorTreeElement> messages = entry.getValue();
+ if (messages != null && !messages.isEmpty()) {
+ return true;
+ }
+ }
+ }
+ for (Map.Entry<String, List<NavigatableMessageElement>> entry : myGroupNameToMessagesMap.entrySet()) {
+ final List<NavigatableMessageElement> messages = entry.getValue();
+ if (messages != null && !messages.isEmpty()) {
+ for (NavigatableMessageElement message : messages) {
+ if (kinds.contains(message.getKind())) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
@Override
public ErrorTreeElement[] getChildElements(Object element) {
if (element == myRoot) {
return;
}
myUpdateAlarm.cancelAllRequests();
+ if (selected == null) {
+ hideHint();
+ return;
+ }
+ if (!selected.equals(myKey)) {
+ hideHint();
+ }
myUpdateAlarm.addRequest(new Runnable() {
@Override
public void run() {
}, 10);
}
- private void doHandleSelectionChange(KeyType selected, boolean processIfUnfocused) {
- Window window = SwingUtilities.getWindowAncestor(myComponent);
- if (selected == null
- || window == null
- || !window.isActive()
- || !myEnabled
+ private void doHandleSelectionChange(@NotNull KeyType selected, boolean processIfUnfocused) {
+ if (!myEnabled
|| !myComponent.isEnabled()
|| !myComponent.isShowing()
|| !myComponent.getVisibleRect().intersects(getVisibleRect(selected))
else {
Dimension size = myTipComponent.getPreferredSize();
myPopup.setBounds(location.x, location.y, size.width, size.height);
+ myPopup.setHeavyWeight(hasOwnedWindows());
if (!myPopup.isVisible()) {
myPopup.setVisible(true);
}
return false;
}
+ private boolean hasOwnedWindows() {
+ Window owner = SwingUtilities.getWindowAncestor(myComponent);
+ Window popup = SwingUtilities.getWindowAncestor(myTipComponent);
+ for (Window other : owner.getOwnedWindows()) {
+ if (popup != other && other.isVisible()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private void hideHint() {
myUpdateAlarm.cancelAllRequests();
if (myPopup.isVisible()) {
myView.setBounds(location.x, location.y, size.width, size.height);
if (myView.isVisible()) {
myView.invalidate();
+ myView.validate();
myView.repaint();
}
}
<action id="EmmetNextEditPoint" class="com.intellij.codeInsight.template.emmet.actions.GoToEditPointAction$Forward"
text="Next Emmet Edit Point" description="Go to next Emmet edit point">
- <keyboard-shortcut first-keystroke="alt shift OPEN_BRACKET" keymap="$default"/>
+ <keyboard-shortcut first-keystroke="alt shift CLOSE_BRACKET" keymap="$default"/>
<keyboard-shortcut first-keystroke="control alt RIGHT" keymap="Mac OS X 10.5+" replace-all="true"/>
</action>
<action id="EmmetPreviousEditPoint" class="com.intellij.codeInsight.template.emmet.actions.GoToEditPointAction$Backward"
text="Previous Emmet Edit Point" description="Go to previous Emmet edit point">
- <keyboard-shortcut first-keystroke="alt shift CLOSE_BRACKET" keymap="$default"/>
+ <keyboard-shortcut first-keystroke="alt shift OPEN_BRACKET" keymap="$default"/>
<keyboard-shortcut first-keystroke="control alt LEFT" keymap="Mac OS X 10.5+" replace-all="true"/>
</action>
</group>
jdk.combo.box.none.item=<None>
jdk.combo.box.invalid.item={0} [Invalid]
module.libraries.target.jdk.project.radio=<html><b>&Project SDK:</b><br>This SDK is default for all project modules.<br>\
- A module specific SDK can be configured for each of the modules as required</html>
+ A module specific SDK can be configured for each of the modules as required.</html>
module.libraries.target.jdk.module.radio=&Module SDK:
module.libraries.target.jdk.select.title=Select Project SDK
module.libraries.javadoc.url.button=Specify Documentation &URL...
project.module.compile.output.path=Use module compile output path
project.compiler.output=<html><b>Project compiler output:</b><br>This path is used to store all project compilation results. <br>\
A directory corresponding to each module is created under this path. <br>This directory contains two subdirectories: Production and Test for production code and test sources, respectively.<br>\
- A module specific compiler output path can be configured for each of the modules as required</html>
+ A module specific compiler output path can be configured for each of the modules as required.</html>
find.usages.action.text=Find Usages
dependencies.used.in.popup.title=Used in
project.language.level=<html><b>Project language level:</b><br>This language level is default for all project modules.<br>\
- A module specific language level can be configured for each of the modules as required</html>
+ A module specific language level can be configured for each of the modules as required.</html>
classpath.panel.analyze=Analyze
classpath.panel.navigate.action.text=Navigate
output.tab.title=Output
descriptors.addAll(intentions.inspectionFixesToShow);
descriptors.addAll(intentions.guttersToShow);
- PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
+ final int fileOffset = editor.getCaretModel().getOffset();
+ PsiElement hostElement = file.getViewProvider().findElementAt(fileOffset, file.getLanguage());
+ PsiElement injectedElement = InjectedLanguageUtil.findElementAtNoCommit(file, fileOffset);
+
+ PsiFile injectedFile = injectedElement != null ? injectedElement.getContainingFile() : null;
+ Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile);
+
List<IntentionAction> result = new ArrayList<IntentionAction>();
List<HighlightInfo> infos = DaemonCodeAnalyzerEx.getInstanceEx(file.getProject()).getFileLevelHighlights(file.getProject(), file);
for (HighlightInfo info : infos) {
for (Pair<HighlightInfo.IntentionActionDescriptor, TextRange> pair : info.quickFixActionRanges) {
HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first;
- if (actionInGroup.getAction().isAvailable(file.getProject(), editor, file)) {
+ final IntentionAction action = actionInGroup.getAction();
+
+ if (ShowIntentionActionsHandler.availableFor(file, editor, action)
+ || (injectedElement != null && hostElement != injectedElement && ShowIntentionActionsHandler.availableFor(injectedFile, injectedEditor, action))) {
descriptors.add(actionInGroup);
}
}
// add all intention options for simplicity
for (HighlightInfo.IntentionActionDescriptor descriptor : descriptors) {
result.add(descriptor.getAction());
- List<IntentionAction> options = descriptor.getOptions(element,editor);
- if (options != null) {
- for (IntentionAction option : options) {
- if (option.isAvailable(file.getProject(), editor, file)) {
- result.add(option);
+
+ if (injectedElement != null && injectedElement != hostElement) {
+ List<IntentionAction> options = descriptor.getOptions(injectedElement, injectedEditor);
+ if (options != null) {
+ for (IntentionAction option : options) {
+ if (ShowIntentionActionsHandler.availableFor(injectedFile, injectedEditor, option)) {
+ result.add(option);
+ }
+ }
+ }
+ }
+
+ if (hostElement != null) {
+ List<IntentionAction> options = descriptor.getOptions(hostElement, editor);
+ if (options != null) {
+ for (IntentionAction option : options) {
+ if (ShowIntentionActionsHandler.availableFor(file, editor, option)) {
+ result.add(option);
+ }
}
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
+ if ("equals".equals(method.getName())) return proxy == args[0];
+ if ("hashCode".equals(method.getName())) return hashCode();
return method.invoke(myRemote, args);
}
else {
/**
* JIRA 4.4.5, REST API 2.0.alpha1
*/
- @NonNls private static final String JIRA_4_TEST_SERVER_URL = "http://trackers-tests.labs.intellij.net:8014";
+ @NonNls private static final String JIRA_4_TEST_SERVER_URL = "http://idea-qa-task-2.labs.intellij.net:8014";
/**
* JIRA 5.0.6, REST API 2.0
*/
import com.intellij.lang.Language;
import com.intellij.lang.xml.XMLLanguage;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
+import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlText;
import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.util.ObjectUtils;
/**
* @author Dennis.Ushakov
*/
public class EmmetEditPointUtil {
- public static void moveForward(Editor editor, PsiFile file) {
+ public static void moveForward(final Editor editor, final PsiFile file) {
if (!isApplicableFile(file)) return;
moveToNextPoint(editor, file, editor.getCaretModel().getOffset(), 1);
}
- public static void moveBackward(Editor editor, PsiFile file) {
+ public static void moveBackward(final Editor editor, final PsiFile file) {
if (!isApplicableFile(file)) return;
moveToNextPoint(editor, file, editor.getCaretModel().getOffset(), -1);
}
private static void moveToNextPoint(Editor editor, PsiFile file, int offset, int inc) {
final Document doc = editor.getDocument();
+ final TemplateLanguageFileViewProvider provider = ObjectUtils.tryCast(file.getViewProvider(), TemplateLanguageFileViewProvider.class);
+ final Language additionalLanguage = provider != null ? provider.getTemplateDataLanguage() : null;
PsiDocumentManager.getInstance(file.getProject()).commitDocument(doc);
for (int i = offset + inc; i < doc.getTextLength() && i >= 0; i += inc) {
PsiElement current = InjectedLanguageUtil.findElementAtNoCommit(file, i);
- if (current == null) continue;
+ if (checkAndMove(editor, doc, i, current)) return;
+ if (additionalLanguage != null) {
+ current = provider.findElementAt(i, additionalLanguage);
+ if (checkAndMove(editor, doc, i, current)) return;
+ }
+ }
+ }
- if (current.getParent() instanceof XmlText) {
- final int line = doc.getLineNumber(i);
- final int lineStart = doc.getLineStartOffset(line);
- final int lineEnd = doc.getLineEndOffset(line);
- if (lineEnd == offset) continue;
+ private static boolean checkAndMove(Editor editor, Document doc, int offset, PsiElement current) {
+ if (current == null) return false;
+ if (current.getParent() instanceof XmlText) {
+ final int line = doc.getLineNumber(offset);
+ final int lineStart = doc.getLineStartOffset(line);
+ final int lineEnd = doc.getLineEndOffset(line);
- final CharSequence text = doc.getCharsSequence().subSequence(lineStart, lineEnd);
- if (StringUtil.isEmptyOrSpaces(text) && moveCaret(editor, current, lineEnd)) {
- return;
- }
- } else if (isEmptyEditPoint(current) && moveCaret(editor, current, current.getTextRange().getStartOffset())) {
- return;
+ final CharSequence text = doc.getCharsSequence().subSequence(lineStart, lineEnd);
+ if (StringUtil.isEmptyOrSpaces(text) && moveCaret(editor, current, lineEnd)) {
+ return true;
}
+ } else if (isEmptyEditPoint(current) && moveCaret(editor, current, current.getTextRange().getStartOffset())) {
+ return true;
}
+ return false;
}
private static boolean moveCaret(Editor editor, PsiElement current, int offset) {
editor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, current.getContainingFile());
- if (editor.getCaretModel().getOffset() == offset) return false;
- editor.getCaretModel().moveToOffset(offset);
+ final CaretModel caretModel = editor.getCaretModel();
+ if (caretModel.getOffset() == offset) return false;
+
+ caretModel.moveToOffset(offset);
+ final Caret caret = caretModel.getCurrentCaret();
+ ScrollingModel scrollingModel = editor.getScrollingModel();
+ if (caret == caretModel.getPrimaryCaret()) {
+ scrollingModel.scrollToCaret(ScrollType.RELATIVE);
+ }
return true;
}
static boolean isApplicableFile(PsiFile file) {
if (file == null) return false;
for (Language language : file.getViewProvider().getLanguages()) {
- if (language.isKindOf(XMLLanguage.INSTANCE)) return true;
+ if (language.isKindOf(XMLLanguage.INSTANCE) || "JavaScript".equals(language.getID())) return true;
}
return false;
}
*/
package com.intellij.codeInsight.template.emmet.actions;
-import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.editor.actionSystem.EditorAction;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import com.intellij.openapi.project.DumbAware;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import org.jetbrains.annotations.Nullable;
/**
* @author Dennis.Ushakov
*/
-public abstract class GoToEditPointAction extends DumbAwareAction {
- @Override
- public void update(AnActionEvent e) {
- final Editor editor = getEditor(e);
- final PsiFile file = getFile(e);
- final boolean isApplicable = editor != null && EmmetEditPointUtil.isApplicableFile(file);
- e.getPresentation().setEnabledAndVisible(isApplicable);
+public abstract class GoToEditPointAction extends EditorAction implements DumbAware {
+ protected GoToEditPointAction(EditorActionHandler defaultHandler) {
+ super(defaultHandler);
}
- private static PsiFile getFile(AnActionEvent e) {
- return CommonDataKeys.PSI_FILE.getData(e.getDataContext());
+ @Override
+ public void update(Editor editor, Presentation presentation, DataContext dataContext) {
+ super.update(editor, presentation, dataContext);
+ final PsiFile file = getFile(dataContext);
+ if (!EmmetEditPointUtil.isApplicableFile(file)) {
+ presentation.setEnabledAndVisible(false);
+ }
}
- private static Editor getEditor(AnActionEvent e) {
- final Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
- return editor != null ? InjectedLanguageUtil.getTopLevelEditor(editor) : null;
+ private static PsiFile getFile(DataContext context) {
+ return CommonDataKeys.PSI_FILE.getData(context);
}
public static class Forward extends GoToEditPointAction {
- @Override
- public void actionPerformed(AnActionEvent e) {
- EmmetEditPointUtil.moveForward(getEditor(e), getFile(e));
+ public Forward() {
+ super(new EditorActionHandler(true) {
+ @Override
+ protected void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
+ EmmetEditPointUtil.moveForward(editor, getFile(dataContext));
+ }
+ });
}
}
public static class Backward extends GoToEditPointAction {
- @Override
- public void actionPerformed(AnActionEvent e) {
- EmmetEditPointUtil.moveBackward(getEditor(e), getFile(e));
+ public Backward() {
+ super(new EditorActionHandler(true) {
+ @Override
+ protected void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
+ EmmetEditPointUtil.moveBackward(editor, getFile(dataContext));
+ }
+ });
}
}
}