NotNull, dispose
[fedora-idea.git] / platform / lang-impl / src / com / intellij / codeInsight / completion / CompletionUtil.java
blobdd9b2ac3fc51500b322336278804e6b7a0d99939
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.
17 package com.intellij.codeInsight.completion;
19 import com.intellij.codeInsight.CodeInsightSettings;
20 import com.intellij.codeInsight.TailType;
21 import com.intellij.codeInsight.lookup.Lookup;
22 import com.intellij.codeInsight.lookup.LookupElement;
23 import com.intellij.codeInsight.lookup.LookupItem;
24 import com.intellij.featureStatistics.FeatureUsageTracker;
25 import com.intellij.openapi.extensions.Extensions;
26 import com.intellij.openapi.fileTypes.FileType;
27 import com.intellij.openapi.util.Key;
28 import com.intellij.openapi.util.NotNullLazyValue;
29 import com.intellij.openapi.editor.Document;
30 import com.intellij.openapi.editor.Editor;
31 import com.intellij.patterns.ElementPattern;
32 import static com.intellij.patterns.PlatformPatterns.character;
33 import com.intellij.psi.PsiElement;
34 import com.intellij.psi.PsiFile;
35 import com.intellij.psi.PsiDocumentManager;
36 import com.intellij.psi.filters.TrueFilter;
37 import com.intellij.util.containers.HashMap;
38 import org.jetbrains.annotations.NonNls;
39 import org.jetbrains.annotations.NotNull;
40 import org.jetbrains.annotations.Nullable;
42 public class CompletionUtil {
43 public static final Key<TailType> TAIL_TYPE_ATTR = LookupItem.TAIL_TYPE_ATTR;
45 private static final CompletionData ourGenericCompletionData = new CompletionData() {
47 final CompletionVariant variant = new CompletionVariant(PsiElement.class, TrueFilter.INSTANCE);
48 variant.addCompletionFilter(TrueFilter.INSTANCE, TailType.NONE);
49 registerVariant(variant);
52 private static final HashMap<FileType, NotNullLazyValue<CompletionData>> ourCustomCompletionDatas = new HashMap<FileType, NotNullLazyValue<CompletionData>>();
54 public static final @NonNls String DUMMY_IDENTIFIER = CompletionInitializationContext.DUMMY_IDENTIFIER;
55 public static final @NonNls String DUMMY_IDENTIFIER_TRIMMED = DUMMY_IDENTIFIER.trim();
57 public static boolean startsWith(String text, String prefix) {
58 //if (text.length() <= prefix.length()) return false;
59 return toLowerCase(text).startsWith(toLowerCase(prefix));
62 private static String toLowerCase(String text) {
63 CodeInsightSettings settings = CodeInsightSettings.getInstance();
64 switch (settings.COMPLETION_CASE_SENSITIVE) {
65 case CodeInsightSettings.NONE:
66 return text.toLowerCase();
68 case CodeInsightSettings.FIRST_LETTER: {
69 StringBuffer buffer = new StringBuffer();
70 buffer.append(text.toLowerCase());
71 if (buffer.length() > 0) {
72 buffer.setCharAt(0, text.charAt(0));
74 return buffer.toString();
77 default:
78 return text;
82 public static CompletionData getCompletionDataByElement(final PsiFile file) {
84 final CompletionData mainData = getCompletionDataByFileType(file.getFileType());
85 return mainData != null ? mainData : ourGenericCompletionData;
88 public static void registerCompletionData(FileType fileType, NotNullLazyValue<CompletionData> completionData) {
89 ourCustomCompletionDatas.put(fileType, completionData);
92 public static void registerCompletionData(FileType fileType, final CompletionData completionData) {
93 registerCompletionData(fileType, new NotNullLazyValue<CompletionData>() {
94 @NotNull
95 protected CompletionData compute() {
96 return completionData;
98 });
101 @Nullable
102 public static CompletionData getCompletionDataByFileType(FileType fileType) {
103 for(CompletionDataEP ep: Extensions.getExtensions(CompletionDataEP.EP_NAME)) {
104 if (ep.fileType.equals(fileType.getName())) {
105 return ep.getHandler();
108 final NotNullLazyValue<CompletionData> lazyValue = ourCustomCompletionDatas.get(fileType);
109 return lazyValue == null ? null : lazyValue.getValue();
113 static boolean isOverwrite(final LookupElement item, final char completionChar) {
114 return completionChar != Lookup.AUTO_INSERT_SELECT_CHAR
115 ? completionChar == Lookup.REPLACE_SELECT_CHAR
116 : item.getUserData(LookupItem.OVERWRITE_ON_AUTOCOMPLETE_ATTR) != null;
120 public static boolean shouldShowFeature(final CompletionParameters parameters, @NonNls final String id) {
121 return FeatureUsageTracker.getInstance().isToBeShown(id, parameters.getPosition().getProject());
124 public static String findJavaIdentifierPrefix(final PsiElement insertedElement, final int offset) {
125 return findIdentifierPrefix(insertedElement, offset, character().javaIdentifierPart(), character().javaIdentifierStart());
128 public static String findIdentifierPrefix(PsiElement insertedElement, int offset, ElementPattern<Character> idPart,
129 ElementPattern<Character> idStart) {
130 if(insertedElement == null) return "";
131 final String text = insertedElement.getText();
132 final int offsetInElement = offset - insertedElement.getTextRange().getStartOffset();
133 int start = offsetInElement - 1;
134 while (start >=0 ) {
135 if (!idPart.accepts(text.charAt(start))) break;
136 --start;
138 while (start + 1 < offsetInElement && !idStart.accepts(text.charAt(start + 1))) {
139 start++;
142 return text.substring(start + 1, offsetInElement).trim();
145 static InsertionContext emulateInsertion(InsertionContext oldContext, int newStart, final LookupElement item) {
146 final InsertionContext newContext = newContext(oldContext, item);
147 emulateInsertion(item, newStart, newContext);
148 return newContext;
151 private static InsertionContext newContext(InsertionContext oldContext, LookupElement forElement) {
152 final Editor editor = oldContext.getEditor();
153 return new InsertionContext(new OffsetMap(editor.getDocument()), Lookup.AUTO_INSERT_SELECT_CHAR, new LookupElement[]{forElement}, oldContext.getFile(), editor);
156 public static InsertionContext newContext(InsertionContext oldContext, LookupElement forElement, int startOffset, int tailOffset) {
157 final InsertionContext context = newContext(oldContext, forElement);
158 setOffsets(context, startOffset, tailOffset);
159 return context;
162 public static void emulateInsertion(LookupElement item, int offset, InsertionContext context) {
163 setOffsets(context, offset, offset);
165 final Editor editor = context.getEditor();
166 final Document document = editor.getDocument();
167 final String lookupString = item.getLookupString();
169 document.insertString(offset, lookupString);
170 editor.getCaretModel().moveToOffset(context.getTailOffset());
171 PsiDocumentManager.getInstance(context.getProject()).commitDocument(document);
172 item.handleInsert(context);
175 private static void setOffsets(InsertionContext context, int offset, final int tailOffset) {
176 final OffsetMap offsetMap = context.getOffsetMap();
177 offsetMap.addOffset(CompletionInitializationContext.START_OFFSET, offset);
178 offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, tailOffset);
179 offsetMap.addOffset(CompletionInitializationContext.SELECTION_END_OFFSET, tailOffset);
180 context.setTailOffset(tailOffset);