Skip to content

Commit 2badd65

Browse files
joaodinissfclaude
andcommitted
feat(builder): workspace-wide master switch to disable DDK code generation
Add a single shared preference (node com.avaloq.tools.ddk, key disableBuilderParticipants, default: generation enabled) that disables code generation by the builder participants of all DDK languages at once. - ConditionalBuilderParticipant gates build() on the switch; the Check and Format participants check it at the top of their custom build() overrides, and Scope/Export now bind ConditionalBuilderParticipant subclasses in place of the stock BuilderParticipant so they are covered too. - Each language's Compiler preference page shows the same master checkbox (BuilderParticipantMasterSwitch): live page instances mirror the pending state instantly, nothing persists before Apply, and while active the per-language options are grayed out with their prior enablement captured and restored, leaving stock dependency-driven enablement intact. - Re-enabling generation via Apply/OK schedules a full rebuild so generated artifacts catch up on changes made while the switch was off. - Explicit CLEAN builds are exempt from the gate: Project > Clean still deletes generated artifacts while the switch is on (they stay deleted until regeneration is re-enabled). - The disable polarity means the native boolean default (false = enabled) holds in every context without a preference initializer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 5b71cc1 commit 2badd65

17 files changed

Lines changed: 559 additions & 1 deletion

File tree

com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderConfigurationBlock.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,51 @@
1212
package com.avaloq.tools.ddk.check.ui.builder;
1313

1414
import org.eclipse.swt.widgets.Composite;
15+
import org.eclipse.swt.widgets.Control;
1516
import org.eclipse.xtext.xbase.ui.builder.XbaseBuilderConfigurationBlock;
1617

18+
import com.avaloq.tools.ddk.xtext.ui.BuilderParticipantMasterSwitch;
19+
1720

1821
/**
19-
* UI for configuring Check compiler.
22+
* UI for configuring Check compiler. Adds the workspace-wide DDK generation master switch on top of the stock options.
2023
*/
2124
@SuppressWarnings("restriction")
2225
public class CheckBuilderConfigurationBlock extends XbaseBuilderConfigurationBlock {
2326

27+
private BuilderParticipantMasterSwitch masterSwitch;
28+
29+
@Override
30+
protected Control doCreateContents(final Composite parent) {
31+
if (getProject() != null) {
32+
return super.doCreateContents(parent); // project property page: the master switch is workspace-wide only
33+
}
34+
masterSwitch = new BuilderParticipantMasterSwitch(parent, super::doCreateContents);
35+
return masterSwitch.getControl();
36+
}
37+
2438
@Override
2539
protected void createGeneralSectionItems(final Composite composite) {
2640
super.createGeneralSectionItems(composite);
2741
addCheckBox(composite, "Generate as DSL internal checks (not SCA plugin)", CheckBuilderPreferenceAccess.PREF_GENERATE_LANGUAGE_INTERNAL_CHECKS, BOOLEAN_VALUES, 0); //$NON-NLS-1$
2842
}
2943

44+
@Override
45+
public boolean performOk() {
46+
final boolean rebuildRequired = masterSwitch != null && masterSwitch.save();
47+
final boolean result = super.performOk();
48+
if (rebuildRequired) {
49+
getBuildJob(getProject()).schedule(); // re-enabling generation: rebuild to catch up on changes made while it was off
50+
}
51+
return result;
52+
}
53+
54+
@Override
55+
public void performDefaults() {
56+
if (masterSwitch != null) {
57+
masterSwitch.restoreDefaults();
58+
}
59+
super.performDefaults();
60+
}
61+
3062
}

