diff --git a/platform/lang-impl/api-dump-experimental.txt b/platform/lang-impl/api-dump-experimental.txt index 077e9e87e361..b551ea7cdb68 100644 --- a/platform/lang-impl/api-dump-experimental.txt +++ b/platform/lang-impl/api-dump-experimental.txt @@ -529,6 +529,13 @@ f:com.intellij.ide.actions.searcheverywhere.SearchEverywhereUI - *:selectFirst():V com.intellij.ide.actions.searcheverywhere.SearchListener - *:standardSearchFoundNoResults(com.intellij.ide.actions.searcheverywhere.SearchEverywhereContributor):V +*a:com.intellij.ide.fileTemplates.actions.CustomCreateFromTemplateAction +- com.intellij.ide.actions.CreateFileFromTemplateAction +- p:(java.lang.String):V +- p:buildDialog(com.intellij.openapi.project.Project,com.intellij.psi.PsiDirectory,com.intellij.ide.actions.CreateFileFromTemplateDialog$Builder):V +- p:getActionName(com.intellij.psi.PsiDirectory,java.lang.String,java.lang.String):java.lang.String +- p:getLiveTemplateDefaults(com.intellij.openapi.actionSystem.DataContext,com.intellij.psi.PsiFile):java.util.Map +- p:postProcess(com.intellij.psi.PsiFile,com.intellij.openapi.actionSystem.DataContext,java.lang.String,java.util.Map):V f:com.intellij.ide.impl.StructureViewWrapperImpl - com.intellij.ide.structureView.StructureViewWrapper - com.intellij.openapi.Disposable diff --git a/platform/lang-impl/api-dump-unreviewed.txt b/platform/lang-impl/api-dump-unreviewed.txt index 352c72e03db0..39b56d8cdae7 100644 --- a/platform/lang-impl/api-dump-unreviewed.txt +++ b/platform/lang-impl/api-dump-unreviewed.txt @@ -8210,6 +8210,7 @@ a:com.intellij.ide.actions.CreateFromTemplateAction - p:getErrorTitle():java.lang.String - p:isAvailable(com.intellij.openapi.actionSystem.DataContext):Z - s:moveCaretAfterNameIdentifier(com.intellij.psi.PsiNameIdentifierOwner):V +- p:postProcess(com.intellij.psi.PsiElement,com.intellij.openapi.actionSystem.DataContext,java.lang.String,java.util.Map):V - p:postProcess(com.intellij.psi.PsiElement,java.lang.String,java.util.Map):V - update(com.intellij.openapi.actionSystem.AnActionEvent):V a:com.intellij.ide.actions.CreateTemplateInPackageAction @@ -9381,6 +9382,10 @@ a:com.intellij.ide.fileTemplates.actions.CreateFromTemplateActionBase - pa:getTemplate(com.intellij.openapi.project.Project,com.intellij.psi.PsiDirectory):com.intellij.ide.fileTemplates.FileTemplate - s:startLiveTemplate(com.intellij.psi.PsiFile):V - s:startLiveTemplate(com.intellij.psi.PsiFile,java.util.Map):V +f:com.intellij.ide.fileTemplates.actions.CreateFromTemplateManager +- ():V +- s:startLiveTemplate(com.intellij.psi.PsiFile):V +- s:startLiveTemplate(com.intellij.psi.PsiFile,java.util.Map):V f:com.intellij.ide.fileTemplates.actions.FileTemplateSeparator - com.intellij.openapi.actionSystem.ActionGroup - ():V diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CreateFromTemplateAction.java b/platform/lang-impl/src/com/intellij/ide/actions/CreateFromTemplateAction.java index 11f0d119a248..413d6b751c63 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/CreateFromTemplateAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/CreateFromTemplateAction.java @@ -108,7 +108,7 @@ public abstract class CreateFromTemplateAction extends AnA editor.getCaretModel().moveToOffset(offset); } try (var ignored = SlowOperations.startSection(SlowOperations.ACTION_PERFORM)) { - postProcess(createdElement, selectedTemplateName.get(), builder.getCustomProperties()); + postProcess(createdElement, dataContext, selectedTemplateName.get(), builder.getCustomProperties()); } } }); @@ -133,6 +133,11 @@ public abstract class CreateFromTemplateAction extends AnA return CreateFileFromTemplateDialog.createDialog(project); } + protected void postProcess(@NotNull T createdElement, @NotNull DataContext dataContext, + String templateName, Map customProperties) { + postProcess(createdElement, templateName, customProperties); + } + protected void postProcess(@NotNull T createdElement, String templateName, Map customProperties) { } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateActionBase.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateActionBase.java index 5b3f1559b37b..03a676cb8596 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateActionBase.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateActionBase.java @@ -1,20 +1,15 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.fileTemplates.actions; -import com.intellij.codeInsight.template.TemplateManager; -import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.ide.IdeView; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; import com.intellij.ide.fileTemplates.ui.CreateFromTemplateDialog; import com.intellij.ide.util.DirectoryChooserUtil; -import com.intellij.ide.util.EditorHelper; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.command.WriteCommandAction; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsActions; import com.intellij.psi.PsiDirectory; @@ -24,11 +19,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.*; +import java.util.Collections; +import java.util.Map; +import java.util.Properties; import java.util.function.Supplier; import static com.intellij.util.ObjectUtils.notNull; +/** + * Consider using {@link CustomCreateFromTemplateAction} instead for subclasses. + */ public abstract class CreateFromTemplateActionBase extends AnAction { public CreateFromTemplateActionBase() { super(); @@ -77,35 +77,20 @@ public abstract class CreateFromTemplateActionBase extends AnAction { } } + /** + * @deprecated Use {@link CreateFromTemplateManager#startLiveTemplate(PsiFile)} instead + */ + @Deprecated public static void startLiveTemplate(@NotNull PsiFile file) { - startLiveTemplate(file, Collections.emptyMap()); + CreateFromTemplateManager.startLiveTemplate(file, Collections.emptyMap()); } + /** + * @deprecated Use {@link CreateFromTemplateManager#startLiveTemplate(PsiFile, Map)} instead + */ + @Deprecated public static void startLiveTemplate(@NotNull PsiFile file, @NotNull Map defaultValues) { - Editor editor = EditorHelper.openInEditor(file); - if (editor == null) return; - - TemplateImpl template = new TemplateImpl("", file.getText(), ""); - template.setInline(true); - int count = template.getSegmentsCount(); - if (count == 0) return; - - // Using LinkedHashSet for a saving variables orders - Set variables = new LinkedHashSet<>(); - for (int i = 0; i < count; i++) { - variables.add(template.getSegmentName(i)); - } - variables.removeAll(TemplateImpl.INTERNAL_VARS_SET); - for (String variable : variables) { - String defaultValue = defaultValues.getOrDefault(variable, variable); - template.addVariable(variable, null, '"' + defaultValue + '"', true); - } - - Project project = file.getProject(); - WriteCommandAction.runWriteCommandAction(project, () -> editor.getDocument().setText(template.getTemplateText())); - - editor.getCaretModel().moveToOffset(0); // ensures caret at the start of the template - TemplateManager.getInstance(project).startTemplate(editor, template); + CreateFromTemplateManager.startLiveTemplate(file, defaultValues); } protected @Nullable PsiDirectory getTargetDirectory(DataContext dataContext, IdeView view) { diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateManager.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateManager.java new file mode 100644 index 000000000000..6ed95a6d7275 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CreateFromTemplateManager.java @@ -0,0 +1,49 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ide.fileTemplates.actions; + +import com.intellij.codeInsight.template.TemplateManager; +import com.intellij.codeInsight.template.impl.TemplateImpl; +import com.intellij.ide.util.EditorHelper; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +public final class CreateFromTemplateManager { + public static void startLiveTemplate(@NotNull PsiFile file) { + startLiveTemplate(file, Collections.emptyMap()); + } + + public static void startLiveTemplate(@NotNull PsiFile file, @NotNull Map defaultValues) { + Editor editor = EditorHelper.openInEditor(file); + if (editor == null) return; + + TemplateImpl template = new TemplateImpl("", file.getText(), ""); + template.setInline(true); + int count = template.getSegmentsCount(); + if (count == 0) return; + + // Using LinkedHashSet for a saving variables orders + Set variables = new LinkedHashSet<>(); + for (int i = 0; i < count; i++) { + variables.add(template.getSegmentName(i)); + } + variables.removeAll(TemplateImpl.INTERNAL_VARS_SET); + for (String variable : variables) { + String defaultValue = defaultValues.getOrDefault(variable, variable); + template.addVariable(variable, null, '"' + defaultValue + '"', true); + } + + Project project = file.getProject(); + WriteCommandAction.runWriteCommandAction(project, () -> editor.getDocument().setText(template.getTemplateText())); + + editor.getCaretModel().moveToOffset(0); // ensures caret at the start of the template + TemplateManager.getInstance(project).startTemplate(editor, template); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CustomCreateFromTemplateAction.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CustomCreateFromTemplateAction.java new file mode 100644 index 000000000000..aa131035cbdf --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/actions/CustomCreateFromTemplateAction.java @@ -0,0 +1,69 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ide.fileTemplates.actions; + +import com.intellij.ide.actions.CreateFileFromTemplateAction; +import com.intellij.ide.actions.CreateFileFromTemplateDialog; +import com.intellij.ide.fileTemplates.FileTemplate; +import com.intellij.ide.fileTemplates.FileTemplateManager; +import com.intellij.ide.fileTemplates.FileTemplateUtil; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.Map; + +import static com.intellij.ide.fileTemplates.actions.CreateFromTemplateManager.startLiveTemplate; +import static com.intellij.util.ObjectUtils.notNull; + +@ApiStatus.Experimental +public abstract class CustomCreateFromTemplateAction extends CreateFileFromTemplateAction { + @NotNull private final String myTemplateName; + + protected CustomCreateFromTemplateAction(@NotNull String name) { + myTemplateName = name; + } + + @SuppressWarnings("HardCodedStringLiteral") + @Override + protected void buildDialog(@NotNull Project project, + @NotNull PsiDirectory directory, + @NotNull CreateFileFromTemplateDialog.Builder builder) { + FileTemplateManager fileTemplateManager = FileTemplateManager.getInstance(project); + FileTemplate template = fileTemplateManager.getInternalTemplate(myTemplateName); + + builder + .setTitle(myTemplateName) + .addKind(myTemplateName, FileTemplateUtil.getIcon(template), template.getName()); + } + + @SuppressWarnings("HardCodedStringLiteral") + @Override + protected String getActionName(PsiDirectory directory, @NotNull String newName, String templateName) { + return templateName; + } + + @Override + protected void postProcess(@NotNull PsiFile createdElement, + @NotNull DataContext dataContext, + String templateName, + Map customProperties) { + super.postProcess(createdElement, dataContext, templateName, customProperties); + + var selectedTemplate = FileTemplateManager.getInstance(createdElement.getProject()) + .getInternalTemplate(templateName); + + if (selectedTemplate.isLiveTemplateEnabled()) { + Map defaultValues = getLiveTemplateDefaults(dataContext, createdElement); + startLiveTemplate(createdElement, notNull(defaultValues, Collections.emptyMap())); + } + } + + protected @Nullable Map getLiveTemplateDefaults(@NotNull DataContext dataContext, @NotNull PsiFile file) { + return null; + } +} diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/CreateFxmlFileAction.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/CreateFxmlFileAction.java index b2ff3a24d1e1..41d0c3a66f3f 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/CreateFxmlFileAction.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/CreateFxmlFileAction.java @@ -1,55 +1,38 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.plugins.javaFX.actions; -import com.intellij.ide.fileTemplates.FileTemplate; -import com.intellij.ide.fileTemplates.FileTemplateManager; -import com.intellij.ide.fileTemplates.actions.CreateFromTemplateActionBase; -import com.intellij.openapi.actionSystem.*; +import com.intellij.ide.fileTemplates.actions.CustomCreateFromTemplateAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.roots.PackageIndex; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; -import com.intellij.psi.util.CachedValueProvider.Result; -import com.intellij.psi.util.CachedValuesManager; import com.intellij.util.PathUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; -import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory; -import java.util.Arrays; import java.util.Collections; import java.util.Map; -import java.util.Set; -import static com.intellij.psi.search.GlobalSearchScope.moduleWithDependenciesAndLibrariesScope; -import static org.jetbrains.plugins.javaFX.fxml.JavaFxCommonNames.JAVAFX_APPLICATION_APPLICATION; +import static org.jetbrains.plugins.javaFX.actions.JavaFxTemplateManager.isJavaFxTemplateAvailable; -public final class CreateFxmlFileAction extends CreateFromTemplateActionBase { +final class CreateFxmlFileAction extends CustomCreateFromTemplateAction implements DumbAware { private static final String INTERNAL_TEMPLATE_NAME = "FxmlFile.fxml"; - @Override - public @NotNull ActionUpdateThread getActionUpdateThread() { - return ActionUpdateThread.BGT; + CreateFxmlFileAction() { + super(INTERNAL_TEMPLATE_NAME); } @Override - protected FileTemplate getTemplate(Project project, PsiDirectory dir) { - return FileTemplateManager.getInstance(project).getInternalTemplate(INTERNAL_TEMPLATE_NAME); - } - - @Override - protected Map getLiveTemplateDefaults(DataContext dataContext, @NotNull PsiFile file) { + protected Map getLiveTemplateDefaults(@NotNull DataContext dataContext, @NotNull PsiFile file) { String packageName = ReadAction.compute(() -> { PsiDirectory psiDirectory = file.getContainingDirectory(); if (psiDirectory != null) { @@ -101,42 +84,7 @@ public final class CreateFxmlFileAction extends CreateFromTemplateActionBase { } @Override - public void update(final @NotNull AnActionEvent e) { - final DataContext dataContext = e.getDataContext(); - final Presentation presentation = e.getPresentation(); - - presentation.setEnabledAndVisible(isJavaFxTemplateAvailable(dataContext, JavaModuleSourceRootTypes.PRODUCTION)); - } - - static boolean isJavaFxTemplateAvailable(DataContext dataContext, Set> requiredRootTypes) { - var project = CommonDataKeys.PROJECT.getData(dataContext); - var view = LangDataKeys.IDE_VIEW.getData(dataContext); - if (project == null || view == null) { - return false; - } - - var directories = view.getDirectories(); - if (directories.length == 0) return false; - - var index = ProjectRootManager.getInstance(project).getFileIndex(); - var underRoot = Arrays.stream(directories) - .map(PsiDirectory::getVirtualFile) - .anyMatch(virtualFile -> index.isUnderSourceRootOfType(virtualFile, requiredRootTypes)); - - if (!underRoot) return false; - - // root types check is less expensive on start toolbar update than checking module dependencies - var module = ModuleUtilCore.findModuleForFile(directories[0].getVirtualFile(), project); - return hasJavaFxDependency(module); - } - - private static boolean hasJavaFxDependency(@Nullable Module module) { - if (module == null || module.isDisposed()) return false; - - return CachedValuesManager.getManager(module.getProject()).getCachedValue(module, () -> { - boolean hasClass = JavaPsiFacade.getInstance(module.getProject()) - .findClass(JAVAFX_APPLICATION_APPLICATION, moduleWithDependenciesAndLibrariesScope(module)) != null; - return Result.create(hasClass, ProjectRootManager.getInstance(module.getProject())); - }); + public void update(@NotNull AnActionEvent e) { + e.getPresentation().setEnabledAndVisible(isJavaFxTemplateAvailable(e.getDataContext(), JavaModuleSourceRootTypes.PRODUCTION)); } } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/CreateJavaFxApplicationAction.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/CreateJavaFxApplicationAction.java index a44f7de0e9ea..cbc70526a0d3 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/CreateJavaFxApplicationAction.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/CreateJavaFxApplicationAction.java @@ -1,32 +1,21 @@ // Copyright 2000-2021 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. package org.jetbrains.plugins.javaFX.actions; -import com.intellij.ide.fileTemplates.FileTemplate; -import com.intellij.ide.fileTemplates.FileTemplateManager; -import com.intellij.ide.fileTemplates.actions.CreateFromTemplateActionBase; -import com.intellij.openapi.actionSystem.ActionUpdateThread; +import com.intellij.ide.fileTemplates.actions.CustomCreateFromTemplateAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDirectory; +import com.intellij.openapi.project.DumbAware; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.model.java.JavaSourceRootType; import java.util.Set; -import static org.jetbrains.plugins.javaFX.actions.CreateFxmlFileAction.isJavaFxTemplateAvailable; - -final class CreateJavaFxApplicationAction extends CreateFromTemplateActionBase { +import static org.jetbrains.plugins.javaFX.actions.JavaFxTemplateManager.isJavaFxTemplateAvailable; +final class CreateJavaFxApplicationAction extends CustomCreateFromTemplateAction implements DumbAware { private static final String FILE_TEMPLATE_NAME = "JavaFXApplication.java"; - @Override - public @NotNull ActionUpdateThread getActionUpdateThread() { - return ActionUpdateThread.BGT; - } - - @Override - protected FileTemplate getTemplate(Project project, PsiDirectory dir) { - return FileTemplateManager.getInstance(project).getTemplate(FILE_TEMPLATE_NAME); + CreateJavaFxApplicationAction() { + super(FILE_TEMPLATE_NAME); } @Override diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/JavaFxTemplateManager.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/JavaFxTemplateManager.java new file mode 100644 index 000000000000..d5dcda19cf03 --- /dev/null +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/JavaFxTemplateManager.java @@ -0,0 +1,56 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.plugins.javaFX.actions; + +import com.intellij.java.library.JavaLibraryModificationTracker; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.util.CachedValueProvider.Result; +import com.intellij.psi.util.CachedValuesManager; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.module.JpsModuleSourceRootType; + +import java.util.Arrays; +import java.util.Set; + +import static com.intellij.psi.search.GlobalSearchScope.moduleWithDependenciesAndLibrariesScope; +import static org.jetbrains.plugins.javaFX.fxml.JavaFxCommonNames.JAVAFX_APPLICATION_APPLICATION; + +final class JavaFxTemplateManager { + static boolean isJavaFxTemplateAvailable(DataContext dataContext, Set> requiredRootTypes) { + var project = CommonDataKeys.PROJECT.getData(dataContext); + var view = LangDataKeys.IDE_VIEW.getData(dataContext); + if (project == null || view == null) { + return false; + } + + var directories = view.getDirectories(); + if (directories.length == 0) return false; + + var index = ProjectRootManager.getInstance(project).getFileIndex(); + var underRoot = Arrays.stream(directories) + .map(PsiDirectory::getVirtualFile) + .anyMatch(virtualFile -> index.isUnderSourceRootOfType(virtualFile, requiredRootTypes)); + + if (!underRoot) return false; + + // root types check is less expensive on start toolbar update than checking module dependencies + var module = ModuleUtilCore.findModuleForFile(directories[0].getVirtualFile(), project); + return hasJavaFxDependency(module); + } + + private static boolean hasJavaFxDependency(@Nullable Module module) { + if (module == null || module.isDisposed()) return false; + + return CachedValuesManager.getManager(module.getProject()).getCachedValue(module, () -> { + boolean hasClass = JavaPsiFacade.getInstance(module.getProject()) + .findClass(JAVAFX_APPLICATION_APPLICATION, moduleWithDependenciesAndLibrariesScope(module)) != null; + return Result.create(hasClass, JavaLibraryModificationTracker.getInstance(module.getProject())); + }); + } +}