IDEA-136406 Complete current statement doesn't insert a method body for default metho...
[idea/community.git] / java / java-impl / src / com / intellij / codeInsight / editorActions / smartEnter / MissingMethodBodyFixer.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.codeInsight.editorActions.smartEnter;
17
18 import com.intellij.openapi.editor.Document;
19 import com.intellij.openapi.editor.Editor;
20 import com.intellij.psi.*;
21 import com.intellij.psi.util.PsiTreeUtil;
22 import com.intellij.util.IncorrectOperationException;
23
24 import static com.intellij.psi.PsiModifier.*;
25
26 /**
27  * Created by IntelliJ IDEA.
28  * User: max
29  * Date: Sep 5, 2003
30  * Time: 7:24:03 PM
31  * To change this template use Options | File Templates.
32  */
33 public class MissingMethodBodyFixer implements Fixer {
34   @Override
35   public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
36     if (!(psiElement instanceof PsiMethod)) return;
37     PsiMethod method = (PsiMethod) psiElement;
38     final PsiClass containingClass = method.getContainingClass();
39     if (!shouldHaveBody(method)) return;
40
41     final PsiCodeBlock body = method.getBody();
42     final Document doc = editor.getDocument();
43     if (body != null) {
44       // See IDEADEV-1093. This is quite hacky heuristic but it seem to be best we can do.
45       String bodyText = body.getText();
46       if (bodyText.startsWith("{")) {
47         final PsiStatement[] statements = body.getStatements();
48         if (statements.length > 0) {
49           if (statements[0] instanceof PsiDeclarationStatement) {
50             if (PsiTreeUtil.getDeepestLast(statements[0]) instanceof PsiErrorElement) {
51               if (containingClass.getRBrace() == null) {
52                 doc.insertString(body.getTextRange().getStartOffset() + 1, "\n}");
53               }
54             }
55           }
56         }
57       }
58       return;
59     }
60     int endOffset = method.getThrowsList().getTextRange().getEndOffset();
61     if (endOffset < doc.getTextLength() && doc.getCharsSequence().charAt(endOffset) == ';') {
62       doc.deleteString(endOffset, endOffset + 1);
63     }
64     doc.insertString(endOffset, "{\n}");
65   }
66
67   static boolean shouldHaveBody(PsiMethod method) {
68     PsiClass containingClass = method.getContainingClass();
69     if (containingClass == null) return false;
70     if (containingClass.isInterface() && !method.hasModifierProperty(DEFAULT)) return false;
71     if (method.hasModifierProperty(ABSTRACT)) return false;
72     return !method.hasModifierProperty(NATIVE);
73   }
74 }