com.avaloq.tools.ddk.check.ui/src/com/avaloq/tools/ddk/check/ui/builder/CheckBuilderParticipant.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public class CheckBuilderParticipant extends ConditionalBuilderParticipant {
6060

6161
@Override
6262
public void build(final IBuildContext context, final IProgressMonitor monitor) throws CoreException {
63+
if (!isBuilderParticipantEnabled() && context.getBuildType() != BuildType.CLEAN) {
64+
return;
65+
}
6366
if (!isEnabled(context)) {
6467
return;
6568
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Avaloq Group AG and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Avaloq Group AG - initial API and implementation
10+
*******************************************************************************/
11+
package com.avaloq.tools.ddk.xtext.builder;
12+
13+
import org.apache.logging.log4j.LogManager;
14+
import org.apache.logging.log4j.Logger;
15+
import org.eclipse.core.runtime.preferences.InstanceScope;
16+
import org.osgi.service.prefs.BackingStoreException;
17+
import org.osgi.service.prefs.Preferences;
18+
19+
20+
/**
21+
* 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
22+
* 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
23+
* preference page. As a plain boolean preference it defaults to {@code false} (generation enabled), so behavior is unchanged unless a user opts in.
24+
*/
25+
public final class BuilderParticipantSettings {
26+
27+
/** Preference node shared by all DDK languages. */
28+
public static final String QUALIFIER = "com.avaloq.tools.ddk"; //$NON-NLS-1$
29+
30+
/** Boolean preference key; {@code true} disables generation by all DDK builder participants on workspace builds. */
31+
public static final String PREF_DISABLE_BUILDER_PARTICIPANTS = "disableBuilderParticipants"; //$NON-NLS-1$
32+
33+
private static final Logger LOGGER = LogManager.getLogger(BuilderParticipantSettings.class);
34+
35+
private BuilderParticipantSettings() {
36+
// static utility
37+
}
38+
39+
/**
40+
* Returns whether generation by the DDK builder participants is disabled workspace-wide.
41+
*
42+
* @return {@code true} if the master switch disables generation, {@code false} otherwise (the default)
43+
*/
44+
public static boolean isGenerationDisabled() {
45+
return InstanceScope.INSTANCE.getNode(QUALIFIER).getBoolean(PREF_DISABLE_BUILDER_PARTICIPANTS, false);
46+
}
47+
48+
/**
49+
* Sets whether generation by the DDK builder participants is disabled workspace-wide.
50+
*
51+
* @param disabled
52+
* {@code true} to disable generation for all DDK languages, {@code false} to re-enable it
53+
*/
54+
public static void setGenerationDisabled(final boolean disabled) {
55+
final Preferences node = InstanceScope.INSTANCE.getNode(QUALIFIER);
56+
node.putBoolean(PREF_DISABLE_BUILDER_PARTICIPANTS, disabled);
57+
try {
58+
node.flush();
59+
} catch (BackingStoreException e) {
60+
LOGGER.error("Could not persist the DDK builder participant master switch", e); //$NON-NLS-1$
61+
}
62+
}
63+
64+
}

com.avaloq.tools.ddk.xtext.builder/src/com/avaloq/tools/ddk/xtext/builder/ConditionalBuilderParticipant.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
*******************************************************************************/
1111
package com.avaloq.tools.ddk.xtext.builder;
1212

13+
import org.eclipse.core.runtime.CoreException;
14+
import org.eclipse.core.runtime.IProgressMonitor;
1315
import org.eclipse.xtext.builder.BuilderParticipant;
1416
import org.eclipse.xtext.resource.IResourceDescription.Delta;
1517
import org.eclipse.xtext.resource.IResourceServiceProvider;
@@ -22,6 +24,29 @@ public class ConditionalBuilderParticipant extends BuilderParticipant {
2224

2325
private static final String GENERATION_FILE_SRC_DIRECTORY = "src"; //$NON-NLS-1$
2426

27+
@Override
28+
public void build(final IBuildContext context, final IProgressMonitor monitor) throws CoreException {
29+
if (!isBuilderParticipantEnabled() && context.getBuildType() != BuildType.CLEAN) {
30+
return;
31+
}
32+
super.build(context, monitor);
33+
}
34+
35+
/**
36+
* Determines whether DDK builder participants should regenerate their artifacts on workspace builds. Disabled workspace-wide for all DDK languages at once by
37+
* the master switch on the languages' Compiler preference pages (see {@link BuilderParticipantSettings}); enabled by default.
38+
* <p>
39+
* Note that the switch governs every {@code ConditionalBuilderParticipant} descendant that delegates to {@code super.build(...)} — including participants of
40+
* downstream languages built on this class. Subclasses overriding {@link #build(IBuildContext, IProgressMonitor)} without delegating to {@code super} must
41+
* 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
42+
* Project &gt; Clean still deletes the generated artifacts (which then stay deleted until the switch is re-enabled).
43+
*
44+
* @return {@code true} if generation should run, {@code false} if the DDK-wide master switch disables it
45+
*/
46+
protected boolean isBuilderParticipantEnabled() {
47+
return !BuilderParticipantSettings.isGenerationDisabled();
48+
}
49+
2550
/**
2651
* Checks whether {@link BuilderParticipant} should run for a given {@link Delta} and it has no errors.
2752
*

com.avaloq.tools.ddk.xtext.export.ui/META-INF/MANIFEST.MF

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Require-Bundle: org.eclipse.xtext.ui,
1313
org.eclipse.ui.editors,
1414
org.eclipse.ui,
1515
org.eclipse.xtext.builder,
16+
com.avaloq.tools.ddk.xtext.builder,
1617
org.antlr.runtime,
1718
com.avaloq.tools.ddk.xtext.expression.ui,
1819
com.avaloq.tools.ddk.xtext.export,

com.avaloq.tools.ddk.xtext.export.ui/src/com/avaloq/tools/ddk/xtext/export/ui/ExportUiModule.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,21 @@
1111
package com.avaloq.tools.ddk.xtext.export.ui;
1212

1313
import org.eclipse.ui.plugin.AbstractUIPlugin;
14+
import org.eclipse.xtext.builder.IXtextBuilderParticipant;
15+
import org.eclipse.xtext.builder.preferences.BuilderConfigurationBlock;
1416
import org.eclipse.xtext.ui.editor.outline.impl.OutlineFilterAndSorter.IComparator;
1517
import org.eclipse.xtext.ui.editor.templates.CrossReferenceTemplateVariableResolver;
1618

19+
import com.avaloq.tools.ddk.xtext.export.ui.builder.ExportBuilderConfigurationBlock;
20+
import com.avaloq.tools.ddk.xtext.export.ui.builder.ExportBuilderParticipant;
1721
import com.avaloq.tools.ddk.xtext.export.ui.outline.ExportOutlineNodeComparator;
1822
import com.avaloq.tools.ddk.xtext.ui.templates.KeywordAwareCrossReferenceTemplateVariableResolver;
1923

2024

2125
/**
2226
* Use this class to register components to be used within the IDE.
2327
*/
28+
@SuppressWarnings("restriction")
2429
public class ExportUiModule extends com.avaloq.tools.ddk.xtext.export.ui.AbstractExportUiModule {
2530
public ExportUiModule(final AbstractUIPlugin plugin) {
2631
super(plugin);
@@ -41,4 +46,23 @@ public Class<? extends CrossReferenceTemplateVariableResolver> bindCrossReferenc
4146
// CHECKSTYLE:ON
4247
return ExportOutlineNodeComparator.class;
4348
}
49+
50+
/**
51+
* Binds the Export builder participant, which honors the per-language preference allowing regeneration to be disabled on a workspace build.
52+
*
53+
* @return the {@link ExportBuilderParticipant} class
54+
*/
55+
@Override
56+
public Class<? extends IXtextBuilderParticipant> bindIXtextBuilderParticipant() {
57+
return ExportBuilderParticipant.class;
58+
}
59+
60+
/**
61+
* Binds the Export builder configuration block, which contributes the "disable the builder participant on workspace build" checkbox to the Compiler page.
62+
*
63+
* @return the {@link ExportBuilderConfigurationBlock} class
64+
*/
65+
public Class<? extends BuilderConfigurationBlock> bindBuilderConfigurationBlock() {
66+
return ExportBuilderConfigurationBlock.class;
67+
}
4468
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Avaloq Group AG and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Avaloq Group AG - initial API and implementation
10+
*******************************************************************************/
11+
package com.avaloq.tools.ddk.xtext.export.ui.builder;
12+
13+
import org.eclipse.swt.widgets.Composite;
14+
import org.eclipse.swt.widgets.Control;
15+
import org.eclipse.xtext.builder.preferences.BuilderConfigurationBlock;
16+
17+
import com.avaloq.tools.ddk.xtext.ui.BuilderParticipantMasterSwitch;
18+
19+
20+
/**
21+
* UI for configuring the Export compiler. Adds the workspace-wide DDK generation master switch on top of the stock options.
22+
*/
23+
@SuppressWarnings("restriction")
24+
public class ExportBuilderConfigurationBlock extends BuilderConfigurationBlock {
25+
26+
private BuilderParticipantMasterSwitch masterSwitch;
27+
28+
@Override
29+
protected Control doCreateContents(final Composite parent) {
30+
if (getProject() != null) {
31+
return super.doCreateContents(parent); // project property page: the master switch is workspace-wide only
32+
}
33+
masterSwitch = new BuilderParticipantMasterSwitch(parent, super::doCreateContents);
34+
return masterSwitch.getControl();
35+
}
36+
37+
@Override
38+
public boolean performOk() {
39+
final boolean rebuildRequired = masterSwitch != null && masterSwitch.save();
40+
final boolean result = super.performOk();
41+
if (rebuildRequired) {
42+
getBuildJob(getProject()).schedule(); // re-enabling generation: rebuild to catch up on changes made while it was off
43+
}
44+
return result;
45+
}
46+
47+
@Override
48+
public void performDefaults() {
49+
if (masterSwitch != null) {
50+
masterSwitch.restoreDefaults();
51+
}
52+
super.performDefaults();
53+
}
54+
55+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Avaloq Group AG and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Avaloq Group AG - initial API and implementation
10+
*******************************************************************************/
11+
package com.avaloq.tools.ddk.xtext.export.ui.builder;
12+
13+
import com.avaloq.tools.ddk.xtext.builder.ConditionalBuilderParticipant;
14+
15+
16+
/**
17+
* A builder participant for the Export language. Honors the workspace-wide DDK master switch that disables regeneration of the generated artifacts on workspace
18+
* builds (see {@link ConditionalBuilderParticipant#isBuilderParticipantEnabled()}).
19+
*/
20+
public class ExportBuilderParticipant extends ConditionalBuilderParticipant {
21+
22+
}

com.avaloq.tools.ddk.xtext.format.ui/src/com/avaloq/tools/ddk/xtext/format/ui/FormatUiModule.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212

1313
import org.eclipse.ui.plugin.AbstractUIPlugin;
1414
import org.eclipse.xtext.builder.IXtextBuilderParticipant;
15+
import org.eclipse.xtext.builder.preferences.BuilderConfigurationBlock;
1516
import org.eclipse.xtext.ui.editor.hyperlinking.IHyperlinkHelper;
1617
import org.eclipse.xtext.ui.editor.templates.CrossReferenceTemplateVariableResolver;
1718
import org.eclipse.xtext.xtext.generator.model.project.IXtextProjectConfig;
1819
import org.eclipse.xtext.xtext.generator.model.project.XtextProjectConfig;
1920

21+
import com.avaloq.tools.ddk.xtext.format.ui.builder.FormatBuilderConfigurationBlock;
2022
import com.avaloq.tools.ddk.xtext.format.ui.builder.FormatBuilderParticipant;
2123
import com.avaloq.tools.ddk.xtext.format.ui.hyperlinking.FormatHyperlinkHelper;
2224
import com.avaloq.tools.ddk.xtext.ui.templates.KeywordAwareCrossReferenceTemplateVariableResolver;
@@ -25,6 +27,7 @@
2527
/**
2628
* Use this class to register components to be used within the Eclipse IDE.
2729
*/
30+
@SuppressWarnings("restriction")
2831
public class FormatUiModule extends AbstractFormatUiModule {
2932

3033
public FormatUiModule(final AbstractUIPlugin plugin) {
@@ -55,6 +58,17 @@ public Class<? extends IXtextBuilderParticipant> bindIXtextBuilderParticipant()
5558
return FormatBuilderParticipant.class;
5659
}
5760

61+
/**
62+
* Binds the Format-specific builder configuration block, which contributes the "disable the builder participant on workspace build" checkbox to the Compiler
63+
* page.
64+
*
65+
* @return the Format builder configuration block
66+
*/
67+
@Override
68+
public Class<? extends BuilderConfigurationBlock> bindBuilderConfigurationBlock() {
69+
return FormatBuilderConfigurationBlock.class;
70+
}
71+
5872
@Override
5973
public void configure(final Binder binder) {
6074
super.configure(binder);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Avaloq Group AG and others.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Avaloq Group AG - initial API and implementation
10+
*******************************************************************************/
11+
12+
package com.avaloq.tools.ddk.xtext.format.ui.builder;
13+
14+
import org.eclipse.swt.widgets.Composite;
15+
import org.eclipse.swt.widgets.Control;
16+
import org.eclipse.xtext.xbase.ui.builder.XbaseBuilderConfigurationBlock;
17+
18+
import com.avaloq.tools.ddk.xtext.ui.BuilderParticipantMasterSwitch;
19+
20+
21+
/**
22+
* UI for configuring the Format compiler. Adds the workspace-wide DDK generation master switch on top of the stock options.
23+
*/
24+
@SuppressWarnings("restriction")
25+
public class FormatBuilderConfigurationBlock extends XbaseBuilderConfigurationBlock {
26+
27+
private BuilderParticipantMasterSwitch masterSwitch;
28+
29+
@Override
30+
protected Control doCreateContents(final Composite parent) {
31+
if (getProject() != null) {
32+
return super.doCreateContents(parent); // project property page: the master switch is workspace-wide only
33+
}
34+
masterSwitch = new BuilderParticipantMasterSwitch(parent, super::doCreateContents);
35+
return masterSwitch.getControl();
36+
}
37+
38+
@Override
39+
public boolean performOk() {
40+
final boolean rebuildRequired = masterSwitch != null && masterSwitch.save();
41+
final boolean result = super.performOk();
42+
if (rebuildRequired) {
43+
getBuildJob(getProject()).schedule(); // re-enabling generation: rebuild to catch up on changes made while it was off
44+
}
45+
return result;
46+
}
47+
48+
@Override
49+
public void performDefaults() {
50+
if (masterSwitch != null) {
51+
masterSwitch.restoreDefaults();
52+
}
53+
super.performDefaults();
54+
}
55+
56+
}

0 commit comments

Comments
 (0)