diff --git a/com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderConfigurationBlock.java b/com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderConfigurationBlock.java index 60080debed..25d5335c6a 100644 --- a/com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderConfigurationBlock.java +++ b/com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderConfigurationBlock.java @@ -12,19 +12,51 @@ package com.avaloq.tools.ddk.check.ui.builder; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.xtext.xbase.ui.builder.XbaseBuilderConfigurationBlock; +import com.avaloq.tools.ddk.xtext.ui.BuilderParticipantMasterSwitch; + /** - * UI for configuring Check compiler. + * UI for configuring Check compiler. Adds the workspace-wide DDK generation master switch on top of the stock options. */ @SuppressWarnings("restriction") public class CheckBuilderConfigurationBlock extends XbaseBuilderConfigurationBlock { + private BuilderParticipantMasterSwitch masterSwitch; + + @Override + protected Control doCreateContents(final Composite parent) { + if (getProject() != null) { + return super.doCreateContents(parent); // project property page: the master switch is workspace-wide only + } + masterSwitch = new BuilderParticipantMasterSwitch(parent, super::doCreateContents); + return masterSwitch.getControl(); + } + @Override protected void createGeneralSectionItems(final Composite composite) { super.createGeneralSectionItems(composite); addCheckBox(composite, "Generate as DSL internal checks (not SCA plugin)", CheckBuilderPreferenceAccess.PREF_GENERATE_LANGUAGE_INTERNAL_CHECKS, BOOLEAN_VALUES, 0); //$NON-NLS-1$ } + @Override + public boolean performOk() { + final boolean rebuildRequired = masterSwitch != null && masterSwitch.save(); + final boolean result = super.performOk(); + if (rebuildRequired) { + getBuildJob(getProject()).schedule(); // re-enabling generation: rebuild to catch up on changes made while it was off + } + return result; + } + + @Override + public void performDefaults() { + if (masterSwitch != null) { + masterSwitch.restoreDefaults(); + } + super.performDefaults(); + } + } diff --git a/com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderParticipant.java b/com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderParticipant.java index d5bb9d9245..5573055585 100644 --- a/com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderParticipant.java +++ b/com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderParticipant.java @@ -60,6 +60,9 @@ public class CheckBuilderParticipant extends ConditionalBuilderParticipant { @Override public void build(final IBuildContext context, final IProgressMonitor monitor) throws CoreException { + if (!isBuilderParticipantEnabled() && context.getBuildType() != BuildType.CLEAN) { + return; + } if (!isEnabled(context)) { return; } diff --git a/com.avaloq.tools.ddk.xtext.builder/src/com/avaloq/tools/ddk/xtext/builder/BuilderParticipantSettings.java b/com.avaloq.tools.ddk.xtext.builder/src/com/avaloq/tools/ddk/xtext/builder/BuilderParticipantSettings.java new file mode 100644 index 0000000000..e529fe16f6 --- /dev/null +++ b/com.avaloq.tools.ddk.xtext.builder/src/com/avaloq/tools/ddk/xtext/builder/BuilderParticipantSettings.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2026 Avaloq Group AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Avaloq Group AG - initial API and implementation + *******************************************************************************/ +package com.avaloq.tools.ddk.xtext.builder; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.osgi.service.prefs.BackingStoreException; +import org.osgi.service.prefs.Preferences; + + +/** + * Access to the workspace-wide setting that disables code generation by the builder participants of all DDK languages at once. The setting is shared by all DDK + * languages (a single boolean in the {@code com.avaloq.tools.ddk} instance preference node) and is surfaced as the master switch on each language's Compiler + * preference page. As a plain boolean preference it defaults to {@code false} (generation enabled), so behavior is unchanged unless a user opts in. + */ +public final class BuilderParticipantSettings { + + /** Preference node shared by all DDK languages. */ + public static final String QUALIFIER = "com.avaloq.tools.ddk"; //$NON-NLS-1$ + + /** Boolean preference key; {@code true} disables generation by all DDK builder participants on workspace builds. */ + public static final String PREF_DISABLE_BUILDER_PARTICIPANTS = "disableBuilderParticipants"; //$NON-NLS-1$ + + private static final Logger LOGGER = LogManager.getLogger(BuilderParticipantSettings.class); + + private BuilderParticipantSettings() { + // static utility + } + + /** + * Returns whether generation by the DDK builder participants is disabled workspace-wide. + * + * @return {@code true} if the master switch disables generation, {@code false} otherwise (the default) + */ + public static boolean isGenerationDisabled() { + return InstanceScope.INSTANCE.getNode(QUALIFIER).getBoolean(PREF_DISABLE_BUILDER_PARTICIPANTS, false); + } + + /** + * Sets whether generation by the DDK builder participants is disabled workspace-wide. + * + * @param disabled + * {@code true} to disable generation for all DDK languages, {@code false} to re-enable it + */ + public static void setGenerationDisabled(final boolean disabled) { + final Preferences node = InstanceScope.INSTANCE.getNode(QUALIFIER); + node.putBoolean(PREF_DISABLE_BUILDER_PARTICIPANTS, disabled); + try { + node.flush(); + } catch (BackingStoreException e) { + LOGGER.error("Could not persist the DDK builder participant master switch", e); //$NON-NLS-1$ + } + } + +} diff --git a/com.avaloq.tools.ddk.xtext.builder/src/com/avaloq/tools/ddk/xtext/builder/ConditionalBuilderParticipant.java b/com.avaloq.tools.ddk.xtext.builder/src/com/avaloq/tools/ddk/xtext/builder/ConditionalBuilderParticipant.java index 25eda88c9f..0473f1bb94 100644 --- a/com.avaloq.tools.ddk.xtext.builder/src/com/avaloq/tools/ddk/xtext/builder/ConditionalBuilderParticipant.java +++ b/com.avaloq.tools.ddk.xtext.builder/src/com/avaloq/tools/ddk/xtext/builder/ConditionalBuilderParticipant.java @@ -10,6 +10,8 @@ *******************************************************************************/ package com.avaloq.tools.ddk.xtext.builder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.xtext.builder.BuilderParticipant; import org.eclipse.xtext.resource.IResourceDescription.Delta; import org.eclipse.xtext.resource.IResourceServiceProvider; @@ -22,6 +24,29 @@ public class ConditionalBuilderParticipant extends BuilderParticipant { private static final String GENERATION_FILE_SRC_DIRECTORY = "src"; //$NON-NLS-1$ + @Override + public void build(final IBuildContext context, final IProgressMonitor monitor) throws CoreException { + if (!isBuilderParticipantEnabled() && context.getBuildType() != BuildType.CLEAN) { + return; + } + super.build(context, monitor); + } + + /** + * Determines whether DDK builder participants should regenerate their artifacts on workspace builds. Disabled workspace-wide for all DDK languages at once by + * the master switch on the languages' Compiler preference pages (see {@link BuilderParticipantSettings}); enabled by default. + *
+ * Note that the switch governs every {@code ConditionalBuilderParticipant} descendant that delegates to {@code super.build(...)} — including participants of + * downstream languages built on this class. Subclasses overriding {@link #build(IBuildContext, IProgressMonitor)} without delegating to {@code super} must + * check this method themselves to be covered by the switch. Explicit {@code CLEAN} builds are exempt from the gate: while the switch disables regeneration, a + * Project > Clean still deletes the generated artifacts (which then stay deleted until the switch is re-enabled). + * + * @return {@code true} if generation should run, {@code false} if the DDK-wide master switch disables it + */ + protected boolean isBuilderParticipantEnabled() { + return !BuilderParticipantSettings.isGenerationDisabled(); + } + /** * Checks whether {@link BuilderParticipant} should run for a given {@link Delta} and it has no errors. * diff --git a/com.avaloq.tools.ddk.xtext.export.ui/META-INF/MANIFEST.MF b/com.avaloq.tools.ddk.xtext.export.ui/META-INF/MANIFEST.MF index bf63d35ad2..cab72d97ff 100644 --- a/com.avaloq.tools.ddk.xtext.export.ui/META-INF/MANIFEST.MF +++ b/com.avaloq.tools.ddk.xtext.export.ui/META-INF/MANIFEST.MF @@ -13,6 +13,7 @@ Require-Bundle: org.eclipse.xtext.ui, org.eclipse.ui.editors, org.eclipse.ui, org.eclipse.xtext.builder, + com.avaloq.tools.ddk.xtext.builder, org.antlr.runtime, com.avaloq.tools.ddk.xtext.expression.ui, com.avaloq.tools.ddk.xtext.export, diff --git a/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/ExportUiModule.java b/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/ExportUiModule.java index 4137aa58bd..e827b12dc5 100644 --- a/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/ExportUiModule.java +++ b/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/ExportUiModule.java @@ -11,9 +11,13 @@ package com.avaloq.tools.ddk.xtext.export.ui; import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.eclipse.xtext.builder.IXtextBuilderParticipant; +import org.eclipse.xtext.builder.preferences.BuilderConfigurationBlock; import org.eclipse.xtext.ui.editor.outline.impl.OutlineFilterAndSorter.IComparator; import org.eclipse.xtext.ui.editor.templates.CrossReferenceTemplateVariableResolver; +import com.avaloq.tools.ddk.xtext.export.ui.builder.ExportBuilderConfigurationBlock; +import com.avaloq.tools.ddk.xtext.export.ui.builder.ExportBuilderParticipant; import com.avaloq.tools.ddk.xtext.export.ui.outline.ExportOutlineNodeComparator; import com.avaloq.tools.ddk.xtext.ui.templates.KeywordAwareCrossReferenceTemplateVariableResolver; @@ -21,6 +25,7 @@ /** * Use this class to register components to be used within the IDE. */ +@SuppressWarnings("restriction") public class ExportUiModule extends com.avaloq.tools.ddk.xtext.export.ui.AbstractExportUiModule { public ExportUiModule(final AbstractUIPlugin plugin) { super(plugin); @@ -41,4 +46,23 @@ public Class extends CrossReferenceTemplateVariableResolver> bindCrossReferenc // CHECKSTYLE:ON return ExportOutlineNodeComparator.class; } + + /** + * Binds the Export builder participant, which honors the per-language preference allowing regeneration to be disabled on a workspace build. + * + * @return the {@link ExportBuilderParticipant} class + */ + @Override + public Class extends IXtextBuilderParticipant> bindIXtextBuilderParticipant() { + return ExportBuilderParticipant.class; + } + + /** + * Binds the Export builder configuration block, which contributes the "disable the builder participant on workspace build" checkbox to the Compiler page. + * + * @return the {@link ExportBuilderConfigurationBlock} class + */ + public Class extends BuilderConfigurationBlock> bindBuilderConfigurationBlock() { + return ExportBuilderConfigurationBlock.class; + } } diff --git a/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/builder/ExportBuilderConfigurationBlock.java b/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/builder/ExportBuilderConfigurationBlock.java new file mode 100644 index 0000000000..a9dd686fdb --- /dev/null +++ b/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/builder/ExportBuilderConfigurationBlock.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2026 Avaloq Group AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Avaloq Group AG - initial API and implementation + *******************************************************************************/ +package com.avaloq.tools.ddk.xtext.export.ui.builder; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.xtext.builder.preferences.BuilderConfigurationBlock; + +import com.avaloq.tools.ddk.xtext.ui.BuilderParticipantMasterSwitch; + + +/** + * UI for configuring the Export compiler. Adds the workspace-wide DDK generation master switch on top of the stock options. + */ +@SuppressWarnings("restriction") +public class ExportBuilderConfigurationBlock extends BuilderConfigurationBlock { + + private BuilderParticipantMasterSwitch masterSwitch; + + @Override + protected Control doCreateContents(final Composite parent) { + if (getProject() != null) { + return super.doCreateContents(parent); // project property page: the master switch is workspace-wide only + } + masterSwitch = new BuilderParticipantMasterSwitch(parent, super::doCreateContents); + return masterSwitch.getControl(); + } + + @Override + public boolean performOk() { + final boolean rebuildRequired = masterSwitch != null && masterSwitch.save(); + final boolean result = super.performOk(); + if (rebuildRequired) { + getBuildJob(getProject()).schedule(); // re-enabling generation: rebuild to catch up on changes made while it was off + } + return result; + } + + @Override + public void performDefaults() { + if (masterSwitch != null) { + masterSwitch.restoreDefaults(); + } + super.performDefaults(); + } + +} diff --git a/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/builder/ExportBuilderParticipant.java b/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/builder/ExportBuilderParticipant.java new file mode 100644 index 0000000000..17e18ef82b --- /dev/null +++ b/com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/builder/ExportBuilderParticipant.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2026 Avaloq Group AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Avaloq Group AG - initial API and implementation + *******************************************************************************/ +package com.avaloq.tools.ddk.xtext.export.ui.builder; + +import com.avaloq.tools.ddk.xtext.builder.ConditionalBuilderParticipant; + + +/** + * A builder participant for the Export language. Honors the workspace-wide DDK master switch that disables regeneration of the generated artifacts on workspace + * builds (see {@link ConditionalBuilderParticipant#isBuilderParticipantEnabled()}). + */ +public class ExportBuilderParticipant extends ConditionalBuilderParticipant { + +} diff --git a/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/FormatUiModule.java b/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/FormatUiModule.java index 95820e4280..bf474dd811 100644 --- a/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/FormatUiModule.java +++ b/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/FormatUiModule.java @@ -12,11 +12,13 @@ import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.xtext.builder.IXtextBuilderParticipant; +import org.eclipse.xtext.builder.preferences.BuilderConfigurationBlock; import org.eclipse.xtext.ui.editor.hyperlinking.IHyperlinkHelper; import org.eclipse.xtext.ui.editor.templates.CrossReferenceTemplateVariableResolver; import org.eclipse.xtext.xtext.generator.model.project.IXtextProjectConfig; import org.eclipse.xtext.xtext.generator.model.project.XtextProjectConfig; +import com.avaloq.tools.ddk.xtext.format.ui.builder.FormatBuilderConfigurationBlock; import com.avaloq.tools.ddk.xtext.format.ui.builder.FormatBuilderParticipant; import com.avaloq.tools.ddk.xtext.format.ui.hyperlinking.FormatHyperlinkHelper; import com.avaloq.tools.ddk.xtext.ui.templates.KeywordAwareCrossReferenceTemplateVariableResolver; @@ -25,6 +27,7 @@ /** * Use this class to register components to be used within the Eclipse IDE. */ +@SuppressWarnings("restriction") public class FormatUiModule extends AbstractFormatUiModule { public FormatUiModule(final AbstractUIPlugin plugin) { @@ -55,6 +58,17 @@ public Class extends IXtextBuilderParticipant> bindIXtextBuilderParticipant() return FormatBuilderParticipant.class; } + /** + * Binds the Format-specific builder configuration block, which contributes the "disable the builder participant on workspace build" checkbox to the Compiler + * page. + * + * @return the Format builder configuration block + */ + @Override + public Class extends BuilderConfigurationBlock> bindBuilderConfigurationBlock() { + return FormatBuilderConfigurationBlock.class; + } + @Override public void configure(final Binder binder) { super.configure(binder); diff --git a/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/builder/FormatBuilderConfigurationBlock.java b/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/builder/FormatBuilderConfigurationBlock.java new file mode 100644 index 0000000000..e944ab1ef0 --- /dev/null +++ b/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/builder/FormatBuilderConfigurationBlock.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2026 Avaloq Group AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Avaloq Group AG - initial API and implementation + *******************************************************************************/ + +package com.avaloq.tools.ddk.xtext.format.ui.builder; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.xtext.xbase.ui.builder.XbaseBuilderConfigurationBlock; + +import com.avaloq.tools.ddk.xtext.ui.BuilderParticipantMasterSwitch; + + +/** + * UI for configuring the Format compiler. Adds the workspace-wide DDK generation master switch on top of the stock options. + */ +@SuppressWarnings("restriction") +public class FormatBuilderConfigurationBlock extends XbaseBuilderConfigurationBlock { + + private BuilderParticipantMasterSwitch masterSwitch; + + @Override + protected Control doCreateContents(final Composite parent) { + if (getProject() != null) { + return super.doCreateContents(parent); // project property page: the master switch is workspace-wide only + } + masterSwitch = new BuilderParticipantMasterSwitch(parent, super::doCreateContents); + return masterSwitch.getControl(); + } + + @Override + public boolean performOk() { + final boolean rebuildRequired = masterSwitch != null && masterSwitch.save(); + final boolean result = super.performOk(); + if (rebuildRequired) { + getBuildJob(getProject()).schedule(); // re-enabling generation: rebuild to catch up on changes made while it was off + } + return result; + } + + @Override + public void performDefaults() { + if (masterSwitch != null) { + masterSwitch.restoreDefaults(); + } + super.performDefaults(); + } + +} diff --git a/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/builder/FormatBuilderParticipant.java b/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/builder/FormatBuilderParticipant.java index 69ab1a63a0..833e062e5b 100644 --- a/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/builder/FormatBuilderParticipant.java +++ b/com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/builder/FormatBuilderParticipant.java @@ -36,6 +36,9 @@ public class FormatBuilderParticipant extends ConditionalBuilderParticipant { @Override public void build(final IBuildContext context, final IProgressMonitor monitor) throws CoreException { + if (!isBuilderParticipantEnabled() && context.getBuildType() != BuildType.CLEAN) { + return; + } if (!isEnabled(context)) { return; } diff --git a/com.avaloq.tools.ddk.xtext.scope.ui/META-INF/MANIFEST.MF b/com.avaloq.tools.ddk.xtext.scope.ui/META-INF/MANIFEST.MF index e77d8a35ed..e51340f9e8 100644 --- a/com.avaloq.tools.ddk.xtext.scope.ui/META-INF/MANIFEST.MF +++ b/com.avaloq.tools.ddk.xtext.scope.ui/META-INF/MANIFEST.MF @@ -12,6 +12,7 @@ Require-Bundle: org.eclipse.xtext.ui, org.eclipse.ui.editors, org.eclipse.ui, org.eclipse.xtext.builder, + com.avaloq.tools.ddk.xtext.builder, org.antlr.runtime, com.avaloq.tools.ddk.xtext.expression.ui, com.avaloq.tools.ddk.xtext.scope, diff --git a/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/ScopeUiModule.java b/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/ScopeUiModule.java index 6f5cf74333..effa109454 100644 --- a/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/ScopeUiModule.java +++ b/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/ScopeUiModule.java @@ -11,14 +11,19 @@ package com.avaloq.tools.ddk.xtext.scope.ui; import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.eclipse.xtext.builder.IXtextBuilderParticipant; +import org.eclipse.xtext.builder.preferences.BuilderConfigurationBlock; import org.eclipse.xtext.ui.editor.templates.CrossReferenceTemplateVariableResolver; +import com.avaloq.tools.ddk.xtext.scope.ui.builder.ScopeBuilderConfigurationBlock; +import com.avaloq.tools.ddk.xtext.scope.ui.builder.ScopeBuilderParticipant; import com.avaloq.tools.ddk.xtext.ui.templates.KeywordAwareCrossReferenceTemplateVariableResolver; /** * Use this class to register components to be used within the IDE. */ +@SuppressWarnings("restriction") public class ScopeUiModule extends com.avaloq.tools.ddk.xtext.scope.ui.AbstractScopeUiModule { public ScopeUiModule(final AbstractUIPlugin plugin) { super(plugin); @@ -33,4 +38,24 @@ public Class extends CrossReferenceTemplateVariableResolver> bindCrossReferenc return KeywordAwareCrossReferenceTemplateVariableResolver.class; } + /** + * Binds the Scope builder participant which honors the per-language preference controlling whether the generated artifacts are regenerated on a workspace + * build, overriding the generated {@code BuilderParticipant} binding. + * + * @return {@link ScopeBuilderParticipant} + */ + @Override + public Class extends IXtextBuilderParticipant> bindIXtextBuilderParticipant() { + return ScopeBuilderParticipant.class; + } + + /** + * Binds the configuration block contributing the Scope-specific checkbox to the "Compiler" preference page. + * + * @return {@link ScopeBuilderConfigurationBlock} + */ + public Class extends BuilderConfigurationBlock> bindBuilderConfigurationBlock() { + return ScopeBuilderConfigurationBlock.class; + } + } diff --git a/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/builder/ScopeBuilderConfigurationBlock.java b/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/builder/ScopeBuilderConfigurationBlock.java new file mode 100644 index 0000000000..eb7a4dbe56 --- /dev/null +++ b/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/builder/ScopeBuilderConfigurationBlock.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2026 Avaloq Group AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Avaloq Group AG - initial API and implementation + *******************************************************************************/ +package com.avaloq.tools.ddk.xtext.scope.ui.builder; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.xtext.builder.preferences.BuilderConfigurationBlock; + +import com.avaloq.tools.ddk.xtext.ui.BuilderParticipantMasterSwitch; + + +/** + * UI for configuring the Scope compiler. Adds the workspace-wide DDK generation master switch on top of the stock options. + */ +@SuppressWarnings("restriction") +public class ScopeBuilderConfigurationBlock extends BuilderConfigurationBlock { + + private BuilderParticipantMasterSwitch masterSwitch; + + @Override + protected Control doCreateContents(final Composite parent) { + if (getProject() != null) { + return super.doCreateContents(parent); // project property page: the master switch is workspace-wide only + } + masterSwitch = new BuilderParticipantMasterSwitch(parent, super::doCreateContents); + return masterSwitch.getControl(); + } + + @Override + public boolean performOk() { + final boolean rebuildRequired = masterSwitch != null && masterSwitch.save(); + final boolean result = super.performOk(); + if (rebuildRequired) { + getBuildJob(getProject()).schedule(); // re-enabling generation: rebuild to catch up on changes made while it was off + } + return result; + } + + @Override + public void performDefaults() { + if (masterSwitch != null) { + masterSwitch.restoreDefaults(); + } + super.performDefaults(); + } + +} diff --git a/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/builder/ScopeBuilderParticipant.java b/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/builder/ScopeBuilderParticipant.java new file mode 100644 index 0000000000..12a0829eda --- /dev/null +++ b/com.avaloq.tools.ddk.xtext.scope.ui/src/com/avaloq/tools/ddk/xtext/scope/ui/builder/ScopeBuilderParticipant.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2026 Avaloq Group AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Avaloq Group AG - initial API and implementation + *******************************************************************************/ +package com.avaloq.tools.ddk.xtext.scope.ui.builder; + +import com.avaloq.tools.ddk.xtext.builder.ConditionalBuilderParticipant; + + +/** + * A builder participant for the Scope DSL. Honors the workspace-wide DDK master switch that disables regeneration of the generated artifacts on workspace + * builds (see {@link ConditionalBuilderParticipant#isBuilderParticipantEnabled()}). + */ +public class ScopeBuilderParticipant extends ConditionalBuilderParticipant { + +} diff --git a/com.avaloq.tools.ddk.xtext.ui/META-INF/MANIFEST.MF b/com.avaloq.tools.ddk.xtext.ui/META-INF/MANIFEST.MF index c3f5284384..0e84fb5bb0 100644 --- a/com.avaloq.tools.ddk.xtext.ui/META-INF/MANIFEST.MF +++ b/com.avaloq.tools.ddk.xtext.ui/META-INF/MANIFEST.MF @@ -17,6 +17,7 @@ Require-Bundle: com.avaloq.tools.ddk.xtext, com.avaloq.tools.ddk.check.runtime.ui;visibility:=reexport, com.google.guava, com.avaloq.tools.ddk.xtext.ide, + com.avaloq.tools.ddk.xtext.builder, com.avaloq.tools.ddk Import-Package: org.apache.logging.log4j, org.apache.logging.log4j.util diff --git a/com.avaloq.tools.ddk.xtext.ui/src/com/avaloq/tools/ddk/xtext/ui/BuilderParticipantMasterSwitch.java b/com.avaloq.tools.ddk.xtext.ui/src/com/avaloq/tools/ddk/xtext/ui/BuilderParticipantMasterSwitch.java new file mode 100644 index 0000000000..d362c3ff75 --- /dev/null +++ b/com.avaloq.tools.ddk.xtext.ui/src/com/avaloq/tools/ddk/xtext/ui/BuilderParticipantMasterSwitch.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2026 Avaloq Group AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Avaloq Group AG - initial API and implementation + *******************************************************************************/ +package com.avaloq.tools.ddk.xtext.ui; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Function; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +import com.avaloq.tools.ddk.xtext.builder.BuilderParticipantSettings; + + +/** + * Adds the workspace-wide "disable DDK code generation" master switch on top of a DDK language's Compiler preference page content. The switch is one shared + * preference for all DDK languages (see {@link BuilderParticipantSettings}), surfaced identically on the Check, Scope, Export and Format Compiler pages. All + * live instances mirror each other instantly (before Apply): toggling the switch on one page updates it on every other open page, so the four checkboxes always + * agree and no page can save a stale value over another page's change. Nothing is persisted until the dialog applies; Cancel discards the pending state. + *
+ * While active, the per-language options below the switch are grayed out: they keep their values but have no effect, because the builder participants skip
+ * generation altogether. Each control's own enablement is captured before graying out and restored afterwards, so options the stock page keeps disabled (e.g.
+ * controls dependent on an unchecked option) are not force-enabled. When the switch is untouched, the stock page enablement is never modified.
+ */
+public final class BuilderParticipantMasterSwitch {
+
+ /** Live instances within the preference dialog; used to mirror the pending (unsaved) state across the DDK languages' pages. */
+ private static final List