mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
show autoimport popup when type space after class name, even if visible pass hasnt been run
This commit is contained in:
+14
-6
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
@@ -129,12 +130,12 @@ public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> im
|
||||
|
||||
DaemonCodeAnalyzerImpl codeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
|
||||
|
||||
boolean canImportHere = true;
|
||||
|
||||
if (classes.length == 1
|
||||
&& com.intellij.codeInsight.CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY
|
||||
&& (allowCaretNearRef || !isCaretNearRef(editor, myRef))
|
||||
&& !JspPsiUtil.isInJspFile(psiFile)
|
||||
&& codeAnalyzer.canChangeFileSilently(psiFile)
|
||||
&& !hasUnresolvedImportWhichCanImport(psiFile, classes[0].getName())) {
|
||||
&& (canImportHere = canImportHere(allowCaretNearRef, editor, psiFile, classes[0].getName()))
|
||||
&& CodeInsightSettings.getInstance().ADD_UNAMBIGIOUS_IMPORTS_ON_THE_FLY
|
||||
&& codeAnalyzer.canChangeFileSilently(psiFile)) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
public void run() {
|
||||
action.execute();
|
||||
@@ -142,13 +143,20 @@ public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> im
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (doShow) {
|
||||
|
||||
if (doShow && canImportHere) {
|
||||
String hintText = ShowAutoImportPass.getMessage(classes.length > 1, classes[0].getQualifiedName());
|
||||
HintManager.getInstance().showQuestionHint(editor, hintText, myRef.getTextOffset(), myRef.getTextRange().getEndOffset(), action);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean canImportHere(boolean allowCaretNearRef, Editor editor, PsiFile psiFile, String exampleClassName) {
|
||||
return (allowCaretNearRef || !isCaretNearRef(editor, myRef)) &&
|
||||
!JspPsiUtil.isInJspFile(psiFile) &&
|
||||
!hasUnresolvedImportWhichCanImport(psiFile, exampleClassName);
|
||||
}
|
||||
|
||||
protected abstract boolean isQualified(T reference);
|
||||
|
||||
public boolean showHint(final Editor editor) {
|
||||
|
||||
@@ -68,6 +68,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase {
|
||||
@@ -286,7 +291,7 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase {
|
||||
|
||||
CodeInsightTestFixtureImpl.instantiateAndRun(getFile(), getEditor(), toIgnore.toNativeArray());
|
||||
|
||||
if (doTestLineMarkers()) {
|
||||
if (!canChangeDocumentDuringHighlighting()) {
|
||||
Document document = getDocument(getFile());
|
||||
assertTrue(((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject())).getFileStatusMap().allDirtyScopesAreNull(document));
|
||||
}
|
||||
@@ -295,6 +300,23 @@ public abstract class DaemonAnalyzerTestCase extends CodeInsightTestCase {
|
||||
return infos == null ? Collections.<HighlightInfo>emptyList() : new ArrayList<HighlightInfo>(infos);
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
protected @interface CanChangeDocumentDuringHighlighting {}
|
||||
|
||||
private boolean canChangeDocumentDuringHighlighting() {
|
||||
String methodName = "test" + getTestName(false);
|
||||
Method method = null;
|
||||
try {
|
||||
method = getClass().getDeclaredMethod(methodName);
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
fail(methodName);
|
||||
}
|
||||
CanChangeDocumentDuringHighlighting annotation = method.getAnnotation(CanChangeDocumentDuringHighlighting.class);
|
||||
return annotation != null;
|
||||
}
|
||||
|
||||
public static List<HighlightInfo> filter(final List<HighlightInfo> infos, HighlightSeverity minSeverity) {
|
||||
ArrayList<HighlightInfo> result = new ArrayList<HighlightInfo>();
|
||||
for (final HighlightInfo info : infos) {
|
||||
|
||||
@@ -269,10 +269,7 @@ public class DaemonListeners implements Disposable {
|
||||
if (file instanceof PsiCodeFragment) return true;
|
||||
Project project = file.getProject();
|
||||
if (!ModuleUtil.projectContainsFile(project, virtualFile, false)) return false;
|
||||
FileEditor[] editors = FileEditorManager.getInstance(myProject).getEditors(virtualFile);
|
||||
for (FileEditor editor : editors) {
|
||||
if (!editor.isModified()) return false;
|
||||
}
|
||||
if (!FileDocumentManager.getInstance().isFileModified(virtualFile)) return false;
|
||||
FilePath path = new FilePathImpl(virtualFile);
|
||||
boolean vcsIsThinking = !VcsDirtyScopeManager.getInstance(myProject).whatFilesDirty(Arrays.asList(path)).isEmpty();
|
||||
if (vcsIsThinking) return false;
|
||||
|
||||
+1
-3
@@ -33,9 +33,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class IdentifierHighlighterPassFactory extends AbstractProjectComponent implements TextEditorHighlightingPassFactory {
|
||||
public IdentifierHighlighterPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) {
|
||||
super(project);
|
||||
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{
|
||||
Pass.UPDATE_VISIBLE
|
||||
}, null, false, -1);
|
||||
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_VISIBLE}, null, false, -1);
|
||||
}
|
||||
|
||||
public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) {
|
||||
|
||||
+11
-5
@@ -17,6 +17,7 @@
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeHighlighting.HighlightingPass;
|
||||
import com.intellij.codeHighlighting.Pass;
|
||||
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
|
||||
import com.intellij.concurrency.Job;
|
||||
import com.intellij.concurrency.JobImpl;
|
||||
@@ -37,8 +38,8 @@ import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -202,7 +203,7 @@ public abstract class PassExecutorService implements Disposable {
|
||||
toBeSubmitted.put(key, scheduledPass);
|
||||
for (int predecessorId : pass.getCompletionPredecessorIds()) {
|
||||
ScheduledPass predecessor = findOrCreatePredecessorPass(fileEditors, document, toBeSubmitted, textEditorHighlightingPasses, freePasses,
|
||||
updateProgress, threadsToStartCountdown, jobPriority, predecessorId);
|
||||
updateProgress, threadsToStartCountdown, jobPriority, predecessorId, passId);
|
||||
if (predecessor != null) {
|
||||
predecessor.mySuccessorsOnCompletion.add(scheduledPass);
|
||||
scheduledPass.myRunningPredecessorsCount.incrementAndGet();
|
||||
@@ -210,7 +211,7 @@ public abstract class PassExecutorService implements Disposable {
|
||||
}
|
||||
for (int predecessorId : pass.getStartingPredecessorIds()) {
|
||||
ScheduledPass predecessor = findOrCreatePredecessorPass(fileEditors, document, toBeSubmitted, textEditorHighlightingPasses, freePasses,
|
||||
updateProgress, threadsToStartCountdown, jobPriority, predecessorId);
|
||||
updateProgress, threadsToStartCountdown, jobPriority, predecessorId, passId);
|
||||
if (predecessor != null) {
|
||||
predecessor.mySuccessorsOnSubmit.add(scheduledPass);
|
||||
scheduledPass.myRunningPredecessorsCount.incrementAndGet();
|
||||
@@ -230,12 +231,17 @@ public abstract class PassExecutorService implements Disposable {
|
||||
final DaemonProgressIndicator updateProgress,
|
||||
final AtomicInteger myThreadsToStartCountdown,
|
||||
final int jobPriority,
|
||||
final int predecessorId) {
|
||||
final int predecessorId, int passId) {
|
||||
Pair<Document, Integer> predkey = Pair.create(document, predecessorId);
|
||||
ScheduledPass predecessor = toBeSubmitted.get(predkey);
|
||||
if (predecessor == null) {
|
||||
TextEditorHighlightingPass textEditorPass = findPassById(predecessorId, textEditorHighlightingPasses);
|
||||
predecessor = textEditorPass == null ? null : createScheduledPass(fileEditors, textEditorPass, toBeSubmitted, textEditorHighlightingPasses,freePasses,
|
||||
if (textEditorPass == null && predecessorId == Pass.UPDATE_VISIBLE && passId != Pass.UPDATE_ALL && findPassById(Pass.UPDATE_ALL, textEditorHighlightingPasses) != null) {
|
||||
// when UPDATE_VISIBLE pass is not going to run, pretend that all dependent passes are depend on UPDATE_ALL pass instead
|
||||
return findOrCreatePredecessorPass(fileEditors, document, toBeSubmitted, textEditorHighlightingPasses, freePasses, updateProgress,
|
||||
myThreadsToStartCountdown, jobPriority, Pass.UPDATE_ALL, passId);
|
||||
}
|
||||
predecessor = textEditorPass == null ? null : createScheduledPass(fileEditors, textEditorPass, toBeSubmitted, textEditorHighlightingPasses, freePasses,
|
||||
updateProgress, myThreadsToStartCountdown, jobPriority);
|
||||
}
|
||||
return predecessor;
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.HintAction;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
@@ -78,8 +79,9 @@ public class ShowAutoImportPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
public void doApplyInformationToEditor() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (!myEditor.getContentComponent().hasFocus()) return;
|
||||
Application application = ApplicationManager.getApplication();
|
||||
application.assertIsDispatchThread();
|
||||
if (!application.isUnitTestMode() && !myEditor.getContentComponent().hasFocus()) return;
|
||||
List<HighlightInfo> visibleHighlights = getVisibleHighlights(myStartOffset, myEndOffset, myProject, myEditor);
|
||||
|
||||
int caretOffset = myEditor.getCaretModel().getOffset();
|
||||
@@ -89,10 +91,9 @@ public class ShowAutoImportPass extends TextEditorHighlightingPass {
|
||||
if (info.startOffset <= caretOffset && showAddImportHint(info)) return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < visibleHighlights.size(); i++) {
|
||||
for (HighlightInfo visibleHighlight : visibleHighlights) {
|
||||
ProgressManager.checkCanceled();
|
||||
HighlightInfo info = visibleHighlights.get(i);
|
||||
if (info.startOffset > caretOffset && showAddImportHint(info)) return;
|
||||
if (visibleHighlight.startOffset > caretOffset && showAddImportHint(visibleHighlight)) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -40,10 +40,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class ShowIntentionsPassFactory extends AbstractProjectComponent implements TextEditorHighlightingPassFactory {
|
||||
public ShowIntentionsPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) {
|
||||
super(project);
|
||||
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{
|
||||
Pass.UPDATE_VISIBLE,
|
||||
Pass.UPDATE_ALL,
|
||||
}, null, false, Pass.POPUP_HINTS);
|
||||
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL,}, null, false, Pass.POPUP_HINTS);
|
||||
}
|
||||
|
||||
@NonNls
|
||||
|
||||
@@ -331,7 +331,7 @@ public abstract class UsefulTestCase extends TestCase {
|
||||
public static void assertEmpty(final Object[] array) {
|
||||
assertOrderedEquals(array);
|
||||
}
|
||||
|
||||
|
||||
public static void assertEmpty(final Collection<?> collection) {
|
||||
assertEmpty(null, collection);
|
||||
}
|
||||
|
||||
+12
-12
@@ -47,7 +47,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
private final VcsGuess myGuess;
|
||||
private final SynchronizedLife myLife;
|
||||
|
||||
private MyProgressHolder myProgressHolder;
|
||||
private final MyProgressHolder myProgressHolder;
|
||||
|
||||
public VcsDirtyScopeManagerImpl(Project project, ChangeListManager changeListManager, ProjectLevelVcsManager vcsManager) {
|
||||
myProject = project;
|
||||
@@ -104,7 +104,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
}
|
||||
});
|
||||
|
||||
if (lifeDrop.isDone() && (! lifeDrop.isSuspened())) {
|
||||
if (lifeDrop.isDone() && !lifeDrop.isSuspened()) {
|
||||
myChangeListManager.scheduleUpdate();
|
||||
}
|
||||
}
|
||||
@@ -153,8 +153,8 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
convertPaths(dirsRecursivelyDirty, dirsConverted);
|
||||
}
|
||||
});
|
||||
final boolean haveStuff = ((filesConverted != null) && (! filesConverted.isEmpty())) ||
|
||||
((dirsConverted != null) && (! dirsConverted.isEmpty()));
|
||||
final boolean haveStuff = filesConverted != null && ! filesConverted.isEmpty()
|
||||
|| dirsConverted != null && ! dirsConverted.isEmpty();
|
||||
if (! haveStuff) return false;
|
||||
|
||||
return takeDirt(new Consumer<DirtBuilder>() {
|
||||
@@ -183,11 +183,11 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
};
|
||||
final LifeDrop lifeDrop = myLife.doIfAlive(runnable);
|
||||
|
||||
if (lifeDrop.isDone() && (! lifeDrop.isSuspened()) && (Boolean.TRUE.equals(wasNotEmptyRef.get()))) {
|
||||
if (lifeDrop.isDone() && !lifeDrop.isSuspened() && Boolean.TRUE.equals(wasNotEmptyRef.get())) {
|
||||
myChangeListManager.scheduleUpdate();
|
||||
}
|
||||
// no sense in checking correct here any more: vcs is searched for asynchronously
|
||||
return (! lifeDrop.isDone());
|
||||
return !lifeDrop.isDone();
|
||||
}
|
||||
|
||||
private void convert(@Nullable final Collection<VirtualFile> from, final Collection<VcsRoot> to) {
|
||||
@@ -211,8 +211,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
convert(dirsRecursivelyDirty, dirsConverted);
|
||||
}
|
||||
});
|
||||
final boolean haveStuff = ((filesConverted != null) && (! filesConverted.isEmpty())) ||
|
||||
((dirsConverted != null) && (! dirsConverted.isEmpty()));
|
||||
final boolean haveStuff = filesConverted != null && ! filesConverted.isEmpty() || dirsConverted != null && ! dirsConverted.isEmpty();
|
||||
if (! haveStuff) return false;
|
||||
|
||||
return takeDirt(new Consumer<DirtBuilder>() {
|
||||
@@ -369,10 +368,11 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
currentHolderRef.set(new MyProgressHolder(new DirtBuilder(myDirtBuilder), null));
|
||||
}
|
||||
});
|
||||
final VcsInvalidated inProgressInvalidated = inProgressHolderRef.get().calculateInvalidated();
|
||||
final VcsInvalidated currentInvalidated = currentHolderRef.get().calculateInvalidated();
|
||||
final VcsInvalidated inProgressInvalidated = inProgressHolderRef.get() == null ? null : inProgressHolderRef.get().calculateInvalidated();
|
||||
final VcsInvalidated currentInvalidated = currentHolderRef.get() == null ? null : currentHolderRef.get().calculateInvalidated();
|
||||
for (FilePath fp : files) {
|
||||
if (inProgressInvalidated != null && inProgressInvalidated.isFileDirty(fp) || currentInvalidated.isFileDirty(fp)) {
|
||||
if (inProgressInvalidated != null && inProgressInvalidated.isFileDirty(fp)
|
||||
|| currentInvalidated != null && currentInvalidated.isFileDirty(fp)) {
|
||||
result.add(fp);
|
||||
}
|
||||
}
|
||||
@@ -457,7 +457,7 @@ public class VcsDirtyScopeManagerImpl extends VcsDirtyScopeManager implements Pr
|
||||
public LifeDrop doIfAliveAndNotSuspended(final Runnable runnable) {
|
||||
synchronized (myLock) {
|
||||
synchronized (myLock) {
|
||||
if (LifeStages.ALIVE.equals(myStage) && (! mySuspended)) {
|
||||
if (LifeStages.ALIVE.equals(myStage) && ! mySuspended) {
|
||||
runnable.run();
|
||||
return new LifeDrop(true, mySuspended);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user