srcly 0.1.26__tar.gz → 0.1.27__tar.gz

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.
Files changed (316) hide show
  1. {srcly-0.1.26 → srcly-0.1.27}/PKG-INFO +1 -1
  2. {srcly-0.1.26 → srcly-0.1.27}/app/services/focus_overlay.py +8 -1
  3. srcly-0.1.27/app/services/python/python_analysis.py +313 -0
  4. srcly-0.1.27/app/services/typescript/typescript_analysis.py +948 -0
  5. srcly-0.1.27/app/static/assets/index-BD7BxeQJ.js +66 -0
  6. srcly-0.1.27/app/static/assets/index-BDq2TMkJ.css +1 -0
  7. {srcly-0.1.26 → srcly-0.1.27}/app/static/index.html +2 -2
  8. {srcly-0.1.26 → srcly-0.1.27}/pyproject.toml +1 -1
  9. srcly-0.1.26/app/services/python/python_analysis.py +0 -317
  10. srcly-0.1.26/app/services/typescript/typescript_analysis.py +0 -1353
  11. srcly-0.1.26/app/static/assets/index-BeWzlQnV.css +0 -1
  12. srcly-0.1.26/app/static/assets/index-TkRIdY4e.js +0 -66
  13. {srcly-0.1.26 → srcly-0.1.27}/.gitignore +0 -0
  14. {srcly-0.1.26 → srcly-0.1.27}/README.md +0 -0
  15. {srcly-0.1.26 → srcly-0.1.27}/app/.gitignore +0 -0
  16. {srcly-0.1.26 → srcly-0.1.27}/app/__init__.py +0 -0
  17. {srcly-0.1.26 → srcly-0.1.27}/app/config.py +0 -0
  18. {srcly-0.1.26 → srcly-0.1.27}/app/main.py +0 -0
  19. {srcly-0.1.26 → srcly-0.1.27}/app/models.py +0 -0
  20. {srcly-0.1.26 → srcly-0.1.27}/app/routers/analysis.py +0 -0
  21. {srcly-0.1.26 → srcly-0.1.27}/app/routers/files.py +0 -0
  22. {srcly-0.1.26 → srcly-0.1.27}/app/run.py +0 -0
  23. {srcly-0.1.26 → srcly-0.1.27}/app/services/analysis.py +0 -0
  24. {srcly-0.1.26 → srcly-0.1.27}/app/services/analysis_types.py +0 -0
  25. {srcly-0.1.26 → srcly-0.1.27}/app/services/cache.py +0 -0
  26. {srcly-0.1.26 → srcly-0.1.27}/app/services/css/css_analysis.py +0 -0
  27. {srcly-0.1.26 → srcly-0.1.27}/app/services/data_flow_analysis.py +0 -0
  28. {srcly-0.1.26 → srcly-0.1.27}/app/services/ipynb/ipynb_analysis.py +0 -0
  29. {srcly-0.1.26 → srcly-0.1.27}/app/services/markdown/markdown_analysis.py +0 -0
  30. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/abap-BdImnpbu.js +0 -0
  31. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/actionscript-3-CfeIJUat.js +0 -0
  32. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ada-bCR0ucgS.js +0 -0
  33. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/andromeeda-C-Jbm3Hp.js +0 -0
  34. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/angular-html-CU67Zn6k.js +0 -0
  35. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/angular-ts-BwZT4LLn.js +0 -0
  36. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/apache-Pmp26Uib.js +0 -0
  37. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/apex-DhZLUxFE.js +0 -0
  38. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/apl-dKokRX4l.js +0 -0
  39. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/applescript-Co6uUVPk.js +0 -0
  40. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ara-BRHolxvo.js +0 -0
  41. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/asciidoc-Dv7Oe6Be.js +0 -0
  42. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/asm-D_Q5rh1f.js +0 -0
  43. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/astro-CbQHKStN.js +0 -0
  44. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/aurora-x-D-2ljcwZ.js +0 -0
  45. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/awk-DMzUqQB5.js +0 -0
  46. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ayu-dark-Cv9koXgw.js +0 -0
  47. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ballerina-BFfxhgS-.js +0 -0
  48. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/bat-BkioyH1T.js +0 -0
  49. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/beancount-k_qm7-4y.js +0 -0
  50. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/berry-D08WgyRC.js +0 -0
  51. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/bibtex-CHM0blh-.js +0 -0
  52. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/bicep-Bmn6On1c.js +0 -0
  53. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/blade-DVc8C-J4.js +0 -0
  54. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/bsl-BO_Y6i37.js +0 -0
  55. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/c-BIGW1oBm.js +0 -0
  56. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/cadence-Bv_4Rxtq.js +0 -0
  57. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/cairo-KRGpt6FW.js +0 -0
  58. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/catppuccin-frappe-DFWUc33u.js +0 -0
  59. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/catppuccin-latte-C9dUb6Cb.js +0 -0
  60. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/catppuccin-macchiato-DQyhUUbL.js +0 -0
  61. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/catppuccin-mocha-D87Tk5Gz.js +0 -0
  62. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/clarity-D53aC0YG.js +0 -0
  63. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/clojure-P80f7IUj.js +0 -0
  64. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/cmake-D1j8_8rp.js +0 -0
  65. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/cobol-nwyudZeR.js +0 -0
  66. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/codeowners-Bp6g37R7.js +0 -0
  67. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/codeql-DsOJ9woJ.js +0 -0
  68. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/coffee-Ch7k5sss.js +0 -0
  69. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/common-lisp-Cg-RD9OK.js +0 -0
  70. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/coq-DkFqJrB1.js +0 -0
  71. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/cpp-CofmeUqb.js +0 -0
  72. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/crystal-tKQVLTB8.js +0 -0
  73. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/csharp-CX12Zw3r.js +0 -0
  74. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/css-DPfMkruS.js +0 -0
  75. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/csv-fuZLfV_i.js +0 -0
  76. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/cue-D82EKSYY.js +0 -0
  77. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/cypher-COkxafJQ.js +0 -0
  78. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/d-85-TOEBH.js +0 -0
  79. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/dark-plus-eOWES_5F.js +0 -0
  80. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/dart-CF10PKvl.js +0 -0
  81. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/dax-CEL-wOlO.js +0 -0
  82. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/desktop-BmXAJ9_W.js +0 -0
  83. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/diff-D97Zzqfu.js +0 -0
  84. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/docker-BcOcwvcX.js +0 -0
  85. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/dotenv-Da5cRb03.js +0 -0
  86. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/dracula-BzJJZx-M.js +0 -0
  87. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/dracula-soft-BXkSAIEj.js +0 -0
  88. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/dream-maker-BtqSS_iP.js +0 -0
  89. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/edge-BkV0erSs.js +0 -0
  90. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/elixir-CDX3lj18.js +0 -0
  91. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/elm-DbKCFpqz.js +0 -0
  92. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/emacs-lisp-C9XAeP06.js +0 -0
  93. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/erb-BOJIQeun.js +0 -0
  94. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/erlang-DsQrWhSR.js +0 -0
  95. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/everforest-dark-BgDCqdQA.js +0 -0
  96. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/everforest-light-C8M2exoo.js +0 -0
  97. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/fennel-BYunw83y.js +0 -0
  98. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/fish-BvzEVeQv.js +0 -0
  99. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/fluent-C4IJs8-o.js +0 -0
  100. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/fortran-fixed-form-BZjJHVRy.js +0 -0
  101. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/fortran-free-form-D22FLkUw.js +0 -0
  102. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/fsharp-CXgrBDvD.js +0 -0
  103. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gdresource-B7Tvp0Sc.js +0 -0
  104. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gdscript-DTMYz4Jt.js +0 -0
  105. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gdshader-DkwncUOv.js +0 -0
  106. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/genie-D0YGMca9.js +0 -0
  107. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gherkin-DyxjwDmM.js +0 -0
  108. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/git-commit-F4YmCXRG.js +0 -0
  109. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/git-rebase-r7XF79zn.js +0 -0
  110. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/github-dark-DHJKELXO.js +0 -0
  111. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/github-dark-default-Cuk6v7N8.js +0 -0
  112. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/github-dark-dimmed-DH5Ifo-i.js +0 -0
  113. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -0
  114. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/github-light-DAi9KRSo.js +0 -0
  115. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/github-light-default-D7oLnXFd.js +0 -0
  116. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/github-light-high-contrast-BfjtVDDH.js +0 -0
  117. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gleam-BspZqrRM.js +0 -0
  118. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/glimmer-js-Rg0-pVw9.js +0 -0
  119. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/glimmer-ts-U6CK756n.js +0 -0
  120. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/glsl-DplSGwfg.js +0 -0
  121. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gnuplot-DdkO51Og.js +0 -0
  122. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/go-Dn2_MT6a.js +0 -0
  123. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/graphql-ChdNCCLP.js +0 -0
  124. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/groovy-gcz8RCvz.js +0 -0
  125. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gruvbox-dark-hard-CFHQjOhq.js +0 -0
  126. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gruvbox-dark-medium-GsRaNv29.js +0 -0
  127. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gruvbox-dark-soft-CVdnzihN.js +0 -0
  128. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gruvbox-light-hard-CH1njM8p.js +0 -0
  129. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gruvbox-light-medium-DRw_LuNl.js +0 -0
  130. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/gruvbox-light-soft-hJgmCMqR.js +0 -0
  131. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/hack-CaT9iCJl.js +0 -0
  132. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/haml-B8DHNrY2.js +0 -0
  133. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/handlebars-BL8al0AC.js +0 -0
  134. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/haskell-Df6bDoY_.js +0 -0
  135. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/haxe-CzTSHFRz.js +0 -0
  136. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/hcl-BWvSN4gD.js +0 -0
  137. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/hjson-D5-asLiD.js +0 -0
  138. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/hlsl-D3lLCCz7.js +0 -0
  139. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/houston-DnULxvSX.js +0 -0
  140. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/html-GMplVEZG.js +0 -0
  141. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/html-derivative-BFtXZ54Q.js +0 -0
  142. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/http-jrhK8wxY.js +0 -0
  143. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/hurl-irOxFIW8.js +0 -0
  144. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/hxml-Bvhsp5Yf.js +0 -0
  145. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/hy-DFXneXwc.js +0 -0
  146. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/imba-DGztddWO.js +0 -0
  147. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ini-BEwlwnbL.js +0 -0
  148. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/java-CylS5w8V.js +0 -0
  149. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/javascript-wDzz0qaB.js +0 -0
  150. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/jinja-4LBKfQ-Z.js +0 -0
  151. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/jison-wvAkD_A8.js +0 -0
  152. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/json-Cp-IABpG.js +0 -0
  153. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/json5-C9tS-k6U.js +0 -0
  154. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/jsonc-Des-eS-w.js +0 -0
  155. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/jsonl-DcaNXYhu.js +0 -0
  156. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/jsonnet-DFQXde-d.js +0 -0
  157. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/jssm-C2t-YnRu.js +0 -0
  158. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/jsx-g9-lgVsj.js +0 -0
  159. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/julia-C8NyazO9.js +0 -0
  160. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/kanagawa-dragon-CkXjmgJE.js +0 -0
  161. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/kanagawa-lotus-CfQXZHmo.js +0 -0
  162. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/kanagawa-wave-DWedfzmr.js +0 -0
  163. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/kdl-DV7GczEv.js +0 -0
  164. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/kotlin-BdnUsdx6.js +0 -0
  165. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/kusto-BvAqAH-y.js +0 -0
  166. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/laserwave-DUszq2jm.js +0 -0
  167. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/latex-BUKiar2Z.js +0 -0
  168. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/lean-DP1Csr6i.js +0 -0
  169. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/less-B1dDrJ26.js +0 -0
  170. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/light-plus-B7mTdjB0.js +0 -0
  171. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/liquid-DYVedYrR.js +0 -0
  172. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/llvm-BtvRca6l.js +0 -0
  173. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/log-2UxHyX5q.js +0 -0
  174. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/logo-BtOb2qkB.js +0 -0
  175. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/lua-BbnMAYS6.js +0 -0
  176. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/luau-CXu1NL6O.js +0 -0
  177. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/make-CHLpvVh8.js +0 -0
  178. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/markdown-Cvjx9yec.js +0 -0
  179. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/marko-CPi9NSCl.js +0 -0
  180. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/material-theme-D5KoaKCx.js +0 -0
  181. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/material-theme-darker-BfHTSMKl.js +0 -0
  182. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/material-theme-lighter-B0m2ddpp.js +0 -0
  183. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/material-theme-ocean-CyktbL80.js +0 -0
  184. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/material-theme-palenight-Csfq5Kiy.js +0 -0
  185. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/matlab-D7o27uSR.js +0 -0
  186. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/mdc-DUICxH0z.js +0 -0
  187. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/mdx-Cmh6b_Ma.js +0 -0
  188. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/mermaid-DKYwYmdq.js +0 -0
  189. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/min-dark-CafNBF8u.js +0 -0
  190. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/min-light-CTRr51gU.js +0 -0
  191. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/mipsasm-CKIfxQSi.js +0 -0
  192. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/mojo-1DNp92w6.js +0 -0
  193. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/monokai-D4h5O-jR.js +0 -0
  194. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/move-Bu9oaDYs.js +0 -0
  195. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/narrat-DRg8JJMk.js +0 -0
  196. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/nextflow-CUEJCptM.js +0 -0
  197. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/nginx-DknmC5AR.js +0 -0
  198. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/night-owl-C39BiMTA.js +0 -0
  199. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/nim-CVrawwO9.js +0 -0
  200. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/nix-BbRYJGeE.js +0 -0
  201. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/nord-Ddv68eIx.js +0 -0
  202. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/nushell-C-sUppwS.js +0 -0
  203. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/objective-c-DXmwc3jG.js +0 -0
  204. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/objective-cpp-CLxacb5B.js +0 -0
  205. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ocaml-C0hk2d4L.js +0 -0
  206. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/one-dark-pro-DVMEJ2y_.js +0 -0
  207. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/one-light-PoHY5YXO.js +0 -0
  208. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/pascal-D93ZcfNL.js +0 -0
  209. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/perl-C0TMdlhV.js +0 -0
  210. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/php-CDn_0X-4.js +0 -0
  211. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/pkl-u5AG7uiY.js +0 -0
  212. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/plastic-3e1v2bzS.js +0 -0
  213. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/plsql-ChMvpjG-.js +0 -0
  214. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/po-BTJTHyun.js +0 -0
  215. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/poimandres-CS3Unz2-.js +0 -0
  216. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/polar-C0HS_06l.js +0 -0
  217. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/postcss-CXtECtnM.js +0 -0
  218. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/powerquery-CEu0bR-o.js +0 -0
  219. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/powershell-Dpen1YoG.js +0 -0
  220. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/prisma-Dd19v3D-.js +0 -0
  221. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/prolog-CbFg5uaA.js +0 -0
  222. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/proto-DyJlTyXw.js +0 -0
  223. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/pug-CGlum2m_.js +0 -0
  224. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/puppet-BMWR74SV.js +0 -0
  225. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/purescript-CklMAg4u.js +0 -0
  226. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/python-B6aJPvgy.js +0 -0
  227. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/qml-3beO22l8.js +0 -0
  228. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/qmldir-C8lEn-DE.js +0 -0
  229. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/qss-IeuSbFQv.js +0 -0
  230. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/r-DiinP2Uv.js +0 -0
  231. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/racket-BqYA7rlc.js +0 -0
  232. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/raku-DXvB9xmW.js +0 -0
  233. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/razor-WgofotgN.js +0 -0
  234. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/red-bN70gL4F.js +0 -0
  235. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/reg-C-SQnVFl.js +0 -0
  236. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/regexp-CDVJQ6XC.js +0 -0
  237. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/rel-C3B-1QV4.js +0 -0
  238. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/riscv-BM1_JUlF.js +0 -0
  239. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/rose-pine-BHrmToEH.js +0 -0
  240. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/rose-pine-dawn-CnK8MTSM.js +0 -0
  241. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/rose-pine-moon-NleAzG8P.js +0 -0
  242. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/rosmsg-BJDFO7_C.js +0 -0
  243. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/rst-B0xPkSld.js +0 -0
  244. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ruby-BvKwtOVI.js +0 -0
  245. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/rust-B1yitclQ.js +0 -0
  246. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/sas-cz2c8ADy.js +0 -0
  247. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/sass-Cj5Yp3dK.js +0 -0
  248. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/scala-C151Ov-r.js +0 -0
  249. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/scheme-C98Dy4si.js +0 -0
  250. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/scss-OYdSNvt2.js +0 -0
  251. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/sdbl-DVxCFoDh.js +0 -0
  252. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/shaderlab-Dg9Lc6iA.js +0 -0
  253. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/shellscript-Yzrsuije.js +0 -0
  254. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/shellsession-BADoaaVG.js +0 -0
  255. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/slack-dark-BthQWCQV.js +0 -0
  256. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/slack-ochin-DqwNpetd.js +0 -0
  257. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/smalltalk-BERRCDM3.js +0 -0
  258. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/snazzy-light-Bw305WKR.js +0 -0
  259. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/solarized-dark-DXbdFlpD.js +0 -0
  260. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/solarized-light-L9t79GZl.js +0 -0
  261. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/solidity-BbcW6ACK.js +0 -0
  262. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/soy-Brmx7dQM.js +0 -0
  263. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/sparql-rVzFXLq3.js +0 -0
  264. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/splunk-BtCnVYZw.js +0 -0
  265. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/sql-BLtJtn59.js +0 -0
  266. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ssh-config-_ykCGR6B.js +0 -0
  267. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/stata-BH5u7GGu.js +0 -0
  268. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/stylus-BEDo0Tqx.js +0 -0
  269. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/svelte-3Dk4HxPD.js +0 -0
  270. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/swift-Dg5xB15N.js +0 -0
  271. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/synthwave-84-CbfX1IO0.js +0 -0
  272. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/system-verilog-CnnmHF94.js +0 -0
  273. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/systemd-4A_iFExJ.js +0 -0
  274. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/talonscript-CkByrt1z.js +0 -0
  275. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/tasl-QIJgUcNo.js +0 -0
  276. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/tcl-dwOrl1Do.js +0 -0
  277. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/templ-W15q3VgB.js +0 -0
  278. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/terraform-BETggiCN.js +0 -0
  279. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/tex-Cppo0RY3.js +0 -0
  280. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/tokyo-night-hegEt444.js +0 -0
  281. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/toml-vGWfd6FD.js +0 -0
  282. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/ts-tags-zn1MmPIZ.js +0 -0
  283. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/tsv-B_m7g4N7.js +0 -0
  284. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/tsx-COt5Ahok.js +0 -0
  285. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/turtle-BsS91CYL.js +0 -0
  286. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/twig-CO9l9SDP.js +0 -0
  287. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/typescript-BPQ3VLAy.js +0 -0
  288. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/typespec-Df68jz8_.js +0 -0
  289. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/typst-DHCkPAjA.js +0 -0
  290. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/v-BcVCzyr7.js +0 -0
  291. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vala-CsfeWuGM.js +0 -0
  292. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vb-D17OF-Vu.js +0 -0
  293. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/verilog-BQ8w6xss.js +0 -0
  294. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vesper-DU1UobuO.js +0 -0
  295. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vhdl-CeAyd5Ju.js +0 -0
  296. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/viml-CJc9bBzg.js +0 -0
  297. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vitesse-black-Bkuqu6BP.js +0 -0
  298. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vitesse-dark-D0r3Knsf.js +0 -0
  299. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vitesse-light-CVO1_9PV.js +0 -0
  300. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vue-CCoi5OLL.js +0 -0
  301. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vue-html-DAAvJJDi.js +0 -0
  302. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vue-vine-_Ih-lPRR.js +0 -0
  303. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/vyper-CDx5xZoG.js +0 -0
  304. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/wasm-CG6Dc4jp.js +0 -0
  305. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/wasm-MzD3tlZU.js +0 -0
  306. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/wenyan-BV7otONQ.js +0 -0
  307. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/wgsl-Dx-B1_4e.js +0 -0
  308. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/wikitext-BhOHFoWU.js +0 -0
  309. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/wit-5i3qLPDT.js +0 -0
  310. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/wolfram-lXgVvXCa.js +0 -0
  311. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/xml-sdJ4AIDG.js +0 -0
  312. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/xsl-CtQFsRM5.js +0 -0
  313. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/yaml-Buea-lGh.js +0 -0
  314. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/zenscript-DVFEvuxE.js +0 -0
  315. {srcly-0.1.26 → srcly-0.1.27}/app/static/assets/zig-VOosw3JB.js +0 -0
  316. {srcly-0.1.26 → srcly-0.1.27}/app/static/vite.svg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: srcly
