From 667a0e06d14f4947a37425d280ac274548e1ef12 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Mon, 2 Jul 2012 14:25:28 +0200 Subject: [PATCH 01/16] groovy tests logging --- .../src/org/jetbrains/jps/cmdline/BuildSession.java | 6 ++++++ .../plugins/groovy/compiler/GroovyCompilerTestCase.java | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index c441d770a610..c33ae9938e73 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -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 { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java index e17b4fc68070..b2983364fcb1 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java @@ -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); From fe2dbcc62b2a10090c32627ba160b2b3a870b3ae Mon Sep 17 00:00:00 2001 From: irengrig Date: Mon, 2 Jul 2012 16:52:35 +0400 Subject: [PATCH 02/16] SVN: also repeat svn listener actions if WC LOCKED is thrown (similar as BUSY), repeat more --- .../org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java | 2 +- plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java index 2d2a1b8fd962..91c21d74f9a2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/RepeatSvnActionThroughBusy.java @@ -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; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 2634f757e5d6..b23732e8cb9d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -163,7 +163,10 @@ public class SvnVcs extends AbstractVcs { @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()); From f23caa73db0be073b36940e5d8ff2113ef3de456 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Mon, 2 Jul 2012 15:28:02 +0200 Subject: [PATCH 03/16] Local History: do not offer to create a bug report --- .../history/core/ChangeListStorageImpl.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java index a939c88f6204..1dcca83c303e 100644 --- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java +++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java @@ -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 = "
" + + "
" + + "Please attach log files from " + logFile + "
" + + "to the YouTrack issue"; Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, "Local History is broken", - message + "
" + - "
" + - "Please attach log files from " + logFile + "
" + - "to the YouTrack issue", + 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); From 3e881fda9db3f3166582ab244442152613b1c9a6 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 2 Jul 2012 17:36:55 +0400 Subject: [PATCH 04/16] reverted previous change ( abd1fcf - drop in memory cache for key upon removeAllValues value, fileId request) as in memory representation reflects unsaved document data --- .../src/com/intellij/util/indexing/MemoryIndexStorage.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java b/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java index 5f00aa52c9d1..e52744970aa4 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java @@ -150,8 +150,10 @@ public class MemoryIndexStorage implements IndexStorage getMemValueContainer(key).removeAssociatedValue(inputId); return; } - - myMap.remove(key); // + final ChangeTrackingValueContainer valueContainer = myMap.get(key); + if (valueContainer != null) { + valueContainer.dropMergedData(); + } myBackendStorage.removeAllValues(key, inputId); } From 809878d30268617650c2791c3f3f00519fc93233 Mon Sep 17 00:00:00 2001 From: irengrig Date: Mon, 2 Jul 2012 17:51:41 +0400 Subject: [PATCH 05/16] SVN: additional for: "SVN: make annotate revision action work for before-renames" --- .../org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java index c5fdc50b315b..6e0cd264f475 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java @@ -144,7 +144,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn } } catch (VcsException e1) { - // + exception[0] = e1; } catch (SVNException e1) { exception[0] = new VcsException(e); From 5b8b1e4a9aa4d1cbdfcefe72aaa22fac1885a105 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 2 Jul 2012 17:52:39 +0400 Subject: [PATCH 06/16] fix test by ensuring no unsaved documents exist --- .../codeInsight/completion/ClassNameCompletionTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java index c9b621160790..86e736bdc587 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java @@ -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; @@ -198,6 +199,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); From d0e003113d1a1b6a5e908b6573ca17c947176e14 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 2 Jul 2012 13:38:05 +0200 Subject: [PATCH 07/16] IDEA-87135 Mutual hotkey to clear log in tool-window logs --- .../openapi/actionSystem/IdeActions.java | 2 + .../notification/EventLogConsole.java | 52 +++++++++++-------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java index b6fa20a49a20..6d29fa5b3f2b 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java @@ -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"; } diff --git a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java index 25dbb98ea411..d1902e784f05 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java @@ -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()); + } + } + } } From f1a73a6760069f0a36a75d90449d3450bf5d5e74 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 2 Jul 2012 14:27:21 +0200 Subject: [PATCH 08/16] less CLASS_NAME mentions --- .../AbstractBasicToClassNameDelegator.java | 62 ------------------- .../JavaClassNameCompletionContributor.java | 4 +- .../XmlBasicToClassNameDelegator.java | 49 +++++++++++---- .../completion/CompletionType.java | 9 ++- .../completion/CodeCompletionHandlerBase.java | 1 + .../GroovyCompletionContributor.java | 14 ----- 6 files changed, 48 insertions(+), 91 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/completion/AbstractBasicToClassNameDelegator.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AbstractBasicToClassNameDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/AbstractBasicToClassNameDelegator.java deleted file mode 100644 index ca918ed8109f..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/completion/AbstractBasicToClassNameDelegator.java +++ /dev/null @@ -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() { - public void consume(final CompletionResult lookupElement) { - updateProperties(lookupElement.getLookupElement()); - result.passResult(lookupElement); - } - }); - } -} diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index 8585eabb9c91..bce477cb79ed 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -179,8 +179,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); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java index 96e174e1eb04..515a4e101b97 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java @@ -19,27 +19,52 @@ 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()) { + final int invocationCount = parameters.getInvocationCount(); + CompletionParameters classParams; + 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() { + 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 } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionType.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionType.java index 7e71d7326c94..23818c37f580 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionType.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionType.java @@ -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 } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 913a89aa2bd3..8271124deabe 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -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; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index cf15f678bd2f..4bfe01cfe0e8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -261,20 +261,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() { - @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() { @Override protected void addCompletions(@NotNull CompletionParameters parameters, From 89f6e3153bbd7c265567735deb11e379e84f0aad Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 2 Jul 2012 15:19:23 +0200 Subject: [PATCH 09/16] don't show java class names in js on second completion --- .../JavaClassNameCompletionContributor.java | 19 ++++++++++++++--- .../XmlBasicToClassNameDelegator.java | 16 ++------------ .../completion/ClassNameCompletionTest.java | 6 ++++++ .../completion/CompletionParameters.java | 6 +++++- .../completion/SkipAutopopupInStrings.java | 18 ++++++++++------ .../FilePathCompletionContributor.java | 1 - .../GroovyCompletionContributor.java | 21 ------------------- .../PropertiesCompletionContributor.java | 16 +++++++++++--- 8 files changed, 54 insertions(+), 49 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index bce477cb79ed..62999d5f611d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -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; @@ -52,10 +53,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() { + addAllClasses(parameters, parameters.getInvocationCount() <= 1, result.getPrefixMatcher(), new Consumer() { @Override public void consume(LookupElement element) { _result.addElement(element); @@ -64,6 +65,18 @@ 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; + } + return false; + } + public static void addAllClasses(CompletionParameters parameters, final boolean filterByScope, @NotNull final PrefixMatcher matcher, diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java index 515a4e101b97..cd6882ea27fd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java @@ -29,8 +29,7 @@ public class XmlBasicToClassNameDelegator extends CompletionContributor { @Override public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) { PsiElement position = parameters.getPosition(); - if (parameters.getCompletionType() != CompletionType.BASIC || - !JavaCompletionContributor.mayStartClassName(result) || + if (!JavaCompletionContributor.mayStartClassName(result) || !position.getContainingFile().getLanguage().isKindOf(StdLanguages.XML)) { return; } @@ -42,18 +41,7 @@ public class XmlBasicToClassNameDelegator extends CompletionContributor { } if (empty || parameters.isExtendedCompletion()) { - final int invocationCount = parameters.getInvocationCount(); - CompletionParameters classParams; - 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() { + CompletionService.getCompletionService().getVariantsFromContributors(parameters.delegateToClassName(), null, new Consumer() { public void consume(final CompletionResult completionResult) { LookupElement lookupElement = completionResult.getLookupElement(); JavaPsiClassReferenceElement classElement = lookupElement.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java index 86e736bdc587..6c5768c0e9f1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java @@ -95,6 +95,12 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase { checkResultByFile(getTestName(false) + "_after.txt"); } + public void testInPropertiesFile() throws Exception { + myFixture.configureByText("a.properties", "abc = StrinBui"); + complete(); + myFixture.checkResult("abc = java.lang.StringBuilder"); + } + public void testDoubleStringBuffer() throws Exception { createClass("package java.lang; public class StringBuffer {}"); doTest(); diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java index 971c86136a47..1058bdb15efe 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java @@ -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; } } diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/SkipAutopopupInStrings.java b/platform/lang-api/src/com/intellij/codeInsight/completion/SkipAutopopupInStrings.java index 7b50882ea357..8f3714dbda93 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/SkipAutopopupInStrings.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/SkipAutopopupInStrings.java @@ -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); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java index 4c53bbb1e7aa..5dbe6a9c223a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java @@ -176,7 +176,6 @@ public class FilePathCompletionContributor extends CompletionContributor { } } }; - extend(CompletionType.CLASS_NAME, psiElement(), provider); extend(CompletionType.BASIC, psiElement(), provider); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 4bfe01cfe0e8..6d0ad639e0fc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -815,25 +815,4 @@ public class GroovyCompletionContributor extends CompletionContributor { } } } - - private static class GlobalStaticMembersProvider extends CompletionProvider { - @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() { - @Override - public void consume(LookupElement element) { - result.addElement(element); - } - }); - } - } } diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertiesCompletionContributor.java b/plugins/properties/src/com/intellij/lang/properties/PropertiesCompletionContributor.java index a66cd2fd3748..370b6b6856c0 100644 --- a/plugins/properties/src/com/intellij/lang/properties/PropertiesCompletionContributor.java +++ b/plugins/properties/src/com/intellij/lang/properties/PropertiesCompletionContributor.java @@ -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() { + public void consume(final CompletionResult completionResult) { + result.passResult(completionResult); + } + }); + } + } + @Override public void beforeCompletion(@NotNull CompletionInitializationContext context) { if (context.getFile() instanceof PropertiesFile) { From 2895fabd969263b951685883579b8aefddf84863 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 2 Jul 2012 16:18:38 +0200 Subject: [PATCH 10/16] another tweak in matching degree --- .../testSrc/com/intellij/psi/util/NameUtilTest.java | 6 ++++++ .../src/com/intellij/psi/codeStyle/MinusculeMatcher.java | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java index 2f5f17c32b8c..74d23da62ebd 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilTest.java @@ -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"); } diff --git a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java index 59919fd3e0d0..91181db42432 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java +++ b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java @@ -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++; } From 376bfbf056a458a869042195afeeaa548390a187 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 2 Jul 2012 16:28:00 +0200 Subject: [PATCH 11/16] don't SOE --- .../codeInsight/completion/XmlBasicToClassNameDelegator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java index cd6882ea27fd..cbfa168512f5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/XmlBasicToClassNameDelegator.java @@ -29,7 +29,8 @@ public class XmlBasicToClassNameDelegator extends CompletionContributor { @Override public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) { PsiElement position = parameters.getPosition(); - if (!JavaCompletionContributor.mayStartClassName(result) || + if (parameters.getCompletionType() != CompletionType.BASIC || + !JavaCompletionContributor.mayStartClassName(result) || !position.getContainingFile().getLanguage().isKindOf(StdLanguages.XML)) { return; } From 6864c83b2746facc4a377ce7bddfadbd25863d60 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Mon, 2 Jul 2012 19:10:35 +0400 Subject: [PATCH 12/16] Symfony2/PSR-1/2 keep ')' and '{' on one line option --- .../src/com/intellij/formatting/DependentSpacingRule.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-api/src/com/intellij/formatting/DependentSpacingRule.java b/platform/lang-api/src/com/intellij/formatting/DependentSpacingRule.java index 643e08ed1049..a6fe9a2ddb8e 100644 --- a/platform/lang-api/src/com/intellij/formatting/DependentSpacingRule.java +++ b/platform/lang-api/src/com/intellij/formatting/DependentSpacingRule.java @@ -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 } From 22c2def2cf94e69bdd51f86b1a01d310903588ec Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 2 Jul 2012 19:28:10 +0400 Subject: [PATCH 13/16] IDEA-88053 VFS Indexing failure --- .../intellij/util/io/PagedFileStorage.java | 184 +++++++++++++----- 1 file changed, 135 insertions(+), 49 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index 0539b85804ca..eaf2bbd87802 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -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 myMap; - private long mySizeLimit; - private long mySize; private final ConcurrentHashMap myIndex2Storage = new ConcurrentHashMap(); + private final LinkedHashMap 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 mySegmentsToRemove = new ConcurrentLinkedQueue(); + 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(10, 0.75f) { + mySegments = new LinkedHashMap(10, 0.75f) { @Override protected boolean removeEldestEntry(Map.Entry 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 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 getBuffersOrderedForOwner(int index, StorageLockContext storageLockContext) { - checkThreadAccess(storageLockContext); - Map mineBuffers = null; - for (Map.Entry entry : myMap.entrySet()) { - if ((entry.getKey() & FILE_INDEX_MASK) == index) { - if (mineBuffers == null) { - mineBuffers = new TreeMap(new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return o1 - o2; - } - }); + mySegmentsAccessLock.lock(); + try { + checkThreadAccess(storageLockContext); + Map mineBuffers = null; + for (Map.Entry entry : mySegments.entrySet()) { + if ((entry.getKey() & FILE_INDEX_MASK) == index) { + if (mineBuffers == null) { + mineBuffers = new TreeMap(new Comparator() { + @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 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 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(); + } } } From 0d3bf08a852eefc4ba9a02d23b34624cb90a85dd Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 2 Jul 2012 19:46:32 +0400 Subject: [PATCH 14/16] [github] Fix GithubOpenInBrowserAction for organizational accounts * Don't use GithubUtil.getGithubUrl, since it assumes that repository should contain user name (which is not true for organizational accounts). * Get the url from config, don't form an url from username and repository name. * Form a valid HTTPS url from all three possible formats: https, git and ssh. * Refactor: extract a couple of methods. * Add +1 to the line retrieved from the LogicalPosition of the editor (since it counts from 0). --- .../github/GithubOpenInBrowserAction.java | 80 +++++++++++++++---- .../jetbrains/plugins/github/GithubUtil.java | 1 + 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java index eb12b099aa42..fd5bcc184dd7 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java @@ -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; } + } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java index 649e5482ae8e..52e9e6fcb215 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java @@ -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()) { From 2611f42ce4fd9269bdee6adbd545b46247771e64 Mon Sep 17 00:00:00 2001 From: irengrig Date: Mon, 2 Jul 2012 20:14:09 +0400 Subject: [PATCH 15/16] SVN: correctly append relative url part when calculating annotation for revision by URL --- .../jetbrains/idea/svn/annotate/SvnAnnotationProvider.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java index 6e0cd264f475..0e46f2f37849 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java @@ -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(); From d75075c0c2e57f73dd275eee027b1ec9fd37d1fe Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 2 Jul 2012 18:25:09 +0200 Subject: [PATCH 16/16] suggest all visible classes everywhere (IDEA-87958) --- .../JavaClassNameCompletionContributor.java | 25 +++------------ .../completion/ClassNameCompletionTest.java | 2 ++ .../GroovyCompletionContributor.java | 31 ++----------------- .../completion/weighers/GrKindWeigher.java | 16 ++++++++-- .../GroovyClassNameCompletionTest.groovy | 4 +-- .../completion/GroovyCompletionTest.groovy | 8 +++-- 6 files changed, 31 insertions(+), 55 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java index 62999d5f611d..1c1cefe8ce8e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaClassNameCompletionContributor.java @@ -31,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; @@ -74,6 +73,9 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { if (SkipAutopopupInStrings.isInStringLiteral(position)) { return true; } + if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) { + return true; + } return false; } @@ -83,22 +85,8 @@ public class JavaClassNameCompletionContributor extends CompletionContributor { @NotNull final Consumer 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); @@ -120,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() { @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)); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java index 6c5768c0e9f1..ce660ae3cddb 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java @@ -65,6 +65,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase { String path = "/afterNewThrowable"; configureByFile(path + "/before1.java"); + myFixture.type('\n'); checkResultByFile(path + "/after1.java"); } @@ -81,6 +82,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase { String path = "/afterNewThrowable"; configureByFile(path + "/before2.java"); + myFixture.type('\n'); checkResultByFile(path + "/after2.java"); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index 6d0ad639e0fc..f433e8c8897f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -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 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 AFTER_AT = psiElement().afterLeaf("@"); - private static final ElementPattern IN_CATCH_TYPE = psiElement().afterLeaf(psiElement().withText("(").withParent(GrCatchClause.class)); + public static final ElementPattern AFTER_AT = psiElement().afterLeaf("@"); + public static final ElementPattern 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 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() { @Override @@ -203,7 +199,7 @@ public class GroovyCompletionContributor extends CompletionContributor { .createClassLookupItems(psiClass, afterNew, new GroovyClassNameInsertHandler(), new Condition() { @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. extend(CompletionType.BASIC, AFTER_DOT, new CompletionProvider() { @@ -378,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; @@ -431,8 +413,6 @@ public class GroovyCompletionContributor extends CompletionContributor { } }; - final PsiElement position = parameters.getPosition(); - final Map staticMembers = hashMap(); final PsiElement qualifier = reference.getQualifier(); final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null; @@ -455,8 +435,6 @@ public class GroovyCompletionContributor extends CompletionContributor { unresolvedProps = Collections.emptySet(); } - final ElementFilter classFilter = getClassFilter(position); - final List zeroPriority = arrayList(); reference.processVariants(matcher, parameters, new Consumer() { public void consume(LookupElement lookupElement) { @@ -489,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) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java index dd469ca38610..f29092426b24 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/weighers/GrKindWeigher.java @@ -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, diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy index 87023a3ac2d8..cbab89c619f8 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy @@ -226,14 +226,14 @@ new Fxoo()\n""" myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}" myFixture.configureByText "a.groovy", "@Abcd" complete() - myFixture.checkResult "@AbcdAnno" + assert myFixture.lookupElementStrings[0] == 'AbcdAnno' } public void testOnlyExceptionsInCatch() { myFixture.addClass "class AbcdClass {}; class AbcdException extends Throwable {}" myFixture.configureByText "a.groovy", "try {} catch (Abcd" complete() - myFixture.checkResult "try {} catch (AbcdException" + assert myFixture.lookupElementStrings[0] == 'AbcdException' } public void testClassNameInMultilineString() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index d84a161f0306..e480ac9d4cd3 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -712,17 +712,17 @@ format()""" } public void testOnlyAnnotationsAfterAt() { - myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}" + myFixture.addClass "class AbcdClass {}; @interface AbcdXAnno {}" myFixture.configureByText "a.groovy", "@Abcd class A {}" myFixture.completeBasic() - myFixture.checkResult "@AbcdAnno class A {}" + assert myFixture.lookupElementStrings[0] == 'AbcdXAnno' } public void testOnlyAnnotationsAfterAtInMethodParameters() { myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}" myFixture.configureByText "a.groovy", "def foo(@Abcd ) {}" myFixture.completeBasic() - myFixture.checkResult "def foo(@AbcdAnno ) {}" + 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 e) {}" myFixture.completeBasic() + assert myFixture.lookupElementStrings[0] == 'AbcdException' + myFixture.type('\n') myFixture.checkResult "try {} catch (AbcdException e) {}" }