mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -509,6 +509,12 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset(file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false);
|
||||
if (ref != null && !(ref instanceof PsiReferenceExpression)) {
|
||||
context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER.trim() + ";");
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiElement element = file.findElementAt(context.getStartOffset());
|
||||
|
||||
if (psiElement().inside(PsiAnnotation.class).accepts(element)) {
|
||||
|
||||
@@ -680,8 +680,8 @@ public class JavaCompletionUtil {
|
||||
final Document document = context.getEditor().getDocument();
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
final PsiFile file = context.getFile();
|
||||
final PsiReferenceExpression ref =
|
||||
PsiTreeUtil.findElementOfClassAtOffset(file, context.getStartOffset(), PsiReferenceExpression.class, false);
|
||||
final PsiJavaCodeReferenceElement ref =
|
||||
PsiTreeUtil.findElementOfClassAtOffset(file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false);
|
||||
if (ref != null) {
|
||||
final PsiElement qualifier = ref.getQualifier();
|
||||
if (qualifier != null) {
|
||||
@@ -1001,11 +1001,11 @@ public class JavaCompletionUtil {
|
||||
}
|
||||
|
||||
public static boolean hasAccessibleInnerClass(@NotNull PsiClass psiClass, @NotNull PsiElement position) {
|
||||
final PsiClass[] inners = psiClass.getAllInnerClasses();
|
||||
final PsiClass[] inners = psiClass.getInnerClasses();
|
||||
if (inners.length > 0) {
|
||||
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(position.getProject()).getResolveHelper();
|
||||
for (PsiClass inner : inners) {
|
||||
if (resolveHelper.isAccessible(inner, position, null)) {
|
||||
if (inner.hasModifierProperty(PsiModifier.STATIC) && resolveHelper.isAccessible(inner, position, null)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package com.intellij.psi.util.proximity;
|
||||
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.util.ProximityLocation;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -24,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class KnownPackageWeigher extends ProximityWeigher {
|
||||
public class KnownElementWeigher extends ProximityWeigher {
|
||||
|
||||
public Comparable weigh(@NotNull final PsiElement element, @NotNull final ProximityLocation location) {
|
||||
if (element instanceof PsiClass) {
|
||||
@@ -34,6 +36,15 @@ public class KnownPackageWeigher extends ProximityWeigher {
|
||||
if (qname.startsWith("javax.")) return 1;
|
||||
}
|
||||
}
|
||||
if (element instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)element;
|
||||
if ("finalize".equals(method.getName()) || "registerNatives".equals(method.getName())) {
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ class Xxx {
|
||||
private Xxx(String x) {
|
||||
}
|
||||
|
||||
class Yyy {
|
||||
static class Yyy {
|
||||
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@ class Xxx {
|
||||
private Xxx(String x) {
|
||||
}
|
||||
|
||||
class Yyy {
|
||||
static class Yyy {
|
||||
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Foo {
|
||||
{
|
||||
Zzoo l = new Zz<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class Zzoo {
|
||||
void run();
|
||||
|
||||
class Impl implements Zzoo {}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class Foo {
|
||||
{
|
||||
Zzoo l = new Zzoo()<caret>
|
||||
}
|
||||
}
|
||||
|
||||
class Zzoo {
|
||||
void run();
|
||||
|
||||
class Impl implements Zzoo {}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.
|
||||
*/
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class Bar {
|
||||
|
||||
static class CellWrapper {
|
||||
public boolean isSeparator() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class MyRenderer extends DefaultListCellRenderer {
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean s, boolean focus) {
|
||||
assert value instanceof CellWrapper;
|
||||
|
||||
value.is<caret><car>
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.
|
||||
*/
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class Bar {
|
||||
|
||||
static class CellWrapper {
|
||||
public boolean isSeparator() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class MyRenderer extends DefaultListCellRenderer {
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean s, boolean focus) {
|
||||
assert value instanceof CellWrapper;
|
||||
|
||||
((CellWrapper) value).isSeparator()<caret><car>
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class Bar {
|
||||
|
||||
static class CellWrapper {
|
||||
public boolean isSeparator() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class MyRenderer extends DefaultListCellRenderer {
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean s, boolean focus) {
|
||||
assert value instanceof CellWrapper;
|
||||
|
||||
value.is<caret>
|
||||
|
||||
mySelected = isSelected;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
public class Bar {
|
||||
|
||||
static class CellWrapper {
|
||||
public boolean isSeparator() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static class MyRenderer extends DefaultListCellRenderer {
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean s, boolean focus) {
|
||||
assert value instanceof CellWrapper;
|
||||
|
||||
((CellWrapper) value).isSeparator()<caret>
|
||||
|
||||
mySelected = isSelected;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
public class Bar {
|
||||
|
||||
{
|
||||
fina<caret>x
|
||||
}
|
||||
|
||||
}
|
||||
+45
-20
@@ -17,8 +17,6 @@ package com.intellij.codeInsight.completion
|
||||
|
||||
import com.intellij.codeInsight.lookup.Lookup
|
||||
import com.intellij.openapi.actionSystem.IdeActions
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
|
||||
/**
|
||||
@@ -252,13 +250,13 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
}
|
||||
""")
|
||||
type 'ite'
|
||||
ApplicationManager.application.invokeAndWait({
|
||||
myFixture.type 'r'
|
||||
lookup.markReused()
|
||||
lookup.currentItem = lookup.items[0]
|
||||
CommandProcessor.instance.executeCommand project, ({lookup.finishLookup Lookup.NORMAL_SELECT_CHAR} as Runnable), null, null
|
||||
edt {
|
||||
myFixture.type 'r'
|
||||
lookup.markReused()
|
||||
lookup.currentItem = lookup.items[0]
|
||||
CommandProcessor.instance.executeCommand project, ({lookup.finishLookup Lookup.NORMAL_SELECT_CHAR} as Runnable), null, null
|
||||
|
||||
} as Runnable, ModalityState.NON_MODAL)
|
||||
}
|
||||
myFixture.checkResult """
|
||||
class A { Iterable iterable;
|
||||
{ iterable<caret> }
|
||||
@@ -273,14 +271,13 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
}
|
||||
""")
|
||||
type 'ite'
|
||||
ApplicationManager.application.invokeAndWait({
|
||||
myFixture.type 'r'
|
||||
lookup.markReused()
|
||||
myFixture.type '\b\b'
|
||||
lookup.currentItem = lookup.items[0]
|
||||
CommandProcessor.instance.executeCommand project, ({lookup.finishLookup Lookup.NORMAL_SELECT_CHAR} as Runnable), null, null
|
||||
|
||||
} as Runnable, ModalityState.NON_MODAL)
|
||||
edt {
|
||||
myFixture.type 'r'
|
||||
lookup.markReused()
|
||||
myFixture.type '\b\b'
|
||||
lookup.currentItem = lookup.items[0]
|
||||
CommandProcessor.instance.executeCommand project, ({lookup.finishLookup Lookup.NORMAL_SELECT_CHAR} as Runnable), null, null
|
||||
}
|
||||
myFixture.checkResult """
|
||||
class A { Iterable iterable;
|
||||
{ iterable<caret> }
|
||||
@@ -295,10 +292,7 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
}
|
||||
""")
|
||||
type 'th'
|
||||
ApplicationManager.application.invokeAndWait({
|
||||
myFixture.type 'r'
|
||||
myFixture.type '\t'
|
||||
} as Runnable, ModalityState.NON_MODAL)
|
||||
edt { myFixture.type 'r\t'}
|
||||
myFixture.checkResult """
|
||||
class A {
|
||||
{ throw new <caret> }
|
||||
@@ -306,4 +300,35 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
"""
|
||||
}
|
||||
|
||||
public void testTwoQuickRestartsAfterHiding() {
|
||||
myFixture.configureByText("a.java", """
|
||||
class A {
|
||||
{ <caret> }
|
||||
}
|
||||
""")
|
||||
edt { myFixture.type 'A' }
|
||||
joinAlarm() // completion started
|
||||
edt { assert lookup; myFixture.type 'IO' }
|
||||
joinAlarm()
|
||||
joinAlarm()
|
||||
joinCompletion()
|
||||
assert lookup
|
||||
assert 'ArrayIndexOutOfBoundsException' in myFixture.lookupElementStrings
|
||||
}
|
||||
|
||||
public void testTypingDuringExplicitCompletion() {
|
||||
myFixture.configureByText("a.java", """
|
||||
class A {
|
||||
{ Runnable r = new <caret> }
|
||||
}
|
||||
""")
|
||||
myFixture.complete CompletionType.SMART
|
||||
edt { myFixture.type 'Thr' }
|
||||
joinCompletion()
|
||||
assert lookup
|
||||
assert 'Thread' in myFixture.lookupElementStrings
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+4
-1
@@ -138,7 +138,6 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
assertEquals(1, ((PsiMethod)myItems[1].getObject()).getParameterList().getParametersCount());
|
||||
assertEquals(2, ((PsiMethod)myItems[2].getObject()).getParameterList().getParametersCount());
|
||||
}
|
||||
|
||||
public void testStatsForClassNameInExpression() throws Throwable {
|
||||
final VirtualFile foo = getSourceRoot().createChildDirectory(this, "foo");
|
||||
VfsUtil.saveText(foo.createChildData(this, "FooBar.java"), "package foo; public interface FooBar {}");
|
||||
@@ -149,4 +148,8 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
|
||||
assertPreferredItems(0, "FooBee", "FooBar");
|
||||
}
|
||||
|
||||
public void testDispreferFinalize() throws Throwable {
|
||||
checkPreferredItems(0, "final", "finalize");
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -664,6 +664,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
public void testClassNameWithInner() throws Throwable { doTest() }
|
||||
|
||||
public void testClassNameWithInstanceInner() throws Throwable { doTest('\n') }
|
||||
|
||||
public void testDoubleFalse() throws Throwable {
|
||||
configureByFile(getTestName(false) + ".java");
|
||||
assertStringItems("false", "finalize");
|
||||
@@ -785,6 +787,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
public void testCastTooComplexInstanceofedQualifier() throws Throwable { doAntiTest(); }
|
||||
public void testDontCastInstanceofedQualifier() throws Throwable { doTest(); }
|
||||
public void testQualifierCastingWithUnknownAssignments() throws Throwable { doTest(); }
|
||||
public void testQualifierCastingBeforeLt() throws Throwable { doTest(); }
|
||||
|
||||
public void testWildcardsInLookup() throws Exception {
|
||||
configure()
|
||||
|
||||
+29
-20
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.completion
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler
|
||||
import com.intellij.codeInsight.lookup.LookupManager
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
import com.intellij.util.ui.UIUtil
|
||||
|
||||
@@ -28,13 +28,7 @@ import com.intellij.util.ui.UIUtil
|
||||
*/
|
||||
abstract class CompletionAutoPopupTestCase extends LightCodeInsightFixtureTestCase {
|
||||
@Override protected void setUp() {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable(){
|
||||
@Override
|
||||
void run() {
|
||||
superSetUp()
|
||||
}
|
||||
|
||||
})
|
||||
edt { superSetUp() }
|
||||
CompletionAutoPopupHandler.ourTestingAutopopup = true
|
||||
}
|
||||
void superSetUp() {
|
||||
@@ -46,28 +40,43 @@ abstract class CompletionAutoPopupTestCase extends LightCodeInsightFixtureTestCa
|
||||
|
||||
@Override protected void tearDown() {
|
||||
CompletionAutoPopupHandler.ourTestingAutopopup = false
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable(){
|
||||
@Override
|
||||
void run() {
|
||||
superTearDown()
|
||||
}
|
||||
|
||||
})
|
||||
edt { superTearDown() }
|
||||
}
|
||||
|
||||
protected void doHighlighting() {
|
||||
UIUtil.invokeAndWaitIfNeeded({ myFixture.doHighlighting() } as Runnable)
|
||||
edt { myFixture.doHighlighting() }
|
||||
}
|
||||
|
||||
void type(String s) {
|
||||
for (i in 0..<s.size()) {
|
||||
final c = s.charAt(i)
|
||||
myFixture.type(c)
|
||||
ApplicationManager.application.invokeAndWait({ } as Runnable, ModalityState.NON_MODAL) // for the autopopup handler's alarm, or the restartCompletion's invokeLater
|
||||
ApplicationManager.application.invokeAndWait({ } as Runnable, ModalityState.NON_MODAL) // for invokeLater in CompletionProgressIndicator.stop()
|
||||
joinAlarm() // for the autopopup handler's alarm, or the restartCompletion's invokeLater
|
||||
joinCompletion()
|
||||
}
|
||||
}
|
||||
|
||||
protected void joinCompletion() {
|
||||
for (j in 1..1000) {
|
||||
def l = lookup
|
||||
if (!l || !l.calculating) {
|
||||
joinAlarm() // for invokeLater in CompletionProgressIndicator.stop()
|
||||
return
|
||||
}
|
||||
Thread.sleep(10)
|
||||
}
|
||||
fail("Too long completion")
|
||||
}
|
||||
|
||||
protected void joinAlarm() {
|
||||
edt { PlatformTestUtil.waitForAlarm(CodeInsightSettings.instance.AUTO_LOOKUP_DELAY)}
|
||||
}
|
||||
|
||||
protected void edt(Closure c) {
|
||||
UIUtil.invokeAndWaitIfNeeded(c as Runnable)
|
||||
}
|
||||
|
||||
|
||||
@Override protected void runTest() {
|
||||
runTestBare()
|
||||
}
|
||||
@@ -81,7 +90,7 @@ abstract class CompletionAutoPopupTestCase extends LightCodeInsightFixtureTestCa
|
||||
}
|
||||
|
||||
LookupImpl getLookup() {
|
||||
LookupManager.getActiveLookup(myFixture.getEditor())
|
||||
(LookupImpl)LookupManager.getActiveLookup(myFixture.getEditor())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+53
-29
@@ -120,7 +120,18 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
|
||||
psiFile.putUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING, Boolean.TRUE);
|
||||
|
||||
final CompletionProgressIndicator indicator = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
CompletionProgressIndicator indicator = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
if (indicator != null) {
|
||||
indicator.closeAndFinish(false);
|
||||
} else {
|
||||
CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
|
||||
if (phase instanceof CompletionPhase.ZombiePhase) {
|
||||
indicator = ((CompletionPhase.ZombiePhase)phase).indicator;
|
||||
}
|
||||
}
|
||||
|
||||
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
|
||||
|
||||
if (indicator != null) {
|
||||
boolean repeated = indicator.isRepeatedInvocation(myCompletionType, editor);
|
||||
if (repeated && !indicator.isRunning() && (!isAutocompleteCommonPrefixOnInvocation() || indicator.fillInCommonPrefix(true))) {
|
||||
@@ -130,8 +141,6 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
if (repeated) {
|
||||
time = Math.max(indicator.getParameters().getInvocationCount() + 1, 2);
|
||||
indicator.restorePrefix();
|
||||
} else {
|
||||
indicator.closeAndFinish(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,6 +276,8 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
|
||||
final LookupImpl lookup = obtainLookup(editor);
|
||||
|
||||
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.Synchronous());
|
||||
|
||||
final Semaphore freezeSemaphore = new Semaphore();
|
||||
freezeSemaphore.down();
|
||||
final CompletionProgressIndicator indicator = new CompletionProgressIndicator(editor, parameters, this, freezeSemaphore,
|
||||
@@ -274,7 +285,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
|
||||
final AtomicReference<LookupElement[]> data = startCompletionThread(parameters, indicator, initContext);
|
||||
|
||||
if (!invokedExplicitly && (!ApplicationManager.getApplication().isUnitTestMode() || CompletionAutoPopupHandler.ourTestingAutopopup)) {
|
||||
if ((!invokedExplicitly && !ApplicationManager.getApplication().isUnitTestMode()) || CompletionAutoPopupHandler.ourTestingAutopopup) {
|
||||
indicator.notifyBackgrounded();
|
||||
return;
|
||||
}
|
||||
@@ -368,7 +379,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
}
|
||||
};
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode() && !CompletionAutoPopupHandler.ourTestingAutopopup) {
|
||||
computeRunnable.run();
|
||||
} else {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(computeRunnable);
|
||||
@@ -467,12 +478,14 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
final LookupElement[] items) {
|
||||
if (items.length == 0) {
|
||||
LookupManager.getInstance(indicator.getProject()).hideActiveLookup();
|
||||
handleEmptyLookup(indicator.getProject(), indicator.getEditor(), indicator.getParameters(), indicator);
|
||||
CompletionServiceImpl.setCompletionPhase(
|
||||
handleEmptyLookup(indicator.getProject(), indicator.getEditor(), indicator.getParameters(), indicator));
|
||||
return;
|
||||
}
|
||||
|
||||
final AutoCompletionDecision decision = shouldAutoComplete(indicator, items);
|
||||
if (decision == AutoCompletionDecision.SHOW_LOOKUP) {
|
||||
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated());
|
||||
indicator.getLookup().setCalculating(false);
|
||||
indicator.showLookup();
|
||||
if (isAutocompleteCommonPrefixOnInvocation() && items.length > 1) {
|
||||
@@ -488,10 +501,10 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
handleSingleItem(offset2, indicator, items, item.getLookupString(), item);
|
||||
|
||||
// the insert handler may have started a live template with completion
|
||||
if (CompletionService.getCompletionService().getCurrentCompletion() == null) {
|
||||
indicator.liveAfterDeath(null);
|
||||
} else {
|
||||
LOG.assertTrue(!indicator.isZombie(), indicator);
|
||||
if (CompletionService.getCompletionService().getCurrentCompletion() == null &&
|
||||
!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.InsertedSingleItem(indicator));
|
||||
assert indicator.getCompletionState().isWaitingAfterAutoInsertion();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -591,22 +604,29 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
return invokedExplicitly && CodeInsightSettings.getInstance().AUTOCOMPLETE_COMMON_PREFIX;
|
||||
}
|
||||
|
||||
protected void handleEmptyLookup(Project project, Editor editor, final CompletionParameters parameters, final CompletionProgressIndicator indicator) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return;
|
||||
protected CompletionPhase handleEmptyLookup(Project project, Editor editor, final CompletionParameters parameters, final CompletionProgressIndicator indicator) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) return CompletionPhase.NoCompletion;
|
||||
if (!invokedExplicitly) {
|
||||
return;
|
||||
return CompletionPhase.NoCompletion;
|
||||
}
|
||||
indicator.assertDisposed();
|
||||
assert !indicator.isAutopopupCompletion();
|
||||
|
||||
final CompletionPhase[] result = {CompletionPhase.NoCompletion};
|
||||
for (final CompletionContributor contributor : CompletionContributor.forParameters(parameters)) {
|
||||
final String text = contributor.handleEmptyLookup(parameters, editor);
|
||||
if (StringUtil.isNotEmpty(text)) {
|
||||
final EditorHintListener listener = new EditorHintListener() {
|
||||
public void hintShown(final Project project, final LightweightHint hint, final int flags) {
|
||||
indicator.liveAfterDeath(hint);
|
||||
if (!indicator.areModifiersChanged()) {
|
||||
result[0] = new CompletionPhase.NoSuggestionsHint(hint, indicator);
|
||||
CompletionServiceImpl.setCompletionPhase(result[0]);
|
||||
}
|
||||
}
|
||||
};
|
||||
final MessageBusConnection connection = project.getMessageBus().connect();
|
||||
connection.subscribe(EditorHintListener.TOPIC, listener);
|
||||
assert text != null;
|
||||
HintManager.getInstance().showErrorHint(editor, text);
|
||||
connection.disconnect();
|
||||
break;
|
||||
@@ -616,32 +636,36 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
if (codeAnalyzer != null) {
|
||||
codeAnalyzer.updateVisibleHighlighters(editor);
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
|
||||
private static void lookupItemSelected(final CompletionProgressIndicator context, @NotNull final LookupElement item, final char completionChar,
|
||||
private static void lookupItemSelected(final CompletionProgressIndicator indicator, @NotNull final LookupElement item, final char completionChar,
|
||||
final List<LookupElement> items) {
|
||||
if (context.getHandler().autopopup) {
|
||||
if (indicator.getHandler().autopopup) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_BASIC);
|
||||
}
|
||||
|
||||
final Editor editor = context.getEditor();
|
||||
final PsiFile file = context.getParameters().getOriginalFile();
|
||||
final InsertionContext context1 = new InsertionContext(context.getOffsetMap(), completionChar, items.toArray(new LookupElement[items.size()]), file, editor);
|
||||
final Editor editor = indicator.getEditor();
|
||||
final PsiFile file = indicator.getParameters().getOriginalFile();
|
||||
final InsertionContext context = new InsertionContext(indicator.getOffsetMap(), completionChar, items.toArray(new LookupElement[items.size()]), file, editor);
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
final int idEndOffset = context.getIdentifierEndOffset();
|
||||
if (idEndOffset != context.getSelectionEndOffset() && CompletionUtil.isOverwrite(item, completionChar)) {
|
||||
editor.getDocument().deleteString(context.getSelectionEndOffset(), idEndOffset);
|
||||
final int idEndOffset = indicator.getIdentifierEndOffset();
|
||||
if (idEndOffset != indicator.getSelectionEndOffset() && CompletionUtil.isOverwrite(item, completionChar)) {
|
||||
editor.getDocument().deleteString(indicator.getSelectionEndOffset(), idEndOffset);
|
||||
}
|
||||
|
||||
PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments();
|
||||
item.handleInsert(context1);
|
||||
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
|
||||
assert context.getStartOffset() >= 0 : "stale startOffset";
|
||||
assert context.getTailOffset() >= 0 : "stale tailOffset";
|
||||
|
||||
PsiDocumentManager.getInstance(indicator.getProject()).commitAllDocuments();
|
||||
item.handleInsert(context);
|
||||
PostprocessReformattingAspect.getInstance(indicator.getProject()).doPostponedFormatting();
|
||||
|
||||
|
||||
final int tailOffset = context1.getTailOffset();
|
||||
final int tailOffset = context.getTailOffset();
|
||||
if (tailOffset >= 0) {
|
||||
if (context1.shouldAddCompletionChar() &&
|
||||
if (context.shouldAddCompletionChar() &&
|
||||
completionChar != Lookup.AUTO_INSERT_SELECT_CHAR && completionChar != Lookup.REPLACE_SELECT_CHAR &&
|
||||
completionChar != Lookup.NORMAL_SELECT_CHAR && completionChar != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) {
|
||||
TailType.insertChar(editor, tailOffset, completionChar);
|
||||
@@ -653,11 +677,11 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
}
|
||||
});
|
||||
final Runnable runnable = context1.getLaterRunnable();
|
||||
final Runnable runnable = context.getLaterRunnable();
|
||||
if (runnable != null) {
|
||||
final Runnable runnable1 = new Runnable() {
|
||||
public void run() {
|
||||
final Project project = context1.getProject();
|
||||
final Project project = context.getProject();
|
||||
if (project.isDisposed()) return;
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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.completion.impl.CompletionServiceImpl;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.editor.event.*;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.ui.HintListener;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.EventObject;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class CompletionPhase implements Disposable {
|
||||
public static final CompletionPhase NoCompletion = new CompletionPhase() {};
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public static class AutoPopupAlarm extends CompletionPhase {}
|
||||
public static class Synchronous extends CompletionPhase {}
|
||||
public static class BgCalculation extends CompletionPhase {}
|
||||
public static class ItemsCalculated extends CompletionPhase {}
|
||||
public static class Restarted extends CompletionPhase {}
|
||||
|
||||
public static class ZombiePhase extends CompletionPhase {
|
||||
public final CompletionProgressIndicator indicator;
|
||||
|
||||
protected ZombiePhase(@Nullable final LightweightHint hint, final CompletionProgressIndicator indicator) {
|
||||
this.indicator = indicator;
|
||||
@NotNull Editor editor = indicator.getEditor();
|
||||
final HintListener hintListener = new HintListener() {
|
||||
public void hintHidden(final EventObject event) {
|
||||
CompletionServiceImpl.setCompletionPhase(NoCompletion);
|
||||
}
|
||||
};
|
||||
final DocumentAdapter documentListener = new DocumentAdapter() {
|
||||
@Override
|
||||
public void beforeDocumentChange(DocumentEvent e) {
|
||||
CompletionServiceImpl.setCompletionPhase(NoCompletion);
|
||||
}
|
||||
};
|
||||
final SelectionListener selectionListener = new SelectionListener() {
|
||||
public void selectionChanged(SelectionEvent e) {
|
||||
CompletionServiceImpl.setCompletionPhase(NoCompletion);
|
||||
}
|
||||
};
|
||||
final CaretListener caretListener = new CaretListener() {
|
||||
public void caretPositionChanged(CaretEvent e) {
|
||||
CompletionServiceImpl.setCompletionPhase(NoCompletion);
|
||||
}
|
||||
};
|
||||
|
||||
final Document document = editor.getDocument();
|
||||
final SelectionModel selectionModel = editor.getSelectionModel();
|
||||
final CaretModel caretModel = editor.getCaretModel();
|
||||
|
||||
|
||||
if (hint != null) {
|
||||
hint.addHintListener(hintListener);
|
||||
}
|
||||
document.addDocumentListener(documentListener);
|
||||
selectionModel.addSelectionListener(selectionListener);
|
||||
caretModel.addCaretListener(caretListener);
|
||||
|
||||
Disposer.register(this, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (hint != null) {
|
||||
hint.removeHintListener(hintListener);
|
||||
hint.hide();
|
||||
}
|
||||
document.removeDocumentListener(documentListener);
|
||||
selectionModel.removeSelectionListener(selectionListener);
|
||||
caretModel.removeCaretListener(caretListener);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class InsertedSingleItem extends ZombiePhase {
|
||||
public InsertedSingleItem(CompletionProgressIndicator indicator) {
|
||||
super(null, indicator);
|
||||
}
|
||||
}
|
||||
public static class NoSuggestionsHint extends ZombiePhase {
|
||||
public NoSuggestionsHint(@Nullable LightweightHint hint, CompletionProgressIndicator indicator) {
|
||||
super(hint, indicator);
|
||||
}
|
||||
}
|
||||
public static class PossiblyDisturbingAutoPopup extends CompletionPhase {}
|
||||
public static class EmptyAutoPopup extends CompletionPhase {}
|
||||
|
||||
}
|
||||
+57
-99
@@ -25,11 +25,7 @@ import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.editor.event.*;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -47,8 +43,6 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.ReferenceRange;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.ui.HintListener;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -62,7 +56,6 @@ import javax.swing.*;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.Collections;
|
||||
import java.util.EventObject;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@@ -146,6 +139,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
|
||||
void notifyBackgrounded() {
|
||||
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.BgCalculation());
|
||||
myState.setBackgrounded();
|
||||
}
|
||||
|
||||
@@ -197,6 +191,10 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
public CompletionState getCompletionState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
private static int findReplacementOffset(int selectionEndOffset, PsiReference reference) {
|
||||
final List<TextRange> ranges = ReferenceRange.getAbsoluteRanges(reference);
|
||||
for (TextRange range : ranges) {
|
||||
@@ -287,20 +285,20 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
private void processModifier(KeyEvent e) {
|
||||
final int code = e.getKeyCode();
|
||||
if (code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_META || code == KeyEvent.VK_ALT || code == KeyEvent.VK_SHIFT) {
|
||||
contentComponent.removeKeyListener(this);
|
||||
myState.modifiersChanged();
|
||||
if (myState.isWaitingAfterAutoInsertion()) {
|
||||
unregisterItself(true);
|
||||
myState.handleDeath();
|
||||
CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
assert currentCompletion == null : currentCompletion;
|
||||
|
||||
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
|
||||
}
|
||||
contentComponent.removeKeyListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean isZombie() {
|
||||
return myState.isZombie();
|
||||
}
|
||||
|
||||
private void setMergeCommand() {
|
||||
CommandProcessor.getInstance().setCurrentCommandGroupId(getCompletionCommandName());
|
||||
}
|
||||
@@ -321,63 +319,12 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
CompletionServiceImpl.getCompletionService().setCurrentCompletion(this);
|
||||
}
|
||||
|
||||
public void liveAfterDeath(@Nullable final LightweightHint hint) {
|
||||
void assertDisposed() {
|
||||
myState.assertDisposed();
|
||||
}
|
||||
|
||||
if (myState.areModifiersChanged() || ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
registerItself();
|
||||
|
||||
|
||||
final HintListener hintListener = new HintListener() {
|
||||
public void hintHidden(final EventObject event) {
|
||||
unregisterItself(true);
|
||||
}
|
||||
};
|
||||
final DocumentAdapter documentListener = new DocumentAdapter() {
|
||||
@Override
|
||||
public void beforeDocumentChange(DocumentEvent e) {
|
||||
unregisterItself(true);
|
||||
}
|
||||
};
|
||||
final SelectionListener selectionListener = new SelectionListener() {
|
||||
public void selectionChanged(SelectionEvent e) {
|
||||
unregisterItself(true);
|
||||
}
|
||||
};
|
||||
final CaretListener caretListener = new CaretListener() {
|
||||
public void caretPositionChanged(CaretEvent e) {
|
||||
unregisterItself(true);
|
||||
}
|
||||
};
|
||||
|
||||
final Document document = myEditor.getDocument();
|
||||
final SelectionModel selectionModel = myEditor.getSelectionModel();
|
||||
final CaretModel caretModel = myEditor.getCaretModel();
|
||||
|
||||
|
||||
if (hint != null) {
|
||||
hint.addHintListener(hintListener);
|
||||
}
|
||||
document.addDocumentListener(documentListener);
|
||||
selectionModel.addSelectionListener(selectionListener);
|
||||
caretModel.addCaretListener(caretListener);
|
||||
|
||||
myState.goZombie(hint, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (hint != null) {
|
||||
hint.removeHintListener(hintListener);
|
||||
}
|
||||
document.removeDocumentListener(documentListener);
|
||||
selectionModel.removeSelectionListener(selectionListener);
|
||||
caretModel.removeCaretListener(caretListener);
|
||||
}
|
||||
});
|
||||
|
||||
boolean areModifiersChanged() {
|
||||
return myState.areModifiersChanged();
|
||||
}
|
||||
|
||||
public CodeCompletionHandlerBase getHandler() {
|
||||
@@ -453,21 +400,15 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
public void closeAndFinish(boolean hideLookup) {
|
||||
LOG.assertTrue(this == CompletionServiceImpl.getCompletionService().getCurrentCompletion());
|
||||
|
||||
if (myState.getCompletionHint() != null) {
|
||||
myState.getCompletionHint().hide();
|
||||
}
|
||||
|
||||
Lookup lookup = LookupManager.getActiveLookup(myEditor);
|
||||
if (lookup != null) {
|
||||
LOG.assertTrue(lookup == myLookup);
|
||||
myLookup.removeLookupListener(myLookupListener);
|
||||
finishCompletionProcess();
|
||||
LOG.assertTrue(lookup == myLookup);
|
||||
myLookup.removeLookupListener(myLookupListener);
|
||||
finishCompletionProcess();
|
||||
myState.assertDisposed();
|
||||
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
|
||||
|
||||
if (hideLookup) {
|
||||
LookupManager.getInstance(getProject()).hideActiveLookup();
|
||||
}
|
||||
} else {
|
||||
myState.assertDisposed();
|
||||
if (hideLookup) {
|
||||
LookupManager.getInstance(getProject()).hideActiveLookup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +420,15 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
Disposer.dispose(myQueue);
|
||||
unregisterItself(false);
|
||||
|
||||
myState.handleDeath();
|
||||
|
||||
CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
assert currentCompletion == this : currentCompletion + "!=" + this;
|
||||
CompletionServiceImpl.getCompletionService().setCurrentCompletion(null);
|
||||
|
||||
CompletionServiceImpl.assertPhase(CompletionPhase.BgCalculation.class, CompletionPhase.ItemsCalculated.class, CompletionPhase.Synchronous.class, CompletionPhase.Restarted.class);
|
||||
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@@ -490,13 +439,6 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterItself(boolean afterDeath) {
|
||||
myState.handleDeath(afterDeath);
|
||||
CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
assert currentCompletion == this : currentCompletion + "!=" + this;
|
||||
CompletionServiceImpl.getCompletionService().setCurrentCompletion(null);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
super.stop();
|
||||
|
||||
@@ -507,22 +449,32 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
public void run() {
|
||||
if (isOutdated()) return;
|
||||
if (!isBackgrounded()) return;
|
||||
if (isCanceled() && !myState.isRestartScheduled()) return;
|
||||
|
||||
if (isCanceled() && myState.isRestartScheduled()) {
|
||||
CompletionServiceImpl.assertPhase(CompletionPhase.Restarted.class);
|
||||
return;
|
||||
}
|
||||
|
||||
myLookup.setCalculating(false);
|
||||
|
||||
if (hideAutopopupIfMeaningless()) {
|
||||
if (isCanceled()) {
|
||||
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
|
||||
return;
|
||||
}
|
||||
|
||||
if (CompletionServiceImpl.isPhase(CompletionPhase.BgCalculation.class) && hideAutopopupIfMeaningless()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (myState.hasNoVariants()) {
|
||||
LookupManager.getInstance(getProject()).hideActiveLookup();
|
||||
|
||||
final CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
LOG.assertTrue(current == null, current + "!=" + CompletionProgressIndicator.this);
|
||||
|
||||
if (!isAutopopupCompletion()) {
|
||||
myHandler.handleEmptyLookup(getProject(), myEditor, myParameters, CompletionProgressIndicator.this);
|
||||
LookupManager.getInstance(getProject()).hideActiveLookup();
|
||||
|
||||
final CompletionProgressIndicator current = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
LOG.assertTrue(current == null, current + "!=" + CompletionProgressIndicator.this);
|
||||
|
||||
CompletionServiceImpl
|
||||
.setCompletionPhase(myHandler.handleEmptyLookup(getProject(), myEditor, myParameters, CompletionProgressIndicator.this));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -530,6 +482,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
myLookup.setFocused(true);
|
||||
}
|
||||
updateLookup();
|
||||
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.ItemsCalculated());
|
||||
}
|
||||
}
|
||||
}, myQueue.getModalityState());
|
||||
@@ -542,6 +495,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
if (items.isEmpty() && !myLookup.isCalculating()) {
|
||||
myLookup.hideLookup(false);
|
||||
LOG.assertTrue(CompletionServiceImpl.getCompletionService().getCurrentCompletion() == null);
|
||||
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.EmptyAutoPopup());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -549,6 +503,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
if ((item.getPrefixMatcher().getPrefix() + myLookup.getAdditionalPrefix()).equals(item.getLookupString())) {
|
||||
myLookup.hideLookup(true); // so that the autopopup attempts to restart after the next typed character
|
||||
LOG.assertTrue(CompletionServiceImpl.getCompletionService().getCurrentCompletion() == null);
|
||||
CompletionServiceImpl.setCompletionPhase(new CompletionPhase.PossiblyDisturbingAutoPopup());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -585,8 +540,6 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
|
||||
public void restorePrefix() {
|
||||
closeAndFinish(false);
|
||||
|
||||
new WriteCommandAction(getProject(), getCompletionCommandName()) {
|
||||
@Override
|
||||
protected void run(Result result) throws Throwable {
|
||||
@@ -676,6 +629,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
public void scheduleRestart() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
myState.scheduleRestart();
|
||||
final CompletionPhase phase = new CompletionPhase.Restarted();
|
||||
CompletionServiceImpl.setCompletionPhase(phase);
|
||||
|
||||
final Project project = getProject();
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@@ -684,6 +639,9 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
if (isOutdated()) {
|
||||
return;
|
||||
}
|
||||
if (phase != CompletionServiceImpl.getCompletionPhase()) {
|
||||
return;
|
||||
}
|
||||
|
||||
closeAndFinish(false);
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
@@ -13,7 +11,6 @@ public class CompletionState {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.CompletionState");
|
||||
private boolean myCompletionDisposed;
|
||||
private boolean myShownLookup;
|
||||
private LightweightHint myCompletionHint;
|
||||
private Boolean myToRestart;
|
||||
private boolean myRestartScheduled;
|
||||
private boolean myModifiersChanged;
|
||||
@@ -21,7 +18,6 @@ public class CompletionState {
|
||||
private boolean myBackgrounded;
|
||||
private volatile boolean myFocusLookupWhenDone;
|
||||
private volatile int myCount;
|
||||
private Runnable myZombieCleanup;
|
||||
|
||||
public CompletionState(boolean shownLookup) {
|
||||
myShownLookup = shownLookup;
|
||||
@@ -34,7 +30,6 @@ public class CompletionState {
|
||||
public void setCompletionDisposed(boolean completionDisposed) {
|
||||
LOG.assertTrue(!myCompletionDisposed, this);
|
||||
LOG.assertTrue(!isWaitingAfterAutoInsertion(), this);
|
||||
LOG.assertTrue(myCompletionHint == null, this);
|
||||
myCompletionDisposed = completionDisposed;
|
||||
}
|
||||
|
||||
@@ -46,21 +41,6 @@ public class CompletionState {
|
||||
myShownLookup = shownLookup;
|
||||
}
|
||||
|
||||
public LightweightHint getCompletionHint() {
|
||||
return myCompletionHint;
|
||||
}
|
||||
|
||||
public void goZombie(@Nullable LightweightHint completionHint, @NotNull Runnable cleanup) {
|
||||
LOG.assertTrue(myZombieCleanup == null, this);
|
||||
if (completionHint != null) {
|
||||
LOG.assertTrue(myCompletionHint == null, this);
|
||||
} else {
|
||||
LOG.assertTrue(!myModifiersChanged, this);
|
||||
}
|
||||
myCompletionHint = completionHint;
|
||||
myZombieCleanup = cleanup;
|
||||
}
|
||||
|
||||
public boolean isToRestart() {
|
||||
return myToRestart == Boolean.TRUE;
|
||||
}
|
||||
@@ -91,10 +71,16 @@ public class CompletionState {
|
||||
}
|
||||
|
||||
public boolean isWaitingAfterAutoInsertion() {
|
||||
return myRestorePrefix != null && isZombie();
|
||||
CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
|
||||
if (phase instanceof CompletionPhase.InsertedSingleItem && ((CompletionPhase.InsertedSingleItem)phase).indicator.getCompletionState() == this) {
|
||||
LOG.assertTrue(myRestorePrefix != null, this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setRestorePrefix(Runnable restorePrefix) {
|
||||
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
|
||||
myRestorePrefix = restorePrefix;
|
||||
}
|
||||
|
||||
@@ -121,27 +107,17 @@ public class CompletionState {
|
||||
}
|
||||
|
||||
public void restorePrefix() {
|
||||
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
|
||||
if (myRestorePrefix != null) {
|
||||
myRestorePrefix.run();
|
||||
myRestorePrefix = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void handleDeath(boolean afterDeath) {
|
||||
public void handleDeath() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
boolean zombie = isZombie();
|
||||
LOG.assertTrue(afterDeath == zombie, this);
|
||||
assertDisposed();
|
||||
if (zombie) {
|
||||
myZombieCleanup.run();
|
||||
}
|
||||
myZombieCleanup = null;
|
||||
myCompletionHint = null;
|
||||
setRestorePrefix(null);
|
||||
}
|
||||
|
||||
public boolean isZombie() {
|
||||
return myZombieCleanup != null;
|
||||
myRestorePrefix = null;
|
||||
}
|
||||
|
||||
int incCount() {
|
||||
@@ -155,9 +131,9 @@ public class CompletionState {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CompletionState{" +
|
||||
"myCompletionDisposed=" + myCompletionDisposed +
|
||||
"phase=" + CompletionServiceImpl.getCompletionPhase() +
|
||||
", myCompletionDisposed=" + myCompletionDisposed +
|
||||
", myShownLookup=" + myShownLookup +
|
||||
", myCompletionHint=" + myCompletionHint +
|
||||
", myToRestart=" + myToRestart +
|
||||
", myRestartScheduled=" + myRestartScheduled +
|
||||
", myModifiersReleased=" + myModifiersChanged +
|
||||
@@ -165,7 +141,6 @@ public class CompletionState {
|
||||
", myBackgrounded=" + myBackgrounded +
|
||||
", myFocusLookupWhenDone=" + myFocusLookupWhenDone +
|
||||
", myCount=" + myCount +
|
||||
", myZombieCleanup=" + myZombieCleanup +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
+38
-1
@@ -20,10 +20,12 @@ import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -35,6 +37,8 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.impl.CompletionServiceImpl");
|
||||
private Throwable myTrace = null;
|
||||
private CompletionProgressIndicator myCurrentCompletion;
|
||||
private static CompletionPhase ourPhase = CompletionPhase.NoCompletion;
|
||||
private static String ourPhaseTrace;
|
||||
|
||||
public static CompletionServiceImpl getCompletionService() {
|
||||
return (CompletionServiceImpl)CompletionService.getCompletionService();
|
||||
@@ -138,7 +142,13 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
final String newLookupString = handleCaseInsensitiveVariant(prefix, oldLookupString);
|
||||
if (!newLookupString.equals(oldLookupString)) {
|
||||
final Document document = context.getEditor().getDocument();
|
||||
document.replaceString(context.getStartOffset(), context.getTailOffset(), newLookupString);
|
||||
int startOffset = context.getStartOffset();
|
||||
int tailOffset = context.getTailOffset();
|
||||
|
||||
assert startOffset >= 0 : "stale startOffset";
|
||||
assert tailOffset >= 0 : "stale tailOffset";
|
||||
|
||||
document.replaceString(startOffset, tailOffset, newLookupString);
|
||||
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document);
|
||||
}
|
||||
}
|
||||
@@ -162,4 +172,31 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
return lookupString;
|
||||
}
|
||||
|
||||
public static void assertPhase(Class<? extends CompletionPhase>... possibilities) {
|
||||
if (!isPhase(possibilities)) {
|
||||
LOG.error(ourPhase + "; set at " + ourPhaseTrace);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPhase(Class<? extends CompletionPhase>... possibilities) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
for (Class<? extends CompletionPhase> possibility : possibilities) {
|
||||
if (possibility.isInstance(ourPhase)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setCompletionPhase(@NotNull CompletionPhase phase) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
Disposer.dispose(ourPhase);
|
||||
ourPhase = phase;
|
||||
ourPhaseTrace = DebugUtil.currentStackTrace();
|
||||
}
|
||||
|
||||
public static CompletionPhase getCompletionPhase() {
|
||||
// ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
return ourPhase;
|
||||
}
|
||||
}
|
||||
|
||||
+15
-2
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.editorActions;
|
||||
import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
|
||||
import com.intellij.codeInsight.completion.CompletionPhase;
|
||||
import com.intellij.codeInsight.completion.CompletionProgressIndicator;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
|
||||
@@ -93,9 +94,14 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
|
||||
|
||||
final boolean isMainEditor = FileEditorManager.getInstance(project).getSelectedTextEditor() == editor;
|
||||
|
||||
final CompletionPhase.AutoPopupAlarm phase = new CompletionPhase.AutoPopupAlarm();
|
||||
CompletionServiceImpl.setCompletionPhase(phase);
|
||||
|
||||
final Runnable request = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (CompletionServiceImpl.getCompletionPhase() != phase) return;
|
||||
|
||||
if (project.isDisposed() || !file.isValid()) return;
|
||||
if (editor.isDisposed() || isMainEditor && FileEditorManager.getInstance(project).getSelectedTextEditor() != editor) return;
|
||||
if (ApplicationManager.getApplication().isWriteAccessAllowed()) return; //it will fail anyway
|
||||
@@ -152,9 +158,16 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
|
||||
}
|
||||
|
||||
final CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
|
||||
if (currentCompletion != null) {
|
||||
currentCompletion.closeAndFinish(true);
|
||||
if (CompletionServiceImpl.isPhase(CompletionPhase.AutoPopupAlarm.class, CompletionPhase.EmptyAutoPopup.class, CompletionPhase.PossiblyDisturbingAutoPopup.class)) {
|
||||
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
|
||||
assert currentCompletion == null;
|
||||
} else {
|
||||
if (currentCompletion != null) {
|
||||
currentCompletion.closeAndFinish(true);
|
||||
}
|
||||
CompletionServiceImpl.assertPhase(CompletionPhase.NoCompletion.getClass());
|
||||
}
|
||||
|
||||
state.stopAutoPopup();
|
||||
}
|
||||
|
||||
|
||||
+31
-23
@@ -54,6 +54,7 @@ import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
|
||||
@@ -839,35 +840,42 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
|
||||
public LookupElement[] complete(final CompletionType type, final int invocationCount) {
|
||||
assertInitialized();
|
||||
myEmptyLookup = false;
|
||||
new WriteCommandAction(getProject()) {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
protected void run(Result result) throws Exception {
|
||||
final CodeCompletionHandlerBase handler = new CodeCompletionHandlerBase(type) {
|
||||
public void run() {
|
||||
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
|
||||
@Override
|
||||
protected PsiFile createFileCopy(final PsiFile file) {
|
||||
final PsiFile copy = super.createFileCopy(file);
|
||||
if (myFileContext != null) {
|
||||
final PsiElement contextCopy = myFileContext.copy();
|
||||
final PsiFile containingFile = contextCopy.getContainingFile();
|
||||
if (containingFile instanceof PsiFileImpl) {
|
||||
((PsiFileImpl)containingFile).setOriginalFile(myFileContext.getContainingFile());
|
||||
public void run() {
|
||||
final CodeCompletionHandlerBase handler = new CodeCompletionHandlerBase(type) {
|
||||
@Override
|
||||
protected PsiFile createFileCopy(final PsiFile file) {
|
||||
final PsiFile copy = super.createFileCopy(file);
|
||||
if (myFileContext != null) {
|
||||
final PsiElement contextCopy = myFileContext.copy();
|
||||
final PsiFile containingFile = contextCopy.getContainingFile();
|
||||
if (containingFile instanceof PsiFileImpl) {
|
||||
((PsiFileImpl)containingFile).setOriginalFile(myFileContext.getContainingFile());
|
||||
}
|
||||
setContext(copy, contextCopy);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
setContext(copy, contextCopy);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void completionFinished(final int offset1, final int offset2, final CompletionProgressIndicator indicator,
|
||||
final LookupElement[] items) {
|
||||
myEmptyLookup = items.length == 0;
|
||||
super.completionFinished(offset1, offset2, indicator, items);
|
||||
@Override
|
||||
protected void completionFinished(final int offset1, final int offset2, final CompletionProgressIndicator indicator,
|
||||
final LookupElement[] items) {
|
||||
myEmptyLookup = items.length == 0;
|
||||
super.completionFinished(offset1, offset2, indicator, items);
|
||||
}
|
||||
};
|
||||
Editor editor = getCompletionEditor();
|
||||
handler.invokeCompletion(getProject(), editor, PsiUtilBase.getPsiFileInEditor(editor, getProject()), invocationCount);
|
||||
|
||||
}
|
||||
};
|
||||
Editor editor = getCompletionEditor();
|
||||
handler.invokeCompletion(getProject(), editor, PsiUtilBase.getPsiFileInEditor(editor, getProject()), invocationCount);
|
||||
}, null, null);
|
||||
}
|
||||
}.execute();
|
||||
});
|
||||
|
||||
return getLookupElements();
|
||||
}
|
||||
|
||||
|
||||
@@ -781,7 +781,7 @@
|
||||
order="before openedInEditor"/>
|
||||
<weigher key="proximity" implementationClass="com.intellij.psi.util.proximity.JavaInheritanceWeigher" id="javaInheritance"
|
||||
order="after explicitlyImported, before sameLogicalRoot"/>
|
||||
<weigher key="proximity" implementationClass="com.intellij.psi.util.proximity.KnownPackageWeigher" id="knownPackage"
|
||||
<weigher key="proximity" implementationClass="com.intellij.psi.util.proximity.KnownElementWeigher" id="knownElement"
|
||||
order="after sameModule, before sdkOrLibrary"/>
|
||||
|
||||
<statistician key="proximity" implementationClass="com.intellij.codeInsight.completion.JavaProximityStatistician"/>
|
||||
|
||||
Reference in New Issue
Block a user