sysml-v2-lsp 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.10.0]
4
+
5
+ ### Added
6
+
7
+ - Off-main-thread parsing via worker thread — diagnostics arrive faster while hover/completion stay responsive
8
+ - Early-open document queue: files opened before server initialisation are re-validated once the DFA is ready
9
+ - Enum value recognition (`enum red;` and bare `red;`) modelled as `EnumUsage` children in the symbol table
10
+ - DFA loader module for worker-side snapshot hydration
11
+ - Expanded warm-up text with `import` and `import all` variants
12
+
13
+ ### Changed
14
+
15
+ - Parse-retry comment trimmed to a concise one-liner
16
+ - `empty-enum` diagnostic no longer fires when the enum body contains explicit or implicit values
17
+
18
+ ### Fixed
19
+
20
+ - False-positive syntax errors on `import` statements inside package bodies
21
+
3
22
  ## [0.9.0]
4
23
 
5
24
  ### Added
@@ -107,7 +107,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
107
107
  `&&lineOffsets.push(j+1)}ranges.push({startLine:this.offsetToLine(lineOffsets,open),endLine:this.offsetToLine(lineOffsets,i-1)})}}return ranges}checkUnverifiedRequirements(allSymbols,indexes,workspaceTexts){let diagnostics=[],satisfiedNames,verifiedNames,satisfyBlockRanges;if(workspaceTexts){satisfiedNames=new Set,verifiedNames=new Set,satisfyBlockRanges=new Map;for(let text of workspaceTexts)this.extractSatisfyReferences(text,satisfiedNames),this.extractVerifyReferences(text,verifiedNames),satisfyBlockRanges.set("__static__",this.extractSatisfyBlockRanges(text))}else if(this.documentManager){let uris=this.documentManager.getUris(),versionKey=uris.map(u=>u+":"+this.documentManager.getVersion(u)).join("|");if(this.satisfyCache&&this.satisfyCache.versionKey===versionKey)satisfiedNames=this.satisfyCache.satisfiedNames,satisfyBlockRanges=this.satisfyCache.satisfyBlockRanges;else{satisfiedNames=new Set,satisfyBlockRanges=new Map;for(let uri of uris){let text=this.documentManager.getText(uri);text&&(this.extractSatisfyReferences(text,satisfiedNames),satisfyBlockRanges.set(uri,this.extractSatisfyBlockRanges(text)))}this.satisfyCache={versionKey,satisfiedNames,satisfyBlockRanges}}if(this.verifyCache&&this.verifyCache.versionKey===versionKey)verifiedNames=this.verifyCache.verifiedNames;else{verifiedNames=new Set;for(let uri of uris){let text=this.documentManager.getText(uri);text&&this.extractVerifyReferences(text,verifiedNames)}this.verifyCache={versionKey,verifiedNames}}}else satisfiedNames=new Set,verifiedNames=new Set,satisfyBlockRanges=new Map;let requirementUsages=allSymbols.filter(s=>s.kind==="requirement");for(let req of requirementUsages){if(req.parentQualifiedName&&indexes.byQualifiedName.get(req.parentQualifiedName)?.kind==="requirement")continue;let uriRanges=satisfyBlockRanges.get(req.uri)??satisfyBlockRanges.get("__static__")??[],reqLine=req.selectionRange.start.line;if(uriRanges.some(r=>reqLine>=r.startLine&&reqLine<=r.endLine))continue;let isSatisfied=satisfiedNames.has(req.name)||satisfiedNames.has(req.qualifiedName);if(!(verifiedNames.has(req.name)||verifiedNames.has(req.qualifiedName))){let message=isSatisfied?`Requirement '${req.name}' is satisfied but has no verification case \u2014 consider adding: verify ${req.name} by <VerificationCase>;`:`Requirement '${req.name}' has no verification case \u2014 consider adding: verify ${req.name} by <VerificationCase>;`;diagnostics.push({severity:import_node.DiagnosticSeverity.Warning,range:req.selectionRange,message,source:"sysml",code:"unverified-requirement",data:{name:req.name,qualifiedName:req.qualifiedName}})}}return diagnostics}extractVerifyReferences(text,out){let stripped=this.stripComments(text),re=/\bverify\s+(?:requirement\s+)?([\w]+(?:::[\w]+)*)\s*(?:by\b|;|:|\{)/g,m2;for(;(m2=re.exec(stripped))!==null;){let ref=m2[1];out.add(ref);let lastSeg=ref.includes("::")?ref.split("::").pop():ref;out.add(lastSeg)}}stripComments(text){return text.replace(/\/\*[\s\S]*?\*\//g,m2=>m2.replace(/[^\n]/g," ")).replace(/\/\/[^\n]*/g,m2=>" ".repeat(m2.length))}offsetToLine(lineOffsets,offset){let lo=0,hi=lineOffsets.length-1;for(;lo<hi;){let mid=lo+hi+1>>>1;lineOffsets[mid]<=offset?lo=mid:hi=mid-1}return lo}checkRedefinitionMultiplicity(symbolsInUri,indexes){let diagnostics=[];for(let s of symbolsInUri){if(!s.typeName||!s.multiplicityRange)continue;let c0=s.typeName.charCodeAt(0);if(!(c0>=97&&c0<=122))continue;let base=(indexes.byName.get(s.typeName)??[]).find(c=>!!c.multiplicityRange);if(!base?.multiplicityRange)continue;let baseLower=base.multiplicityRange.lower,baseUpper=base.multiplicityRange.upper,curLower=s.multiplicityRange.lower,curUpper=s.multiplicityRange.upper,lowerOk=curLower>=baseLower,upperOk=baseUpper==="*"||curUpper!=="*"&&curUpper<=baseUpper;lowerOk&&upperOk||diagnostics.push({severity:import_node.DiagnosticSeverity.Error,range:s.selectionRange,message:`Redefinition multiplicity [${s.multiplicity??"?"}] is incompatible with base '${base.name}' multiplicity [${base.multiplicity??"?"}]`,source:"sysml",code:"invalid-redefinition-multiplicity"})}return diagnostics}checkPortCompatibility(text,uri,indexes){if(!text)return[];let diagnostics=[],re=/\bconnect\s+([A-Za-z_][\w.]*)\s+to\s+([A-Za-z_][\w.]*)/g,m2;for(;(m2=re.exec(text))!==null;){let left=m2[1].split(".").pop(),right=m2[2].split(".").pop(),lSym=(indexes.portsByName.get(left)??[])[0],rSym=(indexes.portsByName.get(right)??[])[0];if(!lSym||!rSym)continue;let lType=lSym.typeNames[0]??lSym.typeName,rType=rSym.typeNames[0]??rSym.typeName;if(!lType||!rType||lType===rType)continue;let range=this.indexToRange(text,m2.index,m2[0].length);diagnostics.push({severity:import_node.DiagnosticSeverity.Warning,range,message:`Port compatibility issue: '${left}' (${lType}) is connected to '${right}' (${rType})`,source:"sysml",code:"incompatible-port-types",data:{uri}})}return diagnostics}checkConstraintBodyReferences(text,uri,symbolsInUri,indexes){if(!text)return[];let diagnostics=[],blocks=this.extractConstraintBlocks(text);for(let b of blocks){if(this.hasDocumentationOnlyConstraintBody(b.body)){let trimStart=b.body.search(/\S/),startInBody=trimStart>=0?trimStart:0,trimmedLen=Math.max(1,b.body.trim().length);diagnostics.push({severity:import_node.DiagnosticSeverity.Warning,range:this.indexToRange(text,b.bodyOffset+startInBody,trimmedLen),message:"Invalid constraint body: expected expression, found documentation text",source:"sysml",code:"invalid-constraint-body",data:{uri}});continue}let parent=this.findConstraintScopeSymbol(symbolsInUri,indexes,b.startLine);if(!parent)continue;let parentMembers=indexes.byParent.get(parent.qualifiedName)??[];if(parentMembers.length===0)continue;let ignoredRanges=this.getIgnoredBodyRanges(b.body),idRe=/\b([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*)\b/g,im;for(;(im=idRe.exec(b.body))!==null;){if(this.isIndexInRanges(im.index,ignoredRanges))continue;let expr=im[1];if(this.isConstraintKeyword(expr)||/^\d/.test(expr))continue;let path=expr.split(".");if(this.resolvePathFromParent(path,parentMembers,indexes))continue;if(path.length===1){let root=path[0];if(indexes.byName.has(root)||resolveLibraryType(root)!==void 0)continue}let absoluteStart=b.bodyOffset+im.index;diagnostics.push({severity:import_node.DiagnosticSeverity.Warning,range:this.indexToRange(text,absoluteStart,expr.length),message:`Unresolved constraint reference '${expr}' in scope '${parent.name}'`,source:"sysml",code:"unresolved-constraint-reference",data:{uri}})}}return diagnostics}extractConstraintBlocks(text){let out=[],re=/\b(?:require\s+)?constraint\s*\{/g,m2;for(;(m2=re.exec(text))!==null;){let open=m2.index+m2[0].length-1,depth=1,i=open+1;for(;i<text.length&&depth>0;){let ch=text[i];ch==="{"&&depth++,ch==="}"&&depth--,i++}if(depth!==0)continue;let bodyStart=open+1,bodyEnd=i-1,body=text.slice(bodyStart,bodyEnd),startLine=text.slice(0,bodyStart).split(`
