@ngcompass/rules 0.1.2-beta → 0.1.4-beta

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.
@@ -213,5 +213,5 @@ xdescribe('MyComponent', () => {
213
213
  // After:
214
214
  describe('MyComponent', () => {
215
215
  it('should render', () => { ... });
216
- });`};var te="component-no-manual-detect-changes",Ft=new Set(["detectChanges","markForCheck"]),qt=new Set(["cdr","cdref","changedetectorref","_cdr","_cdref","changedetector","_changedetector","changedetectionref","cd","_cd"]),He=createAnyAngularClassRule(te,(t,e)=>{var r,i;let o,l,u=t.node;if(i=u,analyzeComponent(i)?.type!=="Component")return null;let a=(l=(r=(function(n){let f=new Set,m=w(n),d=U(m);if(d){for(let h of ee(d.value??d))if($(h)==="ChangeDetectorRef"){let y=F(h);y&&f.add(y);}}for(let h of m)if(h.type==="PropertyDefinition"&&h.value){let y=s(h.value);if(y&&(function(g){if(g.type!=="CallExpression")return false;let S=s(g.callee);if(S?.type!=="Identifier"||S.name!=="inject")return false;let[A]=g.arguments??[],M=s(A);return M?.type==="Identifier"&&M.name==="ChangeDetectorRef"})(y)){let g=h.key;g?.type==="Identifier"&&f.add(g.name);}}return f})(u)).size>0,n=>!!r.has(n)||!l&&qt.has(n.toLowerCase())),p=(o=analyzeComponent(u),o?.type==="Component"&&o.changeDetection?.kind==="literal"&&o.changeDetection.value===ChangeDetectionStrategy.OnPush),c=(function(n,f,m,d){let h=[],y=[...w(n)];for(;y.length>0;){let g=s(y.pop());if(!g)continue;let S=(function(A){if(A.type!=="CallExpression")return null;let M=s(A.callee);if(!x(M))return null;let P=v(M);return P&&Ft.has(P)?P:null})(g);for(let A of(S&&(function(M,P){if(M.type!=="CallExpression")return false;let I=s(M.callee);if(!I||!x(I))return false;let T=s(I.object);if(!T)return false;if(T.type==="Identifier")return P(T.name);if(!x(T))return false;let D=s(T.object),_=v(T);return (D?.type==="ThisExpression"||D?.type==="Identifier"&&D.name==="this")&&!!_&&P(_)})(g,d)&&(m&&S==="markForCheck"||h.push((function(M,P,I,T){let D=b(M),{line:_,column:V}=P.locator.location(D);return {filePath:P.filePath,ruleName:te,message:T?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${I}) can hide state-flow bugs and make rendering harder to predict.`,line:_,column:V,severity:T?"warn":"error",fix:E[te],codeExample:R[te]}})(g,f,S,m))),C(g)))y.push(A);}return h})(u,e,p,a);return c.length>0?c:null});var Se="signal-no-side-effects-in-computed",zt=new Set(["post","put","patch","subscribe","unsubscribe","next","complete","setItem","removeItem","appendChild","removeChild","dispatch"]),Wt=new Set(["set","update","mutate"]),Vt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]),ze=createCallExpressionRule(Se,(t,e)=>{if(!O(t.callee,"computed"))return null;let r=G(t),i=r?K(r):null;if(!i)return null;let o=(function(l){let u=[l];for(;u.length>0;){var a;let p=s(u.pop());if(p){if(p!==l){if((function(c){let n=s(c);if(!n)return false;if(n.type==="AssignmentExpression"){let f=s(n.left);return !!f&&x(f)}if(n.type==="UpdateExpression"||n.type==="UnaryExpression"&&n.operator==="delete"){let f=s(n.argument);return !!f&&x(f)}return false})(p))return {node:p,type:"write"};if(p.type==="CallExpression"){let c=(function(n){let f=s(n);if(!f||f.type!=="CallExpression")return "";let m=s(f.callee);return x(m)&&v(m)||""})(p);if(Wt.has(c))return {node:p,type:"write"};if(zt.has(c))return {node:p,type:"effect"}}}if(!(p!==l&&(a=p).type&&Vt.has(a.type)))for(let c of C(p))u.push(c);}}return null})(i);return o?(function(l,u,a,p){let c=b(l)||b(u),{line:n,column:f}=a.locator.location(c);return {filePath:a.filePath,ruleName:Se,message:p==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:n,column:f,severity:"error",fix:E[Se]}})(o.node,t,e,o.type):null});var ve="signal-effect-must-be-destroy-scoped",We=createAnyAngularClassRule(ve,(t,e)=>{let r=w(t.node);if(r.length===0)return null;let i=[];for(let o of r)o&&B(o)&&!be(o)&&i.push(...(function(l,u){let a=L(l);if(!a)return [];let p=$e(l),c=[];for(let n of _e(a))(function(f){if(f.type!=="CallExpression")return false;let m=s(f.callee);return !!m&&(m.type==="Identifier"?m.name==="effect":!!x(m)&&v(m)==="effect")})(n)&&!(function(f){let m=s((Array.isArray(f.arguments)?f.arguments:[])[1]);if(!m||m.type!=="ObjectExpression")return false;for(let d of Array.isArray(m.properties)?m.properties:[]){let h=s(d);if(h?.type==="Property"){let y=s(h.key),g=y?.type==="Identifier"?y.name:v(y)||"";if(g==="injector")return true;if(g==="manualCleanup"){let S=s(h.value);if(S?.type==="Literal"&&S.value===true)return true}}}return false})(n)&&c.push((function(f,m,d){let h=b(f),{line:y,column:g}=d.locator.location(h);return {filePath:d.filePath,ruleName:ve,message:`effect() inside "${m}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:g,severity:"error",fix:E[ve]}})(n,p,u));return c})(o,e));return i.length>0?i:null});var re="rxjs-no-nested-subscribe",Gt=new Set(["next","error","complete"]),Kt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function Ae(t){if(t.type!=="CallExpression")return false;let e=s(t.callee);return !!x(e)&&v(e)==="subscribe"}function Ve(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var Xe=createCallExpressionRule(re,(t,e)=>{if(!Ae(t))return null;for(let r of (function(i){if(!Ae(i))return [];let o=Array.isArray(i.arguments)?i.arguments:[];if(o.length===0)return [];let l=s(o[0]);if(l?.type==="ObjectExpression"){if(l.type!=="ObjectExpression")return [];let a=[];for(let p of Array.isArray(l.properties)?l.properties:[]){let c=s(p);if(c?.type==="Property"&&Gt.has((function(n){let f=s(n.key);return f?f.type==="Identifier"?f.name:v(f)||"":""})(c))){let n=s(c.value);Ve(n)&&a.push(n);}}return a}let u=[];for(let a=0;a<Math.min(o.length,3);a++){let p=s(o[a]);Ve(p)&&u.push(p);}return u})(t)){let i=s(r.body);if(i&&(function(o){let l=[o];for(;l.length>0;){var u;let a=s(l.pop());if(a){if(a!==o&&Ae(a))return true;if(!(a!==o&&(u=a).type&&Kt.has(u.type)))for(let p of C(a))l.push(p);}}return false})(i))return (function(o,l){let u=b(o),{line:a,column:p}=l.locator.location(u);return {filePath:l.filePath,ruleName:re,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:a,column:p,severity:"error",fix:E[re],codeExample:R[re]}})(t,e)}return null});var ne="prefer-on-push-component-change-detection";function ie(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function oe(t){return t.replace(/\\/g,"/")}var Ye=createComponentRule(ne,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(i){if(!i||typeof i!="object")return false;let{kind:o,value:l}=i;return o!=="non-literal"&&(o==="literal"?l!==ChangeDetectionStrategy.OnPush:o==="missing")})(r.changeDetection)?null:(function(i,o){let l,u,a,p,c=(l=i.metadata??{},u=i.node,ie(l,"decoratorStart")??ie(l,"start")??ie(u,"start")??ie(i,"start")??0),{line:n,column:f}=o.locator.location(c),m=(a=i.metadata,typeof(p=a?.className)=="string"?p:"AnonymousComponent"),d=(function(h,y){if(!y.project)return null;let g=h.metadata,S=g?.className;if(typeof S!="string"||!S)return null;let A=oe(y.filePath),{ngModuleMap:M,classToFile:P}=y.project;for(let[T,D]of M){var I;if(D.isStandalone||!D.declarations.has(S))continue;let _=P.get(S);if(_&&oe(_)!==A)continue;let V=0;for(let Ie of D.declarations)Ie!==S&&(I=P.get(Ie))&&oe(I).endsWith(".component.ts")&&V++;return {moduleName:(oe(T).split("/").pop()??T).replace(/\.ts$/,""),siblingComponentCount:V}}return null})(i,o);return {filePath:o.filePath,ruleName:ne,message:(function(h,y){if(!y)return `Component '${h}' uses default change detection, which can re-render more often than needed.`;let{moduleName:g,siblingComponentCount:S}=y,A=S>0?` ${S} other component${S===1?"":"s"} are declared in '${g}'.`:"";return `Component '${h}' uses default change detection, which can re-render more often than needed.${A}`})(m,d),line:n,column:f,severity:"error",fix:E[ne],codeExample:R[ne]}})(t,e)},{requires:{projectContext:true}});var Ne="template-no-call-expression",tr=new Set(["translate","$localize","$any"]),rr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function Ge(t){let e=s(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var Ke=createTemplateExpressionRule(Ne,(t,e)=>(function(r,i){let o=r?[r]:[];for(;o.length>0;){let l=s(o.pop());if(l){if(Ge(l)&&!(function(u){let a=s(u);if(!a||!Ge(a))return false;let p=s(a.callee);if(!p)return false;if(p.type==="Identifier")return tr.has(p.name);if(!x(p))return false;let c=v(p);return !!c&&rr.has(c)})(l)){if((function(a){let p;return (p=s(a),Array.isArray(p?.arguments)?p.arguments:[]).length>0})(l))return true;let u=(function(a){let p=s(a);if(!p)return "";let c=s(p.callee);return c?c.type==="Identifier"?c.name??"":x(c)?v(c):"":""})(l);if(u&&!(function(a,p){let c=a.startsWith("get")||a.startsWith("is")||a.startsWith("has");if(p.crossRef?.signalMembers?.has(a))return true;if(p.typeChecker&&p.crossRef?.componentPath)try{let n=p.typeChecker,f=p.crossRef.componentPath,m=n.getProgram().getSourceFile(f);if(m){let d=m.statements.find(h=>er.isClassDeclaration(h));if(d&&d.name){let h=n.getTypeAtLocation(d),y=n.getPropertyOfType(h,a);if(y){if(!y)return !1;let g=y.valueDeclaration??y.declarations?.[0];if(!g)return !1;let S=n.getTypeOfSymbolAtLocation(y,g);if(!S)return !1;let A=n.typeToString(S);return A.includes("Signal")||A.includes("writable")||A.includes("computed")}}}}catch{}return !c})(u,i))return true}for(let u of C(l))o.push(u);}}return false})(t.expression,e)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Ne,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:l,column:u,severity:"error",fix:E[Ne]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function Ze(t,e,r,i){let o=k(t,e.sourceSpan.start),{line:l,column:u}=t.locator.location(o);return {filePath:t.filePath,ruleName:r,message:i,line:l,column:u,severity:"error",fix:E[r]}}var Qe=createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let i of t.attributes)i.name==="*ngFor"&&!(function(o){return !!o.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(i.value??"")&&r.push(Ze(e,i,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let i of t.blocks)i.name!=="for"||i.parameters.some(o=>{let l=o.expression?.trim()??"";return !!l&&!!/^track\b/.test(l)&&l.replace(/^track\b/,"").trim().length>0})||r.push(Ze(e,i,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var Ce="template-no-object-literal-binding",Je=createTemplateExpressionRule(Ce,(t,e)=>(function(r){let i=r?[r]:[];for(;i.length>0;){let o=s(i.pop());if(o){if(o.type==="ObjectExpression")return true;for(let l of C(o))i.push(l);}}return false})(t.expression)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Ce,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Ce]}})(t,e)]:null,{requires:{htmlAst:true}});var Re="template-no-array-literal-binding",et=createTemplateExpressionRule(Re,(t,e)=>(function(r){let i=r?[r]:[];for(;i.length>0;){let o=s(i.pop());if(o){if(o.type==="ArrayExpression")return true;for(let l of C(o))i.push(l);}}return false})(t.expression)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Re,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Re]}})(t,e)]:null,{requires:{htmlAst:true}});var we=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),tt=createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(l){let u=s(l.callee);if(!u)return null;if(u.type==="Identifier"&&u.name)return we.has(u.name)?u.name:null;if(x(u)){let a=v(u);return a&&we.has(a)?a:null}return null})(t);if(!r)return null;let{line:i,column:o}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${we.get(r)} sanitization, which can expose unsafe content.`,line:i,column:o,severity:"error",fix:E["no-bypass-sanitization"]}});var lr=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),ur=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,cr=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,rt=createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=lr.get(t.name);if(!r)return null;let i=t.value??"";if(ur.test(i)||cr.test(i)||t.name==="[style]"&&!/[.(|?]/.test(i))return null;let{line:o,column:l}=e.locator.location(k(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:o,column:l,severity:r.severity,fix:E["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var fr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),nt=createAnyAngularClassRule("no-document-access",(t,e)=>{let r=w(t.node);if(r.length===0)return null;let i=(function(a){let p=new Set,c=[...a];for(;c.length;){let n=s(c.pop());if(n){if(n.type==="VariableDeclarator"&&n.init){let f=s(n.init);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=n.id??n.key;m?.type==="Identifier"&&m.name&&p.add(m.name);}}if(n.type==="AssignmentExpression"&&n.right){let f=s(n.right);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=s(n.left);if(m&&x(m)&&s(m.object)?.type==="ThisExpression"){let d=m.property?.name;typeof d=="string"&&d&&p.add(d);}}}for(let f of C(n))c.push(f);}}return p})(r),o=[],l=new Set,u=[...r];for(;u.length;){let a=s(u.pop());if(a){if(a.type==="IfStatement"&&a.test){let p=s(a.test);if(p){let c=(function(n,f){let m=[n];for(;m.length;){let d=s(m.pop());if(d){if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformBrowser"))return "browser";if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformServer"))return "server";if(d.type==="UnaryExpression"&&d.operator==="!"&&d.argument){let h=s(d.argument);if(h?.type==="CallExpression"&&h.callee&&O(h.callee,"isPlatformServer"))return "browser"}if(d.type==="Identifier"&&f.has(d.name))return "browser";for(let h of C(d))m.push(h);}}return null})(p,i);if(c==="browser"){a.alternate&&u.push(a.alternate);continue}if(c==="server"){a.consequent&&u.push(a.consequent);continue}}}if(a.type==="CallExpression"&&a.callee){let p=s(a.callee);if(p&&(O(p,"afterNextRender")||O(p,"afterRender"))){let c=a.arguments??[];for(let n=1;n<c.length;n++)u.push(c[n]);continue}}if(x(a)){let p=(function(c){let n=c;for(;n&&x(n);)n=s(n.object);return n?.type==="Identifier"?n.name??null:null})(a);if(p&&fr.has(p)){let c=a;for(;c&&x(c);)c=s(c.object);let n=b(c);if(n!==void 0&&!l.has(n)){l.add(n);let{line:f,column:m}=e.locator.location(n);o.push({filePath:e.filePath,ruleName:"no-document-access",message:`Direct access to \`${p}\` can run during SSR where browser globals do not exist.`,line:f,column:m,severity:"error",fix:E["no-document-access"],codeExample:R["no-document-access"]});}}}for(let p of C(a))u.push(p);}}return o.length?o:null});var dr=new Set(["nativeElement","getBoundingClientRect","querySelector","querySelectorAll","getElementById","createElement","scrollIntoView","focus","blur","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollTop","scrollLeft","innerHTML","outerHTML","textContent","parentElement","parentNode","firstChild","lastChild","nextSibling","previousSibling","children","ownerDocument","insertBefore","appendChild","removeChild","replaceChild","cloneNode","setAttribute","getAttribute","removeAttribute","hasAttribute","classList","dispatchEvent","contains","matches","closest","getClientRects","addEventListener","removeEventListener","requestAnimationFrame","cancelAnimationFrame"]),yr=["getElementsBy","offset","client","scroll"],it=createAnyAngularClassRule("prefer-after-render-over-after-view-init",(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[];for(let o of ["ngAfterViewInit","ngAfterContentInit"]){let l=r.find(c=>c.key?.name===o),u=l?L(l):null;if(!u||!l||!(function(c){let n=[c];for(;n.length;){let f=s(n.pop());if(f){if((f.type==="MemberExpression"||f.type==="StaticMemberExpression"||f.type==="OptionalMemberExpression")&&!f.computed){let m=f.property?.name??"";if(dr.has(m))return true;for(let d of yr)if(m.startsWith(d))return true}if(f.type==="Identifier"&&(f.name==="document"||f.name==="window"))return true;for(let m of C(f))n.push(m);}}return false})(u))continue;let{line:a,column:p}=e.locator.location(b(l));i.push({filePath:e.filePath,ruleName:"prefer-after-render-over-after-view-init",message:`\`${o}\` contains DOM access that can run before browser-only APIs are safe.`,line:a,column:p,severity:"warn",fix:E["prefer-after-render-over-after-view-init"],codeExample:R["prefer-after-render-over-after-view-init"]});}return i.length?i:null});var ae=new Map;function Me(t){return /ngOnDestroy\s*\([^)]*\)\s*\{[^}]*\.unsubscribe\s*\(\)/s.test(t)}var ot=createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{var r,i;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t))return null;let l=s(t.callee),u=x(l)?l?.object:null;if(u&&Z(u)||J(Q(u))||(r=e.filePath,i=e.fileContent,(o=ae.get(r))!==void 0||(o=Me(i),ae.size>=500&&ae.clear(),ae.set(r,o)),o))return null;let a=b(t),{line:p,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:p,column:c,severity:"error",fix:E["rxjs-require-takeUntilDestroyed"]}});var se=new Map,le="rxjs-no-subscribe-in-component",at=createCallExpressionRule(le,(t,e)=>{var r,i;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t)||(function(n){let f=s(n.callee);if(!f||!x(f))return false;let m=s(f.object);if(!m)return false;if(m.type==="CallExpression"){let d=s(m.callee);if(x(d)&&v(d)==="pipe"&&(Array.isArray(m.arguments)?m.arguments:[]).some(h=>{let y=s(h);if(y?.type!=="CallExpression")return false;let g=s(y.callee)?.name;return g==="take"||g==="first"}))return true}return J(Q(m))})(t))return null;let l=s(t.callee),u=s(l?.object);if(u&&Z(u)||(r=e.filePath,i=e.fileContent,(o=se.get(r))!==void 0||(o=Me(i),se.size>=500&&se.clear(),se.set(r,o)),o))return null;let a=b(t),{line:p,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:le,message:(function(n,f){let m="Open-ended subscriptions in components can outlive the component and make state harder to track.",d=f.crossRef?.templateReferences;if(!d)return m;let h=s(n.callee),y=s(h?.object),g=y?v(y):null;if(!g)return m;let S=g.endsWith("$")?g.slice(0,-1):g;return d.has(g)||d.has(S)?`'${g}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:m})(t,e),line:p,column:c,severity:"error",fix:E[le],codeExample:R[le]}},{requires:{projectContext:true}});var ue="rxjs-avoid-subject-as-event-bus",st=new Set(["Subject","ReplaySubject","AsyncSubject","BehaviorSubject"]),xr=new Set(["destroy$","destroyed$","ondestroy$","ngondestroy$","unsubscribe$","unsub$","teardown$","dispose$","cleanup$","cleanupsubject$"]),br=/state|loading|error|active|selected|open|visible|disabled|count|value|data|hidden|expanded|pending|success|failed/i;function H(t,e,r){let i=[t];for(;i.length;){let o=s(i.pop());if(!o)continue;let l=s(o.callee);if(o.type==="CallExpression"&&v(l)===e){let u=s(l?.object);if(u&&x(u)&&s(u.object)?.type==="ThisExpression"){let a=v(u);a&&r.add(a);}}for(let u of C(o))i.push(u);}}var lt=createAnyAngularClassRule(ue,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node);if(r.length===0)return null;let i=(function(a){let p=Be(a.sourceText,st),c=new Map;for(let[n,f]of p)for(let m of f)c.set(m,n);return c})(e),o=(function(a){let p=new Set,c=U(a);if(c){let n=L(c);n&&H(n,"next",p);}for(let n of a)if(B(n)){n.kind==="set"&&(function(m){let d=m.decorators;if(!Array.isArray(d))return false;for(let h of d){let y=s(h.expression);if(y?.name==="Input"||s(y?.callee)?.name==="Input")return true}return false})(n)&&H(n,"next",p);let f=n.key?.name;if(f==="ngOnChanges"){let m=L(n);m&&H(m,"next",p);}if(f==="ngOnDestroy"){let m=L(n);m&&H(m,"complete",p);}}else n.type==="PropertyDefinition"&&n.value&&H(n.value,"next",p);return p})(r),l=(function(a){let p=new Set;for(let c of a){let n=B(c)?L(c):c.type==="PropertyDefinition"?c.value:null;n&&H(n,"pipe",p);}return p})(r),u=[];for(let a of r){if(a.type!=="PropertyDefinition"||a.accessibility==="public")continue;let p=s(a.value??a.initializer);if(!p||p.type!=="NewExpression")continue;let c=(function(d,h){let y=s(d);if(!y)return null;if(y.type==="Identifier")return h.get(y.name)??null;if(x(y)){let g=v(y);return g&&st.has(g)?g:null}return null})(p.callee,i),n=a.key?.name??"";if(!c||!n||xr.has(n.toLowerCase())||o.has(n)||l.has(n))continue;let{line:f,column:m}=e.locator.location(b(a));u.push({filePath:e.filePath,ruleName:ue,message:br.test(n)?`${c} '${n}' is used for component UI state, which adds stream overhead to local state updates.`:`${c} '${n}' is acting as a local event bus, which makes component interactions harder to trace.`,line:f,column:m,severity:"warn",fix:E[ue],codeExample:R[ue]});}return u.length?u:null});var Pe="rxjs-prefer-toSignal-for-template-state",ut=new Set(["Observable","Subject","BehaviorSubject","ReplaySubject","AsyncSubject"]),vr=new Set(["destroy$","destroyed$","unsub$","teardown$","dispose$"]),ct=createAnyAngularClassRule(Pe,(t,e)=>{if(t.metadata?.type!=="Component")return null;let i=e.crossRef?.templateReferences;if(i===void 0)return null;let o=w(t.node),l=[];for(let u of o){if(u.type!=="PropertyDefinition")continue;let a=u.key?.name??"";if(!a||!a.endsWith("$")||vr.has(a.toLowerCase())||(function(f){let m=f.modifiers,d=f.decorators??(Array.isArray(m)?m.filter(h=>h.type==="Decorator"):void 0);return Array.isArray(d)&&d.some(h=>{let y=s(h.expression);return (y?.type==="CallExpression"?j(y):y?.type==="Identifier"?y.name:null)==="Output"})})(u))continue;let p=a.slice(0,-1);if(!i.has(a)&&!i.has(p)||!(function(f){if(ut.has((function(y){let g=y.typeAnnotation,S=s(g?.typeAnnotation);if(!S||S.type!=="TSTypeReference"&&S.type!=="TypeReference")return "";let A=S.typeName??S.name;if(typeof A=="string")return A;if(A&&typeof A=="object"){if(A.type==="Identifier")return A.name??"";if(A.type==="TSQualifiedName")return s(A.right)?.name??""}return ""})(f)))return true;let m=s(f.value??f.initializer);if(!m)return false;let d=j(m);if(d==="toSignal"||d==="signal"||d==="computed")return false;if(m.type==="NewExpression"){let y=s(m.callee),g=y?.type==="Identifier"?y.name:v(y);return !!g&&ut.has(g)}let h=[m];for(;h.length>0;){let y=s(h.pop());if(y){if(y.type==="CallExpression"&&j(y)==="pipe")return true;for(let g of C(y))h.push(g);}}return false})(u))continue;let{line:c,column:n}=e.locator.location(b(u));l.push({filePath:e.filePath,ruleName:Pe,message:`Observable "${a}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:c,column:n,severity:"warn",fix:E[Pe]});}return l.length?l:null},{requires:{projectContext:true,htmlAst:true}});var Oe="toSignal-require-initialValue",pt=createCallExpressionRule(Oe,(t,e)=>{if(!O(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],i=r[1]?s(r[1]):null;if(!i||i.type!=="ObjectExpression"||!(function(o){let l=W(o,"initialValue");if(l&&!xe(l.value))return true;let u=W(o,"requireSync");return !!u&&Ee(u.value)})(i)){let{line:o,column:l}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:Oe,message:"toSignal() can emit undefined before the observable produces a value.",line:o,column:l,severity:"warn",fix:E[Oe]}}return null});var Cr=new Set(["set","update","mutate"]),Rr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame","then","catch","finally","subscribe"]),ft=createCallExpressionRule("signal-prefer-computed-over-sync-effect",(t,e)=>{if(!O(t.callee,"effect"))return null;let r=G(t),i=r?K(r):null;if(!i)return null;let{hasRead:o,hasWrite:l,hasAsync:u,hasLinked:a,firstWrite:p}=(function(f,m){let d={hasRead:false,hasWrite:false,hasAsync:false,hasLinked:false,firstWrite:null},h=[f];for(;h.length;){let y=s(h.pop());if(y){if((y.type==="AwaitExpression"||y.type==="YieldExpression")&&(d.hasAsync=true),y.type==="CallExpression"){let g=j(y);g&&Rr.has(g)&&(d.hasAsync=true),g==="linkedSignal"&&(d.hasLinked=true),(function(S){let A=s(S);if(!A||A.type!=="CallExpression")return false;let M=s(A.callee);return x(M)&&Cr.has(v(M)||"")})(y)?(d.hasWrite=true,d.firstWrite||(d.firstWrite=y)):(function(S,A,M){let P=s(S);if(!P||P.type!=="CallExpression"||Array.isArray(P.arguments)&&P.arguments.length>0)return false;let I=s(P.callee);if(!I)return false;if(A.typeChecker)try{let T=q(I,A);if(T){let D=A.typeChecker.getTypeOfSymbolAtLocation(T,T.valueDeclaration);if(D&&A.typeChecker.typeToString(D).includes("Signal"))return !0}}catch{}return x(I)?s(I.object)?.type==="ThisExpression":M&&I.type==="Identifier"})(y,m,true)&&(d.hasRead=true);}for(let g of C(y))h.push(g);}}return d})(i,e);if(!l||!o||u||a)return null;let{line:c,column:n}=e.locator.location(b(p||t));return {filePath:e.filePath,ruleName:"signal-prefer-computed-over-sync-effect",message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:c,column:n,severity:"warn",fix:E["signal-prefer-computed-over-sync-effect"]}},{requires:{typeChecker:true}});var mt=new Set(["afterRender","afterNextRender"]),Mr=/\bafterNextRender\s*\(|\bafterRender\s*\(/,ce=new Map,dt=createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!O(t.callee,"untracked")||(function(o,l){let u=l.sourceText??l.fileContent;if(typeof u=="string"&&!Mr.test(u))return false;let a=o.parent;for(;a;){if(a.type==="CallExpression"&&mt.has(j(a)))return true;a=a.parent;}let p=b(o);return (function(c){let n=ce.get(c.filePath);if(n!==void 0)return n;let f=c.program;return n=f?(function(m){let d=[],h=m.body,y=Array.isArray(h)?[...h]:[m];for(;y.length;){let g=s(y.pop());if(g){if(g.type==="CallExpression"&&mt.has(j(g))){let S=s(g.arguments?.[0]);if(S){let A=b(S),M=S.end??S.span?.end??b(S);M>A&&d.push([A,M]);}}for(let S of C(g))y.push(S);}}return d})(f):[],ce.size>=300&&ce.clear(),ce.set(c.filePath,n),n})(l).some(([c,n])=>p>=c&&p<n)})(t,e))return null;let{line:r,column:i}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:i,severity:"warn",fix:E["signal-avoid-untracked-overuse"]}});var pe="prefer-inject-over-constructor-di",Or=new Set(["http","router","route","cdr","cdref","changedetectorref","injector","ngzone","zone","renderer","renderer2","elementref","el","document","platform","location","dialog","snack","toast","store","facade","logger","translate","i18n","auth","api","client","matdialog","overlay","breakpointobserver","snackbar","matsnackbar","bottomsheet","matbottomsheet","clipboard","directionality","focusmonitor","mediamatcher","viewportruler","scrolldispatcher","dragdrop","liveannouncer","activatedroute","fb","firestore","angularfire","formbuilder","titleservice","metaservice","title","meta","sanitizer","domsanitizer","compiler","applicationref","componentfactoryresolver","viewcontainerref","templateref","destroyref"]),Tr=new Set(["data","config","options","opts","params","payload","input","value","values","items","item","context","ctx","model","vm","state","initialstate","result","name","id","label","text","title","message","url","path","index","count","size","length","width","height","color","type","key","mode","flag","enabled","disabled","visible","hidden"]),Ir=["Service","Facade","Store","Client","Repository","Adapter","Manager","Controller","Provider","Registry","Logger","Router","ActivatedRoute","ChangeDetectorRef","DestroyRef","Injector","NgZone","Renderer2","ElementRef","HttpClient","ViewContainerRef","TemplateRef","ComponentFactoryResolver","ApplicationRef","MatDialog","MatDialogRef","MatSnackBar","MatBottomSheet","Overlay","OverlayRef","BreakpointObserver","Clipboard","FocusMonitor","MediaMatcher","ScrollDispatcher","DragDrop","LiveAnnouncer","Directionality","ViewportRuler","FormBuilder","DomSanitizer","Title","Meta","Dispatcher","Gateway","Handler","Interceptor","Guard","Resolver","Factory","Strategy","Validator"],kr=new Set(["string","number","boolean","symbol","bigint","any","unknown","void"]),yt=createAnyAngularClassRule(pe,(t,e)=>{let r=U(w(t.node));if(!r)return null;let i=ee(r.value??r).filter(a=>(function(p,c){let n=s(p);if(!n)return false;if(Array.isArray(n.decorators)&&n.decorators.length>0||n.accessibility||n.readonly)return true;if(c.typeChecker){let d=q(p,c);if(d&&Fe(d))return true}let f=(F(p)||"").toLowerCase().trim();if(!f||Tr.has(f))return false;if(Or.has(f))return true;let m=($(p)||"").trim();return !(!m||kr.has(m.toLowerCase()))&&Ir.some(d=>m.endsWith(d))})(a,e));if(i.length===0)return null;let{line:o,column:l}=e.locator.location(b(r)),u=i.map(a=>`${F(a)}: ${$(a)}`).join(", ");return {filePath:e.filePath,ruleName:pe,message:`Constructor dependency injection makes class setup less composable than inject().${u?` Offending params: ${u}.`:""}`,line:o,column:l,severity:"warn",fix:E[pe],codeExample:R[pe]}},{requires:{typeChecker:true}});var fe="signal-prefer-input-signal";function jr(t){let e=s(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var ht=createAnyAngularClassRule(fe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[],o=e.project?.standaloneComponents?.has(e.filePath)??false;for(let l of r){let u=s(l);if(u&&(u.type==="PropertyDefinition"||u.type==="AccessorProperty")&&Array.isArray(u.decorators)&&u.decorators.some(jr)){let a=b(u),{line:p,column:c}=e.locator.location(a),n=s(u.key),f=(n?.type==="Identifier"?n.name:n?.type==="Literal"?String(n.value):"")||"(unknown)",m=`'${f}' uses @Input(), which keeps this input outside Angular's signal graph.`;o&&(m+=" Standalone declarations benefit most from signal inputs."),i.push({filePath:e.filePath,ruleName:fe,message:m,line:p,column:c,severity:o?"error":"warn",fix:E[fe],codeExample:R[fe]});}}return i.length>0?i:null},{requires:{projectContext:true}});var me="signal-prefer-output-function",gt=createAnyAngularClassRule(me,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[];for(let o of r){let l=s(o);if(l&&(l.type==="PropertyDefinition"||l.type==="AccessorProperty")&&Array.isArray(l.decorators)&&l.decorators.some(u=>{let a=s(u.expression??u);if(!a)return false;if(a.type==="Identifier")return a.name==="Output";if(a.type==="CallExpression"){let p=s(a.callee);return p?.type==="Identifier"&&p.name==="Output"}return false})&&(function(u,a){let p=s(u.value);if(p?.type==="NewExpression"){let n=s(p.callee);if(n?.type==="Identifier"&&n.name==="EventEmitter")return true}let c=s(u.typeAnnotation);if(c&&$(c).includes("EventEmitter"))return true;if(a.typeChecker){let n=q(u,a);if(n&&(typeof n.getName=="function"?n.getName():"").includes("EventEmitter"))return true}return false})(l,e)){let u=b(l),{line:a,column:p}=e.locator.location(u),c=s(l.key),n=(c?.type==="Identifier"?c.name:c?.type==="Literal"?String(c.value):"")||"(unknown)";i.push({filePath:e.filePath,ruleName:me,message:`'${n}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:a,column:p,severity:"warn",fix:E[me],codeExample:R[me]});}}return i.length>0?i:null},{requires:{typeChecker:true}});var de="signal-prefer-model";function Et(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let i=s(r.expression??r);if(!i)return false;if(i.type==="Identifier")return i.name===e;if(i.type==="CallExpression"){let o=s(i.callee);return o?.type==="Identifier"&&o.name===e}return false})}function xt(t,e){let r=s(t.value);if(!r||r.type!=="CallExpression")return false;let i=s(r.callee);if(!i)return false;if(i.type==="Identifier")return i.name===e;if(x(i)){let o=s(i.object);return o?.type==="Identifier"&&o.name===e}return false}var bt=createAnyAngularClassRule(de,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=new Map,o=new Map;for(let u of r){let a=s(u);if(!a||a.type!=="PropertyDefinition"&&a.type!=="AccessorProperty")continue;let p=(function(c){let n=s(c.key);return n?n.type==="Identifier"?n.name??null:n.type==="Literal"?String(n.value):null:null})(a);p&&((Et(a,"Input")||xt(a,"input"))&&i.set(p,a),(Et(a,"Output")||xt(a,"output"))&&o.set(p,a));}let l=[];for(let[u,a]of o){if(!u.endsWith("Change"))continue;let p=u.slice(0,-6),c=i.get(p);if(c){let n=b(c),{line:f,column:m}=e.locator.location(n);l.push({filePath:e.filePath,ruleName:de,message:`The \`${p}\` / \`${u}\` pair implements two-way binding with extra wiring that model() avoids.`,line:f,column:m,severity:"warn",fix:E[de],codeExample:R[de]});}}return l.length>0?l:null});var Br=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),Te="template-prefer-control-flow",St=createTemplateAttributeRule(Te,(t,e)=>{var r;let i=(r=t.name,Br.get(r)??null);if(!i)return null;let o=k(e,t.sourceSpan.start),{line:l,column:u}=e.locator.location(o);return {filePath:e.filePath,ruleName:Te,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${i}\` control flow benefits.`,line:l,column:u,severity:"error",fix:E[Te]}},{requires:{htmlAst:true}});var vt=new WeakMap,At=createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,i,o=(function c(n){let f=s(n);if(!f)return null;if(f.type==="BinaryExpression"&&f.operator==="|"){let m=s(f.right);return m?.type==="Identifier"&&m.name==="async"?s(f.left):c(f.left)}return null})(t.expression),l=o?(function c(n,f=0){if(!n||f>10)return null;if(n.type==="Identifier")return n.name;if(n.type==="ThisExpression")return "this";if(n.type==="Literal"){let m=n.value;return m===null?"null":typeof m=="string"||typeof m=="number"||typeof m=="boolean"||typeof m=="bigint"?String(m):null}if(n.type==="CallExpression"){let m=c(n.callee,f+1),d=(Array.isArray(n.arguments)?n.arguments:[]).map(h=>c(h,f+1)??"?");return `${m}(${d.join(",")})`}if(x(n)){let m=c(n.object,f+1),d=v(n);if(m&&d)return `${m}.${d}`}if(n.type==="UnaryExpression")return `${n.operator}${c(n.argument,f+1)}`;if(n.type==="ConditionalExpression")return `${c(n.test,f+1)}?${c(n.consequent,f+1)}:${c(n.alternate,f+1)}`;if(n.type==="OptionalExpression"||n.type==="ChainExpression")return c(n.expression,f+1);if(n.type==="LogicalExpression"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}if(n.type==="BinaryExpression"&&n.operator!=="|"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}if(n.type==="ArrayExpression")return `[${(n.elements??[]).map(d=>c(d,f+1)??"?").join(",")}]`;if(n.type==="ObjectExpression")return `{${(n.properties??[]).map(d=>{let h=d.key?c(d.key,f+1):"?",y=d.value?c(d.value,f+1):"?";return `${h}:${y}`}).join(",")}}`;if(n.type==="TemplateLiteral")return "`tmpl`";if(n.type==="AssignmentExpression"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}return null})(o):null;if(!l)return null;let u=(r=e.template,i=r?.templateStartOffset,`${e.filePath}@${typeof i=="number"&&Number.isFinite(i)?i:0}`),a=vt.get(e);a||(a=new Map,vt.set(e,a));let p=a.get(u);if(p||(p=new Set,a.set(u,p)),p.has(l)){let c=k(e,t.sourceSpan.start),{line:n,column:f}=e.locator.location(c);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${l}" can create repeated work and inconsistent loading states.`,line:n,column:f,severity:"warn",fix:E["template-no-async-pipe-duplication"]}}return p.add(l),null},{requires:{htmlAst:true}});var qr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),Hr=new Set(["xdescribe","xit","xtest","xcontext"]);function Nt(t){return t.type==="Identifier"?t.name??null:null}var Ct=createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let i;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let o=s(t.callee);if(!o)return null;let l=(i=Nt(o)||(function(n){if(n.type==="MemberExpression"||n.type==="StaticMemberExpression"||n.type==="OptionalMemberExpression"){let f=s(n.object),m=n.property?.name??"",d=(f?.type==="Identifier"?f.name:"")??"";return d?`${d}.${m}`:null}return null})(o))&&qr.has(i)?i:null;if(!l){if(Nt(o)==="pending"){let n=b(t),{line:f,column:m}=e.locator.location(n);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:f,column:m,severity:"error",fix:E["spec-no-focused-test"]}}return null}let u=b(t),{line:a,column:p}=e.locator.location(u),c=Hr.has(l)?`\`${l}\` disables a test that may be forgotten.`:`\`${l}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:c,line:a,column:p,severity:"error",fix:E["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function Rt(){N(He,"correctness"),N(ze,"correctness"),N(We,"correctness"),N(Xe,"correctness"),N(Ye,"performance"),N(Ke,"performance"),N(Qe,"performance"),N(Je,"performance"),N(et,"performance"),N(tt,"security"),N(rt,"security"),N(nt,"ssr"),N(it,"ssr"),N(at,"reactivity"),N(ot,"reactivity"),N(lt,"reactivity"),N(ct,"reactivity"),N(pt,"reactivity"),N(ft,"reactivity"),N(dt,"reactivity"),N(yt,"modern-api"),N(ht,"modern-api"),N(gt,"modern-api"),N(bt,"modern-api"),N(St,"template"),N(At,"template"),N(Ct,"testing");}(async()=>{if(Rt(),configureRuleExecutor(De,ke),!parentPort)return;let{rootDir:t,tasks:e}=workerData,r=[],i=[],o=createAnalysisContext(t),l=new Map;for(let u of e){let a=l.get(u.filePath)??[];a.push(u),l.set(u.filePath,a);}for(let[u,a]of l){let p=performance.now();try{let c=await executeBatchedTasks(a,o);r.push(...c),parentPort.postMessage(wt(u,a.length,c,performance.now()-p));}catch(c){for(let n of a)i.push({task:n,error:c instanceof Error?c.message:String(c)});parentPort.postMessage(wt(u,a.length,[],performance.now()-p));}finally{o.evict(u);}}parentPort.postMessage({results:r,errors:i});})();var wt=(t,e,r,i)=>{let o=0,l=0;for(let u of r)for(let a of u.failures)a.severity==="error"?o++:a.severity==="warn"&&l++;return {kind:"file-progress",filePath:t,taskCount:e,issueCount:o+l,errorCount:o,warningCount:l,duration:i}};//# sourceMappingURL=execution-worker.js.map
216
+ });`};var te="component-no-manual-detect-changes",Ft=new Set(["detectChanges","markForCheck"]),qt=new Set(["cdr","cdref","changedetectorref","_cdr","_cdref","changedetector","_changedetector","changedetectionref","cd","_cd"]),He=createAnyAngularClassRule(te,(t,e)=>{var r,i;let o,l,u=t.node;if(i=u,analyzeComponent(i)?.type!=="Component")return null;let a=(l=(r=(function(n){let f=new Set,m=w(n),d=U(m);if(d){for(let h of ee(d.value??d))if($(h)==="ChangeDetectorRef"){let y=F(h);y&&f.add(y);}}for(let h of m)if(h.type==="PropertyDefinition"&&h.value){let y=s(h.value);if(y&&(function(g){if(g.type!=="CallExpression")return false;let S=s(g.callee);if(S?.type!=="Identifier"||S.name!=="inject")return false;let[A]=g.arguments??[],M=s(A);return M?.type==="Identifier"&&M.name==="ChangeDetectorRef"})(y)){let g=h.key;g?.type==="Identifier"&&f.add(g.name);}}return f})(u)).size>0,n=>!!r.has(n)||!l&&qt.has(n.toLowerCase())),p=(o=analyzeComponent(u),o?.type==="Component"&&o.changeDetection?.kind==="literal"&&o.changeDetection.value===ChangeDetectionStrategy.OnPush),c=(function(n,f,m,d){let h=[],y=[...w(n)];for(;y.length>0;){let g=s(y.pop());if(!g)continue;let S=(function(A){if(A.type!=="CallExpression")return null;let M=s(A.callee);if(!x(M))return null;let P=v(M);return P&&Ft.has(P)?P:null})(g);for(let A of(S&&(function(M,P){if(M.type!=="CallExpression")return false;let I=s(M.callee);if(!I||!x(I))return false;let T=s(I.object);if(!T)return false;if(T.type==="Identifier")return P(T.name);if(!x(T))return false;let D=s(T.object),_=v(T);return (D?.type==="ThisExpression"||D?.type==="Identifier"&&D.name==="this")&&!!_&&P(_)})(g,d)&&(m&&S==="markForCheck"||h.push((function(M,P,I,T){let D=b(M),{line:_,column:V}=P.locator.location(D);return {filePath:P.filePath,ruleName:te,message:T?"Manual change detection in an OnPush component couples rendering to imperative calls.":`Manual change detection (${I}) can hide state-flow bugs and make rendering harder to predict.`,line:_,column:V,severity:T?"warn":"error",fix:E[te],codeExample:R[te]}})(g,f,S,m))),C(g)))y.push(A);}return h})(u,e,p,a);return c.length>0?c:null});var Se="signal-no-side-effects-in-computed",zt=new Set(["post","put","patch","subscribe","unsubscribe","next","complete","setItem","removeItem","appendChild","removeChild","dispatch"]),Wt=new Set(["set","update","mutate"]),Vt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]),ze=createCallExpressionRule(Se,(t,e)=>{if(!O(t.callee,"computed"))return null;let r=G(t),i=r?K(r):null;if(!i)return null;let o=(function(l){let u=[l];for(;u.length>0;){var a;let p=s(u.pop());if(p){if(p!==l){if((function(c){let n=s(c);if(!n)return false;if(n.type==="AssignmentExpression"){let f=s(n.left);return !!f&&x(f)}if(n.type==="UpdateExpression"||n.type==="UnaryExpression"&&n.operator==="delete"){let f=s(n.argument);return !!f&&x(f)}return false})(p))return {node:p,type:"write"};if(p.type==="CallExpression"){let c=(function(n){let f=s(n);if(!f||f.type!=="CallExpression")return "";let m=s(f.callee);return x(m)&&v(m)||""})(p);if(Wt.has(c))return {node:p,type:"write"};if(zt.has(c))return {node:p,type:"effect"}}}if(!(p!==l&&(a=p).type&&Vt.has(a.type)))for(let c of C(p))u.push(c);}}return null})(i);return o?(function(l,u,a,p){let c=b(l)||b(u),{line:n,column:f}=a.locator.location(c);return {filePath:a.filePath,ruleName:Se,message:p==="write"?"computed() writes to state, which can create reactive cycles.":"computed() contains a side effect, so it is no longer a pure derivation.",line:n,column:f,severity:"error",fix:E[Se]}})(o.node,t,e,o.type):null});var ve="signal-effect-must-be-destroy-scoped",We=createAnyAngularClassRule(ve,(t,e)=>{let r=w(t.node);if(r.length===0)return null;let i=[];for(let o of r)o&&B(o)&&!be(o)&&i.push(...(function(l,u){let a=L(l);if(!a)return [];let p=$e(l),c=[];for(let n of _e(a))(function(f){if(f.type!=="CallExpression")return false;let m=s(f.callee);return !!m&&(m.type==="Identifier"?m.name==="effect":!!x(m)&&v(m)==="effect")})(n)&&!(function(f){let m=s((Array.isArray(f.arguments)?f.arguments:[])[1]);if(!m||m.type!=="ObjectExpression")return false;for(let d of Array.isArray(m.properties)?m.properties:[]){let h=s(d);if(h?.type==="Property"){let y=s(h.key),g=y?.type==="Identifier"?y.name:v(y)||"";if(g==="injector")return true;if(g==="manualCleanup"){let S=s(h.value);if(S?.type==="Literal"&&S.value===true)return true}}}return false})(n)&&c.push((function(f,m,d){let h=b(f),{line:y,column:g}=d.locator.location(h);return {filePath:d.filePath,ruleName:ve,message:`effect() inside "${m}" has no explicit lifecycle owner, so cleanup can be unclear.`,line:y,column:g,severity:"error",fix:E[ve]}})(n,p,u));return c})(o,e));return i.length>0?i:null});var re="rxjs-no-nested-subscribe",Gt=new Set(["next","error","complete"]),Kt=new Set(["ArrowFunctionExpression","FunctionExpression","FunctionDeclaration"]);function Ae(t){if(t.type!=="CallExpression")return false;let e=s(t.callee);return !!x(e)&&v(e)==="subscribe"}function Ve(t){return !!t&&(t.type==="ArrowFunctionExpression"||t.type==="FunctionExpression")}var Xe=createCallExpressionRule(re,(t,e)=>{if(!Ae(t))return null;for(let r of (function(i){if(!Ae(i))return [];let o=Array.isArray(i.arguments)?i.arguments:[];if(o.length===0)return [];let l=s(o[0]);if(l?.type==="ObjectExpression"){if(l.type!=="ObjectExpression")return [];let a=[];for(let p of Array.isArray(l.properties)?l.properties:[]){let c=s(p);if(c?.type==="Property"&&Gt.has((function(n){let f=s(n.key);return f?f.type==="Identifier"?f.name:v(f)||"":""})(c))){let n=s(c.value);Ve(n)&&a.push(n);}}return a}let u=[];for(let a=0;a<Math.min(o.length,3);a++){let p=s(o[a]);Ve(p)&&u.push(p);}return u})(t)){let i=s(r.body);if(i&&(function(o){let l=[o];for(;l.length>0;){var u;let a=s(l.pop());if(a){if(a!==o&&Ae(a))return true;if(!(a!==o&&(u=a).type&&Kt.has(u.type)))for(let p of C(a))l.push(p);}}return false})(i))return (function(o,l){let u=b(o),{line:a,column:p}=l.locator.location(u);return {filePath:l.filePath,ruleName:re,message:"Nested subscribe() calls make stream lifetimes harder to reason about and can leak work.",line:a,column:p,severity:"error",fix:E[re],codeExample:R[re]}})(t,e)}return null});var ne="prefer-on-push-component-change-detection";function ie(t,e){let r=t?.[e];return typeof r=="number"?r:void 0}function oe(t){return t.replace(/\\/g,"/")}var Ye=createComponentRule(ne,(t,e)=>{let r=t.metadata??{};return r.type!=="Component"||!(function(i){if(!i||typeof i!="object")return false;let{kind:o,value:l}=i;return o!=="non-literal"&&(o==="literal"?l!==ChangeDetectionStrategy.OnPush:o==="missing")})(r.changeDetection)?null:(function(i,o){let l,u,a,p,c=(l=i.metadata??{},u=i.node,ie(l,"decoratorStart")??ie(l,"start")??ie(u,"start")??ie(i,"start")??0),{line:n,column:f}=o.locator.location(c),m=(a=i.metadata,typeof(p=a?.className)=="string"?p:"AnonymousComponent"),d=(function(h,y){if(!y.project)return null;let g=h.metadata,S=g?.className;if(typeof S!="string"||!S)return null;let A=oe(y.filePath),{ngModuleMap:M,classToFile:P}=y.project;for(let[T,D]of M){var I;if(D.isStandalone||!D.declarations.has(S))continue;let _=P.get(S);if(_&&oe(_)!==A)continue;let V=0;for(let Ie of D.declarations)Ie!==S&&(I=P.get(Ie))&&oe(I).endsWith(".component.ts")&&V++;return {moduleName:(oe(T).split("/").pop()??T).replace(/\.ts$/,""),siblingComponentCount:V}}return null})(i,o);return {filePath:o.filePath,ruleName:ne,message:(function(h,y){if(!y)return `Component '${h}' uses default change detection, which can re-render more often than needed.`;let{moduleName:g,siblingComponentCount:S}=y,A=S>0?` ${S} other component${S===1?"":"s"} are declared in '${g}'.`:"";return `Component '${h}' uses default change detection, which can re-render more often than needed.${A}`})(m,d),line:n,column:f,severity:"error",fix:E[ne],codeExample:R[ne]}})(t,e)},{requires:{projectContext:true}});var Ne="template-no-call-expression",tr=new Set(["translate","$localize","$any"]),rr=new Set(["slice","toString","toFixed","toUpperCase","toLowerCase","trim","join","includes","indexOf","startsWith","endsWith","charAt","substring","replace","split","concat","toISOString","toLocaleDateString","toLocaleTimeString","toLocaleString"]);function Ge(t){let e=s(t);return !!e&&(e.type==="CallExpression"||e.type==="OptionalCallExpression")}var Ke=createTemplateExpressionRule(Ne,(t,e)=>(function(r,i){let o=r?[r]:[];for(;o.length>0;){let l=s(o.pop());if(l){if(Ge(l)&&!(function(u){let a=s(u);if(!a||!Ge(a))return false;let p=s(a.callee);if(!p)return false;if(p.type==="Identifier")return tr.has(p.name);if(!x(p))return false;let c=v(p);return !!c&&rr.has(c)})(l)){if((function(a){let p;return (p=s(a),Array.isArray(p?.arguments)?p.arguments:[]).length>0})(l))return true;let u=(function(a){let p=s(a);if(!p)return "";let c=s(p.callee);return c?c.type==="Identifier"?c.name??"":x(c)?v(c):"":""})(l);if(u&&!(function(a,p){let c=a.startsWith("get")||a.startsWith("is")||a.startsWith("has");if(p.crossRef?.signalMembers?.has(a))return true;if(p.typeChecker&&p.crossRef?.componentPath)try{let n=p.typeChecker,f=p.crossRef.componentPath,m=n.getProgram().getSourceFile(f);if(m){let d=m.statements.find(h=>er.isClassDeclaration(h));if(d&&d.name){let h=n.getTypeAtLocation(d),y=n.getPropertyOfType(h,a);if(y){if(!y)return !1;let g=y.valueDeclaration??y.declarations?.[0];if(!g)return !1;let S=n.getTypeOfSymbolAtLocation(y,g);if(!S)return !1;let A=n.typeToString(S);return A.includes("Signal")||A.includes("writable")||A.includes("computed")}}}}catch{}return !c})(u,i))return true}for(let u of C(l))o.push(u);}}return false})(t.expression,e)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Ne,message:"Template method calls run on every change detection cycle and can make rendering slower.",line:l,column:u,severity:"error",fix:E[Ne]}})(t,e)]:null,{requires:{htmlAst:true,typeChecker:true,projectContext:true}});function Ze(t,e,r,i){let o=k(t,e.sourceSpan.start),{line:l,column:u}=t.locator.location(o);return {filePath:t.filePath,ruleName:r,message:i,line:l,column:u,severity:"error",fix:E[r]}}var Qe=createTemplateRule("template-trackby-required",(t,e)=>{let r=[];for(let i of t.attributes)i.name==="*ngFor"&&!(function(o){return !!o.match(/\btrackBy\s*:\s*([^;]+?)\s*(?:;|$)/)?.[1]?.trim()})(i.value??"")&&r.push(Ze(e,i,"template-trackby-required-for-ngfor","*ngFor without trackBy can recreate DOM nodes unnecessarily when list items change."));for(let i of t.blocks)i.name!=="for"||i.parameters.some(o=>{let l=o.expression?.trim()??"";return !!l&&!!/^track\b/.test(l)&&l.replace(/^track\b/,"").trim().length>0})||r.push(Ze(e,i,"template-track-required-for-atfor","@for without a track expression can recreate DOM nodes unnecessarily when list items change."));return r.length>0?r:null},{requires:{htmlAst:true}});var Ce="template-no-object-literal-binding",Je=createTemplateExpressionRule(Ce,(t,e)=>(function(r){let i=r?[r]:[];for(;i.length>0;){let o=s(i.pop());if(o){if(o.type==="ObjectExpression")return true;for(let l of C(o))i.push(l);}}return false})(t.expression)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Ce,message:"Object literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Ce]}})(t,e)]:null,{requires:{htmlAst:true}});var Re="template-no-array-literal-binding",et=createTemplateExpressionRule(Re,(t,e)=>(function(r){let i=r?[r]:[];for(;i.length>0;){let o=s(i.pop());if(o){if(o.type==="ArrayExpression")return true;for(let l of C(o))i.push(l);}}return false})(t.expression)?[(function(r,i){let o=k(i,r.sourceSpan.start),{line:l,column:u}=i.locator.location(o);return {filePath:i.filePath,ruleName:Re,message:"Array literals in template bindings create a new reference on every change detection cycle.",line:l,column:u,severity:"warn",fix:E[Re]}})(t,e)]:null,{requires:{htmlAst:true}});var we=new Map([["bypassSecurityTrustHtml","HTML"],["bypassSecurityTrustScript","Script"],["bypassSecurityTrustStyle","Style"],["bypassSecurityTrustUrl","URL"],["bypassSecurityTrustResourceUrl","Resource URL"]]),tt=createCallExpressionRule("no-bypass-sanitization",(t,e)=>{let r=(function(l){let u=s(l.callee);if(!u)return null;if(u.type==="Identifier"&&u.name)return we.has(u.name)?u.name:null;if(x(u)){let a=v(u);return a&&we.has(a)?a:null}return null})(t);if(!r)return null;let{line:i,column:o}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"no-bypass-sanitization",message:`\`${r}\` bypasses Angular's ${we.get(r)} sanitization, which can expose unsafe content.`,line:i,column:o,severity:"error",fix:E["no-bypass-sanitization"]}});var lr=new Map([["[innerHTML]",{desc:"innerHTML directly renders HTML markup and can execute injected scripts",severity:"error"}],["[outerHTML]",{desc:"outerHTML replaces the element with raw HTML and is susceptible to XSS",severity:"error"}],["[srcdoc]",{desc:"srcdoc embeds raw HTML inside an iframe and can execute injected scripts",severity:"error"}],["[style]",{desc:"binding complex expressions to [style] can enable CSS injection",severity:"warn"}]]),ur=/\|\s*(safeHtml|safeStyle|safeUrl|safeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|trustStyle|trustUrl|trustResourceUrl|bypassSecurity)\b/i,cr=/\b(getSafeHtml|getSafeUrl|getSafeStyle|getSafeResourceUrl|sanitize|sanitizeHtml|sanitizeUrl|trustHtml|bypassSecurity)\s*\(/i,rt=createTemplateAttributeRule("template-no-unsafe-bindings",(t,e)=>{let r=lr.get(t.name);if(!r)return null;let i=t.value??"";if(ur.test(i)||cr.test(i)||t.name==="[style]"&&!/[.(|?]/.test(i))return null;let{line:o,column:l}=e.locator.location(k(e,t.sourceSpan.start));return {filePath:e.filePath,ruleName:"template-no-unsafe-bindings",message:`\`${t.name}\` binds raw content: ${r.desc}. Unsanitized values can create injection risk.`,line:o,column:l,severity:r.severity,fix:E["template-no-unsafe-bindings"]}},{requires:{htmlAst:true}});var fr=new Set(["document","window","localStorage","sessionStorage","navigator","location"]),nt=createAnyAngularClassRule("no-document-access",(t,e)=>{let r=w(t.node);if(r.length===0)return null;let i=(function(a){let p=new Set,c=[...a];for(;c.length;){let n=s(c.pop());if(n){if(n.type==="VariableDeclarator"&&n.init){let f=s(n.init);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=n.id??n.key;m?.type==="Identifier"&&m.name&&p.add(m.name);}}if(n.type==="AssignmentExpression"&&n.right){let f=s(n.right);if(f?.type==="CallExpression"&&f.callee&&O(f.callee,"isPlatformBrowser")){let m=s(n.left);if(m&&x(m)&&s(m.object)?.type==="ThisExpression"){let d=m.property?.name;typeof d=="string"&&d&&p.add(d);}}}for(let f of C(n))c.push(f);}}return p})(r),o=[],l=new Set,u=[...r];for(;u.length;){let a=s(u.pop());if(a){if(a.type==="IfStatement"&&a.test){let p=s(a.test);if(p){let c=(function(n,f){let m=[n];for(;m.length;){let d=s(m.pop());if(d){if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformBrowser"))return "browser";if(d.type==="CallExpression"&&d.callee&&O(d.callee,"isPlatformServer"))return "server";if(d.type==="UnaryExpression"&&d.operator==="!"&&d.argument){let h=s(d.argument);if(h?.type==="CallExpression"&&h.callee&&O(h.callee,"isPlatformServer"))return "browser"}if(d.type==="Identifier"&&f.has(d.name))return "browser";for(let h of C(d))m.push(h);}}return null})(p,i);if(c==="browser"){a.alternate&&u.push(a.alternate);continue}if(c==="server"){a.consequent&&u.push(a.consequent);continue}}}if(a.type==="CallExpression"&&a.callee){let p=s(a.callee);if(p&&(O(p,"afterNextRender")||O(p,"afterRender"))){let c=a.arguments??[];for(let n=1;n<c.length;n++)u.push(c[n]);continue}}if(x(a)){let p=(function(c){let n=c;for(;n&&x(n);)n=s(n.object);return n?.type==="Identifier"?n.name??null:null})(a);if(p&&fr.has(p)){let c=a;for(;c&&x(c);)c=s(c.object);let n=b(c);if(n!==void 0&&!l.has(n)){l.add(n);let{line:f,column:m}=e.locator.location(n);o.push({filePath:e.filePath,ruleName:"no-document-access",message:`Direct access to \`${p}\` can run during SSR where browser globals do not exist.`,line:f,column:m,severity:"error",fix:E["no-document-access"],codeExample:R["no-document-access"]});}}}for(let p of C(a))u.push(p);}}return o.length?o:null});var dr=new Set(["nativeElement","getBoundingClientRect","querySelector","querySelectorAll","getElementById","createElement","scrollIntoView","focus","blur","offsetWidth","offsetHeight","clientWidth","clientHeight","scrollTop","scrollLeft","innerHTML","outerHTML","textContent","parentElement","parentNode","firstChild","lastChild","nextSibling","previousSibling","children","ownerDocument","insertBefore","appendChild","removeChild","replaceChild","cloneNode","setAttribute","getAttribute","removeAttribute","hasAttribute","classList","dispatchEvent","contains","matches","closest","getClientRects","addEventListener","removeEventListener","requestAnimationFrame","cancelAnimationFrame"]),yr=["getElementsBy","offset","client","scroll"],it=createAnyAngularClassRule("prefer-after-render-over-after-view-init",(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[];for(let o of ["ngAfterViewInit","ngAfterContentInit"]){let l=r.find(c=>c.key?.name===o),u=l?L(l):null;if(!u||!l||!(function(c){let n=[c];for(;n.length;){let f=s(n.pop());if(f){if((f.type==="MemberExpression"||f.type==="StaticMemberExpression"||f.type==="OptionalMemberExpression")&&!f.computed){let m=f.property?.name??"";if(dr.has(m))return true;for(let d of yr)if(m.startsWith(d))return true}if(f.type==="Identifier"&&(f.name==="document"||f.name==="window"))return true;for(let m of C(f))n.push(m);}}return false})(u))continue;let{line:a,column:p}=e.locator.location(b(l));i.push({filePath:e.filePath,ruleName:"prefer-after-render-over-after-view-init",message:`\`${o}\` contains DOM access that can run before browser-only APIs are safe.`,line:a,column:p,severity:"warn",fix:E["prefer-after-render-over-after-view-init"],codeExample:R["prefer-after-render-over-after-view-init"]});}return i.length?i:null});var ae=new Map;function Me(t){return /ngOnDestroy\s*\([^)]*\)\s*\{[^}]*\.unsubscribe\s*\(\)/s.test(t)}var ot=createCallExpressionRule("rxjs-require-takeUntilDestroyed",(t,e)=>{var r,i;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t))return null;let l=s(t.callee),u=x(l)?l?.object:null;if(u&&Z(u)||J(Q(u))||(r=e.filePath,i=e.fileContent,(o=ae.get(r))!==void 0||(o=Me(i),ae.size>=500&&ae.clear(),ae.set(r,o)),o))return null;let a=b(t),{line:p,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:"rxjs-require-takeUntilDestroyed",message:"A component subscription without teardown can keep running after the component is destroyed.",line:p,column:c,severity:"error",fix:E["rxjs-require-takeUntilDestroyed"]}});var se=new Map,le="rxjs-no-subscribe-in-component",at=createCallExpressionRule(le,(t,e)=>{var r,i;let o;if(!e.filePath.endsWith(".component.ts")&&!e.filePath.endsWith(".directive.ts")&&!/\@(Component|Directive)\s*[\(\{]/.test(e.fileContent)||!Y(t)||(function(n){let f=s(n.callee);if(!f||!x(f))return false;let m=s(f.object);if(!m)return false;if(m.type==="CallExpression"){let d=s(m.callee);if(x(d)&&v(d)==="pipe"&&(Array.isArray(m.arguments)?m.arguments:[]).some(h=>{let y=s(h);if(y?.type!=="CallExpression")return false;let g=s(y.callee)?.name;return g==="take"||g==="first"}))return true}return J(Q(m))})(t))return null;let l=s(t.callee),u=s(l?.object);if(u&&Z(u)||(r=e.filePath,i=e.fileContent,(o=se.get(r))!==void 0||(o=Me(i),se.size>=500&&se.clear(),se.set(r,o)),o))return null;let a=b(t),{line:p,column:c}=e.locator.location(a);return {filePath:e.filePath,ruleName:le,message:(function(n,f){let m="Open-ended subscriptions in components can outlive the component and make state harder to track.",d=f.crossRef?.templateReferences;if(!d)return m;let h=s(n.callee),y=s(h?.object),g=y?v(y):null;if(!g)return m;let S=g.endsWith("$")?g.slice(0,-1):g;return d.has(g)||d.has(S)?`'${g}' is read by the template, so subscribing manually adds state and teardown work the template can own.`:m})(t,e),line:p,column:c,severity:"error",fix:E[le],codeExample:R[le]}},{requires:{projectContext:true}});var ue="rxjs-avoid-subject-as-event-bus",st=new Set(["Subject","ReplaySubject","AsyncSubject","BehaviorSubject"]),xr=new Set(["destroy$","destroyed$","ondestroy$","ngondestroy$","unsubscribe$","unsub$","teardown$","dispose$","cleanup$","cleanupsubject$"]),br=/state|loading|error|active|selected|open|visible|disabled|count|value|data|hidden|expanded|pending|success|failed/i;function H(t,e,r){let i=[t];for(;i.length;){let o=s(i.pop());if(!o)continue;let l=s(o.callee);if(o.type==="CallExpression"&&v(l)===e){let u=s(l?.object);if(u&&x(u)&&s(u.object)?.type==="ThisExpression"){let a=v(u);a&&r.add(a);}}for(let u of C(o))i.push(u);}}var lt=createAnyAngularClassRule(ue,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node);if(r.length===0)return null;let i=(function(a){let p=Be(a.sourceText,st),c=new Map;for(let[n,f]of p)for(let m of f)c.set(m,n);return c})(e),o=(function(a){let p=new Set,c=U(a);if(c){let n=L(c);n&&H(n,"next",p);}for(let n of a)if(B(n)){n.kind==="set"&&(function(m){let d=m.decorators;if(!Array.isArray(d))return false;for(let h of d){let y=s(h.expression);if(y?.name==="Input"||s(y?.callee)?.name==="Input")return true}return false})(n)&&H(n,"next",p);let f=n.key?.name;if(f==="ngOnChanges"){let m=L(n);m&&H(m,"next",p);}if(f==="ngOnDestroy"){let m=L(n);m&&H(m,"complete",p);}}else n.type==="PropertyDefinition"&&n.value&&H(n.value,"next",p);return p})(r),l=(function(a){let p=new Set;for(let c of a){let n=B(c)?L(c):c.type==="PropertyDefinition"?c.value:null;n&&H(n,"pipe",p);}return p})(r),u=[];for(let a of r){if(a.type!=="PropertyDefinition"||a.accessibility==="public")continue;let p=s(a.value??a.initializer);if(!p||p.type!=="NewExpression")continue;let c=(function(d,h){let y=s(d);if(!y)return null;if(y.type==="Identifier")return h.get(y.name)??null;if(x(y)){let g=v(y);return g&&st.has(g)?g:null}return null})(p.callee,i),n=a.key?.name??"";if(!c||!n||xr.has(n.toLowerCase())||o.has(n)||l.has(n))continue;let{line:f,column:m}=e.locator.location(b(a));u.push({filePath:e.filePath,ruleName:ue,message:br.test(n)?`${c} '${n}' is used for component UI state, which adds stream overhead to local state updates.`:`${c} '${n}' is acting as a local event bus, which makes component interactions harder to trace.`,line:f,column:m,severity:"warn",fix:E[ue],codeExample:R[ue]});}return u.length?u:null});var Pe="rxjs-prefer-toSignal-for-template-state",ut=new Set(["Observable","Subject","BehaviorSubject","ReplaySubject","AsyncSubject"]),vr=new Set(["destroy$","destroyed$","unsub$","teardown$","dispose$"]),ct=createAnyAngularClassRule(Pe,(t,e)=>{if(t.metadata?.type!=="Component")return null;let i=e.crossRef?.templateReferences;if(i===void 0)return null;let o=w(t.node),l=[];for(let u of o){if(u.type!=="PropertyDefinition")continue;let a=u.key?.name??"";if(!a||!a.endsWith("$")||vr.has(a.toLowerCase())||(function(f){let m=f.modifiers,d=f.decorators??(Array.isArray(m)?m.filter(h=>h.type==="Decorator"):void 0);return Array.isArray(d)&&d.some(h=>{let y=s(h.expression);return (y?.type==="CallExpression"?j(y):y?.type==="Identifier"?y.name:null)==="Output"})})(u))continue;let p=a.slice(0,-1);if(!i.has(a)&&!i.has(p)||!(function(f){if(ut.has((function(y){let g=y.typeAnnotation,S=s(g?.typeAnnotation);if(!S||S.type!=="TSTypeReference"&&S.type!=="TypeReference")return "";let A=S.typeName??S.name;if(typeof A=="string")return A;if(A&&typeof A=="object"){if(A.type==="Identifier")return A.name??"";if(A.type==="TSQualifiedName")return s(A.right)?.name??""}return ""})(f)))return true;let m=s(f.value??f.initializer);if(!m)return false;let d=j(m);if(d==="toSignal"||d==="signal"||d==="computed")return false;if(m.type==="NewExpression"){let y=s(m.callee),g=y?.type==="Identifier"?y.name:v(y);return !!g&&ut.has(g)}let h=[m];for(;h.length>0;){let y=s(h.pop());if(y){if(y.type==="CallExpression"&&j(y)==="pipe")return true;for(let g of C(y))h.push(g);}}return false})(u))continue;let{line:c,column:n}=e.locator.location(b(u));l.push({filePath:e.filePath,ruleName:Pe,message:`Observable "${a}" is read by the template, which can add async-pipe churn and weaker signal integration.`,line:c,column:n,severity:"warn",fix:E[Pe]});}return l.length?l:null},{requires:{projectContext:true,htmlAst:true}});var Oe="toSignal-require-initialValue",pt=createCallExpressionRule(Oe,(t,e)=>{if(!O(t.callee,"toSignal"))return null;let r=Array.isArray(t.arguments)?t.arguments:[],i=r[1]?s(r[1]):null;if(!i||i.type!=="ObjectExpression"||!(function(o){let l=W(o,"initialValue");if(l&&!xe(l.value))return true;let u=W(o,"requireSync");return !!u&&Ee(u.value)})(i)){let{line:o,column:l}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:Oe,message:"toSignal() can emit undefined before the observable produces a value.",line:o,column:l,severity:"warn",fix:E[Oe]}}return null});var Cr=new Set(["set","update","mutate"]),Rr=new Set(["setTimeout","setInterval","queueMicrotask","requestAnimationFrame","then","catch","finally","subscribe"]),ft=createCallExpressionRule("signal-prefer-computed-over-sync-effect",(t,e)=>{if(!O(t.callee,"effect"))return null;let r=G(t),i=r?K(r):null;if(!i)return null;let{hasRead:o,hasWrite:l,hasAsync:u,hasLinked:a,firstWrite:p}=(function(f,m){let d={hasRead:false,hasWrite:false,hasAsync:false,hasLinked:false,firstWrite:null},h=[f];for(;h.length;){let y=s(h.pop());if(y){if((y.type==="AwaitExpression"||y.type==="YieldExpression")&&(d.hasAsync=true),y.type==="CallExpression"){let g=j(y);g&&Rr.has(g)&&(d.hasAsync=true),g==="linkedSignal"&&(d.hasLinked=true),(function(S){let A=s(S);if(!A||A.type!=="CallExpression")return false;let M=s(A.callee);return x(M)&&Cr.has(v(M)||"")})(y)?(d.hasWrite=true,d.firstWrite||(d.firstWrite=y)):(function(S,A,M){let P=s(S);if(!P||P.type!=="CallExpression"||Array.isArray(P.arguments)&&P.arguments.length>0)return false;let I=s(P.callee);if(!I)return false;if(A.typeChecker)try{let T=q(I,A);if(T){let D=A.typeChecker.getTypeOfSymbolAtLocation(T,T.valueDeclaration);if(D&&A.typeChecker.typeToString(D).includes("Signal"))return !0}}catch{}return x(I)?s(I.object)?.type==="ThisExpression":M&&I.type==="Identifier"})(y,m,true)&&(d.hasRead=true);}for(let g of C(y))h.push(g);}}return d})(i,e);if(!l||!o||u||a)return null;let{line:c,column:n}=e.locator.location(b(p||t));return {filePath:e.filePath,ruleName:"signal-prefer-computed-over-sync-effect",message:"This effect reads reactive values and writes derived state, which adds extra reactive cycles.",line:c,column:n,severity:"warn",fix:E["signal-prefer-computed-over-sync-effect"]}},{requires:{typeChecker:true}});var mt=new Set(["afterRender","afterNextRender"]),Mr=/\bafterNextRender\s*\(|\bafterRender\s*\(/,ce=new Map,dt=createCallExpressionRule("signal-avoid-untracked-overuse",(t,e)=>{if(!O(t.callee,"untracked")||(function(o,l){let u=l.sourceText??l.fileContent;if(typeof u=="string"&&!Mr.test(u))return false;let a=o.parent;for(;a;){if(a.type==="CallExpression"&&mt.has(j(a)))return true;a=a.parent;}let p=b(o);return (function(c){let n=ce.get(c.filePath);if(n!==void 0)return n;let f=c.program;return n=f?(function(m){let d=[],h=m.body,y=Array.isArray(h)?[...h]:[m];for(;y.length;){let g=s(y.pop());if(g){if(g.type==="CallExpression"&&mt.has(j(g))){let S=s(g.arguments?.[0]);if(S){let A=b(S),M=S.end??S.span?.end??b(S);M>A&&d.push([A,M]);}}for(let S of C(g))y.push(S);}}return d})(f):[],ce.size>=300&&ce.clear(),ce.set(c.filePath,n),n})(l).some(([c,n])=>p>=c&&p<n)})(t,e))return null;let{line:r,column:i}=e.locator.location(b(t));return {filePath:e.filePath,ruleName:"signal-avoid-untracked-overuse",message:"untracked() hides this read from dependency tracking, which can mask stale reactive state.",line:r,column:i,severity:"warn",fix:E["signal-avoid-untracked-overuse"]}});var pe="prefer-inject-over-constructor-di",Or=new Set(["http","router","route","cdr","cdref","changedetectorref","injector","ngzone","zone","renderer","renderer2","elementref","el","document","platform","location","dialog","snack","toast","store","facade","logger","translate","i18n","auth","api","client","matdialog","overlay","breakpointobserver","snackbar","matsnackbar","bottomsheet","matbottomsheet","clipboard","directionality","focusmonitor","mediamatcher","viewportruler","scrolldispatcher","dragdrop","liveannouncer","activatedroute","fb","firestore","angularfire","formbuilder","titleservice","metaservice","title","meta","sanitizer","domsanitizer","compiler","applicationref","componentfactoryresolver","viewcontainerref","templateref","destroyref"]),Tr=new Set(["data","config","options","opts","params","payload","input","value","values","items","item","context","ctx","model","vm","state","initialstate","result","name","id","label","text","title","message","url","path","index","count","size","length","width","height","color","type","key","mode","flag","enabled","disabled","visible","hidden"]),Ir=["Service","Facade","Store","Client","Repository","Adapter","Manager","Controller","Provider","Registry","Logger","Router","ActivatedRoute","ChangeDetectorRef","DestroyRef","Injector","NgZone","Renderer2","ElementRef","HttpClient","ViewContainerRef","TemplateRef","ComponentFactoryResolver","ApplicationRef","MatDialog","MatDialogRef","MatSnackBar","MatBottomSheet","Overlay","OverlayRef","BreakpointObserver","Clipboard","FocusMonitor","MediaMatcher","ScrollDispatcher","DragDrop","LiveAnnouncer","Directionality","ViewportRuler","FormBuilder","DomSanitizer","Title","Meta","Dispatcher","Gateway","Handler","Interceptor","Guard","Resolver","Factory","Strategy","Validator"],kr=new Set(["string","number","boolean","symbol","bigint","any","unknown","void"]),yt=createAnyAngularClassRule(pe,(t,e)=>{let r=U(w(t.node));if(!r)return null;let i=ee(r.value??r).filter(a=>(function(p,c){let n=s(p);if(!n)return false;if(Array.isArray(n.decorators)&&n.decorators.length>0||n.accessibility||n.readonly)return true;if(c.typeChecker){let d=q(p,c);if(d&&Fe(d))return true}let f=(F(p)||"").toLowerCase().trim();if(!f||Tr.has(f))return false;if(Or.has(f))return true;let m=($(p)||"").trim();return !(!m||kr.has(m.toLowerCase()))&&Ir.some(d=>m.endsWith(d))})(a,e));if(i.length===0)return null;let{line:o,column:l}=e.locator.location(b(r)),u=i.map(a=>`${F(a)}: ${$(a)}`).join(", ");return {filePath:e.filePath,ruleName:pe,message:`Constructor dependency injection makes class setup less composable than inject().${u?` Offending params: ${u}.`:""}`,line:o,column:l,severity:"warn",fix:E[pe],codeExample:R[pe]}},{requires:{typeChecker:true}});var fe="signal-prefer-input-signal";function jr(t){let e=s(t.expression??t);if(!e)return false;if(e.type==="Identifier")return e.name==="Input";if(e.type==="CallExpression"){let r=s(e.callee);return r?.type==="Identifier"&&r.name==="Input"}return false}var ht=createAnyAngularClassRule(fe,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[],o=e.project?.standaloneComponents?.has(e.filePath)??false;for(let l of r){let u=s(l);if(u&&(u.type==="PropertyDefinition"||u.type==="AccessorProperty")&&Array.isArray(u.decorators)&&u.decorators.some(jr)){let a=b(u),{line:p,column:c}=e.locator.location(a),n=s(u.key),f=(n?.type==="Identifier"?n.name:n?.type==="Literal"?String(n.value):"")||"(unknown)",m=`'${f}' uses @Input(), which keeps this input outside Angular's signal graph.`;o&&(m+=" Standalone declarations benefit most from signal inputs."),i.push({filePath:e.filePath,ruleName:fe,message:m,line:p,column:c,severity:o?"error":"warn",fix:E[fe],codeExample:R[fe]});}}return i.length>0?i:null},{requires:{projectContext:true}});var me="signal-prefer-output-function",gt=createAnyAngularClassRule(me,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=[];for(let o of r){let l=s(o);if(l&&(l.type==="PropertyDefinition"||l.type==="AccessorProperty")&&Array.isArray(l.decorators)&&l.decorators.some(u=>{let a=s(u.expression??u);if(!a)return false;if(a.type==="Identifier")return a.name==="Output";if(a.type==="CallExpression"){let p=s(a.callee);return p?.type==="Identifier"&&p.name==="Output"}return false})&&(function(u,a){let p=s(u.value);if(p?.type==="NewExpression"){let n=s(p.callee);if(n?.type==="Identifier"&&n.name==="EventEmitter")return true}let c=s(u.typeAnnotation);if(c&&$(c).includes("EventEmitter"))return true;if(a.typeChecker){let n=q(u,a);if(n&&(typeof n.getName=="function"?n.getName():"").includes("EventEmitter"))return true}return false})(l,e)){let u=b(l),{line:a,column:p}=e.locator.location(u),c=s(l.key),n=(c?.type==="Identifier"?c.name:c?.type==="Literal"?String(c.value):"")||"(unknown)";i.push({filePath:e.filePath,ruleName:me,message:`'${n}' uses @Output() EventEmitter, which adds boilerplate compared with output().`,line:a,column:p,severity:"warn",fix:E[me],codeExample:R[me]});}}return i.length>0?i:null},{requires:{typeChecker:true}});var de="signal-prefer-model";function Et(t,e){return Array.isArray(t.decorators)&&t.decorators.some(r=>{let i=s(r.expression??r);if(!i)return false;if(i.type==="Identifier")return i.name===e;if(i.type==="CallExpression"){let o=s(i.callee);return o?.type==="Identifier"&&o.name===e}return false})}function xt(t,e){let r=s(t.value);if(!r||r.type!=="CallExpression")return false;let i=s(r.callee);if(!i)return false;if(i.type==="Identifier")return i.name===e;if(x(i)){let o=s(i.object);return o?.type==="Identifier"&&o.name===e}return false}var bt=createAnyAngularClassRule(de,(t,e)=>{if(t.decoratorName!=="Component"&&t.decoratorName!=="Directive")return null;let r=w(t.node),i=new Map,o=new Map;for(let u of r){let a=s(u);if(!a||a.type!=="PropertyDefinition"&&a.type!=="AccessorProperty")continue;let p=(function(c){let n=s(c.key);return n?n.type==="Identifier"?n.name??null:n.type==="Literal"?String(n.value):null:null})(a);p&&((Et(a,"Input")||xt(a,"input"))&&i.set(p,a),(Et(a,"Output")||xt(a,"output"))&&o.set(p,a));}let l=[];for(let[u,a]of o){if(!u.endsWith("Change"))continue;let p=u.slice(0,-6),c=i.get(p);if(c){let n=b(c),{line:f,column:m}=e.locator.location(n);l.push({filePath:e.filePath,ruleName:de,message:`The \`${p}\` / \`${u}\` pair implements two-way binding with extra wiring that model() avoids.`,line:f,column:m,severity:"warn",fix:E[de],codeExample:R[de]});}}return l.length>0?l:null});var Br=new Map([["*ngIf","@if"],["*ngFor","@for"],["*ngSwitch","@switch"],["[ngSwitch]","@switch"],["*ngSwitchCase","@case"],["*ngSwitchDefault","@default"]]),Te="template-prefer-control-flow",St=createTemplateAttributeRule(Te,(t,e)=>{var r;let i=(r=t.name,Br.get(r)??null);if(!i)return null;let o=k(e,t.sourceSpan.start),{line:l,column:u}=e.locator.location(o);return {filePath:e.filePath,ruleName:Te,message:`\`${t.name}\` uses legacy structural directive syntax, so it misses the \`${i}\` control flow benefits.`,line:l,column:u,severity:"error",fix:E[Te]}},{requires:{htmlAst:true}});var vt=new WeakMap,At=createTemplateExpressionRule("template-no-async-pipe-duplication",(t,e)=>{let r,i,o=(function c(n){let f=s(n);if(!f)return null;if(f.type==="BinaryExpression"&&f.operator==="|"){let m=s(f.right);return m?.type==="Identifier"&&m.name==="async"?s(f.left):c(f.left)}return null})(t.expression),l=o?(function c(n,f=0){if(!n||f>10)return null;if(n.type==="Identifier")return n.name;if(n.type==="ThisExpression")return "this";if(n.type==="Literal"){let m=n.value;return m===null?"null":typeof m=="string"||typeof m=="number"||typeof m=="boolean"||typeof m=="bigint"?String(m):null}if(n.type==="CallExpression"){let m=c(n.callee,f+1),d=(Array.isArray(n.arguments)?n.arguments:[]).map(h=>c(h,f+1)??"?");return `${m}(${d.join(",")})`}if(x(n)){let m=c(n.object,f+1),d=v(n);if(m&&d)return `${m}.${d}`}if(n.type==="UnaryExpression")return `${n.operator}${c(n.argument,f+1)}`;if(n.type==="ConditionalExpression")return `${c(n.test,f+1)}?${c(n.consequent,f+1)}:${c(n.alternate,f+1)}`;if(n.type==="OptionalExpression"||n.type==="ChainExpression")return c(n.expression,f+1);if(n.type==="LogicalExpression"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}if(n.type==="BinaryExpression"&&n.operator!=="|"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}if(n.type==="ArrayExpression")return `[${(n.elements??[]).map(d=>c(d,f+1)??"?").join(",")}]`;if(n.type==="ObjectExpression")return `{${(n.properties??[]).map(d=>{let h=d.key?c(d.key,f+1):"?",y=d.value?c(d.value,f+1):"?";return `${h}:${y}`}).join(",")}}`;if(n.type==="TemplateLiteral")return "`tmpl`";if(n.type==="AssignmentExpression"){let m=c(n.left,f+1),d=c(n.right,f+1);if(m&&d)return `${m}${n.operator}${d}`}return null})(o):null;if(!l)return null;let u=(r=e.template,i=r?.templateStartOffset,`${e.filePath}@${typeof i=="number"&&Number.isFinite(i)?i:0}`),a=vt.get(e);a||(a=new Map,vt.set(e,a));let p=a.get(u);if(p||(p=new Set,a.set(u,p)),p.has(l)){let c=k(e,t.sourceSpan.start),{line:n,column:f}=e.locator.location(c);return {filePath:e.filePath,ruleName:"template-no-async-pipe-duplication",message:`Duplicate async pipe subscriptions for "${l}" can create repeated work and inconsistent loading states.`,line:n,column:f,severity:"warn",fix:E["template-no-async-pipe-duplication"]}}return p.add(l),null},{requires:{htmlAst:true}});var qr=new Set(["fdescribe","fit","describe.only","it.only","test.only","context.only","xdescribe","xit","xtest","xcontext"]),Hr=new Set(["xdescribe","xit","xtest","xcontext"]);function Nt(t){return t.type==="Identifier"?t.name??null:null}var Ct=createCallExpressionRule("spec-no-focused-test",(t,e)=>{var r;let i;if(!((r=e.filePath).endsWith(".spec.ts")||r.endsWith(".test.ts")))return null;let o=s(t.callee);if(!o)return null;let l=(i=Nt(o)||(function(n){if(n.type==="MemberExpression"||n.type==="StaticMemberExpression"||n.type==="OptionalMemberExpression"){let f=s(n.object),m=n.property?.name??"",d=(f?.type==="Identifier"?f.name:"")??"";return d?`${d}.${m}`:null}return null})(o))&&qr.has(i)?i:null;if(!l){if(Nt(o)==="pending"){let n=b(t),{line:f,column:m}=e.locator.location(n);return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:"`pending()` disables the test body, so the committed suite can miss coverage.",line:f,column:m,severity:"error",fix:E["spec-no-focused-test"]}}return null}let u=b(t),{line:a,column:p}=e.locator.location(u),c=Hr.has(l)?`\`${l}\` disables a test that may be forgotten.`:`\`${l}\` is a focused test helper that can skip the rest of the suite in CI.`;return {filePath:e.filePath,ruleName:"spec-no-focused-test",message:c,line:a,column:p,severity:"error",fix:E["spec-no-focused-test"]}},{dependencyType:"spec",requires:{tsAst:true}});function Rt(){N(He,"correctness"),N(ze,"correctness"),N(We,"correctness"),N(Xe,"correctness"),N(Ye,"performance"),N(Ke,"performance"),N(Qe,"performance"),N(Je,"performance"),N(et,"performance"),N(tt,"security"),N(rt,"security"),N(nt,"ssr"),N(it,"ssr"),N(at,"reactivity"),N(ot,"reactivity"),N(lt,"reactivity"),N(ct,"reactivity"),N(pt,"reactivity"),N(ft,"reactivity"),N(dt,"reactivity"),N(yt,"modern-api"),N(ht,"modern-api"),N(gt,"modern-api"),N(bt,"modern-api"),N(St,"template"),N(At,"template"),N(Ct,"testing");}(async()=>{if(Rt(),configureRuleExecutor(De,ke),!parentPort)return;let{rootDir:t,tasks:e}=workerData,r=[],i=[],o=createAnalysisContext(t),l=new Map;for(let u of e){let a=l.get(u.filePath)??[];a.push(u),l.set(u.filePath,a);}for(let[u,a]of l){let p=performance.now();try{let c=await executeBatchedTasks(a,o);r.push(...c),parentPort.postMessage(wt(u,a.length,c,performance.now()-p));}catch(c){for(let n of a)i.push({task:n,error:c instanceof Error?c.message:String(c)});parentPort.postMessage(wt(u,a.length,[],performance.now()-p));}finally{o.evict(u);}}parentPort.postMessage({results:r,errors:i});})();var wt=(t,e,r,i)=>{let o=0,l=0;for(let u of r)for(let a of u.failures)a.severity==="error"?o++:a.severity==="warn"&&l++;return {kind:"file-progress",filePath:t,taskCount:e,typeAware:false,issueCount:o+l,errorCount:o,warningCount:l,duration:i}};//# sourceMappingURL=execution-worker.js.map
217
217
  //# sourceMappingURL=execution-worker.js.map