scripting: take PSI into consideration on command detection appcode/163.2025 clion/163.2020 dbe/163.2021 idea/163.2022 phpstorm/163.2024 pycharm/163.2023 rubymine/163.2026 webstorm/163.2027 webstorm/163.2028
authorGregory.Shrago <gregory.shrago@jetbrains.com>
Thu, 28 Jul 2016 22:55:52 +0000 (01:55 +0300)
committerGregory.Shrago <gregory.shrago@jetbrains.com>
Thu, 28 Jul 2016 22:56:50 +0000 (01:56 +0300)
platform/lang-impl/src/com/intellij/execution/console/RunIdeConsoleAction.java

index 22f63cfcaa7f481972ed5113a2ebf28467fd3c40..9a65d66ee7460a40fef9d2cbd3c81e58e103afd6 100644 (file)
@@ -42,8 +42,9 @@ import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VfsUtilCore;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.LeafPsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.ExceptionUtil;
 import com.intellij.util.NotNullFunction;
 import com.intellij.util.ObjectUtils;
 import com.intellij.util.ExceptionUtil;
 import com.intellij.util.NotNullFunction;
 import com.intellij.util.ObjectUtils;
@@ -127,7 +128,8 @@ public class RunIdeConsoleAction extends DumbAwareAction {
                                    @NotNull VirtualFile file,
                                    @NotNull Editor editor,
                                    @NotNull IdeScriptEngine engine) {
                                    @NotNull VirtualFile file,
                                    @NotNull Editor editor,
                                    @NotNull IdeScriptEngine engine) {
-    String command = getCommandText(editor);
+    String command = getCommandText(project, editor);
+    if (StringUtil.isEmptyOrSpaces(command)) return;
     String profile = getProfileText(file);
     RunContentDescriptor descriptor = getConsoleView(project, file);
     ConsoleViewImpl consoleView = (ConsoleViewImpl)descriptor.getExecutionConsole();
     String profile = getProfileText(file);
     RunContentDescriptor descriptor = getConsoleView(project, file);
     ConsoleViewImpl consoleView = (ConsoleViewImpl)descriptor.getExecutionConsole();
@@ -171,12 +173,31 @@ public class RunIdeConsoleAction extends DumbAwareAction {
   }
 
   @NotNull
   }
 
   @NotNull
-  private static String getCommandText(@NotNull Editor editor) {
+  private static String getCommandText(@NotNull Project project, @NotNull Editor editor) {
     TextRange selectedRange = EditorUtil.getSelectionInAnyMode(editor);
     Document document = editor.getDocument();
     TextRange selectedRange = EditorUtil.getSelectionInAnyMode(editor);
     Document document = editor.getDocument();
-    if (selectedRange.getLength() == 0) {
+    if (selectedRange.isEmpty()) {
       int line = document.getLineNumber(selectedRange.getStartOffset());
       selectedRange = TextRange.create(document.getLineStartOffset(line), document.getLineEndOffset(line));
       int line = document.getLineNumber(selectedRange.getStartOffset());
       selectedRange = TextRange.create(document.getLineStartOffset(line), document.getLineEndOffset(line));
+
+      // try detect a non-trivial composite PSI element if there's a PSI file
+      PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+      if (file != null && file.getFirstChild() != null && file.getFirstChild() != file.getLastChild()) {
+        PsiElement e1 = file.findElementAt(selectedRange.getStartOffset());
+        PsiElement e2 = file.findElementAt(selectedRange.getEndOffset());
+        while (e1 != e2 && (e1 instanceof PsiWhiteSpace || e1 != null && StringUtil.isEmptyOrSpaces(e1.getText()))) {
+          e1 = ObjectUtils.chooseNotNull(e1.getNextSibling(), PsiTreeUtil.getDeepestFirst(e1.getParent()));
+        }
+        while (e1 != e2 && (e2 instanceof PsiWhiteSpace || e2 != null && StringUtil.isEmptyOrSpaces(e2.getText()))) {
+          e2 = ObjectUtils.chooseNotNull(e2.getPrevSibling(), PsiTreeUtil.getDeepestLast(e2.getParent()));
+        }
+        if (e1 instanceof LeafPsiElement) e1 = e1.getParent();
+        if (e2 instanceof LeafPsiElement) e2 = e2.getParent();
+        PsiElement parent = e1 == null ? e2 : e2 == null ? e1 : PsiTreeUtil.findCommonParent(e1, e2);
+        if (parent != null && parent != file) {
+          selectedRange = parent.getTextRange();
+        }
+      }
     }
     return document.getText(selectedRange);
   }
     }
     return document.getText(selectedRange);
   }
@@ -242,6 +263,7 @@ public class RunIdeConsoleAction extends DumbAwareAction {
       Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
       VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
       if (project == null || editor == null || virtualFile == null) return;
       Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
       VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(e.getDataContext());
       if (project == null || editor == null || virtualFile == null) return;
+      PsiDocumentManager.getInstance(project).commitAllDocuments();
 
       String extension = virtualFile.getExtension();
       if (extension != null && (engine == null || !engine.getFileExtensions().contains(extension))) {
 
       String extension = virtualFile.getExtension();
       if (extension != null && (engine == null || !engine.getFileExtensions().contains(extension))) {