import*as Bindings from"../bindings/bindings.js";import*as Platform from"../platform/platform.js";import*as TextUtils from"../text_utils/text_utils.js";import*as Workspace from"../workspace/workspace.js";export const decoratorType="coverage";export class CoverageDecorationManager{constructor(e){this._coverageModel=e,this._textByProvider=new Map,this._uiSourceCodeByContentProvider=new Platform.MapUtilities.Multimap;for(const o of Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodes())o.addLineDecoration(0,"coverage",this);Workspace.Workspace.WorkspaceImpl.instance().addEventListener(Workspace.Workspace.Events.UISourceCodeAdded,this._onUISourceCodeAdded,this)}reset(){for(const e of Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodes())e.removeDecorationsForType("coverage")}dispose(){this.reset(),Workspace.Workspace.WorkspaceImpl.instance().removeEventListener(Workspace.Workspace.Events.UISourceCodeAdded,this._onUISourceCodeAdded,this)}update(e){for(const o of e)for(const e of this._uiSourceCodeByContentProvider.get(o.contentProvider()))e.removeDecorationsForType("coverage"),e.addLineDecoration(0,"coverage",this)}async usageByLine(e){const o=[],{content:t}=await e.requestContent();if(!t)return[];const n=new TextUtils.Text.Text(t);await this._updateTexts(e,n);const r=n.lineEndings();for(let i=0;i<n.lineCount();++i){const t=r[i]-(i?r[i-1]:0)-1;if(!t){o.push(void 0);continue}const n=this._rawLocationsForSourceLocation(e,i,0),s=this._rawLocationsForSourceLocation(e,i,t),[c,a]=await Promise.all([n,s]);let d;for(let e=0,o=0;e<c.length;++e){const t=c[e];for(;o<a.length&&CoverageDecorationManager._compareLocations(t,a[o])>=0;)++o;if(o>=a.length||a[o].id!==t.id)continue;const n=a[o++],r=this._textByProvider.get(n.contentProvider);if(!r)continue;const i=r.value();let s=Math.min(r.offsetFromPosition(t.line,t.column),i.length-1),u=Math.min(r.offsetFromPosition(n.line,n.column),i.length-1);for(;s<=u&&/\s/.test(i[s]);)++s;for(;s<=u&&/\s/.test(i[u]);)--u;if(s<=u&&(d=this._coverageModel.usageForRange(n.contentProvider,s,u)),d)break}o.push(d)}return o}async _updateTexts(e,o){const t=[];for(let n=0;n<o.lineCount();++n)for(const o of await this._rawLocationsForSourceLocation(e,n,0))this._textByProvider.has(o.contentProvider)||(this._textByProvider.set(o.contentProvider,null),this._uiSourceCodeByContentProvider.set(o.contentProvider,e),t.push(this._updateTextForProvider(o.contentProvider)));await Promise.all(t)}async _updateTextForProvider(e){const{content:o}=await e.requestContent();this._textByProvider.set(e,new TextUtils.Text.Text(o||""))}async _rawLocationsForSourceLocation(e,o,t){const n=[],r=e.contentType();if(r.hasScripts()){let i=await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().uiLocationToRawLocations(e,o,t);i=i.filter((e=>Boolean(e.script())));for(const e of i){const o=e.script();o&&(o.isInlineScript()&&r.isDocument()&&(e.lineNumber-=o.lineOffset,e.lineNumber||(e.columnNumber-=o.columnOffset)),n.push({id:`js:${e.scriptId}`,contentProvider:o,line:e.lineNumber,column:e.columnNumber}))}}if(r.isStyleSheet()||r.isDocument()){const i=Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance().uiLocationToRawLocations(new Workspace.UISourceCode.UILocation(e,o,t));for(const e of i){const o=e.header();o&&(o.isInline&&r.isDocument()&&(e.lineNumber-=o.startLine,e.lineNumber||(e.columnNumber-=o.startColumn)),n.push({id:`css:${e.styleSheetId}`,contentProvider:o,line:e.lineNumber,column:e.columnNumber}))}}return n.sort(CoverageDecorationManager._compareLocations)}static _compareLocations(e,o){return e.id.localeCompare(o.id)||e.line-o.line||e.column-o.column}_onUISourceCodeAdded(e){e.data.addLineDecoration(0,"coverage",this)}}