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.
17 package com
.intellij
.codeInsight
.completion
;
19 import com
.intellij
.codeInsight
.lookup
.LookupElement
;
20 import com
.intellij
.codeInsight
.lookup
.LookupItem
;
21 import com
.intellij
.codeInsight
.template
.Template
;
22 import com
.intellij
.codeInsight
.template
.TemplateEditingAdapter
;
23 import com
.intellij
.codeInsight
.template
.TemplateManager
;
24 import com
.intellij
.openapi
.command
.CommandProcessor
;
25 import com
.intellij
.openapi
.diagnostic
.Logger
;
26 import com
.intellij
.openapi
.editor
.Document
;
27 import com
.intellij
.openapi
.editor
.Editor
;
28 import com
.intellij
.openapi
.editor
.RangeMarker
;
29 import com
.intellij
.openapi
.util
.Key
;
30 import com
.intellij
.psi
.PsiDocumentManager
;
31 import com
.intellij
.psi
.PsiFile
;
32 import org
.jetbrains
.annotations
.NotNull
;
37 public abstract class TemplateInsertHandler
implements InsertHandler
{
38 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInsight.completion.TemplateInsertHandler");
40 protected static final Object EXPANDED_TEMPLATE_ATTR
= Key
.create("EXPANDED_TEMPLATE_ATTR");
42 public void handleInsert(final InsertionContext context
, final LookupElement item
) {
43 context
.setAddCompletionChar(false);
44 if (isTemplateToBeCompleted(item
)) {
45 handleTemplate((LookupItem
) item
, context
);
49 protected static boolean isTemplateToBeCompleted(final LookupElement lookupItem
) {
50 return lookupItem
instanceof LookupItem
&& lookupItem
.getObject() instanceof Template
51 && ((LookupItem
)lookupItem
).getAttribute(EXPANDED_TEMPLATE_ATTR
) == null;
54 protected void handleTemplate(@NotNull final LookupItem lookupItem
,
55 @NotNull final InsertionContext context
) {
56 LOG
.assertTrue(CommandProcessor
.getInstance().getCurrentCommand() != null);
57 PsiDocumentManager
.getInstance(context
.getProject()).commitDocument(context
.getEditor().getDocument());
59 Template template
= (Template
)lookupItem
.getObject();
61 final Editor editor
= context
.getEditor();
62 final Document document
= editor
.getDocument();
64 final int templateStartOffset
= context
.getStartOffset();
65 document
.replaceString(templateStartOffset
, templateStartOffset
+ lookupItem
.getLookupString().length(), "");
67 final RangeMarker offsetRangeMarker
= document
.createRangeMarker(templateStartOffset
, templateStartOffset
);
69 TemplateManager
.getInstance(editor
.getProject()).startTemplate(editor
, template
, new TemplateEditingAdapter() {
70 public void templateFinished(Template template
, boolean brokenOff
) {
71 lookupItem
.setAttribute(EXPANDED_TEMPLATE_ATTR
, Boolean
.TRUE
);
73 if (!offsetRangeMarker
.isValid()) return;
75 final Editor editor
= context
.getEditor();
76 final int startOffset
= offsetRangeMarker
.getStartOffset();
77 final int endOffset
= editor
.getCaretModel().getOffset();
78 String lookupString
= editor
.getDocument().getCharsSequence().subSequence(startOffset
, endOffset
).toString();
79 lookupItem
.setLookupString(lookupString
);
81 final OffsetMap offsetMap
= context
.getOffsetMap();
82 offsetMap
.addOffset(CompletionInitializationContext
.SELECTION_END_OFFSET
, endOffset
);
83 offsetMap
.addOffset(CompletionInitializationContext
.IDENTIFIER_END_OFFSET
, endOffset
);
85 final PsiFile psiFile
= context
.getFile();
87 InsertionContext newContext
=
88 new InsertionContext(offsetMap
, context
.getCompletionChar(), LookupElement
.EMPTY_ARRAY
, psiFile
, editor
);
90 populateInsertMap(psiFile
, offsetMap
);
92 handleInsert(newContext
, lookupItem
);
97 protected void populateInsertMap(@NotNull final PsiFile file
, @NotNull final OffsetMap offsetMap
) {