codeslick-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/README.md +458 -0
  2. package/__tests__/cli-reporter.test.ts +86 -0
  3. package/__tests__/config-loader.test.ts +247 -0
  4. package/__tests__/local-scanner.test.ts +245 -0
  5. package/bin/codeslick.cjs +153 -0
  6. package/dist/packages/cli/src/commands/auth.d.ts +36 -0
  7. package/dist/packages/cli/src/commands/auth.d.ts.map +1 -0
  8. package/dist/packages/cli/src/commands/auth.js +226 -0
  9. package/dist/packages/cli/src/commands/auth.js.map +1 -0
  10. package/dist/packages/cli/src/commands/config.d.ts +37 -0
  11. package/dist/packages/cli/src/commands/config.d.ts.map +1 -0
  12. package/dist/packages/cli/src/commands/config.js +196 -0
  13. package/dist/packages/cli/src/commands/config.js.map +1 -0
  14. package/dist/packages/cli/src/commands/init.d.ts +32 -0
  15. package/dist/packages/cli/src/commands/init.d.ts.map +1 -0
  16. package/dist/packages/cli/src/commands/init.js +171 -0
  17. package/dist/packages/cli/src/commands/init.js.map +1 -0
  18. package/dist/packages/cli/src/commands/scan.d.ts +40 -0
  19. package/dist/packages/cli/src/commands/scan.d.ts.map +1 -0
  20. package/dist/packages/cli/src/commands/scan.js +204 -0
  21. package/dist/packages/cli/src/commands/scan.js.map +1 -0
  22. package/dist/packages/cli/src/config/config-loader.d.ts +67 -0
  23. package/dist/packages/cli/src/config/config-loader.d.ts.map +1 -0
  24. package/dist/packages/cli/src/config/config-loader.js +146 -0
  25. package/dist/packages/cli/src/config/config-loader.js.map +1 -0
  26. package/dist/packages/cli/src/reporters/cli-reporter.d.ts +69 -0
  27. package/dist/packages/cli/src/reporters/cli-reporter.d.ts.map +1 -0
  28. package/dist/packages/cli/src/reporters/cli-reporter.js +244 -0
  29. package/dist/packages/cli/src/reporters/cli-reporter.js.map +1 -0
  30. package/dist/packages/cli/src/scanner/local-scanner.d.ts +92 -0
  31. package/dist/packages/cli/src/scanner/local-scanner.d.ts.map +1 -0
  32. package/dist/packages/cli/src/scanner/local-scanner.js +221 -0
  33. package/dist/packages/cli/src/scanner/local-scanner.js.map +1 -0
  34. package/dist/src/lib/analyzers/helpers/ai-code-detection-utils.d.ts +88 -0
  35. package/dist/src/lib/analyzers/helpers/ai-code-detection-utils.d.ts.map +1 -0
  36. package/dist/src/lib/analyzers/helpers/ai-code-detection-utils.js +371 -0
  37. package/dist/src/lib/analyzers/helpers/ai-code-detection-utils.js.map +1 -0
  38. package/dist/src/lib/analyzers/helpers/jsx-helpers.d.ts +63 -0
  39. package/dist/src/lib/analyzers/helpers/jsx-helpers.d.ts.map +1 -0
  40. package/dist/src/lib/analyzers/helpers/jsx-helpers.js +95 -0
  41. package/dist/src/lib/analyzers/helpers/jsx-helpers.js.map +1 -0
  42. package/dist/src/lib/analyzers/helpers/variable-tracker.d.ts +59 -0
  43. package/dist/src/lib/analyzers/helpers/variable-tracker.d.ts.map +1 -0
  44. package/dist/src/lib/analyzers/helpers/variable-tracker.js +231 -0
  45. package/dist/src/lib/analyzers/helpers/variable-tracker.js.map +1 -0
  46. package/dist/src/lib/analyzers/java/security-checks/access-control.d.ts +20 -0
  47. package/dist/src/lib/analyzers/java/security-checks/access-control.d.ts.map +1 -0
  48. package/dist/src/lib/analyzers/java/security-checks/access-control.js +129 -0
  49. package/dist/src/lib/analyzers/java/security-checks/access-control.js.map +1 -0
  50. package/dist/src/lib/analyzers/java/security-checks/ai-generated-code.d.ts +25 -0
  51. package/dist/src/lib/analyzers/java/security-checks/ai-generated-code.d.ts.map +1 -0
  52. package/dist/src/lib/analyzers/java/security-checks/ai-generated-code.js +221 -0
  53. package/dist/src/lib/analyzers/java/security-checks/ai-generated-code.js.map +1 -0
  54. package/dist/src/lib/analyzers/java/security-checks/code-quality.d.ts +18 -0
  55. package/dist/src/lib/analyzers/java/security-checks/code-quality.d.ts.map +1 -0
  56. package/dist/src/lib/analyzers/java/security-checks/code-quality.js +84 -0
  57. package/dist/src/lib/analyzers/java/security-checks/code-quality.js.map +1 -0
  58. package/dist/src/lib/analyzers/java/security-checks/crypto-validation.d.ts +18 -0
  59. package/dist/src/lib/analyzers/java/security-checks/crypto-validation.d.ts.map +1 -0
  60. package/dist/src/lib/analyzers/java/security-checks/crypto-validation.js +161 -0
  61. package/dist/src/lib/analyzers/java/security-checks/crypto-validation.js.map +1 -0
  62. package/dist/src/lib/analyzers/java/security-checks/deserialization-xxe.d.ts +20 -0
  63. package/dist/src/lib/analyzers/java/security-checks/deserialization-xxe.d.ts.map +1 -0
  64. package/dist/src/lib/analyzers/java/security-checks/deserialization-xxe.js +163 -0
  65. package/dist/src/lib/analyzers/java/security-checks/deserialization-xxe.js.map +1 -0
  66. package/dist/src/lib/analyzers/java/security-checks/enhanced-supply-chain.d.ts +24 -0
  67. package/dist/src/lib/analyzers/java/security-checks/enhanced-supply-chain.d.ts.map +1 -0
  68. package/dist/src/lib/analyzers/java/security-checks/enhanced-supply-chain.js +178 -0
  69. package/dist/src/lib/analyzers/java/security-checks/enhanced-supply-chain.js.map +1 -0
  70. package/dist/src/lib/analyzers/java/security-checks/exception-handling.d.ts +25 -0
  71. package/dist/src/lib/analyzers/java/security-checks/exception-handling.d.ts.map +1 -0
  72. package/dist/src/lib/analyzers/java/security-checks/exception-handling.js +179 -0
  73. package/dist/src/lib/analyzers/java/security-checks/exception-handling.js.map +1 -0
  74. package/dist/src/lib/analyzers/java/security-checks/file-operations.d.ts +17 -0
  75. package/dist/src/lib/analyzers/java/security-checks/file-operations.d.ts.map +1 -0
  76. package/dist/src/lib/analyzers/java/security-checks/file-operations.js +67 -0
  77. package/dist/src/lib/analyzers/java/security-checks/file-operations.js.map +1 -0
  78. package/dist/src/lib/analyzers/java/security-checks/framework-security.d.ts +25 -0
  79. package/dist/src/lib/analyzers/java/security-checks/framework-security.d.ts.map +1 -0
  80. package/dist/src/lib/analyzers/java/security-checks/framework-security.js +396 -0
  81. package/dist/src/lib/analyzers/java/security-checks/framework-security.js.map +1 -0
  82. package/dist/src/lib/analyzers/java/security-checks/hardcoded-credentials.d.ts +20 -0
  83. package/dist/src/lib/analyzers/java/security-checks/hardcoded-credentials.d.ts.map +1 -0
  84. package/dist/src/lib/analyzers/java/security-checks/hardcoded-credentials.js +123 -0
  85. package/dist/src/lib/analyzers/java/security-checks/hardcoded-credentials.js.map +1 -0
  86. package/dist/src/lib/analyzers/java/security-checks/injection-attacks.d.ts +23 -0
  87. package/dist/src/lib/analyzers/java/security-checks/injection-attacks.d.ts.map +1 -0
  88. package/dist/src/lib/analyzers/java/security-checks/injection-attacks.js +201 -0
  89. package/dist/src/lib/analyzers/java/security-checks/injection-attacks.js.map +1 -0
  90. package/dist/src/lib/analyzers/java/security-checks/insecure-design.d.ts +20 -0
  91. package/dist/src/lib/analyzers/java/security-checks/insecure-design.d.ts.map +1 -0
  92. package/dist/src/lib/analyzers/java/security-checks/insecure-design.js +121 -0
  93. package/dist/src/lib/analyzers/java/security-checks/insecure-design.js.map +1 -0
  94. package/dist/src/lib/analyzers/java/security-checks/logging-failures.d.ts +20 -0
  95. package/dist/src/lib/analyzers/java/security-checks/logging-failures.d.ts.map +1 -0
  96. package/dist/src/lib/analyzers/java/security-checks/logging-failures.js +89 -0
  97. package/dist/src/lib/analyzers/java/security-checks/logging-failures.js.map +1 -0
  98. package/dist/src/lib/analyzers/java/security-checks/security-misconfiguration.d.ts +26 -0
  99. package/dist/src/lib/analyzers/java/security-checks/security-misconfiguration.d.ts.map +1 -0
  100. package/dist/src/lib/analyzers/java/security-checks/security-misconfiguration.js +309 -0
  101. package/dist/src/lib/analyzers/java/security-checks/security-misconfiguration.js.map +1 -0
  102. package/dist/src/lib/analyzers/java/security-checks/unsafe-patterns.d.ts +18 -0
  103. package/dist/src/lib/analyzers/java/security-checks/unsafe-patterns.d.ts.map +1 -0
  104. package/dist/src/lib/analyzers/java/security-checks/unsafe-patterns.js +114 -0
  105. package/dist/src/lib/analyzers/java/security-checks/unsafe-patterns.js.map +1 -0
  106. package/dist/src/lib/analyzers/java/utils/createVulnerability.d.ts +58 -0
  107. package/dist/src/lib/analyzers/java/utils/createVulnerability.d.ts.map +1 -0
  108. package/dist/src/lib/analyzers/java/utils/createVulnerability.js +71 -0
  109. package/dist/src/lib/analyzers/java/utils/createVulnerability.js.map +1 -0
  110. package/dist/src/lib/analyzers/java-analyzer.d.ts +209 -0
  111. package/dist/src/lib/analyzers/java-analyzer.d.ts.map +1 -0
  112. package/dist/src/lib/analyzers/java-analyzer.js +1720 -0
  113. package/dist/src/lib/analyzers/java-analyzer.js.map +1 -0
  114. package/dist/src/lib/analyzers/javascript/quality-checks/ai-hallucinations.d.ts +27 -0
  115. package/dist/src/lib/analyzers/javascript/quality-checks/ai-hallucinations.d.ts.map +1 -0
  116. package/dist/src/lib/analyzers/javascript/quality-checks/ai-hallucinations.js +123 -0
  117. package/dist/src/lib/analyzers/javascript/quality-checks/ai-hallucinations.js.map +1 -0
  118. package/dist/src/lib/analyzers/javascript/quality-checks/async-patterns.d.ts +44 -0
  119. package/dist/src/lib/analyzers/javascript/quality-checks/async-patterns.d.ts.map +1 -0
  120. package/dist/src/lib/analyzers/javascript/quality-checks/async-patterns.js +224 -0
  121. package/dist/src/lib/analyzers/javascript/quality-checks/async-patterns.js.map +1 -0
  122. package/dist/src/lib/analyzers/javascript/quality-checks/code-patterns.d.ts +50 -0
  123. package/dist/src/lib/analyzers/javascript/quality-checks/code-patterns.d.ts.map +1 -0
  124. package/dist/src/lib/analyzers/javascript/quality-checks/code-patterns.js +284 -0
  125. package/dist/src/lib/analyzers/javascript/quality-checks/code-patterns.js.map +1 -0
  126. package/dist/src/lib/analyzers/javascript/quality-checks/comparison-issues.d.ts +27 -0
  127. package/dist/src/lib/analyzers/javascript/quality-checks/comparison-issues.d.ts.map +1 -0
  128. package/dist/src/lib/analyzers/javascript/quality-checks/comparison-issues.js +86 -0
  129. package/dist/src/lib/analyzers/javascript/quality-checks/comparison-issues.js.map +1 -0
  130. package/dist/src/lib/analyzers/javascript/quality-checks/reference-errors.d.ts +32 -0
  131. package/dist/src/lib/analyzers/javascript/quality-checks/reference-errors.d.ts.map +1 -0
  132. package/dist/src/lib/analyzers/javascript/quality-checks/reference-errors.js +44 -0
  133. package/dist/src/lib/analyzers/javascript/quality-checks/reference-errors.js.map +1 -0
  134. package/dist/src/lib/analyzers/javascript/security-checks/access-control.d.ts +22 -0
  135. package/dist/src/lib/analyzers/javascript/security-checks/access-control.d.ts.map +1 -0
  136. package/dist/src/lib/analyzers/javascript/security-checks/access-control.js +168 -0
  137. package/dist/src/lib/analyzers/javascript/security-checks/access-control.js.map +1 -0
  138. package/dist/src/lib/analyzers/javascript/security-checks/ai-generated-code.d.ts +25 -0
  139. package/dist/src/lib/analyzers/javascript/security-checks/ai-generated-code.d.ts.map +1 -0
  140. package/dist/src/lib/analyzers/javascript/security-checks/ai-generated-code.js +232 -0
  141. package/dist/src/lib/analyzers/javascript/security-checks/ai-generated-code.js.map +1 -0
  142. package/dist/src/lib/analyzers/javascript/security-checks/authentication-failures.d.ts +27 -0
  143. package/dist/src/lib/analyzers/javascript/security-checks/authentication-failures.d.ts.map +1 -0
  144. package/dist/src/lib/analyzers/javascript/security-checks/authentication-failures.js +222 -0
  145. package/dist/src/lib/analyzers/javascript/security-checks/authentication-failures.js.map +1 -0
  146. package/dist/src/lib/analyzers/javascript/security-checks/credential-crypto.d.ts +28 -0
  147. package/dist/src/lib/analyzers/javascript/security-checks/credential-crypto.d.ts.map +1 -0
  148. package/dist/src/lib/analyzers/javascript/security-checks/credential-crypto.js +176 -0
  149. package/dist/src/lib/analyzers/javascript/security-checks/credential-crypto.js.map +1 -0
  150. package/dist/src/lib/analyzers/javascript/security-checks/enhanced-supply-chain.d.ts +23 -0
  151. package/dist/src/lib/analyzers/javascript/security-checks/enhanced-supply-chain.d.ts.map +1 -0
  152. package/dist/src/lib/analyzers/javascript/security-checks/enhanced-supply-chain.js +113 -0
  153. package/dist/src/lib/analyzers/javascript/security-checks/enhanced-supply-chain.js.map +1 -0
  154. package/dist/src/lib/analyzers/javascript/security-checks/exception-handling.d.ts +28 -0
  155. package/dist/src/lib/analyzers/javascript/security-checks/exception-handling.d.ts.map +1 -0
  156. package/dist/src/lib/analyzers/javascript/security-checks/exception-handling.js +227 -0
  157. package/dist/src/lib/analyzers/javascript/security-checks/exception-handling.js.map +1 -0
  158. package/dist/src/lib/analyzers/javascript/security-checks/injection-attacks.d.ts +32 -0
  159. package/dist/src/lib/analyzers/javascript/security-checks/injection-attacks.d.ts.map +1 -0
  160. package/dist/src/lib/analyzers/javascript/security-checks/injection-attacks.js +260 -0
  161. package/dist/src/lib/analyzers/javascript/security-checks/injection-attacks.js.map +1 -0
  162. package/dist/src/lib/analyzers/javascript/security-checks/insecure-design.d.ts +26 -0
  163. package/dist/src/lib/analyzers/javascript/security-checks/insecure-design.d.ts.map +1 -0
  164. package/dist/src/lib/analyzers/javascript/security-checks/insecure-design.js +164 -0
  165. package/dist/src/lib/analyzers/javascript/security-checks/insecure-design.js.map +1 -0
  166. package/dist/src/lib/analyzers/javascript/security-checks/security-misconfiguration.d.ts +26 -0
  167. package/dist/src/lib/analyzers/javascript/security-checks/security-misconfiguration.d.ts.map +1 -0
  168. package/dist/src/lib/analyzers/javascript/security-checks/security-misconfiguration.js +775 -0
  169. package/dist/src/lib/analyzers/javascript/security-checks/security-misconfiguration.js.map +1 -0
  170. package/dist/src/lib/analyzers/javascript/security-checks/software-integrity.d.ts +25 -0
  171. package/dist/src/lib/analyzers/javascript/security-checks/software-integrity.d.ts.map +1 -0
  172. package/dist/src/lib/analyzers/javascript/security-checks/software-integrity.js +168 -0
  173. package/dist/src/lib/analyzers/javascript/security-checks/software-integrity.js.map +1 -0
  174. package/dist/src/lib/analyzers/javascript/security-checks/storage-security.d.ts +27 -0
  175. package/dist/src/lib/analyzers/javascript/security-checks/storage-security.d.ts.map +1 -0
  176. package/dist/src/lib/analyzers/javascript/security-checks/storage-security.js +108 -0
  177. package/dist/src/lib/analyzers/javascript/security-checks/storage-security.js.map +1 -0
  178. package/dist/src/lib/analyzers/javascript/security-checks/xss-dom-security.d.ts +28 -0
  179. package/dist/src/lib/analyzers/javascript/security-checks/xss-dom-security.d.ts.map +1 -0
  180. package/dist/src/lib/analyzers/javascript/security-checks/xss-dom-security.js +143 -0
  181. package/dist/src/lib/analyzers/javascript/security-checks/xss-dom-security.js.map +1 -0
  182. package/dist/src/lib/analyzers/javascript/syntax/syntax-helpers.d.ts +53 -0
  183. package/dist/src/lib/analyzers/javascript/syntax/syntax-helpers.d.ts.map +1 -0
  184. package/dist/src/lib/analyzers/javascript/syntax/syntax-helpers.js +144 -0
  185. package/dist/src/lib/analyzers/javascript/syntax/syntax-helpers.js.map +1 -0
  186. package/dist/src/lib/analyzers/javascript/syntax/typescript-syntax.d.ts +72 -0
  187. package/dist/src/lib/analyzers/javascript/syntax/typescript-syntax.d.ts.map +1 -0
  188. package/dist/src/lib/analyzers/javascript/syntax/typescript-syntax.js +314 -0
  189. package/dist/src/lib/analyzers/javascript/syntax/typescript-syntax.js.map +1 -0
  190. package/dist/src/lib/analyzers/javascript/utils/createVulnerability.d.ts +58 -0
  191. package/dist/src/lib/analyzers/javascript/utils/createVulnerability.d.ts.map +1 -0
  192. package/dist/src/lib/analyzers/javascript/utils/createVulnerability.js +71 -0
  193. package/dist/src/lib/analyzers/javascript/utils/createVulnerability.js.map +1 -0
  194. package/dist/src/lib/analyzers/javascript/utils/metrics-calculator.d.ts +36 -0
  195. package/dist/src/lib/analyzers/javascript/utils/metrics-calculator.d.ts.map +1 -0
  196. package/dist/src/lib/analyzers/javascript/utils/metrics-calculator.js +70 -0
  197. package/dist/src/lib/analyzers/javascript/utils/metrics-calculator.js.map +1 -0
  198. package/dist/src/lib/analyzers/javascript/utils/performance-analyzer.d.ts +29 -0
  199. package/dist/src/lib/analyzers/javascript/utils/performance-analyzer.d.ts.map +1 -0
  200. package/dist/src/lib/analyzers/javascript/utils/performance-analyzer.js +55 -0
  201. package/dist/src/lib/analyzers/javascript/utils/performance-analyzer.js.map +1 -0
  202. package/dist/src/lib/analyzers/javascript-analyzer.d.ts +95 -0
  203. package/dist/src/lib/analyzers/javascript-analyzer.d.ts.map +1 -0
  204. package/dist/src/lib/analyzers/javascript-analyzer.js +2141 -0
  205. package/dist/src/lib/analyzers/javascript-analyzer.js.map +1 -0
  206. package/dist/src/lib/analyzers/python/security-checks/access-control.d.ts +21 -0
  207. package/dist/src/lib/analyzers/python/security-checks/access-control.d.ts.map +1 -0
  208. package/dist/src/lib/analyzers/python/security-checks/access-control.js +305 -0
  209. package/dist/src/lib/analyzers/python/security-checks/access-control.js.map +1 -0
  210. package/dist/src/lib/analyzers/python/security-checks/ai-generated-code.d.ts +25 -0
  211. package/dist/src/lib/analyzers/python/security-checks/ai-generated-code.d.ts.map +1 -0
  212. package/dist/src/lib/analyzers/python/security-checks/ai-generated-code.js +242 -0
  213. package/dist/src/lib/analyzers/python/security-checks/ai-generated-code.js.map +1 -0
  214. package/dist/src/lib/analyzers/python/security-checks/authentication-flaws.d.ts +24 -0
  215. package/dist/src/lib/analyzers/python/security-checks/authentication-flaws.d.ts.map +1 -0
  216. package/dist/src/lib/analyzers/python/security-checks/authentication-flaws.js +207 -0
  217. package/dist/src/lib/analyzers/python/security-checks/authentication-flaws.js.map +1 -0
  218. package/dist/src/lib/analyzers/python/security-checks/code-quality.d.ts +27 -0
  219. package/dist/src/lib/analyzers/python/security-checks/code-quality.d.ts.map +1 -0
  220. package/dist/src/lib/analyzers/python/security-checks/code-quality.js +206 -0
  221. package/dist/src/lib/analyzers/python/security-checks/code-quality.js.map +1 -0
  222. package/dist/src/lib/analyzers/python/security-checks/credentials-crypto.d.ts +24 -0
  223. package/dist/src/lib/analyzers/python/security-checks/credentials-crypto.d.ts.map +1 -0
  224. package/dist/src/lib/analyzers/python/security-checks/credentials-crypto.js +113 -0
  225. package/dist/src/lib/analyzers/python/security-checks/credentials-crypto.js.map +1 -0
  226. package/dist/src/lib/analyzers/python/security-checks/crypto-failures.d.ts +20 -0
  227. package/dist/src/lib/analyzers/python/security-checks/crypto-failures.d.ts.map +1 -0
  228. package/dist/src/lib/analyzers/python/security-checks/crypto-failures.js +129 -0
  229. package/dist/src/lib/analyzers/python/security-checks/crypto-failures.js.map +1 -0
  230. package/dist/src/lib/analyzers/python/security-checks/data-integrity.d.ts +19 -0
  231. package/dist/src/lib/analyzers/python/security-checks/data-integrity.d.ts.map +1 -0
  232. package/dist/src/lib/analyzers/python/security-checks/data-integrity.js +90 -0
  233. package/dist/src/lib/analyzers/python/security-checks/data-integrity.js.map +1 -0
  234. package/dist/src/lib/analyzers/python/security-checks/deserialization.d.ts +20 -0
  235. package/dist/src/lib/analyzers/python/security-checks/deserialization.d.ts.map +1 -0
  236. package/dist/src/lib/analyzers/python/security-checks/deserialization.js +68 -0
  237. package/dist/src/lib/analyzers/python/security-checks/deserialization.js.map +1 -0
  238. package/dist/src/lib/analyzers/python/security-checks/django-security.d.ts +25 -0
  239. package/dist/src/lib/analyzers/python/security-checks/django-security.d.ts.map +1 -0
  240. package/dist/src/lib/analyzers/python/security-checks/django-security.js +180 -0
  241. package/dist/src/lib/analyzers/python/security-checks/django-security.js.map +1 -0
  242. package/dist/src/lib/analyzers/python/security-checks/enhanced-supply-chain.d.ts +23 -0
  243. package/dist/src/lib/analyzers/python/security-checks/enhanced-supply-chain.d.ts.map +1 -0
  244. package/dist/src/lib/analyzers/python/security-checks/enhanced-supply-chain.js +127 -0
  245. package/dist/src/lib/analyzers/python/security-checks/enhanced-supply-chain.js.map +1 -0
  246. package/dist/src/lib/analyzers/python/security-checks/exception-handling.d.ts +23 -0
  247. package/dist/src/lib/analyzers/python/security-checks/exception-handling.d.ts.map +1 -0
  248. package/dist/src/lib/analyzers/python/security-checks/exception-handling.js +120 -0
  249. package/dist/src/lib/analyzers/python/security-checks/exception-handling.js.map +1 -0
  250. package/dist/src/lib/analyzers/python/security-checks/flask-security.d.ts +24 -0
  251. package/dist/src/lib/analyzers/python/security-checks/flask-security.d.ts.map +1 -0
  252. package/dist/src/lib/analyzers/python/security-checks/flask-security.js +143 -0
  253. package/dist/src/lib/analyzers/python/security-checks/flask-security.js.map +1 -0
  254. package/dist/src/lib/analyzers/python/security-checks/injection-attacks.d.ts +28 -0
  255. package/dist/src/lib/analyzers/python/security-checks/injection-attacks.d.ts.map +1 -0
  256. package/dist/src/lib/analyzers/python/security-checks/injection-attacks.js +174 -0
  257. package/dist/src/lib/analyzers/python/security-checks/injection-attacks.js.map +1 -0
  258. package/dist/src/lib/analyzers/python/security-checks/insecure-design.d.ts +20 -0
  259. package/dist/src/lib/analyzers/python/security-checks/insecure-design.d.ts.map +1 -0
  260. package/dist/src/lib/analyzers/python/security-checks/insecure-design.js +160 -0
  261. package/dist/src/lib/analyzers/python/security-checks/insecure-design.js.map +1 -0
  262. package/dist/src/lib/analyzers/python/security-checks/logging-failures.d.ts +20 -0
  263. package/dist/src/lib/analyzers/python/security-checks/logging-failures.d.ts.map +1 -0
  264. package/dist/src/lib/analyzers/python/security-checks/logging-failures.js +121 -0
  265. package/dist/src/lib/analyzers/python/security-checks/logging-failures.js.map +1 -0
  266. package/dist/src/lib/analyzers/python/security-checks/nosql-injection.d.ts +26 -0
  267. package/dist/src/lib/analyzers/python/security-checks/nosql-injection.d.ts.map +1 -0
  268. package/dist/src/lib/analyzers/python/security-checks/nosql-injection.js +248 -0
  269. package/dist/src/lib/analyzers/python/security-checks/nosql-injection.js.map +1 -0
  270. package/dist/src/lib/analyzers/python/security-checks/security-misconfiguration.d.ts +26 -0
  271. package/dist/src/lib/analyzers/python/security-checks/security-misconfiguration.d.ts.map +1 -0
  272. package/dist/src/lib/analyzers/python/security-checks/security-misconfiguration.js +375 -0
  273. package/dist/src/lib/analyzers/python/security-checks/security-misconfiguration.js.map +1 -0
  274. package/dist/src/lib/analyzers/python/security-checks/ssrf-detection.d.ts +26 -0
  275. package/dist/src/lib/analyzers/python/security-checks/ssrf-detection.d.ts.map +1 -0
  276. package/dist/src/lib/analyzers/python/security-checks/ssrf-detection.js +160 -0
  277. package/dist/src/lib/analyzers/python/security-checks/ssrf-detection.js.map +1 -0
  278. package/dist/src/lib/analyzers/python/security-checks/web-security.d.ts +23 -0
  279. package/dist/src/lib/analyzers/python/security-checks/web-security.d.ts.map +1 -0
  280. package/dist/src/lib/analyzers/python/security-checks/web-security.js +117 -0
  281. package/dist/src/lib/analyzers/python/security-checks/web-security.js.map +1 -0
  282. package/dist/src/lib/analyzers/python/utils/createVulnerability.d.ts +58 -0
  283. package/dist/src/lib/analyzers/python/utils/createVulnerability.d.ts.map +1 -0
  284. package/dist/src/lib/analyzers/python/utils/createVulnerability.js +71 -0
  285. package/dist/src/lib/analyzers/python/utils/createVulnerability.js.map +1 -0
  286. package/dist/src/lib/analyzers/python-analyzer.d.ts +111 -0
  287. package/dist/src/lib/analyzers/python-analyzer.d.ts.map +1 -0
  288. package/dist/src/lib/analyzers/python-analyzer.js +1600 -0
  289. package/dist/src/lib/analyzers/python-analyzer.js.map +1 -0
  290. package/dist/src/lib/analyzers/secrets/patterns/api-keys/ai-providers.d.ts +14 -0
  291. package/dist/src/lib/analyzers/secrets/patterns/api-keys/ai-providers.d.ts.map +1 -0
  292. package/dist/src/lib/analyzers/secrets/patterns/api-keys/ai-providers.js +47 -0
  293. package/dist/src/lib/analyzers/secrets/patterns/api-keys/ai-providers.js.map +1 -0
  294. package/dist/src/lib/analyzers/secrets/patterns/api-keys/aws.d.ts +13 -0
  295. package/dist/src/lib/analyzers/secrets/patterns/api-keys/aws.d.ts.map +1 -0
  296. package/dist/src/lib/analyzers/secrets/patterns/api-keys/aws.js +36 -0
  297. package/dist/src/lib/analyzers/secrets/patterns/api-keys/aws.js.map +1 -0
  298. package/dist/src/lib/analyzers/secrets/patterns/api-keys/cloud-providers.d.ts +15 -0
  299. package/dist/src/lib/analyzers/secrets/patterns/api-keys/cloud-providers.d.ts.map +1 -0
  300. package/dist/src/lib/analyzers/secrets/patterns/api-keys/cloud-providers.js +68 -0
  301. package/dist/src/lib/analyzers/secrets/patterns/api-keys/cloud-providers.js.map +1 -0
  302. package/dist/src/lib/analyzers/secrets/patterns/api-keys/communication.d.ts +15 -0
  303. package/dist/src/lib/analyzers/secrets/patterns/api-keys/communication.d.ts.map +1 -0
  304. package/dist/src/lib/analyzers/secrets/patterns/api-keys/communication.js +68 -0
  305. package/dist/src/lib/analyzers/secrets/patterns/api-keys/communication.js.map +1 -0
  306. package/dist/src/lib/analyzers/secrets/patterns/api-keys/generic.d.ts +12 -0
  307. package/dist/src/lib/analyzers/secrets/patterns/api-keys/generic.d.ts.map +1 -0
  308. package/dist/src/lib/analyzers/secrets/patterns/api-keys/generic.js +45 -0
  309. package/dist/src/lib/analyzers/secrets/patterns/api-keys/generic.js.map +1 -0
  310. package/dist/src/lib/analyzers/secrets/patterns/api-keys/github.d.ts +14 -0
  311. package/dist/src/lib/analyzers/secrets/patterns/api-keys/github.d.ts.map +1 -0
  312. package/dist/src/lib/analyzers/secrets/patterns/api-keys/github.js +47 -0
  313. package/dist/src/lib/analyzers/secrets/patterns/api-keys/github.js.map +1 -0
  314. package/dist/src/lib/analyzers/secrets/patterns/api-keys/stripe.d.ts +13 -0
  315. package/dist/src/lib/analyzers/secrets/patterns/api-keys/stripe.d.ts.map +1 -0
  316. package/dist/src/lib/analyzers/secrets/patterns/api-keys/stripe.js +36 -0
  317. package/dist/src/lib/analyzers/secrets/patterns/api-keys/stripe.js.map +1 -0
  318. package/dist/src/lib/analyzers/secrets/patterns/api-keys.d.ts +15 -0
  319. package/dist/src/lib/analyzers/secrets/patterns/api-keys.d.ts.map +1 -0
  320. package/dist/src/lib/analyzers/secrets/patterns/api-keys.js +32 -0
  321. package/dist/src/lib/analyzers/secrets/patterns/api-keys.js.map +1 -0
  322. package/dist/src/lib/analyzers/secrets/patterns/credentials.d.ts +15 -0
  323. package/dist/src/lib/analyzers/secrets/patterns/credentials.d.ts.map +1 -0
  324. package/dist/src/lib/analyzers/secrets/patterns/credentials.js +68 -0
  325. package/dist/src/lib/analyzers/secrets/patterns/credentials.js.map +1 -0
  326. package/dist/src/lib/analyzers/secrets/patterns/private-keys.d.ts +16 -0
  327. package/dist/src/lib/analyzers/secrets/patterns/private-keys.d.ts.map +1 -0
  328. package/dist/src/lib/analyzers/secrets/patterns/private-keys.js +79 -0
  329. package/dist/src/lib/analyzers/secrets/patterns/private-keys.js.map +1 -0
  330. package/dist/src/lib/analyzers/secrets/patterns/tokens.d.ts +15 -0
  331. package/dist/src/lib/analyzers/secrets/patterns/tokens.d.ts.map +1 -0
  332. package/dist/src/lib/analyzers/secrets/patterns/tokens.js +58 -0
  333. package/dist/src/lib/analyzers/secrets/patterns/tokens.js.map +1 -0
  334. package/dist/src/lib/analyzers/secrets/secrets-analyzer.d.ts +88 -0
  335. package/dist/src/lib/analyzers/secrets/secrets-analyzer.d.ts.map +1 -0
  336. package/dist/src/lib/analyzers/secrets/secrets-analyzer.js +162 -0
  337. package/dist/src/lib/analyzers/secrets/secrets-analyzer.js.map +1 -0
  338. package/dist/src/lib/analyzers/secrets/validators/context-checker.d.ts +56 -0
  339. package/dist/src/lib/analyzers/secrets/validators/context-checker.d.ts.map +1 -0
  340. package/dist/src/lib/analyzers/secrets/validators/context-checker.js +199 -0
  341. package/dist/src/lib/analyzers/secrets/validators/context-checker.js.map +1 -0
  342. package/dist/src/lib/analyzers/secrets/validators/entropy-checker.d.ts +56 -0
  343. package/dist/src/lib/analyzers/secrets/validators/entropy-checker.d.ts.map +1 -0
  344. package/dist/src/lib/analyzers/secrets/validators/entropy-checker.js +102 -0
  345. package/dist/src/lib/analyzers/secrets/validators/entropy-checker.js.map +1 -0
  346. package/dist/src/lib/analyzers/security-checks/es6-security.d.ts +38 -0
  347. package/dist/src/lib/analyzers/security-checks/es6-security.d.ts.map +1 -0
  348. package/dist/src/lib/analyzers/security-checks/es6-security.js +125 -0
  349. package/dist/src/lib/analyzers/security-checks/es6-security.js.map +1 -0
  350. package/dist/src/lib/analyzers/security-checks/python-async-security.d.ts +46 -0
  351. package/dist/src/lib/analyzers/security-checks/python-async-security.d.ts.map +1 -0
  352. package/dist/src/lib/analyzers/security-checks/python-async-security.js +92 -0
  353. package/dist/src/lib/analyzers/security-checks/python-async-security.js.map +1 -0
  354. package/dist/src/lib/analyzers/security-checks/react-security.d.ts +49 -0
  355. package/dist/src/lib/analyzers/security-checks/react-security.d.ts.map +1 -0
  356. package/dist/src/lib/analyzers/security-checks/react-security.js +125 -0
  357. package/dist/src/lib/analyzers/security-checks/react-security.js.map +1 -0
  358. package/dist/src/lib/analyzers/types.d.ts +92 -0
  359. package/dist/src/lib/analyzers/types.d.ts.map +1 -0
  360. package/dist/src/lib/analyzers/types.js +3 -0
  361. package/dist/src/lib/analyzers/types.js.map +1 -0
  362. package/dist/src/lib/analyzers/typescript/security-checks/access-control.d.ts +19 -0
  363. package/dist/src/lib/analyzers/typescript/security-checks/access-control.d.ts.map +1 -0
  364. package/dist/src/lib/analyzers/typescript/security-checks/access-control.js +210 -0
  365. package/dist/src/lib/analyzers/typescript/security-checks/access-control.js.map +1 -0
  366. package/dist/src/lib/analyzers/typescript/security-checks/ai-generated-code.d.ts +25 -0
  367. package/dist/src/lib/analyzers/typescript/security-checks/ai-generated-code.d.ts.map +1 -0
  368. package/dist/src/lib/analyzers/typescript/security-checks/ai-generated-code.js +242 -0
  369. package/dist/src/lib/analyzers/typescript/security-checks/ai-generated-code.js.map +1 -0
  370. package/dist/src/lib/analyzers/typescript/security-checks/authentication.d.ts +28 -0
  371. package/dist/src/lib/analyzers/typescript/security-checks/authentication.d.ts.map +1 -0
  372. package/dist/src/lib/analyzers/typescript/security-checks/authentication.js +357 -0
  373. package/dist/src/lib/analyzers/typescript/security-checks/authentication.js.map +1 -0
  374. package/dist/src/lib/analyzers/typescript/security-checks/code-injection.d.ts +26 -0
  375. package/dist/src/lib/analyzers/typescript/security-checks/code-injection.d.ts.map +1 -0
  376. package/dist/src/lib/analyzers/typescript/security-checks/code-injection.js +380 -0
  377. package/dist/src/lib/analyzers/typescript/security-checks/code-injection.js.map +1 -0
  378. package/dist/src/lib/analyzers/typescript/security-checks/code-quality.d.ts +23 -0
  379. package/dist/src/lib/analyzers/typescript/security-checks/code-quality.d.ts.map +1 -0
  380. package/dist/src/lib/analyzers/typescript/security-checks/code-quality.js +109 -0
  381. package/dist/src/lib/analyzers/typescript/security-checks/code-quality.js.map +1 -0
  382. package/dist/src/lib/analyzers/typescript/security-checks/credentials-crypto.d.ts +21 -0
  383. package/dist/src/lib/analyzers/typescript/security-checks/credentials-crypto.d.ts.map +1 -0
  384. package/dist/src/lib/analyzers/typescript/security-checks/credentials-crypto.js +153 -0
  385. package/dist/src/lib/analyzers/typescript/security-checks/credentials-crypto.js.map +1 -0
  386. package/dist/src/lib/analyzers/typescript/security-checks/enhanced-supply-chain.d.ts +23 -0
  387. package/dist/src/lib/analyzers/typescript/security-checks/enhanced-supply-chain.d.ts.map +1 -0
  388. package/dist/src/lib/analyzers/typescript/security-checks/enhanced-supply-chain.js +146 -0
  389. package/dist/src/lib/analyzers/typescript/security-checks/enhanced-supply-chain.js.map +1 -0
  390. package/dist/src/lib/analyzers/typescript/security-checks/exception-handling.d.ts +23 -0
  391. package/dist/src/lib/analyzers/typescript/security-checks/exception-handling.d.ts.map +1 -0
  392. package/dist/src/lib/analyzers/typescript/security-checks/exception-handling.js +187 -0
  393. package/dist/src/lib/analyzers/typescript/security-checks/exception-handling.js.map +1 -0
  394. package/dist/src/lib/analyzers/typescript/security-checks/information-disclosure.d.ts +19 -0
  395. package/dist/src/lib/analyzers/typescript/security-checks/information-disclosure.d.ts.map +1 -0
  396. package/dist/src/lib/analyzers/typescript/security-checks/information-disclosure.js +97 -0
  397. package/dist/src/lib/analyzers/typescript/security-checks/information-disclosure.js.map +1 -0
  398. package/dist/src/lib/analyzers/typescript/security-checks/injection-attacks.d.ts +29 -0
  399. package/dist/src/lib/analyzers/typescript/security-checks/injection-attacks.d.ts.map +1 -0
  400. package/dist/src/lib/analyzers/typescript/security-checks/injection-attacks.js +319 -0
  401. package/dist/src/lib/analyzers/typescript/security-checks/injection-attacks.js.map +1 -0
  402. package/dist/src/lib/analyzers/typescript/security-checks/logging-failures.d.ts +21 -0
  403. package/dist/src/lib/analyzers/typescript/security-checks/logging-failures.d.ts.map +1 -0
  404. package/dist/src/lib/analyzers/typescript/security-checks/logging-failures.js +121 -0
  405. package/dist/src/lib/analyzers/typescript/security-checks/logging-failures.js.map +1 -0
  406. package/dist/src/lib/analyzers/typescript/security-checks/security-misconfiguration.d.ts +27 -0
  407. package/dist/src/lib/analyzers/typescript/security-checks/security-misconfiguration.d.ts.map +1 -0
  408. package/dist/src/lib/analyzers/typescript/security-checks/security-misconfiguration.js +213 -0
  409. package/dist/src/lib/analyzers/typescript/security-checks/security-misconfiguration.js.map +1 -0
  410. package/dist/src/lib/analyzers/typescript/security-checks/type-security.d.ts +19 -0
  411. package/dist/src/lib/analyzers/typescript/security-checks/type-security.d.ts.map +1 -0
  412. package/dist/src/lib/analyzers/typescript/security-checks/type-security.js +59 -0
  413. package/dist/src/lib/analyzers/typescript/security-checks/type-security.js.map +1 -0
  414. package/dist/src/lib/analyzers/typescript/type-checker.d.ts +17 -0
  415. package/dist/src/lib/analyzers/typescript/type-checker.d.ts.map +1 -0
  416. package/dist/src/lib/analyzers/typescript/type-checker.js +515 -0
  417. package/dist/src/lib/analyzers/typescript/type-checker.js.map +1 -0
  418. package/dist/src/lib/analyzers/typescript/utils/createVulnerability.d.ts +58 -0
  419. package/dist/src/lib/analyzers/typescript/utils/createVulnerability.d.ts.map +1 -0
  420. package/dist/src/lib/analyzers/typescript/utils/createVulnerability.js +71 -0
  421. package/dist/src/lib/analyzers/typescript/utils/createVulnerability.js.map +1 -0
  422. package/dist/src/lib/analyzers/typescript-analyzer.d.ts +116 -0
  423. package/dist/src/lib/analyzers/typescript-analyzer.d.ts.map +1 -0
  424. package/dist/src/lib/analyzers/typescript-analyzer.js +1660 -0
  425. package/dist/src/lib/analyzers/typescript-analyzer.js.map +1 -0
  426. package/dist/src/lib/security/compliance-mapping.d.ts +29 -0
  427. package/dist/src/lib/security/compliance-mapping.d.ts.map +1 -0
  428. package/dist/src/lib/security/compliance-mapping.js +1342 -0
  429. package/dist/src/lib/security/compliance-mapping.js.map +1 -0
  430. package/dist/src/lib/security/severity-scoring.d.ts +47 -0
  431. package/dist/src/lib/security/severity-scoring.d.ts.map +1 -0
  432. package/dist/src/lib/security/severity-scoring.js +965 -0
  433. package/dist/src/lib/security/severity-scoring.js.map +1 -0
  434. package/dist/src/lib/standards/references.d.ts +16 -0
  435. package/dist/src/lib/standards/references.d.ts.map +1 -0
  436. package/dist/src/lib/standards/references.js +1161 -0
  437. package/dist/src/lib/standards/references.js.map +1 -0
  438. package/dist/src/lib/types/index.d.ts +167 -0
  439. package/dist/src/lib/types/index.d.ts.map +1 -0
  440. package/dist/src/lib/types/index.js +3 -0
  441. package/dist/src/lib/types/index.js.map +1 -0
  442. package/dist/src/lib/utils/code-cleaner.d.ts +59 -0
  443. package/dist/src/lib/utils/code-cleaner.d.ts.map +1 -0
  444. package/dist/src/lib/utils/code-cleaner.js +283 -0
  445. package/dist/src/lib/utils/code-cleaner.js.map +1 -0
  446. package/package.json +51 -0
  447. package/src/commands/auth.ts +308 -0
  448. package/src/commands/config.ts +226 -0
  449. package/src/commands/init.ts +202 -0
  450. package/src/commands/scan.ts +238 -0
  451. package/src/config/config-loader.ts +175 -0
  452. package/src/reporters/cli-reporter.ts +282 -0
  453. package/src/scanner/local-scanner.ts +250 -0
  454. package/tsconfig.json +24 -0
  455. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,1720 @@