3
- Version: 0.1.26
3
+ Version: 0.1.27
4
4
  Summary: Interactive codebase treemap and metrics viewer.
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: fastapi>=0.121.3
@@ -1034,9 +1034,16 @@ def compute_focus_overlay(
1034
1034
  usage_fn_scope_id = u.containing_fn_scope_id
1035
1035
  usage_fn_chain = set(_ancestor_chain(usage_fn_scope_id))
1036
1036
 
1037
+
1037
1038
  def_chain = set(_ancestor_chain(def_scope.id))
1038
1039
 
1039
- if usage_fn_scope_id in def_chain:
1040
+ # START FIX: If the definition is within the current focus range, treat as local.
1041
+ definition_in_focus = (focus_start_line <= d.def_line <= focus_end_line)
1042
+
1043
+ if definition_in_focus:
1044
+ category = "local"
1045
+ tooltip = f"Local declaration (line {d.def_line})"
1046
+ elif usage_fn_scope_id in def_chain:
1040
1047
  category = "local"
1041
1048
  tooltip = f"Local declaration (line {d.def_line})"
1042
1049
  elif def_scope.id in usage_fn_chain and def_scope.id != global_scope.id:
@@ -0,0 +1,313 @@
1
+ import tree_sitter_python as tspython
2
+ from tree_sitter import Language, Parser, Node
3
+ from typing import List
4
+
5
+ from app.services.analysis_types import FileMetrics, FunctionMetrics
6
+
7
+ # Load Python grammar
8
+ PYTHON_LANGUAGE = Language(tspython.language())
9
+
10
+ class PythonTreeSitterAnalyzer:
11
+ def __init__(self):
12
+ self.parser = Parser(PYTHON_LANGUAGE)
13
+
14
+ def analyze_file(self, file_path: str) -> FileMetrics:
15
+ with open(file_path, 'rb') as f:
16
+ content = f.read()
17
+
18
+ tree = self.parser.parse(content)
19
+
20
+ lines = content.splitlines()
21
+ nloc = len([l for l in lines if l.strip()])
22
+
23
+ # Initialize file-level counters
24
+ self._file_comment_lines = 0
25
+ self._file_todo_count = 0
26
+ self._file_classes_count = 0
27
+ self._file_python_import_count = 0
28
+ self._file_max_nesting_depth = 0
29
+
30
+ # Run single-pass traversal
31
+ top_level_functions = []
32
+ self._scan_tree(tree.root_node, top_level_functions, [], 0)
33
+
34
+ # Calculate imports separately (logic is distinct and fast enough to keep separate/clean)
35
+ import_scope = self._compute_import_scope(tree.root_node, content)
36
+ if import_scope is not None:
37
+ top_level_functions.insert(0, import_scope)
38
+
39
+ # Average complexity (top-level only, matching original behavior)
40
+ avg_complexity = 0.0
41
+ if top_level_functions:
42
+ avg_complexity = sum(f.cyclomatic_complexity for f in top_level_functions) / len(top_level_functions)
43
+
44
+ # File level comment density
45
+ comment_density = self._file_comment_lines / nloc if nloc > 0 else 0.0
46
+
47
+ # Aggregate function metrics for file summary
48
+ # Note: Previous implementation calculated avg function length based on top-level functions?
49
+ # "total_function_length = sum(f.nloc for f in functions)"
50
+ # Yes, purely top-level iteration.
51
+ total_function_length = sum(f.nloc for f in top_level_functions)
52
+ average_function_length = total_function_length / len(top_level_functions) if top_level_functions else 0.0
53
+ parameter_count = sum(f.parameter_count for f in top_level_functions)
54
+
55
+ return FileMetrics(
56
+ nloc=nloc,
57
+ average_cyclomatic_complexity=avg_complexity,
58
+ function_list=top_level_functions,
59
+ filename=file_path,
60
+ comment_lines=self._file_comment_lines,
61
+ comment_density=comment_density,
62
+ max_nesting_depth=self._file_max_nesting_depth,
63
+ average_function_length=average_function_length,
64
+ parameter_count=parameter_count,
65
+ todo_count=self._file_todo_count,
66
+ classes_count=self._file_classes_count,
67
+ # Initialize other fields to valid defaults
68
+ tsx_nesting_depth=0,
69
+ tsx_render_branching_count=0,
70
+ tsx_react_use_effect_count=0,
71
+ tsx_anonymous_handler_count=0,
72
+ tsx_prop_count=0,
73
+ ts_any_usage_count=0,
74
+ ts_ignore_count=0,
75
+ ts_import_coupling_count=0,
76
+ python_import_count=self._file_python_import_count,
77
+ tsx_hardcoded_string_volume=0,
78
+ tsx_duplicated_string_count=0,
79
+ ts_type_interface_count=0,
80
+ ts_export_count=0,
81
+ md_data_url_count=0
82
+ )
83
+
84
+ def _scan_tree(
85
+ self,
86
+ node: Node,
87
+ parent_list: List[FunctionMetrics],
88
+ active_scopes: List[dict],
89
+ current_nesting: int
90
+ ):
91
+ """
92
+ Single-pass visitor to collect metrics.
93
+
94
+ parent_list: List to append new FunctionMetrics to (children of parent scope or top level).
95
+ active_scopes: Stack of dicts: {'metrics': FunctionMetrics, 'base_nesting': int}
96
+ current_nesting: Current nesting depth relative to file root.
97
+ """
98
+
99
+ node_type = node.type
100
+
101
+ # 1. Update File Metrics
102
+ if node_type == 'class_definition':
103
+ self._file_classes_count += 1
104
+ elif node_type in {'import_statement', 'import_from_statement'}:
105
+ self._file_python_import_count += 1
106
+
107
+ # 2. Check Nesting Depth for File
108
+ # File max nesting is just max of current_nesting encountered
109
+ # Wait, if we are at 'if' (nesting), current_nesting is passed as incremented.
110
+ # But we need to record it.
111
+ # Actually, let's track max seen.
112
+ is_nesting_node = node_type in {
113
+ 'if_statement', 'for_statement', 'while_statement', 'try_statement',
114
+ 'with_statement', 'match_statement'
115
+ }
116
+
117
+ # Update nesting for next recursion
118
+ next_nesting = current_nesting
119
+ if is_nesting_node:
120
+ next_nesting += 1
121
+
122
+ if next_nesting > self._file_max_nesting_depth:
123
+ self._file_max_nesting_depth = next_nesting
124
+
125
+ # 3. Update Active Scopes (Nesting & Comments)
126
+ if node_type == 'comment':
127
+ lines = (node.end_point.row - node.start_point.row + 1)
128
+ text = node.text.decode('utf-8', errors='ignore')
129
+ is_todo = 'TODO' in text or 'FIXME' in text
130
+
131
+ self._file_comment_lines += lines
132
+ if is_todo:
133
+ self._file_todo_count += 1
134
+
135
+ for scope in active_scopes:
136
+ scope['metrics'].comment_lines += lines
137
+ if is_todo:
138
+ scope['metrics'].todo_count += 1
139
+
140
+ # Update Max Nesting for Scopes
141
+ if is_nesting_node:
142
+ for scope in active_scopes:
143
+ # Depth relative to where the scope started
144
+ depth = next_nesting - scope['base_nesting']
145
+ if depth > scope['metrics'].max_nesting_depth:
146
+ scope['metrics'].max_nesting_depth = depth
147
+
148
+ # 4. Complexity (Applies to immediate scope only)
149
+ # Complexity types
150
+ if active_scopes:
151
+ current_scope = active_scopes[-1]['metrics']
152
+ if node_type in {
153
+ 'if_statement', 'for_statement', 'while_statement', 'except_clause',
154
+ 'with_statement', 'match_statement', 'case_pattern'
155
+ }:
156
+ current_scope.cyclomatic_complexity += 1
157
+ elif node_type == 'boolean_operator':
158
+ # Check text for 'and'/'or'
159
+ # Optimization: check text content
160
+ text = node.text.decode('utf-8')
161
+ if 'and' in text or 'or' in text:
162
+ current_scope.cyclomatic_complexity += 1
163
+
164
+ # 5. Handle Scope Creation
165
+ scope_created = False
166
+ target_list_for_children = parent_list
167
+
168
+ # Define scope types
169
+ is_scope = node_type in {
170
+ 'function_definition',
171
+ 'class_definition',
172
+ 'lambda',
173
+ 'async_function_definition'
174
+ }
175
+
176
+ if is_scope:
177
+ new_metrics = self._create_scope_metrics(node)
178
+ parent_list.append(new_metrics)
179
+
180
+ # Function complexity default is 1
181
+ new_metrics.cyclomatic_complexity = 1
182
+
183
+ new_scope_ctx = {
184
+ 'metrics': new_metrics,
185
+ 'base_nesting': current_nesting
186
+ # Note: 'base_nesting' is the ambient nesting level AT the function definition.
187
+ # Content inside will start contributing to depth from there.
188
+ }
189
+ active_scopes.append(new_scope_ctx)
190
+ target_list_for_children = new_metrics.children
191
+ scope_created = True
192
+
193
+ # Recurse
194
+ for child in node.children:
195
+ # Optimization: If we just created a scope, we are passing its children list.
196
+ # But we must treat the child as children of the node.
197
+ # The 'target_list_for_children' is where the child's *scopes* should act effectively.
198
+ # Wait, `scan_tree` adds *scopes* to `parent_list`.
199
+ # If `child` is an `if_statement` (not a scope), it shouldn't be added to `parent_list`.
200
+ # `scan_tree` ONLY appends to `parent_list` IF `is_scope` is true.
201
+ # So passing `target_list_for_children` is safe.
202
+ self._scan_tree(child, target_list_for_children, active_scopes, next_nesting)
203
+
204
+ if scope_created:
205
+ active_scopes.pop()
206
+
207
+ def _create_scope_metrics(self, node: Node) -> FunctionMetrics:
208
+ name = self._get_scope_name(node)
209
+ start_line = node.start_point.row + 1
210
+ end_line = node.end_point.row + 1
211
+ nloc = end_line - start_line + 1
212
+
213
+ # Parameter count is fast enough to compute locally
214
+ parameter_count = self._count_parameters(node)
215
+
216
+ return FunctionMetrics(
217
+ name=name,
218
+ cyclomatic_complexity=0, # Will be accumulated
219
+ nloc=nloc,
220
+ start_line=start_line,
221
+ end_line=end_line,
222
+ parameter_count=parameter_count,
223
+ max_nesting_depth=0, # Will be accumulated
224
+ comment_lines=0, # Will be accumulated
225
+ todo_count=0, # Will be accumulated
226
+ origin_type=node.type
227
+ )
228
+
229
+ def _get_scope_name(self, node: Node) -> str:
230
+ if node.type in {'function_definition', 'class_definition', 'async_function_definition'}:
231
+ name_node = node.child_by_field_name('name')
232
+ if name_node:
233
+ prefix = ""
234
+ if node.type == 'class_definition': prefix = "(class) "
235
+ if node.type == 'async_function_definition': prefix = "(async) "
236
+ return f"{prefix}{name_node.text.decode('utf-8')}"
237
+
238
+ elif node.type == 'lambda':
239
+ return "(lambda)"
240
+
241
+ return "(anonymous)"
242
+
243
+ def _count_parameters(self, node: Node) -> int:
244
+ params_node = node.child_by_field_name('parameters')
245
+ if params_node:
246
+ count = 0
247
+ for child in params_node.children:
248
+ if child.type in {'identifier', 'typed_parameter', 'default_parameter', 'typed_default_parameter', 'list_splat_pattern', 'dictionary_splat_pattern'}:
249
+ count += 1
250
+ return count
251
+ return 0
252
+
253
+ def _compute_import_scope(self, root_node: Node, content: bytes) -> FunctionMetrics | None:
254
+ """
255
+ Create a synthetic top-level scope representing import statements.
256
+ Kept separate as it requires specific logic for contiguous block merging.
257
+ """
258
+ import_spans: List[tuple[int, int]] = []
259
+ lines = content.splitlines()
260
+
261
+ def only_blank_lines_between(end_line: int, start_line: int) -> bool:
262
+ if start_line <= end_line + 1:
263
+ return True
264
+ for line_no in range(end_line + 1, start_line):
265
+ idx = line_no - 1
266
+ if 0 <= idx < len(lines):
267
+ if lines[idx].strip():
268
+ return False
269
+ return True
270
+
271
+ def traverse(n: Node) -> None:
272
+ if n.type in {"import_statement", "import_from_statement"}:
273
+ start_line = n.start_point.row + 1
274
+ end_line = n.end_point.row + 1
275
+ import_spans.append((start_line, end_line))
276
+ for child in n.children:
277
+ traverse(child)
278
+
279
+ traverse(root_node)
280
+
281
+ if not import_spans:
282
+ return None
283
+
284
+ import_spans.sort(key=lambda s: (s[0], s[1]))
285
+ total_import_loc = sum(e - s + 1 for s, e in import_spans)
286
+
287
+ blocks: List[tuple[int, int, int]] = []
288
+ cur_s, cur_e = import_spans[0]
289
+ cur_loc = cur_e - cur_s + 1
290
+ for s, e in import_spans[1:]:
291
+ if only_blank_lines_between(cur_e, s):
292
+ cur_e = max(cur_e, e)
293
+ cur_loc += (e - s + 1)
294
+ else:
295
+ blocks.append((cur_s, cur_e, cur_loc))
296
+ cur_s, cur_e = s, e
297
+ cur_loc = e - s + 1
298
+ blocks.append((cur_s, cur_e, cur_loc))
299
+
300
+ block_s, block_e, _ = max(blocks, key=lambda b: (b[2], -b[0]))
301
+
302
+ return FunctionMetrics(
303
+ name="(imports)",
304
+ cyclomatic_complexity=0,
305
+ nloc=total_import_loc,
306
+ start_line=block_s,
307
+ end_line=block_e,
308
+ parameter_count=0,
309
+ max_nesting_depth=0,
310
+ comment_lines=0,
311
+ todo_count=0,
312
+ origin_type="imports",
313
+ )