mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
-62
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class AbstractBasicToClassNameDelegator extends CompletionContributor {
|
||||
protected abstract boolean isClassNameCompletionSupported(CompletionResultSet result, PsiFile file, PsiElement position);
|
||||
|
||||
protected void updateProperties(LookupElement lookupElement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
|
||||
if (parameters.getCompletionType() != CompletionType.BASIC || parameters.getInvocationCount() == 0) return;
|
||||
|
||||
final PsiFile file = parameters.getOriginalFile();
|
||||
final PsiElement position = parameters.getPosition();
|
||||
if (!isClassNameCompletionSupported(result, file, position)) return;
|
||||
|
||||
final boolean empty = result.runRemainingContributors(parameters, true).isEmpty();
|
||||
|
||||
final CompletionParameters classParams;
|
||||
|
||||
final int invocationCount = parameters.getInvocationCount();
|
||||
if (empty) {
|
||||
classParams = parameters.withType(CompletionType.CLASS_NAME);
|
||||
}
|
||||
else if (invocationCount > 1) {
|
||||
classParams = parameters.withType(CompletionType.CLASS_NAME).withInvocationCount(invocationCount - 1);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CompletionService.getCompletionService().getVariantsFromContributors(classParams, null, new Consumer<CompletionResult>() {
|
||||
public void consume(final CompletionResult lookupElement) {
|
||||
updateProperties(lookupElement.getLookupElement());
|
||||
result.passResult(lookupElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+23
-25
@@ -22,6 +22,7 @@ import com.intellij.lang.LangBundle;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.patterns.PsiJavaElementPattern;
|
||||
@@ -30,7 +31,6 @@ import com.intellij.psi.filters.ClassFilter;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.TrueFilter;
|
||||
import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
|
||||
import com.intellij.psi.filters.types.AssignableFromFilter;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -52,10 +52,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet _result) {
|
||||
if (parameters.isExtendedCompletion()) {
|
||||
if (parameters.getCompletionType() == CompletionType.CLASS_NAME ||
|
||||
parameters.isExtendedCompletion() && mayContainClassName(parameters)) {
|
||||
CompletionResultSet result = _result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
|
||||
addAllClasses(parameters, parameters.getInvocationCount() <= 1,
|
||||
JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
addAllClasses(parameters, parameters.getInvocationCount() <= 1, result.getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
_result.addElement(element);
|
||||
@@ -64,28 +64,29 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean mayContainClassName(CompletionParameters parameters) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
PsiFile file = position.getContainingFile();
|
||||
if (file instanceof PsiPlainTextFile || file.getFileType() instanceof CustomSyntaxTableFileType) {
|
||||
return true;
|
||||
}
|
||||
if (SkipAutopopupInStrings.isInStringLiteral(position)) {
|
||||
return true;
|
||||
}
|
||||
if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void addAllClasses(CompletionParameters parameters,
|
||||
final boolean filterByScope,
|
||||
@NotNull final PrefixMatcher matcher,
|
||||
@NotNull final Consumer<LookupElement> consumer) {
|
||||
final PsiElement insertedElement = parameters.getPosition();
|
||||
|
||||
final ElementFilter filter;
|
||||
if (JavaSmartCompletionContributor.AFTER_THROW_NEW.accepts(insertedElement) ||
|
||||
JavaCompletionContributor.INSIDE_METHOD_THROWS_CLAUSE.accepts(insertedElement) ||
|
||||
JavaCompletionContributor.IN_CATCH_TYPE.accepts(insertedElement) ||
|
||||
JavaCompletionContributor.IN_MULTI_CATCH_TYPE.accepts(insertedElement)) {
|
||||
filter = new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE);
|
||||
}
|
||||
else if (JavaCompletionContributor.IN_RESOURCE_TYPE.accepts(insertedElement)) {
|
||||
filter = new AssignableFromFilter(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE);
|
||||
}
|
||||
else if (IN_TYPE_PARAMETER.accepts(insertedElement)) {
|
||||
filter = new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class));
|
||||
}
|
||||
else {
|
||||
filter = TrueFilter.INSTANCE;
|
||||
}
|
||||
final ElementFilter filter =
|
||||
IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) : TrueFilter.INSTANCE;
|
||||
|
||||
final boolean inJavaContext = parameters.getPosition() instanceof PsiIdentifier;
|
||||
final boolean afterNew = AFTER_NEW.accepts(insertedElement);
|
||||
@@ -107,13 +108,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean lookingForAnnotations = psiElement().afterLeaf("@").accepts(insertedElement);
|
||||
final boolean pkgContext = JavaCompletionUtil.inSomePackage(insertedElement);
|
||||
AllClassesGetter.processJavaClasses(parameters, matcher, filterByScope, new Consumer<PsiClass>() {
|
||||
@Override
|
||||
public void consume(PsiClass psiClass) {
|
||||
if (lookingForAnnotations && !psiClass.isAnnotationType()) return;
|
||||
|
||||
if (filter.isAcceptable(psiClass, insertedElement)) {
|
||||
if (!inJavaContext) {
|
||||
consumer.consume(AllClassesGetter.createLookupItem(psiClass, AllClassesGetter.TRY_SHORTENING));
|
||||
@@ -179,8 +177,8 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
private static boolean shouldShowSecondSmartCompletionHint(final CompletionParameters parameters) {
|
||||
return parameters.getCompletionType() == CompletionType.CLASS_NAME &&
|
||||
parameters.getInvocationCount() == 1 &&
|
||||
return parameters.getCompletionType() == CompletionType.BASIC &&
|
||||
parameters.getInvocationCount() == 2 &&
|
||||
parameters.getOriginalFile().getLanguage().isKindOf(JavaLanguage.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
+26
-12
@@ -19,27 +19,41 @@ import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class XmlBasicToClassNameDelegator extends AbstractBasicToClassNameDelegator {
|
||||
public class XmlBasicToClassNameDelegator extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
protected boolean isClassNameCompletionSupported(CompletionResultSet result, PsiFile file, PsiElement position) {
|
||||
if (!JavaCompletionContributor.mayStartClassName(result)) return false;
|
||||
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
if (parameters.getCompletionType() != CompletionType.BASIC ||
|
||||
!JavaCompletionContributor.mayStartClassName(result) ||
|
||||
!position.getContainingFile().getLanguage().isKindOf(StdLanguages.XML)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return file.getLanguage().isKindOf(StdLanguages.XML);
|
||||
}
|
||||
final boolean empty = result.runRemainingContributors(parameters, true).isEmpty();
|
||||
|
||||
@Override
|
||||
protected void updateProperties(LookupElement lookupElement) {
|
||||
JavaPsiClassReferenceElement classElement = lookupElement.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
if (!empty && parameters.getInvocationCount() == 0) {
|
||||
result.restartCompletionWhenNothingMatches();
|
||||
}
|
||||
|
||||
if (empty || parameters.isExtendedCompletion()) {
|
||||
CompletionService.getCompletionService().getVariantsFromContributors(parameters.delegateToClassName(), null, new Consumer<CompletionResult>() {
|
||||
public void consume(final CompletionResult completionResult) {
|
||||
LookupElement lookupElement = completionResult.getLookupElement();
|
||||
JavaPsiClassReferenceElement classElement = lookupElement.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
}
|
||||
lookupElement.putUserData(XmlCompletionContributor.WORD_COMPLETION_COMPATIBLE, Boolean.TRUE); //todo think of a less dirty interaction
|
||||
result.passResult(completionResult);
|
||||
}
|
||||
});
|
||||
}
|
||||
lookupElement.putUserData(XmlCompletionContributor.WORD_COMPLETION_COMPATIBLE, Boolean.TRUE); //todo think of a less dirty interaction
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -64,6 +65,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
|
||||
String path = "/afterNewThrowable";
|
||||
|
||||
configureByFile(path + "/before1.java");
|
||||
myFixture.type('\n');
|
||||
checkResultByFile(path + "/after1.java");
|
||||
}
|
||||
|
||||
@@ -80,6 +82,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
|
||||
String path = "/afterNewThrowable";
|
||||
|
||||
configureByFile(path + "/before2.java");
|
||||
myFixture.type('\n');
|
||||
checkResultByFile(path + "/after2.java");
|
||||
}
|
||||
|
||||
@@ -94,6 +97,12 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
|
||||
checkResultByFile(getTestName(false) + "_after.txt");
|
||||
}
|
||||
|
||||
public void testInPropertiesFile() throws Exception {
|
||||
myFixture.configureByText("a.properties", "abc = StrinBui<caret>");
|
||||
complete();
|
||||
myFixture.checkResult("abc = java.lang.StringBuilder<caret>");
|
||||
}
|
||||
|
||||
public void testDoubleStringBuffer() throws Exception {
|
||||
createClass("package java.lang; public class StringBuffer {}");
|
||||
doTest();
|
||||
@@ -198,6 +207,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
|
||||
private void cleanupVfs() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
for (VirtualFile file : myFixture.getTempDirFixture().getFile("").getChildren()) {
|
||||
try {
|
||||
file.delete(this);
|
||||
|
||||
@@ -329,6 +329,9 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
final File file = new File(deleted);
|
||||
final RootDescriptor rd = pd.rootsIndex.getModuleAndRoot(file);
|
||||
if (rd != null) {
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Applying deleted path from fs event: " + file.getPath());
|
||||
}
|
||||
pd.fsState.registerDeleted(rd.module, file, rd.isTestRoot, timestamps);
|
||||
}
|
||||
else {
|
||||
@@ -341,6 +344,9 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
final File file = new File(changed);
|
||||
final RootDescriptor rd = pd.rootsIndex.getModuleAndRoot(file);
|
||||
if (rd != null) {
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Applying dirty path from fs event: " + file.getPath());
|
||||
}
|
||||
pd.fsState.markDirty(file, rd, timestamps);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -44,6 +44,10 @@ public final class CompletionParameters {
|
||||
myLookup = lookup;
|
||||
}
|
||||
|
||||
public CompletionParameters delegateToClassName() {
|
||||
return withType(CompletionType.CLASS_NAME).withInvocationCount(myInvocationCount - 1);
|
||||
}
|
||||
|
||||
public CompletionParameters withType(CompletionType type) {
|
||||
return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount, myLookup);
|
||||
}
|
||||
@@ -100,6 +104,6 @@ public final class CompletionParameters {
|
||||
}
|
||||
|
||||
public boolean isExtendedCompletion() {
|
||||
return myCompletionType == CompletionType.CLASS_NAME || myCompletionType == CompletionType.BASIC && myInvocationCount >= 2;
|
||||
return myCompletionType == CompletionType.BASIC && myInvocationCount >= 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,12 @@ package com.intellij.codeInsight.completion;
|
||||
* @author peter
|
||||
*/
|
||||
public enum CompletionType {
|
||||
BASIC, SMART, @Deprecated CLASS_NAME
|
||||
BASIC,
|
||||
SMART,
|
||||
|
||||
/**
|
||||
* Only to be passed to {@link CompletionService#getVariantsFromContributors(CompletionParameters, CompletionContributor, com.intellij.util.Consumer)}
|
||||
* to invoke special class-name providers for various file types where those class names are applicable (e.g. xml, txt, properties, custom)
|
||||
*/
|
||||
CLASS_NAME
|
||||
}
|
||||
|
||||
+12
-6
@@ -39,17 +39,23 @@ public class SkipAutopopupInStrings extends CompletionConfidence {
|
||||
@NotNull
|
||||
@Override
|
||||
public ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) {
|
||||
ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(PsiUtilBase.getLanguageAtOffset(psiFile, offset));
|
||||
if (definition != null) {
|
||||
if (isStringLiteral(contextElement, definition) || isStringLiteral(contextElement.getParent(), definition) ||
|
||||
isStringLiteralWithError(contextElement, definition) || isStringLiteralWithError(contextElement.getParent(), definition)) {
|
||||
return ThreeState.YES;
|
||||
}
|
||||
if (isInStringLiteral(contextElement)) {
|
||||
return ThreeState.YES;
|
||||
}
|
||||
|
||||
return ThreeState.UNSURE;
|
||||
}
|
||||
|
||||
public static boolean isInStringLiteral(PsiElement element) {
|
||||
ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(PsiUtilBase.findLanguageFromElement(element));
|
||||
if (definition == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isStringLiteral(element, definition) || isStringLiteral(element.getParent(), definition) ||
|
||||
isStringLiteralWithError(element, definition) || isStringLiteralWithError(element.getParent(), definition);
|
||||
}
|
||||
|
||||
private static boolean isStringLiteral(PsiElement element, ParserDefinition definition) {
|
||||
return PlatformPatterns.psiElement().withElementType(definition.getStringLiteralElements()).accepts(element);
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class DependentSpacingRule {
|
||||
|
||||
enum Anchor {
|
||||
public enum Anchor {
|
||||
MIN_LINE_FEEDS, MAX_LINE_FEEDS
|
||||
}
|
||||
|
||||
enum Trigger {
|
||||
public enum Trigger {
|
||||
HAS_LINE_FEEDS, DOES_NOT_HAVE_LINE_FEEDS
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -86,6 +86,7 @@ public class CodeCompletionHandlerBase {
|
||||
|
||||
public CodeCompletionHandlerBase(CompletionType completionType, boolean invokedExplicitly, boolean autopopup, boolean synchronous) {
|
||||
myCompletionType = completionType;
|
||||
LOG.assertTrue(myCompletionType != CompletionType.CLASS_NAME, "Class name completion shouldn't be invoked directly");
|
||||
this.invokedExplicitly = invokedExplicitly;
|
||||
this.autopopup = autopopup;
|
||||
this.synchronous = synchronous;
|
||||
|
||||
-1
@@ -176,7 +176,6 @@ public class FilePathCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
};
|
||||
extend(CompletionType.CLASS_NAME, psiElement(), provider);
|
||||
extend(CompletionType.BASIC, psiElement(), provider);
|
||||
}
|
||||
|
||||
|
||||
@@ -150,8 +150,10 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
getMemValueContainer(key).removeAssociatedValue(inputId);
|
||||
return;
|
||||
}
|
||||
|
||||
myMap.remove(key); //
|
||||
final ChangeTrackingValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
valueContainer.dropMergedData();
|
||||
}
|
||||
|
||||
myBackendStorage.removeAllValues(key, inputId);
|
||||
}
|
||||
|
||||
@@ -119,30 +119,33 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
isCompletelyBroken = true;
|
||||
}
|
||||
|
||||
notifyUser("Local History storage file has become corrupted and was rebuilt.");
|
||||
notifyUser("Local History storage file has become corrupted and will be rebuilt.");
|
||||
}
|
||||
|
||||
|
||||
public static void notifyUser(String message) {
|
||||
final String logFile = PathManager.getLogPath();
|
||||
String createIssuePart = "<br>" +
|
||||
"<br>" +
|
||||
"Please attach log files from <a href=\"file\">" + logFile + "</a><br>" +
|
||||
"to the <a href=\"url\">YouTrack issue</a>";
|
||||
|
||||
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID,
|
||||
"Local History is broken",
|
||||
message + "<br>" +
|
||||
"<br>" +
|
||||
"Please attach log files from <a href=\"file\">" + logFile + "</a><br>" +
|
||||
"to the <a href=\"url\">YouTrack issue</a>",
|
||||
message /*+ createIssuePart*/,
|
||||
NotificationType.ERROR,
|
||||
new NotificationListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification notification,
|
||||
@NotNull HyperlinkEvent event) {
|
||||
if ("url".equals(event.getDescription())) {
|
||||
BrowserUtil.launchBrowser("http://youtrack.jetbrains.net/issue/IDEA-71270");
|
||||
}
|
||||
else {
|
||||
File file = new File(logFile);
|
||||
ShowFilePathAction.openFile(file);
|
||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
if ("url".equals(event.getDescription())) {
|
||||
BrowserUtil.launchBrowser("http://youtrack.jetbrains.net/issue/IDEA-71270");
|
||||
}
|
||||
else {
|
||||
File file = new File(logFile);
|
||||
ShowFilePathAction.openFile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}), null);
|
||||
|
||||
@@ -255,4 +255,6 @@ public interface IdeActions {
|
||||
String ACTION_REDO = "$Redo";
|
||||
String GROUP_REFACTOR = "RefactoringMenu";
|
||||
String CHANGES_VIEW_ROLLBACK = "ChangesView.Rollback";
|
||||
|
||||
String CONSOLE_CLEAR_ALL = "ConsoleView.ClearAll";
|
||||
}
|
||||
|
||||
@@ -88,10 +88,13 @@ class EventLogConsole {
|
||||
|
||||
((EditorMarkupModel)editor.getMarkupModel()).setErrorStripeVisible(true);
|
||||
|
||||
final ClearLog clearLog = new ClearLog();
|
||||
clearLog.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.CONSOLE_CLEAR_ALL).getShortcutSet(), editor.getContentComponent());
|
||||
|
||||
editor.addEditorMouseListener(new EditorPopupHandler() {
|
||||
public void invokePopup(final EditorMouseEvent event) {
|
||||
final ActionManager actionManager = ActionManager.getInstance();
|
||||
final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, createPopupActions(actionManager));
|
||||
final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, createPopupActions(actionManager, clearLog));
|
||||
final MouseEvent mouseEvent = event.getMouseEvent();
|
||||
menu.getComponent().show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY());
|
||||
}
|
||||
@@ -99,31 +102,12 @@ class EventLogConsole {
|
||||
return editor;
|
||||
}
|
||||
|
||||
private DefaultActionGroup createPopupActions(ActionManager actionManager) {
|
||||
private DefaultActionGroup createPopupActions(ActionManager actionManager, ClearLog action) {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(new EditorCopyAction());
|
||||
group.add(actionManager.getAction(IdeActions.ACTION_COMPARE_CLIPBOARD_WITH_SELECTION));
|
||||
group.addSeparator();
|
||||
group.add(new DumbAwareAction("Clear All") {
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
final boolean enabled = e.getData(PlatformDataKeys.EDITOR) != null;
|
||||
e.getPresentation().setEnabled(enabled);
|
||||
e.getPresentation().setVisible(enabled);
|
||||
}
|
||||
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
for (Notification notification : myProjectModel.getNotifications()) {
|
||||
notification.expire();
|
||||
myProjectModel.removeNotification(notification);
|
||||
}
|
||||
myProjectModel.setStatusMessage(null, 0);
|
||||
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
if (editor != null) {
|
||||
editor.getDocument().deleteString(0, editor.getDocument().getTextLength());
|
||||
}
|
||||
}
|
||||
});
|
||||
group.add(action);
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -240,4 +224,28 @@ class EventLogConsole {
|
||||
document.insertString(document.getTextLength(), s);
|
||||
}
|
||||
|
||||
private class ClearLog extends DumbAwareAction {
|
||||
public ClearLog() {
|
||||
super("Clear All");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
final boolean enabled = e.getData(PlatformDataKeys.EDITOR) != null;
|
||||
e.getPresentation().setEnabled(enabled);
|
||||
e.getPresentation().setVisible(enabled);
|
||||
}
|
||||
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
for (Notification notification : myProjectModel.getNotifications()) {
|
||||
notification.expire();
|
||||
myProjectModel.removeNotification(notification);
|
||||
}
|
||||
myProjectModel.setStatusMessage(null, 0);
|
||||
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
if (editor != null) {
|
||||
editor.getDocument().deleteString(0, editor.getDocument().getTextLength());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,6 +377,7 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
}
|
||||
|
||||
public void testMatchingDegree() {
|
||||
assertPreference("jscote", "JsfCompletionTest", "JSCompletionTest", NameUtil.MatchingCaseSensitivity.NONE);
|
||||
assertPreference("OCO", "OneCoolObject", "OCObject");
|
||||
assertPreference("MUp", "MavenUmlProvider", "MarkUp");
|
||||
assertPreference("MUP", "MarkUp", "MavenUmlProvider");
|
||||
@@ -400,6 +401,11 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
assertPreference(" Boo", "boolean", "Boolean", NameUtil.MatchingCaseSensitivity.NONE);
|
||||
}
|
||||
|
||||
public void testPreferWordBoundaryMatch() {
|
||||
assertPreference("*les", "configureByFiles", "getLookupElementStrings", NameUtil.MatchingCaseSensitivity.FIRST_LETTER);
|
||||
assertPreference("*les", "configureByFiles", "getLookupElementStrings", NameUtil.MatchingCaseSensitivity.NONE);
|
||||
}
|
||||
|
||||
public void testPreferEarlyMatching() {
|
||||
assertPreference(" path", "getAbsolutePath", "findPath");
|
||||
}
|
||||
|
||||
@@ -264,7 +264,9 @@ public class MinusculeMatcher implements Matcher {
|
||||
if (p < 0) {
|
||||
break;
|
||||
}
|
||||
matchingCase += c == myPattern[p] ? 1 : 0;
|
||||
if (Character.isUpperCase(myPattern[p]) || i == range.getStartOffset()) {
|
||||
matchingCase += c == myPattern[p] ? 1 : 0;
|
||||
}
|
||||
}
|
||||
fragmentCount++;
|
||||
}
|
||||
|
||||
@@ -30,11 +30,9 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -441,13 +439,17 @@ public class PagedFileStorage implements Forceable {
|
||||
private static final int FILE_INDEX_SHIFT = 16;
|
||||
private final boolean checkThreadAccess;
|
||||
public final StorageLockContext myDefaultStorageLockContext;
|
||||
|
||||
private int myMappingChangeCount;
|
||||
private final LinkedHashMap<Integer, ByteBufferWrapper> myMap;
|
||||
private long mySizeLimit;
|
||||
private long mySize;
|
||||
private final ConcurrentHashMap<Integer, PagedFileStorage> myIndex2Storage = new ConcurrentHashMap<Integer, PagedFileStorage>();
|
||||
|
||||
private final LinkedHashMap<Integer, ByteBufferWrapper> mySegments;
|
||||
private final SequenceLock mySegmentsAccessLock = new SequenceLock(); // protects map operations of mySegments, needed for LRU order, mySize and myMappingChangeCount
|
||||
|
||||
private final SequenceLock mySegmentsAllocationLock = new SequenceLock();
|
||||
private final ConcurrentLinkedQueue<ByteBufferWrapper> mySegmentsToRemove = new ConcurrentLinkedQueue<ByteBufferWrapper>();
|
||||
private volatile long mySize;
|
||||
private volatile long mySizeLimit;
|
||||
private volatile int myMappingChangeCount;
|
||||
|
||||
public StorageLock() {
|
||||
this(true);
|
||||
}
|
||||
@@ -457,7 +459,7 @@ public class PagedFileStorage implements Forceable {
|
||||
myDefaultStorageLockContext = new StorageLockContext(this);
|
||||
|
||||
mySizeLimit = UPPER_LIMIT;
|
||||
myMap = new LinkedHashMap<Integer, ByteBufferWrapper>(10, 0.75f) {
|
||||
mySegments = new LinkedHashMap<Integer, ByteBufferWrapper>(10, 0.75f) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Integer, ByteBufferWrapper> eldest) {
|
||||
return mySize > mySizeLimit;
|
||||
@@ -469,8 +471,9 @@ public class PagedFileStorage implements Forceable {
|
||||
// this method can be called after removeEldestEntry
|
||||
ByteBufferWrapper wrapper = super.remove(key);
|
||||
if (wrapper != null) {
|
||||
++myMappingChangeCount;
|
||||
mySegmentsToRemove.offer(wrapper);
|
||||
mySize -= wrapper.myLength;
|
||||
wrapper.dispose();
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
@@ -502,33 +505,79 @@ public class PagedFileStorage implements Forceable {
|
||||
}
|
||||
|
||||
private ByteBufferWrapper get(Integer key) {
|
||||
ByteBufferWrapper wrapper = myMap.get(key);
|
||||
if (wrapper != null) {
|
||||
ByteBufferWrapper wrapper;
|
||||
try { // fast path
|
||||
mySegmentsAccessLock.lock();
|
||||
wrapper = mySegments.get(key);
|
||||
if (wrapper != null) return wrapper;
|
||||
}
|
||||
finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
mySegmentsAllocationLock.lock();
|
||||
try {
|
||||
// check if anybody cared about our segment
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
wrapper = mySegments.get(key);
|
||||
if (wrapper != null) return wrapper;
|
||||
} finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
long started = IOStatistics.DEBUG ? System.currentTimeMillis() : 0;
|
||||
wrapper = createValue(key);
|
||||
|
||||
if (IOStatistics.DEBUG) {
|
||||
long finished = System.currentTimeMillis();
|
||||
if (finished - started > IOStatistics.MIN_IO_TIME_TO_REPORT) {
|
||||
IOStatistics.dump(
|
||||
"Mapping " + wrapper.myLength + " from " + wrapper.myPosition + " file:" + wrapper.myFile + " for " + (finished - started));
|
||||
}
|
||||
}
|
||||
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
mySegments.put(key, wrapper);
|
||||
mySize += wrapper.myLength;
|
||||
}
|
||||
finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
ensureSize(mySizeLimit);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
long started = IOStatistics.DEBUG ? System.currentTimeMillis() : 0;
|
||||
wrapper = createValue(key);
|
||||
mySize += wrapper.myLength;
|
||||
|
||||
if (IOStatistics.DEBUG) {
|
||||
long finished = System.currentTimeMillis();
|
||||
if (finished - started > IOStatistics.MIN_IO_TIME_TO_REPORT) {
|
||||
IOStatistics.dump(
|
||||
"Mapping " + wrapper.myLength + " from " + wrapper.myPosition + " file:" + wrapper.myFile + " for " + (finished - started));
|
||||
}
|
||||
finally {
|
||||
mySegmentsAllocationLock.unlock();
|
||||
}
|
||||
myMap.put(key, wrapper);
|
||||
}
|
||||
|
||||
ensureSize(mySizeLimit);
|
||||
return wrapper;
|
||||
private void disposeRemovedSegments() {
|
||||
assert mySegmentsAllocationLock.isHeldByCurrentThread();
|
||||
Iterator<ByteBufferWrapper> iterator = mySegmentsToRemove.iterator();
|
||||
while(iterator.hasNext()) {
|
||||
iterator.next().dispose();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureSize(long sizeLimit) {
|
||||
while (mySize > sizeLimit) {
|
||||
// we still have to drop something
|
||||
myMap.doRemoveEldestEntry();
|
||||
assert mySegmentsAllocationLock.isHeldByCurrentThread();
|
||||
|
||||
try {
|
||||
mySegmentsAccessLock.lock();
|
||||
while (mySize > sizeLimit) {
|
||||
// we still have to drop something
|
||||
mySegments.doRemoveEldestEntry();
|
||||
}
|
||||
} finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
disposeRemovedSegments();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -541,7 +590,7 @@ public class PagedFileStorage implements Forceable {
|
||||
if (off > owner.length()) {
|
||||
throw new IndexOutOfBoundsException("off=" + off + " key.owner.length()=" + owner.length());
|
||||
}
|
||||
++myMappingChangeCount;
|
||||
|
||||
int min = Math.min((int)(owner.length() - off), owner.myPageSize);
|
||||
ByteBufferWrapper wrapper = ByteBufferWrapper.readWriteDirect(owner.myFile, off, min);
|
||||
IOException oome = null;
|
||||
@@ -586,30 +635,49 @@ public class PagedFileStorage implements Forceable {
|
||||
}
|
||||
|
||||
private @Nullable Map<Integer, ByteBufferWrapper> getBuffersOrderedForOwner(int index, StorageLockContext storageLockContext) {
|
||||
checkThreadAccess(storageLockContext);
|
||||
Map<Integer, ByteBufferWrapper> mineBuffers = null;
|
||||
for (Map.Entry<Integer, ByteBufferWrapper> entry : myMap.entrySet()) {
|
||||
if ((entry.getKey() & FILE_INDEX_MASK) == index) {
|
||||
if (mineBuffers == null) {
|
||||
mineBuffers = new TreeMap<Integer, ByteBufferWrapper>(new Comparator<Integer>() {
|
||||
@Override
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return o1 - o2;
|
||||
}
|
||||
});
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
checkThreadAccess(storageLockContext);
|
||||
Map<Integer, ByteBufferWrapper> mineBuffers = null;
|
||||
for (Map.Entry<Integer, ByteBufferWrapper> entry : mySegments.entrySet()) {
|
||||
if ((entry.getKey() & FILE_INDEX_MASK) == index) {
|
||||
if (mineBuffers == null) {
|
||||
mineBuffers = new TreeMap<Integer, ByteBufferWrapper>(new Comparator<Integer>() {
|
||||
@Override
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return o1 - o2;
|
||||
}
|
||||
});
|
||||
}
|
||||
mineBuffers.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
mineBuffers.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return mineBuffers;
|
||||
}
|
||||
finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
return mineBuffers;
|
||||
}
|
||||
|
||||
private void unmapBuffersForOwner(int index, StorageLockContext storageLockContext) {
|
||||
final Map<Integer, ByteBufferWrapper> buffers = getBuffersOrderedForOwner(index, storageLockContext);
|
||||
|
||||
if (buffers != null) {
|
||||
for (Integer key : buffers.keySet()) {
|
||||
myMap.remove(key);
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
for (Integer key : buffers.keySet()) {
|
||||
mySegments.remove(key);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
mySegmentsAllocationLock.lock();
|
||||
try {
|
||||
disposeRemovedSegments();
|
||||
} finally {
|
||||
mySegmentsAllocationLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -618,14 +686,32 @@ public class PagedFileStorage implements Forceable {
|
||||
Map<Integer, ByteBufferWrapper> buffers = getBuffersOrderedForOwner(index, storageLockContext);
|
||||
|
||||
if (buffers != null) {
|
||||
for(ByteBufferWrapper buffer:buffers.values()) {
|
||||
buffer.flush();
|
||||
mySegmentsAllocationLock.lock();
|
||||
try {
|
||||
for(ByteBufferWrapper buffer:buffers.values()) {
|
||||
buffer.flush();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
mySegmentsAllocationLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidateBuffer(int page) {
|
||||
myMap.remove(page);
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
mySegments.remove(page);
|
||||
} finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
mySegmentsAllocationLock.lock();
|
||||
try {
|
||||
disposeRemovedSegments();
|
||||
}
|
||||
finally {
|
||||
mySegmentsAllocationLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,10 @@ import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.github.ui.GithubLoginDialog;
|
||||
|
||||
import static org.jetbrains.plugins.github.GithubUtil.*;
|
||||
@@ -106,8 +107,7 @@ public class GithubOpenInBrowserAction extends DumbAwareAction {
|
||||
}
|
||||
final GitRepository gitRepository = manager.getRepositoryForFile(root);
|
||||
// Check that given repository is properly configured git repository
|
||||
final GitRemote gitRemote = findGitHubRemoteBranch(gitRepository);
|
||||
final String pushUrl = getGithubUrl(gitRemote);
|
||||
final String githubRemoteUrl = findGithubRemoteUrl(gitRepository);
|
||||
|
||||
final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE);
|
||||
final String rootPath = root.getPath();
|
||||
@@ -117,38 +117,84 @@ public class GithubOpenInBrowserAction extends DumbAwareAction {
|
||||
return;
|
||||
}
|
||||
|
||||
String userAndRepository = getUserAndRepositoryOrShowError(project, pushUrl);
|
||||
String branch = getBranchNameOnRemote(project, root);
|
||||
if (branch == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current tracked branch
|
||||
String relativePath = path.substring(rootPath.length());
|
||||
String urlToOpen = makeUrlToOpen(e, relativePath, branch, githubRemoteUrl);
|
||||
BrowserUtil.launchBrowser(urlToOpen);
|
||||
}
|
||||
|
||||
private static String makeUrlToOpen(@NotNull AnActionEvent e, @NotNull String relativePath, @NotNull String branch,
|
||||
@NotNull String githubRemoteUrl) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append(makeGithubRepoUrlFromRemoteUrl(githubRemoteUrl)).append("/blob/").append(branch).append(relativePath);
|
||||
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
if (editor != null) {
|
||||
final int line = editor.getCaretModel().getLogicalPosition().line + 1; // lines are counted internally from 0, but from 1 on github
|
||||
builder.append("#L").append(line);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String makeGithubRepoUrlFromRemoteUrl(@NotNull String remoteUrl) {
|
||||
remoteUrl = removeEndingDotGit(remoteUrl);
|
||||
if (remoteUrl.startsWith("http")) {
|
||||
return remoteUrl;
|
||||
}
|
||||
if (remoteUrl.startsWith("git://")) {
|
||||
return "https" + remoteUrl.substring(3);
|
||||
}
|
||||
return convertFromSshToHttp(remoteUrl);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String convertFromSshToHttp(@NotNull String remoteUrl) {
|
||||
// Format: git@github.com:account/repository
|
||||
int indexOfAt = remoteUrl.indexOf("@");
|
||||
if (indexOfAt < 0) {
|
||||
throw new IllegalStateException("Invalid remote Github SSH url: " + remoteUrl);
|
||||
}
|
||||
String withoutPrefix = remoteUrl.substring(indexOfAt + 1, remoteUrl.length());
|
||||
return "https://" + withoutPrefix.replace(':', '/');
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String removeEndingDotGit(@NotNull String url) {
|
||||
final String DOT_GIT = ".git";
|
||||
if (url.endsWith(DOT_GIT)) {
|
||||
return url.substring(0, url.length() - DOT_GIT.length());
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getBranchNameOnRemote(@NotNull Project project, @NotNull VirtualFile root) {
|
||||
final GitBranch tracked;
|
||||
try {
|
||||
final GitBranch current = GitBranch.current(project, root);
|
||||
if (current == null) {
|
||||
Messages.showErrorDialog(project, "Cannot find local branch", CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
tracked = current.tracked(project, root);
|
||||
if (tracked == null || !tracked.isRemote()) {
|
||||
Messages.showErrorDialog(project, "Cannot find tracked branch for branch: " + current.getFullName(), CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
Messages.showErrorDialog(project, "Error occurred while inspecting branches: " + e1, CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
String branch = tracked.getName();
|
||||
if (branch.startsWith("origin/")) {
|
||||
branch = branch.substring(7);
|
||||
}
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("https://github.com/").append(userAndRepository).append("/blob/").append(branch).append(path.substring(rootPath.length()));
|
||||
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
if (editor != null) {
|
||||
final int line = editor.getCaretModel().getLogicalPosition().line;
|
||||
builder.append("#L").append(line);
|
||||
}
|
||||
BrowserUtil.launchBrowser(builder.toString());
|
||||
return branch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -450,6 +450,7 @@ public class GithubUtil {
|
||||
final String host = githubSettings.getHost();
|
||||
final String username = githubSettings.getLogin();
|
||||
|
||||
// TODO this doesn't work with organizational accounts
|
||||
final String userRepoMarkerSSHProtocol = host + ":" + username + "/";
|
||||
final String userRepoMarkerOtherProtocols = host + "/" + username + "/";
|
||||
for (String pushUrl : gitRemote.getUrls()) {
|
||||
|
||||
+3
-63
@@ -34,10 +34,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.FilterPositionUtil;
|
||||
import com.intellij.psi.filters.TrueFilter;
|
||||
import com.intellij.psi.filters.types.AssignableFromFilter;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
@@ -177,8 +174,8 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
|
||||
private static final ElementPattern<PsiElement> AFTER_NUMBER_LITERAL = psiElement().afterLeaf(
|
||||
psiElement().withElementType(elementType().oneOf(mNUM_DOUBLE, mNUM_INT, mNUM_LONG, mNUM_FLOAT, mNUM_BIG_INT, mNUM_BIG_DECIMAL)));
|
||||
private static final ElementPattern<PsiElement> AFTER_AT = psiElement().afterLeaf("@");
|
||||
private static final ElementPattern<PsiElement> IN_CATCH_TYPE = psiElement().afterLeaf(psiElement().withText("(").withParent(GrCatchClause.class));
|
||||
public static final ElementPattern<PsiElement> AFTER_AT = psiElement().afterLeaf("@");
|
||||
public static final ElementPattern<PsiElement> IN_CATCH_TYPE = psiElement().afterLeaf(psiElement().withText("(").withParent(GrCatchClause.class));
|
||||
|
||||
|
||||
private static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) {
|
||||
@@ -194,7 +191,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
final Consumer<LookupElement> consumer,
|
||||
final InheritorsHolder inheritors, final PrefixMatcher matcher) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final ElementFilter filter = getClassFilter(position);
|
||||
final boolean afterNew = JavaClassNameCompletionContributor.AFTER_NEW.accepts(position);
|
||||
AllClassesGetter.processJavaClasses(parameters, matcher, parameters.getInvocationCount() <= 1, new Consumer<PsiClass>() {
|
||||
@Override
|
||||
@@ -203,7 +199,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
.createClassLookupItems(psiClass, afterNew, new GroovyClassNameInsertHandler(), new Condition<PsiClass>() {
|
||||
@Override
|
||||
public boolean value(PsiClass psiClass) {
|
||||
return !inheritors.alreadyProcessed(psiClass) && filter.isAcceptable(psiClass, position);
|
||||
return !inheritors.alreadyProcessed(psiClass);
|
||||
}
|
||||
})) {
|
||||
consumer.consume(element);
|
||||
@@ -212,16 +208,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
});
|
||||
}
|
||||
|
||||
private static ElementFilter getClassFilter(PsiElement position) {
|
||||
if (AFTER_AT.accepts(position)) {
|
||||
return new AssignableFromFilter(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION);
|
||||
}
|
||||
if (IN_CATCH_TYPE.accepts(position)) {
|
||||
return new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE);
|
||||
}
|
||||
return TrueFilter.INSTANCE;
|
||||
}
|
||||
|
||||
public GroovyCompletionContributor() {
|
||||
//provide 'this' and 'super' completions in ClassName.<caret>
|
||||
extend(CompletionType.BASIC, AFTER_DOT, new CompletionProvider<CompletionParameters>() {
|
||||
@@ -261,20 +247,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
MapKeysCompletionProvider.register(this);
|
||||
GroovyDocCompletionProvider.register(this);
|
||||
|
||||
// class name stuff
|
||||
|
||||
extend(CompletionType.CLASS_NAME, psiElement().withParent(GrReferenceElement.class), new GlobalStaticMembersProvider());
|
||||
|
||||
extend(CompletionType.CLASS_NAME, psiElement(), new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
ProcessingContext context,
|
||||
@NotNull CompletionResultSet result) {
|
||||
result.stopHere();
|
||||
addAllClasses(parameters, result.withPrefixMatcher(CompletionUtil.findJavaIdentifierPrefix(parameters)), new InheritorsHolder(parameters.getPosition(), result));
|
||||
}
|
||||
});
|
||||
|
||||
extend(CompletionType.BASIC, STATEMENT_START, new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
@@ -392,10 +364,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
public static boolean isClassNamePossible(PsiElement position) {
|
||||
if (PsiJavaPatterns.psiElement().inside(GrImportStatement.class).accepts(position)) {
|
||||
return false;
|
||||
}
|
||||
if (position instanceof PsiComment) return false;
|
||||
PsiElement parent = position.getParent();
|
||||
if (parent instanceof GrReferenceElement) {
|
||||
return ((GrReferenceElement)parent).getQualifier() == null;
|
||||
@@ -445,8 +413,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
};
|
||||
|
||||
final PsiElement position = parameters.getPosition();
|
||||
|
||||
final Map<PsiModifierListOwner, LookupElement> staticMembers = hashMap();
|
||||
final PsiElement qualifier = reference.getQualifier();
|
||||
final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null;
|
||||
@@ -469,8 +435,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
unresolvedProps = Collections.emptySet();
|
||||
}
|
||||
|
||||
final ElementFilter classFilter = getClassFilter(position);
|
||||
|
||||
final List<LookupElement> zeroPriority = arrayList();
|
||||
reference.processVariants(matcher, parameters, new Consumer<LookupElement>() {
|
||||
public void consume(LookupElement lookupElement) {
|
||||
@@ -503,9 +467,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
staticMembers.put(CompletionUtil.getOriginalOrSelf((PsiModifierListOwner)object), lookupElement);
|
||||
}
|
||||
}
|
||||
if (object instanceof PsiClass && !classFilter.isAcceptable(object, position)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PrioritizedLookupElement prio = lookupElement.as(PrioritizedLookupElement.CLASS_CONDITION_KEY);
|
||||
if (prio == null || prio.getPriority() == 0) {
|
||||
@@ -829,25 +790,4 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class GlobalStaticMembersProvider extends CompletionProvider<CompletionParameters> {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
ProcessingContext context,
|
||||
@NotNull final CompletionResultSet result) {
|
||||
if (!parameters.isExtendedCompletion()) return;
|
||||
|
||||
final PsiElement position = parameters.getPosition();
|
||||
if (((GrReferenceElement)position.getParent()).getQualifier() != null) return;
|
||||
|
||||
if (StringUtil.isEmpty(result.getPrefixMatcher().getPrefix())) return;
|
||||
|
||||
completeStaticMembers(parameters).processStaticMethodsGlobally(result.getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
result.addElement(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-2
@@ -21,11 +21,13 @@ import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionContributor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
@@ -86,6 +88,15 @@ public class GrKindWeigher extends CompletionWeigher {
|
||||
|
||||
if (isPriorityKeyword(o)) return NotQualifiedKind.local;
|
||||
if (isLightElement(o)) return NotQualifiedKind.unknown;
|
||||
if (o instanceof PsiClass) {
|
||||
if (((PsiClass)o).isAnnotationType() && GroovyCompletionContributor.AFTER_AT.accepts(position)) {
|
||||
return NotQualifiedKind.restrictedClass;
|
||||
}
|
||||
if (GroovyCompletionContributor.IN_CATCH_TYPE.accepts(position) &&
|
||||
InheritanceUtil.isInheritor((PsiClass)o, CommonClassNames.JAVA_LANG_THROWABLE)) {
|
||||
return NotQualifiedKind.restrictedClass;
|
||||
}
|
||||
}
|
||||
if (o instanceof PsiMember) {
|
||||
final PsiClass containingClass = ((PsiMember)o).getContainingClass();
|
||||
if (isAccessor((PsiMember)o)) return NotQualifiedKind.accessor;
|
||||
@@ -145,18 +156,19 @@ public class GrKindWeigher extends CompletionWeigher {
|
||||
return qualifier.getManager().areElementsEquivalent(member.getContainingClass(), psiClass);
|
||||
}
|
||||
|
||||
private static enum NotQualifiedKind {
|
||||
private enum NotQualifiedKind {
|
||||
arrayType,
|
||||
innerClass,
|
||||
unknown,
|
||||
accessor,
|
||||
member,
|
||||
currentClassMember,
|
||||
restrictedClass,
|
||||
local,
|
||||
onTop
|
||||
}
|
||||
|
||||
private static enum QualifiedKind {
|
||||
private enum QualifiedKind {
|
||||
innerClass,
|
||||
unknown,
|
||||
accessor,
|
||||
|
||||
+3
-1
@@ -231,7 +231,9 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
VfsUtil.saveText(ObjectUtils.assertNotNull(file.getVirtualFile()), barText);
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
System.out.println("Changing file text: psiFile= " + file + "; vFile= " + virtualFile);
|
||||
VfsUtil.saveText(ObjectUtils.assertNotNull(virtualFile), barText);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
+2
-2
@@ -226,14 +226,14 @@ new Fxoo()<caret>\n"""
|
||||
myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}"
|
||||
myFixture.configureByText "a.groovy", "@Abcd<caret>"
|
||||
complete()
|
||||
myFixture.checkResult "@AbcdAnno<caret>"
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdAnno'
|
||||
}
|
||||
|
||||
public void testOnlyExceptionsInCatch() {
|
||||
myFixture.addClass "class AbcdClass {}; class AbcdException extends Throwable {}"
|
||||
myFixture.configureByText "a.groovy", "try {} catch (Abcd<caret>"
|
||||
complete()
|
||||
myFixture.checkResult "try {} catch (AbcdException<caret>"
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdException'
|
||||
}
|
||||
|
||||
public void testClassNameInMultilineString() {
|
||||
|
||||
+5
-3
@@ -712,17 +712,17 @@ format(<caret>)"""
|
||||
}
|
||||
|
||||
public void testOnlyAnnotationsAfterAt() {
|
||||
myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}"
|
||||
myFixture.addClass "class AbcdClass {}; @interface AbcdXAnno {}"
|
||||
myFixture.configureByText "a.groovy", "@Abcd<caret> class A {}"
|
||||
myFixture.completeBasic()
|
||||
myFixture.checkResult "@AbcdAnno<caret> class A {}"
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdXAnno'
|
||||
}
|
||||
|
||||
public void testOnlyAnnotationsAfterAtInMethodParameters() {
|
||||
myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}"
|
||||
myFixture.configureByText "a.groovy", "def foo(@Abcd<caret> ) {}"
|
||||
myFixture.completeBasic()
|
||||
myFixture.checkResult "def foo(@AbcdAnno<caret> ) {}"
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdAnno'
|
||||
}
|
||||
|
||||
public void testNoCompletionInClassBodyComments() {
|
||||
@@ -767,6 +767,8 @@ try {} catch (AbcdException"""
|
||||
myFixture.addClass "class AbcdClass {}; class AbcdException extends Throwable {}"
|
||||
myFixture.configureByText "a.groovy", "try {} catch (Abcd<caret> e) {}"
|
||||
myFixture.completeBasic()
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdException'
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResult "try {} catch (AbcdException<caret> e) {}"
|
||||
}
|
||||
|
||||
|
||||
+13
-3
@@ -15,16 +15,26 @@
|
||||
*/
|
||||
package com.intellij.lang.properties;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionInitializationContext;
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.lang.properties.psi.PropertiesFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class PropertiesCompletionContributor extends CompletionContributor {
|
||||
@Override
|
||||
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
if (parameters.isExtendedCompletion()) {
|
||||
CompletionService.getCompletionService().getVariantsFromContributors(parameters.delegateToClassName(), null, new Consumer<CompletionResult>() {
|
||||
public void consume(final CompletionResult completionResult) {
|
||||
result.passResult(completionResult);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeCompletion(@NotNull CompletionInitializationContext context) {
|
||||
if (context.getFile() instanceof PropertiesFile) {
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.tmatesoft.svn.core.SVNException;
|
||||
* Time: 3:45 PM
|
||||
*/
|
||||
public abstract class RepeatSvnActionThroughBusy {
|
||||
public static final int REPEAT = 3;
|
||||
public static final int REPEAT = 10;
|
||||
protected int myCnt = REPEAT;
|
||||
protected long myTimeout = 50;
|
||||
protected abstract void executeImpl() throws SVNException;
|
||||
|
||||
@@ -163,7 +163,10 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
@Override
|
||||
public boolean process(Exception e) {
|
||||
if (e instanceof SVNException) {
|
||||
if (SVNErrorCode.SQLITE_ERROR.equals(((SVNException)e).getErrorMessage().getErrorCode())) {
|
||||
final SVNErrorCode errorCode = ((SVNException)e).getErrorMessage().getErrorCode();
|
||||
if (SVNErrorCode.WC_LOCKED.equals(errorCode)) {
|
||||
return true;
|
||||
} else if (SVNErrorCode.SQLITE_ERROR.equals(errorCode)) {
|
||||
Throwable cause = ((SVNException)e).getErrorMessage().getCause();
|
||||
if (cause instanceof SqlJetException) {
|
||||
return SqlJetErrorCode.BUSY.equals(((SqlJetException)cause).getErrorCode());
|
||||
|
||||
@@ -144,7 +144,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
}
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
//
|
||||
exception[0] = e1;
|
||||
}
|
||||
catch (SVNException e1) {
|
||||
exception[0] = new VcsException(e);
|
||||
@@ -215,7 +215,11 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
if (wcRootInfo == null || wcRootInfo.getURL() == null) {
|
||||
throw new VcsException("Can not find relative path for " + wasFile.getPath() + "@" + revision.getRevisionNumber().asString());
|
||||
}
|
||||
final SVNURL wasUrl = wcRootInfo.getURL().appendPath(relativePath, true);
|
||||
SVNURL wasUrl = wcRootInfo.getURL();
|
||||
final String[] strings = relativePath.replace('\\','/').split("/");
|
||||
for (String string : strings) {
|
||||
wasUrl = wasUrl.appendPath(string, true);
|
||||
}
|
||||
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
final SVNRevision svnRevision = ((SvnRevisionNumber)revision.getRevisionNumber()).getRevision();
|
||||
|
||||
Reference in New Issue
Block a user