Merge branch 'master' into uta/complete-statement
authorAlexey Utkin <alexey.utkin@jetbrains.com>
Wed, 16 Mar 2016 09:34:43 +0000 (12:34 +0300)
committerAlexey Utkin <alexey.utkin@jetbrains.com>
Wed, 16 Mar 2016 09:34:43 +0000 (12:34 +0300)
platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterAfterUnmatchedBraceHandler.java
platform/lang-impl/src/com/intellij/lang/SmartEnterProcessorWithFixers.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/smartEnter/GroovySmartEnterProcessor.java

index 35293104ffdb3e4cab817a8684a2913ce5961159..5af4ca556789d9a036732aeb69009f546dd51ce8 100644 (file)
@@ -31,6 +31,7 @@ import com.intellij.openapi.editor.highlighter.EditorHighlighter;
 import com.intellij.openapi.editor.highlighter.HighlighterIterator;
 import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.NotNullLazyKey;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.TextRange;
@@ -43,11 +44,22 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.util.PsiUtilCore;
 import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.NotNullFunction;
+import com.intellij.util.containers.HashSet;
 import com.intellij.util.text.CharArrayUtil;
 import org.jetbrains.annotations.NotNull;
 
 public class EnterAfterUnmatchedBraceHandler extends EnterHandlerDelegateAdapter {
   private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.enter.EnterAfterUnmatchedBraceHandler");
+  protected static final NotNullLazyKey<HashSet<Language>, PsiFile> LANGUAGE_OVERRIDE = NotNullLazyKey.create(
+    "overrideEnterAfterUnmatchedBraceHandler",
+    new NotNullFunction<PsiFile, HashSet<Language>>() {
+      @NotNull
+      @Override
+      public HashSet<Language> fun(PsiFile holder) {
+        return new HashSet<Language>();
+      }
+    });
 
   @Override
   public Result preprocessEnter(@NotNull final PsiFile file,
@@ -81,7 +93,7 @@ public class EnterAfterUnmatchedBraceHandler extends EnterHandlerDelegateAdapter
    * @return true, if handler is in charge
    */
   public boolean isApplicable(@NotNull PsiFile file, int caretOffset) {
-    return true;
+    return !LANGUAGE_OVERRIDE.getValue(file).contains(PsiUtilCore.getLanguageAtOffset(file, caretOffset));
   }
 
   /**
index a09f393768503634970f148f673153308f199bb8..dd921ee88f854b1f38a39cf89df5077114ad11a3 100644 (file)
@@ -48,7 +48,8 @@ public abstract class SmartEnterProcessorWithFixers extends SmartEnterProcessor
   protected int myFirstErrorOffset = Integer.MAX_VALUE;
 
   private final List<Fixer<? extends SmartEnterProcessorWithFixers>> myFixers = new ArrayList<Fixer<? extends SmartEnterProcessorWithFixers>>();
-  private final List<FixEnterProcessor> myEnterProcessors = new ArrayList<FixEnterProcessor>();
+  protected final List<FixEnterProcessor> myEnterProcessors = new ArrayList<FixEnterProcessor>();
+  private final List<FixEnterProcessor> myAfterEnterProcessors = new ArrayList<FixEnterProcessor>();
 
   protected static void plainEnter(@NotNull final Editor editor) {
     getEnterHandler().execute(editor, ((EditorEx)editor).getDataContext());
@@ -70,12 +71,25 @@ public abstract class SmartEnterProcessorWithFixers extends SmartEnterProcessor
 
   @Override
   public boolean process(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile psiFile) {
+    FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.complete.statement");
+    return invokeProcessor(project, editor, psiFile, false);
+  }
+
+  @Override
+  public boolean processAfterCompletion(@NotNull Editor editor, @NotNull PsiFile psiFile) {
+    return invokeProcessor(psiFile.getProject(), editor, psiFile, true);
+  }
+
+  protected boolean invokeProcessor(@NotNull final Project project,
+                                    @NotNull final Editor editor,
+                                    @NotNull final PsiFile psiFile,
+                                    boolean afterCompletion) {
     final Document document = editor.getDocument();
-    final String textForRollback = document.getText();
+    final CharSequence textForRollback = document.getImmutableCharSequence();
     try {
       editor.putUserData(SMART_ENTER_TIMESTAMP, editor.getDocument().getModificationStamp());
       myFirstErrorOffset = Integer.MAX_VALUE;
-      process(project, editor, psiFile, 0);
+      process(project, editor, psiFile, 0, afterCompletion);
     }
     catch (TooManyAttemptsException e) {
       document.replaceString(0, document.getTextLength(), textForRollback);
@@ -86,9 +100,13 @@ public abstract class SmartEnterProcessorWithFixers extends SmartEnterProcessor
     return true;
   }
 
-  protected void process(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile file, final int attempt)
-    throws TooManyAttemptsException {
-    FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.complete.statement");
+  protected void process(
+    @NotNull final Project project,
+    @NotNull final Editor editor,
+    @NotNull final PsiFile file,
+    final int attempt,
+    boolean afterCompletion) throws TooManyAttemptsException {
+
     if (attempt > MAX_ATTEMPTS) throw new TooManyAttemptsException();
 
     try {
@@ -101,6 +119,7 @@ public abstract class SmartEnterProcessorWithFixers extends SmartEnterProcessor
 
       PsiElement atCaret = getStatementAtCaret(editor, file);
       if (atCaret == null) {
+        processDefaultEnter(project, editor, file);
         return;
       }
 
@@ -116,19 +135,23 @@ public abstract class SmartEnterProcessorWithFixers extends SmartEnterProcessor
           }
           if (isUncommited(project) || !psiElement.isValid()) {
             moveCaretInsideBracesIfAny(editor, file);
-            process(project, editor, file, attempt + 1);
+            process(project, editor, file, attempt + 1, afterCompletion);
             return;
           }
         }
       }
 
-      doEnter(atCaret, file, editor);
+      doEnter(atCaret, file, editor, afterCompletion);
     }
     catch (IncorrectOperationException e) {
       LOG.error(e);
     }
   }
 
+  protected void processDefaultEnter(@NotNull final Project project,
+                                     @NotNull final Editor editor,
+                                     @NotNull final PsiFile file) {}
+
   protected void collectAllElements(@NotNull PsiElement element, @NotNull OrderedSet<PsiElement> result, boolean recursive) {
     result.add(0, element);
     if (doNotStepInto(element)) {
@@ -143,39 +166,45 @@ public abstract class SmartEnterProcessorWithFixers extends SmartEnterProcessor
     }
   }
 
-  protected void doEnter(@NotNull PsiElement atCaret, @NotNull PsiFile file, @NotNull Editor editor) throws IncorrectOperationException {
+  protected void doEnter(@NotNull PsiElement atCaret, @NotNull PsiFile psiFile, @NotNull Editor editor, boolean afterCompletion)
+    throws IncorrectOperationException {
     if (myFirstErrorOffset != Integer.MAX_VALUE) {
       editor.getCaretModel().moveToOffset(myFirstErrorOffset);
       reformat(atCaret);
       return;
     }
 
-    reformat(atCaret);
+    if (reformatBeforeEnter(atCaret)) {
+      reformat(atCaret);
+    }
     commit(editor);
 
     for (FixEnterProcessor enterProcessor : myEnterProcessors) {
-      if (enterProcessor.doEnter(atCaret, file, editor, isModified(editor))) {
+      if (enterProcessor.doEnter(atCaret, psiFile, editor, isModified(editor))) {
         return;
       }
     }
 
-    if (!isModified(editor)) {
+    if (!isModified(editor) && !afterCompletion) {
       plainEnter(editor);
     }
     else {
-      if (myFirstErrorOffset == Integer.MAX_VALUE) {
-        editor.getCaretModel().moveToOffset(atCaret.getTextRange().getEndOffset());
-      }
-      else {
-        editor.getCaretModel().moveToOffset(myFirstErrorOffset);
-      }
+      editor.getCaretModel().moveToOffset(myFirstErrorOffset == Integer.MAX_VALUE
+                                          ? atCaret.getTextRange().getEndOffset()
+                                          : myFirstErrorOffset);
     }
   }
 
+  protected boolean reformatBeforeEnter(@NotNull PsiElement atCaret) {return true;}
+
   protected void addEnterProcessors(FixEnterProcessor... processors) {
     ContainerUtil.addAllNotNull(myEnterProcessors, processors);
   }
 
+  protected void addAfterEnterProcessors(FixEnterProcessor... processors) {
+    ContainerUtil.addAllNotNull(myAfterEnterProcessors, processors);
+  }
+
   protected void addFixers(Fixer<? extends SmartEnterProcessorWithFixers>... fixers) {
     ContainerUtil.addAllNotNull(myFixers, fixers);
   }
@@ -205,4 +234,10 @@ public abstract class SmartEnterProcessorWithFixers extends SmartEnterProcessor
   public void commit(@NotNull Editor editor) { // pull up
     super.commit(editor);
   }
+
+  public void registerUnresolvedError(int offset) {
+    if (myFirstErrorOffset > offset) {
+      myFirstErrorOffset = offset;
+    }
+  }
 }
index 343e0541b0c0c8726c7661b171095bda7192e3e9..b79d652a826d28ec0ede35c4481e40c5e5f63363 100644 (file)
@@ -192,12 +192,6 @@ public class GroovySmartEnterProcessor extends SmartEnterProcessorWithFixers {
     }
   }
 
-  public void registerUnresolvedError(int offset) {
-    if (myFirstErrorOffset > offset) {
-      myFirstErrorOffset = offset;
-    }
-  }
-
   private static PsiElement[] getChildren(PsiElement element) {
     PsiElement psiChild = element.getFirstChild();
     if (psiChild == null) return new PsiElement[0];