sysml-v2-lsp 0.19.0 → 0.20.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.
@@ -52,7 +52,7 @@ ${stack}`)},console.warn=function(...args){logger.warn(serialize(args))}}}});var
52
52
  `));let result={declaration:declLine,packageName,documentation};if(hoverInfoCache.size>=HOVER_CACHE_MAX){let firstKey=hoverInfoCache.keys().next().value;firstKey!==void 0&&hoverInfoCache.delete(firstKey)}return hoverInfoCache.set(name,result),result}var WEIGHTS={size:.25,depth:.2,coupling:.25,docDebt:.1,fanOut:.2};function analyseComplexity(symbols){if(symbols.length===0)return emptyReport();let defs=symbols.filter(s=>isDefinition(s.kind)),usages=symbols.filter(s=>isUsage(s.kind)),packages=symbols.filter(s=>s.kind==="package"),depthMap=computeDepths(symbols),maxDepth=Math.max(...Array.from(depthMap.values()),0),byQualifiedName=new Map(symbols.map(s=>[s.qualifiedName,s])),childCounts=new Map;for(let d of defs)childCounts.set(d.qualifiedName,0);for(let s of symbols)s.parentQualifiedName&&childCounts.has(s.parentQualifiedName)&&childCounts.set(s.parentQualifiedName,(childCounts.get(s.parentQualifiedName)??0)+1);let avgChildrenPerDef=defs.length>0?round(Array.from(childCounts.values()).reduce((a,b)=>a+b,0)/defs.length):0,defNames=new Set(defs.map(d=>d.name)),couplingCount=0,typeRefsPerDef=new Map;for(let d of defs)typeRefsPerDef.set(d.qualifiedName,0);let advanced=computeAdvancedSignals(symbols,defs,byQualifiedName);for(let s of usages)for(let tn of s.typeNames)defNames.has(tn)&&(couplingCount++,s.parentQualifiedName&&typeRefsPerDef.has(s.parentQualifiedName)&&typeRefsPerDef.set(s.parentQualifiedName,(typeRefsPerDef.get(s.parentQualifiedName)??0)+1));let referencedTypes=new Set(usages.flatMap(s=>s.typeNames)),unusedDefinitions=defs.filter(d=>d.kind!=="enum def"&&!referencedTypes.has(d.name)).length,documentedDefs=defs.filter(d=>d.documentation).length,documentationCoverage=defs.length>0?round(documentedDefs/defs.length*100):100,hotspots=defs.map(d=>{let cc=childCounts.get(d.qualifiedName)??0,dp=depthMap.get(d.qualifiedName)??0,tr=typeRefsPerDef.get(d.qualifiedName)??0,hasDoc=!!d.documentation,behaviorSignal=advanced.behaviorByDef.get(d.qualifiedName)??0,score=computeDefScore(cc,dp,tr,hasDoc,behaviorSignal);return{qualifiedName:d.qualifiedName,kind:d.kind,childCount:cc,depth:dp,typeRefs:tr,hasDoc,score}}).sort((a,b)=>b.score-a.score),enrichedDepth=Math.max(maxDepth,advanced.maxCalcChainDepth+1),enrichedCoupling=couplingCount+advanced.specializationLinks+Math.round(advanced.performUsages*.5)+Math.round(advanced.transitionUsages*.5)+Math.round(advanced.stdLibTypeRefs*.6),enrichedFanOut=avgChildrenPerDef+advanced.actionComplexityBonus,complexityIndex=computeIndex(symbols.length,enrichedDepth,enrichedCoupling,defs.length,enrichedFanOut,documentationCoverage);return{totalElements:symbols.length,definitions:defs.length,usages:usages.length,packages:packages.length,maxDepth,avgChildrenPerDef,couplingCount,unusedDefinitions,documentationCoverage,complexityIndex,rating:indexToRating(complexityIndex),hotspots}}function computeAdvancedSignals(symbols,defs,byQualifiedName){let defNames=new Set(defs.map(d=>d.name)),behaviorByDef=new Map;for(let d of defs)behaviorByDef.set(d.qualifiedName,0);let specializationLinks=0,performUsages=0,transitionUsages=0,stdLibTypeRefs=0,maxCalcChainDepth=0,actionComplexityBonus=0,addBehavior=(qualifiedName,amount)=>{!qualifiedName||!behaviorByDef.has(qualifiedName)||behaviorByDef.set(qualifiedName,(behaviorByDef.get(qualifiedName)??0)+amount)};for(let d of defs)specializationLinks+=d.typeNames.length,addBehavior(d.qualifiedName,Math.min(3,d.typeNames.length));for(let s of symbols){switch(s.kind){case"perform action":performUsages++,addBehavior(s.parentQualifiedName,2);break;case"calc":addBehavior(s.parentQualifiedName,2);break;case"calc def":addBehavior(s.parentQualifiedName,1);break;case"transition":transitionUsages++,addBehavior(s.parentQualifiedName,2);break;case"exhibit state":addBehavior(s.parentQualifiedName,1);break;default:break}if(s.kind==="action def"){let localBehavior=symbols.filter(c=>c.parentQualifiedName===s.qualifiedName).reduce((score,c)=>c.kind==="perform action"||c.kind==="calc"||c.kind==="calc def"?score+2:c.kind==="action"?score+1:score,0);actionComplexityBonus+=Math.min(4,localBehavior/4),addBehavior(s.qualifiedName,Math.min(4,localBehavior))}if(s.kind==="calc"||s.kind==="calc def"){let chainDepth=calcChainDepth(s,byQualifiedName);chainDepth>maxCalcChainDepth&&(maxCalcChainDepth=chainDepth),addBehavior(s.parentQualifiedName,Math.min(3,chainDepth))}for(let typeName of s.typeNames)defNames.has(typeName)||looksLikeStdLibType(typeName)&&(stdLibTypeRefs++,addBehavior(s.parentQualifiedName,1))}return{specializationLinks,performUsages,transitionUsages,stdLibTypeRefs,maxCalcChainDepth,actionComplexityBonus,behaviorByDef}}function calcChainDepth(symbol,byQualifiedName){let depth=1,cursor=symbol.parentQualifiedName?byQualifiedName.get(symbol.parentQualifiedName):void 0;for(;cursor&&(cursor.kind==="calc"||cursor.kind==="calc def");)depth++,cursor=cursor.parentQualifiedName?byQualifiedName.get(cursor.parentQualifiedName):void 0;return depth}function looksLikeStdLibType(typeName){return typeName?typeName.includes("::")?!0:new Set(["String","Boolean","Integer","Natural","Real","Complex","Number","Map","OrderedMap","Set","Sequence","Bag","Vector","KeyValuePair","Duration","Time","DateTime","Mass","Length","Speed","Acceleration"]).has(typeName):!1}function emptyReport(){return{totalElements:0,definitions:0,usages:0,packages:0,maxDepth:0,avgChildrenPerDef:0,couplingCount:0,unusedDefinitions:0,documentationCoverage:100,complexityIndex:0,rating:"trivial",hotspots:[]}}function computeDepths(symbols){let result=new Map,byQN=new Map(symbols.map(s=>[s.qualifiedName,s]));function depth(qn){if(result.has(qn))return result.get(qn);let sym=byQN.get(qn);if(!sym||!sym.parentQualifiedName)return result.set(qn,0),0;let d=depth(sym.parentQualifiedName)+1;return result.set(qn,d),d}for(let s of symbols)depth(s.qualifiedName);return result}function computeIndex(elementCount,maxDepth,coupling,defCount,avgFanOut,docCoverage){let sizeN=clamp(Math.log2(Math.max(elementCount,1))/10),depthN=clamp(maxDepth/8),couplingN=defCount>0?clamp(coupling/defCount/5):0,fanOutN=clamp(avgFanOut/15),docDebtN=clamp(1-docCoverage/100),raw=WEIGHTS.size*sizeN+WEIGHTS.depth*depthN+WEIGHTS.coupling*couplingN+WEIGHTS.fanOut*fanOutN+WEIGHTS.docDebt*docDebtN;return Math.round(raw*100)}function computeDefScore(childCount,depth,typeRefs,hasDoc,behaviorSignal=0){let cc=clamp(childCount/15)*30,dp=clamp(depth/6)*20,tr=clamp(typeRefs/5)*25,dc=hasDoc?0:15,bs=clamp(behaviorSignal/8)*10;return Math.round(Math.min(100,cc+dp+tr+dc+bs))}function indexToRating(index2){return index2<=10?"trivial":index2<=25?"simple":index2<=50?"moderate":index2<=75?"complex":"very complex"}function clamp(value){return Math.max(0,Math.min(1,value))}function round(value){return Math.round(value*100)/100}function containsWord(text,word){let idx=0;for(;(idx=text.indexOf(word,idx))!==-1;){let before=idx>0?text.charCodeAt(idx-1):32,after=idx+word.length<text.length?text.charCodeAt(idx+word.length):32;if(!isIdentPart(before)&&!isIdentPart(after))return!0;idx+=1}return!1}function findWordPositions(text,word){let results=[],idx=0;for(;(idx=text.indexOf(word,idx))!==-1;){let before=idx>0?text.charCodeAt(idx-1):32,afterIdx=idx+word.length,after=afterIdx<text.length?text.charCodeAt(afterIdx):32;!isIdentPart(before)&&!isIdentPart(after)&&results.push({pos:idx,afterPos:afterIdx}),idx+=1}return results}function findWordPositionsCI(text,word){let lower=text.toLowerCase(),wordLower=word.toLowerCase(),results=[],idx=0;for(;(idx=lower.indexOf(wordLower,idx))!==-1;){let before=idx>0?lower.charCodeAt(idx-1):32,afterIdx=idx+wordLower.length,after=afterIdx<lower.length?lower.charCodeAt(afterIdx):32;!isIdentPart(before)&&!isIdentPart(after)&&results.push({pos:idx,afterPos:afterIdx}),idx+=1}return results}function skipWS(text,pos){for(;pos<text.length;){let ch=text[pos];if(ch===" "||ch===" "||ch===`
53
53
  `||ch==="\r")pos++;else break}return pos}function readIdent(text,pos,allowDots=!1){let end=pos;for(;end<text.length;){let ch=text.charCodeAt(end);if(isIdentPart(ch))end++;else if(allowDots&&text[end]===".")end++;else if(text[end]===":"&&end+1<text.length&&text[end+1]===":")end+=2;else break}return[text.substring(pos,end),end]}function readNameOrQuoted(text,pos,allowDots=!1){if(pos<text.length&&text[pos]==="'"){let close=text.indexOf("'",pos+1);if(close>=0)return[text.substring(pos+1,close),close+1]}return readIdent(text,pos,allowDots)}function readWordAfterKeyword(text,afterPos,allowDots=!1){let start=skipWS(text,afterPos);return readIdent(text,start,allowDots)}function readCommaSeparatedIdents(text,pos){let names=[],p=skipWS(text,pos);for(;p<text.length;){let[name,end]=readIdent(text,p);if(!name)break;if(names.push(name),p=skipWS(text,end),p<text.length&&text[p]===",")p=skipWS(text,p+1);else break}return names}var SysMLModelProvider=class{constructor(documentManager2){this.documentManager=documentManager2}documentManager;_stCache=new Map;removeUri(uri){this._stCache.delete(uri)}clearAll(){let count=this._stCache.size;return this._stCache.clear(),count}get cacheSize(){return this._stCache.size}_getSymbolTable(uri,parseResult){let version=this.documentManager.getVersion(uri),cached=this._stCache.get(uri);if(cached&&cached.version===version)return cached.table;let table=new SymbolTable;return table.build(uri,parseResult),this._stCache.set(uri,{version,table}),table}getModel(uri,version,scopes){let startTime=Date.now(),parseResult=this.documentManager.get(uri);if(!parseResult)return{version:-1};let scopeSet=new Set(scopes&&scopes.length>0?scopes:["elements","relationships","sequenceDiagrams","activityDiagrams","resolvedTypes","diagnostics"]),symbolTable=this._getSymbolTable(uri,parseResult),lines=(this.documentManager.getText(uri)??"").split(`
54
54
  `),result={version};scopeSet.has("elements")&&(result.elements=this.convertToElementDTOs(symbolTable,uri,lines)),scopeSet.has("relationships")&&(result.relationships=this.extractRelationships(symbolTable,uri,lines)),scopeSet.has("sequenceDiagrams")&&(result.sequenceDiagrams=this.extractSequenceDiagrams(symbolTable,uri,lines)),scopeSet.has("activityDiagrams")&&(result.activityDiagrams=this.extractActivityDiagrams(symbolTable,uri,lines)),scopeSet.has("resolvedTypes")&&(result.resolvedTypes=this.extractResolvedTypes(symbolTable,uri,lines)),scopeSet.has("diagnostics")&&(result.diagnostics=this.extractSemanticDiagnostics(symbolTable,uri));let allSymbols=symbolTable.getSymbolsForUri(uri),resolved=allSymbols.filter(s=>s.typeNames.length>0),parseTimeMs=this.documentManager.getParseTimeMs(uri),timingBreakdown=this.documentManager.getTimingBreakdown(uri),modelBuildTimeMs=Date.now()-startTime;return result.stats={totalElements:allSymbols.length,resolvedElements:resolved.length,unresolvedElements:allSymbols.length-resolved.length,parseTimeMs,lexTimeMs:timingBreakdown.lexMs,parseOnlyTimeMs:timingBreakdown.parseMs,modelBuildTimeMs,complexity:analyseComplexity(allSymbols)},result}convertToElementDTOs(symbolTable,uri,lines){let symbols=symbolTable.getSymbolsForUri(uri),byQualifiedName=new Map;for(let sym of symbols)byQualifiedName.set(sym.qualifiedName,sym);let childrenOf=new Map;for(let sym of symbols)if(sym.parentQualifiedName&&byQualifiedName.has(sym.parentQualifiedName)){let list=childrenOf.get(sym.parentQualifiedName)??[];list.push(sym),childrenOf.set(sym.parentQualifiedName,list)}return symbols.filter(s=>!s.parentQualifiedName||!byQualifiedName.has(s.parentQualifiedName)).map(s=>this.symbolToElementDTO(s,childrenOf,lines))}symbolToElementDTO(symbol,childrenOf,lines){let children=(childrenOf.get(symbol.qualifiedName)??[]).filter(c=>c.qualifiedName!==symbol.qualifiedName).map(c=>this.symbolToElementDTO(c,childrenOf,lines)),attributes={};if(symbol.typeNames.length>0){let typeLabel=symbol.typeNames.join(", ");symbol.kind==="port"||symbol.kind==="port def"?attributes.portType=typeLabel:attributes.partType=typeLabel}symbol.documentation&&(attributes.documentation=symbol.documentation),symbol.metadataAnnotations&&symbol.metadataAnnotations.length>0&&(attributes.metadataAnnotations=symbol.metadataAnnotations.join(", ")),symbol.exposeTargets&&symbol.exposeTargets.length>0&&(attributes.exposeTargets=symbol.exposeTargets.join(",")),symbol.viewFilters&&symbol.viewFilters.length>0&&(attributes.viewFilters=symbol.viewFilters.join(",")),symbol.viewRendering&&(attributes.viewRendering=symbol.viewRendering);let direction=this.extractDirection(symbol,lines);direction&&(attributes.direction=direction);let multiplicity=this.extractMultiplicity(symbol,lines);multiplicity&&(attributes.multiplicity=multiplicity);let modifier=this.extractModifier(symbol,lines);modifier&&(attributes.modifier=modifier);let visibility=this.extractVisibility(symbol,lines);visibility&&(attributes.visibility=visibility);let value=this.extractValue(symbol,lines);value&&(attributes.value=value);let relationships=[];for(let tn of symbol.typeNames)relationships.push({type:"typing",source:symbol.name,target:tn});let specializations=this.extractSpecializations(symbol,lines);for(let spec of specializations)relationships.push({type:"specializes",source:symbol.name,target:spec});return{type:symbol.kind,name:symbol.name,range:this.rangeToDTO(symbol.range),children,attributes,relationships}}extractRelationships(symbolTable,uri,lines){let symbols=symbolTable.getSymbolsForUri(uri),relationships=[];for(let symbol of symbols){if(symbol.kind==="package"||symbol.kind==="import"||symbol.kind==="comment"||symbol.kind==="doc")continue;if(symbol.typeNames.length>0&&isUsage(symbol.kind))for(let tn of symbol.typeNames)relationships.push({type:"typing",source:symbol.name,target:tn});let specializations=this.extractSpecializations(symbol,lines);for(let spec of specializations)relationships.push({type:"specializes",source:symbol.name,target:spec});if(symbol.kind==="connection"){let connectionTargets=this.extractConnectionEndpoints(symbol,lines);connectionTargets.length===2&&relationships.push({type:"connection",source:connectionTargets[0],target:connectionTargets[1],name:symbol.name})}if(symbol.kind==="allocation"){let allocTargets=this.extractConnectionEndpoints(symbol,lines);allocTargets.length===2&&relationships.push({type:"allocation",source:allocTargets[0],target:allocTargets[1],name:symbol.name})}let elementText=this.getElementText(symbol,lines),additionalRels=this.extractKeywordRelationships(symbol.name,elementText);relationships.push(...additionalRels)}let fullText=lines.join(`
55
- `),standaloneSatisfy=this.extractStandaloneSatisfyVerify(stripComments(fullText));for(let rel of standaloneSatisfy)relationships.some(r=>r.type===rel.type&&r.source===rel.source&&r.target===rel.target)||relationships.push(rel);return relationships}extractSequenceDiagrams(symbolTable,uri,lines){let symbols=symbolTable.getSymbolsForUri(uri),diagrams=[],seen=new Set;for(let symbol of symbols){if(symbol.kind!=="action def"&&symbol.kind!=="action")continue;let children=this.getChildSymbols(symbol,symbolTable),participants=[],messages=[];for(let child of children)(child.kind==="part"||child.kind==="item")&&participants.push({name:child.name,type:child.typeNames.join(", ")||child.kind,range:this.rangeToDTO(child.range)});let fullText=this.getFullElementText(symbol,lines),occurrence=1;for(let{afterPos}of findWordPositionsCI(fullText,"send")){let sigStart=skipWS(fullText,afterPos),[signal,afterSig]=readIdent(fullText,sigStart,!0);if(!signal)continue;let kwStart=skipWS(fullText,afterSig),[kw,afterKw]=readIdent(fullText,kwStart);if(kw!=="via"&&kw!=="to")continue;let tgtStart=skipWS(fullText,afterKw),[target]=readIdent(fullText,tgtStart,!0);target&&messages.push({name:`send_${occurrence}`,from:symbol.name,to:target,payload:signal,occurrence:occurrence++,range:this.rangeToDTO(symbol.range)})}for(let{afterPos}of findWordPositionsCI(fullText,"accept")){let sigStart=skipWS(fullText,afterPos),[signal,afterSig]=readIdent(fullText,sigStart,!0);if(!signal)continue;let kwStart=skipWS(fullText,afterSig),[kw,afterKw]=readIdent(fullText,kwStart);if(kw!=="via"&&kw!=="from")continue;let srcStart=skipWS(fullText,afterKw),[source]=readIdent(fullText,srcStart,!0);source&&messages.push({name:`accept_${occurrence}`,from:source,to:symbol.name,payload:signal,occurrence:occurrence++,range:this.rangeToDTO(symbol.range)})}for(let child of children)if(child.kind==="action"){let childText=this.getFullElementText(child,lines);for(let{afterPos}of findWordPositionsCI(childText,"send")){let sigStart=skipWS(childText,afterPos),[signal,afterSig]=readIdent(childText,sigStart,!0);if(!signal)continue;let kwStart=skipWS(childText,afterSig),[kw,afterKw]=readIdent(childText,kwStart);if(kw!=="via"&&kw!=="to")continue;let tgtStart=skipWS(childText,afterKw),[target]=readIdent(childText,tgtStart,!0);target&&messages.push({name:child.name,from:target??symbol.name,to:signal??"",payload:signal??"",occurrence:occurrence++,range:this.rangeToDTO(child.range)})}for(let{afterPos}of findWordPositionsCI(childText,"accept")){let sigStart=skipWS(childText,afterPos),[signal,afterSig]=readIdent(childText,sigStart,!0);if(!signal)continue;let kwStart=skipWS(childText,afterSig),[kw,afterKw]=readIdent(childText,kwStart);if(kw!=="via"&&kw!=="from")continue;let srcStart=skipWS(childText,afterKw),[source]=readIdent(childText,srcStart,!0);source&&messages.push({name:child.name,from:source??"",to:symbol.name,payload:signal??"",occurrence:occurrence++,range:this.rangeToDTO(child.range)})}}(participants.length>0||messages.length>0)&&(diagrams.push({name:symbol.name,participants,messages,range:this.rangeToDTO(symbol.range)}),messages.length>0&&seen.add(symbol.qualifiedName))}for(let symbol of symbols){if(seen.has(symbol.qualifiedName)||symbol.kind!=="action def"&&symbol.kind!=="action")continue;let children=this.getChildSymbols(symbol,symbolTable);if(!children.some(c=>c.kind==="action"||c.kind==="action def"))continue;let flows=this.extractSuccessions(symbol,lines);if(flows.length===0)continue;let participants=children.filter(c=>c.kind==="action"||c.kind==="action def").map(c=>({name:c.name,type:c.typeNames.join(", ")||"action",range:this.rangeToDTO(c.range)})),messages=[],occ=1;for(let flow of flows){if(flow.from==="start"||flow.to==="done")continue;let label=flow.guard??flow.to;messages.push({name:label,from:flow.from,to:flow.to,payload:flow.guard??"",occurrence:occ++,range:flow.range})}if(participants.length>0||messages.length>0){let existingIdx=diagrams.findIndex(d=>d.name===symbol.name);existingIdx>=0&&diagrams.splice(existingIdx,1),diagrams.push({name:symbol.name,participants,messages,range:this.rangeToDTO(symbol.range)})}}return diagrams}extractActivityDiagrams(symbolTable,uri,lines){let symbols=symbolTable.getSymbolsForUri(uri),diagrams=[];for(let symbol of symbols){if(symbol.kind!=="action def"&&symbol.kind!=="action")continue;let children=this.getChildSymbols(symbol,symbolTable),hasChildActions=children.some(c=>c.kind==="action"||c.kind==="action def");if(symbol.kind==="action"&&!hasChildActions)continue;let actions=[],decisions=[],flows=[],states=[];for(let child of children){let childText=this.getElementText(child,lines);if(child.kind==="action"||child.kind==="action def"){let actionType="action",lowerText=childText.toLowerCase();lowerText.includes("fork")?actionType="fork":lowerText.includes("join")?actionType="join":lowerText.includes("merge")?actionType="merge":lowerText.includes("decide")&&(actionType="decision");let subActions=this.getChildSymbols(child,symbolTable).filter(c=>c.kind==="action"||c.kind==="action def").map(c=>this.symbolToActionDTO(c,symbolTable,lines));if(actions.push({name:child.name,type:actionType,isDefinition:child.kind==="action def",range:this.rangeToDTO(child.range),parent:symbol.name,children:subActions.map(a=>a.name),subActions:subActions.length>0?subActions:void 0}),actionType==="decision"){let branches=this.extractDecisionBranches(child,lines);decisions.push({name:child.name,condition:"",branches,range:this.rangeToDTO(child.range)})}}if(child.kind==="state"||child.kind==="state def"){let stateType=childText.toLowerCase().includes("initial")?"initial":childText.toLowerCase().includes("final")?"final":"intermediate";states.push({name:child.name,type:stateType,range:this.rangeToDTO(child.range)})}}let successionFlows=this.extractSuccessions(symbol,lines);flows.push(...successionFlows);let fullText=this.getFullElementText(symbol,lines);if(findWordPositions(fullText,"decide").some(({afterPos})=>{let p=skipWS(fullText,afterPos);return p<fullText.length&&fullText[p]===";"})){let branches=[];for(let{afterPos:ifAfter}of findWordPositions(fullText,"if")){let thenIdx=fullText.indexOf("then",ifAfter);if(thenIdx<0)continue;let bBefore=thenIdx>0?fullText.charCodeAt(thenIdx-1):32,bAfter=thenIdx+4<fullText.length?fullText.charCodeAt(thenIdx+4):32;if(isIdentPart(bBefore)||isIdentPart(bAfter))continue;let condition=fullText.substring(ifAfter,thenIdx).trim(),[target]=readWordAfterKeyword(fullText,thenIdx+4);target&&branches.push({condition,target})}branches.length>0&&decisions.push({name:"decide",condition:"",branches,range:this.rangeToDTO(symbol.range)})}if(flows.length>0){let hasStartFlow=flows.some(f=>f.from==="start"),hasDoneFlow=flows.some(f=>f.to==="done");hasStartFlow&&actions.unshift({name:"start",type:"initial",isDefinition:!1,range:this.rangeToDTO(symbol.range)}),hasDoneFlow&&actions.push({name:"done",type:"final",isDefinition:!1,range:this.rangeToDTO(symbol.range)}),flows.some(f=>f.from==="decide")&&actions.push({name:"decide",type:"decision",isDefinition:!1,range:this.rangeToDTO(symbol.range)})}(actions.length>0||flows.length>0||states.length>0)&&diagrams.push({name:symbol.name,actions,decisions,flows,states,range:this.rangeToDTO(symbol.range)})}return diagrams}extractResolvedTypes(symbolTable,uri,lines){let symbols=symbolTable.getSymbolsForUri(uri),result={};for(let symbol of symbols){if(!isDefinition(symbol.kind)&&symbol.typeNames.length===0)continue;let specializes=[],specList=this.extractSpecializations(symbol,lines);for(let s of specList)specializes.includes(s)||specializes.push(s);for(let tn of symbol.typeNames)specializes.includes(tn)||specializes.push(tn);let specializationChain=[...specializes],features=this.getChildSymbols(symbol,symbolTable).filter(c=>isUsage(c.kind)).map(c=>({name:c.name,kind:this.featureKindFromElementKind(c.kind),type:c.typeNames.join(", ")||void 0,isDerived:!1,isReadonly:!1}));result[symbol.qualifiedName]={qualifiedName:symbol.qualifiedName,simpleName:symbol.name,kind:symbol.kind,isLibraryType:!1,specializationChain,specializes,features}}return result}extractSemanticDiagnostics(symbolTable,uri){let symbols=symbolTable.getSymbolsForUri(uri),diagnostics=[],allSymbolNames=new Set(symbolTable.getAllSymbols().map(s=>s.name));for(let symbol of symbols){for(let tn of symbol.typeNames)allSymbolNames.has(tn)||diagnostics.push({code:"unresolved-type",message:`Type '${tn}' could not be resolved in the current scope`,severity:"warning",range:this.rangeToDTO(symbol.selectionRange),elementName:symbol.name});symbol.kind==="enum def"&&(this.getChildSymbols(symbol,symbolTable).some(c=>c.kind==="enum"||c.kind==="attribute")||diagnostics.push({code:"empty-enum",message:`Enumeration '${symbol.name}' has no enum values defined`,severity:"info",range:this.rangeToDTO(symbol.range),elementName:symbol.name}))}return diagnostics}rangeToDTO(range){return{start:{line:range.start.line,character:range.start.character},end:{line:range.end.line,character:range.end.character}}}getChildSymbols(parent,symbolTable){return symbolTable.getSymbolsForUri(parent.uri).filter(s=>s.parentQualifiedName===parent.qualifiedName)}getElementText(symbol,lines){let startLine=symbol.range.start.line,endLine=Math.min(startLine+2,symbol.range.end.line,lines.length-1);return lines.slice(startLine,endLine+1).join(`
55
+ `),standaloneSatisfy=this.extractStandaloneSatisfyVerify(stripComments(fullText));for(let rel of standaloneSatisfy)relationships.some(r=>r.type===rel.type&&r.source===rel.source&&r.target===rel.target)||relationships.push(rel);return relationships}extractSequenceDiagrams(symbolTable,uri,lines){let symbols=symbolTable.getSymbolsForUri(uri),diagrams=[],seen=new Set;for(let symbol of symbols){if(symbol.kind!=="action def"&&symbol.kind!=="action")continue;let children=this.getChildSymbols(symbol,symbolTable),participants=[],messages=[];for(let child of children)(child.kind==="part"||child.kind==="item")&&participants.push({name:child.name,type:child.typeNames.join(", ")||child.kind,range:this.rangeToDTO(child.range)});let fullText=this.getFullElementText(symbol,lines),occurrence=1;for(let{afterPos}of findWordPositionsCI(fullText,"send")){let sigStart=skipWS(fullText,afterPos),[signal,afterSig]=readIdent(fullText,sigStart,!0);if(!signal)continue;let kwStart=skipWS(fullText,afterSig),[kw,afterKw]=readIdent(fullText,kwStart);if(kw!=="via"&&kw!=="to")continue;let tgtStart=skipWS(fullText,afterKw),[target]=readIdent(fullText,tgtStart,!0);target&&messages.push({name:`send_${occurrence}`,from:symbol.name,to:target,payload:signal,occurrence:occurrence++,range:this.rangeToDTO(symbol.range)})}for(let{afterPos}of findWordPositionsCI(fullText,"accept")){let sigStart=skipWS(fullText,afterPos),[signal,afterSig]=readIdent(fullText,sigStart,!0);if(!signal)continue;let kwStart=skipWS(fullText,afterSig),[kw,afterKw]=readIdent(fullText,kwStart);if(kw!=="via"&&kw!=="from")continue;let srcStart=skipWS(fullText,afterKw),[source]=readIdent(fullText,srcStart,!0);source&&messages.push({name:`accept_${occurrence}`,from:source,to:symbol.name,payload:signal,occurrence:occurrence++,range:this.rangeToDTO(symbol.range)})}for(let child of children)if(child.kind==="action"){let childText=this.getFullElementText(child,lines);for(let{afterPos}of findWordPositionsCI(childText,"send")){let sigStart=skipWS(childText,afterPos),[signal,afterSig]=readIdent(childText,sigStart,!0);if(!signal)continue;let kwStart=skipWS(childText,afterSig),[kw,afterKw]=readIdent(childText,kwStart);if(kw!=="via"&&kw!=="to")continue;let tgtStart=skipWS(childText,afterKw),[target]=readIdent(childText,tgtStart,!0);target&&messages.push({name:child.name,from:target??symbol.name,to:signal??"",payload:signal??"",occurrence:occurrence++,range:this.rangeToDTO(child.range)})}for(let{afterPos}of findWordPositionsCI(childText,"accept")){let sigStart=skipWS(childText,afterPos),[signal,afterSig]=readIdent(childText,sigStart,!0);if(!signal)continue;let kwStart=skipWS(childText,afterSig),[kw,afterKw]=readIdent(childText,kwStart);if(kw!=="via"&&kw!=="from")continue;let srcStart=skipWS(childText,afterKw),[source]=readIdent(childText,srcStart,!0);source&&messages.push({name:child.name,from:source??"",to:symbol.name,payload:signal??"",occurrence:occurrence++,range:this.rangeToDTO(child.range)})}}(participants.length>0||messages.length>0)&&(diagrams.push({name:symbol.name,participants,messages,range:this.rangeToDTO(symbol.range)}),messages.length>0&&seen.add(symbol.qualifiedName))}for(let symbol of symbols){if(seen.has(symbol.qualifiedName)||symbol.kind!=="action def"&&symbol.kind!=="action")continue;let children=this.getChildSymbols(symbol,symbolTable);if(!children.some(c=>c.kind==="action"||c.kind==="action def"))continue;let flows=this.extractSuccessions(symbol,lines);if(flows.length===0)continue;let participants=children.filter(c=>c.kind==="action"||c.kind==="action def").map(c=>({name:c.name,type:c.typeNames.join(", ")||"action",range:this.rangeToDTO(c.range)})),messages=[],occ=1;for(let flow of flows){if(flow.from==="start"||flow.to==="done")continue;let label=flow.guard??flow.to;messages.push({name:label,from:flow.from,to:flow.to,payload:flow.guard??"",occurrence:occ++,range:flow.range})}if(participants.length>0||messages.length>0){let existingIdx=diagrams.findIndex(d=>d.name===symbol.name);existingIdx>=0&&diagrams.splice(existingIdx,1),diagrams.push({name:symbol.name,participants,messages,range:this.rangeToDTO(symbol.range)})}}let containerKinds=new Set(["part def","part","item def","item","interface def","interface","connection def","connection","occurrence def","occurrence"]),rootName=qualified=>{if(!qualified)return qualified;let dotIdx=qualified.indexOf("."),head=dotIdx>=0?qualified.substring(0,dotIdx):qualified,ccIdx=head.lastIndexOf("::");return ccIdx>=0?head.substring(ccIdx+2):head};for(let symbol of symbols){if(seen.has(symbol.qualifiedName)||!containerKinds.has(symbol.kind))continue;let children=this.getChildSymbols(symbol,symbolTable),fullText=this.getFullElementText(symbol,lines),parsedMessages=[],occ=1;for(let keyword of["flow","message"])for(let{afterPos}of findWordPositionsCI(fullText,keyword)){let nameStart=skipWS(fullText,afterPos),[name,afterName]=readIdent(fullText,nameStart);if(!name||name==="def")continue;let fromStart=skipWS(fullText,afterName),[fromKw,afterFromKw]=readIdent(fullText,fromStart);if(fromKw!=="from")continue;let srcStart=skipWS(fullText,afterFromKw),[srcRaw,afterSrc]=readIdent(fullText,srcStart,!0);if(!srcRaw)continue;let toStart=skipWS(fullText,afterSrc),[toKw,afterToKw]=readIdent(fullText,toStart);if(toKw!=="to")continue;let tgtStart=skipWS(fullText,afterToKw),[tgtRaw]=readIdent(fullText,tgtStart,!0);tgtRaw&&parsedMessages.push({name,from:rootName(srcRaw),to:rootName(tgtRaw),payload:name,occurrence:occ++,range:this.rangeToDTO(symbol.range)})}if(parsedMessages.length===0)continue;let participants=[];for(let child of children)(child.kind==="part"||child.kind==="item"||child.kind==="part def"||child.kind==="item def"||child.kind==="ref")&&(participants.find(p=>p.name===child.name)||participants.push({name:child.name,type:child.typeNames.join(", ")||child.kind,range:this.rangeToDTO(child.range)}));for(let msg of parsedMessages)for(let endpoint of[msg.from,msg.to])endpoint&&!participants.find(p=>p.name===endpoint)&&participants.push({name:endpoint,type:"participant",range:this.rangeToDTO(symbol.range)});let existingIdx=diagrams.findIndex(d=>d.name===symbol.name);existingIdx>=0&&diagrams.splice(existingIdx,1),diagrams.push({name:symbol.name,participants,messages:parsedMessages,range:this.rangeToDTO(symbol.range)}),seen.add(symbol.qualifiedName)}return diagrams}extractActivityDiagrams(symbolTable,uri,lines){let symbols=symbolTable.getSymbolsForUri(uri),diagrams=[];for(let symbol of symbols){if(symbol.kind!=="action def"&&symbol.kind!=="action")continue;let children=this.getChildSymbols(symbol,symbolTable),hasChildActions=children.some(c=>c.kind==="action"||c.kind==="action def");if(symbol.kind==="action"&&!hasChildActions)continue;let actions=[],decisions=[],flows=[],states=[];for(let child of children){let childText=this.getElementText(child,lines);if(child.kind==="action"||child.kind==="action def"){let actionType="action",lowerText=childText.toLowerCase();lowerText.includes("fork")?actionType="fork":lowerText.includes("join")?actionType="join":lowerText.includes("merge")?actionType="merge":lowerText.includes("decide")&&(actionType="decision");let subActions=this.getChildSymbols(child,symbolTable).filter(c=>c.kind==="action"||c.kind==="action def").map(c=>this.symbolToActionDTO(c,symbolTable,lines));if(actions.push({name:child.name,type:actionType,isDefinition:child.kind==="action def",range:this.rangeToDTO(child.range),parent:symbol.name,children:subActions.map(a=>a.name),subActions:subActions.length>0?subActions:void 0}),actionType==="decision"){let branches=this.extractDecisionBranches(child,lines);decisions.push({name:child.name,condition:"",branches,range:this.rangeToDTO(child.range)})}}if(child.kind==="state"||child.kind==="state def"){let stateType=childText.toLowerCase().includes("initial")?"initial":childText.toLowerCase().includes("final")?"final":"intermediate";states.push({name:child.name,type:stateType,range:this.rangeToDTO(child.range)})}}let successionFlows=this.extractSuccessions(symbol,lines);flows.push(...successionFlows);let fullText=this.getFullElementText(symbol,lines);if(findWordPositions(fullText,"decide").some(({afterPos})=>{let p=skipWS(fullText,afterPos);return p<fullText.length&&fullText[p]===";"})){let branches=[];for(let{afterPos:ifAfter}of findWordPositions(fullText,"if")){let thenIdx=fullText.indexOf("then",ifAfter);if(thenIdx<0)continue;let bBefore=thenIdx>0?fullText.charCodeAt(thenIdx-1):32,bAfter=thenIdx+4<fullText.length?fullText.charCodeAt(thenIdx+4):32;if(isIdentPart(bBefore)||isIdentPart(bAfter))continue;let condition=fullText.substring(ifAfter,thenIdx).trim(),[target]=readWordAfterKeyword(fullText,thenIdx+4);target&&branches.push({condition,target})}branches.length>0&&decisions.push({name:"decide",condition:"",branches,range:this.rangeToDTO(symbol.range)})}if(flows.length>0){let hasStartFlow=flows.some(f=>f.from==="start"),hasDoneFlow=flows.some(f=>f.to==="done");hasStartFlow&&actions.unshift({name:"start",type:"initial",isDefinition:!1,range:this.rangeToDTO(symbol.range)}),hasDoneFlow&&actions.push({name:"done",type:"final",isDefinition:!1,range:this.rangeToDTO(symbol.range)}),flows.some(f=>f.from==="decide")&&actions.push({name:"decide",type:"decision",isDefinition:!1,range:this.rangeToDTO(symbol.range)})}(actions.length>0||flows.length>0||states.length>0)&&diagrams.push({name:symbol.name,actions,decisions,flows,states,range:this.rangeToDTO(symbol.range)})}return diagrams}extractResolvedTypes(symbolTable,uri,lines){let symbols=symbolTable.getSymbolsForUri(uri),result={};for(let symbol of symbols){if(!isDefinition(symbol.kind)&&symbol.typeNames.length===0)continue;let specializes=[],specList=this.extractSpecializations(symbol,lines);for(let s of specList)specializes.includes(s)||specializes.push(s);for(let tn of symbol.typeNames)specializes.includes(tn)||specializes.push(tn);let specializationChain=[...specializes],features=this.getChildSymbols(symbol,symbolTable).filter(c=>isUsage(c.kind)).map(c=>({name:c.name,kind:this.featureKindFromElementKind(c.kind),type:c.typeNames.join(", ")||void 0,isDerived:!1,isReadonly:!1}));result[symbol.qualifiedName]={qualifiedName:symbol.qualifiedName,simpleName:symbol.name,kind:symbol.kind,isLibraryType:!1,specializationChain,specializes,features}}return result}extractSemanticDiagnostics(symbolTable,uri){let symbols=symbolTable.getSymbolsForUri(uri),diagnostics=[],allSymbolNames=new Set(symbolTable.getAllSymbols().map(s=>s.name));for(let symbol of symbols){for(let tn of symbol.typeNames)allSymbolNames.has(tn)||diagnostics.push({code:"unresolved-type",message:`Type '${tn}' could not be resolved in the current scope`,severity:"warning",range:this.rangeToDTO(symbol.selectionRange),elementName:symbol.name});symbol.kind==="enum def"&&(this.getChildSymbols(symbol,symbolTable).some(c=>c.kind==="enum"||c.kind==="attribute")||diagnostics.push({code:"empty-enum",message:`Enumeration '${symbol.name}' has no enum values defined`,severity:"info",range:this.rangeToDTO(symbol.range),elementName:symbol.name}))}return diagnostics}rangeToDTO(range){return{start:{line:range.start.line,character:range.start.character},end:{line:range.end.line,character:range.end.character}}}getChildSymbols(parent,symbolTable){return symbolTable.getSymbolsForUri(parent.uri).filter(s=>s.parentQualifiedName===parent.qualifiedName)}getElementText(symbol,lines){let startLine=symbol.range.start.line,endLine=Math.min(startLine+2,symbol.range.end.line,lines.length-1);return lines.slice(startLine,endLine+1).join(`
56
56
  `)}getFullElementText(symbol,lines){let startLine=symbol.range.start.line,endLine=Math.min(symbol.range.end.line,lines.length-1);return lines.slice(startLine,endLine+1).join(`
57
57
  `)}extractDirection(symbol,lines){if(symbol.kind!=="port"&&symbol.kind!=="port def")return;let elementText=this.getElementText(symbol,lines);if(containsWord(elementText,"inout"))return"inout";if(containsWord(elementText,"in"))return"in";if(containsWord(elementText,"out"))return"out"}extractMultiplicity(symbol,lines){let elementText=this.getElementText(symbol,lines),open=elementText.indexOf("[");if(open<0)return;let close=elementText.indexOf("]",open+1);if(!(close<0))return elementText.substring(open+1,close)}extractModifier(symbol,lines){let elementText=this.getElementText(symbol,lines),modifiers=[];return containsWord(elementText,"abstract")&&modifiers.push("abstract"),containsWord(elementText,"readonly")&&modifiers.push("readonly"),containsWord(elementText,"derived")&&modifiers.push("derived"),containsWord(elementText,"variation")&&modifiers.push("variation"),containsWord(elementText,"individual")&&modifiers.push("individual"),modifiers.length>0?modifiers.join(", "):void 0}extractVisibility(symbol,lines){let elementText=this.getElementText(symbol,lines);if(containsWord(elementText,"private"))return"private";if(containsWord(elementText,"protected"))return"protected";if(containsWord(elementText,"public"))return"public"}extractValue(symbol,lines){if(symbol.kind!=="attribute")return;let elementText=this.getElementText(symbol,lines),eqIdx=elementText.indexOf("=");if(eqIdx<0)return;let start=eqIdx+1;if(start<elementText.length&&elementText[start]==="=")return;start=skipWS(elementText,start);let end=start;for(;end<elementText.length;){let ch=elementText[end];if(ch===";"||ch==="{"||ch==="}"||ch===`
58
58
  `)break;end++}let val=elementText.substring(start,end).trim();if(val&&!val.includes("def")&&val.length<100)return val}extractSpecializations(symbol,lines){let elementText=this.getElementText(symbol,lines),colonGtIdx=elementText.indexOf(":>");if(colonGtIdx>=0&&!(colonGtIdx+2<elementText.length&&elementText[colonGtIdx+2]===">"))return readCommaSeparatedIdents(elementText,colonGtIdx+2);let specPositions=findWordPositions(elementText,"specializes");return specPositions.length>0?readCommaSeparatedIdents(elementText,specPositions[0].afterPos):[]}extractConnectionEndpoints(symbol,lines){let elementText=this.getElementText(symbol,lines),endpoints=[],connectPositions=findWordPositions(elementText,"connect");for(let{afterPos}of connectPositions){let[name1,end1]=readWordAfterKeyword(elementText,afterPos,!0);if(!name1)continue;let toPos=skipWS(elementText,end1);if(elementText.substring(toPos,toPos+2)==="to"){let afterTo=toPos+2,[name2]=readWordAfterKeyword(elementText,afterTo,!0);if(name2)return endpoints.push(name1,name2),endpoints}}let endPositions=findWordPositions(elementText,"end");for(let{afterPos}of endPositions){let[name]=readWordAfterKeyword(elementText,afterPos,!0);name&&endpoints.push(name)}return endpoints}extractStandaloneSatisfyVerify(text){let rels=[],keywords=["satisfy","verify"];for(let kw of keywords){let positions=findWordPositions(text,kw);for(let{afterPos}of positions){let pos=skipWS(text,afterPos),[nextWord,afterWord]=readNameOrQuoted(text,pos);nextWord==="requirement"?pos=skipWS(text,afterWord):pos=skipWS(text,afterPos);let[reqName,afterReq]=readNameOrQuoted(text,pos);if(!reqName||reqName==="requirement")continue;let byPos=skipWS(text,afterReq),[byWord,afterBy]=readIdent(text,byPos),source;if(byWord==="by"){let[byTarget]=readNameOrQuoted(text,skipWS(text,afterBy));if(!byTarget)continue;source=byTarget}rels.push({type:kw,source,target:reqName})}}return rels}extractKeywordRelationships(elementName,elementText){elementText=stripComments(elementText);let rels=[],subsetsPositions=findWordPositions(elementText,"subsets");if(subsetsPositions.length>0){let[target]=readWordAfterKeyword(elementText,subsetsPositions[0].afterPos);target&&rels.push({type:"subsetting",source:elementName,target})}let redefPositions=findWordPositions(elementText,"redefines");if(redefPositions.length>0){let[target]=readWordAfterKeyword(elementText,redefPositions[0].afterPos);target&&rels.push({type:"redefinition",source:elementName,target})}let satisfyPositions=findWordPositions(elementText,"satisfy");if(satisfyPositions.length>0){let pos=skipWS(elementText,satisfyPositions[0].afterPos),[nextWord,afterWord]=readNameOrQuoted(elementText,pos);nextWord==="requirement"&&(pos=skipWS(elementText,afterWord));let[reqName,afterReq]=readNameOrQuoted(elementText,pos);if(reqName&&reqName!=="requirement"){let satisfier=elementName,byPos=skipWS(elementText,afterReq),[byWord,afterBy]=readIdent(elementText,byPos);if(byWord==="by"){let[byTarget]=readNameOrQuoted(elementText,skipWS(elementText,afterBy));byTarget&&(satisfier=byTarget)}rels.push({type:"satisfy",source:satisfier,target:reqName})}}let verifyPositions=findWordPositions(elementText,"verify");if(verifyPositions.length>0){let pos=skipWS(elementText,verifyPositions[0].afterPos),[nextWord,afterWord]=readNameOrQuoted(elementText,pos);nextWord==="requirement"&&(pos=skipWS(elementText,afterWord));let[reqName,afterReq]=readNameOrQuoted(elementText,pos);if(reqName&&reqName!=="requirement"){let verifier=elementName,byPos=skipWS(elementText,afterReq),[byWord,afterBy]=readIdent(elementText,byPos);if(byWord==="by"){let[byTarget]=readNameOrQuoted(elementText,skipWS(elementText,afterBy));byTarget&&(verifier=byTarget)}rels.push({type:"verify",source:verifier,target:reqName})}}return rels}extractDecisionBranches(symbol,lines){let elementText=this.getElementText(symbol,lines),branches=[],ifPositions=findWordPositions(elementText,"if");for(let{afterPos}of ifPositions){let thenIdx=elementText.indexOf("then",afterPos);if(thenIdx<0)continue;let beforeThen=thenIdx>0?elementText.charCodeAt(thenIdx-1):32,afterThen=thenIdx+4<elementText.length?elementText.charCodeAt(thenIdx+4):32;if(isIdentPart(beforeThen)||isIdentPart(afterThen))continue;let condition=elementText.substring(afterPos,thenIdx).trim(),[target]=readWordAfterKeyword(elementText,thenIdx+4);target&&branches.push({condition,target})}let elsePositions=findWordPositions(elementText,"else");if(elsePositions.length>0){let[target]=readWordAfterKeyword(elementText,elsePositions[0].afterPos);target&&branches.push({condition:"else",target})}return branches}extractSuccessions(parent,lines){let elementText=this.getFullElementText(parent,lines),flows=[],seen=new Set,range=this.rangeToDTO(parent.range),addFlow=(from,to,guard)=>{if(from===to)return;let key=`${from}->${to}`;if(seen.has(key))return;seen.add(key);let f={from,to,range};guard&&(f.guard=guard),flows.push(f)};function braceDepthAt(text,pos){let depth=0;for(let i=0;i<pos&&i<text.length;i++)text[i]==="{"?depth++:text[i]==="}"&&depth--;return depth}let firstBrace=elementText.indexOf("{"),topDepth=firstBrace>=0?braceDepthAt(elementText,firstBrace+1):1,stripQualifier=name=>{let idx=name.lastIndexOf("::");return idx>=0?name.substring(idx+2):name},tokens=[];for(let{pos,afterPos}of findWordPositions(elementText,"first")){if(braceDepthAt(elementText,pos)!==topDepth)continue;let nameStart=skipWS(elementText,afterPos),[name]=readNameOrQuoted(elementText,nameStart);name&&tokens.push({type:"first",name:stripQualifier(name),index:pos})}for(let{pos,afterPos}of findWordPositions(elementText,"then")){if(braceDepthAt(elementText,pos)!==topDepth)continue;let lookbackStart=Math.max(0,pos-100),preceding=elementText.substring(lookbackStart,pos);if(containsWord(preceding,"if")&&!preceding.includes(";"))continue;let nameStart=skipWS(elementText,afterPos),[maybeAction,afterAction]=readIdent(elementText,nameStart);maybeAction==="action"&&(nameStart=skipWS(elementText,afterAction));let[name]=readNameOrQuoted(elementText,nameStart);!name||name==="if"||tokens.push({type:"then",name:stripQualifier(name),index:pos})}tokens.sort((a,b)=>a.index-b.index);let coveredIndices=new Set;for(let i=0;i<tokens.length;i++)if(tokens[i].type==="first"){let chain=[tokens[i].name];coveredIndices.add(i);for(let j=i+1;j<tokens.length&&tokens[j].type==="then";j++)chain.push(tokens[j].name),coveredIndices.add(j);for(let k=0;k<chain.length-1;k++)addFlow(chain[k],chain[k+1])}let uncoveredThens=tokens.filter((t,i)=>!coveredIndices.has(i)&&t.type==="then");if(uncoveredThens.length>0)for(let i=0;i<uncoveredThens.length-1;i++)addFlow(uncoveredThens[i].name,uncoveredThens[i+1].name);if(flows.length>0){let allTargets=new Set(flows.map(f=>f.to)),allSources=new Set(flows.map(f=>f.from)),entryActions=flows.map(f=>f.from).filter(name=>name!=="start"&&name!=="done"&&!allTargets.has(name)),exitActions=flows.map(f=>f.to).filter(name=>name!=="start"&&name!=="done"&&!allSources.has(name));entryActions.length>0&&addFlow("start",entryActions[0]),exitActions.length>0&&addFlow(exitActions[exitActions.length-1],"done")}for(let{afterPos}of findWordPositions(elementText,"succession")){let p=skipWS(elementText,afterPos),[word1,afterWord1]=readIdent(elementText,p);if(word1==="flow"){p=skipWS(elementText,afterWord1);let[fromKw,afterFrom]=readIdent(elementText,p);if(fromKw==="from"){p=skipWS(elementText,afterFrom);let[srcFull,afterSrc]=readIdent(elementText,p,!0),src=srcFull.includes(".")?srcFull.substring(0,srcFull.indexOf(".")):srcFull;p=skipWS(elementText,afterSrc);let[toKw,afterTo]=readIdent(elementText,p);if(toKw==="to"){p=skipWS(elementText,afterTo);let[dstFull]=readIdent(elementText,p,!0),dst=dstFull.includes(".")?dstFull.substring(0,dstFull.indexOf(".")):dstFull;src&&dst&&addFlow(src,dst)}}continue}let nameStart=p;word1==="first"&&(nameStart=skipWS(elementText,afterWord1));let[name1]=readNameOrQuoted(elementText,nameStart);if(!name1)continue;let afterName1=nameStart+name1.length+(elementText[nameStart]==="'"?2:0),thenCheck=skipWS(elementText,afterName1),[thenKw,afterThen]=readIdent(elementText,thenCheck);if(thenKw==="then"){let name2Start=skipWS(elementText,afterThen),[name2]=readNameOrQuoted(elementText,name2Start);name2&&addFlow(stripQualifier(name1),stripQualifier(name2))}}if(findWordPositions(elementText,"decide").some(({afterPos})=>{let p=skipWS(elementText,afterPos);return p<elementText.length&&elementText[p]===";"})){for(let fi=flows.length-1;fi>=0;fi--)flows[fi].from==="decide"&&(seen.delete(`decide->${flows[fi].to}`),flows.splice(fi,1));let branchTargets=[];for(let{afterPos:ifAfter}of findWordPositions(elementText,"if")){let thenIdx=elementText.indexOf("then",ifAfter);if(thenIdx<0)continue;let bBefore=thenIdx>0?elementText.charCodeAt(thenIdx-1):32,bAfter=thenIdx+4<elementText.length?elementText.charCodeAt(thenIdx+4):32;if(isIdentPart(bBefore)||isIdentPart(bAfter))continue;let condition=elementText.substring(ifAfter,thenIdx).trim(),targetStart=skipWS(elementText,thenIdx+4),[target]=readNameOrQuoted(elementText,targetStart);if(target){let afterTarget=targetStart+target.length+(elementText[targetStart]==="'"?2:0),semi=skipWS(elementText,afterTarget);semi<elementText.length&&elementText[semi]===";"&&(addFlow("decide",target,condition),branchTargets.push(target))}}for(let{pos:mergePos,afterPos:mergeAfter}of findWordPositions(elementText,"merge")){let mStart=skipWS(elementText,mergeAfter),[mergeTarget]=readNameOrQuoted(elementText,mStart);if(!mergeTarget)continue;let afterMT=mStart+mergeTarget.length+(elementText[mStart]==="'"?2:0),semiP=skipWS(elementText,afterMT);if(semiP>=elementText.length||elementText[semiP]!==";")continue;for(let branch of branchTargets)addFlow(branch,mergeTarget);let afterMerge=tokens.filter(t=>t.type==="then"&&t.index>mergePos);afterMerge.length>0?addFlow(mergeTarget,afterMerge[0].name):mergeTarget!=="done"&&addFlow(mergeTarget,"done")}}return flows}featureKindFromElementKind(kind){switch(kind){case"attribute":case"attribute def":return"attribute";case"port":case"port def":return"port";case"action":case"action def":return"action";case"state":case"state def":return"state";default:return"reference"}}symbolToActionDTO(symbol,symbolTable,lines){let childText=this.getElementText(symbol,lines),actionType="action",lowerText=childText.toLowerCase();return lowerText.includes("fork")?actionType="fork":lowerText.includes("join")?actionType="join":lowerText.includes("merge")?actionType="merge":lowerText.includes("decide")&&(actionType="decision"),{name:symbol.name,type:actionType,isDefinition:symbol.kind==="action def",range:this.rangeToDTO(symbol.range)}}};var import_node=__toESM(require_node3());var CodeActionProvider=class{constructor(documentManager2){this.documentManager=documentManager2}documentManager;provideCodeActions(params){let actions=[],uri=params.textDocument.uri;for(let diagnostic of params.context.diagnostics){let typoFix=this.tryKeywordTypoFix(uri,diagnostic);typoFix&&actions.push(typoFix);let namingFix=this.tryNamingConventionFix(uri,diagnostic);namingFix&&actions.push(namingFix);let docFix=this.tryMissingDocFix(uri,diagnostic);docFix&&actions.push(docFix);let enumFix=this.tryEmptyEnumFix(uri,diagnostic);enumFix&&actions.push(enumFix);let unusedFix=this.tryUnusedDefinitionFix(uri,diagnostic);unusedFix&&actions.push(unusedFix);let redefMultFix=this.tryRedefinitionMultiplicityFix(uri,diagnostic);redefMultFix&&actions.push(redefMultFix);let portCompatFix=this.tryPortCompatibilityFix(uri,diagnostic);portCompatFix&&actions.push(portCompatFix);let constraintRefFix=this.tryConstraintReferenceFix(uri,diagnostic);constraintRefFix&&actions.push(constraintRefFix);let unresolvedTypeFixes=this.tryUnresolvedTypeFixes(uri,diagnostic);unresolvedTypeFixes.length>0&&actions.push(...unresolvedTypeFixes)}return actions}tryUnresolvedTypeFixes(uri,diagnostic){if(diagnostic.code!=="unresolved-type")return[];let text=this.documentManager.getText(uri);if(!text)return[];let unresolvedType=diagnostic.data?.typeName??extractQuotedString(diagnostic.message,"Type '");if(!unresolvedType)return[];let actions=[],allSymbols=this.documentManager.getWorkspaceSymbolTable().getAllSymbols(),packageNames=new Set;for(let s of allSymbols){if(!isDefinition(s.kind)||s.name!==unresolvedType||s.uri===uri)continue;let parentQn=s.parentQualifiedName||"",qn=s.qualifiedName||"",pkg=(parentQn.split("::")[0]||qn.split("::")[0]||"").trim();!pkg||pkg===unresolvedType||pkg&&packageNames.add(pkg)}for(let pkg of packageNames){if(this.hasImportForPackage(text,pkg))continue;let insertPos=this.findImportInsertPosition(text),importText=`${this.getChildIndentForPackageLine(text,insertPos.line)}public import ${pkg}::*;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "sysml-v2-lsp",
3
3
  "displayName": "SysML v2 Language Server",
4
4
  "description": "Language Server Protocol implementation for SysML v2, powered by ANTLR4",
5
- "version": "0.19.0",
5
+ "version": "0.20.0",
6
6
  "publisher": "JamieD",
7
7
  "license": "MIT",
8
8
  "repository": {