1
+ "use strict";
2
+ /**
3
+ * ⚠️ SHARED MODULE: Java Security Analyzer
4
+ *
5
+ * CRITICAL: This module is used by BOTH WebTool and GitHub App
6
+ *
7
+ * WebTool uses this for:
8
+ * - /api/analyze endpoint - Interactive single-file analysis (<3s target)
9
+ * - Real-time vulnerability detection for individual developers
10
+ *
11
+ * GitHub App uses this for:
12
+ * - /api/github/webhook - Batch PR analysis (10-30s OK)
13
+ * - Automated security checks for professional teams
14
+ *
15
+ * ⚠️ BEFORE MODIFYING THIS FILE:
16
+ * 1. Run all 96 analyzer tests: npm test analyzers
17
+ * 2. Test WebTool: Paste Java code at /analyze → Verify results
18
+ * 3. Test GitHub: Open PR with Java → Verify webhook comment
19
+ * 4. Verify performance: Analysis must complete in <2s per file
20
+ * 5. Check detection rate: All 18 Java checks must still detect
21
+ *
22
+ * CRITICAL OUTPUT FORMAT (DO NOT CHANGE):
23
+ * - result.security.vulnerabilities - Used by both systems
24
+ * - Each vulnerability has: line, message, severity, cvssScore, owasp, cwe
25
+ * - Changing this structure breaks BOTH WebTool and GitHub UI parsing
26
+ *
27
+ * See: docs/technical/WEBTOOL_GITHUB_SEPARATION.md
28
+ *
29
+ * Last modified: 2025-11-18
30
+ * Last verified (both systems): 2025-11-18
31
+ */
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.JavaAnalyzer = void 0;
34
+ const references_1 = require("../standards/references");
35
+ const code_cleaner_1 = require("../utils/code-cleaner");
36
+ // Modular security checks
37
+ const injection_attacks_1 = require("./java/security-checks/injection-attacks");
38
+ const deserialization_xxe_1 = require("./java/security-checks/deserialization-xxe");
39
+ const hardcoded_credentials_1 = require("./java/security-checks/hardcoded-credentials");
40
+ const crypto_validation_1 = require("./java/security-checks/crypto-validation");
41
+ const file_operations_1 = require("./java/security-checks/file-operations");
42
+ const unsafe_patterns_1 = require("./java/security-checks/unsafe-patterns");
43
+ const code_quality_1 = require("./java/security-checks/code-quality");
44
+ const framework_security_1 = require("./java/security-checks/framework-security");
45
+ const security_misconfiguration_1 = require("./java/security-checks/security-misconfiguration");
46
+ const exception_handling_1 = require("./java/security-checks/exception-handling");
47
+ const enhanced_supply_chain_1 = require("./java/security-checks/enhanced-supply-chain");
48
+ const access_control_1 = require("./java/security-checks/access-control");
49
+ const insecure_design_1 = require("./java/security-checks/insecure-design");
50
+ const logging_failures_1 = require("./java/security-checks/logging-failures");
51
+ const secrets_analyzer_1 = require("./secrets/secrets-analyzer");
52
+ const ai_generated_code_1 = require("./java/security-checks/ai-generated-code");
53
+ class JavaAnalyzer {
54
+ constructor() {
55
+ this.language = 'java';
56
+ }
57
+ async analyze(input) {
58
+ const result = {
59
+ syntax: { valid: true, errors: [], lineErrors: [] },
60
+ quality: { score: 100, issues: [] },
61
+ performance: { score: 100, suggestions: [] },
62
+ security: { vulnerabilities: [] },
63
+ metrics: { complexity: 1, maintainability: 100, lines: 0, functions: 0 }
64
+ };
65
+ try {
66
+ this.analyzeSyntax(input.code, result);
67
+ this.analyzeQuality(input.code, result);
68
+ this.analyzePerformance(input.code, result);
69
+ this.analyzeSecurity(input.code, result);
70
+ this.calculateMetrics(input.code, result);
71
+ // AI-Generated Code Detection (Phase 1.5, Week 5-7)
72
+ const lines = input.code.split('\n');
73
+ result.security.vulnerabilities.push(...(0, ai_generated_code_1.checkAIGeneratedCode)(lines, input.filename));
74
+ }
75
+ catch (error) {
76
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
77
+ result.syntax.valid = false;
78
+ result.syntax.errors.push(`Java analysis error: ${errorMessage}`);
79
+ }
80
+ return result;
81
+ }
82
+ async validateSyntax(code) {
83
+ // Basic Java syntax checks
84
+ if (code.length > 50 && !code.includes('public class') && !code.includes('class ')) {
85
+ return false;
86
+ }
87
+ // Check for balanced parentheses/braces
88
+ let braceCount = 0;
89
+ let parenCount = 0;
90
+ for (const char of code) {
91
+ if (char === '{')
92
+ braceCount++;
93
+ if (char === '}')
94
+ braceCount--;
95
+ if (char === '(')
96
+ parenCount++;
97
+ if (char === ')')
98
+ parenCount--;
99
+ }
100
+ return braceCount === 0 && parenCount === 0;
101
+ }
102
+ getLanguageInfo() {
103
+ return {
104
+ name: 'Java',
105
+ extensions: ['.java', '.class', '.jar'],
106
+ description: 'Enterprise and mobile language (Android)'
107
+ };
108
+ }
109
+ analyzeSyntax(code, result) {
110
+ const errors = [];
111
+ const lineErrors = [];
112
+ // Check for public class
113
+ if (code.length > 50 && !code.includes('public class') && !code.includes('class ')) {
114
+ errors.push('Java code must have at least one class');
115
+ }
116
+ // Basic syntax checks
117
+ const lines = code.split('\n');
118
+ lines.forEach((line, index) => {
119
+ const lineNumber = index + 1;
120
+ const trimmed = line.trim();
121
+ // CRITICAL FIX: Use CodeCleaner to remove comments (handles strings correctly)
122
+ const codeWithoutComment = code_cleaner_1.CodeCleaner.removeLineComments(line, 'java');
123
+ if (codeWithoutComment &&
124
+ !trimmed.startsWith('//') &&
125
+ !trimmed.startsWith('/*') &&
126
+ !codeWithoutComment.endsWith(';') &&
127
+ !codeWithoutComment.endsWith('{') &&
128
+ !codeWithoutComment.endsWith('}') &&
129
+ !trimmed.startsWith('if') &&
130
+ !trimmed.startsWith('for') &&
131
+ !trimmed.startsWith('while') &&
132
+ !trimmed.startsWith('public') &&
133
+ !trimmed.startsWith('private') &&
134
+ !trimmed.startsWith('protected') &&
135
+ !trimmed.startsWith('class') &&
136
+ !trimmed.startsWith('@') &&
137
+ !trimmed.startsWith('import') &&
138
+ !trimmed.startsWith('package') &&
139
+ (codeWithoutComment.includes('=') ||
140
+ codeWithoutComment.includes('System.out') ||
141
+ trimmed.startsWith('return') ||
142
+ trimmed.startsWith('throw') ||
143
+ trimmed.startsWith('break') ||
144
+ trimmed.startsWith('continue'))) {
145
+ lineErrors.push({
146
+ line: lineNumber,
147
+ error: 'Missing semicolon',
148
+ suggestion: `Add ; at the end: ${codeWithoutComment};`,
149
+ severity: 'error'
150
+ });
151
+ }
152
+ });
153
+ // Advanced detection methods
154
+ this.detectMethodSignatureErrors(code, lineErrors);
155
+ this.detectUnbalancedBraces(code, lineErrors);
156
+ this.detectNullPointerRisks(code, lineErrors);
157
+ this.detectCompilationErrors(code, lineErrors);
158
+ this.detectRuntimeExceptions(code, lineErrors);
159
+ this.detectConcurrencyIssues(code, lineErrors);
160
+ this.detectMemoryLeaks(code, lineErrors);
161
+ this.detectIOExceptions(code, lineErrors);
162
+ this.detectSQLInjection(code, lineErrors);
163
+ this.detectSerializationIssues(code, lineErrors);
164
+ this.detectPerformanceIssues(code, lineErrors);
165
+ this.detectNamingConventions(code, lineErrors);
166
+ this.detectAccessModifierIssues(code, lineErrors);
167
+ this.detectResourceLeaks(code, lineErrors);
168
+ this.detectBoxingUnboxing(code, lineErrors);
169
+ this.detectDeprecatedAPIs(code, lineErrors);
170
+ this.detectExceptionHandling(code, lineErrors);
171
+ this.detectDuplicateVariables(code, lineErrors);
172
+ this.detectMethodNamingIssues(code, lineErrors);
173
+ this.detectMagicNumbers(code, lineErrors);
174
+ this.detectGodClasses(code, lineErrors);
175
+ this.detectTooManyParameters(code, lineErrors);
176
+ this.detectStringComparisonWithEquals(code, lineErrors);
177
+ this.detectEmptyCatchBlocks(code, lineErrors);
178
+ this.detectUninitializedVariables(code, lineErrors);
179
+ this.detectMissingReturnStatements(code, lineErrors);
180
+ this.detectInvalidModifierOrder(code, lineErrors);
181
+ // DON'T add general balance errors - specific methods above already detect these issues
182
+ // with proper line numbers, enabling Auto-Fix functionality
183
+ result.syntax.errors = errors;
184
+ result.syntax.lineErrors = lineErrors;
185
+ result.syntax.valid = errors.length === 0 && lineErrors.filter(e => e.severity === 'error').length === 0;
186
+ if (!result.syntax.valid) {
187
+ result.quality.score -= errors.length * 15;
188
+ }
189
+ }
190
+ /**
191
+ * Detect method signature errors - Missing parentheses, malformed signatures
192
+ *
193
+ * Fixed logic:
194
+ * - Checks ALL lines ending with { (not just method signatures)
195
+ * - Detects missing ) in method signatures, catch blocks, if/while/for statements
196
+ * - Avoids false positives on multi-line declarations (lines without {)
197
+ */
198
+ detectMethodSignatureErrors(code, lineErrors) {
199
+ /**
200
+ * IMPROVED LOGIC (2025-10-16):
201
+ * - Properly handles strings with parentheses: "text (with parens)"
202
+ * - Uses CodeCleaner to remove comments before counting
203
+ * - Only checks lines ending with { (avoids multi-line false positives)
204
+ * - Handles multi-line parameter lists correctly
205
+ */
206
+ const lines = code.split('\n');
207
+ lines.forEach((line, index) => {
208
+ const lineNumber = index + 1;
209
+ const trimmed = line.trim();
210
+ // Skip comments and empty lines
211
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*') || !trimmed)
212
+ return;
213
+ // CRITICAL: Use CodeCleaner to remove comments (handles both // and /* */ correctly)
214
+ const codeWithoutComment = code_cleaner_1.CodeCleaner.removeLineComments(line, 'java');
215
+ if (!codeWithoutComment.trim())
216
+ return;
217
+ // Only check lines that end with { (potential syntax error location)
218
+ // This avoids false positives on multi-line method declarations like:
219
+ // public void createUser(String name, String email,
220
+ // String address, String phone, <- no { on this line
221
+ if (!codeWithoutComment.endsWith('{'))
222
+ return;
223
+ // IMPROVED: Remove string literals to avoid counting parentheses inside strings
224
+ // Example: String msg = "Hello (world)"; -> String msg = ;
225
+ let codeWithoutStrings = codeWithoutComment;
226
+ // Remove double-quoted strings
227
+ codeWithoutStrings = codeWithoutStrings.replace(/"(?:[^"\\]|\\.)*"/g, '""');
228
+ // Remove single-quoted chars
229
+ codeWithoutStrings = codeWithoutStrings.replace(/'(?:[^'\\]|\\.)'/g, "''");
230
+ // Count parentheses in the cleaned line (no comments, no strings)
231
+ let parenCount = 0;
232
+ for (const char of codeWithoutStrings) {
233
+ if (char === '(')
234
+ parenCount++;
235
+ if (char === ')')
236
+ parenCount--;
237
+ }
238
+ // If there are unclosed parentheses, it's a syntax error
239
+ // Examples:
240
+ // - public void processUser(User user { -> parenCount = 1
241
+ // - } catch (Exception e { -> parenCount = 1
242
+ // - if (condition { -> parenCount = 1
243
+ if (parenCount > 0) {
244
+ lineErrors.push({
245
+ line: lineNumber,
246
+ error: 'Syntax Error: Missing closing parenthesis before opening brace',
247
+ suggestion: 'Add closing parenthesis ) before {',
248
+ severity: 'error',
249
+ references: references_1.javaStandards['compilation-errors'] || []
250
+ });
251
+ }
252
+ // If there are too many closing parentheses, also report
253
+ // BUT: Skip if this is a multi-line parameter list ending
254
+ // FIX (Dec 12, 2025): Check if line contains ONLY closing paren + { (no opening paren)
255
+ // Example valid multi-line signatures that should NOT be flagged:
256
+ // Line 56: public void createUser(String name, String email,
257
+ // Line 57: String phone, String city) { <- has ) but no (
258
+ const hasOpenParen = codeWithoutStrings.includes('(');
259
+ const hasCloseParen = codeWithoutStrings.includes(')');
260
+ const isMultiLineContinuation = hasCloseParen && !hasOpenParen;
261
+ if (parenCount < 0 && !isMultiLineContinuation) {
262
+ lineErrors.push({
263
+ line: lineNumber,
264
+ error: 'Syntax Error: Extra closing parenthesis',
265
+ suggestion: 'Remove extra ) or add opening parenthesis (',
266
+ severity: 'error',
267
+ references: references_1.javaStandards['compilation-errors'] || []
268
+ });
269
+ }
270
+ });
271
+ }
272
+ /**
273
+ * Detect unbalanced braces - Missing opening or closing braces
274
+ *
275
+ * Tracks brace balance across the entire file to detect:
276
+ * - Methods/blocks with missing closing }
277
+ * - Extra closing } without matching opening {
278
+ */
279
+ detectUnbalancedBraces(code, lineErrors) {
280
+ const lines = code.split('\n');
281
+ const openBraces = []; // Stack of line numbers where { was opened
282
+ lines.forEach((line, index) => {
283
+ const lineNumber = index + 1;
284
+ const trimmed = line.trim();
285
+ // Skip full-line comments
286
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
287
+ return;
288
+ // CRITICAL FIX: Use CodeCleaner to properly remove comments
289
+ const codeWithoutComment = code_cleaner_1.CodeCleaner.removeLineComments(line, 'java');
290
+ // PHASE 6 FIX (2025-11-21): Remove string literals before counting braces
291
+ // Previous bug: Braces inside strings like "${jndi:ldap://...}" were counted
292
+ // This caused false positives on classes with JNDI exploit strings
293
+ let codeWithoutStrings = codeWithoutComment;
294
+ // Remove double-quoted strings (most common in Java)
295
+ codeWithoutStrings = codeWithoutStrings.replace(/"(?:[^"\\]|\\.)*"/g, '""');
296
+ // Remove single-quoted chars
297
+ codeWithoutStrings = codeWithoutStrings.replace(/'(?:[^'\\]|\\.)'/g, "''");
298
+ // Count braces in this line
299
+ for (const char of codeWithoutStrings) {
300
+ if (char === '{') {
301
+ openBraces.push(lineNumber);
302
+ }
303
+ else if (char === '}') {
304
+ if (openBraces.length > 0) {
305
+ openBraces.pop(); // Match closing brace with opening brace
306
+ }
307
+ else {
308
+ // Extra closing brace without matching opening brace
309
+ lineErrors.push({
310
+ line: lineNumber,
311
+ error: 'Syntax Error: Extra closing brace (no matching opening brace)',
312
+ suggestion: 'Remove extra } or add opening brace',
313
+ severity: 'error',
314
+ references: references_1.javaStandards['compilation-errors'] || []
315
+ });
316
+ }
317
+ }
318
+ }
319
+ });
320
+ // After processing all lines, check if there are unclosed braces
321
+ if (openBraces.length > 0) {
322
+ // Report the LAST unclosed brace (most likely the problematic one)
323
+ const lastOpenBraceLine = openBraces[openBraces.length - 1];
324
+ lineErrors.push({
325
+ line: lastOpenBraceLine,
326
+ error: 'Syntax Error: Missing closing brace',
327
+ suggestion: 'Add closing brace } to close this block',
328
+ severity: 'error',
329
+ references: references_1.javaStandards['compilation-errors'] || []
330
+ });
331
+ }
332
+ }
333
+ /**
334
+ * Detect NullPointerException risks - null checks and Optional usage
335
+ */
336
+ detectNullPointerRisks(code, lineErrors) {
337
+ const lines = code.split('\n');
338
+ lines.forEach((line, index) => {
339
+ const lineNumber = index + 1;
340
+ const trimmed = line.trim();
341
+ // Skip all types of comments
342
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*') || trimmed.startsWith('*/'))
343
+ return;
344
+ // Detect direct null assignment without checks
345
+ if (line.match(/=\s*null\s*;/) && !line.includes('//')) {
346
+ lineErrors.push({
347
+ line: lineNumber,
348
+ error: 'NullPointerException risk: Null assignment',
349
+ suggestion: 'Consider using Optional<T> or adding null checks',
350
+ severity: 'warning',
351
+ references: references_1.javaStandards['null-pointer'] || []
352
+ });
353
+ }
354
+ // DISABLED: Too aggressive - generates false positives on every method call
355
+ // Detect method calls on potentially null objects (disabled)
356
+ /*
357
+ if (line.match(/\w+\.\w+\(/) && !line.includes('if') && !line.includes('!=') && !line.includes('null')) {
358
+ const prevLines = lines.slice(Math.max(0, index - 3), index);
359
+ const hasNullCheck = prevLines.some(l => l.includes('!= null') || l.includes('== null'));
360
+
361
+ if (!hasNullCheck && line.includes('get') && !line.includes('Optional')) {
362
+ lineErrors.push({
363
+ line: lineNumber,
364
+ error: 'NullPointerException risk: Method call without null check',
365
+ suggestion: 'Add check: if (object != null) { ... } or use Optional',
366
+ severity: 'info',
367
+ references: javaStandards['null-pointer'] || []
368
+ });
369
+ }
370
+ }
371
+ */
372
+ });
373
+ }
374
+ /**
375
+ * Detect compilation errors - Cannot find symbol, type mismatches
376
+ */
377
+ detectCompilationErrors(code, lineErrors) {
378
+ const lines = code.split('\n');
379
+ lines.forEach((line, index) => {
380
+ const lineNumber = index + 1;
381
+ if (line.trim().startsWith('//'))
382
+ return;
383
+ // Detect common typos in type names (use word boundaries to avoid false positives)
384
+ const commonTypos = {
385
+ 'Strng': 'String',
386
+ 'Strin': 'String',
387
+ 'Integr': 'Integer',
388
+ 'Intger': 'Integer',
389
+ 'Booln': 'Boolean',
390
+ 'Boolen': 'Boolean',
391
+ 'ArrayLst': 'ArrayList',
392
+ 'HashMp': 'HashMap'
393
+ };
394
+ Object.entries(commonTypos).forEach(([typo, correct]) => {
395
+ // Use word boundary regex to avoid matching typo inside correct word
396
+ // e.g., don't match "Strin" inside "String"
397
+ const regex = new RegExp(`\\b${typo}\\b`);
398
+ if (regex.test(line)) {
399
+ lineErrors.push({
400
+ line: lineNumber,
401
+ error: `Compilation error: Type "${typo}" does not exist`,
402
+ suggestion: `Use "${correct}" instead of "${typo}"`,
403
+ severity: 'error',
404
+ references: references_1.javaStandards['compilation-errors'] || []
405
+ });
406
+ }
407
+ });
408
+ // DISABLED: Generates too many duplicate warnings
409
+ // Detect missing import statements (disabled - too noisy)
410
+ /*
411
+ const needsImport = [
412
+ { pattern: /\bArrayList\b/, import: 'import java.util.ArrayList;' },
413
+ { pattern: /\bHashMap\b/, import: 'import java.util.HashMap;' },
414
+ { pattern: /\bList\b/, import: 'import java.util.List;' },
415
+ { pattern: /\bMap\b/, import: 'import java.util.Map;' },
416
+ { pattern: /\bScanner\b/, import: 'import java.util.Scanner;' },
417
+ { pattern: /\bFile\b/, import: 'import java.io.File;' }
418
+ ];
419
+
420
+ needsImport.forEach(({ pattern, import: importStmt }) => {
421
+ if (pattern.test(line) && !code.includes(importStmt)) {
422
+ lineErrors.push({
423
+ line: lineNumber,
424
+ error: `Possible compilation error: Missing import`,
425
+ suggestion: `Add: ${importStmt}`,
426
+ severity: 'warning',
427
+ references: javaStandards['compilation-errors'] || []
428
+ });
429
+ }
430
+ });
431
+ */
432
+ });
433
+ }
434
+ /**
435
+ * Detect runtime exceptions - ClassCast, ArrayBounds, IllegalArgument, IllegalState
436
+ */
437
+ detectRuntimeExceptions(code, lineErrors) {
438
+ const lines = code.split('\n');
439
+ lines.forEach((line, index) => {
440
+ const lineNumber = index + 1;
441
+ if (line.trim().startsWith('//'))
442
+ return;
443
+ // Detect unsafe casting
444
+ if (line.match(/\(\w+\)\s*\w+/) && !line.includes('instanceof')) {
445
+ lineErrors.push({
446
+ line: lineNumber,
447
+ error: 'ClassCastException risk: Cast without check',
448
+ suggestion: 'Use instanceof before casting: if (obj instanceof Type) { Type t = (Type) obj; }',
449
+ severity: 'warning',
450
+ references: references_1.javaStandards['class-cast'] || []
451
+ });
452
+ }
453
+ // Detect array access without bounds checking
454
+ if (line.match(/\w+\[\d+\]/) || line.match(/\w+\[i\]/)) {
455
+ const arrayMatch = line.match(/(\w+)\[/);
456
+ if (arrayMatch) {
457
+ const arrayName = arrayMatch[1];
458
+ const prevLines = lines.slice(Math.max(0, index - 3), index);
459
+ const hasBoundsCheck = prevLines.some(l => l.includes(`${arrayName}.length`) || l.includes('< length'));
460
+ if (!hasBoundsCheck) {
461
+ lineErrors.push({
462
+ line: lineNumber,
463
+ error: 'ArrayIndexOutOfBoundsException risk: Access without bounds check',
464
+ suggestion: `Check: if (index >= 0 && index < ${arrayName}.length)`,
465
+ severity: 'info',
466
+ references: references_1.javaStandards['array-bounds'] || []
467
+ });
468
+ }
469
+ }
470
+ }
471
+ // DISABLED: Too aggressive - generates too many false positives
472
+ // Detect missing argument validation ONLY for critical methods (disabled for now)
473
+ /*
474
+ if (line.match(/public\s+\w+\s+\w+\s*\([^)]*\w+[^)]*\)/) && !line.includes('void main')) {
475
+ const nextLines = lines.slice(index + 1, Math.min(index + 5, lines.length));
476
+ const hasValidation = nextLines.some(l =>
477
+ l.includes('if') && (l.includes('== null') || l.includes('< 0') || l.includes('isEmpty'))
478
+ );
479
+
480
+ if (!hasValidation) {
481
+ lineErrors.push({
482
+ line: lineNumber,
483
+ error: 'IllegalArgumentException risk: Missing parameter validation',
484
+ suggestion: 'Add validation: if (param == null) throw new IllegalArgumentException("...");',
485
+ severity: 'info',
486
+ references: javaStandards['illegal-argument'] || []
487
+ });
488
+ }
489
+ }
490
+ */
491
+ });
492
+ }
493
+ /**
494
+ * Detect concurrency issues - ConcurrentModification, synchronized, volatile
495
+ */
496
+ detectConcurrencyIssues(code, lineErrors) {
497
+ const lines = code.split('\n');
498
+ lines.forEach((line, index) => {
499
+ const lineNumber = index + 1;
500
+ if (line.trim().startsWith('//'))
501
+ return;
502
+ // Detect modification during iteration
503
+ if (line.match(/for\s*\(\s*\w+\s+\w+\s*:\s*(\w+)\)/)) {
504
+ const iterMatch = line.match(/for\s*\(\s*\w+\s+\w+\s*:\s*(\w+)\)/);
505
+ if (iterMatch) {
506
+ const collectionName = iterMatch[1];
507
+ const nextLines = lines.slice(index + 1, Math.min(index + 10, lines.length));
508
+ nextLines.forEach((nextLine, offset) => {
509
+ if (nextLine.includes(`${collectionName}.add`) ||
510
+ nextLine.includes(`${collectionName}.remove`)) {
511
+ lineErrors.push({
512
+ line: lineNumber,
513
+ error: `ConcurrentModificationException risk: Modification of ${collectionName} during iteration`,
514
+ suggestion: `Use Iterator.remove() or iterate over a copy: new ArrayList<>(${collectionName})`,
515
+ severity: 'error',
516
+ references: references_1.javaStandards['concurrency-issues'] || []
517
+ });
518
+ }
519
+ });
520
+ }
521
+ }
522
+ // Detect missing synchronization on shared data
523
+ if (line.match(/static\s+\w+\s+\w+\s*=/) && !line.includes('final') && !line.includes('private')) {
524
+ lineErrors.push({
525
+ line: lineNumber,
526
+ error: 'Concurrency risk: Non-final static variable without synchronization',
527
+ suggestion: 'Add synchronized, use volatile, or make final if possible',
528
+ severity: 'warning',
529
+ references: references_1.javaStandards['concurrency-issues'] || []
530
+ });
531
+ }
532
+ // Detect double-checked locking without volatile
533
+ if (line.includes('synchronized') && line.includes('if')) {
534
+ const prevLines = lines.slice(Math.max(0, index - 3), index);
535
+ const hasVolatile = prevLines.some(l => l.includes('volatile'));
536
+ if (!hasVolatile) {
537
+ lineErrors.push({
538
+ line: lineNumber,
539
+ error: 'Double-checked locking pattern requires volatile',
540
+ suggestion: 'Declare the variable as volatile to ensure visibility between threads',
541
+ severity: 'warning',
542
+ references: references_1.javaStandards['concurrency-issues'] || []
543
+ });
544
+ }
545
+ }
546
+ });
547
+ }
548
+ /**
549
+ * Detect memory leaks - Unclosed resources, static collections, listeners
550
+ */
551
+ detectMemoryLeaks(code, lineErrors) {
552
+ const lines = code.split('\n');
553
+ lines.forEach((line, index) => {
554
+ const lineNumber = index + 1;
555
+ if (line.trim().startsWith('//'))
556
+ return;
557
+ // Detect static collections that might grow indefinitely
558
+ if (line.match(/static\s+.*\b(ArrayList|HashMap|HashSet|List|Map|Set)\b/) && !line.includes('final')) {
559
+ lineErrors.push({
560
+ line: lineNumber,
561
+ error: 'Memory leak risk: Static collection can grow indefinitely',
562
+ suggestion: 'Use WeakHashMap, limit size, or clear collection periodically',
563
+ severity: 'warning',
564
+ references: references_1.javaStandards['memory-errors'] || []
565
+ });
566
+ }
567
+ // Detect listeners without removal
568
+ if (line.includes('addListener') || line.includes('addEventListener')) {
569
+ lineErrors.push({
570
+ line: lineNumber,
571
+ error: 'Memory leak risk: Listener added without removal',
572
+ suggestion: 'Make sure to remove listeners when they are no longer needed',
573
+ severity: 'info',
574
+ references: references_1.javaStandards['memory-errors'] || []
575
+ });
576
+ }
577
+ // Detect potential infinite recursion
578
+ if (line.match(/public\s+\w+\s+(\w+)\s*\([^)]*\)/)) {
579
+ const methodMatch = line.match(/public\s+\w+\s+(\w+)\s*\([^)]*\)/);
580
+ if (methodMatch) {
581
+ const methodName = methodMatch[1];
582
+ const nextLines = lines.slice(index + 1, Math.min(index + 20, lines.length));
583
+ const hasRecursion = nextLines.some(l => l.includes(`${methodName}(`));
584
+ const hasBaseCase = nextLines.some(l => l.includes('return') && !l.includes(`${methodName}(`));
585
+ if (hasRecursion && !hasBaseCase) {
586
+ lineErrors.push({
587
+ line: lineNumber,
588
+ error: 'StackOverflowError risk: Recursion without apparent base case',
589
+ suggestion: 'Add stopping condition to avoid infinite recursion',
590
+ severity: 'warning',
591
+ references: references_1.javaStandards['memory-errors'] || []
592
+ });
593
+ }
594
+ }
595
+ }
596
+ });
597
+ }
598
+ /**
599
+ * Detect IO exceptions - File operations without try-with-resources
600
+ */
601
+ detectIOExceptions(code, lineErrors) {
602
+ const lines = code.split('\n');
603
+ lines.forEach((line, index) => {
604
+ const lineNumber = index + 1;
605
+ if (line.trim().startsWith('//'))
606
+ return;
607
+ // Detect file operations without try-with-resources
608
+ const ioClasses = ['FileReader', 'FileWriter', 'BufferedReader', 'BufferedWriter',
609
+ 'FileInputStream', 'FileOutputStream', 'Scanner'];
610
+ ioClasses.forEach(ioClass => {
611
+ if (line.includes(`new ${ioClass}`) && !line.includes('try')) {
612
+ const prevLines = lines.slice(Math.max(0, index - 2), index);
613
+ const hasTryWithResources = prevLines.some(l => l.includes('try ('));
614
+ if (!hasTryWithResources) {
615
+ lineErrors.push({
616
+ line: lineNumber,
617
+ error: `Resource leak risk: ${ioClass} without try-with-resources`,
618
+ suggestion: `Use try-with-resources: try (${ioClass} reader = new ${ioClass}(...)) { ... }`,
619
+ severity: 'warning',
620
+ references: references_1.javaStandards['io-exceptions'] || []
621
+ });
622
+ }
623
+ }
624
+ });
625
+ });
626
+ }
627
+ /**
628
+ * Detect SQL injection - String concatenation in SQL
629
+ *
630
+ * NOTE: SQL Injection is now detected in analyzeSecurity() with full CVSS scoring,
631
+ * compliance mapping (OWASP/CWE/PCI-DSS), and remediation details.
632
+ * This method is kept for backward compatibility but does NOT add duplicates to lineErrors.
633
+ */
634
+ detectSQLInjection(code, lineErrors) {
635
+ // SQL Injection detection moved to analyzeSecurity() for comprehensive security analysis
636
+ // Keeping this method empty to maintain the call in analyzeSyntax()
637
+ return;
638
+ }
639
+ /**
640
+ * Detect serialization issues - Unsafe deserialization
641
+ */
642
+ detectSerializationIssues(code, lineErrors) {
643
+ const lines = code.split('\n');
644
+ lines.forEach((line, index) => {
645
+ const lineNumber = index + 1;
646
+ if (line.trim().startsWith('//'))
647
+ return;
648
+ // Detect unsafe deserialization
649
+ if (line.includes('ObjectInputStream') && !line.includes('ValidatingObjectInputStream')) {
650
+ lineErrors.push({
651
+ line: lineNumber,
652
+ error: 'Security risk: Deserialization without validation',
653
+ suggestion: 'Use ValidatingObjectInputStream or validate allowed classes',
654
+ severity: 'warning',
655
+ references: references_1.javaStandards['serialization'] || []
656
+ });
657
+ }
658
+ // Detect Serializable without serialVersionUID
659
+ if (line.includes('implements Serializable')) {
660
+ const nextLines = lines.slice(index + 1, Math.min(index + 10, lines.length));
661
+ const hasSerialVersionUID = nextLines.some(l => l.includes('serialVersionUID'));
662
+ if (!hasSerialVersionUID) {
663
+ lineErrors.push({
664
+ line: lineNumber,
665
+ error: 'Serializable class without serialVersionUID',
666
+ suggestion: 'Add: private static final long serialVersionUID = 1L;',
667
+ severity: 'info',
668
+ references: references_1.javaStandards['serialization'] || []
669
+ });
670
+ }
671
+ }
672
+ });
673
+ }
674
+ /**
675
+ * Detect performance issues - Vector/Hashtable, String concat in loops, inefficient loops
676
+ */
677
+ detectPerformanceIssues(code, lineErrors) {
678
+ const lines = code.split('\n');
679
+ lines.forEach((line, index) => {
680
+ const lineNumber = index + 1;
681
+ if (line.trim().startsWith('//'))
682
+ return;
683
+ // Detect Vector usage
684
+ if (line.match(/\bVector\b/) && !line.includes('//')) {
685
+ lineErrors.push({
686
+ line: lineNumber,
687
+ error: 'Performance issue: Vector is synchronized (slow)',
688
+ suggestion: 'Use ArrayList for better performance (or CopyOnWriteArrayList if thread-safety is needed)',
689
+ severity: 'warning',
690
+ references: references_1.javaStandards['collections-performance'] || []
691
+ });
692
+ }
693
+ // Detect Hashtable usage
694
+ if (line.match(/\bHashtable\b/) && !line.includes('//')) {
695
+ lineErrors.push({
696
+ line: lineNumber,
697
+ error: 'Performance issue: Hashtable is synchronized (slow)',
698
+ suggestion: 'Use HashMap for better performance (or ConcurrentHashMap if thread-safety is needed)',
699
+ severity: 'warning',
700
+ references: references_1.javaStandards['collections-performance'] || []
701
+ });
702
+ }
703
+ // Detect string concatenation in loops
704
+ if (line.match(/for\s*\(/) || line.match(/while\s*\(/)) {
705
+ const loopStartIndex = index;
706
+ const nextLines = lines.slice(index + 1, Math.min(index + 15, lines.length));
707
+ nextLines.forEach((nextLine, offset) => {
708
+ if (nextLine.includes('+=') && (nextLine.includes('"') || nextLine.includes("'"))) {
709
+ lineErrors.push({
710
+ line: loopStartIndex + 1,
711
+ error: 'Performance issue: String concatenation in loop',
712
+ suggestion: 'Use StringBuilder: StringBuilder sb = new StringBuilder(); ... sb.append(...);',
713
+ severity: 'warning',
714
+ references: references_1.javaStandards['string-concatenation'] || []
715
+ });
716
+ }
717
+ });
718
+ }
719
+ // Detect inefficient collection iteration
720
+ if (line.match(/for\s*\(\s*int\s+i\s*=\s*0.*\.size\(\)/)) {
721
+ lineErrors.push({
722
+ line: lineNumber,
723
+ error: 'Performance issue: Inefficient iteration',
724
+ suggestion: 'Use enhanced for loop: for (Type item : collection) or forEach',
725
+ severity: 'info',
726
+ references: references_1.javaStandards['performance'] || []
727
+ });
728
+ }
729
+ });
730
+ }
731
+ /**
732
+ * Detect naming convention violations - camelCase, PascalCase, UPPER_CASE
733
+ */
734
+ detectNamingConventions(code, lineErrors) {
735
+ const lines = code.split('\n');
736
+ lines.forEach((line, index) => {
737
+ const lineNumber = index + 1;
738
+ if (line.trim().startsWith('//'))
739
+ return;
740
+ // Detect class names not starting with uppercase
741
+ const classMatch = line.match(/class\s+([a-z][a-zA-Z0-9]*)/);
742
+ if (classMatch) {
743
+ lineErrors.push({
744
+ line: lineNumber,
745
+ error: `Class name should start with uppercase: "${classMatch[1]}"`,
746
+ suggestion: `Rename to PascalCase: ${classMatch[1].charAt(0).toUpperCase() + classMatch[1].slice(1)}`,
747
+ severity: 'warning',
748
+ references: references_1.javaStandards['naming-conventions'] || []
749
+ });
750
+ }
751
+ // Detect variable names starting with uppercase (but exclude constants)
752
+ const varMatch = line.match(/\b(int|String|boolean|double|float|long|char|byte|short)\s+([A-Z]\w*)\s*=/);
753
+ if (varMatch && !line.includes('static final')) {
754
+ // Only flag if it's not a constant (constants should be UPPERCASE)
755
+ lineErrors.push({
756
+ line: lineNumber,
757
+ error: `Variable name should start with lowercase: "${varMatch[2]}"`,
758
+ suggestion: `Use camelCase: ${varMatch[2].charAt(0).toLowerCase() + varMatch[2].slice(1)}`,
759
+ severity: 'warning',
760
+ references: references_1.javaStandards['naming-conventions'] || []
761
+ });
762
+ }
763
+ // Detect constants not in UPPER_CASE
764
+ if (line.match(/static\s+final\s+\w+\s+([a-z][a-zA-Z0-9]*)\s*=/)) {
765
+ const constMatch = line.match(/static\s+final\s+\w+\s+([a-z][a-zA-Z0-9]*)\s*=/);
766
+ if (constMatch) {
767
+ lineErrors.push({
768
+ line: lineNumber,
769
+ error: `Constant should be in UPPER_CASE: "${constMatch[1]}"`,
770
+ suggestion: `Rename to: ${constMatch[1].toUpperCase().replace(/([A-Z])/g, '_$1')}`,
771
+ severity: 'info',
772
+ references: references_1.javaStandards['naming-conventions'] || []
773
+ });
774
+ }
775
+ }
776
+ });
777
+ }
778
+ /**
779
+ * Detect access modifier issues - Methods without explicit modifiers
780
+ */
781
+ detectAccessModifierIssues(code, lineErrors) {
782
+ const lines = code.split('\n');
783
+ lines.forEach((line, index) => {
784
+ const lineNumber = index + 1;
785
+ if (line.trim().startsWith('//'))
786
+ return;
787
+ // Detect methods without explicit access modifiers
788
+ if (line.match(/^\s*\w+\s+\w+\s*\(/) &&
789
+ !line.includes('public') &&
790
+ !line.includes('private') &&
791
+ !line.includes('protected')) {
792
+ lineErrors.push({
793
+ line: lineNumber,
794
+ error: 'Method without explicit access modifier (package-private)',
795
+ suggestion: 'Add public, private or protected for clarity',
796
+ severity: 'info',
797
+ references: references_1.javaStandards['access-modifiers'] || []
798
+ });
799
+ }
800
+ // Detect public fields (should use getters/setters)
801
+ if (line.match(/public\s+\w+\s+\w+\s*;/) && !line.includes('static') && !line.includes('final')) {
802
+ lineErrors.push({
803
+ line: lineNumber,
804
+ error: 'Public field detected - violates encapsulation',
805
+ suggestion: 'Make private and add getters/setters',
806
+ severity: 'warning',
807
+ references: references_1.javaStandards['access-modifiers'] || []
808
+ });
809
+ }
810
+ });
811
+ }
812
+ /**
813
+ * Detect resource leaks - Missing try-with-resources for AutoCloseable
814
+ */
815
+ detectResourceLeaks(code, lineErrors) {
816
+ const lines = code.split('\n');
817
+ lines.forEach((line, index) => {
818
+ const lineNumber = index + 1;
819
+ if (line.trim().startsWith('//'))
820
+ return;
821
+ // Detect AutoCloseable resources not in try-with-resources
822
+ const autoCloseableTypes = [
823
+ 'InputStream', 'OutputStream', 'Reader', 'Writer',
824
+ 'Connection', 'Statement', 'ResultSet',
825
+ 'Socket', 'ServerSocket', 'Channel'
826
+ ];
827
+ autoCloseableTypes.forEach(type => {
828
+ if (line.includes(`new ${type}`) || line.includes(`= ${type}`)) {
829
+ const prevLines = lines.slice(Math.max(0, index - 2), index);
830
+ const hasTryWithResources = prevLines.some(l => l.includes('try ('));
831
+ const isInTryWithResources = line.includes('try (');
832
+ if (!hasTryWithResources && !isInTryWithResources) {
833
+ lineErrors.push({
834
+ line: lineNumber,
835
+ error: `Resource leak risk: ${type} should be in try-with-resources`,
836
+ suggestion: `Use: try (${type} resource = ...) { ... }`,
837
+ severity: 'warning',
838
+ references: references_1.javaStandards['resource-leaks'] || []
839
+ });
840
+ }
841
+ }
842
+ });
843
+ });
844
+ }
845
+ /**
846
+ * Detect boxing/unboxing - Unnecessary autoboxing
847
+ */
848
+ detectBoxingUnboxing(code, lineErrors) {
849
+ const lines = code.split('\n');
850
+ lines.forEach((line, index) => {
851
+ const lineNumber = index + 1;
852
+ if (line.trim().startsWith('//'))
853
+ return;
854
+ // Detect unnecessary Integer.valueOf or new Integer
855
+ if (line.match(/Integer\.valueOf\(\d+\)/) || line.match(/new Integer\(/)) {
856
+ lineErrors.push({
857
+ line: lineNumber,
858
+ error: 'Unnecessary primitive boxing',
859
+ suggestion: 'Use primitive int directly, autoboxing when necessary',
860
+ severity: 'info',
861
+ references: references_1.javaStandards['performance'] || []
862
+ });
863
+ }
864
+ // Detect primitive wrapper in loop
865
+ if (line.match(/for\s*\(/) || line.match(/while\s*\(/)) {
866
+ const nextLines = lines.slice(index + 1, Math.min(index + 10, lines.length));
867
+ nextLines.forEach(nextLine => {
868
+ if (nextLine.match(/Integer\s+\w+\s*=/) || nextLine.match(/Double\s+\w+\s*=/)) {
869
+ lineErrors.push({
870
+ line: lineNumber,
871
+ error: 'Performance issue: Wrapper in loop causes boxing/unboxing',
872
+ suggestion: 'Use primitive type (int, double) in loops for better performance',
873
+ severity: 'info',
874
+ references: references_1.javaStandards['performance'] || []
875
+ });
876
+ }
877
+ });
878
+ }
879
+ });
880
+ }
881
+ /**
882
+ * Detect deprecated APIs - Date, Vector, Hashtable, etc.
883
+ */
884
+ detectDeprecatedAPIs(code, lineErrors) {
885
+ const lines = code.split('\n');
886
+ const deprecatedAPIs = [
887
+ { old: 'java.util.Date', new: 'java.time.LocalDate or java.time.Instant', pattern: /\bDate\b/ },
888
+ { old: 'SimpleDateFormat', new: 'DateTimeFormatter', pattern: /SimpleDateFormat/ },
889
+ { old: 'StringTokenizer', new: 'String.split()', pattern: /StringTokenizer/ },
890
+ { old: 'Thread.stop()', new: 'Thread interruption', pattern: /\.stop\(\)/ },
891
+ { old: 'Thread.suspend()', new: 'Thread interruption', pattern: /\.suspend\(\)/ },
892
+ { old: 'finalize()', new: 'try-with-resources or Cleaner API', pattern: /\bfinalize\s*\(\s*\)/ }
893
+ ];
894
+ lines.forEach((line, index) => {
895
+ const lineNumber = index + 1;
896
+ if (line.trim().startsWith('//'))
897
+ return;
898
+ deprecatedAPIs.forEach(({ old, new: newApi, pattern }) => {
899
+ if (pattern.test(line)) {
900
+ lineErrors.push({
901
+ line: lineNumber,
902
+ error: `Deprecated API: ${old} is deprecated`,
903
+ suggestion: `Use ${newApi} instead`,
904
+ severity: 'warning',
905
+ references: references_1.javaStandards['deprecated-apis'] || []
906
+ });
907
+ }
908
+ });
909
+ });
910
+ }
911
+ /**
912
+ * Detect exception handling issues - Empty catch, catching Exception/Throwable
913
+ */
914
+ detectExceptionHandling(code, lineErrors) {
915
+ const lines = code.split('\n');
916
+ lines.forEach((line, index) => {
917
+ const lineNumber = index + 1;
918
+ if (line.trim().startsWith('//'))
919
+ return;
920
+ // Detect catching generic Exception
921
+ if (line.match(/catch\s*\(\s*Exception\s+\w+\)/)) {
922
+ lineErrors.push({
923
+ line: lineNumber,
924
+ error: 'Bad practice: Generic Exception catch',
925
+ suggestion: 'Catch specific exceptions (IOException, SQLException, etc.)',
926
+ severity: 'warning',
927
+ references: references_1.javaStandards['exception-handling'] || []
928
+ });
929
+ }
930
+ // Detect catching Throwable
931
+ if (line.match(/catch\s*\(\s*Throwable\s+\w+\)/)) {
932
+ lineErrors.push({
933
+ line: lineNumber,
934
+ error: 'CRITICAL: Catching Throwable captures system errors',
935
+ suggestion: 'Never catch Throwable, use specific exceptions',
936
+ severity: 'error',
937
+ references: references_1.javaStandards['exception-handling'] || []
938
+ });
939
+ }
940
+ // Detect empty catch blocks
941
+ if (line.match(/catch\s*\([^)]+\)\s*\{\s*\}/)) {
942
+ lineErrors.push({
943
+ line: lineNumber,
944
+ error: 'CRITICAL: Empty catch block - exception ignored',
945
+ suggestion: 'Handle the exception or at least log: logger.error("...", e);',
946
+ severity: 'error',
947
+ references: references_1.javaStandards['exception-handling'] || []
948
+ });
949
+ }
950
+ // Detect printStackTrace() usage
951
+ if (line.includes('.printStackTrace()')) {
952
+ lineErrors.push({
953
+ line: lineNumber,
954
+ error: 'Bad practice: printStackTrace() in production',
955
+ suggestion: 'Use a logger: logger.error("Error occurred", e);',
956
+ severity: 'info',
957
+ references: references_1.javaStandards['exception-handling'] || []
958
+ });
959
+ }
960
+ });
961
+ }
962
+ /**
963
+ * Detect duplicate variable declarations - SYNTAX ERROR (Error 26)
964
+ *
965
+ * Tracks variable declarations within method scope and detects when
966
+ * the same variable name is declared twice, which is a compilation error.
967
+ */
968
+ detectDuplicateVariables(code, lineErrors) {
969
+ const lines = code.split('\n');
970
+ const variablesByMethod = new Map();
971
+ let currentMethod = null;
972
+ let braceDepth = 0;
973
+ let methodBraceDepth = 0;
974
+ lines.forEach((line, index) => {
975
+ const lineNumber = index + 1;
976
+ const trimmed = line.trim();
977
+ // Skip comments
978
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
979
+ return;
980
+ // CRITICAL FIX: Use CodeCleaner to remove comments (handles strings correctly)
981
+ // Old approach: trimmed.split('//')[0] - doesn't handle strings
982
+ // Example: String url = "https://example.com"; <- split('//')[0] would break this!
983
+ const codeWithoutComment = code_cleaner_1.CodeCleaner.removeLineComments(line, 'java');
984
+ if (!codeWithoutComment.trim())
985
+ return;
986
+ // Track method entry
987
+ if (codeWithoutComment.match(/(?:public|private|protected|static|\s)+\s+\w+\s+(\w+)\s*\([^)]*\)\s*\{/)) {
988
+ const methodMatch = codeWithoutComment.match(/\s(\w+)\s*\(/);
989
+ if (methodMatch) {
990
+ currentMethod = methodMatch[1] + '_' + lineNumber; // Unique ID per method
991
+ variablesByMethod.set(currentMethod, new Map());
992
+ methodBraceDepth = braceDepth;
993
+ }
994
+ }
995
+ // Track brace depth
996
+ for (const char of codeWithoutComment) {
997
+ if (char === '{')
998
+ braceDepth++;
999
+ if (char === '}') {
1000
+ braceDepth--;
1001
+ // Exit method when we close its brace
1002
+ if (currentMethod && braceDepth === methodBraceDepth) {
1003
+ currentMethod = null;
1004
+ }
1005
+ }
1006
+ }
1007
+ // Detect variable declarations inside methods
1008
+ // Pattern: type variableName = ... OR type variableName;
1009
+ // Common types: int, String, boolean, double, float, long, char, byte, short, Object, List, Map, etc.
1010
+ if (currentMethod && codeWithoutComment.match(/\b(int|String|boolean|double|float|long|char|byte|short|Integer|Double|Boolean|Object|List|Map|Set|Array|File)\s+(\w+)\s*(=|;)/)) {
1011
+ const varMatch = codeWithoutComment.match(/\b(int|String|boolean|double|float|long|char|byte|short|Integer|Double|Boolean|Object|List|Map|Set|Array|File)\s+(\w+)\s*(=|;)/);
1012
+ if (varMatch) {
1013
+ const varType = varMatch[1];
1014
+ const varName = varMatch[2];
1015
+ const variables = variablesByMethod.get(currentMethod);
1016
+ // Check if this variable was already declared in this method
1017
+ if (variables.has(varName)) {
1018
+ const firstDeclarationLine = variables.get(varName);
1019
+ lineErrors.push({
1020
+ line: lineNumber,
1021
+ error: `Syntax Error: Variable "${varName}" is already defined on line ${firstDeclarationLine}`,
1022
+ suggestion: `Remove duplicate declaration or rename variable (e.g., ${varName}2)`,
1023
+ severity: 'error',
1024
+ references: references_1.javaStandards['compilation-errors'] || []
1025
+ });
1026
+ }
1027
+ else {
1028
+ // Track this variable declaration
1029
+ variables.set(varName, lineNumber);
1030
+ }
1031
+ }
1032
+ }
1033
+ });
1034
+ }
1035
+ /**
1036
+ * Detect method naming issues - Methods not in camelCase (e.g., Process_User_Data)
1037
+ */
1038
+ detectMethodNamingIssues(code, lineErrors) {
1039
+ const lines = code.split('\n');
1040
+ lines.forEach((line, index) => {
1041
+ const lineNumber = index + 1;
1042
+ const trimmed = line.trim();
1043
+ // Skip comments
1044
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
1045
+ return;
1046
+ // Detect method declarations with snake_case or PascalCase names
1047
+ // Pattern: public/private/protected returnType methodName(...)
1048
+ const methodMatch = line.match(/(?:public|private|protected|static|\s)+\s+(\w+)\s+([A-Z_][a-zA-Z0-9_]*)\s*\(/);
1049
+ if (methodMatch && !line.includes('class ')) {
1050
+ const methodName = methodMatch[2];
1051
+ // Check for snake_case (contains underscore)
1052
+ if (methodName.includes('_')) {
1053
+ lineErrors.push({
1054
+ line: lineNumber,
1055
+ error: `Method name should be camelCase, not snake_case: "${methodName}"`,
1056
+ suggestion: `Rename to camelCase: ${methodName.toLowerCase().replace(/_(.)/g, (_, c) => c.toUpperCase())}`,
1057
+ severity: 'warning',
1058
+ references: references_1.javaStandards['naming-conventions'] || []
1059
+ });
1060
+ }
1061
+ // Check for PascalCase (starts with uppercase, no underscore)
1062
+ else if (methodName[0] === methodName[0].toUpperCase() && !methodName.includes('_')) {
1063
+ lineErrors.push({
1064
+ line: lineNumber,
1065
+ error: `Method name should be camelCase, not PascalCase: "${methodName}"`,
1066
+ suggestion: `Rename to camelCase: ${methodName[0].toLowerCase() + methodName.slice(1)}`,
1067
+ severity: 'warning',
1068
+ references: references_1.javaStandards['naming-conventions'] || []
1069
+ });
1070
+ }
1071
+ }
1072
+ });
1073
+ }
1074
+ /**
1075
+ * Detect magic numbers - Numeric literals that should be named constants
1076
+ */
1077
+ detectMagicNumbers(code, lineErrors) {
1078
+ const lines = code.split('\n');
1079
+ let inMultiLineComment = false;
1080
+ lines.forEach((line, index) => {
1081
+ const lineNumber = index + 1;
1082
+ const trimmed = line.trim();
1083
+ // Track multi-line comment blocks (/* ... */)
1084
+ if (trimmed.includes('/*')) {
1085
+ inMultiLineComment = true;
1086
+ }
1087
+ if (trimmed.includes('*/')) {
1088
+ inMultiLineComment = false;
1089
+ return; // Skip the line with */
1090
+ }
1091
+ // Skip comments, constants declarations, and array indices
1092
+ if (trimmed.startsWith('//') || inMultiLineComment ||
1093
+ line.includes('static final') || line.includes('final static'))
1094
+ return;
1095
+ // Remove string literals to avoid detecting numbers inside strings
1096
+ // Example: "Java OWASP 2025" should NOT flag 2025 as magic number
1097
+ const lineWithoutStrings = trimmed.replace(/"[^"]*"/g, '').replace(/'[^']*'/g, '');
1098
+ // Detect magic numbers: integers >= 10 (excluding 0, 1, -1 which are universal)
1099
+ // Pattern: numbers not in declarations or array indices
1100
+ const magicNumberPattern = /\b(1[0-9]|[2-9][0-9]|[1-9][0-9]{2,})\b/g;
1101
+ const matches = [...lineWithoutStrings.matchAll(magicNumberPattern)];
1102
+ if (matches.length > 0) {
1103
+ // Check if it's in a context where magic numbers are acceptable
1104
+ const isArrayIndex = lineWithoutStrings.match(/\[\s*\d+\s*\]/);
1105
+ const isConstantDecl = lineWithoutStrings.match(/=\s*\d+\s*;/) && line.includes('final');
1106
+ // Skip cryptographic operations (SecureRandom, BigInteger, MessageDigest, etc.)
1107
+ const isCryptoOperation = trimmed.match(/SecureRandom|BigInteger|MessageDigest|Cipher|KeyGenerator|SecretKey/i);
1108
+ if (!isArrayIndex && !isConstantDecl && !isCryptoOperation) {
1109
+ matches.forEach(match => {
1110
+ const number = match[0];
1111
+ lineErrors.push({
1112
+ line: lineNumber,
1113
+ error: `Magic number detected: ${number}`,
1114
+ suggestion: `Replace with a named constant: private static final int MEANINGFUL_NAME = ${number};`,
1115
+ severity: 'info',
1116
+ references: references_1.javaStandards['naming-conventions'] || []
1117
+ });
1118
+ });
1119
+ }
1120
+ }
1121
+ });
1122
+ }
1123
+ /**
1124
+ * Detect God Classes - Classes with too many methods (violates SRP)
1125
+ */
1126
+ detectGodClasses(code, lineErrors) {
1127
+ const lines = code.split('\n');
1128
+ // Count methods per class
1129
+ let currentClass = null;
1130
+ lines.forEach((line, index) => {
1131
+ const lineNumber = index + 1;
1132
+ const trimmed = line.trim();
1133
+ // Skip comments
1134
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
1135
+ return;
1136
+ // Detect class declaration
1137
+ const classMatch = line.match(/(?:public|private|protected)?\s*class\s+(\w+)/);
1138
+ if (classMatch) {
1139
+ // Report previous class if it was a God class
1140
+ if (currentClass && currentClass.methods > 10) {
1141
+ lineErrors.push({
1142
+ line: currentClass.line,
1143
+ error: `God Class detected: ${currentClass.name} has ${currentClass.methods} methods (>10)`,
1144
+ suggestion: 'Refactor into smaller, focused classes following Single Responsibility Principle',
1145
+ severity: 'warning',
1146
+ references: references_1.javaStandards['naming-conventions'] || []
1147
+ });
1148
+ }
1149
+ // Start tracking new class
1150
+ currentClass = { name: classMatch[1], line: lineNumber, methods: 0 };
1151
+ }
1152
+ // Count methods in current class
1153
+ if (currentClass && line.match(/(?:public|private|protected)\s+\w+\s+\w+\s*\(/)) {
1154
+ currentClass.methods++;
1155
+ }
1156
+ });
1157
+ // Check last class
1158
+ if (currentClass) {
1159
+ const classInfo = currentClass;
1160
+ if (classInfo.methods > 10) {
1161
+ lineErrors.push({
1162
+ line: classInfo.line,
1163
+ error: `God Class detected: ${classInfo.name} has ${classInfo.methods} methods (>10)`,
1164
+ suggestion: 'Refactor into smaller, focused classes following Single Responsibility Principle',
1165
+ severity: 'warning',
1166
+ references: references_1.javaStandards['naming-conventions'] || []
1167
+ });
1168
+ }
1169
+ }
1170
+ }
1171
+ /**
1172
+ * Detect methods with too many parameters (>7 is a code smell)
1173
+ * Methods with many parameters are hard to test, maintain, and understand.
1174
+ * Consider using parameter objects or builder pattern.
1175
+ */
1176
+ detectTooManyParameters(code, lineErrors) {
1177
+ const lines = code.split('\n');
1178
+ const MAX_PARAMETERS = 7; // Industry standard threshold
1179
+ // FIX (Dec 12, 2025): Handle multi-line method signatures
1180
+ // Previous: Only checked single-line method declarations
1181
+ // Now: Collect method signature across multiple lines until closing )
1182
+ lines.forEach((line, index) => {
1183
+ const lineNumber = index + 1;
1184
+ const trimmed = line.trim();
1185
+ // Skip comments
1186
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
1187
+ return;
1188
+ // Detect method declaration start: [access modifier] returnType methodName(
1189
+ // Pattern: public void methodName( or private String getValue(
1190
+ const methodStartMatch = line.match(/(?:public|private|protected)\s+\w+\s+(\w+)\s*\(/);
1191
+ if (methodStartMatch) {
1192
+ const methodName = methodStartMatch[1];
1193
+ // Collect full method signature across multiple lines until we find closing )
1194
+ let fullSignature = line;
1195
+ let currentIndex = index;
1196
+ // If line doesn't have closing ), continue collecting from next lines
1197
+ let openParens = (fullSignature.match(/\(/g) || []).length;
1198
+ let closeParens = (fullSignature.match(/\)/g) || []).length;
1199
+ while (openParens > closeParens && currentIndex < lines.length - 1) {
1200
+ currentIndex++;
1201
+ const nextLine = lines[currentIndex];
1202
+ fullSignature += ' ' + nextLine;
1203
+ openParens += (nextLine.match(/\(/g) || []).length;
1204
+ closeParens += (nextLine.match(/\)/g) || []).length;
1205
+ }
1206
+ // Now extract parameters from full signature
1207
+ const fullMethodMatch = fullSignature.match(/\(([^)]*)\)/);
1208
+ if (fullMethodMatch) {
1209
+ const paramsString = fullMethodMatch[1].trim();
1210
+ // Skip empty parameter lists
1211
+ if (!paramsString)
1212
+ return;
1213
+ // Count parameters by splitting on commas
1214
+ // Need to be careful about generics like List<String, Integer>
1215
+ // Simple heuristic: count commas not inside <> brackets
1216
+ let paramCount = 1; // Start at 1 if we have any parameters
1217
+ let depth = 0;
1218
+ for (const char of paramsString) {
1219
+ if (char === '<')
1220
+ depth++;
1221
+ else if (char === '>')
1222
+ depth--;
1223
+ else if (char === ',' && depth === 0)
1224
+ paramCount++;
1225
+ }
1226
+ if (paramCount > MAX_PARAMETERS) {
1227
+ lineErrors.push({
1228
+ line: lineNumber,
1229
+ error: `Method has too many parameters: ${methodName} has ${paramCount} parameters (max recommended: ${MAX_PARAMETERS})`,
1230
+ suggestion: 'Refactor using parameter objects, builder pattern, or method decomposition',
1231
+ severity: 'warning',
1232
+ references: references_1.javaStandards['naming-conventions'] || []
1233
+ });
1234
+ }
1235
+ }
1236
+ }
1237
+ });
1238
+ }
1239
+ /**
1240
+ * Detect string comparison using == instead of .equals()
1241
+ * IMPORTANT: This is a QUALITY/LOGIC issue, NOT a syntax error
1242
+ * Using == compares object references, not string content
1243
+ */
1244
+ detectStringComparisonWithEquals(code, lineErrors) {
1245
+ const lines = code.split('\n');
1246
+ lines.forEach((line, index) => {
1247
+ const lineNumber = index + 1;
1248
+ const trimmed = line.trim();
1249
+ // Skip comments
1250
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
1251
+ return;
1252
+ // Remove comments from line for analysis
1253
+ const codeWithoutComment = code_cleaner_1.CodeCleaner.removeLineComments(line, 'java');
1254
+ if (!codeWithoutComment.trim())
1255
+ return;
1256
+ // Detect == or != with string literals or String variables
1257
+ // Pattern 1: variable == "string literal"
1258
+ // Pattern 2: "string literal" == variable
1259
+ // Pattern 3: stringVar == anotherStringVar (if variables look like strings)
1260
+ // Check for == or != with string literals
1261
+ const stringLiteralPattern = /(\w+)\s*(==|!=)\s*"([^"]*)"|"([^"]*)"\s*(==|!=)\s*(\w+)/;
1262
+ const match = codeWithoutComment.match(stringLiteralPattern);
1263
+ if (match) {
1264
+ const operator = match[2] || match[5];
1265
+ const suggestion = operator === '==' ? '.equals()' : '!.equals()';
1266
+ lineErrors.push({
1267
+ line: lineNumber,
1268
+ error: `String comparison using ${operator} instead of .equals() - compares object references, not content`,
1269
+ suggestion: `Use ${suggestion} method for string comparison: variable.equals("string")`,
1270
+ severity: 'warning', // QUALITY issue, not syntax error
1271
+ references: references_1.javaStandards['naming-conventions'] || []
1272
+ });
1273
+ }
1274
+ });
1275
+ }
1276
+ /**
1277
+ * Detect empty catch blocks - Multi-line empty catch blocks
1278
+ */
1279
+ detectEmptyCatchBlocks(code, lineErrors) {
1280
+ const lines = code.split('\n');
1281
+ for (let i = 0; i < lines.length; i++) {
1282
+ const line = lines[i];
1283
+ const trimmed = line.trim();
1284
+ // Skip comments
1285
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
1286
+ continue;
1287
+ // Detect catch block opening
1288
+ if (trimmed.match(/catch\s*\([^)]+\)\s*\{/)) {
1289
+ // Check if it's a single-line empty catch (already detected elsewhere)
1290
+ if (trimmed.match(/catch\s*\([^)]+\)\s*\{\s*\}/)) {
1291
+ continue; // Already handled by detectExceptionHandling
1292
+ }
1293
+ // Check next few lines for empty catch block
1294
+ let braceDepth = 1;
1295
+ let isEmpty = true;
1296
+ let j = i + 1;
1297
+ while (j < lines.length && braceDepth > 0) {
1298
+ const nextLine = lines[j].trim();
1299
+ // Skip comments
1300
+ if (!nextLine.startsWith('//') && !nextLine.startsWith('/*') && nextLine.length > 0) {
1301
+ // Count braces
1302
+ for (const char of nextLine) {
1303
+ if (char === '{')
1304
+ braceDepth++;
1305
+ if (char === '}')
1306
+ braceDepth--;
1307
+ }
1308
+ // If there's any code (not just closing brace), it's not empty
1309
+ if (nextLine !== '}' && !nextLine.startsWith('}')) {
1310
+ isEmpty = false;
1311
+ break;
1312
+ }
1313
+ }
1314
+ j++;
1315
+ }
1316
+ if (isEmpty && braceDepth === 0) {
1317
+ lineErrors.push({
1318
+ line: i + 1,
1319
+ error: 'Empty catch block detected - exceptions should not be silently ignored',
1320
+ suggestion: 'Handle the exception: log it, rethrow it, or at least add a comment explaining why it\'s safe to ignore',
1321
+ severity: 'error',
1322
+ references: references_1.javaStandards['exception-handling'] || []
1323
+ });
1324
+ }
1325
+ }
1326
+ }
1327
+ }
1328
+ /**
1329
+ * Detect uninitialized variables - Variables declared but not initialized
1330
+ */
1331
+ detectUninitializedVariables(code, lineErrors) {
1332
+ const lines = code.split('\n');
1333
+ lines.forEach((line, index) => {
1334
+ const lineNumber = index + 1;
1335
+ const trimmed = line.trim();
1336
+ // Skip comments
1337
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
1338
+ return;
1339
+ // Detect variable declaration without initialization
1340
+ // Pattern: type variableName; (without = assignment)
1341
+ const uninitMatch = line.match(/\b(int|String|boolean|double|float|long|char|byte|short|Integer|Double|Boolean|Object|List|Map|Set|Array)\s+(\w+)\s*;/);
1342
+ if (uninitMatch && !line.includes('=')) {
1343
+ const varType = uninitMatch[1];
1344
+ const varName = uninitMatch[2];
1345
+ // SPRING FRAMEWORK FIX (2025-11-22): Skip dependency injection annotated fields
1346
+ // Spring annotations like @Value, @Autowired, @Inject initialize fields at runtime
1347
+ // Checking previous line for these annotations to avoid false positives
1348
+ const prevLine = index > 0 ? lines[index - 1].trim() : '';
1349
+ const springAnnotations = ['@Value(', '@Autowired', '@Inject', '@Resource'];
1350
+ if (springAnnotations.some(annotation => prevLine.includes(annotation))) {
1351
+ // This field is initialized by Spring/Jakarta - skip uninitialized check
1352
+ return;
1353
+ }
1354
+ // Check if variable is used before initialization in next lines
1355
+ const nextLines = lines.slice(index + 1, Math.min(index + 10, lines.length));
1356
+ let isUsedBeforeInit = false;
1357
+ let isInitialized = false;
1358
+ for (const nextLine of nextLines) {
1359
+ // Skip comments
1360
+ if (nextLine.trim().startsWith('//'))
1361
+ continue;
1362
+ // Check if variable is assigned
1363
+ if (nextLine.match(new RegExp(`${varName}\\s*=`))) {
1364
+ isInitialized = true;
1365
+ break;
1366
+ }
1367
+ // Check if variable is used (in expression, method call, etc.)
1368
+ if (nextLine.includes(varName) && !nextLine.match(new RegExp(`\\b${varType}\\s+${varName}\\b`))) {
1369
+ isUsedBeforeInit = true;
1370
+ break;
1371
+ }
1372
+ }
1373
+ if (isUsedBeforeInit && !isInitialized) {
1374
+ lineErrors.push({
1375
+ line: lineNumber,
1376
+ error: `Variable "${varName}" may not be initialized before use`,
1377
+ suggestion: `Initialize variable: ${varType} ${varName} = null; // or appropriate default value`,
1378
+ severity: 'error',
1379
+ references: references_1.javaStandards['compilation-errors'] || []
1380
+ });
1381
+ }
1382
+ }
1383
+ });
1384
+ }
1385
+ /**
1386
+ * Detect missing return statements - Non-void methods without return in all paths
1387
+ */
1388
+ detectMissingReturnStatements(code, lineErrors) {
1389
+ const lines = code.split('\n');
1390
+ for (let i = 0; i < lines.length; i++) {
1391
+ const line = lines[i];
1392
+ const trimmed = line.trim();
1393
+ // Skip comments
1394
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
1395
+ continue;
1396
+ // Detect non-void method declaration
1397
+ const methodMatch = line.match(/(?:public|private|protected)\s+(\w+)\s+(\w+)\s*\([^)]*\)\s*\{/);
1398
+ if (methodMatch && methodMatch[1] !== 'void') {
1399
+ const returnType = methodMatch[1];
1400
+ const methodName = methodMatch[2];
1401
+ // Look for if-else blocks without return in all branches
1402
+ let hasIfElse = false;
1403
+ let hasReturnInIf = false;
1404
+ let hasReturnInElse = false;
1405
+ let braceDepth = 1;
1406
+ let j = i + 1;
1407
+ while (j < lines.length && braceDepth > 0) {
1408
+ const nextLine = lines[j].trim();
1409
+ // Count braces
1410
+ for (const char of nextLine) {
1411
+ if (char === '{')
1412
+ braceDepth++;
1413
+ if (char === '}')
1414
+ braceDepth--;
1415
+ }
1416
+ // Check for if-else
1417
+ if (nextLine.startsWith('if ') || nextLine.startsWith('if(')) {
1418
+ hasIfElse = true;
1419
+ }
1420
+ // Check for return in if block
1421
+ if (hasIfElse && nextLine.includes('return') && braceDepth === 2) {
1422
+ hasReturnInIf = true;
1423
+ }
1424
+ // Check for else
1425
+ if (nextLine.startsWith('else') || nextLine.includes('} else')) {
1426
+ // Check for return in else block
1427
+ const elseStart = j;
1428
+ let elseDepth = braceDepth;
1429
+ for (let k = elseStart; k < Math.min(elseStart + 10, lines.length); k++) {
1430
+ if (lines[k].includes('return')) {
1431
+ hasReturnInElse = true;
1432
+ break;
1433
+ }
1434
+ }
1435
+ }
1436
+ j++;
1437
+ }
1438
+ // If there's an if-else but missing return in else branch
1439
+ if (hasIfElse && hasReturnInIf && !hasReturnInElse) {
1440
+ lineErrors.push({
1441
+ line: i + 1,
1442
+ error: `Method "${methodName}" may not return a value in all code paths`,
1443
+ suggestion: `Add return statement in else branch: return ${returnType === 'boolean' ? 'false' : returnType === 'int' ? '0' : 'null'};`,
1444
+ severity: 'error',
1445
+ references: references_1.javaStandards['compilation-errors'] || []
1446
+ });
1447
+ }
1448
+ }
1449
+ }
1450
+ }
1451
+ /**
1452
+ * Detect invalid modifier order - Incorrect order (e.g., "static public" instead of "public static")
1453
+ */
1454
+ detectInvalidModifierOrder(code, lineErrors) {
1455
+ const lines = code.split('\n');
1456
+ lines.forEach((line, index) => {
1457
+ const lineNumber = index + 1;
1458
+ const trimmed = line.trim();
1459
+ // Skip comments
1460
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*'))
1461
+ return;
1462
+ // Detect invalid modifier order
1463
+ // Correct order: [access modifier] [static] [final] [other modifiers]
1464
+ // Invalid patterns:
1465
+ // - static/final/abstract before access modifiers
1466
+ const invalidOrderPatterns = [
1467
+ { pattern: /\b(static|final|abstract|synchronized|native|strictfp)\s+(public|private|protected)\b/, correct: 'public static' },
1468
+ { pattern: /\bfinal\s+static\b/, correct: 'static final' }
1469
+ ];
1470
+ invalidOrderPatterns.forEach(({ pattern, correct }) => {
1471
+ if (pattern.test(line)) {
1472
+ const match = line.match(pattern);
1473
+ if (match) {
1474
+ lineErrors.push({
1475
+ line: lineNumber,
1476
+ error: `Invalid modifier order: "${match[0]}"`,
1477
+ suggestion: `Use correct order: ${correct}`,
1478
+ severity: 'warning',
1479
+ references: references_1.javaStandards['naming-conventions'] || []
1480
+ });
1481
+ }
1482
+ }
1483
+ });
1484
+ });
1485
+ }
1486
+ analyzeQuality(code, result) {
1487
+ const issues = [];
1488
+ // Check for class names starting with lowercase
1489
+ const classes = code.match(/class\s+([a-z][a-zA-Z]*)/g);
1490
+ if (classes) {
1491
+ issues.push({
1492
+ type: 'warning',
1493
+ message: 'Class names should start with uppercase (PascalCase)',
1494
+ severity: 'medium'
1495
+ });
1496
+ result.quality.score -= 5;
1497
+ }
1498
+ // Check for very long methods
1499
+ const methods = code.match(/public\s+\w+\s+\w+\s*\([^)]*\)\s*\{[^}]+\}/g);
1500
+ if (methods) {
1501
+ methods.forEach(method => {
1502
+ const lines = method.split('\n').length;
1503
+ if (lines > 20) {
1504
+ issues.push({
1505
+ type: 'warning',
1506
+ message: 'Method too long - consider refactoring',
1507
+ severity: 'medium'
1508
+ });
1509
+ result.quality.score -= 5;
1510
+ }
1511
+ });
1512
+ }
1513
+ // Check for magic numbers usage
1514
+ const magicNumbers = code.match(/[^a-zA-Z_]\d{2,}/g);
1515
+ if (magicNumbers && magicNumbers.length > 2) {
1516
+ issues.push({
1517
+ type: 'info',
1518
+ message: 'Consider using named constants instead of magic numbers',
1519
+ severity: 'low'
1520
+ });
1521
+ result.quality.score -= 3;
1522
+ }
1523
+ // Check for missing JavaDoc in public methods
1524
+ const publicMethods = code.match(/public\s+\w+\s+\w+/g);
1525
+ const javadocCount = (code.match(/\/\*\*[\s\S]*?\*\//g) || []).length;
1526
+ if (publicMethods && publicMethods.length > javadocCount) {
1527
+ issues.push({
1528
+ type: 'info',
1529
+ message: 'Add JavaDoc documentation to public methods',
1530
+ severity: 'low'
1531
+ });
1532
+ result.quality.score -= 2;
1533
+ }
1534
+ result.quality.issues = issues;
1535
+ result.quality.score = Math.max(0, result.quality.score);
1536
+ }
1537
+ analyzePerformance(code, result) {
1538
+ const suggestions = [];
1539
+ // Check for string concatenation in loops
1540
+ if (code.match(/for.*\{[\s\S]*?\+\s*=.*"/)) {
1541
+ suggestions.push('Use StringBuilder for concatenation in loops');
1542
+ result.performance.score -= 15;
1543
+ }
1544
+ // Check Vector vs ArrayList usage
1545
+ if (code.includes('Vector')) {
1546
+ suggestions.push('Use ArrayList instead of Vector for better performance');
1547
+ result.performance.score -= 8;
1548
+ }
1549
+ // Check Hashtable vs HashMap usage
1550
+ if (code.includes('Hashtable')) {
1551
+ suggestions.push('Use HashMap instead of Hashtable (unless synchronization is needed)');
1552
+ result.performance.score -= 8;
1553
+ }
1554
+ // Check for unnecessary loops
1555
+ if (code.match(/for\s*\([^)]+\)\s*\{\s*if\s*\([^)]+\)\s*\{[\s\S]*?\}\s*\}/)) {
1556
+ suggestions.push('Consider using streams with filter() for better readability');
1557
+ result.performance.score -= 5;
1558
+ }
1559
+ // Check System.out.println usage in loops
1560
+ if (code.match(/for.*\{[\s\S]*?System\.out\.println/)) {
1561
+ suggestions.push('Avoid I/O in loops for better performance');
1562
+ result.performance.score -= 10;
1563
+ }
1564
+ result.performance.suggestions = suggestions;
1565
+ result.performance.score = Math.max(0, result.performance.score);
1566
+ }
1567
+ /**
1568
+ * Analyzes Java code for security vulnerabilities using modular security checks
1569
+ *
1570
+ * This method coordinates all security analysis by delegating to specialized modules:
1571
+ * - Injection attacks (SQL, Command, LDAP, XPath)
1572
+ * - Deserialization and XXE vulnerabilities
1573
+ * - Hardcoded credentials detection
1574
+ * - Cryptographic validation (weak algorithms, insecure random)
1575
+ * - File operation security (path traversal, upload validation)
1576
+ * - Unsafe patterns (reflection, NPE, exception handling)
1577
+ * - Code quality issues (God classes, debug output)
1578
+ *
1579
+ * All checks are performed in parallel for optimal performance.
1580
+ */
1581
+ analyzeSecurity(code, result) {
1582
+ const lines = code.split('\n');
1583
+ // Run all modular security checks
1584
+ const vulnerabilities = [
1585
+ ...(0, injection_attacks_1.checkInjectionAttacks)(lines),
1586
+ ...(0, deserialization_xxe_1.checkDeserializationAndXXE)(lines),
1587
+ ...(0, hardcoded_credentials_1.checkHardcodedCredentials)(lines),
1588
+ ...(0, crypto_validation_1.checkCryptoValidation)(lines),
1589
+ ...(0, file_operations_1.checkFileOperations)(lines),
1590
+ ...(0, unsafe_patterns_1.checkUnsafePatterns)(lines),
1591
+ ...(0, code_quality_1.checkCodeQuality)(lines, code),
1592
+ ...(0, framework_security_1.checkFrameworkSecurity)(lines, code),
1593
+ // OWASP A02:2025 - Security Misconfiguration (NEW - Phase 7B)
1594
+ ...(0, security_misconfiguration_1.checkSecurityMisconfiguration)(lines),
1595
+ // OWASP A10:2025 - Mishandling of Exceptional Conditions (NEW - Phase 7B)
1596
+ ...(0, exception_handling_1.checkExceptionHandling)(lines),
1597
+ // OWASP A03:2025 - Software Supply Chain Failures (Enhanced - Phase 7B)
1598
+ ...(0, enhanced_supply_chain_1.checkEnhancedSupplyChain)(lines),
1599
+ // OWASP A01:2025 - Broken Access Control (Phase 7B Day 8)
1600
+ ...(0, access_control_1.checkAccessControl)(lines),
1601
+ // OWASP A06:2025 - Insecure Design (Phase 7B Day 9)
1602
+ ...(0, insecure_design_1.checkInsecureDesign)(lines),
1603
+ // OWASP A09:2025 - Security Logging and Monitoring Failures (Phase 7B Day 9)
1604
+ ...(0, logging_failures_1.checkLoggingFailures)(lines)
1605
+ ];
1606
+ // Secrets Detection (Phase 1.5, Week 1)
1607
+ const secretsAnalyzer = (0, secrets_analyzer_1.createSecretsAnalyzer)();
1608
+ vulnerabilities.push(...secretsAnalyzer.analyzeCode(code, 'unknown.java', 'java'));
1609
+ // =============================================================================
1610
+ // DEDUPLICATION: Remove duplicate vulnerabilities on same line
1611
+ // =============================================================================
1612
+ // Fix for Beta Testing Issue: Deserialization and XXE reported twice
1613
+ // Multiple checks can flag the same line (e.g., different detection patterns)
1614
+ // Solution: Keep only the vulnerability with highest CVSS score per line
1615
+ result.security.vulnerabilities = this.deduplicateVulnerabilities(vulnerabilities);
1616
+ }
1617
+ /**
1618
+ * Deduplicate vulnerabilities that appear on the same line
1619
+ *
1620
+ * Beta Testing Fix (Dec 9, 2025):
1621
+ * - Deserialization reported twice (line 56, CVSS 9.8 and 5.0)
1622
+ * - XXE reported twice (lines 50 and 52)
1623
+ *
1624
+ * Strategy: For each line with multiple vulnerabilities of similar type,
1625
+ * keep only the one with the highest CVSS score.
1626
+ *
1627
+ * @param vulnerabilities - Array of all detected vulnerabilities
1628
+ * @returns Deduplicated array with highest CVSS per line
1629
+ */
1630
+ /**
1631
+ * P1-5: Generic deduplication for ALL vulnerability types (Dec 30, 2025)
1632
+ * Previous: Only handled deserialization and XXE
1633
+ * Now: Handles all duplicates using category-based deduplication
1634
+ */
1635
+ deduplicateVulnerabilities(vulnerabilities) {
1636
+ // P1-5: Use category-based deduplication (line + category as unique key)
1637
+ const getCategory = (message) => {
1638
+ const lower = message.toLowerCase();
1639
+ if (lower.includes('hardcoded credential'))
1640
+ return 'hardcoded-credential';
1641
+ if (lower.includes('sql injection'))
1642
+ return 'sql-injection';
1643
+ if (lower.includes('command injection'))
1644
+ return 'command-injection';
1645
+ if (lower.includes('deserialization'))
1646
+ return 'deserialization';
1647
+ if (lower.includes('xxe') || lower.includes('xml external entity'))
1648
+ return 'xxe';
1649
+ if (lower.includes('path traversal'))
1650
+ return 'path-traversal';
1651
+ if (lower.includes('ldap injection'))
1652
+ return 'ldap-injection';
1653
+ if (lower.includes('xss') || lower.includes('cross-site scripting'))
1654
+ return 'xss';
1655
+ if (lower.includes('ssrf'))
1656
+ return 'ssrf';
1657
+ if (lower.includes('weak hash') || lower.includes('md5') || lower.includes('sha1'))
1658
+ return 'weak-hash';
1659
+ if (lower.includes('insecure random'))
1660
+ return 'insecure-random';
1661
+ if (lower.includes('missing csrf'))
1662
+ return 'missing-csrf';
1663
+ if (lower.includes('open redirect'))
1664
+ return 'open-redirect';
1665
+ if (lower.includes('missing authentication'))
1666
+ return 'missing-authentication';
1667
+ if (lower.includes('logging'))
1668
+ return 'logging';
1669
+ // Fallback: use first 30 chars as category
1670
+ return message.substring(0, 30);
1671
+ };
1672
+ const uniqueMap = new Map();
1673
+ vulnerabilities.forEach(vuln => {
1674
+ const line = vuln.line || 0;
1675
+ const category = getCategory(vuln.message || '');
1676
+ const key = `${line}:${category}`;
1677
+ const existing = uniqueMap.get(key);
1678
+ if (!existing) {
1679
+ uniqueMap.set(key, vuln);
1680
+ }
1681
+ else {
1682
+ // Keep higher CVSS score
1683
+ const existingScore = existing.cvssScore || 0;
1684
+ const currentScore = vuln.cvssScore || 0;
1685
+ if (currentScore > existingScore) {
1686
+ uniqueMap.set(key, vuln);
1687
+ }
1688
+ }
1689
+ });
1690
+ return Array.from(uniqueMap.values());
1691
+ }
1692
+ calculateMetrics(code, result) {
1693
+ const lines = code.split('\n');
1694
+ result.metrics.lines = lines.length;
1695
+ const methods = (code.match(/public\s+\w+\s+\w+\s*\(/g) || []).length;
1696
+ result.metrics.functions = methods;
1697
+ // Calculate cyclomatic complexity - Java
1698
+ let complexity = 1;
1699
+ const javaKeywords = ['if', 'else', 'for', 'while', 'switch', 'case', 'catch', 'finally'];
1700
+ javaKeywords.forEach(keyword => {
1701
+ const matches = code.match(new RegExp(`\\b${keyword}\\b`, 'g'));
1702
+ if (matches)
1703
+ complexity += matches.length;
1704
+ });
1705
+ // Java logical operators
1706
+ const andOperators = code.match(/&&/g);
1707
+ const orOperators = code.match(/\|\|/g);
1708
+ const ternaryOperators = code.match(/\?[^:]*:/g);
1709
+ if (andOperators)
1710
+ complexity += andOperators.length;
1711
+ if (orOperators)
1712
+ complexity += orOperators.length;
1713
+ if (ternaryOperators)
1714
+ complexity += ternaryOperators.length;
1715
+ result.metrics.complexity = complexity;
1716
+ result.metrics.maintainability = Math.max(0, 100 - complexity * 3);
1717
+ }
1718
+ }
1719
+ exports.JavaAnalyzer = JavaAnalyzer;
1720
+ //# sourceMappingURL=java-analyzer.js.map