mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
don't schedule EDT activity if editor notification provider is not applicable
GitOrigin-RevId: b117f5f780e5bc2a011451af37e768aa133acc1e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3bcda88d84
commit
cd70ce6049
+10
-10
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.ui;
|
||||
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
@@ -44,14 +44,14 @@ public final class AlternativeSourceNotificationProvider implements EditorNotifi
|
||||
private static final Key<Boolean> FILE_PROCESSED_KEY = Key.create("AlternativeSourceCheckDone");
|
||||
|
||||
@Override
|
||||
public @NotNull Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
public @Nullable Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file) {
|
||||
if (!DebuggerSettings.getInstance().SHOW_ALTERNATIVE_SOURCE) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (DumbService.getInstance(project).isDumb()) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
DebuggerSession javaSession = DebuggerManagerEx.getInstanceEx(project).getContext().getDebuggerSession();
|
||||
@@ -59,29 +59,29 @@ public final class AlternativeSourceNotificationProvider implements EditorNotifi
|
||||
|
||||
if (session == null) {
|
||||
setFileProcessed(file, false);
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
XSourcePosition position = session.getCurrentPosition();
|
||||
if (position == null || !file.equals(position.getFile())) {
|
||||
setFileProcessed(file, false);
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
if (!(psiFile instanceof PsiJavaFile)) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiClass[] classes = ((PsiJavaFile)psiFile).getClasses();
|
||||
if (classes.length == 0) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiClass baseClass = classes[0];
|
||||
String name = baseClass.getQualifiedName();
|
||||
if (name == null) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiClass[] altClasses = JavaPsiFacade.getInstance(project).findClasses(name, javaSession.getSearchScope());
|
||||
@@ -94,7 +94,7 @@ public final class AlternativeSourceNotificationProvider implements EditorNotifi
|
||||
setFileProcessed(file, true);
|
||||
|
||||
if (alts.size() <= 1) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
for (PsiClass cls : alts) {
|
||||
|
||||
@@ -187,12 +187,12 @@ public final class SnippetEditorDecorator implements EditorNotificationProvider
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
public @Nullable Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file) {
|
||||
if (ScratchFileService.findRootType(file) instanceof JShellRootType) {
|
||||
return editor -> new ConfigurationPane(project, file, editor);
|
||||
}
|
||||
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -80,10 +80,10 @@ final class AttachSourcesNotificationProvider implements EditorNotificationProvi
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
public @Nullable Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file) {
|
||||
if (!FileTypeRegistry.getInstance().isFileOfType(file, JavaClassFileType.INSTANCE)) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
String classFileInfo = getTextWithClassFileInfo(file);
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl
|
||||
|
||||
import com.intellij.diff.DiffContentFactory
|
||||
@@ -38,7 +38,7 @@ class LibrarySourceNotificationProvider : EditorNotificationProvider {
|
||||
override fun collectNotificationData(
|
||||
project: Project,
|
||||
file: VirtualFile,
|
||||
): Function<in FileEditor, out JComponent?> {
|
||||
): Function<in FileEditor, out JComponent?>? {
|
||||
if (file.fileType is LanguageFileType && ProjectRootManager.getInstance(project).fileIndex.isInLibrarySource(file)) {
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file)
|
||||
if (psiFile is PsiJavaFile) {
|
||||
@@ -69,7 +69,7 @@ class LibrarySourceNotificationProvider : EditorNotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
return EditorNotificationProvider.CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
private fun differs(src: PsiClass): Boolean {
|
||||
|
||||
+11
-8
@@ -17,11 +17,12 @@ import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import com.intellij.ui.EditorNotifications;
|
||||
import com.intellij.ui.EditorNotificationsImpl;
|
||||
import com.intellij.util.ui.EDT;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -59,20 +60,22 @@ public abstract class SdkSetupNotificationTestBase extends JavaCodeInsightFixtur
|
||||
@NotNull String fileName,
|
||||
@NotNull String fileText) {
|
||||
FileEditor editor = openTextInEditor(fixture, fileName, fileText);
|
||||
return (EditorNotificationPanel)EditorNotificationsImpl.getNotificationPanels(editor).get(SdkSetupNotificationProvider.class);
|
||||
EditorNotificationsImpl editorNotifications = (EditorNotificationsImpl)EditorNotifications.getInstance(fixture.getProject());
|
||||
return (EditorNotificationPanel)(editorNotifications.getNotificationPanels(editor).get(SdkSetupNotificationProvider.class));
|
||||
}
|
||||
|
||||
static @NotNull FileEditor openTextInEditor(@NotNull JavaCodeInsightTestFixture fixture,
|
||||
@NotNull String fileName,
|
||||
@NotNull String fileText) {
|
||||
EDT.dispatchAllInvocationEvents();
|
||||
EditorNotificationsImpl.completeAsyncTasks(fixture.getProject());
|
||||
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue();
|
||||
EditorNotificationsImpl editorNotifications = (EditorNotificationsImpl)EditorNotifications.getInstance(fixture.getProject());
|
||||
editorNotifications.completeAsyncTasks();
|
||||
|
||||
final PsiFile psiFile = fixture.configureByText(fileName, fileText);
|
||||
PsiFile psiFile = fixture.configureByText(fileName, fileText);
|
||||
FileEditorManager fileEditorManager = FileEditorManager.getInstance(fixture.getProject());
|
||||
VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
|
||||
final FileEditor[] editors = fileEditorManager.openFile(virtualFile, true);
|
||||
FileEditor[] editors = fileEditorManager.openFile(virtualFile, true);
|
||||
Disposer.register(fixture.getTestRootDisposable(), new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
@@ -81,8 +84,8 @@ public abstract class SdkSetupNotificationTestBase extends JavaCodeInsightFixtur
|
||||
});
|
||||
assertThat(editors).hasSize(1);
|
||||
|
||||
EDT.dispatchAllInvocationEvents();
|
||||
EditorNotificationsImpl.completeAsyncTasks(fixture.getProject());
|
||||
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue();
|
||||
editorNotifications.completeAsyncTasks();
|
||||
|
||||
return editors[0];
|
||||
}
|
||||
|
||||
+7
-7
@@ -67,21 +67,23 @@ public class UnknownSdkTrackerTest extends JavaCodeInsightFixtureTestCase {
|
||||
public void testMissingModuleJdk() {
|
||||
setModuleSdk("missingSDK", JavaSdk.getInstance());
|
||||
|
||||
final List<String> fixes = detectMissingSdks();
|
||||
List<String> fixes = detectMissingSdks();
|
||||
assertThat(fixes)
|
||||
.withFailMessage(String.valueOf(fixes))
|
||||
.hasSize(1)
|
||||
.first().asString().startsWith("SdkFixInfo:");
|
||||
.first().asString().matches(s -> s.startsWith("SdkFixInfo:") || s.startsWith("SdkSetupNotification:"));
|
||||
}
|
||||
|
||||
public void testMissingModuleUnknownSdk() {
|
||||
setModuleSdk("missingSDK", "foo-bar-baz");
|
||||
|
||||
final List<String> fixes = detectMissingSdks();
|
||||
List<String> fixes = detectMissingSdks();
|
||||
assertThat(fixes)
|
||||
.withFailMessage(String.valueOf(fixes))
|
||||
.hasSize(1)
|
||||
.first().asString().startsWith("SdkSetupNotification:");
|
||||
.first()
|
||||
.asString()
|
||||
.startsWith("SdkSetupNotification:");
|
||||
}
|
||||
|
||||
public void testNoProjectSdk() {
|
||||
@@ -106,7 +108,6 @@ public class UnknownSdkTrackerTest extends JavaCodeInsightFixtureTestCase {
|
||||
|
||||
public void testNoModuleSdk() {
|
||||
ModuleRootModificationUtil.setModuleSdk(getModule(), null);
|
||||
|
||||
final List<String> fixes = detectMissingSdks();
|
||||
assertThat(fixes)
|
||||
.withFailMessage(String.valueOf(fixes))
|
||||
@@ -156,7 +157,6 @@ public class UnknownSdkTrackerTest extends JavaCodeInsightFixtureTestCase {
|
||||
assertThat(lookupCalls).hasValue(2);
|
||||
}
|
||||
|
||||
|
||||
@TestFor(issues = "IDEA-237884")
|
||||
public void testShouldNotRantOnCustomSDKType() {
|
||||
final Sdk broken = ProjectJdkTable.getInstance().createSdk("broken-sdk-123", SimpleJavaSdkType.getInstance());
|
||||
@@ -267,7 +267,7 @@ public class UnknownSdkTrackerTest extends JavaCodeInsightFixtureTestCase {
|
||||
private @NotNull List<String> detectMissingSdks() {
|
||||
UnknownSdkTracker.getInstance(getProject()).updateUnknownSdks();
|
||||
|
||||
ArrayList<String> infos = new ArrayList<>();
|
||||
List<String> infos = new ArrayList<>();
|
||||
EditorNotificationPanel sdkNotification =
|
||||
SdkSetupNotificationTestBase.runOnText(myFixture, "Sample.java", "class Sample { java.lang.String foo; }");
|
||||
if (sdkNotification != null) {
|
||||
|
||||
+30
-28
@@ -1,41 +1,43 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.execution.impl
|
||||
|
||||
import com.intellij.execution.ExecutionBundle
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectFileIndex
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotifications
|
||||
import com.intellij.ui.EditorNotificationProvider
|
||||
import java.util.function.Function
|
||||
import javax.swing.JComponent
|
||||
|
||||
class RunConfigEditorNotificationProvider : EditorNotifications.Provider<EditorNotificationPanel>() {
|
||||
private val KEY: Key<EditorNotificationPanel> = Key.create("RunConfigEditorNotificationProvider")
|
||||
|
||||
override fun getKey(): Key<EditorNotificationPanel> = KEY
|
||||
|
||||
override fun createNotificationPanel(file: VirtualFile, fileEditor: FileEditor, project: Project): EditorNotificationPanel? {
|
||||
if (!file.name.endsWith(".run.xml")) return null
|
||||
if (!ProjectFileIndex.getInstance(project).isInContent(file)) return null
|
||||
|
||||
val runManager = RunManagerImpl.getInstanceImpl(project)
|
||||
if (!runManager.isFileContainsRunConfiguration(file)) return null
|
||||
|
||||
val panel = EditorNotificationPanel(fileEditor, EditorNotificationPanel.Status.Warning)
|
||||
panel.text = ExecutionBundle.message("manual.editing.of.config.file.not.recommended")
|
||||
@Suppress("DialogTitleCapitalization") val message = ExecutionBundle.message("open.run.debug.dialog")
|
||||
panel.createActionLabel(message) {
|
||||
val oldSelectedConfig = runManager.selectedConfiguration
|
||||
|
||||
runManager.selectConfigurationStoredInFile(file)
|
||||
val ok = EditConfigurationsDialog(project).showAndGet()
|
||||
|
||||
if (!ok) {
|
||||
runManager.selectedConfiguration = oldSelectedConfig
|
||||
}
|
||||
private class RunConfigEditorNotificationProvider : EditorNotificationProvider {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (!file.nameSequence.endsWith(".run.xml") || !ProjectFileIndex.getInstance(project).isInContent(file)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return panel
|
||||
val runManager = RunManagerImpl.getInstanceImpl(project)
|
||||
if (!runManager.isFileContainsRunConfiguration(file)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return Function { fileEditor ->
|
||||
val panel = EditorNotificationPanel(fileEditor, EditorNotificationPanel.Status.Warning)
|
||||
panel.text = ExecutionBundle.message("manual.editing.of.config.file.not.recommended")
|
||||
@Suppress("DialogTitleCapitalization") val message = ExecutionBundle.message("open.run.debug.dialog")
|
||||
panel.createActionLabel(message) {
|
||||
val oldSelectedConfig = runManager.selectedConfiguration
|
||||
|
||||
runManager.selectConfigurationStoredInFile(file)
|
||||
val ok = EditConfigurationsDialog(project).showAndGet()
|
||||
|
||||
if (!ok) {
|
||||
runManager.selectedConfiguration = oldSelectedConfig
|
||||
}
|
||||
}
|
||||
|
||||
panel
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-11
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeInsight.daemon.ProjectSdkSetupValidator;
|
||||
@@ -22,26 +22,22 @@ import java.util.function.Function;
|
||||
/**
|
||||
* @author Danila Ponomarenko
|
||||
*/
|
||||
public final class SdkSetupNotificationProvider implements EditorNotificationProvider,
|
||||
DumbAware {
|
||||
|
||||
public final class SdkSetupNotificationProvider implements EditorNotificationProvider, DumbAware {
|
||||
@Override
|
||||
public @NotNull Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file) {
|
||||
public @Nullable Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file) {
|
||||
if (!UnknownSdkEditorNotification.getInstance(project).allowProjectSdkNotifications()) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
for (ProjectSdkSetupValidator validator : ProjectSdkSetupValidator.EP_NAME.getExtensionList()) {
|
||||
if (validator.isApplicableFor(project, file)) {
|
||||
String errorMessage = validator.getErrorMessage(project, file);
|
||||
return errorMessage != null ?
|
||||
fileEditor -> createPanel(errorMessage, fileEditor, validator.getFixHandler(project, file)) :
|
||||
CONST_NULL;
|
||||
return errorMessage == null ? null : fileEditor -> createPanel(errorMessage, fileEditor, validator.getFixHandler(project, file));
|
||||
}
|
||||
}
|
||||
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
|
||||
@@ -22,13 +22,16 @@ import java.util.function.Function;
|
||||
* </p>
|
||||
*/
|
||||
public interface EditorNotificationProvider {
|
||||
|
||||
ProjectExtensionPointName<EditorNotificationProvider> EP_NAME =
|
||||
new ProjectExtensionPointName<>("com.intellij.editorNotificationProvider");
|
||||
|
||||
/**
|
||||
* @deprecated Use {@code null}.
|
||||
*/
|
||||
@Deprecated
|
||||
Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> CONST_NULL = __ -> null;
|
||||
|
||||
@RequiresReadLock
|
||||
@NotNull Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file);
|
||||
@Nullable Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file);
|
||||
}
|
||||
|
||||
+2
-2
@@ -34,7 +34,7 @@ class PluginAdvertiserEditorNotificationProvider : EditorNotificationProvider,
|
||||
override fun collectNotificationData(
|
||||
project: Project,
|
||||
file: VirtualFile,
|
||||
): Function<in FileEditor, out JComponent?> {
|
||||
): Function<in FileEditor, out JComponent?>? {
|
||||
val suggestionData = getSuggestionData(project, ApplicationInfo.getInstance().build.productCode, file.name, file.fileType)
|
||||
|
||||
if (suggestionData == null) {
|
||||
@@ -58,7 +58,7 @@ class PluginAdvertiserEditorNotificationProvider : EditorNotificationProvider,
|
||||
LOG.debug("Tried to update extensions cache for file '${file.name}'. shouldUpdateNotifications=$shouldUpdateNotifications")
|
||||
}
|
||||
|
||||
return EditorNotificationProvider.CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
return suggestionData
|
||||
|
||||
@@ -6,8 +6,8 @@ package com.intellij.ui
|
||||
import com.intellij.ProjectTopics
|
||||
import com.intellij.diagnostic.PluginException
|
||||
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.*
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.extensions.ExtensionPointListener
|
||||
import com.intellij.openapi.extensions.PluginDescriptor
|
||||
@@ -26,11 +26,11 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.refactoring.listeners.RefactoringElementAdapter
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListenerProvider
|
||||
import com.intellij.util.SingleAlarm
|
||||
import com.intellij.util.childScope
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt
|
||||
import com.intellij.util.containers.CollectionFactory
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue
|
||||
import com.intellij.util.ui.update.Update
|
||||
import kotlinx.coroutines.*
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
@@ -39,10 +39,14 @@ import java.util.concurrent.CancellationException
|
||||
import java.util.function.BiFunction
|
||||
import javax.swing.JComponent
|
||||
|
||||
class EditorNotificationsImpl(private val project: Project) : EditorNotifications() {
|
||||
private val updateMerger = MergingUpdateQueue("EditorNotifications update merger", 100, true, null, project).usePassThroughInUnitTestMode()
|
||||
class EditorNotificationsImpl(private val project: Project) : EditorNotifications(), Disposable {
|
||||
private val updateAllAlarm = SingleAlarm(::doUpdateAllNotifications, 100, this)
|
||||
|
||||
private val fileToUpdateNotificationJob = CollectionFactory.createConcurrentWeakMap<VirtualFile, Job>()
|
||||
private val fileEditorToMap =
|
||||
CollectionFactory.createConcurrentWeakMap<FileEditor, MutableMap<Class<out EditorNotificationProvider>, JComponent>>()
|
||||
|
||||
private val coroutineScope: CoroutineScope = project.coroutineScope.childScope()
|
||||
|
||||
init {
|
||||
val connection = project.messageBus.connect()
|
||||
@@ -52,11 +56,11 @@ class EditorNotificationsImpl(private val project: Project) : EditorNotificatio
|
||||
}
|
||||
|
||||
override fun selectionChanged(event: FileEditorManagerEvent) {
|
||||
val file = event.newFile
|
||||
val editor = event.newEditor
|
||||
if (file != null && editor != null && java.lang.Boolean.TRUE == editor.getUserData(PENDING_UPDATE)) {
|
||||
val file = event.newFile ?: return
|
||||
val editor = event.newEditor ?: return
|
||||
if (editor.getUserData(PENDING_UPDATE) == java.lang.Boolean.TRUE) {
|
||||
editor.putUserData(PENDING_UPDATE, null)
|
||||
updateEditor(file, editor)
|
||||
updateEditors(file, listOf(editor))
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -87,142 +91,139 @@ class EditorNotificationsImpl(private val project: Project) : EditorNotificatio
|
||||
}, false, null)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
coroutineScope.cancel()
|
||||
// help GC
|
||||
fileToUpdateNotificationJob.clear()
|
||||
fileEditorToMap.clear()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val EDITOR_NOTIFICATION_PROVIDER =
|
||||
Key.create<MutableMap<Class<out EditorNotificationProvider>, JComponent?>>("editor.notification.provider")
|
||||
|
||||
private val PENDING_UPDATE = Key.create<Boolean>("pending.notification.update")
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@JvmStatic
|
||||
fun getNotificationPanels(editor: FileEditor): MutableMap<Class<out EditorNotificationProvider>, JComponent?> {
|
||||
editor.getUserData(EDITOR_NOTIFICATION_PROVIDER)?.let {
|
||||
return it
|
||||
}
|
||||
@VisibleForTesting
|
||||
fun getNotificationPanels(fileEditor: FileEditor): MutableMap<Class<out EditorNotificationProvider>, JComponent> {
|
||||
return fileEditorToMap.computeIfAbsent(fileEditor) { WeakHashMap() }
|
||||
}
|
||||
|
||||
editor.putUserData(EDITOR_NOTIFICATION_PROVIDER, WeakHashMap())
|
||||
editor.getUserData(EDITOR_NOTIFICATION_PROVIDER)?.let {
|
||||
return it
|
||||
}
|
||||
val editorClass = editor.javaClass
|
||||
val pluginException = PluginException.createByClass(
|
||||
"User data is not supported; editorClass='${editorClass.name}'; key='$EDITOR_NOTIFICATION_PROVIDER'",
|
||||
null,
|
||||
editorClass)
|
||||
Logger.getInstance(editorClass).error(pluginException)
|
||||
throw pluginException
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@JvmStatic
|
||||
fun completeAsyncTasks(project: Project) {
|
||||
runUnderModalProgressIfIsEdt {
|
||||
@TestOnly
|
||||
fun completeAsyncTasks() {
|
||||
runUnderModalProgressIfIsEdt {
|
||||
val parentJob = coroutineScope.coroutineContext[Job]!!
|
||||
while (true) {
|
||||
// process all events in EDT
|
||||
withContext(Dispatchers.EDT) {
|
||||
yield()
|
||||
}
|
||||
|
||||
val editorNotificationManager = getInstance(project) as EditorNotificationsImpl
|
||||
for (job in editorNotificationManager.fileToUpdateNotificationJob.values.toList()) {
|
||||
try {
|
||||
job.join()
|
||||
}
|
||||
catch (ignore: CancellationException) {
|
||||
}
|
||||
val jobs = parentJob.children.toList()
|
||||
if (jobs.isEmpty()) {
|
||||
break
|
||||
}
|
||||
|
||||
jobs.joinAll()
|
||||
|
||||
// process all events in EDT
|
||||
withContext(Dispatchers.EDT) {
|
||||
yield()
|
||||
}
|
||||
}
|
||||
}
|
||||
check(fileToUpdateNotificationJob.isEmpty())
|
||||
}
|
||||
|
||||
override fun updateNotifications(provider: EditorNotificationProvider) {
|
||||
for (file in FileEditorManager.getInstance(project).openFilesWithRemotes) {
|
||||
for (editor in getEditors(file)) {
|
||||
updateNotification(editor, provider, null)
|
||||
for (editor in getEditors(file).toList()) {
|
||||
updateNotification(fileEditor = editor, provider = provider, component = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateNotifications(file: VirtualFile) {
|
||||
AppUIExecutor
|
||||
.onUiThread(ModalityState.any())
|
||||
.expireWith(project)
|
||||
.execute {
|
||||
if (project.isDisposed || !file.isValid) {
|
||||
return@execute
|
||||
}
|
||||
var editors = getEditors(file)
|
||||
if (!ApplicationManager.getApplication().isHeadlessEnvironment) {
|
||||
editors = editors.filter { fileEditor ->
|
||||
val visible = UIUtil.isShowing(fileEditor.component)
|
||||
if (!visible) {
|
||||
fileEditor.putUserData(PENDING_UPDATE, java.lang.Boolean.TRUE)
|
||||
}
|
||||
visible
|
||||
}
|
||||
}
|
||||
for (editor in editors) {
|
||||
updateEditor(file, editor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEditors(file: VirtualFile): List<FileEditor> {
|
||||
return FileEditorManager.getInstance(project).getAllEditors(file).filter { it !is TextEditor || isEditorLoaded(it.editor) }
|
||||
}
|
||||
|
||||
private fun updateEditor(file: VirtualFile, fileEditor: FileEditor) {
|
||||
// light project is not disposed in tests
|
||||
if (project.isDisposed) {
|
||||
return
|
||||
}
|
||||
|
||||
val job = project.coroutineScope.launch(start = CoroutineStart.LAZY) {
|
||||
coroutineScope.launch(Dispatchers.EDT + ModalityState.any().asContextElement()) {
|
||||
if (!file.isValid) {
|
||||
return@launch
|
||||
}
|
||||
|
||||
doUpdateNotifications(file)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
private fun doUpdateNotifications(file: VirtualFile) {
|
||||
var editors = getEditors(file)
|
||||
if (!ApplicationManager.getApplication().isHeadlessEnvironment) {
|
||||
editors = editors.filter { fileEditor ->
|
||||
val visible = UIUtil.isShowing(fileEditor.component)
|
||||
if (!visible) {
|
||||
fileEditor.putUserData(PENDING_UPDATE, java.lang.Boolean.TRUE)
|
||||
}
|
||||
visible
|
||||
}
|
||||
}
|
||||
updateEditors(file, editors.toList())
|
||||
}
|
||||
|
||||
private fun getEditors(file: VirtualFile): Sequence<FileEditor> {
|
||||
return FileEditorManager.getInstance(project).getAllEditors(file).asSequence().filter { it !is TextEditor || isEditorLoaded(it.editor) }
|
||||
}
|
||||
|
||||
private fun updateEditors(file: VirtualFile, fileEditors: List<FileEditor>) {
|
||||
val job = coroutineScope.launch(start = CoroutineStart.LAZY) {
|
||||
// delay for debounce
|
||||
delay(100)
|
||||
|
||||
if (!file.isValid) {
|
||||
return@launch
|
||||
}
|
||||
|
||||
// light project is not disposed in tests
|
||||
if (project.isDisposed) {
|
||||
return@launch
|
||||
}
|
||||
|
||||
coroutineContext.ensureActive()
|
||||
try {
|
||||
val point = EditorNotificationProvider.EP_NAME.getPoint(project) as ExtensionPointImpl<EditorNotificationProvider>
|
||||
for (adapter in point.sortedAdapters) {
|
||||
val point = EditorNotificationProvider.EP_NAME.getPoint(project) as ExtensionPointImpl<EditorNotificationProvider>
|
||||
for (adapter in point.sortedAdapters) {
|
||||
coroutineContext.ensureActive()
|
||||
|
||||
try {
|
||||
val provider = adapter.createInstance<EditorNotificationProvider>(project) ?: continue
|
||||
|
||||
coroutineContext.ensureActive()
|
||||
|
||||
try {
|
||||
val provider = adapter.createInstance<EditorNotificationProvider>(project) ?: continue
|
||||
if (DumbService.isDumb(project) && !DumbService.isDumbAware(provider)) {
|
||||
continue
|
||||
}
|
||||
|
||||
coroutineContext.ensureActive()
|
||||
|
||||
if (DumbService.isDumb(project) && !DumbService.isDumbAware(provider)) {
|
||||
continue
|
||||
val componentProvider = readAction {
|
||||
if (file.isValid) {
|
||||
provider.collectNotificationData(project, file)
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
} ?: continue
|
||||
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
|
||||
if (!file.isValid) {
|
||||
return@withContext
|
||||
}
|
||||
|
||||
val componentProvider = readAction {
|
||||
if (file.isValid) {
|
||||
provider.collectNotificationData(project, file)
|
||||
}
|
||||
else {
|
||||
null
|
||||
}
|
||||
} ?: continue
|
||||
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
|
||||
for (fileEditor in fileEditors) {
|
||||
val component = componentProvider.apply(fileEditor)
|
||||
updateNotification(fileEditor, provider, component)
|
||||
updateNotification(fileEditor = fileEditor, provider = provider, component = component)
|
||||
}
|
||||
}
|
||||
catch (e: CancellationException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: Exception) {
|
||||
val pluginException = if (e is PluginException) e else PluginException(e, adapter.pluginDescriptor.pluginId)
|
||||
logger<EditorNotificationsImpl>().error(pluginException)
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
fileToUpdateNotificationJob.remove(file, coroutineContext.job)
|
||||
catch (e: CancellationException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: Exception) {
|
||||
val pluginException = if (e is PluginException) e else PluginException(e, adapter.pluginDescriptor.pluginId)
|
||||
logger<EditorNotificationsImpl>().error(pluginException)
|
||||
}
|
||||
}
|
||||
}
|
||||
job.invokeOnCompletion { fileToUpdateNotificationJob.remove(file, job) }
|
||||
@@ -235,11 +236,11 @@ class EditorNotificationsImpl(private val project: Project) : EditorNotificatio
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
private fun updateNotification(editor: FileEditor, provider: EditorNotificationProvider, component: JComponent?) {
|
||||
val panels = getNotificationPanels(editor)
|
||||
private fun updateNotification(fileEditor: FileEditor, provider: EditorNotificationProvider, component: JComponent?) {
|
||||
val panels = fileEditorToMap.get(fileEditor)
|
||||
val providerClass = provider.javaClass
|
||||
panels.get(providerClass)?.let { old ->
|
||||
FileEditorManager.getInstance(project).removeTopComponent(editor, old)
|
||||
panels?.get(providerClass)?.let { old ->
|
||||
FileEditorManager.getInstance(project).removeTopComponent(fileEditor, old)
|
||||
}
|
||||
if (component != null) {
|
||||
if (component is EditorNotificationPanel) {
|
||||
@@ -248,9 +249,13 @@ class EditorNotificationsImpl(private val project: Project) : EditorNotificatio
|
||||
}
|
||||
}
|
||||
logNotificationShown(project, provider)
|
||||
FileEditorManager.getInstance(project).addTopComponent(editor, component)
|
||||
FileEditorManager.getInstance(project).addTopComponent(fileEditor, component)
|
||||
|
||||
(panels ?: getNotificationPanels(fileEditor)).put(providerClass, component)
|
||||
}
|
||||
else {
|
||||
panels?.remove(providerClass)
|
||||
}
|
||||
panels.put(providerClass, component)
|
||||
}
|
||||
|
||||
override fun updateAllNotifications() {
|
||||
@@ -258,14 +263,20 @@ class EditorNotificationsImpl(private val project: Project) : EditorNotificatio
|
||||
throw UnsupportedOperationException("Editor notifications aren't supported for default project")
|
||||
}
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||
doUpdateAllNotifications()
|
||||
}
|
||||
else {
|
||||
updateAllAlarm.cancelAndRequest()
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
private fun doUpdateAllNotifications() {
|
||||
val fileEditorManager = FileEditorManager.getInstance(project) ?: throw IllegalStateException("No FileEditorManager for $project")
|
||||
updateMerger.queue(object : Update("update") {
|
||||
override fun run() {
|
||||
for (file in fileEditorManager.openFilesWithRemotes) {
|
||||
updateNotifications(file)
|
||||
}
|
||||
}
|
||||
})
|
||||
for (file in fileEditorManager.openFilesWithRemotes) {
|
||||
doUpdateNotifications(file)
|
||||
}
|
||||
}
|
||||
|
||||
internal class RefactoringListenerProvider : RefactoringElementListenerProvider {
|
||||
@@ -277,10 +288,8 @@ class EditorNotificationsImpl(private val project: Project) : EditorNotificatio
|
||||
return object : RefactoringElementAdapter() {
|
||||
override fun elementRenamedOrMoved(newElement: PsiElement) {
|
||||
if (newElement is PsiFile) {
|
||||
val vFile = newElement.getContainingFile().virtualFile
|
||||
if (vFile != null) {
|
||||
getInstance(element.getProject()).updateNotifications(vFile)
|
||||
}
|
||||
val vFile = newElement.getContainingFile().virtualFile ?: return
|
||||
getInstance(element.getProject()).updateNotifications(vFile)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-7
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.editorconfig.configmanagement.editor;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
@@ -20,14 +20,12 @@ import javax.swing.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
final class EditorConfigEditorNotificationProvider implements EditorNotificationProvider {
|
||||
|
||||
@Override
|
||||
public @NotNull Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
public @Nullable Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file) {
|
||||
return file.getFileType().equals(EditorConfigFileType.INSTANCE) &&
|
||||
!getEditorConfigSettings(project).ENABLED ?
|
||||
fileEditor -> new MyPanel(fileEditor, project) :
|
||||
CONST_NULL;
|
||||
return file.getFileType().equals(EditorConfigFileType.INSTANCE) && !getEditorConfigSettings(project).ENABLED
|
||||
? fileEditor -> new MyPanel(fileEditor, project)
|
||||
: null;
|
||||
}
|
||||
|
||||
private static final class MyPanel extends EditorNotificationPanel {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package git4idea.ui
|
||||
|
||||
import com.intellij.codeInsight.hint.HintUtil
|
||||
@@ -11,46 +11,46 @@ import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.help.HelpManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.popup.IconButton
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotificationProvider
|
||||
import com.intellij.ui.EditorNotifications
|
||||
import com.intellij.ui.InplaceButton
|
||||
import git4idea.i18n.GitBundle
|
||||
import git4idea.repo.GitRepositoryFiles
|
||||
import git4idea.repo.GitRepositoryManager
|
||||
import java.awt.BorderLayout
|
||||
import java.util.function.Function
|
||||
import javax.swing.JComponent
|
||||
|
||||
private val KEY: Key<EditorNotificationPanel> = Key.create("GitEditorPromo")
|
||||
private const val PROMO_DISMISSED_KEY = "git.editor.promo.dismissed"
|
||||
|
||||
class GitEditorPromo : EditorNotifications.Provider<EditorNotificationPanel>() {
|
||||
override fun getKey(): Key<EditorNotificationPanel> = KEY
|
||||
private class GitEditorPromo : EditorNotificationProvider {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (!isEnabled() || !CommandLineWaitingManager.getInstance().hasHookFor(file) || file.name != GitRepositoryFiles.COMMIT_EDITMSG) {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun createNotificationPanel(file: VirtualFile,
|
||||
fileEditor: FileEditor,
|
||||
project: Project): EditorNotificationPanel? {
|
||||
return if (isEnabled() && CommandLineWaitingManager.getInstance().hasHookFor(file)
|
||||
&& file.name == GitRepositoryFiles.COMMIT_EDITMSG) {
|
||||
EditorNotificationPanel(HintUtil.PROMOTION_PANE_KEY, EditorNotificationPanel.Status.Info).apply {
|
||||
icon(AllIcons.Ide.Gift)
|
||||
text = GitBundle.message("editor.promo.commit.text", ApplicationNamesInfo.getInstance().fullProductName)
|
||||
val repository = GitRepositoryManager.getInstance(project).repositories.find { it.repositoryFiles.isCommitMessageFile(file.path) }
|
||||
if (repository != null) {
|
||||
createActionLabel(GitBundle.message("editor.promo.commit.try.link"), IdeActions.ACTION_CHECKIN_PROJECT, false)
|
||||
return Function {
|
||||
val panel = EditorNotificationPanel(HintUtil.PROMOTION_PANE_KEY, EditorNotificationPanel.Status.Info)
|
||||
panel.icon(AllIcons.Ide.Gift)
|
||||
panel.text = GitBundle.message("editor.promo.commit.text", ApplicationNamesInfo.getInstance().fullProductName)
|
||||
val repository = GitRepositoryManager.getInstance(project).repositories.find { it.repositoryFiles.isCommitMessageFile(file.path) }
|
||||
if (repository == null) {
|
||||
panel.createActionLabel(GitBundle.message("editor.promo.help.link")) {
|
||||
HelpManager.getInstance().invokeHelp("Commit and push changes")
|
||||
}
|
||||
else {
|
||||
createActionLabel(GitBundle.message("editor.promo.help.link")) {
|
||||
HelpManager.getInstance().invokeHelp("Commit and push changes")
|
||||
}
|
||||
}
|
||||
add(InplaceButton(IconButton(GitBundle.message("editor.promo.close.link"), AllIcons.Actions.Close, AllIcons.Actions.CloseHovered)) {
|
||||
}
|
||||
else {
|
||||
panel.createActionLabel(GitBundle.message("editor.promo.commit.try.link"), IdeActions.ACTION_CHECKIN_PROJECT, false)
|
||||
}
|
||||
panel.add(
|
||||
InplaceButton(IconButton(GitBundle.message("editor.promo.close.link"), AllIcons.Actions.Close, AllIcons.Actions.CloseHovered)) {
|
||||
PropertiesComponent.getInstance().setValue(PROMO_DISMISSED_KEY, true)
|
||||
EditorNotifications.getInstance(project).updateNotifications(this@GitEditorPromo)
|
||||
EditorNotifications.getInstance(project).updateNotifications(this)
|
||||
}, BorderLayout.EAST)
|
||||
}
|
||||
panel
|
||||
}
|
||||
else null
|
||||
}
|
||||
|
||||
private fun isEnabled(): Boolean = !PropertiesComponent.getInstance().getBoolean(PROMO_DISMISSED_KEY)
|
||||
|
||||
+9
-10
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.plugins.groovy.config;
|
||||
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
@@ -30,37 +30,36 @@ import java.util.function.Function;
|
||||
final class ConfigureGroovyLibraryNotificationProvider implements EditorNotificationProvider {
|
||||
|
||||
@Override
|
||||
public @NotNull Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
public @Nullable Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file) {
|
||||
try {
|
||||
if (!file.getFileType().equals(GroovyFileType.GROOVY_FILE_TYPE)) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
// do not show the panel for Gradle build scripts
|
||||
// expecting groovy library to always be available at the gradle distribution
|
||||
if (StringUtil.endsWith(file.getName(), ".gradle") ||
|
||||
CompilerManager.getInstance(project).isExcludedFromCompilation(file)) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
final Module module = ModuleUtilCore.findModuleForFile(file, project);
|
||||
if (module == null ||
|
||||
isMavenModule(module)) {
|
||||
return CONST_NULL;
|
||||
if (module == null || isMavenModule(module)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (GroovyFrameworkConfigNotification configNotification : GroovyFrameworkConfigNotification.EP_NAME.getExtensions()) {
|
||||
if (configNotification.hasFrameworkStructure(module)) {
|
||||
return configNotification.hasFrameworkLibrary(module) ?
|
||||
CONST_NULL :
|
||||
null :
|
||||
fileEditor -> createConfigureNotificationPanel(module, fileEditor);
|
||||
}
|
||||
}
|
||||
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
catch (ProcessCanceledException | IndexNotReadyException ignored) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -12,12 +12,12 @@ import java.util.function.Function
|
||||
import javax.swing.JComponent
|
||||
|
||||
internal class KotlinHighlightingSuspendNotificationProvider : EditorNotificationProvider {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?> {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (!file.isKotlinFileType()) {
|
||||
return EditorNotificationProvider.CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
if (!KotlinHighlightingSuspender.getInstance(project).isSuspended(file)) return EditorNotificationProvider.CONST_NULL
|
||||
if (!KotlinHighlightingSuspender.getInstance(project).isSuspended(file)) return null
|
||||
|
||||
return Function {
|
||||
EditorNotificationPanel(it, EditorNotificationPanel.Status.Warning).apply {
|
||||
|
||||
+3
-4
@@ -13,7 +13,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.projectImport.ProjectImportProvider
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotificationProvider
|
||||
import com.intellij.ui.EditorNotificationProvider.CONST_NULL
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.kotlin.idea.base.scripting.KotlinBaseScriptingBundle
|
||||
import org.jetbrains.kotlin.idea.gradle.KotlinIdeaGradleBundle
|
||||
@@ -34,14 +33,14 @@ internal class GradleScriptNotificationProvider : EditorNotificationProvider {
|
||||
override fun collectNotificationData(
|
||||
project: Project,
|
||||
file: VirtualFile,
|
||||
): Function<in FileEditor, out JComponent?> {
|
||||
): Function<in FileEditor, out JComponent?>? {
|
||||
if (!isGradleKotlinScript(file) || !file.isKotlinFileType()) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
val standaloneScriptActions = GradleStandaloneScriptActionsManager.getInstance(project)
|
||||
val rootsManager = GradleBuildRootsManager.getInstance(project)
|
||||
val scriptUnderRoot = rootsManager?.findScriptBuildRoot(file) ?: return CONST_NULL
|
||||
val scriptUnderRoot = rootsManager?.findScriptBuildRoot(file) ?: return null
|
||||
|
||||
// todo: this actions will be usefull only when gradle fix https://github.com/gradle/gradle/issues/12640
|
||||
fun EditorNotificationPanel.showActionsToFixNotEvaluated() {
|
||||
|
||||
+6
-7
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
package org.jetbrains.kotlin.idea.script.configuration
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotificationProvider
|
||||
import com.intellij.ui.EditorNotificationProvider.*
|
||||
import com.intellij.ui.EditorNotifications
|
||||
import com.intellij.ui.HyperlinkLabel
|
||||
import org.jetbrains.annotations.Nls
|
||||
@@ -33,13 +32,13 @@ import javax.swing.JComponent
|
||||
|
||||
class MultipleScriptDefinitionsChecker : EditorNotificationProvider {
|
||||
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?> {
|
||||
if (!file.isKotlinFileType()) return CONST_NULL
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (!file.isKotlinFileType()) return null
|
||||
|
||||
val ktFile = PsiManager.getInstance(project).findFile(file).safeAs<KtFile>()?.takeIf(KtFile::isScript) ?: return CONST_NULL
|
||||
val ktFile = PsiManager.getInstance(project).findFile(file).safeAs<KtFile>()?.takeIf(KtFile::isScript) ?: return null
|
||||
|
||||
if (KotlinScriptingSettings.getInstance(project).suppressDefinitionsCheck ||
|
||||
!ScriptDefinitionsManager.getInstance(project).isReady()) return CONST_NULL
|
||||
!ScriptDefinitionsManager.getInstance(project).isReady()) return null
|
||||
|
||||
val allApplicableDefinitions = ScriptDefinitionsManager.getInstance(project)
|
||||
.getAllDefinitions()
|
||||
@@ -48,7 +47,7 @@ class MultipleScriptDefinitionsChecker : EditorNotificationProvider {
|
||||
KotlinScriptingSettings.getInstance(project).isScriptDefinitionEnabled(it)
|
||||
}
|
||||
.toList()
|
||||
if (allApplicableDefinitions.size < 2 || areDefinitionsForGradleKts(allApplicableDefinitions)) return CONST_NULL
|
||||
if (allApplicableDefinitions.size < 2 || areDefinitionsForGradleKts(allApplicableDefinitions)) return null
|
||||
|
||||
return Function { fileEditor: FileEditor ->
|
||||
createNotification(fileEditor, project, allApplicableDefinitions)
|
||||
|
||||
+4
-6
@@ -3,7 +3,6 @@ package org.jetbrains.kotlin.idea.script.configuration
|
||||
|
||||
import com.intellij.ide.BrowserUtil
|
||||
import com.intellij.ide.scratch.ScratchUtil
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.project.Project
|
||||
@@ -12,7 +11,6 @@ import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotificationProvider
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.kotlin.idea.base.resources.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings
|
||||
import org.jetbrains.kotlin.idea.util.KOTLIN_AWARE_SOURCE_ROOT_TYPES
|
||||
@@ -21,14 +19,14 @@ import java.util.function.Function
|
||||
import javax.swing.JComponent
|
||||
|
||||
class ScriptingSupportChecker: EditorNotificationProvider {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?> {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (!Registry.`is`("kotlin.scripting.support.warning") || file.isNonScript() || ScratchUtil.isScratch(file)) {
|
||||
return EditorNotificationProvider.CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
// warning panel is hidden
|
||||
if (!KotlinScriptingSettings.getInstance(project).showSupportWarning) {
|
||||
return EditorNotificationProvider.CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
val providers = ScriptingSupportCheckerProvider.CHECKER_PROVIDERS.getExtensionList(project)
|
||||
@@ -70,7 +68,7 @@ class ScriptingSupportChecker: EditorNotificationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
return EditorNotificationProvider.CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-8
@@ -20,7 +20,6 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotificationProvider
|
||||
import com.intellij.ui.EditorNotificationProvider.CONST_NULL
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil
|
||||
import org.jetbrains.kotlin.idea.base.facet.platform.platform
|
||||
import org.jetbrains.kotlin.idea.base.indices.KotlinPackageIndexUtils.findFilesWithExactPackage
|
||||
@@ -35,33 +34,33 @@ import javax.swing.JComponent
|
||||
|
||||
class KotlinAlternativeSourceNotificationProvider : EditorNotificationProvider {
|
||||
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?> {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (!DebuggerSettings.getInstance().SHOW_ALTERNATIVE_SOURCE) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
val javaSession = DebuggerManagerEx.getInstanceEx(project).context.debuggerSession
|
||||
val session = javaSession?.xDebugSession
|
||||
if (session == null) {
|
||||
AlternativeSourceNotificationProvider.setFileProcessed(file, false)
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
val position = session.currentPosition
|
||||
if (file != position?.file) {
|
||||
AlternativeSourceNotificationProvider.setFileProcessed(file, false)
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
if (DumbService.getInstance(project).isDumb) return CONST_NULL
|
||||
if (DumbService.getInstance(project).isDumb) return null
|
||||
|
||||
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return CONST_NULL
|
||||
val ktFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null
|
||||
val alternativeKtFiles = findAlternativeKtFiles(ktFile, project, javaSession)
|
||||
|
||||
AlternativeSourceNotificationProvider.setFileProcessed(file, true)
|
||||
|
||||
if (alternativeKtFiles.size <= 1) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
val currentFirstAlternatives: Collection<KtFile> = listOf(ktFile) + alternativeKtFiles.filter { it != ktFile }
|
||||
|
||||
+6
-7
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
package org.jetbrains.kotlin.idea.inspections
|
||||
|
||||
@@ -11,7 +11,6 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotificationProvider
|
||||
import com.intellij.ui.EditorNotificationProvider.CONST_NULL
|
||||
import org.jetbrains.kotlin.idea.KotlinJvmBundle
|
||||
import org.jetbrains.kotlin.idea.base.util.isGradleModule
|
||||
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||
@@ -21,16 +20,16 @@ import javax.swing.JComponent
|
||||
|
||||
class JavaOutsideModuleDetector : EditorNotificationProvider {
|
||||
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?> {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (file.extension != JavaFileType.DEFAULT_EXTENSION && !FileTypeRegistry.getInstance().isFileOfType(file, JavaFileType.INSTANCE)) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
val module = ModuleUtilCore.findModuleForFile(file, project)?.takeIf { it.isGradleModule } ?: return CONST_NULL
|
||||
val facetSettings = KotlinFacet.get(module)?.configuration?.settings ?: return CONST_NULL
|
||||
val module = ModuleUtilCore.findModuleForFile(file, project)?.takeIf { it.isGradleModule } ?: return null
|
||||
val facetSettings = KotlinFacet.get(module)?.configuration?.settings ?: return null
|
||||
|
||||
val filePath = file.path
|
||||
val nonKotlinPath = module.sourceRoots.map { it.path } - facetSettings.pureKotlinSourceFolders
|
||||
if (nonKotlinPath.any { filePath.startsWith(it) }) return CONST_NULL
|
||||
if (nonKotlinPath.any { filePath.startsWith(it) }) return null
|
||||
|
||||
return Function {
|
||||
EditorNotificationPanel(it, EditorNotificationPanel.Status.Warning).apply {
|
||||
|
||||
+6
-11
@@ -7,7 +7,6 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.compiler.CompilerManager
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.project.DumbService
|
||||
@@ -18,7 +17,6 @@ import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.intellij.openapi.ui.popup.PopupStep
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
|
||||
import com.intellij.openapi.util.NlsContexts
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
@@ -27,7 +25,6 @@ import com.intellij.ui.EditorNotificationProvider.*
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.jetbrains.kotlin.idea.*
|
||||
import org.jetbrains.kotlin.idea.base.facet.platform.platform
|
||||
import org.jetbrains.kotlin.idea.base.util.createComponentActionLabel
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinIdePlugin
|
||||
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinPluginLayout
|
||||
@@ -39,8 +36,6 @@ import org.jetbrains.kotlin.idea.util.application.invokeLater
|
||||
import org.jetbrains.kotlin.idea.util.application.isUnitTestMode
|
||||
import org.jetbrains.kotlin.idea.util.isKotlinFileType
|
||||
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.platform.js.isJs
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import java.awt.event.ComponentAdapter
|
||||
import java.awt.event.ComponentEvent
|
||||
import java.util.function.Function
|
||||
@@ -215,9 +210,9 @@ class UnsupportedAbiVersionNotificationPanelProvider : EditorNotificationProvide
|
||||
}
|
||||
}
|
||||
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?> {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (!file.isKotlinFileType()) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
try {
|
||||
if (
|
||||
@@ -226,14 +221,14 @@ class UnsupportedAbiVersionNotificationPanelProvider : EditorNotificationProvide
|
||||
|| CompilerManager.getInstance(project).isExcludedFromCompilation(file)
|
||||
|| KotlinNotConfiguredSuppressedModulesState.isSuppressed(project)
|
||||
) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
val module = ModuleUtilCore.findModuleForFile(file, project) ?: return CONST_NULL
|
||||
val module = ModuleUtilCore.findModuleForFile(file, project) ?: return null
|
||||
|
||||
val badRoots: Collection<BinaryVersionedFile<BinaryVersion>> = getLibraryRootsWithIncompatibleAbi(module)
|
||||
.takeUnless(Collection<BinaryVersionedFile<BinaryVersion>>::isEmpty)
|
||||
?: return CONST_NULL
|
||||
?: return null
|
||||
|
||||
return Function { doCreate(it, project, badRoots) }
|
||||
} catch (e: ProcessCanceledException) {
|
||||
@@ -242,7 +237,7 @@ class UnsupportedAbiVersionNotificationPanelProvider : EditorNotificationProvide
|
||||
DumbService.getInstance(project).runWhenSmart { updateNotifications(project) }
|
||||
}
|
||||
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
private fun findBadRootsInRuntimeLibraries(
|
||||
|
||||
+7
-8
@@ -20,7 +20,6 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.ui.EditorNotificationPanel
|
||||
import com.intellij.ui.EditorNotificationProvider
|
||||
import com.intellij.ui.EditorNotificationProvider.CONST_NULL
|
||||
import com.intellij.ui.EditorNotifications
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.base.facet.platform.platform
|
||||
@@ -39,19 +38,19 @@ import javax.swing.JComponent
|
||||
|
||||
// Code is partially copied from com.intellij.codeInsight.daemon.impl.SetupSDKNotificationProvider
|
||||
class KotlinSetupEnvironmentNotificationProvider : EditorNotificationProvider {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?> {
|
||||
override fun collectNotificationData(project: Project, file: VirtualFile): Function<in FileEditor, out JComponent?>? {
|
||||
if (!file.isKotlinFileType()) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return CONST_NULL
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file) as? KtFile ?: return null
|
||||
if (psiFile.language !== KotlinLanguage.INSTANCE) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(psiFile) ?: return CONST_NULL
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(psiFile) ?: return null
|
||||
if (!ModuleRootManager.getInstance(module).fileIndex.isInSourceContent(file)) {
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
if (ModuleRootManager.getInstance(module).sdk == null && psiFile.platform.isJvm()) {
|
||||
@@ -68,7 +67,7 @@ class KotlinSetupEnvironmentNotificationProvider : EditorNotificationProvider {
|
||||
return createKotlinNotConfiguredPanel(module, getAbleToRunConfigurators(module).toList())
|
||||
}
|
||||
|
||||
return CONST_NULL
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -100,14 +100,14 @@ public final class PyEditorNotificationProvider implements DumbAware, EditorNoti
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
public @Nullable Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> collectNotificationData(@NotNull Project project,
|
||||
@NotNull VirtualFile file) {
|
||||
PyFile node = getPyFile(project, file);
|
||||
if (node == null) {
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
Module module = guessModule(node);
|
||||
if (module == null || isFileIgnored(node)) return CONST_NULL;
|
||||
if (module == null || isFileIgnored(node)) return null;
|
||||
final Sdk sdk = PythonSdkUtil.findPythonSdk(module);
|
||||
|
||||
final boolean pyCharm = PythonIdeLanguageCustomization.isMainlyPythonIde();
|
||||
@@ -165,7 +165,7 @@ public final class PyEditorNotificationProvider implements DumbAware, EditorNoti
|
||||
}
|
||||
}
|
||||
}
|
||||
return CONST_NULL;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Function<? super @NotNull FileEditor, ? extends @Nullable JComponent> registerProblemWithCommonFixes(PyFile node,
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
@file:Suppress("ReplaceGetOrSet")
|
||||
|
||||
package com.jetbrains.python.sdk
|
||||
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.fixtures.CodeInsightTestFixture
|
||||
import com.intellij.ui.EditorNotifications
|
||||
import com.intellij.ui.EditorNotificationsImpl
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import com.jetbrains.extensions.getSdk
|
||||
import com.jetbrains.python.fixtures.PyTestCase
|
||||
import org.assertj.core.api.AssertionsForClassTypes
|
||||
@@ -32,7 +36,7 @@ class PythonNoSdkEditorNotificationTest : PyTestCase() {
|
||||
}
|
||||
|
||||
val editor = openFileInEditor(fileName, fileText, fixture)
|
||||
val notificationPanel = getNotificationPanel(editor)
|
||||
val notificationPanel = getNotificationPanel(editor, fixture.project)
|
||||
if (!sdkPresent && notificationPanel == null) {
|
||||
fail("\"No SDK notification\" expected")
|
||||
}
|
||||
@@ -45,13 +49,15 @@ class PythonNoSdkEditorNotificationTest : PyTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNotificationPanel(fileEditor: FileEditor): JComponent? {
|
||||
return EditorNotificationsImpl.getNotificationPanels(fileEditor).get(PyEditorNotificationProvider::class.java)
|
||||
private fun getNotificationPanel(fileEditor: FileEditor, project: Project): JComponent? {
|
||||
return (EditorNotifications.getInstance(project) as EditorNotificationsImpl).getNotificationPanels(fileEditor)
|
||||
.get(PyEditorNotificationProvider::class.java)
|
||||
}
|
||||
|
||||
fun openFileInEditor(fileName: String, fileText: String, fixture: CodeInsightTestFixture) : FileEditor {
|
||||
UIUtil.dispatchAllInvocationEvents()
|
||||
EditorNotificationsImpl.completeAsyncTasks(fixture.getProject())
|
||||
private fun openFileInEditor(fileName: String, fileText: String, fixture: CodeInsightTestFixture) : FileEditor {
|
||||
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()
|
||||
val editorNotifications = EditorNotifications.getInstance(fixture.project) as EditorNotificationsImpl
|
||||
editorNotifications.completeAsyncTasks()
|
||||
|
||||
val psiFile: PsiFile = fixture.configureByText(fileName, fileText)
|
||||
val fileEditorManager = FileEditorManager.getInstance(fixture.project)
|
||||
@@ -63,8 +69,8 @@ class PythonNoSdkEditorNotificationTest : PyTestCase() {
|
||||
val editors = fileEditorManager.openFile(virtualFile, true)
|
||||
AssertionsForClassTypes.assertThat(editors).hasSize(1)
|
||||
|
||||
UIUtil.dispatchAllInvocationEvents()
|
||||
EditorNotificationsImpl.completeAsyncTasks(fixture.getProject())
|
||||
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue()
|
||||
editorNotifications.completeAsyncTasks()
|
||||
|
||||
return editors[0]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user