108
108
  `).length-1;out.push({body,bodyOffset:bodyStart,startLine})}return out}resolvePathFromParent(path,parentMembers,indexes){let root=parentMembers.find(s=>s.name===path[0]);if(!root)return!1;if(path.length===1)return!0;let typeName=root.typeNames[0]??root.typeName;for(let i=1;i<path.length;i++){if(!typeName)return!1;let typeDef=(indexes.definitionsByName.get(typeName)??[])[0];if(!typeDef)return!1;let member=(indexes.byParent.get(typeDef.qualifiedName)??[]).find(s=>s.name===path[i]);if(!member)return!1;typeName=member.typeNames[0]??member.typeName}return!0}findContainingSymbolByLine(symbols,line){return symbols.filter(s=>s.range.start.line<=line&&s.range.end.line>=line).sort((a,b)=>{let ar=(a.range.end.line-a.range.start.line)*1e3+(a.range.end.character-a.range.start.character),br=(b.range.end.line-b.range.start.line)*1e3+(b.range.end.character-b.range.start.character);return ar-br})[0]}findConstraintScopeSymbol(symbolsInUri,indexes,line){let scope=this.findContainingSymbolByLine(symbolsInUri,line);for(;scope;){if((indexes.byParent.get(scope.qualifiedName)??[]).length>0||!scope.parentQualifiedName)return scope;scope=indexes.byQualifiedName.get(scope.parentQualifiedName)}}buildSymbolIndexes(allSymbols){let byName=new Map,byParent=new Map,byQualifiedName=new Map,definitionsByName=new Map,portsByName=new Map;for(let s of allSymbols){let nameList=byName.get(s.name)??[];if(nameList.push(s),byName.set(s.name,nameList),byQualifiedName.set(s.qualifiedName,s),s.parentQualifiedName){let children=byParent.get(s.parentQualifiedName)??[];children.push(s),byParent.set(s.parentQualifiedName,children)}if(isDefinition(s.kind)){let defs=definitionsByName.get(s.name)??[];defs.push(s),definitionsByName.set(s.name,defs)}if(s.kind==="port"||s.kind==="port def"){let ports=portsByName.get(s.name)??[];ports.push(s),portsByName.set(s.name,ports)}}return{byName,byParent,byQualifiedName,definitionsByName,portsByName}}isConstraintKeyword(value){return CONSTRAINT_KEYWORDS.has(value)}getIgnoredBodyRanges(body){let ranges=[],blockRe=/\/\*[\s\S]*?\*\//g,m2;for(;(m2=blockRe.exec(body))!==null;)ranges.push({start:m2.index,end:m2.index+m2[0].length});let lineRe=/\/\/[^\n\r]*/g;for(;(m2=lineRe.exec(body))!==null;)ranges.push({start:m2.index,end:m2.index+m2[0].length});return ranges}isIndexInRanges(index2,ranges){for(let r of ranges)if(index2>=r.start&&index2<r.end)return!0;return!1}hasDocumentationOnlyConstraintBody(body){let trimmed=body.trim();if(!trimmed)return!1;let withoutComments=trimmed.replace(/\/\*[\s\S]*?\*\//g," ").replace(/\/\/[^\n\r]*/g," ").trim();if(withoutComments==="doc"||withoutComments==="comment")return!0;let hasExprSignal=/[<>=!+\-*/%()[\].,:]|\b(and|or|not)\b/.test(withoutComments);return/^[A-Za-z_\s]+$/.test(withoutComments)&&!hasExprSignal}indexToRange(text,start,length){let prefix=text.slice(0,start),startLine=prefix.split(`
109
109
  `).length-1,startChar=start-(prefix.lastIndexOf(`
