format multiline notifications in event log (IDEA-80305)
[idea/community.git] / platform / lang-api / src / com / intellij / codeInsight / TailType.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;
17
18 import com.intellij.codeInsight.completion.InsertionContext;
19 import com.intellij.openapi.editor.CaretModel;
20 import com.intellij.openapi.editor.Document;
21 import com.intellij.openapi.editor.Editor;
22 import com.intellij.psi.codeStyle.CodeStyleSettings;
23 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
24 import org.jetbrains.annotations.NotNull;
25
26 /**
27  * @author peter
28  */
29 public abstract class TailType {
30
31   public static int insertChar(final Editor editor, final int tailOffset, final char c) {
32     return insertChar(editor, tailOffset, c, true);
33   }
34
35   public static int insertChar(Editor editor, int tailOffset, char c, boolean overwrite) {
36     Document document = editor.getDocument();
37     int textLength = document.getTextLength();
38     CharSequence chars = document.getCharsSequence();
39     if (tailOffset == textLength || !overwrite || chars.charAt(tailOffset) != c){
40       document.insertString(tailOffset, String.valueOf(c));
41     }
42     return moveCaret(editor, tailOffset, 1);
43   }
44
45   protected static int moveCaret(final Editor editor, final int tailOffset, final int delta) {
46     final CaretModel model = editor.getCaretModel();
47     if (model.getOffset() == tailOffset) {
48       model.moveToOffset(tailOffset + delta);
49     }
50     return tailOffset + delta;
51   }
52
53   public static final TailType UNKNOWN = new TailType(){
54     public int processTail(final Editor editor, final int tailOffset) {
55       return tailOffset;
56     }
57
58     public String toString() {
59       return "UNKNOWN";
60     }
61
62   };
63
64   public static final TailType NONE = new TailType(){
65     public int processTail(final Editor editor, final int tailOffset) {
66       return tailOffset;
67     }
68
69     public String toString() {
70       return "NONE";
71     }
72   };
73
74   public static final TailType SEMICOLON = new CharTailType(';');
75   public static final TailType EXCLAMATION = new CharTailType('!');
76
77   public static final TailType COMMA = new TailType(){
78     public int processTail(final Editor editor, int tailOffset) {
79       CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(editor.getProject());
80       if (styleSettings.SPACE_BEFORE_COMMA) tailOffset = insertChar(editor, tailOffset, ' ');
81       tailOffset = insertChar(editor, tailOffset, ',');
82       if (styleSettings.SPACE_AFTER_COMMA) tailOffset = insertChar(editor, tailOffset, ' ');
83       return tailOffset;
84     }
85
86     public String toString() {
87       return "COMMA";
88     }
89   };
90   /**
91    * insert a space, overtype if already present
92    */
93   public static final TailType SPACE = new CharTailType(' ');
94   /**
95    * always insert a space
96    */
97   public static final TailType INSERT_SPACE = new CharTailType(' ', false);
98   /**
99    * insert a space unless there's one at the caret position already
100    */
101   public static final TailType HUMBLE_SPACE = new CharTailType(' ', false) {
102
103     @Override
104     public boolean isApplicable(@NotNull InsertionContext context) {
105       CharSequence text = context.getDocument().getCharsSequence();
106       if (text.length() > context.getTailOffset() && text.charAt(context.getTailOffset()) == ' ') {
107         return false;
108       }
109       return super.isApplicable(context);
110     }
111
112     @Override
113     public String toString() {
114       return "HUMBLE_SPACE";
115     }
116   };
117   public static final TailType DOT = new CharTailType('.');
118
119   public static final TailType CASE_COLON = new CharTailType(':');
120   public static final TailType COND_EXPR_COLON = new TailType(){
121     public int processTail(final Editor editor, final int tailOffset) {
122       Document document = editor.getDocument();
123       int textLength = document.getTextLength();
124       CharSequence chars = document.getCharsSequence();
125
126       if (tailOffset < textLength - 1 && chars.charAt(tailOffset) == ' ' && chars.charAt(tailOffset + 1) == ':') {
127         return moveCaret(editor, tailOffset, 2);
128       }
129       if (tailOffset < textLength && chars.charAt(tailOffset) == ':') {
130         return moveCaret(editor, tailOffset, 1);
131       }
132       document.insertString(tailOffset, " : ");
133       return moveCaret(editor, tailOffset, 3);
134     }
135
136     public String toString() {
137       return "COND_EXPR_COLON";
138     }
139   };
140
141   public static final TailType EQ = new TailTypeEQ();
142
143   public static class TailTypeEQ extends TailType {
144
145     protected boolean isSpaceAroundAssignmentOperators(Editor editor, int tailOffset) {
146       return CodeStyleSettingsManager.getSettings(editor.getProject()).SPACE_AROUND_ASSIGNMENT_OPERATORS;
147     }
148
149     public int processTail(final Editor editor, int tailOffset) {
150       Document document = editor.getDocument();
151       int textLength = document.getTextLength();
152       CharSequence chars = document.getCharsSequence();
153       if (tailOffset < textLength - 1 && chars.charAt(tailOffset) == ' ' && chars.charAt(tailOffset + 1) == '='){
154         return moveCaret(editor, tailOffset, 2);
155       }
156       if (tailOffset < textLength && chars.charAt(tailOffset) == '='){
157         return moveCaret(editor, tailOffset, 1);
158       }
159       if (isSpaceAroundAssignmentOperators(editor, tailOffset)) {
160         document.insertString(tailOffset, " =");
161         tailOffset = moveCaret(editor, tailOffset, 2);
162         tailOffset = insertChar(editor, tailOffset, ' ');
163       }
164       else{
165         document.insertString(tailOffset, "=");
166         tailOffset = moveCaret(editor, tailOffset, 1);
167       }
168       return tailOffset;
169     }
170   }
171
172   public static final TailType LPARENTH = new CharTailType('(');
173
174   public abstract int processTail(final Editor editor, int tailOffset);
175
176   public static TailType createSimpleTailType(final char c) {
177     return new CharTailType(c);
178   }
179
180   public boolean isApplicable(@NotNull final InsertionContext context) {
181     return true;
182   }
183 }