mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-78158 Go to Declaration doesn't work from completion popup in som cases
This commit is contained in:
+41
-32
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInsight.completion
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.codeInsight.TargetElementUtil
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl
|
||||
import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler
|
||||
import com.intellij.codeInsight.lookup.Lookup
|
||||
@@ -27,6 +28,7 @@ import com.intellij.ide.DataManager
|
||||
import com.intellij.ide.ui.UISettings
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.IdeActions
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.command.impl.CurrentEditorProvider
|
||||
@@ -34,22 +36,27 @@ import com.intellij.openapi.command.impl.UndoManagerImpl
|
||||
import com.intellij.openapi.command.undo.UndoManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.EditorFactory
|
||||
import com.intellij.openapi.editor.LogicalPosition
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.extensions.LoadingOrder
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.util.Consumer
|
||||
import com.intellij.openapi.editor.LogicalPosition
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.util.Computable
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.util.Consumer
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
@Override
|
||||
protected void setUp() {
|
||||
super.setUp() //To change body of overridden methods use File | Settings | File Templates.
|
||||
CompletionAutoPopupHandler.testName = getName()
|
||||
}
|
||||
|
||||
public void testNewItemsOnLongerPrefix() {
|
||||
myFixture.configureByText("a.java", """
|
||||
@@ -147,18 +154,6 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
|
||||
|
||||
}
|
||||
|
||||
public void _testNoAutopopupInTheMiddleOfIdentifier() {
|
||||
myFixture.configureByText("a.java", """
|
||||
class Foo {
|
||||
String foo(String iterable) {
|
||||
return it<caret>rable;
|
||||
}
|
||||
}
|
||||
""")
|
||||
type 'e'
|
||||
assertNull lookup
|
||||
}
|
||||
|
||||
public void testGenerallyFocusLookupInJavaMethod() {
|
||||
myFixture.configureByText("a.java", """
|
||||
class Foo {
|
||||
@@ -935,6 +930,36 @@ public class Bar {
|
||||
assert !lookup
|
||||
}
|
||||
|
||||
public void testTargetElementInLookup() {
|
||||
myFixture.configureByText 'a.java', '''
|
||||
class Foo {
|
||||
void x__foo() {}
|
||||
void bar() {
|
||||
<caret>
|
||||
}
|
||||
void x__goo() {}
|
||||
}
|
||||
'''
|
||||
def cls = ((PsiJavaFile)myFixture.file).getClasses()[0]
|
||||
def foo = cls.methods[0]
|
||||
def goo = cls.methods[2]
|
||||
type('x')
|
||||
assert myFixture.lookupElementStrings == ['x__foo', 'x__goo']
|
||||
edt {
|
||||
assert foo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN)
|
||||
assert goo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
|
||||
}
|
||||
|
||||
type('_')
|
||||
assert myFixture.lookupElementStrings == ['x__foo', 'x__goo']
|
||||
edt {
|
||||
assert goo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_UP)
|
||||
assert foo == TargetElementUtil.instance.findTargetElement(myFixture.editor, TargetElementUtil.LOOKUP_ITEM_ACCEPTED)
|
||||
}
|
||||
}
|
||||
|
||||
public void testExplicitAutocompletionAfterAutoPopup() {
|
||||
myFixture.configureByText 'a.java', 'class Foo <caret>'
|
||||
type 'ext'
|
||||
@@ -1029,22 +1054,6 @@ public class UTest {
|
||||
assert 'xxxxx.SYSTEM_EXCEPTION' == ((JavaPsiClassReferenceElement) myFixture.lookupElements[2]).qualifiedName
|
||||
}
|
||||
|
||||
public void _testTabShouldPreferLookupsToLiveTemplate() {
|
||||
myFixture.configureByText "a.java", """
|
||||
class LiveComplete {
|
||||
public void innerThing() { }
|
||||
public void context() {
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
"""
|
||||
type 'inn'
|
||||
assert myFixture.lookupElementStrings == ['inn', 'innerThing']
|
||||
edt { myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN) }
|
||||
type '\t'
|
||||
assert myFixture.file.text.contains("innerThing();")
|
||||
}
|
||||
|
||||
private FileEditor openEditorForUndo() {
|
||||
FileEditor editor;
|
||||
edt { editor = FileEditorManager.getInstance(project).openFile(myFixture.file.virtualFile, false)[0] }
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -26,7 +27,7 @@ import java.util.Set;
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class OffsetMap {
|
||||
public class OffsetMap implements Disposable {
|
||||
private final Document myDocument;
|
||||
private final Map<OffsetKey, RangeMarker> myMap = new THashMap<OffsetKey, RangeMarker>();
|
||||
private final Set<OffsetKey> myModified = new THashSet<OffsetKey>();
|
||||
|
||||
+16
-32
@@ -40,7 +40,6 @@ import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.editor.ex.RangeMarkerEx;
|
||||
@@ -51,10 +50,7 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
@@ -75,7 +71,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@@ -272,7 +267,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
boolean hasModifiers,
|
||||
int invocationCount,
|
||||
PsiFile hostFile,
|
||||
int hostStartOffset, Editor hostEditor, OffsetMap hostMap) {
|
||||
int hostStartOffset, Editor hostEditor, OffsetMap hostMap, OffsetTranslator translator) {
|
||||
CompletionContext context = createCompletionContext(hostFile, hostStartOffset, hostEditor, hostMap);
|
||||
CompletionParameters parameters = createCompletionParameters(invocationCount, initContext, context);
|
||||
|
||||
@@ -291,8 +286,9 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
freezeSemaphore.down();
|
||||
final CompletionProgressIndicator indicator = new CompletionProgressIndicator(editor, parameters, this, freezeSemaphore,
|
||||
initContext.getOffsetMap(), hasModifiers);
|
||||
indicator.addMapToDispose(hostMap);
|
||||
indicator.addMapToDispose(context.getOffsetMap());
|
||||
Disposer.register(indicator, hostMap);
|
||||
Disposer.register(indicator, context.getOffsetMap());
|
||||
Disposer.register(indicator, translator);
|
||||
|
||||
CompletionServiceImpl.setCompletionPhase(synchronous ? new CompletionPhase.Synchronous(indicator) : new CompletionPhase.BgCalculation(indicator));
|
||||
|
||||
@@ -539,6 +535,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
|
||||
final Document document = fileCopy[0].getViewProvider().getDocument();
|
||||
assert document != null : "no document";
|
||||
final OffsetTranslator translator = new OffsetTranslator(initContext.getEditor().getDocument(), initContext.getFile(), document);
|
||||
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
@Override
|
||||
@@ -546,7 +543,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
patchFileCopy(initContext, fileCopy[0], document);
|
||||
initContext.getFileCopyPatcher().patchFileCopy(fileCopy[0], document, initContext.getOffsetMap());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -559,6 +556,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
if (!synchronous) {
|
||||
if (!CompletionServiceImpl.assertPhase(CompletionPhase.CommittingDocuments.class)) {
|
||||
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
|
||||
Disposer.dispose(translator);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -567,15 +565,18 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
CompletionAutoPopupHandler.runLaterWithCommitted(project, hostDocument, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (phase.checkExpired()) return;
|
||||
doComplete(initContext, hasModifiers, invocationCount, hostFile, hostStartOffset, hostEditor, hostMap);
|
||||
if (phase.checkExpired()) {
|
||||
Disposer.dispose(translator);
|
||||
return;
|
||||
}
|
||||
doComplete(initContext, hasModifiers, invocationCount, hostFile, hostStartOffset, hostEditor, hostMap, translator);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
PsiDocumentManager.getInstance(hostFile.getProject()).commitDocument(hostDocument);
|
||||
|
||||
doComplete(initContext, hasModifiers, invocationCount, hostFile, hostStartOffset, hostEditor, hostMap);
|
||||
doComplete(initContext, hasModifiers, invocationCount, hostFile, hostStartOffset, hostEditor, hostMap, translator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,23 +613,6 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
return context;
|
||||
}
|
||||
|
||||
private static void patchFileCopy(CompletionInitializationContext initContext, PsiFile fileCopy, Document document) {
|
||||
final LinkedList<DocumentEvent> events = new LinkedList<DocumentEvent>();
|
||||
|
||||
final DocumentAdapter listener = new DocumentAdapter() {
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
events.addFirst(e);
|
||||
}
|
||||
};
|
||||
|
||||
document.addDocumentListener(listener);
|
||||
initContext.getFileCopyPatcher().patchFileCopy(fileCopy, document, initContext.getOffsetMap());
|
||||
document.removeDocumentListener(listener);
|
||||
|
||||
document.putUserData(CompletionUtil.RANGE_TRANSLATION, events);
|
||||
}
|
||||
|
||||
private boolean isAutocompleteCommonPrefixOnInvocation() {
|
||||
return invokedExplicitly && CodeInsightSettings.getInstance().AUTOCOMPLETE_COMMON_PREFIX;
|
||||
}
|
||||
@@ -681,7 +665,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
if (!indicator.getProject().isDisposed()) {
|
||||
runnable.run();
|
||||
}
|
||||
indicator.disposeOffsetMaps();
|
||||
indicator.disposeIndicator();
|
||||
}
|
||||
};
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
@@ -692,7 +676,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
}
|
||||
}
|
||||
else {
|
||||
indicator.disposeOffsetMaps();
|
||||
indicator.disposeIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-15
@@ -30,6 +30,7 @@ import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.injected.editor.EditorWindow;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
@@ -61,7 +62,6 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -74,13 +74,12 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class CompletionProgressIndicator extends ProgressIndicatorBase implements CompletionProcess{
|
||||
public class CompletionProgressIndicator extends ProgressIndicatorBase implements CompletionProcess, Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.CompletionProgressIndicator");
|
||||
private final Editor myEditor;
|
||||
private final CompletionParameters myParameters;
|
||||
@@ -115,7 +114,6 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
};
|
||||
private volatile int myCount;
|
||||
private final ConcurrentHashMap<LookupElement, CompletionSorterImpl> myItemSorters = new ConcurrentHashMap<LookupElement, CompletionSorterImpl>(TObjectHashingStrategy.IDENTITY);
|
||||
private final Set<OffsetMap> myMapsToDispose = new THashSet<OffsetMap>();
|
||||
private final PropertyChangeListener myLookupManagerListener;
|
||||
|
||||
public CompletionProgressIndicator(final Editor editor, CompletionParameters parameters, CodeCompletionHandlerBase handler, Semaphore freezeSemaphore,
|
||||
@@ -146,7 +144,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
myQueue.setPassThrough(false);
|
||||
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
addMapToDispose(offsetMap);
|
||||
Disposer.register(this, offsetMap);
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
return;
|
||||
@@ -215,6 +213,10 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
return myItemSorters.get(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
private static int findReplacementOffset(int selectionEndOffset, PsiReference reference) {
|
||||
final List<TextRange> ranges = ReferenceRange.getAbsoluteRanges(reference);
|
||||
for (TextRange range : ranges) {
|
||||
@@ -429,15 +431,12 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
|
||||
if (disposeOffsetMap) {
|
||||
disposeOffsetMaps();
|
||||
disposeIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
void disposeOffsetMaps() {
|
||||
for (OffsetMap map : myMapsToDispose) {
|
||||
map.dispose();
|
||||
}
|
||||
myMapsToDispose.clear();
|
||||
void disposeIndicator() {
|
||||
Disposer.dispose(this);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@@ -738,8 +737,4 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
public void addMapToDispose(OffsetMap map) {
|
||||
myMapsToDispose.add(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.intellij.codeInsight.lookup.LookupValueWithPsiElement;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.util.Key;
|
||||
@@ -43,12 +42,10 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.patterns.PlatformPatterns.character;
|
||||
|
||||
public class CompletionUtil {
|
||||
static final Key<List<DocumentEvent>> RANGE_TRANSLATION = Key.create("completion.rangeTranslation");
|
||||
static final Key<OffsetTranslator> RANGE_TRANSLATION = Key.create("completion.rangeTranslation");
|
||||
public static final Key<TailType> TAIL_TYPE_ATTR = LookupItem.TAIL_TYPE_ATTR;
|
||||
|
||||
private static final CompletionData ourGenericCompletionData = new CompletionData() {
|
||||
@@ -221,19 +218,6 @@ public class CompletionUtil {
|
||||
context.setTailOffset(tailOffset);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Integer translateOffset(int offset, DocumentEvent event) {
|
||||
if (event.getOffset() < offset && offset < event.getOffset() + event.getNewLength()) {
|
||||
if (event.getOldLength() == 0) {
|
||||
return event.getOffset();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return offset <= event.getOffset() ? offset : offset - event.getNewLength() + event.getOldLength();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getTargetElement(LookupElement lookupElement) {
|
||||
Object object = lookupElement.getObject();
|
||||
@@ -262,14 +246,12 @@ public class CompletionUtil {
|
||||
Integer end = range.getEndOffset();
|
||||
final Document document = file.getViewProvider().getDocument();
|
||||
if (document != null) {
|
||||
final List<DocumentEvent> translator = document.getUserData(RANGE_TRANSLATION);
|
||||
final OffsetTranslator translator = document.getUserData(RANGE_TRANSLATION);
|
||||
if (translator != null) {
|
||||
for (DocumentEvent event : translator) {
|
||||
start = translateOffset(start, event);
|
||||
end = translateOffset(end, event);
|
||||
if (start == null || end == null) {
|
||||
return null;
|
||||
}
|
||||
start = translator.translateOffset(start);
|
||||
end = translator.translateOffset(end);
|
||||
if (start == null || end == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.openapi.Disposable;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class OffsetTranslator implements Disposable {
|
||||
private final Document myCopyDocument;
|
||||
private final LinkedList<DocumentEvent> myTranslation = new LinkedList<DocumentEvent>();
|
||||
|
||||
public OffsetTranslator(final Document originalDocument, final PsiFile originalFile, Document copyDocument) {
|
||||
myCopyDocument = copyDocument;
|
||||
myCopyDocument.putUserData(CompletionUtil.RANGE_TRANSLATION, this);
|
||||
|
||||
final LinkedList<DocumentEvent> sinceCommit = new LinkedList<DocumentEvent>();
|
||||
originalDocument.addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
if (isUpToDate()) {
|
||||
DocumentEventImpl inverse =
|
||||
new DocumentEventImpl(originalDocument, e.getOffset(), e.getNewFragment(), e.getOldFragment(), 0, false);
|
||||
sinceCommit.addLast(inverse);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
myCopyDocument.addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
if (isUpToDate()) {
|
||||
myTranslation.addFirst(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
originalFile.getProject().getMessageBus().connect(this).subscribe(PsiModificationTracker.TOPIC, new PsiModificationTracker.Listener() {
|
||||
long lastModCount = originalFile.getModificationStamp();
|
||||
@Override
|
||||
public void modificationCountChanged() {
|
||||
if (isUpToDate() && lastModCount != originalFile.getModificationStamp()) {
|
||||
myTranslation.addAll(sinceCommit);
|
||||
sinceCommit.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private boolean isUpToDate() {
|
||||
return this == myCopyDocument.getUserData(CompletionUtil.RANGE_TRANSLATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (isUpToDate()) {
|
||||
myCopyDocument.putUserData(CompletionUtil.RANGE_TRANSLATION, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer translateOffset(Integer offset) {
|
||||
for (DocumentEvent event : myTranslation) {
|
||||
offset = translateOffset(offset, event);
|
||||
if (offset == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Integer translateOffset(int offset, DocumentEvent event) {
|
||||
if (event.getOffset() < offset && offset < event.getOffset() + event.getNewLength()) {
|
||||
if (event.getOldLength() == 0) {
|
||||
return event.getOffset();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return offset <= event.getOffset() ? offset : offset - event.getNewLength() + event.getOldLength();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,11 +24,10 @@ import com.intellij.codeInsight.completion.OffsetMap;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
import com.intellij.codeInsight.template.*;
|
||||
import com.intellij.codeInsight.template.Result;
|
||||
import com.intellij.lang.LanguageLiteralEscapers;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandAdapter;
|
||||
import com.intellij.openapi.command.CommandEvent;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
@@ -45,6 +44,7 @@ import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.editor.markup.*;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -556,7 +556,7 @@ public class TemplateState implements Disposable {
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
offsetMap.dispose();
|
||||
Disposer.dispose(offsetMap);
|
||||
|
||||
if (completionChar == '.') {
|
||||
EditorModificationUtil.insertStringAtCaret(myEditor, ".");
|
||||
|
||||
@@ -57,7 +57,6 @@ import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.project.ModuleListener;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerAdapter;
|
||||
import com.intellij.openapi.project.ex.ProjectEx;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.project.impl.ProjectImpl;
|
||||
@@ -531,6 +530,8 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
|
||||
public void run() {
|
||||
((UndoManagerImpl)UndoManager.getGlobalInstance()).dropHistoryInTests();
|
||||
((UndoManagerImpl)UndoManager.getInstance(project)).dropHistoryInTests();
|
||||
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
-15
@@ -54,7 +54,6 @@ import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
|
||||
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;
|
||||
@@ -1029,20 +1028,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
LookupManager.getInstance(getProject()).hideActiveLookup();
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
}
|
||||
else {
|
||||
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LookupManager.getInstance(getProject()).hideActiveLookup();
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
UIUtil.pump();
|
||||
}
|
||||
|
||||
((StatisticsManagerImpl)StatisticsManager.getInstance()).clearStatistics();
|
||||
|
||||
FileEditorManager editorManager = FileEditorManager.getInstance(getProject());
|
||||
|
||||
+2
-4
@@ -107,10 +107,9 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu
|
||||
}
|
||||
|
||||
InjectedLanguageManagerImpl injectedLanguageManager = (InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(getProject());
|
||||
Runnable runnable = new Runnable() {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -119,8 +118,7 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
UIUtil.invokeAndWaitIfNeeded(runnable);
|
||||
});
|
||||
|
||||
for (final File fileToDelete : myFilesToDelete) {
|
||||
boolean deleted = FileUtil.delete(fileToDelete);
|
||||
|
||||
Reference in New Issue
Block a user