110
- `)+1);return{start:{line:startLine,character:startChar},end:{line:startLine,character:startChar+length}}}dedupeDiagnostics(diags){let seen=new Set,out=[];for(let d of diags){let key=[d.code??"no-code",d.range.start.line,d.range.start.character,d.range.end.line,d.range.end.character,d.message].join("|");seen.has(key)||(seen.add(key),out.push(d))}return out}checkDuplicateDefinitions(symbols){let diagnostics=[],definitionsByScope=new Map;for(let symbol2 of symbols){if(!isDefinition(symbol2.kind))continue;let scope=symbol2.parentQualifiedName??"__root__",scopeMap=definitionsByScope.get(scope);scopeMap||(scopeMap=new Map,definitionsByScope.set(scope,scopeMap));let defs=scopeMap.get(symbol2.name);defs||(defs=[],scopeMap.set(symbol2.name,defs)),defs.push(symbol2)}for(let scopeMap of definitionsByScope.values())for(let[name,defs]of scopeMap)if(defs.length>1)for(let def of defs)diagnostics.push({severity:import_node.DiagnosticSeverity.Warning,range:def.selectionRange,message:`Duplicate definition: '${name}' is defined ${defs.length} times in the same scope`,source:"sysml",code:"duplicate-definition"});return diagnostics}};function tokenToPosition(token){return{line:(token.line??1)-1,character:token.column??0}}function tokenToRange(token){let start=tokenToPosition(token),length=token.text?.length??1;return{start,end:{line:start.line,character:start.character+length}}}function contextToRange(ctx2){let startToken=ctx2.start,stopToken=ctx2.stop??ctx2.start;if(!startToken)return{start:{line:0,character:0},end:{line:0,character:0}};let start={line:(startToken.line??1)-1,character:startToken.column??0},end=stopToken?{line:(stopToken.line??1)-1,character:(stopToken.column??0)+(stopToken.text?.length??1)}:{line:start.line,character:start.character+1};return{start,end}}var Scope=class{constructor(id,parent=null){this.id=id;this.parent=parent}symbols=new Map;define(symbol2){this.symbols.set(symbol2.name,symbol2)}lookupLocal(name){return this.symbols.get(name)}resolve(name){let local=this.symbols.get(name);return local||this.parent?.resolve(name)}resolveQualified(qualifiedName){let parts=qualifiedName.split("::");if(parts.length===1)return this.resolve(parts[0]);let current=this.resolve(parts[0]);if(current)return current}getLocalSymbols(){return Array.from(this.symbols.values())}getAllVisibleSymbols(){let result=new Map,scope=this;for(;scope;){for(let[name,symbol2]of scope.symbols)result.has(name)||result.set(name,symbol2);scope=scope.parent}return Array.from(result.values())}};var SymbolTable=class{symbols=new Map;symbolsByUri=new Map;globalScope;constructor(){this.globalScope=new Scope("__global__")}build(uri,parseResult){this.clearUri(uri),parseResult.tree&&this.walkTree(parseResult.tree,uri,this.globalScope,"")}getSymbol(qualifiedName){return this.symbols.get(qualifiedName)}findByName(name){let results=[];for(let symbol2 of this.symbols.values())symbol2.name===name&&results.push(symbol2);return results}getSymbolsForUri(uri){return this.symbolsByUri.get(uri)??[]}getAllSymbols(){return Array.from(this.symbols.values())}getGlobalScope(){return this.globalScope}findSymbolAtPosition(uri,line,character){let symbols=this.getSymbolsForUri(uri),best,bestSize=1/0;for(let symbol2 of symbols){let r=symbol2.selectionRange;if(line>=r.start.line&&line<=r.end.line&&(line>r.start.line||character>=r.start.character)&&(line<r.end.line||character<=r.end.character)){let size=(r.end.line-r.start.line)*1e4+(r.end.character-r.start.character);size<bestSize&&(best=symbol2,bestSize=size)}}return best}findReferences(name){let results=[];for(let symbol2 of this.symbols.values())(symbol2.name===name||symbol2.typeNames.includes(name))&&results.push(symbol2);return results}removeUri(uri){this.clearUri(uri),this.symbolsByUri.delete(uri)}clearUri(uri){let existing=this.symbolsByUri.get(uri);if(existing)for(let sym of existing)this.symbols.delete(sym.qualifiedName);this.symbolsByUri.set(uri,[])}walkTree(ctx2,uri,currentScope,parentQualifiedName){let ruleName=this.getRuleName(ctx2),symbol2=this.tryExtractSymbol(ctx2,uri,ruleName,parentQualifiedName),childScope=currentScope;symbol2&&(this.registerSymbol(symbol2,uri,currentScope),childScope=new Scope(symbol2.qualifiedName,currentScope));for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);child instanceof ParserRuleContext&&this.walkTree(child,uri,childScope,symbol2?.qualifiedName??parentQualifiedName)}}registerSymbol(symbol2,uri,scope){this.symbols.set(symbol2.qualifiedName,symbol2);let uriSymbols=this.symbolsByUri.get(uri)??[];uriSymbols.push(symbol2),this.symbolsByUri.set(uri,uriSymbols),scope.define(symbol2)}getRuleName(ctx2){let idx=ctx2.ruleIndex;if(idx>=0&&idx<SysMLv2Parser.ruleNames.length)return SysMLv2Parser.ruleNames[idx];let ctorName=ctx2.constructor.name;return ctorName.endsWith("Context")?ctorName.slice(0,-7):ctorName}tryExtractSymbol(ctx2,uri,ruleName,parentQualifiedName){let kind=this.inferKind(ruleName,ctx2);if(kind===void 0)return;let name=this.extractName(ctx2);if(!name)return;let qualifiedName=parentQualifiedName?`${parentQualifiedName}::${name}`:name,range=contextToRange(ctx2),selectionRange=this.extractNameRange(ctx2)??range,typeNames=this.extractTypeNames(ctx2),typeName=typeNames[0],documentation=this.extractDocumentation(ctx2),{multiplicity,multiplicityRange}=isUsage(kind)?this.extractMultiplicity(ctx2):{},metadataAnnotations=this.extractPrefixMetadataAnnotations(ctx2);return{name,kind,qualifiedName,range,selectionRange,uri,typeName,typeNames,documentation,parentQualifiedName:parentQualifiedName||void 0,children:[],multiplicity,multiplicityRange,metadataAnnotations:metadataAnnotations.length>0?metadataAnnotations:void 0}}inferKind(ruleName,_ctx){let lower=ruleName.toLowerCase();if(lower==="package"||lower==="librarypackage")return"package";if(lower==="partdefinition")return"part def";if(lower==="attributedefinition")return"attribute def";if(lower==="portdefinition")return"port def";if(lower==="connectiondefinition")return"connection def";if(lower==="interfacedefinition")return"interface def";if(lower==="actiondefinition")return"action def";if(lower==="statedefinition")return"state def";if(lower==="requirementdefinition")return"requirement def";if(lower==="constraintdefinition")return"constraint def";if(lower==="itemdefinition")return"item def";if(lower==="allocationdefinition")return"allocation def";if(lower==="usecasedefinition")return"use case def";if(lower==="enumerationdefinition")return"enum def";if(lower==="calculationdefinition"||lower==="calcdefinition")return"calc def";if(lower==="viewdefinition")return"view def";if(lower==="viewpointdefinition")return"viewpoint def";if(lower==="metadatadefinition")return"metadata def";if(lower==="partusage")return"part";if(lower==="attributeusage")return"attribute";if(lower==="portusage")return"port";if(lower==="connectionusage")return"connection";if(lower==="actionusage")return"action";if(lower==="stateusage")return"state";if(lower==="requirementusage")return"requirement";if(lower==="constraintusage")return"constraint";if(lower==="itemusage")return"item";if(lower==="allocationusage")return"allocation";if(lower==="usecaseusage")return"use case";if(lower==="includeusecaseusage")return"include use case";if(lower==="actorusage")return"actor";if(lower==="subjectusage")return"subject";if(lower==="stakeholderusage")return"stakeholder";if(lower==="referenceusage")return"ref";if(lower==="interfaceusage")return"interface";if(lower==="performactionusage")return"perform action";if(lower==="exhibitstateusage")return"exhibit state";if(lower==="transitionusage")return"transition";if(lower==="occurrencedefinition")return"occurrence def";if(lower==="occurrenceusage")return"occurrence";if(lower==="renderingdefinition")return"rendering def";if(lower==="viewusage")return"view";if(lower==="viewpointusage")return"viewpoint";if(lower==="verificationcasedefinition")return"verification case def";if(lower==="verificationcaseusage")return"verification case";if(lower==="analysiscasedefinition")return"analysis case def";if(lower==="analysiscaseusage")return"analysis case";if(lower==="aliasmember")return"alias"}extractName(ctx2){for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof TerminalNode){let token=child.symbol;if(this.isIdentifierToken(token))return this.unquoteName(token.text??"")}if(child instanceof ParserRuleContext){let childRule=this.getRuleName(child);if(childRule.toLowerCase().includes("identification")||childRule.toLowerCase().includes("declarationname")||childRule.toLowerCase().includes("qualifiedname")||childRule.toLowerCase()==="name"){let name=this.extractTextFromSubtree(child);if(name)return name}}}for(let i=0;i<Math.min(ctx2.getChildCount(),5);i++){let child=ctx2.getChild(i);if(child instanceof ParserRuleContext){if(this.isPrefixOrExtensionContext(child))continue;let name=this.extractName(child);if(name)return name}}}extractNameRange(ctx2){for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof TerminalNode&&this.isIdentifierToken(child.symbol))return tokenToRange(child.symbol);if(child instanceof ParserRuleContext){if(this.isPrefixOrExtensionContext(child))continue;let result=this.extractNameRange(child);if(result)return result}}}extractTypeNames(ctx2){let names=[];if(this.collectTypeNamesFromTree(ctx2,names,0),names.length>0)return names;let fullText=ctx2.getText(),braceIdx=fullText.indexOf("{"),text=braceIdx>=0?fullText.substring(0,braceIdx):fullText;text=text.replace(/(redefines|subsets|references|connect|bind|first|then|flow|allocate|assign|accept|send|decide|merge|join|fork|via|default)\b.*/i,"");let specMatch=text.match(/(?:specializes|:>|:>>)\s*('[^']+'|[A-Za-z_]\w*(?:::\w+)*)(?:\s*,\s*(?:'[^']+'|[A-Za-z_]\w*(?:::\w+)*))*/);if(specMatch){let specStr=text.substring(text.indexOf(specMatch[0])+specMatch[0].indexOf(specMatch[1]));for(let part of specStr.split(",")){let qm=part.match(/'([^']+)'/);if(qm){names.push(qm[1]);continue}let m2=part.trim().match(/^([A-Za-z_]\w*(?:::\w+)*)/);m2&&names.push(m2[1])}return names}let defByMatch=text.match(/definedby\s*([A-Za-z_]\w*(?:::\w+)*(?:\s*,\s*[A-Za-z_]\w*(?:::\w+)*)*)/);if(defByMatch){for(let part of defByMatch[1].split(",")){let m2=part.trim().match(/^([A-Za-z_]\w*(?:::\w+)*)/);m2&&names.push(m2[1])}return names}let typingMatch=text.match(/:(?![:>])\s*('[^']+'|[A-Za-z_]\w*(?:::\w+)*)/);if(typingMatch){let fullMatchIdx=text.indexOf(typingMatch[0]),afterColon=text.substring(fullMatchIdx+1).trim();for(let part of afterColon.split(",")){let qm=part.match(/'([^']+)'/);if(qm){names.push(qm[1]);continue}let m2=part.trim().match(/^([A-Za-z_]\w*(?:::\w+)*)/);m2&&names.push(m2[1])}return names}return names}collectTypeNamesFromTree(ctx2,names,depth){if(!(depth>6))for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(!(child instanceof ParserRuleContext))continue;let rn=this.getRuleName(child).toLowerCase();if(rn.includes("specialization")||rn.includes("subclassification")||rn.includes("typing")||rn.includes("conjugation")||rn.includes("disjoining")){let stripped=child.getText().replace(/^(specializes|:>|:>>|:\s|definedby|subsets|redefines|references|conjugates|disjoints)/i,"");for(let part of stripped.split(",")){let qm=part.match(/'([^']+)'/);if(qm)names.push(qm[1]);else{let m2=part.match(/([A-Za-z_]\w*(?:::\w+)*)/);m2&&names.push(m2[1])}}}else(rn.includes("declaration")||rn.includes("featurespecialization")||rn.includes("typings")||rn.includes("usagecompletion")||rn==="usage"||rn==="definition")&&this.collectTypeNamesFromTree(child,names,depth+1)}}extractDocumentation(ctx2){for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof ParserRuleContext){let ruleName=this.getRuleName(child).toLowerCase();if(ruleName.includes("comment")||ruleName.includes("doc")||ruleName.includes("documentation")){let raw=child.getText();if(raw){let text=raw;return text.startsWith("doc")&&(text=text.slice(3)),text.startsWith("comment")&&(text=text.slice(7)),text=text.replace(/^\/\*\s*/,"").replace(/\s*\*\/$/,""),text=text.replace(/^\/\/\s*/,""),text.trim()||raw}return raw??void 0}let nested=this.extractDocumentation(child);if(nested)return nested}}}extractMultiplicity(ctx2){let multCtx=this.findMultiplicityBounds(ctx2);if(!multCtx)return{};let members=multCtx.multiplicityExpressionMember();if(!members||members.length===0)return{};let values=[];for(let member of members){let rawText=member.getText()?.trim();rawText&&values.push(rawText)}if(values.length===0)return{};let lower,upper,multiplicity;if(values.length===1)if(multiplicity=values[0],values[0]==="*")lower=0,upper="*";else{let num=parseInt(values[0],10);if(isNaN(num))return{multiplicity};lower=num,upper=num}else{if(multiplicity=`${values[0]}..${values[1]}`,lower=parseInt(values[0],10),isNaN(lower))return{multiplicity};if(values[1]==="*")upper="*";else if(upper=parseInt(values[1],10),isNaN(upper))return{multiplicity}}return{multiplicity,multiplicityRange:{lower,upper}}}findMultiplicityBounds(ctx2){if(ctx2.ruleIndex===SysMLv2Parser.RULE_multiplicityBounds)return ctx2;for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof ParserRuleContext){let result=this.findMultiplicityBounds(child);if(result)return result}}}isPrefixOrExtensionContext(ctx2){let rule=this.getRuleName(ctx2).toLowerCase();return rule.includes("prefixmetadata")||rule.includes("extensionkeyword")||rule==="occurrencedefinitionprefix"||rule==="occurrenceusageprefix"||rule==="definitionprefix"||rule==="basicdefinitionprefix"||rule==="typeprefix"||rule==="featureprefix"||rule==="basicfeatureprefix"||rule==="endfeatureprefix"}extractPrefixMetadataAnnotations(ctx2){let annotations=[];return this.collectPrefixMetadata(ctx2,annotations,0),annotations}collectPrefixMetadata(ctx2,annotations,depth){if(!(depth>4))for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(!(child instanceof ParserRuleContext))continue;let rule=this.getRuleName(child).toLowerCase();if(rule==="prefixmetadatamember"||rule==="prefixmetadataannotation"){let name=this.extractTextFromSubtree(child);name&&annotations.push(name)}else(rule.includes("prefix")||rule.includes("extensionkeyword")||rule==="definition"||rule==="usage")&&this.collectPrefixMetadata(child,annotations,depth+1)}}isIdentifierToken(token){let text=token.text;return text?this.isQuotedName(text)?!0:/^[a-zA-Z_]/.test(text)&&!this.isKeyword(text):!1}isQuotedName(text){return text.length>=3&&text.startsWith("'")&&text.endsWith("'")}unquoteName(text){return this.isQuotedName(text)?text.slice(1,-1):text}isKeyword(text){return new Set(["about","abstract","accept","action","actor","after","alias","all","allocate","allocation","analysis","and","as","assert","assign","assume","attribute","bind","binding","bool","by","calc","case","comment","concern","connect","connection","constraint","decide","def","default","defined","dependency","derived","do","doc","else","end","entry","enum","event","exhibit","exit","expose","false","feature","filter","first","flow","for","fork","frame","from","hastype","if","implies","import","in","include","individual","inout","interface","istype","item","join","language","library","locale","merge","message","meta","metadata","multiplicity","namespace","nonunique","not","null","objective","occurrence","of","or","ordered","out","package","parallel","part","perform","port","private","protected","public","readonly","redefines","ref","references","render","rendering","rep","require","requirement","return","satisfy","send","snapshot","specializes","stakeholder","state","subject","subsets","succession","then","timeslice","to","transition","true","type","use","variant","variation","verification","verify","view","viewpoint","when","while","xor"]).has(text)}extractTextFromSubtree(ctx2){let parts=[];for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof TerminalNode){let text=child.symbol.text;text&&this.isIdentifierToken(child.symbol)&&parts.push(this.unquoteName(text))}else if(child instanceof ParserRuleContext){let sub=this.extractTextFromSubtree(child);sub&&parts.push(sub)}}return parts.length>0?parts.join("::"):void 0}};var SYSML_KEYWORDS_ARRAY=SysMLv2Lexer.literalNames.filter(n2=>n2!=null).map(n2=>n2.replace(/^'|'$/g,"")).filter(n2=>/^[a-z]+$/.test(n2)).sort(),SYSML_KEYWORDS=new Set(SYSML_KEYWORDS_ARRAY);var McpContext=class{symbolTable=new SymbolTable;loadedDocuments=new Map;loadedDocumentHashes=new Map;lastParseErrors=new Map;lastParseTiming=new Map};function hashTextFNV1a(text){let hash2=2166136261;for(let i=0;i<text.length;i++)hash2^=text.charCodeAt(i),hash2=Math.imul(hash2,16777619);return hash2>>>0}function ensureParsed(ctx2,uri,code){if(code!==void 0){parseAndBuild(ctx2,code,uri);return}if(ctx2.symbolTable.getSymbolsForUri(uri).length===0){let cached2=ctx2.loadedDocuments.get(uri);cached2&&parseAndBuild(ctx2,cached2,uri)}}function formatSymbol(sym){return{name:sym.name,kind:sym.kind,qualifiedName:sym.qualifiedName,...sym.typeNames.length>0?{type:sym.typeNames.join(", ")}:{},...sym.documentation?{documentation:sym.documentation}:{},...sym.parentQualifiedName?{parent:sym.parentQualifiedName}:{},...sym.children.length>0?{children:sym.children}:{},location:{uri:sym.uri,range:sym.range}}}function formatError2(err){return{line:err.line+1,column:err.column+1,message:err.message,length:err.length}}function parseAndBuild(ctx2,text,uri){let hash2=hashTextFNV1a(text),prevHash=ctx2.loadedDocumentHashes.get(uri),currentSymbolCount=ctx2.symbolTable.getSymbolsForUri(uri).length,cachedErrors=ctx2.lastParseErrors.get(uri)??[],canReuseCachedParse=currentSymbolCount>0||cachedErrors.length>0;if(prevHash===hash2&&ctx2.lastParseTiming.has(uri)&&canReuseCachedParse)return{errors:cachedErrors,symbolCount:currentSymbolCount,timingMs:ctx2.lastParseTiming.get(uri)??{lex:0,parse:0}};let result=parseDocument(text);ctx2.symbolTable.build(uri,result),ctx2.loadedDocuments.set(uri,text),ctx2.loadedDocumentHashes.set(uri,hash2),ctx2.lastParseErrors.set(uri,result.errors);let timing={lex:result.timing.lexMs,parse:result.timing.parseMs};return ctx2.lastParseTiming.set(uri,timing),{errors:result.errors,symbolCount:ctx2.symbolTable.getSymbolsForUri(uri).length,timingMs:timing}}function handleParse(ctx2,code,uri){let docUri=uri??"untitled.sysml",{errors,symbolCount,timingMs}=parseAndBuild(ctx2,code,docUri),summary={uri:docUri,symbolCount,errorCount:errors.length,timing:timingMs};errors.length>0&&(summary.errors=errors.map(formatError2));let topLevel=ctx2.symbolTable.getSymbolsForUri(docUri).filter(s=>!s.parentQualifiedName).map(s=>`${s.kind} ${s.qualifiedName}`);return topLevel.length>0&&(summary.topLevelElements=topLevel),summary}function handlePreview(ctx2,opts){let docUri=opts.uri??"preview.sysml",{errors}=parseAndBuild(ctx2,opts.code,docUri),allSymbols=ctx2.symbolTable.getSymbolsForUri(docUri),allNames=new Set(ctx2.symbolTable.getAllSymbols().map(s=>s.name)),semanticDiags=SemanticValidator.validateSymbols(allSymbols,allNames,{allSymbols:ctx2.symbolTable.getAllSymbols(),text:opts.code,uri:docUri}),renderSymbols=allSymbols;if(opts.focus){let focusName=opts.focus,focusSet=new Set,childrenOf=new Map;for(let s of allSymbols)if(s.parentQualifiedName){let list=childrenOf.get(s.parentQualifiedName)??[];list.push(s),childrenOf.set(s.parentQualifiedName,list)}let focused=allSymbols.filter(s=>s.name===focusName||s.qualifiedName===focusName||s.qualifiedName.endsWith(`::${focusName}`));for(let f of focused){focusSet.add(f.qualifiedName);let children=childrenOf.get(f.qualifiedName)??[];for(let child of children)focusSet.add(child.qualifiedName);f.parentQualifiedName&&focusSet.add(f.parentQualifiedName);let typeSource=[...f.typeNames];for(let child of children)typeSource.push(...child.typeNames);for(let tn of typeSource){let typed=allSymbols.find(s=>s.name===tn||s.qualifiedName===tn);if(typed){focusSet.add(typed.qualifiedName);for(let child of childrenOf.get(typed.qualifiedName)??[])focusSet.add(child.qualifiedName)}}}focusSet.size>0&&(renderSymbols=allSymbols.filter(s=>focusSet.has(s.qualifiedName)))}let mermaid=generateMermaidDiagram(renderSymbols,allSymbols,opts.diagramType),result={diagram:mermaid.diagram,diagramType:mermaid.diagramType,description:mermaid.description,elementCount:mermaid.elementCount,errors:errors.map(formatError2)};if(opts.originalCode){let origUri="preview-original.sysml",origResult=parseDocument(opts.originalCode),origTable=new SymbolTable;origTable.build(origUri,origResult);let origSymbols=origTable.getSymbolsForUri(origUri),diff=diffSymbols(origSymbols,allSymbols);result.diff={added:diff.added.map(s=>`${s.kind} ${s.qualifiedName}`),changed:diff.changed.map(s=>`${s.kind} ${s.qualifiedName}`),removed:diff.removed,unchangedCount:diff.unchanged.length}}return semanticDiags.length>0&&(result.semanticIssues=semanticDiags.map(d=>({line:d.range.start.line+1,column:d.range.start.character+1,message:d.message,severity:d.severity===1?"error":d.severity===2?"warning":"info"}))),result}function handleValidate(ctx2,code,uri){let docUri=uri??"untitled.sysml",{errors}=parseAndBuild(ctx2,code,docUri),symbols=ctx2.symbolTable.getSymbolsForUri(docUri),allNames=new Set(ctx2.symbolTable.getAllSymbols().map(s=>s.name)),semanticDiags=SemanticValidator.validateSymbols(symbols,allNames,{allSymbols:ctx2.symbolTable.getAllSymbols(),text:code,uri:docUri}),semanticIssues=semanticDiags.map(d=>({line:d.range.start.line+1,column:d.range.start.character+1,message:d.message,severity:d.severity===1?"error":d.severity===2?"warning":d.severity===3?"info":"hint",code:d.code}));return{valid:errors.length===0&&semanticDiags.filter(d=>d.severity===1).length===0,syntaxErrors:errors.map(formatError2),semanticIssues,totalIssues:errors.length+semanticDiags.length}}function handleGetDiagnostics(ctx2,uri,code){let docUri=uri??"untitled.sysml";ensureParsed(ctx2,docUri,code);let symbols=ctx2.symbolTable.getSymbolsForUri(docUri),allNames=new Set(ctx2.symbolTable.getAllSymbols().map(s=>s.name)),diags=SemanticValidator.validateSymbols(symbols,allNames,{allSymbols:ctx2.symbolTable.getAllSymbols(),text:code??ctx2.loadedDocuments.get(docUri),uri:docUri}),summary={};for(let d of diags){let code2=String(d.code??"unknown");summary[code2]=(summary[code2]??0)+1}return{uri:docUri,diagnostics:diags.map(d=>({line:d.range.start.line+1,column:d.range.start.character+1,message:d.message,severity:d.severity===1?"error":d.severity===2?"warning":d.severity===3?"info":"hint",code:d.code})),summary}}function handleGetSymbols(ctx2,opts){if(opts.code){let docUri=opts.uri??"untitled.sysml";ensureParsed(ctx2,docUri,opts.code)}let symbols=opts.uri?ctx2.symbolTable.getSymbolsForUri(opts.uri):ctx2.symbolTable.getAllSymbols();return opts.kind&&(symbols=symbols.filter(s=>s.kind.toLowerCase()===opts.kind.toLowerCase())),opts.definitionsOnly&&(symbols=symbols.filter(s=>isDefinition(s.kind))),opts.usagesOnly&&(symbols=symbols.filter(s=>isUsage(s.kind))),{count:symbols.length,symbols:symbols.map(formatSymbol)}}function handleGetDefinition(ctx2,name,code,uri){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let exact=ctx2.symbolTable.getSymbol(name);if(exact)return formatSymbol(exact);let matches=ctx2.symbolTable.findByName(name);return matches.length===0?{found:!1,message:`No symbol found with name "${name}"`}:{found:!0,count:matches.length,symbols:matches.map(formatSymbol)}}function handleGetReferences(ctx2,name,code,uri){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let refs=ctx2.symbolTable.findReferences(name);return{name,referenceCount:refs.length,references:refs.map(formatSymbol)}}function handleGetHierarchy(ctx2,name,code,uri){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let target=ctx2.symbolTable.getSymbol(name)??ctx2.symbolTable.findByName(name)[0];if(!target)return{found:!1,message:`No symbol "${name}" found`};let ancestors=[],current=target.parentQualifiedName;for(;current;){let parent=ctx2.symbolTable.getSymbol(current);if(!parent)break;ancestors.unshift({name:parent.name,kind:parent.kind,qualifiedName:parent.qualifiedName}),current=parent.parentQualifiedName}let children=target.children.map(qn=>ctx2.symbolTable.getSymbol(qn)).filter(s=>s!==void 0).map(s=>({name:s.name,kind:s.kind,qualifiedName:s.qualifiedName,...s.typeNames.length>0?{type:s.typeNames.join(", ")}:{}}));return{element:{name:target.name,kind:target.kind,qualifiedName:target.qualifiedName,...target.typeNames.length>0?{type:target.typeNames.join(", ")}:{}},ancestors,children}}function handleGetModelSummary(ctx2,code,uri){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let allSymbols=ctx2.symbolTable.getAllSymbols(),kindCounts={};for(let sym of allSymbols)kindCounts[sym.kind]=(kindCounts[sym.kind]??0)+1;let sorted=Object.entries(kindCounts).sort(([,a],[,b])=>b-a);return{totalSymbols:allSymbols.length,loadedDocuments:Array.from(ctx2.loadedDocuments.keys()),elementsByKind:Object.fromEntries(sorted),definitions:allSymbols.filter(s=>isDefinition(s.kind)).length,usages:allSymbols.filter(s=>isUsage(s.kind)).length}}function handleGetComplexity(ctx2,uri,code){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let symbols=uri?ctx2.symbolTable.getSymbolsForUri(uri):ctx2.symbolTable.getAllSymbols();return analyseComplexity(symbols)}function getElementKinds(){let kinds=Object.values(SysMLElementKind);return{definitions:kinds.filter(k=>isDefinition(k)),usages:kinds.filter(k=>isUsage(k)),other:kinds.filter(k=>!isDefinition(k)&&!isUsage(k)),total:kinds.length}}function handleResourceElementKinds(){return getElementKinds()}function handleResourceKeywords(){return{keywords:SYSML_KEYWORDS_ARRAY,count:SYSML_KEYWORDS_ARRAY.length}}function handleResourceGrammarOverview(){return"# SysML v2 Grammar Overview\n\n## Element Categories\n\n### Definitions (Types)\nDefinitions declare reusable types:\n- `part def` \u2014 structural element type\n- `attribute def` \u2014 value type\n- `port def` \u2014 interface point type\n- `connection def` \u2014 connection type\n- `interface def` \u2014 interface type\n- `action def` \u2014 behavior type\n- `state def` \u2014 state machine type\n- `requirement def` \u2014 requirement type\n- `constraint def` \u2014 constraint type\n- `item def` \u2014 general item type\n- `enum def` \u2014 enumeration type\n- `calc def` \u2014 calculation type\n- `use case def` \u2014 use case type\n- `allocation def` \u2014 allocation type\n- `view def` / `viewpoint def` \u2014 viewpoint types\n\n### Usages (Instances)\nUsages create instances of definitions:\n- `part` \u2014 structural instance\n- `attribute` \u2014 value instance\n- `port` \u2014 port instance\n- `action` \u2014 action step\n- `state` \u2014 state instance\n- `requirement` \u2014 requirement instance\n- `item` \u2014 item instance\n\n## Specialisation Syntax\n- `part car : Vehicle` \u2014 `car` specialises `Vehicle`\n- `part car :> baseVehicle` \u2014 `car` subsets `baseVehicle`\n- `part car :>> specificVehicle` \u2014 `car` redefines `specificVehicle`\n\n## Packages & Namespaces\n```sysml\npackage VehicleModel {\n part def Vehicle { ... }\n part car : Vehicle;\n}\n```\n\n## Documentation\n```sysml\npart def Vehicle {\n doc /* A general vehicle definition */\n attribute mass : Real;\n}\n```\n\n## Unrestricted Names\nNames with spaces use single quotes: `part 'Main Assembly' : Assembly;`\n"}function handlePromptReviewSysml(ctx2,code){let{errors,symbolCount}=parseAndBuild(ctx2,code,"review.sysml"),allSymbols=ctx2.symbolTable.getSymbolsForUri("review.sysml"),defs=allSymbols.filter(s=>isDefinition(s.kind)),usages=allSymbols.filter(s=>isUsage(s.kind)),context=[`Parsed: ${symbolCount} symbols, ${errors.length} syntax errors`,`Definitions: ${defs.map(d=>`${d.kind} ${d.name}`).join(", ")||"none"}`,`Usages: ${usages.map(u=>`${u.kind} ${u.name}`).join(", ")||"none"}`];return errors.length>0&&context.push(`Errors: ${errors.map(e=>`line ${e.line+1}: ${e.message}`).join("; ")}`),[{role:"user",content:{type:"text",text:`Please review the following SysML v2 model for correctness, completeness, and best practices.
110
+ `)+1);return{start:{line:startLine,character:startChar},end:{line:startLine,character:startChar+length}}}dedupeDiagnostics(diags){let seen=new Set,out=[];for(let d of diags){let key=[d.code??"no-code",d.range.start.line,d.range.start.character,d.range.end.line,d.range.end.character,d.message].join("|");seen.has(key)||(seen.add(key),out.push(d))}return out}checkDuplicateDefinitions(symbols){let diagnostics=[],definitionsByScope=new Map;for(let symbol2 of symbols){if(!isDefinition(symbol2.kind))continue;let scope=symbol2.parentQualifiedName??"__root__",scopeMap=definitionsByScope.get(scope);scopeMap||(scopeMap=new Map,definitionsByScope.set(scope,scopeMap));let defs=scopeMap.get(symbol2.name);defs||(defs=[],scopeMap.set(symbol2.name,defs)),defs.push(symbol2)}for(let scopeMap of definitionsByScope.values())for(let[name,defs]of scopeMap)if(defs.length>1)for(let def of defs)diagnostics.push({severity:import_node.DiagnosticSeverity.Warning,range:def.selectionRange,message:`Duplicate definition: '${name}' is defined ${defs.length} times in the same scope`,source:"sysml",code:"duplicate-definition"});return diagnostics}};function tokenToPosition(token){return{line:(token.line??1)-1,character:token.column??0}}function tokenToRange(token){let start=tokenToPosition(token),length=token.text?.length??1;return{start,end:{line:start.line,character:start.character+length}}}function contextToRange(ctx2){let startToken=ctx2.start,stopToken=ctx2.stop??ctx2.start;if(!startToken)return{start:{line:0,character:0},end:{line:0,character:0}};let start={line:(startToken.line??1)-1,character:startToken.column??0},end=stopToken?{line:(stopToken.line??1)-1,character:(stopToken.column??0)+(stopToken.text?.length??1)}:{line:start.line,character:start.character+1};return{start,end}}var Scope=class{constructor(id,parent=null){this.id=id;this.parent=parent}symbols=new Map;define(symbol2){this.symbols.set(symbol2.name,symbol2)}lookupLocal(name){return this.symbols.get(name)}resolve(name){let local=this.symbols.get(name);return local||this.parent?.resolve(name)}resolveQualified(qualifiedName){let parts=qualifiedName.split("::");if(parts.length===1)return this.resolve(parts[0]);let current=this.resolve(parts[0]);if(current)return current}getLocalSymbols(){return Array.from(this.symbols.values())}getAllVisibleSymbols(){let result=new Map,scope=this;for(;scope;){for(let[name,symbol2]of scope.symbols)result.has(name)||result.set(name,symbol2);scope=scope.parent}return Array.from(result.values())}};var SymbolTable=class{symbols=new Map;symbolsByUri=new Map;globalScope;constructor(){this.globalScope=new Scope("__global__")}build(uri,parseResult){this.clearUri(uri),parseResult.tree&&this.walkTree(parseResult.tree,uri,this.globalScope,"")}getSymbol(qualifiedName){return this.symbols.get(qualifiedName)}findByName(name){let results=[];for(let symbol2 of this.symbols.values())symbol2.name===name&&results.push(symbol2);return results}getSymbolsForUri(uri){return this.symbolsByUri.get(uri)??[]}getAllSymbols(){return Array.from(this.symbols.values())}getGlobalScope(){return this.globalScope}findSymbolAtPosition(uri,line,character){let symbols=this.getSymbolsForUri(uri),best,bestSize=1/0;for(let symbol2 of symbols){let r=symbol2.selectionRange;if(line>=r.start.line&&line<=r.end.line&&(line>r.start.line||character>=r.start.character)&&(line<r.end.line||character<=r.end.character)){let size=(r.end.line-r.start.line)*1e4+(r.end.character-r.start.character);size<bestSize&&(best=symbol2,bestSize=size)}}return best}findReferences(name){let results=[];for(let symbol2 of this.symbols.values())(symbol2.name===name||symbol2.typeNames.includes(name))&&results.push(symbol2);return results}removeUri(uri){this.clearUri(uri),this.symbolsByUri.delete(uri)}clearUri(uri){let existing=this.symbolsByUri.get(uri);if(existing)for(let sym of existing)this.symbols.delete(sym.qualifiedName);this.symbolsByUri.set(uri,[])}walkTree(ctx2,uri,currentScope,parentQualifiedName){let ruleName=this.getRuleName(ctx2),symbol2=this.tryExtractSymbol(ctx2,uri,ruleName,parentQualifiedName),childScope=currentScope;symbol2&&(this.registerSymbol(symbol2,uri,currentScope),childScope=new Scope(symbol2.qualifiedName,currentScope));for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);child instanceof ParserRuleContext&&this.walkTree(child,uri,childScope,symbol2?.qualifiedName??parentQualifiedName)}}registerSymbol(symbol2,uri,scope){this.symbols.set(symbol2.qualifiedName,symbol2);let uriSymbols=this.symbolsByUri.get(uri)??[];uriSymbols.push(symbol2),this.symbolsByUri.set(uri,uriSymbols),scope.define(symbol2)}getRuleName(ctx2){let idx=ctx2.ruleIndex;if(idx>=0&&idx<SysMLv2Parser.ruleNames.length)return SysMLv2Parser.ruleNames[idx];let ctorName=ctx2.constructor.name;return ctorName.endsWith("Context")?ctorName.slice(0,-7):ctorName}tryExtractSymbol(ctx2,uri,ruleName,parentQualifiedName){let kind=this.inferKind(ruleName,ctx2);if(kind===void 0)return;let name=this.extractName(ctx2);if(!name)return;let qualifiedName=parentQualifiedName?`${parentQualifiedName}::${name}`:name,range=contextToRange(ctx2),selectionRange=this.extractNameRange(ctx2)??range,typeNames=this.extractTypeNames(ctx2),typeName=typeNames[0],documentation=this.extractDocumentation(ctx2),{multiplicity,multiplicityRange}=isUsage(kind)?this.extractMultiplicity(ctx2):{},metadataAnnotations=this.extractPrefixMetadataAnnotations(ctx2);return{name,kind,qualifiedName,range,selectionRange,uri,typeName,typeNames,documentation,parentQualifiedName:parentQualifiedName||void 0,children:[],multiplicity,multiplicityRange,metadataAnnotations:metadataAnnotations.length>0?metadataAnnotations:void 0}}inferKind(ruleName,_ctx){let lower=ruleName.toLowerCase();if(lower==="package"||lower==="librarypackage")return"package";if(lower==="partdefinition")return"part def";if(lower==="attributedefinition")return"attribute def";if(lower==="portdefinition")return"port def";if(lower==="connectiondefinition")return"connection def";if(lower==="interfacedefinition")return"interface def";if(lower==="actiondefinition")return"action def";if(lower==="statedefinition")return"state def";if(lower==="requirementdefinition")return"requirement def";if(lower==="constraintdefinition")return"constraint def";if(lower==="itemdefinition")return"item def";if(lower==="allocationdefinition")return"allocation def";if(lower==="usecasedefinition")return"use case def";if(lower==="enumerationdefinition")return"enum def";if(lower==="enumeratedvalue")return"enum";if(lower==="enumerationusage")return"enum";if(lower==="calculationdefinition"||lower==="calcdefinition")return"calc def";if(lower==="viewdefinition")return"view def";if(lower==="viewpointdefinition")return"viewpoint def";if(lower==="metadatadefinition")return"metadata def";if(lower==="partusage")return"part";if(lower==="attributeusage")return"attribute";if(lower==="portusage")return"port";if(lower==="connectionusage")return"connection";if(lower==="actionusage")return"action";if(lower==="stateusage")return"state";if(lower==="requirementusage")return"requirement";if(lower==="constraintusage")return"constraint";if(lower==="itemusage")return"item";if(lower==="allocationusage")return"allocation";if(lower==="usecaseusage")return"use case";if(lower==="includeusecaseusage")return"include use case";if(lower==="actorusage")return"actor";if(lower==="subjectusage")return"subject";if(lower==="stakeholderusage")return"stakeholder";if(lower==="referenceusage")return"ref";if(lower==="interfaceusage")return"interface";if(lower==="performactionusage")return"perform action";if(lower==="exhibitstateusage")return"exhibit state";if(lower==="transitionusage")return"transition";if(lower==="occurrencedefinition")return"occurrence def";if(lower==="occurrenceusage")return"occurrence";if(lower==="renderingdefinition")return"rendering def";if(lower==="viewusage")return"view";if(lower==="viewpointusage")return"viewpoint";if(lower==="verificationcasedefinition")return"verification case def";if(lower==="verificationcaseusage")return"verification case";if(lower==="analysiscasedefinition")return"analysis case def";if(lower==="analysiscaseusage")return"analysis case";if(lower==="aliasmember")return"alias"}extractName(ctx2){for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof TerminalNode){let token=child.symbol;if(this.isIdentifierToken(token))return this.unquoteName(token.text??"")}if(child instanceof ParserRuleContext){let childRule=this.getRuleName(child);if(childRule.toLowerCase().includes("identification")||childRule.toLowerCase().includes("declarationname")||childRule.toLowerCase().includes("qualifiedname")||childRule.toLowerCase()==="name"){let name=this.extractTextFromSubtree(child);if(name)return name}}}for(let i=0;i<Math.min(ctx2.getChildCount(),5);i++){let child=ctx2.getChild(i);if(child instanceof ParserRuleContext){if(this.isPrefixOrExtensionContext(child))continue;let name=this.extractName(child);if(name)return name}}}extractNameRange(ctx2){for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof TerminalNode&&this.isIdentifierToken(child.symbol))return tokenToRange(child.symbol);if(child instanceof ParserRuleContext){if(this.isPrefixOrExtensionContext(child))continue;let result=this.extractNameRange(child);if(result)return result}}}extractTypeNames(ctx2){let names=[];if(this.collectTypeNamesFromTree(ctx2,names,0),names.length>0)return names;let fullText=ctx2.getText(),braceIdx=fullText.indexOf("{"),text=braceIdx>=0?fullText.substring(0,braceIdx):fullText;text=text.replace(/(redefines|subsets|references|connect|bind|first|then|flow|allocate|assign|accept|send|decide|merge|join|fork|via|default)\b.*/i,"");let specMatch=text.match(/(?:specializes|:>|:>>)\s*('[^']+'|[A-Za-z_]\w*(?:::\w+)*)(?:\s*,\s*(?:'[^']+'|[A-Za-z_]\w*(?:::\w+)*))*/);if(specMatch){let specStr=text.substring(text.indexOf(specMatch[0])+specMatch[0].indexOf(specMatch[1]));for(let part of specStr.split(",")){let qm=part.match(/'([^']+)'/);if(qm){names.push(qm[1]);continue}let m2=part.trim().match(/^([A-Za-z_]\w*(?:::\w+)*)/);m2&&names.push(m2[1])}return names}let defByMatch=text.match(/definedby\s*([A-Za-z_]\w*(?:::\w+)*(?:\s*,\s*[A-Za-z_]\w*(?:::\w+)*)*)/);if(defByMatch){for(let part of defByMatch[1].split(",")){let m2=part.trim().match(/^([A-Za-z_]\w*(?:::\w+)*)/);m2&&names.push(m2[1])}return names}let typingMatch=text.match(/:(?![:>])\s*('[^']+'|[A-Za-z_]\w*(?:::\w+)*)/);if(typingMatch){let fullMatchIdx=text.indexOf(typingMatch[0]),afterColon=text.substring(fullMatchIdx+1).trim();for(let part of afterColon.split(",")){let qm=part.match(/'([^']+)'/);if(qm){names.push(qm[1]);continue}let m2=part.trim().match(/^([A-Za-z_]\w*(?:::\w+)*)/);m2&&names.push(m2[1])}return names}return names}collectTypeNamesFromTree(ctx2,names,depth){if(!(depth>6))for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(!(child instanceof ParserRuleContext))continue;let rn=this.getRuleName(child).toLowerCase();if(rn.includes("specialization")||rn.includes("subclassification")||rn.includes("typing")||rn.includes("conjugation")||rn.includes("disjoining")){let stripped=child.getText().replace(/^(specializes|:>|:>>|:\s|definedby|subsets|redefines|references|conjugates|disjoints)/i,"");for(let part of stripped.split(",")){let qm=part.match(/'([^']+)'/);if(qm)names.push(qm[1]);else{let m2=part.match(/([A-Za-z_]\w*(?:::\w+)*)/);m2&&names.push(m2[1])}}}else(rn.includes("declaration")||rn.includes("featurespecialization")||rn.includes("typings")||rn.includes("usagecompletion")||rn==="usage"||rn==="definition")&&this.collectTypeNamesFromTree(child,names,depth+1)}}extractDocumentation(ctx2){for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof ParserRuleContext){let ruleName=this.getRuleName(child).toLowerCase();if(ruleName.includes("comment")||ruleName.includes("doc")||ruleName.includes("documentation")){let raw=child.getText();if(raw){let text=raw;return text.startsWith("doc")&&(text=text.slice(3)),text.startsWith("comment")&&(text=text.slice(7)),text=text.replace(/^\/\*\s*/,"").replace(/\s*\*\/$/,""),text=text.replace(/^\/\/\s*/,""),text.trim()||raw}return raw??void 0}let nested=this.extractDocumentation(child);if(nested)return nested}}}extractMultiplicity(ctx2){let multCtx=this.findMultiplicityBounds(ctx2);if(!multCtx)return{};let members=multCtx.multiplicityExpressionMember();if(!members||members.length===0)return{};let values=[];for(let member of members){let rawText=member.getText()?.trim();rawText&&values.push(rawText)}if(values.length===0)return{};let lower,upper,multiplicity;if(values.length===1)if(multiplicity=values[0],values[0]==="*")lower=0,upper="*";else{let num=parseInt(values[0],10);if(isNaN(num))return{multiplicity};lower=num,upper=num}else{if(multiplicity=`${values[0]}..${values[1]}`,lower=parseInt(values[0],10),isNaN(lower))return{multiplicity};if(values[1]==="*")upper="*";else if(upper=parseInt(values[1],10),isNaN(upper))return{multiplicity}}return{multiplicity,multiplicityRange:{lower,upper}}}findMultiplicityBounds(ctx2){if(ctx2.ruleIndex===SysMLv2Parser.RULE_multiplicityBounds)return ctx2;for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof ParserRuleContext){let result=this.findMultiplicityBounds(child);if(result)return result}}}isPrefixOrExtensionContext(ctx2){let rule=this.getRuleName(ctx2).toLowerCase();return rule.includes("prefixmetadata")||rule.includes("extensionkeyword")||rule==="occurrencedefinitionprefix"||rule==="occurrenceusageprefix"||rule==="definitionprefix"||rule==="basicdefinitionprefix"||rule==="typeprefix"||rule==="featureprefix"||rule==="basicfeatureprefix"||rule==="endfeatureprefix"}extractPrefixMetadataAnnotations(ctx2){let annotations=[];return this.collectPrefixMetadata(ctx2,annotations,0),annotations}collectPrefixMetadata(ctx2,annotations,depth){if(!(depth>4))for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(!(child instanceof ParserRuleContext))continue;let rule=this.getRuleName(child).toLowerCase();if(rule==="prefixmetadatamember"||rule==="prefixmetadataannotation"){let name=this.extractTextFromSubtree(child);name&&annotations.push(name)}else(rule.includes("prefix")||rule.includes("extensionkeyword")||rule==="definition"||rule==="usage")&&this.collectPrefixMetadata(child,annotations,depth+1)}}isIdentifierToken(token){let text=token.text;return text?this.isQuotedName(text)?!0:/^[a-zA-Z_]/.test(text)&&!this.isKeyword(text):!1}isQuotedName(text){return text.length>=3&&text.startsWith("'")&&text.endsWith("'")}unquoteName(text){return this.isQuotedName(text)?text.slice(1,-1):text}isKeyword(text){return new Set(["about","abstract","accept","action","actor","after","alias","all","allocate","allocation","analysis","and","as","assert","assign","assume","attribute","bind","binding","bool","by","calc","case","comment","concern","connect","connection","constraint","decide","def","default","defined","dependency","derived","do","doc","else","end","entry","enum","event","exhibit","exit","expose","false","feature","filter","first","flow","for","fork","frame","from","hastype","if","implies","import","in","include","individual","inout","interface","istype","item","join","language","library","locale","merge","message","meta","metadata","multiplicity","namespace","nonunique","not","null","objective","occurrence","of","or","ordered","out","package","parallel","part","perform","port","private","protected","public","readonly","redefines","ref","references","render","rendering","rep","require","requirement","return","satisfy","send","snapshot","specializes","stakeholder","state","subject","subsets","succession","then","timeslice","to","transition","true","type","use","variant","variation","verification","verify","view","viewpoint","when","while","xor"]).has(text)}extractTextFromSubtree(ctx2){let parts=[];for(let i=0;i<ctx2.getChildCount();i++){let child=ctx2.getChild(i);if(child instanceof TerminalNode){let text=child.symbol.text;text&&this.isIdentifierToken(child.symbol)&&parts.push(this.unquoteName(text))}else if(child instanceof ParserRuleContext){let sub=this.extractTextFromSubtree(child);sub&&parts.push(sub)}}return parts.length>0?parts.join("::"):void 0}};var SYSML_KEYWORDS_ARRAY=SysMLv2Lexer.literalNames.filter(n2=>n2!=null).map(n2=>n2.replace(/^'|'$/g,"")).filter(n2=>/^[a-z]+$/.test(n2)).sort(),SYSML_KEYWORDS=new Set(SYSML_KEYWORDS_ARRAY);var McpContext=class{symbolTable=new SymbolTable;loadedDocuments=new Map;loadedDocumentHashes=new Map;lastParseErrors=new Map;lastParseTiming=new Map};function hashTextFNV1a(text){let hash2=2166136261;for(let i=0;i<text.length;i++)hash2^=text.charCodeAt(i),hash2=Math.imul(hash2,16777619);return hash2>>>0}function ensureParsed(ctx2,uri,code){if(code!==void 0){parseAndBuild(ctx2,code,uri);return}if(ctx2.symbolTable.getSymbolsForUri(uri).length===0){let cached2=ctx2.loadedDocuments.get(uri);cached2&&parseAndBuild(ctx2,cached2,uri)}}function formatSymbol(sym){return{name:sym.name,kind:sym.kind,qualifiedName:sym.qualifiedName,...sym.typeNames.length>0?{type:sym.typeNames.join(", ")}:{},...sym.documentation?{documentation:sym.documentation}:{},...sym.parentQualifiedName?{parent:sym.parentQualifiedName}:{},...sym.children.length>0?{children:sym.children}:{},location:{uri:sym.uri,range:sym.range}}}function formatError2(err){return{line:err.line+1,column:err.column+1,message:err.message,length:err.length}}function parseAndBuild(ctx2,text,uri){let hash2=hashTextFNV1a(text),prevHash=ctx2.loadedDocumentHashes.get(uri),currentSymbolCount=ctx2.symbolTable.getSymbolsForUri(uri).length,cachedErrors=ctx2.lastParseErrors.get(uri)??[],canReuseCachedParse=currentSymbolCount>0||cachedErrors.length>0;if(prevHash===hash2&&ctx2.lastParseTiming.has(uri)&&canReuseCachedParse)return{errors:cachedErrors,symbolCount:currentSymbolCount,timingMs:ctx2.lastParseTiming.get(uri)??{lex:0,parse:0}};let result=parseDocument(text);ctx2.symbolTable.build(uri,result),ctx2.loadedDocuments.set(uri,text),ctx2.loadedDocumentHashes.set(uri,hash2),ctx2.lastParseErrors.set(uri,result.errors);let timing={lex:result.timing.lexMs,parse:result.timing.parseMs};return ctx2.lastParseTiming.set(uri,timing),{errors:result.errors,symbolCount:ctx2.symbolTable.getSymbolsForUri(uri).length,timingMs:timing}}function handleParse(ctx2,code,uri){let docUri=uri??"untitled.sysml",{errors,symbolCount,timingMs}=parseAndBuild(ctx2,code,docUri),summary={uri:docUri,symbolCount,errorCount:errors.length,timing:timingMs};errors.length>0&&(summary.errors=errors.map(formatError2));let topLevel=ctx2.symbolTable.getSymbolsForUri(docUri).filter(s=>!s.parentQualifiedName).map(s=>`${s.kind} ${s.qualifiedName}`);return topLevel.length>0&&(summary.topLevelElements=topLevel),summary}function handlePreview(ctx2,opts){let docUri=opts.uri??"preview.sysml",{errors}=parseAndBuild(ctx2,opts.code,docUri),allSymbols=ctx2.symbolTable.getSymbolsForUri(docUri),allNames=new Set(ctx2.symbolTable.getAllSymbols().map(s=>s.name)),semanticDiags=SemanticValidator.validateSymbols(allSymbols,allNames,{allSymbols:ctx2.symbolTable.getAllSymbols(),text:opts.code,uri:docUri}),renderSymbols=allSymbols;if(opts.focus){let focusName=opts.focus,focusSet=new Set,childrenOf=new Map;for(let s of allSymbols)if(s.parentQualifiedName){let list=childrenOf.get(s.parentQualifiedName)??[];list.push(s),childrenOf.set(s.parentQualifiedName,list)}let focused=allSymbols.filter(s=>s.name===focusName||s.qualifiedName===focusName||s.qualifiedName.endsWith(`::${focusName}`));for(let f of focused){focusSet.add(f.qualifiedName);let children=childrenOf.get(f.qualifiedName)??[];for(let child of children)focusSet.add(child.qualifiedName);f.parentQualifiedName&&focusSet.add(f.parentQualifiedName);let typeSource=[...f.typeNames];for(let child of children)typeSource.push(...child.typeNames);for(let tn of typeSource){let typed=allSymbols.find(s=>s.name===tn||s.qualifiedName===tn);if(typed){focusSet.add(typed.qualifiedName);for(let child of childrenOf.get(typed.qualifiedName)??[])focusSet.add(child.qualifiedName)}}}focusSet.size>0&&(renderSymbols=allSymbols.filter(s=>focusSet.has(s.qualifiedName)))}let mermaid=generateMermaidDiagram(renderSymbols,allSymbols,opts.diagramType),result={diagram:mermaid.diagram,diagramType:mermaid.diagramType,description:mermaid.description,elementCount:mermaid.elementCount,errors:errors.map(formatError2)};if(opts.originalCode){let origUri="preview-original.sysml",origResult=parseDocument(opts.originalCode),origTable=new SymbolTable;origTable.build(origUri,origResult);let origSymbols=origTable.getSymbolsForUri(origUri),diff=diffSymbols(origSymbols,allSymbols);result.diff={added:diff.added.map(s=>`${s.kind} ${s.qualifiedName}`),changed:diff.changed.map(s=>`${s.kind} ${s.qualifiedName}`),removed:diff.removed,unchangedCount:diff.unchanged.length}}return semanticDiags.length>0&&(result.semanticIssues=semanticDiags.map(d=>({line:d.range.start.line+1,column:d.range.start.character+1,message:d.message,severity:d.severity===1?"error":d.severity===2?"warning":"info"}))),result}function handleValidate(ctx2,code,uri){let docUri=uri??"untitled.sysml",{errors}=parseAndBuild(ctx2,code,docUri),symbols=ctx2.symbolTable.getSymbolsForUri(docUri),allNames=new Set(ctx2.symbolTable.getAllSymbols().map(s=>s.name)),semanticDiags=SemanticValidator.validateSymbols(symbols,allNames,{allSymbols:ctx2.symbolTable.getAllSymbols(),text:code,uri:docUri}),semanticIssues=semanticDiags.map(d=>({line:d.range.start.line+1,column:d.range.start.character+1,message:d.message,severity:d.severity===1?"error":d.severity===2?"warning":d.severity===3?"info":"hint",code:d.code}));return{valid:errors.length===0&&semanticDiags.filter(d=>d.severity===1).length===0,syntaxErrors:errors.map(formatError2),semanticIssues,totalIssues:errors.length+semanticDiags.length}}function handleGetDiagnostics(ctx2,uri,code){let docUri=uri??"untitled.sysml";ensureParsed(ctx2,docUri,code);let symbols=ctx2.symbolTable.getSymbolsForUri(docUri),allNames=new Set(ctx2.symbolTable.getAllSymbols().map(s=>s.name)),diags=SemanticValidator.validateSymbols(symbols,allNames,{allSymbols:ctx2.symbolTable.getAllSymbols(),text:code??ctx2.loadedDocuments.get(docUri),uri:docUri}),summary={};for(let d of diags){let code2=String(d.code??"unknown");summary[code2]=(summary[code2]??0)+1}return{uri:docUri,diagnostics:diags.map(d=>({line:d.range.start.line+1,column:d.range.start.character+1,message:d.message,severity:d.severity===1?"error":d.severity===2?"warning":d.severity===3?"info":"hint",code:d.code})),summary}}function handleGetSymbols(ctx2,opts){if(opts.code){let docUri=opts.uri??"untitled.sysml";ensureParsed(ctx2,docUri,opts.code)}let symbols=opts.uri?ctx2.symbolTable.getSymbolsForUri(opts.uri):ctx2.symbolTable.getAllSymbols();return opts.kind&&(symbols=symbols.filter(s=>s.kind.toLowerCase()===opts.kind.toLowerCase())),opts.definitionsOnly&&(symbols=symbols.filter(s=>isDefinition(s.kind))),opts.usagesOnly&&(symbols=symbols.filter(s=>isUsage(s.kind))),{count:symbols.length,symbols:symbols.map(formatSymbol)}}function handleGetDefinition(ctx2,name,code,uri){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let exact=ctx2.symbolTable.getSymbol(name);if(exact)return formatSymbol(exact);let matches=ctx2.symbolTable.findByName(name);return matches.length===0?{found:!1,message:`No symbol found with name "${name}"`}:{found:!0,count:matches.length,symbols:matches.map(formatSymbol)}}function handleGetReferences(ctx2,name,code,uri){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let refs=ctx2.symbolTable.findReferences(name);return{name,referenceCount:refs.length,references:refs.map(formatSymbol)}}function handleGetHierarchy(ctx2,name,code,uri){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let target=ctx2.symbolTable.getSymbol(name)??ctx2.symbolTable.findByName(name)[0];if(!target)return{found:!1,message:`No symbol "${name}" found`};let ancestors=[],current=target.parentQualifiedName;for(;current;){let parent=ctx2.symbolTable.getSymbol(current);if(!parent)break;ancestors.unshift({name:parent.name,kind:parent.kind,qualifiedName:parent.qualifiedName}),current=parent.parentQualifiedName}let children=target.children.map(qn=>ctx2.symbolTable.getSymbol(qn)).filter(s=>s!==void 0).map(s=>({name:s.name,kind:s.kind,qualifiedName:s.qualifiedName,...s.typeNames.length>0?{type:s.typeNames.join(", ")}:{}}));return{element:{name:target.name,kind:target.kind,qualifiedName:target.qualifiedName,...target.typeNames.length>0?{type:target.typeNames.join(", ")}:{}},ancestors,children}}function handleGetModelSummary(ctx2,code,uri){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let allSymbols=ctx2.symbolTable.getAllSymbols(),kindCounts={};for(let sym of allSymbols)kindCounts[sym.kind]=(kindCounts[sym.kind]??0)+1;let sorted=Object.entries(kindCounts).sort(([,a],[,b])=>b-a);return{totalSymbols:allSymbols.length,loadedDocuments:Array.from(ctx2.loadedDocuments.keys()),elementsByKind:Object.fromEntries(sorted),definitions:allSymbols.filter(s=>isDefinition(s.kind)).length,usages:allSymbols.filter(s=>isUsage(s.kind)).length}}function handleGetComplexity(ctx2,uri,code){code&&ensureParsed(ctx2,uri??"untitled.sysml",code);let symbols=uri?ctx2.symbolTable.getSymbolsForUri(uri):ctx2.symbolTable.getAllSymbols();return analyseComplexity(symbols)}function getElementKinds(){let kinds=Object.values(SysMLElementKind);return{definitions:kinds.filter(k=>isDefinition(k)),usages:kinds.filter(k=>isUsage(k)),other:kinds.filter(k=>!isDefinition(k)&&!isUsage(k)),total:kinds.length}}function handleResourceElementKinds(){return getElementKinds()}function handleResourceKeywords(){return{keywords:SYSML_KEYWORDS_ARRAY,count:SYSML_KEYWORDS_ARRAY.length}}function handleResourceGrammarOverview(){return"# SysML v2 Grammar Overview\n\n## Element Categories\n\n### Definitions (Types)\nDefinitions declare reusable types:\n- `part def` \u2014 structural element type\n- `attribute def` \u2014 value type\n- `port def` \u2014 interface point type\n- `connection def` \u2014 connection type\n- `interface def` \u2014 interface type\n- `action def` \u2014 behavior type\n- `state def` \u2014 state machine type\n- `requirement def` \u2014 requirement type\n- `constraint def` \u2014 constraint type\n- `item def` \u2014 general item type\n- `enum def` \u2014 enumeration type\n- `calc def` \u2014 calculation type\n- `use case def` \u2014 use case type\n- `allocation def` \u2014 allocation type\n- `view def` / `viewpoint def` \u2014 viewpoint types\n\n### Usages (Instances)\nUsages create instances of definitions:\n- `part` \u2014 structural instance\n- `attribute` \u2014 value instance\n- `port` \u2014 port instance\n- `action` \u2014 action step\n- `state` \u2014 state instance\n- `requirement` \u2014 requirement instance\n- `item` \u2014 item instance\n\n## Specialisation Syntax\n- `part car : Vehicle` \u2014 `car` specialises `Vehicle`\n- `part car :> baseVehicle` \u2014 `car` subsets `baseVehicle`\n- `part car :>> specificVehicle` \u2014 `car` redefines `specificVehicle`\n\n## Packages & Namespaces\n```sysml\npackage VehicleModel {\n part def Vehicle { ... }\n part car : Vehicle;\n}\n```\n\n## Documentation\n```sysml\npart def Vehicle {\n doc /* A general vehicle definition */\n attribute mass : Real;\n}\n```\n\n## Unrestricted Names\nNames with spaces use single quotes: `part 'Main Assembly' : Assembly;`\n"}function handlePromptReviewSysml(ctx2,code){let{errors,symbolCount}=parseAndBuild(ctx2,code,"review.sysml"),allSymbols=ctx2.symbolTable.getSymbolsForUri("review.sysml"),defs=allSymbols.filter(s=>isDefinition(s.kind)),usages=allSymbols.filter(s=>isUsage(s.kind)),context=[`Parsed: ${symbolCount} symbols, ${errors.length} syntax errors`,`Definitions: ${defs.map(d=>`${d.kind} ${d.name}`).join(", ")||"none"}`,`Usages: ${usages.map(u=>`${u.kind} ${u.name}`).join(", ")||"none"}`];return errors.length>0&&context.push(`Errors: ${errors.map(e=>`line ${e.line+1}: ${e.message}`).join("; ")}`),[{role:"user",content:{type:"text",text:`Please review the following SysML v2 model for correctness, completeness, and best practices.
111
111
 
112
112
  ## Parse Results
113
113
  ${context.join(`