66eac56d1092998721e6d564356ea2fb5d1bb2cd
[idea/community.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / CommitCompletionContributor.java
1 /*
2  * Copyright 2000-2011 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.openapi.vcs;
17
18 import com.intellij.codeInsight.completion.*;
19 import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
20 import com.intellij.codeInsight.lookup.LookupElementBuilder;
21 import com.intellij.openapi.editor.Document;
22 import com.intellij.openapi.progress.ProgressManager;
23 import com.intellij.openapi.project.Project;
24 import com.intellij.openapi.vcs.changes.Change;
25 import com.intellij.openapi.vcs.changes.ChangeList;
26 import com.intellij.openapi.vcs.changes.ChangesUtil;
27 import com.intellij.openapi.vcs.ui.CommitMessage;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.patterns.StandardPatterns;
30 import com.intellij.psi.PsiDocumentManager;
31 import com.intellij.psi.PsiFile;
32 import com.intellij.psi.impl.PsiManagerEx;
33 import com.intellij.ui.TextFieldWithAutoCompletionListProvider;
34 import one.util.streamex.StreamEx;
35 import org.jetbrains.annotations.NotNull;
36
37 import java.util.List;
38
39 /**
40  * @author Dmitry Avdeev
41  */
42 public class CommitCompletionContributor extends CompletionContributor {
43
44   @Override
45   public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
46     PsiFile file = parameters.getOriginalFile();
47     Project project = file.getProject();
48     Document document = PsiDocumentManager.getInstance(project).getDocument(file);
49     if (document == null) return;
50
51     CommitMessage commitMessage = document.getUserData(CommitMessage.DATA_KEY);
52     if (commitMessage == null) return;
53
54     result.stopHere();
55     int count = parameters.getInvocationCount();
56
57     String prefix = TextFieldWithAutoCompletionListProvider.getCompletionPrefix(parameters);
58     if (count == 0 && prefix.length() < 5) {
59       result.restartCompletionOnPrefixChange(StandardPatterns.string().withLength(5));
60       return;
61     }
62     CompletionResultSet resultSet = result.caseInsensitive().withPrefixMatcher(
63       count == 0 ? new PlainPrefixMatcher(prefix, true) : new CamelHumpMatcher(prefix));
64     CompletionResultSet prefixed = result.withPrefixMatcher(new PlainPrefixMatcher(prefix, count == 0));
65     for (ChangeList list : commitMessage.getChangeLists()) {
66       ProgressManager.checkCanceled();
67       for (Change change : list.getChanges()) {
68         ProgressManager.checkCanceled();
69         FilePath beforePath = ChangesUtil.getBeforePath(change);
70         FilePath afterPath = ChangesUtil.getAfterPath(change);
71         if (afterPath != null) {
72           addFilePathName(resultSet, afterPath, false);
73           addLanguageSpecificElements(project, count, prefixed, afterPath);
74         }
75         if (beforePath != null) {
76           if (afterPath == null || !beforePath.getName().equals(afterPath.getName())) {
77             addFilePathName(resultSet, beforePath, true);
78           }
79         }
80       }
81     }
82
83     if (count > 0) {
84       result.caseInsensitive()
85         .withPrefixMatcher(new PlainPrefixMatcher(prefix))
86         .addAllElements(
87           StreamEx.of(VcsConfiguration.getInstance(project).getRecentMessages())
88             .reverseSorted()
89             .map(lookupString -> PrioritizedLookupElement.withPriority(LookupElementBuilder.create(lookupString), Integer.MIN_VALUE)));
90     }
91   }
92
93   private static void addFilePathName(CompletionResultSet resultSet, FilePath filePath, boolean strikeout) {
94     resultSet.addElement(LookupElementBuilder.create(filePath.getName())
95                            .withIcon(filePath.getFileType().getIcon())
96                            .withStrikeoutness(strikeout));
97   }
98
99   private static void addLanguageSpecificElements(Project project, int count, CompletionResultSet prefixed, FilePath filePath) {
100     VirtualFile vFile = filePath.getVirtualFile();
101     if (vFile == null) return;
102     PsiFile psiFile = PsiManagerEx.getInstanceEx(project).findFile(vFile);
103     if (psiFile == null) return;
104     PlainTextSymbolCompletionContributor contributor = PlainTextSymbolCompletionContributorEP.forLanguage(psiFile.getLanguage());
105     if (contributor == null) return;
106     prefixed.addAllElements(contributor.getLookupElements(psiFile, count, prefixed.getPrefixMatcher().getPrefix()));
107   }
108 }