From 0f208ed8b142f55368dc1edfcd7f9c31677d6532 Mon Sep 17 00:00:00 2001 From: Leonid Shalupov Date: Thu, 7 Nov 2024 17:35:00 +0100 Subject: [PATCH] ui designer: update generated java forms code on save required for IJI-2340 Remove UI Designer forms compilation (cherry picked from commit 75f67b35e640757a655668e5bc360488578b9db8) IJ-CR-148847 GitOrigin-RevId: 8d172caec6f1a3f518c9ad2129a8e1825f2b51ae --- .../messages/UIDesignerBundle.properties | 1 + .../uiDesigner/GeneralConfigurable.form | 13 ++++- .../uiDesigner/GuiDesignerConfigurable.java | 7 +++ .../uiDesigner/GuiDesignerConfiguration.java | 7 +++ .../uiDesigner/designSurface/GuiEditor.java | 54 +++++++++++++++++++ .../uiDesigner/make/Form2SourceCompiler.java | 4 +- 6 files changed, 83 insertions(+), 3 deletions(-) diff --git a/plugins/ui-designer/resources/messages/UIDesignerBundle.properties b/plugins/ui-designer/resources/messages/UIDesignerBundle.properties index ef039f9b3e03..8f42bce79bd9 100644 --- a/plugins/ui-designer/resources/messages/UIDesignerBundle.properties +++ b/plugins/ui-designer/resources/messages/UIDesignerBundle.properties @@ -513,6 +513,7 @@ group.GuiDesigner.MainToolbarActions.text=UI Designer Toolbar Actions group.GuiDesigner.NewActions.text=Swing UI Designer ui.designer.general.settings.resize.column.and.row.headers=&Resize column and row headers with mouse ui.designer.general.settings.use.dynamic.bundles=Allow changing locale at runtime (requires 2020.1) +ui.designer.general.settings.generate.source.code.on.form.save=Generate source code on form save inspection.message.typo.in.word=Typo in word ''{0}'' inspection.message.typo.in.word.title=Typo in a UI form intention.name.save.to.dictionary=Save ''{0}'' to dictionary diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/GeneralConfigurable.form b/plugins/ui-designer/src/com/intellij/uiDesigner/GeneralConfigurable.form index 0cac47255b36..a96de892e81e 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/GeneralConfigurable.form +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/GeneralConfigurable.form @@ -1,6 +1,6 @@
- + @@ -10,7 +10,7 @@ - + @@ -117,6 +117,15 @@ + + + + + + + + + diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java index 2944e663d7ac..7011ae31fed1 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfigurable.java @@ -74,6 +74,10 @@ public final class GuiDesignerConfigurable implements SearchableConfigurable, Co return true; } + if (myGeneralUI.myChkGenerateSourceCodeOnFormSave.isSelected() != configuration.GENERATE_SOURCES_ON_SAVE) { + return true; + } + if (!Comparing.equal(configuration.DEFAULT_LAYOUT_MANAGER, myGeneralUI.myLayoutManagerCombo.getSelectedItem())) { return true; } @@ -102,6 +106,7 @@ public final class GuiDesignerConfigurable implements SearchableConfigurable, Co configuration.DEFAULT_FIELD_ACCESSIBILITY = (String)myGeneralUI .myDefaultFieldAccessibilityCombo.getSelectedItem(); configuration.RESIZE_HEADERS = myGeneralUI.myResizeHeaders.isSelected(); configuration.USE_DYNAMIC_BUNDLES = myGeneralUI.myChkUseDynamicBundles.isSelected(); + configuration.GENERATE_SOURCES_ON_SAVE = myGeneralUI.myChkGenerateSourceCodeOnFormSave.isSelected(); if (configuration.INSTRUMENT_CLASSES && !myProject.isDefault()) { final DispatchThreadProgressWindow progressWindow = new DispatchThreadProgressWindow(false, myProject); @@ -124,6 +129,7 @@ public final class GuiDesignerConfigurable implements SearchableConfigurable, Co } myGeneralUI.myChkCopyFormsRuntime.setSelected(configuration.COPY_FORMS_RUNTIME_TO_OUTPUT); myGeneralUI.myChkUseDynamicBundles.setSelected(configuration.USE_DYNAMIC_BUNDLES); + myGeneralUI.myChkGenerateSourceCodeOnFormSave.setSelected(configuration.GENERATE_SOURCES_ON_SAVE); myGeneralUI.myLayoutManagerCombo.setModel(new DefaultComboBoxModel<>(LayoutManagerRegistry.getNonDeprecatedLayoutManagerNames())); myGeneralUI.myLayoutManagerCombo.setRenderer(SimpleListCellRenderer.create("", LayoutManagerRegistry::getLayoutManagerDisplayName)); @@ -145,6 +151,7 @@ public final class GuiDesignerConfigurable implements SearchableConfigurable, Co public JRadioButton myRbInstrumentSources; public JCheckBox myChkCopyFormsRuntime; public JCheckBox myChkUseDynamicBundles; + public JCheckBox myChkGenerateSourceCodeOnFormSave; private JComboBox myLayoutManagerCombo; private JComboBox myDefaultFieldAccessibilityCombo; private JCheckBox myResizeHeaders; diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfiguration.java b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfiguration.java index 9f0c23e0f65c..22575d554c19 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfiguration.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/GuiDesignerConfiguration.java @@ -25,6 +25,13 @@ public final class GuiDesignerConfiguration implements PersistentStateComponent< public boolean COPY_FORMS_RUNTIME_TO_OUTPUT = true; + /** + * If INSTRUMENT_CLASSES is false, the user may select between generating source files + * upon Build (default, GENERATE_SOURCES_ON_SAVE is false) and + * generating right after saving the form (GENERATE_SOURCES_ON_SAVE is true) + */ + public boolean GENERATE_SOURCES_ON_SAVE = false; + public @NlsSafe String DEFAULT_LAYOUT_MANAGER = UIFormXmlConstants.LAYOUT_INTELLIJ; public @NlsSafe String DEFAULT_FIELD_ACCESSIBILITY = PsiModifier.PRIVATE; diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java index 838d15f95684..6460790849c9 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java @@ -2,6 +2,9 @@ package com.intellij.uiDesigner.designSurface; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.compiler.CompilerMessageImpl; +import com.intellij.compiler.impl.ExitStatus; +import com.intellij.compiler.progress.BuildOutputService; import com.intellij.designer.DesignerEditorPanelFacade; import com.intellij.designer.LightFillLayout; import com.intellij.ide.DeleteProvider; @@ -15,6 +18,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.undo.UndoManager; +import com.intellij.openapi.compiler.CompilerMessageCategory; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -41,6 +45,7 @@ import com.intellij.ui.JBColor; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBLayeredPane; import com.intellij.uiDesigner.*; +import com.intellij.uiDesigner.compiler.FormErrorInfo; import com.intellij.uiDesigner.compiler.Utils; import com.intellij.uiDesigner.componentTree.ComponentPtr; import com.intellij.uiDesigner.componentTree.ComponentSelectionListener; @@ -51,6 +56,8 @@ import com.intellij.uiDesigner.editor.UIFormEditor; import com.intellij.uiDesigner.lw.CompiledClassPropertiesProvider; import com.intellij.uiDesigner.lw.IProperty; import com.intellij.uiDesigner.lw.LwRootContainer; +import com.intellij.uiDesigner.make.FormElementNavigatable; +import com.intellij.uiDesigner.make.FormSourceCodeGenerator; import com.intellij.uiDesigner.palette.ComponentItem; import com.intellij.uiDesigner.propertyInspector.DesignerToolWindow; import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; @@ -627,6 +634,9 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade private void saveToFile() { LOG.debug("GuiEditor.saveToFile(): group ID=" + myNextSaveGroupId); + + GuiDesignerConfiguration designerConfiguration = GuiDesignerConfiguration.getInstance(myProject); + CommandProcessor.getInstance().executeCommand(getProject(), () -> ApplicationManager.getApplication().runWriteAction(() -> { myInsideChange = true; try { @@ -648,6 +658,50 @@ public final class GuiEditor extends JPanel implements DesignerEditorPanelFacade LOG.error(e); myDocument.replaceString(0, oldText.length(), newText); } + + if (!designerConfiguration.INSTRUMENT_CLASSES && designerConfiguration.GENERATE_SOURCES_ON_SAVE) { + try { + LOG.debug("Updating sources for form '" + myFile.getPath()); + + FileDocumentManager.getInstance().saveDocument(myDocument); + PsiDocumentManager.getInstance(myProject).commitAllDocuments(); + + final FormSourceCodeGenerator generator = new FormSourceCodeGenerator(myProject); + generator.generate(myFile); + + final ArrayList errors = generator.getErrors(); + if (!errors.isEmpty()) { + StringBuilder builder = new StringBuilder(); + builder.append("Unable to update sources for form '").append(myFile.getPath()).append("' due to errors:\n"); + errors.forEach(error -> { + builder.append(error.getComponentId()).append(" ").append(error.getErrorMessage()).append("\n"); + }); + LOG.info(builder.toString()); + + BuildOutputService buildOutput = new BuildOutputService(myProject, "UI Form Compilation"); //NON-NLS + Object sessionId = new Object(); + long stamp = System.currentTimeMillis(); + buildOutput.onStart(sessionId, stamp, null, null); + + for (FormErrorInfo error : errors) { + FormElementNavigatable navigatable = new FormElementNavigatable(myProject, myFile, error.getComponentId()); + buildOutput.addMessage( + sessionId, + new CompilerMessageImpl( + myProject, + CompilerMessageCategory.ERROR, + myFile.getPresentableUrl() + ": " + error.getErrorMessage(), //NON-NLS + myFile, + -1, -1, + navigatable + )); + } + buildOutput.onEnd(sessionId, ExitStatus.ERRORS, stamp + 1); + } + } catch (Throwable e) { + LOG.error(e); + } + } } finally { myInsideChange = false; diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2SourceCompiler.java b/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2SourceCompiler.java index eb293051e7f0..2996ed72db32 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2SourceCompiler.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/make/Form2SourceCompiler.java @@ -65,7 +65,9 @@ public final class Form2SourceCompiler implements SourceInstrumentingCompiler{ @Override public ProcessingItem @NotNull [] getProcessingItems(final @NotNull CompileContext context) { final Project project = context.getProject(); - if (GuiDesignerConfiguration.getInstance(project).INSTRUMENT_CLASSES) { + GuiDesignerConfiguration designerConfiguration = GuiDesignerConfiguration.getInstance(project); + + if (designerConfiguration.INSTRUMENT_CLASSES || designerConfiguration.GENERATE_SOURCES_ON_SAVE) { return ProcessingItem.EMPTY_ARRAY; }