--- name: mps-aspect-intentions description: Use when defining or editing MPS intentions (the Alt+Enter context-action aspect) — adding `IntentionDeclaration` roots, parameterized or surround-with variants, description/isApplicable/execute blocks, child-filter functions, factory-initialized AST splicing, or debugging why an intention is not offered. Lives in the language's `intentions` model and uses `jetbrains.mps.lang.intentions`. type: reference --- # MPS Intentions Aspect ## Loading companion skills Companion names in this skill are lazy dependencies: load only those relevant to the current task. If this skill came from an MCP server, use the host's skill loader to resolve the companion's unique discovered entry URI on the same host-assigned originating server. If the host has no server-backed skill loader, stop and report that limitation; do not silently fall back to a filesystem copy. If this skill came from a filesystem catalog, load the named sibling from that same catalog at `//SKILL.md`, even if remote skill loaders are also available. Do not invent a tool name or server endpoint. Intentions are user-invoked transformations shown in the Alt+Enter popup on a node. They are the canonical way to offer optional refactorings (wrap, convert, introduce, preview) alongside quick-fixes. Authoring lives in `/languageModels/intentions.mps`, language `jetbrains.mps.lang.intentions`. ## Critical Directives - Edit intention roots through MPS MCP tools (`mps_mcp_insert_root_node_from_json`, `mps_mcp_update_node`, `mps_mcp_parse_java_and_insert`). Do not hand-edit serialized `.mps` files. - The intentions model must list every language used in any block body as a used language. In particular, the `add new initialized(...)` surface syntax requires `jetbrains.mps.lang.actions` — add it with `mps_mcp_model_used_language(kind="language")`. Plain (non-`NF_*`) variants like `parent.role.add new(C)` do not need this import. - Use `n as C` (MPS `SNodeTypeCastExpression` with `asCast=true`) — never a Java `(C) n` cast. - Use `:eq:` (`NPEEqualsExpression`) instead of `==` whenever either operand might be `null`. - The execute body runs on the EDT inside an MPS write action automatically — do not spawn threads or open dialogs that block. - `descriptionFunction` runs every time the Alt+Enter popup opens — keep it cheap. - After editing, validate with `mps_mcp_check_root_node_problems` on the intention root and rebuild the language before testing. ## Common-Path Workflow 1. Ensure an `intentions` model exists in the language (create with `mps_mcp_create_model`, passing `moduleName: ""` and `modelName: ".intentions"` — aspect ID `intentions`, case-sensitive, no `@` suffix; see [aspect-model-stereotypes.md](references/aspect-model-stereotypes.md)). Used languages: `jetbrains.mps.lang.intentions`; add `jetbrains.mps.lang.actions` if you will use factory-initialized splicing. 2. Insert an `IntentionDeclaration` root with `mps_mcp_insert_root_node_from_json` (see blueprint in `references/json-blueprints.md`). Set `name`, `forConcept`, and `isAvailableInChildNodes` if the popup should bubble from descendants. 3. Fill `descriptionFunction` (returns a short label String), `executeFunction` (the transformation), and optionally `isApplicableFunction` (gate predicate) and `childFilterFunction` (per-descendant filter when `isAvailableInChildNodes=true`). 4. For multiple menu entries per blueprint use `ParameterizedIntentionDeclaration` with `paramType` + `queryFunction`; use `IntentionParameter` wherever you want "the current value" inside other blocks. 5. For wrap-the-selection transforms use `SurroundWithIntentionDeclaration` and read `editorContext.getSelectedNodes()`. 6. Validate (`mps_mcp_check_root_node_problems`), rebuild the language, exercise via Alt+Enter on a sandbox instance. Headlessly: after MAKE, call `mps_mcp_list_node_intentions` on a sandbox node to confirm the intention is registered and shows the expected description, then `mps_mcp_apply_intention(nodeReference = , intentionId = )` to smoke-test `executeFunction` (for parameterized declarations also pass the row `description`). Surround-with intentions are not covered by these tools. ## Implicit parameters available in every block | Alias | FQN | Where | |---|---|---| | `node` | `jetbrains.mps.lang.intentions.structure.ConceptFunctionParameter_node` | All blocks; typed as `forConcept`. In `ChildFilterFunction` this is the nearest enclosing `forConcept` ancestor. | | `editorContext` | `jetbrains.mps.lang.sharedConcepts.structure.ConceptFunctionParameter_editorContext` | All blocks; the current `EditorContext`. | | `childNode` | `jetbrains.mps.lang.intentions.structure.ConceptFunctionParameter_childNode` | Only inside `ChildFilterFunction`; the descendant under the cursor. | | `parameter` (`IntentionParameter`) | `jetbrains.mps.lang.intentions.structure.IntentionParameter` | Only inside `ParameterizedIntentionDeclaration` blocks; resolves to the current queried value. | ## Related Skills - `mps-aspect-actions` — when the intention needs factory-initialized children, the NodeFactories live there. - `mps-aspect-constraints` — for gating that should apply everywhere (not just Alt+Enter), prefer can-be rules over `isApplicable`. - `mps-aspect-editor-menus-and-keymaps` — when the action belongs on a substitute/transformation menu or a keystroke, not in the Alt+Enter popup. - `mps-model-manipulation` — full smodel/baseLanguage reference; covers the `NF_*` family. For an `executeFunction` body — the AST edit itself — open only `references/property-and-mutation-ops.md` in the `mps-model-manipulation` skill root after loading that companion skill from the same origin. - `mps-collections-and-closures` — collections / closures reference; covers the dual `IsEmptyOperation` and closure literals in `isApplicable` / `execute` bodies. - `mps-node-editing` — MCP recipes for inserting children, updating references, and staged construction. - `mps-aspect-structure-concepts` — when adding the concept that `forConcept` targets. - `mps-quotations` — when the execute body builds a complex subtree literal. - `mps-tests` → `EditorTestCase` — for testing that an intention is offered and produces the expected tree. ## Reference Index **Start here — most common case**: one plain intention (description / isApplicable / execute) → read only `references/blocks-and-parameters.md`, plus `references/json-blueprints.md` when inserting the root through MCP; the execute body's AST edits → only `references/execute-idioms.md`; the intention never shows up → only `references/common-failures.md`. - Open `references/blocks-and-parameters.md` when wiring `descriptionFunction`, `isApplicableFunction`, `executeFunction`, or `childFilterFunction`, or when you need to look up the implicit parameter concept FQNs for any of them. - Open `references/execute-idioms.md` when writing an `executeFunction` body — typical AST-editing operations (insert sibling, isInstanceOf, asCast, list add, select-in-editor), the verbatim `WrapInParens` and `AddOnEntry` examples, the attach-an-annotation (node attribute) idiom (`forConcept = BaseConcept` + context-gated `isApplicable`, `.@role.add(...)` vs `.@Mark = ...`), and the `SelectInEditorOperation` JSON shape live there. - Open `references/factory-initialized.md` when an `executeFunction` allocates new nodes and you want the concept's NodeFactory to seed defaults — the `NF_*` family table, the `add new initialized()` semantics, and the used-language requirement live there. - Open `references/parameterized-intentions.md` when authoring or debugging a `ParameterizedIntentionDeclaration` — `paramType` + `queryFunction` semantics, `IntentionParameter` usage, the per-value `isApplicableFunction` filter, and the full `SetCardinalityTo` example and JSON skeleton are there. - Open `references/surround-and-child-filter.md` when authoring a `SurroundWithIntentionDeclaration` or when configuring `isAvailableInChildNodes` + a `ChildFilterFunction` — verbatim `WrapInParens` and `AddOnEntry.childFilterFunction` walk-throughs are there. - Open `references/json-blueprints.md` when inserting an intention root via `mps_mcp_insert_root_node_from_json` — minimal blueprints for `IntentionDeclaration`, `ParameterizedIntentionDeclaration`, and `SurroundWithIntentionDeclaration` and the validated concept-reference table. - Open `references/common-failures.md` when an intention does not appear, fires on the wrong node, leaves the caret in the wrong place, or shows duplicates — the symptom/cause/fix table is there.