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;
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;
29 public abstract class TailType {
31 public static int insertChar(final Editor editor, final int tailOffset, final char c) {
32 return insertChar(editor, tailOffset, c, true);
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));
42 return moveCaret(editor, tailOffset, 1);
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);
50 return tailOffset + delta;
53 public static final TailType UNKNOWN = new TailType(){
54 public int processTail(final Editor editor, final int tailOffset) {
58 public String toString() {
64 public static final TailType NONE = new TailType(){
65 public int processTail(final Editor editor, final int tailOffset) {
69 public String toString() {
74 public static final TailType SEMICOLON = new CharTailType(';');
75 public static final TailType EXCLAMATION = new CharTailType('!');
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, ' ');
86 public String toString() {
91 * insert a space, overtype if already present
93 public static final TailType SPACE = new CharTailType(' ');
95 * always insert a space
97 public static final TailType INSERT_SPACE = new CharTailType(' ', false);
99 * insert a space unless there's one at the caret position already, followed by a sowrd
101 public static final TailType HUMBLE_SPACE_BEFORE_WORD = new CharTailType(' ', false) {
104 public boolean isApplicable(@NotNull InsertionContext context) {
105 CharSequence text = context.getDocument().getCharsSequence();
106 int tail = context.getTailOffset();
107 if (text.length() > tail + 1 && text.charAt(tail) == ' ' && Character.isLetter(text.charAt(tail + 1))) {
110 return super.isApplicable(context);
114 public String toString() {
115 return "HUMBLE_SPACE_BEFORE_WORD";
118 public static final TailType DOT = new CharTailType('.');
120 public static final TailType CASE_COLON = new CharTailType(':');
121 public static final TailType COND_EXPR_COLON = new TailType(){
122 public int processTail(final Editor editor, final int tailOffset) {
123 Document document = editor.getDocument();
124 int textLength = document.getTextLength();
125 CharSequence chars = document.getCharsSequence();
127 if (tailOffset < textLength - 1 && chars.charAt(tailOffset) == ' ' && chars.charAt(tailOffset + 1) == ':') {
128 return moveCaret(editor, tailOffset, 2);
130 if (tailOffset < textLength && chars.charAt(tailOffset) == ':') {
131 return moveCaret(editor, tailOffset, 1);
133 document.insertString(tailOffset, " : ");
134 return moveCaret(editor, tailOffset, 3);
137 public String toString() {
138 return "COND_EXPR_COLON";
142 public static final TailType EQ = new TailTypeEQ();
144 public static class TailTypeEQ extends TailType {
146 protected boolean isSpaceAroundAssignmentOperators(Editor editor, int tailOffset) {
147 return CodeStyleSettingsManager.getSettings(editor.getProject()).SPACE_AROUND_ASSIGNMENT_OPERATORS;
150 public int processTail(final Editor editor, int tailOffset) {
151 Document document = editor.getDocument();
152 int textLength = document.getTextLength();
153 CharSequence chars = document.getCharsSequence();
154 if (tailOffset < textLength - 1 && chars.charAt(tailOffset) == ' ' && chars.charAt(tailOffset + 1) == '='){
155 return moveCaret(editor, tailOffset, 2);
157 if (tailOffset < textLength && chars.charAt(tailOffset) == '='){
158 return moveCaret(editor, tailOffset, 1);
160 if (isSpaceAroundAssignmentOperators(editor, tailOffset)) {
161 document.insertString(tailOffset, " =");
162 tailOffset = moveCaret(editor, tailOffset, 2);
163 tailOffset = insertChar(editor, tailOffset, ' ');
166 document.insertString(tailOffset, "=");
167 tailOffset = moveCaret(editor, tailOffset, 1);
173 public static final TailType LPARENTH = new CharTailType('(');
175 public abstract int processTail(final Editor editor, int tailOffset);
177 public static TailType createSimpleTailType(final char c) {
178 return new CharTailType(c);
181 public boolean isApplicable(@NotNull final InsertionContext context) {