name: mps-model-manipulation
description: >-
Use when writing or editing MPS BaseLanguage code that lives inside a model — behavior methods, typesystem rules, checking rules, generator queries, constraints, intentions, scope/canBe callbacks, dataflow builders — and combines the smodel, collections, and closures language extensions. Covers querying nodes (.descendants<C>, .ancestor<C>, .children, .parent, containingRoot), filtering sequences (.where, .select, .translate, .ofConcept<C>), building closures ({ it => ... }, yield, recursion), creating and mutating nodes (new node<C>(), add new(C), set new(C), replace with new(C), .detach, .copy), property and link access (SPropertyAccess, SLinkAccess, SLinkListAccess), reference operations (.reference/C : role/, .target), null-safe node equality (:eq: / :ne:), smodel/Java type casts (node:C, node as C, /, downcast), foreach choice, the command / read action lock wrappers, and JSON blueprints for every shape the Java parser cannot produce.
type: reference
Writing MPS BaseLanguage with smodel / collections / closures
Use this skill when authoring code inside an MPS model where BaseLanguage is mixed with the smodel, collections, and closures extensions: behavior methods, checking/typesystem/dataflow rules, generator query functions, intentions, constraints, scope/canBe callbacks. The mps_mcp_parse_java_and_insert parser understands only plain Java, so most non-trivial code requires hand-built node blueprints — this skill is the catalog.
To enumerate nodes/instances/usages across a scope (a whole project, module, model, or repository) rather than navigating from one root, add the jetbrains.mps.lang.smodel.query language — it supplies #instances / #usages / #nodes / #references / #models / #modules and a with (<scope>) { … } wrapper, the same queries the MPS Console runs. Its results compose with the smodel/collections/closures operations catalogued here. See the mps-console skill.
Critical Directives
- Node equality uses
:eq:and:ne:, never==or.equals(). UseNPEEqualsExpression/NPENotEqualsExpression. Seereferences/node-equality.md. - Every
InferredClosureParameterDeclarationneeds atypechild, even though MPS infers the type. Usejetbrains.mps.baseLanguage.structure.UndefinedTypeas placeholder. Omitting it cascades into misleading "different parameter numbers" / "out of search scope" / "operation is not applicable to null" errors. Seereferences/closures-catalog.md. - The Java parser cannot produce smodel/collection types in method return types, cannot parse
:Conceptcasts,.linkaccesses,.behaviorMethod()calls, orMetaAdapterFactory.getContainmentLinkinline. UseLINKS.xxx/CONCEPTS.xxxconstants and replace types post-parse. Seereferences/java-parser-capabilities.md. - Mutations need
command { … }, reads from non-UI code needread action { … }. There is no separate "write action". Behavior methods and rule bodies already hold the right lock. Seereferences/concurrent-access.md. - Pick the right cardinality:
SLinkAccessfor0..1/1;SLinkListAccessfor0..n/1..n. One pair serves both reference links and containment children (there is noSChildAccess/SChildListAccess). Wrong choice triggers "out of search scope" / "access to link X is not expected here". Seereferences/dot-expression-basics.md. foreachhas two concepts: collectionsForEachStatementforsequence/list/set, BaseLanguageForeachStatementfor Java arrays/iterables. Wrong choice → type error. Seereferences/foreach-statements.md.- Used-language imports: NF_* operations require
jetbrains.mps.lang.actionsin the model's used languages; without it,add new initialized(...)etc. fail. Seereferences/property-and-mutation-ops.mdandreferences/openapi-and-dependencies.md. - Never recommend deprecated operations:
.role(use.containingLink),.linkDeclaration(use.link),.roleonSReference(use.link.name),.conceptNode_GetConceptOperation(usenode.conceptvia typesystem).
Common-path workflow
- Identify the source-of-truth layer. If the change is to existing logic in a rule/method body, inspect the current node (shallow
mps_mcp_print_node) before editing. - Prefer
parse_java_and_insertfor plain Java method bodies, expression replacements, and field declarations onLINKS/CONCEPTSinner classes. Seereferences/java-parser-capabilities.md. - For smodel/collections/closures constructs not parseable as Java, build the node blueprint by hand. See:
references/dot-expression-basics.md— the universalDotExpression(operand, operation)chaining pattern, closure literal blueprint, type-cast wrapping rules.references/property-and-mutation-ops.md— property reads/writes,add new(C),replace with new(C), sibling inserts.references/references-and-queries.md—.ancestor<C>,.descendants<C>,.reference/C:role/,.target,.isInstanceOf, sibling queries.references/attribute-access.md— the.@operator: read/set/remove an attribute (annotation) attached to a node and reach the children/refs/properties it grafts on (generator macros, comments, requirement traces).
- For variable declarations and method return types of MPS collection / smodel types, build the type child explicitly —
parse_java_and_insertproduces a wrongClassifierTypefor these in return-type position. Seereferences/variable-declarations.md. - Validate with
mps_mcp_check_root_node_problems(nodeReference, onlyNodesWithProblems=true). Re-read generatedsource_gen/...javaonly to confirm runtime shape — never to apply fixes. Seereferences/workflows.md. - If imports/dependencies break, add a used language or model dependency via
mps_mcp_model_used_language/mps_mcp_model_dependency/mps_mcp_module_dependency. Seereferences/openapi-and-dependencies.md.
If MPS MCP tools are unavailable, do not hand-edit serialized .mps files unless explicitly requested — inspect only and report.
Related Skills
mps-baselanguage— host BaseLanguage statements, expressions, classes; this skill is the smodel/collections/closures overlay.mps-quotations—<…>quotations and antiquotations for assembling node trees inline; use instead of long blueprint chains where they apply.mps-aspect-behavior— per-concept method authoring; behavior bodies are the most common host for this skill.mps-aspect-generator— generator query bodies,$IF$/$MAP_SRC$.mapperFunction, where this skill provides the smodel idioms.mps-aspect-typesystem— inference and checking rule bodies; uses the same idioms.mps-aspect-constraints—getScope,canBe*, property validators; same idiom set.mps-node-editing— programmatic node creation and editing from outside model code (the MCP-tool side rather than smodel-language side).mps-console— the MPS Console and thejetbrains.mps.lang.smodel.querylanguage (with-statement,#instances/#usages/#nodes/#models/#modules, scopes); use it to run or generate the smodel code in this skill across a project/repository scope, or to insert console commands viamps_mcp_insert_console_command_from_json.
Reference Index
references/golden-rules-and-pitfalls.md— read first when an error looks weird (cascadeUnknownDotCall, "out of search scope", "different parameter numbers",List<SNode>vssequence<node<X>>); collected symptom→cause→fix table.references/java-parser-capabilities.md— open before callingmps_mcp_parse_java_and_insert. Lists what the parser handles, what it silently mis-types, and the canonical workarounds (LINKS/CONCEPTS pattern, post-parsereplace_node_child, signature widening to avoid smodel casts in arguments).references/workflows.md— step-by-step recipes: adding a new helper method to a checking-rule class, replacing an expression inside a rule body, interacting withsource_gen/artifacts.references/concept-id-table.md—MetaAdapterFactoryhex IDs for BaseLanguage concepts and links (ThrowStatement,CatchClause,TryCatchStatement,VariableReference, etc.) plus persistent node refs forType,Expression,Classifier,SequenceType,ListType,SNodeType.references/smodel-concepts-catalog.md— every smodel concept (SNodeType,SLinkAccess,Node_GetAncestorOperation,OfConceptOperation,Concept_*Operation,EnumMember_*, …) with its ID and MPS surface notation. Open when you need to pick a concept and don't remember which one.references/baselanguage-key-concepts.md— the small set of BaseLanguage concepts that this skill keeps reaching for (DotExpression,ForeachStatement,BlockStatement,NPE*Expression,UndefinedType).references/concurrent-access.md—command,read action,execute command in EDT,undo-transparent command. Open when writing code that reads/mutates models outside a rule or behavior body.references/collections-catalog.md— every*Operationfromjetbrains.mps.baseLanguage.collections(where/select/translate/any/take/sortBy/reduceLeft/toList/…), the type hierarchy (sequence⊃list/set;map), creator concepts, list/set/map mutators,iteratorvsmodifying_iterator, sorted variants, lazy-vs-eager rule, and theisEmpty/isNotEmptycollections-vs-baselanguage ambiguity.references/closures-catalog.md—ClosureLiteralparameters/body shape,InferredClosureParameterDeclarationrequirements,FunctionType,InvokeFunctionOperationvsInvokeExpression(recursion),YieldStatement, SAM conversion, generated-Java compilation form, runtime jar dependency.references/dot-expression-basics.md— the universalDotExpression(operand, operation)chaining pattern; closure-literal blueprint (the reusable building block); cardinality cheat-sheet (SLinkAccessvsSLinkListAccess, one pair for both references and children); when to wrap an operand inSNodeTypeCastExpression; navigation blueprints (.link,.parent,.children,.ancestor<C>,.ancestors<C>,.descendants<C>including+include-self form);node:Cvsnode as C;expr/(SemanticDowncastExpression) anddowncast expr(DowncastExpression) for crossing into Java APIs;.isInstanceOf/.isNotNull/.isNull/.behaviorMethod(args);where/any/translate/list.addblueprints.references/property-and-mutation-ops.md— read for property reads/writes (SPropertyAccess, assignment,Property_RemoveOperation) and tree mutations (SNodeCreator,add new(C),set new(C),replace with new(C)/replace with(other),.copy,.detach, sibling inserts), including allNF_*factory-initialized variants and the requiredjetbrains.mps.lang.actionsused-language import.references/references-and-queries.md—Node_GetReferenceOperation(.reference/C:role/),Node_GetReferencesOperation,Reference_GetTargetOperationetc.; plus query operations.siblings/.next-sibling/.prev-sibling*,.containingRoot/.containingLink/.model/.index,.isExactly(C),seq.ofConcept<C>,seq.ofAspect<a>, enum-member operations.references/attribute-access.md— the.@operator (AttributeAccess+NodeAttributeQualifier/LinkAttributeQualifier/ChildAttributeQualifier/PropertyAttributeQualifier/AllAttributeQualifier): read, attach/replace (assignable l-value), or remove an attribute, and chain into the children/refs/properties it grafts onto a node. Pairs withmps-aspect-structure-concepts/references/attributes-and-annotations.md(the structure side).references/link-and-concept-literals.md— standalonelink/C : role/(LinkIdRefExpression, two required refs) andconcept/C/(ConceptIdRefExpression). Open when an API needs anSContainmentLink/SReferenceLink/SConceptargument with no precedingnode.operand; covers the distinction fromOperationParm_LinkQualifierandRefConcept_Reference.references/foreach-statements.md— the twoforeachconcepts (collectionsForEachStatement+ForEachVariable/ForEachVariableReferencevs BaseLanguageForeachStatement+LocalVariableDeclaration/VariableReference). Open when iterating produces a typesystem error or when you need to reference the loop variable.references/node-equality.md—NPEEqualsExpression(:eq:) andNPENotEqualsExpression(:ne:) blueprints and when to use them.references/variable-declarations.md— type-child choices for locals and return types (node<C>,nlist<C>,node-ptr<C>,concept<C>,search scope,enummember<E>,sequence/list/set<node<C>>,boolean); creator blueprints fornew arraylist<node<C>>/new hashset<node<C>>/ etc.; the parse-time return-type fix-up blueprints forsequence<node<Type>>andlist<node<Type>>.references/openapi-and-dependencies.md—org.jetbrains.mps.openapi.*interfaces and threading rules (when hand-written Java calls into models); module dependencies vs model dependencies vs used languages, with failure modes ("Concept not imported", "cannot resolve", "Class not found at runtime") and the matching MCP tool to call.