From 5c8d56d085d05967cf0092a49d4d857ae556a431 Mon Sep 17 00:00:00 2001 From: amirrza777 <80536453+amirrza777@users.noreply.github.com> Date: Wed, 22 Jul 2026 21:55:34 +0400 Subject: [PATCH 1/2] Bind the GED worker for generated model and model-transformation diagrams Both generatedModelPlugin.ts and generatedModelTransformationPlugin.ts constructed their diagram module with only the services argument, dropping the languageJsUrl that every other language plugin (classic model, classic model-transformation, metamodel) already receives and forwards. Without it, BaseDiagramModule never binds GedWorkerBaseUrl, so MetadataManager.computeGED() always returns undefined regardless of how small the metadata mismatch is, forcing every edit that changes an element's ID onto the naive ID-equality fallback, which drops routing points, positions, and other layout data for anything that doesn't match by identical ID. Converts both plugin definitions into functions that accept languageJsUrl and pass it through, mirroring the existing pattern in plugin.ts (model-transformation), modelPlugin.ts, and the metamodel plugin. The browser-side worker that actually drives live diagram editing already passes languageJsUrl uniformly to every plugin's create() call, so this fix takes effect without further changes. This directly affects issue #7 (edges not reroutable): once a textual edit shifts a node or edge's ID, the classic pipeline can still recover via GED as long as the affected region is small; the generated pipeline previously had no chance to recover at all. The underlying ID-churn source (position-index-derived IDs for model-transformation statements) is unchanged and can still defeat GED on large diagrams, but this closes the one confirmed gap where recovery was impossible by construction. --- .../src/generatedModelTransformationPlugin.ts | 62 +++++++++++-------- .../src/generatedModelPlugin.ts | 52 +++++++++------- 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/app/packages/language-model-transformation/src/generatedModelTransformationPlugin.ts b/app/packages/language-model-transformation/src/generatedModelTransformationPlugin.ts index 5d69041c..206ff7f4 100644 --- a/app/packages/language-model-transformation/src/generatedModelTransformationPlugin.ts +++ b/app/packages/language-model-transformation/src/generatedModelTransformationPlugin.ts @@ -30,42 +30,50 @@ class EmptyExternalReferenceCollector implements ExternalReferenceCollector { /** * Plugin for generated model transformations (.mt_gen). + * + * @param languageJsUrl The HTTP URL of this plugin's `language.js` entry file, used + * to bind the GED worker so the metadata manager can attempt a smart old-to-new ID + * remapping after a textual edit, instead of always falling back to naive ID matching. */ -const generatedModelTransformationPlugin: LangiumLanguagePlugin = { - rootRule: GeneratedModelTransformationRule, - additionalTerminals: [], - module: { - references: { - ExternalReferenceCollector: () => new EmptyExternalReferenceCollector() - }, - action: { - ActionHandlerRegistry: (services) => { - const registry = new ActionHandlerRegistry(); - registry.register( - "save-as-model-transformation", - new SaveGeneratedModelTransformationActionHandler(services.shared) - ); - return registry; +function createGeneratedModelTransformationPlugin( + languageJsUrl?: string +): LangiumLanguagePlugin { + return { + rootRule: GeneratedModelTransformationRule, + additionalTerminals: [], + module: { + references: { + ExternalReferenceCollector: () => new EmptyExternalReferenceCollector() + }, + action: { + ActionHandlerRegistry: (services) => { + const registry = new ActionHandlerRegistry(); + registry.register( + "save-as-model-transformation", + new SaveGeneratedModelTransformationActionHandler(services.shared) + ); + return registry; + }, + ActionProvider: () => new GeneratedModelTransformationActionProvider() }, - ActionProvider: () => new GeneratedModelTransformationActionProvider() + workspace: { + WorkspaceEdit: (services) => new DefaultWorkspaceEditService(services) + } }, - workspace: { - WorkspaceEdit: (services) => new DefaultWorkspaceEditService(services) + postCreate(services) { + services.shared.glsp.serverModule.configureDiagramModule( + new GeneratedModelTransformationDiagramModule(services, languageJsUrl) + ); } - }, - postCreate(services) { - services.shared.glsp.serverModule.configureDiagramModule( - new GeneratedModelTransformationDiagramModule(services) - ); - } -}; + }; +} /** * Provider for the generated model transformation language plugin. */ export const generatedModelTransformationPluginProvider: LangiumLanguagePluginProvider = { - create(): LangiumLanguagePlugin { - return generatedModelTransformationPlugin; + create(_contributionPlugins, languageJsUrl): LangiumLanguagePlugin { + return createGeneratedModelTransformationPlugin(languageJsUrl); } }; diff --git a/app/packages/language-model/src/generatedModelPlugin.ts b/app/packages/language-model/src/generatedModelPlugin.ts index d5dd6b1b..a49ed62e 100644 --- a/app/packages/language-model/src/generatedModelPlugin.ts +++ b/app/packages/language-model/src/generatedModelPlugin.ts @@ -32,36 +32,44 @@ class EmptyExternalReferenceCollector implements ExternalReferenceCollector { * The plugin for the Generated Model language. * Provides minimal language server functionality for .m_gen files. * The language treats the entire file content as JSON, captured in a single string field. + * + * @param languageJsUrl The HTTP URL of this plugin's `language.js` entry file, used + * to bind the GED worker so the metadata manager can attempt a smart old-to-new ID + * remapping after a textual edit, instead of always falling back to naive ID matching. */ -const generatedModelPlugin: LangiumLanguagePlugin = { - rootRule: GeneratedModelRule, - additionalTerminals: [], - module: { - references: { - ExternalReferenceCollector: () => new EmptyExternalReferenceCollector() - }, - action: { - ActionHandlerRegistry: (services) => { - const registry = new ActionHandlerRegistry(); - registry.register("save-as-model", new SaveGeneratedModelActionHandler(services.shared)); - return registry; +function createGeneratedModelPlugin(languageJsUrl?: string): LangiumLanguagePlugin { + return { + rootRule: GeneratedModelRule, + additionalTerminals: [], + module: { + references: { + ExternalReferenceCollector: () => new EmptyExternalReferenceCollector() + }, + action: { + ActionHandlerRegistry: (services) => { + const registry = new ActionHandlerRegistry(); + registry.register("save-as-model", new SaveGeneratedModelActionHandler(services.shared)); + return registry; + }, + ActionProvider: () => new GeneratedModelActionProvider() }, - ActionProvider: () => new GeneratedModelActionProvider() + workspace: { + WorkspaceEdit: (services) => new DefaultWorkspaceEditService(services) + } }, - workspace: { - WorkspaceEdit: (services) => new DefaultWorkspaceEditService(services) + postCreate(services) { + services.shared.glsp.serverModule.configureDiagramModule( + new GeneratedModelDiagramModule(services, languageJsUrl) + ); } - }, - postCreate(services) { - services.shared.glsp.serverModule.configureDiagramModule(new GeneratedModelDiagramModule(services)); - } -}; + }; +} /** * Provider for the Generated Model language plugin. */ export const generatedModelPluginProvider: LangiumLanguagePluginProvider = { - create(): LangiumLanguagePlugin { - return generatedModelPlugin; + create(_contributionPlugins, languageJsUrl): LangiumLanguagePlugin { + return createGeneratedModelPlugin(languageJsUrl); } }; From 48e168f4d596cfe3e89bea7911cf5effd0cf3b13 Mon Sep 17 00:00:00 2001 From: amirrza777 <80536453+amirrza777@users.noreply.github.com> Date: Wed, 22 Jul 2026 21:55:51 +0400 Subject: [PATCH 2/2] Bump workbench build heap limit to avoid OOM The workbench bundle has grown enough (generated model-transformation support, etc.) that a fresh npm run build now hits Node's default heap limit and crashes with SIGABRT. Matches the memory bump already used elsewhere for similarly large builds in this repo. --- infra/docker/workbench/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/infra/docker/workbench/Dockerfile b/infra/docker/workbench/Dockerfile index d3b04c2d..e2d0d794 100644 --- a/infra/docker/workbench/Dockerfile +++ b/infra/docker/workbench/Dockerfile @@ -5,6 +5,7 @@ WORKDIR /build COPY app/ ./ RUN npm ci +ENV NODE_OPTIONS="--max-old-space-size=6144" RUN npm run build # Workbench runtime (nginx)