update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / completion / simple / RParenthTailType.java
blobf6f334ba4cb494d4dbe05a83b336876a0db51915
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.codeInsight.completion.simple;
18 import com.intellij.codeInsight.TailType;
19 import com.intellij.openapi.diagnostic.Logger;
20 import com.intellij.openapi.editor.Document;
21 import com.intellij.openapi.editor.Editor;
22 import com.intellij.openapi.editor.ex.EditorEx;
23 import com.intellij.openapi.editor.highlighter.EditorHighlighter;
24 import com.intellij.openapi.editor.highlighter.HighlighterIterator;
25 import com.intellij.openapi.util.TextRange;
26 import com.intellij.psi.*;
27 import com.intellij.psi.codeStyle.CodeStyleSettings;
28 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
29 import com.intellij.psi.tree.IElementType;
30 import com.intellij.psi.tree.java.IJavaElementType;
31 import com.intellij.psi.util.PsiTreeUtil;
32 import org.jetbrains.annotations.NonNls;
34 /**
35 * @author peter
37 public abstract class RParenthTailType extends TailType {
38 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.simple.RParenthSimpleTailType");
40 private static TextRange getRangeToCheckParensBalance(PsiFile file, final Document document, int startOffset){
41 PsiElement element = file.findElementAt(startOffset);
42 element = PsiTreeUtil.getParentOfType(element, PsiStatement.class, false);
43 if (element != null) {
44 final PsiElement parent = element.getParent();
45 if (parent instanceof PsiLoopStatement) {
46 element = parent;
49 return element == null ? new TextRange(0, document.getTextLength()) : element.getTextRange();
52 protected abstract boolean isSpaceWithinParentheses(CodeStyleSettings styleSettings, Editor editor, final int tailOffset);
54 public int processTail(final Editor editor, int tailOffset) {
55 CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(editor.getProject());
56 int existingRParenthOffset = getExistingRParenthOffset(editor, tailOffset);
58 boolean spaceWithinParens = isSpaceWithinParentheses(styleSettings, editor, tailOffset);
59 if (existingRParenthOffset < 0){
60 if (spaceWithinParens){
61 tailOffset = insertChar(editor, tailOffset, ' ');
63 editor.getDocument().insertString(tailOffset, ")");
64 return moveCaret(editor, tailOffset, 1);
66 if (spaceWithinParens && tailOffset == existingRParenthOffset) {
67 existingRParenthOffset = insertChar(editor, tailOffset, ' ');
69 return moveCaret(editor, existingRParenthOffset, 1);
72 @NonNls
73 public String toString() {
74 return "RParenth";
77 private static int getExistingRParenthOffset(final Editor editor, final int tailOffset) {
78 final Document document = editor.getDocument();
79 if (tailOffset >= document.getTextLength()) return -1;
81 final CharSequence charsSequence = document.getCharsSequence();
82 EditorHighlighter highlighter = ((EditorEx) editor).getHighlighter();
84 int existingRParenthOffset = -1;
85 for(HighlighterIterator iterator = highlighter.createIterator(tailOffset); !iterator.atEnd(); iterator.advance()){
86 final IElementType tokenType = iterator.getTokenType();
88 if ((!(tokenType instanceof IJavaElementType) || !JavaTokenType.WHITE_SPACE_OR_COMMENT_BIT_SET.contains(tokenType)) &&
89 tokenType != TokenType.WHITE_SPACE) {
90 final int start = iterator.getStart();
91 if (iterator.getEnd() == start + 1 && ')' == charsSequence.charAt(start)) {
92 existingRParenthOffset = start;
94 break;
98 if (existingRParenthOffset >= 0){
99 final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(editor.getProject());
100 psiDocumentManager.commitDocument(document);
101 TextRange range = getRangeToCheckParensBalance(psiDocumentManager.getPsiFile(document), document, editor.getCaretModel().getOffset());
102 int balance = calcParensBalance(document, highlighter, range.getStartOffset(), range.getEndOffset());
103 if (balance > 0){
104 return -1;
107 return existingRParenthOffset;
110 private static int calcParensBalance(Document document, EditorHighlighter highlighter, int rangeStart, int rangeEnd){
111 LOG.assertTrue(0 <= rangeStart);
112 LOG.assertTrue(rangeStart <= rangeEnd);
113 LOG.assertTrue(rangeEnd <= document.getTextLength());
115 HighlighterIterator iterator = highlighter.createIterator(rangeStart);
116 int balance = 0;
117 while(!iterator.atEnd() && iterator.getStart() < rangeEnd){
118 IElementType tokenType = iterator.getTokenType();
119 if (tokenType == JavaTokenType.LPARENTH){
120 balance++;
122 else if (tokenType == JavaTokenType.RPARENTH){
123 balance--;
125 iterator.advance();
127 return balance;