@mocoto/mahoraga 0.14.1 → 0.14.3

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 (306) hide show
  1. package/README.md +0 -34
  2. package/dist/analysts/architects/analyst-structure.js +20 -20
  3. package/dist/analysts/architects/archetypes-custom.js +16 -19
  4. package/dist/analysts/architects/detector-archetypes.js +43 -36
  5. package/dist/analysts/architects/orchestrator-archetypes.js +3 -3
  6. package/dist/analysts/architects/signals-project-advanced.js +26 -28
  7. package/dist/analysts/architects/signals-project.js +2 -2
  8. package/dist/analysts/architects/strategist-structure.js +47 -66
  9. package/dist/analysts/azure-pipelines/analysts/analyst-azure.js +41 -35
  10. package/dist/analysts/azure-pipelines/corrections/correction-azure.js +22 -19
  11. package/dist/analysts/azure-pipelines/detectors/detector-azure-performance.js +21 -18
  12. package/dist/analysts/azure-pipelines/detectors/detector-azure-security.js +25 -20
  13. package/dist/analysts/azure-pipelines/detectors/detector-azure-structure.js +39 -40
  14. package/dist/analysts/azure-pipelines/scorers/scorer-azure.js +10 -7
  15. package/dist/analysts/circleci/analysts/analyst-circleci.js +33 -27
  16. package/dist/analysts/circleci/corrections/correction-circleci.js +22 -20
  17. package/dist/analysts/circleci/detectors/detector-circleci-performance.js +23 -19
  18. package/dist/analysts/circleci/detectors/detector-circleci-security.js +78 -82
  19. package/dist/analysts/circleci/detectors/detector-circleci-structure.js +22 -22
  20. package/dist/analysts/converters/convert-registry.js +1 -1
  21. package/dist/analysts/converters/engines/converter-gha-to-gitlab.js +17 -15
  22. package/dist/analysts/converters/index.js +1 -1
  23. package/dist/analysts/corrections/analyst-quick-fixes.js +25 -28
  24. package/dist/analysts/corrections/analyst-scoring.js +24 -21
  25. package/dist/analysts/corrections/auto-fix-engine.js +1 -1
  26. package/dist/analysts/corrections/corrector-structure.js +43 -42
  27. package/dist/analysts/corrections/fix-alias-imports.js +10 -6
  28. package/dist/analysts/corrections/fix-md-fences.js +23 -23
  29. package/dist/analysts/corrections/map-reversion.js +56 -53
  30. package/dist/analysts/corrections/pruning.js +19 -16
  31. package/dist/analysts/corrections/quick-fixes/fix-any-to-proper-type.js +57 -61
  32. package/dist/analysts/corrections/quick-fixes/fix-unknown-to-specific-type.js +30 -30
  33. package/dist/analysts/corrections/reorganize-barrels.js +13 -13
  34. package/dist/analysts/corrections/rewrite-testes-aliases.js +23 -22
  35. package/dist/analysts/corrections/scoring-shared.js +19 -18
  36. package/dist/analysts/corrections/type-safety/context-analyzer.js +15 -10
  37. package/dist/analysts/corrections/type-safety/type-analyzer.js +3 -3
  38. package/dist/analysts/corrections/type-safety/type-validator.js +4 -3
  39. package/dist/analysts/corrections/type-safety/usage-analyzer.js +39 -42
  40. package/dist/analysts/css/analysts/analyst-css.js +42 -42
  41. package/dist/analysts/css/corrections/correction-css.js +19 -11
  42. package/dist/analysts/css/detectors/detector-css-best-practices.js +129 -118
  43. package/dist/analysts/css/scorers/scorer-css.js +23 -18
  44. package/dist/analysts/css-in-js/analysts/analyst-css-in-js.js +24 -17
  45. package/dist/analysts/css-in-js/corrections/correction-css-in-js.js +31 -16
  46. package/dist/analysts/css-in-js/detectors/detector-css-in-js-best-practices.js +28 -30
  47. package/dist/analysts/css-in-js/scorers/scorer-css-in-js.js +79 -54
  48. package/dist/analysts/css-in-js/shared.js +7 -0
  49. package/dist/analysts/detectors/detector-architecture.js +91 -85
  50. package/dist/analysts/detectors/detector-bugs-ml.js +29 -27
  51. package/dist/analysts/detectors/detector-code-fragile.js +41 -36
  52. package/dist/analysts/detectors/detector-dependencies.js +5 -5
  53. package/dist/analysts/detectors/detector-duplications.js +26 -26
  54. package/dist/analysts/detectors/detector-monorepo.js +51 -45
  55. package/dist/analysts/detectors/detector-performance.js +24 -17
  56. package/dist/analysts/detectors/detector-recommendation-architecture.js +40 -36
  57. package/dist/analysts/detectors/detector-security.js +43 -42
  58. package/dist/analysts/detectors/detector-structure.js +31 -28
  59. package/dist/analysts/github-actions/analysts/analyst-github-actions.js +5 -8
  60. package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js +1 -9
  61. package/dist/analysts/github-actions/detectors/detector-workflow-structure.js +1 -4
  62. package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js +6 -5
  63. package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js +2 -2
  64. package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js +0 -3
  65. package/dist/analysts/go/analysts/analyst-best-practices.js +2 -2
  66. package/dist/analysts/go/analysts/analyst-concurrency.js +1 -1
  67. package/dist/analysts/go/analysts/analyst-security.js +1 -1
  68. package/dist/analysts/go/detectors/detector-conventions.js +1 -1
  69. package/dist/analysts/html/analysts/analyst-html.js +10 -12
  70. package/dist/analysts/html/detectors/detector-html.js +3 -3
  71. package/dist/analysts/js-ts/analysts/analyst-commands-cli.js +22 -22
  72. package/dist/analysts/js-ts/analysts/analyst-functions-long.js +5 -5
  73. package/dist/analysts/js-ts/analysts/analyst-patterns-usage.js +6 -2
  74. package/dist/analysts/js-ts/detectors/detector-anti-patterns-async.js +84 -9
  75. package/dist/analysts/js-ts/detectors/detector-constructions-syntactic.js +33 -10
  76. package/dist/analysts/js-ts/detectors/detector-context-smart.js +6 -6
  77. package/dist/analysts/js-ts/detectors/detector-leaks-memory.js +1 -1
  78. package/dist/analysts/js-ts/detectors/detector-types-unsafe.js +33 -2
  79. package/dist/analysts/php/analysts/analyst-php.js +3 -3
  80. package/dist/analysts/php/detectors/detector-php-best-practices.js +5 -5
  81. package/dist/analysts/php/detectors/detector-php-security.js +5 -5
  82. package/dist/analysts/php/scorers/scorer-php.js +2 -2
  83. package/dist/analysts/plugins/detector-documentation.js +6 -6
  84. package/dist/analysts/plugins/detector-markdown.js +7 -7
  85. package/dist/analysts/python/analysts/analyst-python.js +2 -5
  86. package/dist/analysts/react/analysts/analyst-react-hooks.js +66 -9
  87. package/dist/analysts/react/analysts/analyst-react.js +46 -2
  88. package/dist/analysts/react/corrections/correction-react.js +41 -1
  89. package/dist/analysts/react/detectors/detector-react-best-practices.js +5 -5
  90. package/dist/analysts/react/scorers/scorer-react.js +36 -1
  91. package/dist/analysts/registry/autodiscovery.js +2 -2
  92. package/dist/analysts/rust/analysts/analyst-best-practices.js +42 -3
  93. package/dist/analysts/rust/analysts/analyst-memory.js +2 -2
  94. package/dist/analysts/rust/analysts/analyst-rust.js +52 -5
  95. package/dist/analysts/rust/analysts/analyst-security.js +29 -1
  96. package/dist/analysts/scorers/scorer.js +5 -5
  97. package/dist/analysts/shell/analysts/analyst-shell.js +81 -5
  98. package/dist/analysts/shell/corrections/correction-shell.js +34 -1
  99. package/dist/analysts/shell/detectors/detector-shell-security.js +88 -0
  100. package/dist/analysts/shell/scorers/scorer-shell.js +58 -1
  101. package/dist/analysts/strategists/operator-structure.js +5 -7
  102. package/dist/analysts/strategists/suggestions-contextuais.js +5 -2
  103. package/dist/analysts/svg/analysts/analyst-svg.js +1 -0
  104. package/dist/analysts/tailwind/analysts/analyst-tailwind.js +79 -55
  105. package/dist/analysts/tailwind/corrections/correction-tailwind.js +108 -9
  106. package/dist/analysts/tailwind/detectors/detector-tailwind-best-practices.js +122 -7
  107. package/dist/analysts/tailwind/scorers/scorer-tailwind.js +62 -11
  108. package/dist/analysts/xml/analysts/analyst-xml.js +2 -2
  109. package/dist/app/index.js +1 -0
  110. package/dist/bin/cli-bootstrap.js +6 -4
  111. package/dist/bin/index.js +6 -4
  112. package/dist/caretakers/scoring.js +1 -0
  113. package/dist/cli/commands/command-analysts.js +4 -3
  114. package/dist/cli/commands/command-azure.js +1 -1
  115. package/dist/cli/commands/command-circleci.js +1 -1
  116. package/dist/cli/commands/command-compliance.js +1 -1
  117. package/dist/cli/commands/command-diagnose.js +10 -13
  118. package/dist/cli/commands/command-fix-types.js +9 -32
  119. package/dist/cli/commands/command-formatters.js +2 -2
  120. package/dist/cli/commands/command-github-actions.js +1 -1
  121. package/dist/cli/commands/command-gitlab-ci.js +1 -1
  122. package/dist/cli/commands/command-guardian.js +1 -1
  123. package/dist/cli/commands/command-imports.js +6 -6
  124. package/dist/cli/commands/command-jenkins.js +1 -1
  125. package/dist/cli/commands/command-licenses.js +1 -1
  126. package/dist/cli/commands/command-marketplace.js +7 -7
  127. package/dist/cli/commands/command-names.js +3 -8
  128. package/dist/cli/commands/command-perf.js +7 -9
  129. package/dist/cli/commands/command-plugins.js +4 -4
  130. package/dist/cli/diagnostic/auto-fix.js +2 -2
  131. package/dist/cli/diagnostic/exporters/json-exporter.js +1 -1
  132. package/dist/cli/diagnostic/exporters/sharded-exporter.js +0 -3
  133. package/dist/cli/diagnostic/exporters/svg-optimization-exporter.js +1 -1
  134. package/dist/cli/diagnostic/filters.js +9 -9
  135. package/dist/cli/diagnostic/handlers/archetype-handler.js +3 -6
  136. package/dist/cli/diagnostic/handlers/auto-fix-handler.js +4 -4
  137. package/dist/cli/diagnostic/handlers/guardian-handler.js +1 -1
  138. package/dist/cli/diagnostic/processing-diagnostic.js +31 -35
  139. package/dist/cli/diagnostic/processing-helpers.js +2 -2
  140. package/dist/cli/handlers/fix-types-exporter.js +1 -4
  141. package/dist/cli/helpers/display-frame.js +5 -5
  142. package/dist/core/config/auto/auto-fix-config.js +0 -6
  143. package/dist/core/config/chalk-safe.js +6 -6
  144. package/dist/core/config/config.js +11 -13
  145. package/dist/core/config/conventions.js +1 -1
  146. package/dist/core/config/security.js +2 -2
  147. package/dist/core/execution/analysis-cache.js +5 -8
  148. package/dist/core/execution/ast-cache.js +1 -3
  149. package/dist/core/execution/executor.js +8 -21
  150. package/dist/core/execution/inquisitor.js +24 -21
  151. package/dist/core/execution/results.js +1 -0
  152. package/dist/core/execution/scanner.js +4 -4
  153. package/dist/core/messages/en/analysts/analyst-github-actions-messages.js +1 -1
  154. package/dist/core/messages/en/analysts/analyst-patterns-usage-messages.js +1 -0
  155. package/dist/core/messages/en/analysts/analyst-shell-messages.js +15 -0
  156. package/dist/core/messages/en/analysts/detector-constructions-syntactic-messages.js +6 -0
  157. package/dist/core/messages/en/analysts/detector-js-ts-messages.js +27 -0
  158. package/dist/core/messages/en/analysts/detector-react-messages.js +8 -0
  159. package/dist/core/messages/en/analysts/detector-shell-messages.js +17 -0
  160. package/dist/core/messages/en/analysts/detector-tailwind-messages.js +3 -3
  161. package/dist/core/messages/en/analysts/report-circleci-messages.js +7 -7
  162. package/dist/core/messages/en/caretakers/caretaker-messages.js +1 -7
  163. package/dist/core/messages/en/core/plugin-messages.js +31 -3
  164. package/dist/core/messages/en/log/log.js +4 -4
  165. package/dist/core/messages/en/ui/filter-config.js +1 -5
  166. package/dist/core/messages/i18n-system.js +3 -3
  167. package/dist/core/messages/index.js +3 -3
  168. package/dist/core/messages/ja/analysts/analyst-github-actions-messages.js +1 -1
  169. package/dist/core/messages/ja/analysts/analyst-patterns-usage-messages.js +1 -0
  170. package/dist/core/messages/ja/analysts/analyst-shell-messages.js +15 -0
  171. package/dist/core/messages/ja/analysts/detector-constructions-syntactic-messages.js +6 -0
  172. package/dist/core/messages/ja/analysts/detector-js-ts-messages.js +27 -0
  173. package/dist/core/messages/ja/analysts/detector-react-messages.js +8 -0
  174. package/dist/core/messages/ja/analysts/detector-shell-messages.js +17 -0
  175. package/dist/core/messages/ja/analysts/detector-tailwind-messages.js +3 -3
  176. package/dist/core/messages/ja/analysts/report-circleci-messages.js +7 -7
  177. package/dist/core/messages/ja/caretakers/caretaker-messages.js +1 -7
  178. package/dist/core/messages/ja/core/plugin-messages.js +31 -3
  179. package/dist/core/messages/ja/log/log.js +4 -4
  180. package/dist/core/messages/ja/ui/filter-config.js +1 -1
  181. package/dist/core/messages/pt/analysts/analyst-github-actions-messages.js +1 -1
  182. package/dist/core/messages/pt/analysts/analyst-patterns-usage-messages.js +1 -0
  183. package/dist/core/messages/pt/analysts/analyst-shell-messages.js +15 -0
  184. package/dist/core/messages/pt/analysts/detector-constructions-syntactic-messages.js +6 -0
  185. package/dist/core/messages/pt/analysts/detector-js-ts-messages.js +27 -0
  186. package/dist/core/messages/pt/analysts/detector-react-messages.js +8 -0
  187. package/dist/core/messages/pt/analysts/detector-shell-messages.js +17 -0
  188. package/dist/core/messages/pt/analysts/detector-tailwind-messages.js +3 -3
  189. package/dist/core/messages/pt/analysts/report-circleci-messages.js +7 -7
  190. package/dist/core/messages/pt/caretakers/caretaker-messages.js +1 -7
  191. package/dist/core/messages/pt/core/plugin-messages.js +31 -3
  192. package/dist/core/messages/pt/log/log-engine.js +6 -6
  193. package/dist/core/messages/pt/log/log.js +3 -3
  194. package/dist/core/messages/pt/ui/filter-config.js +1 -1
  195. package/dist/core/messages/shared/icons.js +3 -3
  196. package/dist/core/messages/zh/analysts/analyst-github-actions-messages.js +1 -1
  197. package/dist/core/messages/zh/analysts/analyst-patterns-usage-messages.js +1 -0
  198. package/dist/core/messages/zh/analysts/analyst-shell-messages.js +15 -0
  199. package/dist/core/messages/zh/analysts/detector-constructions-syntactic-messages.js +6 -0
  200. package/dist/core/messages/zh/analysts/detector-js-ts-messages.js +27 -0
  201. package/dist/core/messages/zh/analysts/detector-react-messages.js +8 -0
  202. package/dist/core/messages/zh/analysts/detector-shell-messages.js +17 -0
  203. package/dist/core/messages/zh/analysts/detector-tailwind-messages.js +3 -3
  204. package/dist/core/messages/zh/analysts/report-circleci-messages.js +7 -7
  205. package/dist/core/messages/zh/caretakers/caretaker-messages.js +1 -7
  206. package/dist/core/messages/zh/core/plugin-messages.js +31 -3
  207. package/dist/core/messages/zh/log/log.js +3 -3
  208. package/dist/core/messages/zh/ui/filter-config.js +1 -5
  209. package/dist/core/parsing/filters.js +3 -3
  210. package/dist/core/parsing/langs/json.js +1 -1
  211. package/dist/core/parsing/langs/python.js +1 -1
  212. package/dist/core/parsing/langs/typescript.js +1 -1
  213. package/dist/core/parsing/parser.js +3 -4
  214. package/dist/core/parsing/utils.js +1 -0
  215. package/dist/core/registry/file-registry.js +3 -2
  216. package/dist/core/registry/paths.js +3 -3
  217. package/dist/core/reporting/default-reporter.js +2 -2
  218. package/dist/core/schema/version.js +6 -6
  219. package/dist/core/workers/worker-executor.js +3 -3
  220. package/dist/core/workers/worker-pool.js +0 -0
  221. package/dist/guardian/baseline.js +1 -1
  222. package/dist/guardian/gpg.js +3 -1
  223. package/dist/guardian/integrity.js +2 -7
  224. package/dist/guardian/records.js +7 -1
  225. package/dist/guardian/result.js +1 -1
  226. package/dist/guardian/sentinel.js +7 -1
  227. package/dist/guardian/watcher-hidden.js +6 -1
  228. package/dist/licenses/fs-utils.js +5 -1
  229. package/dist/licenses/generate-notices.js +1 -1
  230. package/dist/licenses/index.js +1 -0
  231. package/dist/licenses/normalizer.js +10 -9
  232. package/dist/node.loader.js +224 -4
  233. package/dist/reports/analise-async-patterns.js +1 -1
  234. package/dist/reports/filter-smart.js +2 -5
  235. package/dist/reports/generator-report.js +7 -7
  236. package/dist/reports/report-archetypes.js +10 -10
  237. package/dist/reports/report-caretaker-health.js +2 -1
  238. package/dist/reports/report-patterns-usage.js +1 -1
  239. package/dist/sdk/analyzer.js +1 -1
  240. package/dist/shared/data-processing/fragment-report.js +11 -11
  241. package/dist/shared/data-processing/json.js +1 -1
  242. package/dist/shared/data-processing/occurrences.js +3 -2
  243. package/dist/shared/formatters/code-min-formatter.js +1 -1
  244. package/dist/shared/formatters/engines/prettier.js +1 -1
  245. package/dist/shared/formatters/engines/stylelint.js +43 -40
  246. package/dist/shared/formatters/formatter.js +8 -8
  247. package/dist/shared/formatters/formatters/code.js +3 -3
  248. package/dist/shared/formatters/formatters/css.js +2 -10
  249. package/dist/shared/formatters/formatters/dotfiles.js +1 -1
  250. package/dist/shared/formatters/formatters/html.js +1 -5
  251. package/dist/shared/formatters/formatters/json.js +0 -3
  252. package/dist/shared/formatters/formatters/markdown.js +19 -24
  253. package/dist/shared/formatters/formatters/properties.js +2 -2
  254. package/dist/shared/formatters/formatters/shell.js +1 -4
  255. package/dist/shared/formatters/formatters/sql.js +0 -3
  256. package/dist/shared/formatters/formatters/xml.js +5 -7
  257. package/dist/shared/formatters/formatters/yaml.js +2 -7
  258. package/dist/shared/formatters/index.js +1 -1
  259. package/dist/shared/helpers/framework-detector.js +6 -2
  260. package/dist/shared/helpers/json.js +1 -1
  261. package/dist/shared/helpers/magic-constants-whitelist.js +1 -1
  262. package/dist/shared/helpers/masking.js +17 -17
  263. package/dist/shared/helpers/reader-report.js +0 -12
  264. package/dist/shared/helpers/structural-hash.js +3 -2
  265. package/dist/shared/helpers/structure.js +1 -1
  266. package/dist/shared/marketplace/registry.js +1 -1
  267. package/dist/shared/marketplace/remote.js +4 -4
  268. package/dist/shared/persistence/persistence.js +13 -6
  269. package/dist/shared/plugins/core-plugin.js +5 -1
  270. package/dist/shared/plugins/registry.js +3 -2
  271. package/dist/types/analysts/tailwind-correction.js +2 -0
  272. package/dist/types/caretakers/imports-barrel.js +1 -0
  273. package/dist/types/caretakers/index.js +4 -0
  274. package/dist/types/caretakers/map-reversion.js +1 -0
  275. package/dist/types/caretakers/pruning.js +1 -0
  276. package/dist/types/caretakers/scoring.js +1 -0
  277. package/dist/types/common/analysts.js +1 -1
  278. package/dist/types/core/config/filters.js +1 -0
  279. package/dist/types/core/config/index.js +2 -0
  280. package/dist/types/core/execution/ambiente.js +1 -0
  281. package/dist/types/core/execution/linguagens.js +1 -0
  282. package/dist/types/core/execution/parse-errors.js +1 -0
  283. package/dist/types/core/execution/results.js +1 -0
  284. package/dist/types/core/execution/structure-json.js +1 -0
  285. package/dist/types/core/index.js +1 -0
  286. package/dist/types/core/messages/index.js +1 -0
  287. package/dist/types/core/messages/log.js +1 -0
  288. package/dist/types/core/parsing/babel-narrow.js +1 -0
  289. package/dist/types/core/parsing/index.js +1 -0
  290. package/dist/types/core/runtime.js +1 -0
  291. package/dist/types/guardian/index.js +2 -0
  292. package/dist/types/guardian/integrity.js +7 -0
  293. package/dist/types/guardian/snapshot.js +1 -0
  294. package/dist/types/index.js +4 -4
  295. package/dist/types/licenses/index.js +2 -0
  296. package/dist/types/processing/display.js +16 -13
  297. package/dist/types/processing/filters.js +8 -11
  298. package/dist/types/reports/compliance.js +1 -0
  299. package/dist/types/reports/streaming.js +1 -0
  300. package/dist/types/scripts/index.js +1 -0
  301. package/dist/types/scripts/migrar-aliases.js +1 -0
  302. package/dist/types/sdk/index.js +1 -0
  303. package/dist/types/shared/index.js +2 -0
  304. package/dist/types/vulnerabilities/index.js +2 -0
  305. package/dist/vulnerabilities/scanner.js +3 -2
  306. package/package.json +14 -20
@@ -10,9 +10,10 @@ import { analyzeTypeUsage } from '../type-safety/type-analyzer.js';
10
10
  import { createTypeDefinition } from '../type-safety/type-creator.js';
11
11
  import { validateTypeReplacement } from '../type-safety/type-validator.js';
12
12
  const { MENSAGENS_CORRECAO_TIPOS } = getMessages();
13
+ const CONFIANCA_MEDIA = 60;
13
14
  const CONFIANCA_NIVEIS = {
14
15
  HIGH: 85,
15
- MEDIUM: 60,
16
+ MEDIUM: CONFIANCA_MEDIA,
16
17
  DEFAULT: 70
17
18
  };
18
19
  export const fixAnyToProperTipo = {
@@ -62,66 +63,7 @@ export async function fixAnyToProperTypeAsync(match, fullCode, fileCaminho, ast)
62
63
  const typeAnalise = analyzeTypeUsage(match, fullCode, fileCaminho, ast);
63
64
  // 2. Estratégia baseada em confiança
64
65
  if (typeAnalise.confidence >= CONFIANCA_NIVEIS.HIGH) {
65
- // ALTA CONFIANÇA: Aplicar tipo automaticamente
66
- if (typeAnalise.isSimpleType) {
67
- // Tipo primitivo: substituir diretamente
68
- const fixedCodigo = fullCode.replace(match[0], `: ${typeAnalise.inferredTipo}`);
69
- // Validar resultado
70
- const validation = await validateTypeReplacement(fullCode, fixedCodigo, typeAnalise);
71
- if (!validation.isCompatible) {
72
- return {
73
- code: fullCode,
74
- applied: false,
75
- reason: `Validação falhou: ${validation.errors.join(', ')}`,
76
- warnings: validation.warnings.map(dimensaoLargura => ({
77
- type: 'unsafe-type',
78
- message: dimensaoLargura,
79
- suggestion: 'Revise manualmente'
80
- }))
81
- };
82
- }
83
- return {
84
- code: fixedCodigo,
85
- applied: true,
86
- warnings: validation.warnings.map(dimensaoLargura => ({
87
- type: 'type-suggestion',
88
- message: dimensaoLargura,
89
- suggestion: MENSAGENS_CORRECAO_TIPOS.validacao.revisar
90
- }))
91
- };
92
- }
93
- else {
94
- // Tipo complexo: criar interface
95
- const typeCaminho = await createTypeDefinition(typeAnalise, fileCaminho);
96
- const importStatement = `import type { ${typeAnalise.typeName} } from '${typeCaminho}';\n`;
97
- // Adicionar import no topo e substituir any
98
- const lines = fullCode.split('\n');
99
- const importIndex = findImportInsertionPoint(lines);
100
- lines.splice(importIndex, 0, importStatement);
101
- let fixedCodigo = lines.join('\n');
102
- fixedCodigo = fixedCodigo.replace(match[0], `: ${typeAnalise.typeName}`);
103
- // Validar resultado
104
- const validation = await validateTypeReplacement(fullCode, fixedCodigo, typeAnalise);
105
- if (!validation.isCompatible) {
106
- return {
107
- code: fullCode,
108
- applied: false,
109
- reason: `Validação falhou: ${validation.errors.join(', ')}`
110
- };
111
- }
112
- return {
113
- code: fixedCodigo,
114
- applied: true,
115
- additionalChanges: [{
116
- type: 'add-import',
117
- content: importStatement
118
- }, {
119
- type: 'create-type-file',
120
- content: typeAnalise.typeDefinition,
121
- path: buildTypesRelPathPosix(typeAnalise.suggestedPath)
122
- }]
123
- };
124
- }
66
+ return await applyHighConfidenceAnyFix(match, fullCode, fileCaminho, typeAnalise);
125
67
  }
126
68
  else if (typeAnalise.confidence >= CONFIANCA_NIVEIS.MEDIUM) {
127
69
  // MÉDIA CONFIANÇA: Sugerir mas não aplicar
@@ -162,6 +104,60 @@ export async function fixAnyToProperTypeAsync(match, fullCode, fileCaminho, ast)
162
104
  };
163
105
  }
164
106
  }
107
+ async function applyHighConfidenceAnyFix(match, fullCode, fileCaminho, typeAnalise) {
108
+ if (typeAnalise.isSimpleType) {
109
+ const fixedCodigo = fullCode.replace(match[0], `: ${typeAnalise.inferredTipo}`);
110
+ const validation = await validateTypeReplacement(fullCode, fixedCodigo, typeAnalise);
111
+ if (!validation.isCompatible) {
112
+ return {
113
+ code: fullCode,
114
+ applied: false,
115
+ reason: `Validação falhou: ${validation.errors.join(', ')}`,
116
+ warnings: validation.warnings.map(dimensaoLargura => ({
117
+ type: 'unsafe-type',
118
+ message: dimensaoLargura,
119
+ suggestion: 'Revise manualmente'
120
+ }))
121
+ };
122
+ }
123
+ return {
124
+ code: fixedCodigo,
125
+ applied: true,
126
+ warnings: validation.warnings.map(dimensaoLargura => ({
127
+ type: 'type-suggestion',
128
+ message: dimensaoLargura,
129
+ suggestion: MENSAGENS_CORRECAO_TIPOS.validacao.revisar
130
+ }))
131
+ };
132
+ }
133
+ const typeCaminho = await createTypeDefinition(typeAnalise, fileCaminho);
134
+ const importStatement = `import type { ${typeAnalise.typeName} } from '${typeCaminho}';\n`;
135
+ const lines = fullCode.split('\n');
136
+ const importIndex = findImportInsertionPoint(lines);
137
+ lines.splice(importIndex, 0, importStatement);
138
+ let fixedCodigo = lines.join('\n');
139
+ fixedCodigo = fixedCodigo.replace(match[0], `: ${typeAnalise.typeName}`);
140
+ const validation = await validateTypeReplacement(fullCode, fixedCodigo, typeAnalise);
141
+ if (!validation.isCompatible) {
142
+ return {
143
+ code: fullCode,
144
+ applied: false,
145
+ reason: `Validação falhou: ${validation.errors.join(', ')}`
146
+ };
147
+ }
148
+ return {
149
+ code: fixedCodigo,
150
+ applied: true,
151
+ additionalChanges: [{
152
+ type: 'add-import',
153
+ content: importStatement
154
+ }, {
155
+ type: 'create-type-file',
156
+ content: typeAnalise.typeDefinition,
157
+ path: buildTypesRelPathPosix(typeAnalise.suggestedPath)
158
+ }]
159
+ };
160
+ }
165
161
  /**
166
162
  * Encontra ponto de inserção para import
167
163
  */
@@ -51,36 +51,7 @@ export async function fixUnknownToSpecificTypeAsync(match, fullCode, fileCaminho
51
51
  const typeAnalise = await analyzeUnknownUsage(match, fullCode, fileCaminho, ast);
52
52
  // 2. Estratégia mais conservadora (requer >= 90% confiança)
53
53
  if (typeAnalise.confidence >= 90) {
54
- // ALTA CONFIANÇA: Criar interface dedicada
55
- const typeCaminho = await createTypeDefinition(typeAnalise, fileCaminho);
56
- const importStatement = `import type { ${typeAnalise.typeName} } from '${typeCaminho}';\n`;
57
- // Adicionar import e substituir unknown
58
- const lines = fullCode.split('\n');
59
- const importIndex = findImportInsertionPoint(lines);
60
- lines.splice(importIndex, 0, importStatement);
61
- let fixedCodigo = lines.join('\n');
62
- fixedCodigo = fixedCodigo.replace(match[0], `: ${typeAnalise.typeName}`);
63
- // Validar
64
- const validation = await validateTypeReplacement(fullCode, fixedCodigo, typeAnalise);
65
- if (!validation.isCompatible) {
66
- return {
67
- code: fullCode,
68
- applied: false,
69
- reason: `Validação falhou: ${validation.errors.join(', ')}`
70
- };
71
- }
72
- return {
73
- code: fixedCodigo,
74
- applied: true,
75
- additionalChanges: [{
76
- type: 'add-import',
77
- content: importStatement
78
- }, {
79
- type: 'create-type-file',
80
- content: typeAnalise.typeDefinition,
81
- path: buildTypesRelPathPosix(typeAnalise.suggestedPath)
82
- }]
83
- };
54
+ return await applyHighConfidenceUnknownFix(match, fullCode, fileCaminho, typeAnalise);
84
55
  }
85
56
  else if (typeAnalise.confidence >= 70) {
86
57
  // MÉDIA CONFIANÇA: Sugerir tipo
@@ -120,6 +91,35 @@ export async function fixUnknownToSpecificTypeAsync(match, fullCode, fileCaminho
120
91
  };
121
92
  }
122
93
  }
94
+ async function applyHighConfidenceUnknownFix(match, fullCode, fileCaminho, typeAnalise) {
95
+ const typeCaminho = await createTypeDefinition(typeAnalise, fileCaminho);
96
+ const importStatement = `import type { ${typeAnalise.typeName} } from '${typeCaminho}';\n`;
97
+ const lines = fullCode.split('\n');
98
+ const importIndex = findImportInsertionPoint(lines);
99
+ lines.splice(importIndex, 0, importStatement);
100
+ let fixedCodigo = lines.join('\n');
101
+ fixedCodigo = fixedCodigo.replace(match[0], `: ${typeAnalise.typeName}`);
102
+ const validation = await validateTypeReplacement(fullCode, fixedCodigo, typeAnalise);
103
+ if (!validation.isCompatible) {
104
+ return {
105
+ code: fullCode,
106
+ applied: false,
107
+ reason: `Validação falhou: ${validation.errors.join(', ')}`
108
+ };
109
+ }
110
+ return {
111
+ code: fixedCodigo,
112
+ applied: true,
113
+ additionalChanges: [{
114
+ type: 'add-import',
115
+ content: importStatement
116
+ }, {
117
+ type: 'create-type-file',
118
+ content: typeAnalise.typeDefinition,
119
+ path: buildTypesRelPathPosix(typeAnalise.suggestedPath)
120
+ }]
121
+ };
122
+ }
123
123
  /**
124
124
  * Encontra ponto de inserção para import
125
125
  */
@@ -28,6 +28,15 @@ function resolverImportRelativo(arquivoRel, importSpec) {
28
28
  const dir = path.posix.dirname(normalizarRel(arquivoRel));
29
29
  return path.posix.normalize(path.posix.join(dir, importSpec));
30
30
  }
31
+ function resolverImportSpec(spec, rel) {
32
+ if (spec.startsWith('@/')) {
33
+ return semExt(normalizarRel(`src/${spec.slice(2)}`));
34
+ }
35
+ if (spec.startsWith('@')) {
36
+ return semExt(normalizarRel(`src/${spec.slice(1)}`)).replace(/^src\//, '');
37
+ }
38
+ return semExt(resolverImportRelativo(rel, spec));
39
+ }
31
40
  function criarMapaMovimentos(mapa, _baseDir) {
32
41
  const movimentos = new Map();
33
42
  for (const entry of mapa) {
@@ -231,16 +240,7 @@ async function atualizarImportsGlobais(srcDir, movimentos) {
231
240
  if (!isRelative && !isAlias) {
232
241
  continue;
233
242
  }
234
- let resolved;
235
- if (spec.startsWith('@/')) {
236
- resolved = semExt(normalizarRel(`src/${spec.slice(2)}`));
237
- }
238
- else if (spec.startsWith('@')) {
239
- resolved = semExt(normalizarRel(`src/${spec.slice(1)}`)).replace(/^src\//, '');
240
- }
241
- else {
242
- resolved = semExt(resolverImportRelativo(rel, spec));
243
- }
243
+ const resolved = resolverImportSpec(spec, rel);
244
244
  const moveDestino = movimentos.get(resolved);
245
245
  if (!moveDestino) {
246
246
  continue;
@@ -301,9 +301,9 @@ async function extrairNomesExportados(srcDir, relPath, visitados = new Set(), pr
301
301
  nomes.add(exportDecl[1]);
302
302
  }
303
303
  // export { name1, name2 as alias, ... }
304
- const exportList = trimmed.match(/^export\s+type\s*\{([^}]+)\}|^export\s*\{([^}]+)\}/);
304
+ const exportList = trimmed.match(/^export\s+(?:type\s+)?\s*\{([^}]+)\}/);
305
305
  if (exportList) {
306
- const body = exportList[1] ?? exportList[2];
306
+ const body = exportList[1];
307
307
  if (body) {
308
308
  body.split(',').forEach(part => {
309
309
  const m = part.trim().match(/^(\w+)(?:\s+as\s+\w+)?$/);
@@ -469,7 +469,7 @@ async function repararImportsBarrelPerdidos(srcDir, barrelsPerdidos, _movimentos
469
469
  if (!match) {
470
470
  return null;
471
471
  }
472
- return { imported: match[1], local: match[2] ?? match[1] };
472
+ return { imported: match[1], local: match[2] || match[1] };
473
473
  }).filter((n) => n !== null);
474
474
  const nomesQueFicam = [];
475
475
  const nomesQueMoveram = [];
@@ -19,7 +19,7 @@ function exists(caminho) {
19
19
  function pathFromAlias(aliasSpec, srcRoot) {
20
20
  const spec = aliasSpec.replace(/^@/, '');
21
21
  const parts = spec.split('/');
22
- const top = parts.shift();
22
+ const top = parts?.shift();
23
23
  return path.join(srcRoot, top ?? '', parts.join('/'));
24
24
  }
25
25
  export function pickExtForAlias(aliasBase, srcRoot) {
@@ -67,40 +67,41 @@ export function rewriteToAlias(spec, ctx) {
67
67
  export function transformCodeForTests(code, ctx) {
68
68
  let changed = false;
69
69
  const rewrite = (spec) => rewriteToAlias(spec, ctx);
70
- code = code.replace(/(import\s+[^'"\n]+?from\s+)(["'])([^"']+?)\2/g, (metrica, p1, delimitadorString, spec) => {
71
- const result = rewrite(spec);
72
- if (!result.changed) {
73
- return metrica;
70
+ let result = code;
71
+ result = result.replace(/(import\s+[^'"\n]+?from\s+)(["'])([^"']+?)\2/g, (substring, p1, delimitadorString, spec) => {
72
+ const res = rewrite(spec);
73
+ if (!res.changed) {
74
+ return substring;
74
75
  }
75
76
  changed = true;
76
- return `${p1}${delimitadorString}${result.value}${delimitadorString}`;
77
+ return `${p1}${delimitadorString}${res.value}${delimitadorString}`;
77
78
  });
78
- code = code.replace(/(import\s*)(["'])([^"']+?)\2/g, (metrica, p1, delimitadorString, spec) => {
79
- const result = rewrite(spec);
80
- if (!result.changed) {
81
- return metrica;
79
+ result = result.replace(/(import\s*)(["'])([^"']+?)\2/g, (substring, p1, delimitadorString, spec) => {
80
+ const res = rewrite(spec);
81
+ if (!res.changed) {
82
+ return substring;
82
83
  }
83
84
  changed = true;
84
- return `${p1}${delimitadorString}${result.value}${delimitadorString}`;
85
+ return `${p1}${delimitadorString}${res.value}${delimitadorString}`;
85
86
  });
86
- code = code.replace(/(import\s*\()(\s*["'])([^"']+?)(["']\s*\))/g, (metrica, p1, q1, spec, q2) => {
87
- const result = rewrite(spec);
88
- if (!result.changed) {
89
- return metrica;
87
+ result = result.replace(/(import\s*\()(\s*["'])([^"']+?)(["']\s*\))/g, (substring, p1, q1, spec, q2) => {
88
+ const res = rewrite(spec);
89
+ if (!res.changed) {
90
+ return substring;
90
91
  }
91
92
  changed = true;
92
- return `${p1}${q1}${result.value}${q2}`;
93
+ return `${p1}${q1}${res.value}${q2}`;
93
94
  });
94
- code = code.replace(/(vi\.(?:do)?mock\s*\()(\s*["'])([^"']+?)(["'])(\s*,?)/g, (metrica, p1, q1, spec, q2, comma = '') => {
95
- const result = rewrite(spec);
96
- if (!result.changed) {
97
- return metrica;
95
+ result = result.replace(/(vi\.(?:do)?mock\s*\()(\s*["'])([^"']+?)(["'])(\s*,?)/g, (substring, p1, q1, spec, q2, comma = '') => {
96
+ const res = rewrite(spec);
97
+ if (!res.changed) {
98
+ return substring;
98
99
  }
99
100
  changed = true;
100
- return `${p1}${q1}${result.value}${q2}${comma}`;
101
+ return `${p1}${q1}${res.value}${q2}${comma}`;
101
102
  });
102
103
  return {
103
- code,
104
+ code: result,
104
105
  changed
105
106
  };
106
107
  }
@@ -236,6 +236,24 @@ export function fixSpacingAroundPunct(string) {
236
236
  count
237
237
  };
238
238
  }
239
+ function getCharacterDisplayName(ch) {
240
+ try {
241
+ if (typeof Intl !== 'undefined') {
242
+ const intlApi = Intl;
243
+ const DisplayNomesCtor = intlApi.DisplayNames;
244
+ if (DisplayNomesCtor) {
245
+ const displayNomes = new DisplayNomesCtor(['en'], {
246
+ type: 'language'
247
+ });
248
+ return typeof displayNomes.of === 'function' ? displayNomes.of(ch) ?? '' : '';
249
+ }
250
+ }
251
+ return '';
252
+ }
253
+ catch {
254
+ return '';
255
+ }
256
+ }
239
257
  /**
240
258
  * Detecta caracteres fora do range ASCII comum.
241
259
  */
@@ -248,24 +266,7 @@ export function detectUncommonChars(text, limite) {
248
266
  }
249
267
  const code = ch.codePointAt(0) ?? 0;
250
268
  if (code >= LIMITES.ASCII_EXTENDED_MIN && !isCaractereComum(code)) {
251
- const name = (() => {
252
- try {
253
- if (typeof Intl !== 'undefined') {
254
- const intlApi = Intl;
255
- const DisplayNomesCtor = intlApi.DisplayNames;
256
- if (DisplayNomesCtor) {
257
- const displayNomes = new DisplayNomesCtor(['en'], {
258
- type: 'language'
259
- });
260
- return typeof displayNomes.of === 'function' ? displayNomes.of(ch) ?? '' : '';
261
- }
262
- }
263
- return '';
264
- }
265
- catch {
266
- return '';
267
- }
268
- })();
269
+ const name = getCharacterDisplayName(ch);
269
270
  issues.push({
270
271
  tipo: 'caracteres-incomuns',
271
272
  posicao: pos,
@@ -5,6 +5,7 @@
5
5
  * Analisador de contexto para Type Safety Auto-Fix
6
6
  * Detecta contextos onde any/unknown NÃO devem ser modificados
7
7
  */
8
+ const CONFIANCA_PADRAO = 60;
8
9
  export { isInComment, isInString, isInStringOrComment } from '../../../shared/helpers/index.js';
9
10
  /**
10
11
  * Verifica se está em contexto TypeScript específico que deve ser ignorado
@@ -152,6 +153,13 @@ export function extractLineContext(code, position) {
152
153
  }
153
154
  return '';
154
155
  }
156
+ function hasInternalValidation(code, lineContext) {
157
+ if (!/(analise|result|data|value)\s*:\s*unknown/.test(lineContext)) {
158
+ return false;
159
+ }
160
+ const beforeFunc = code.substring(Math.max(0, lineContext.length - 200), lineContext.length + 100);
161
+ return /if\s*\(/.test(beforeFunc) || /typeof\s+\w+\s*===/.test(beforeFunc);
162
+ }
155
163
  export function categorizarUnknown(code, fileCaminho, lineContext) {
156
164
  // Type Guards - 100% legítimo
157
165
  if (/:\s*unknown\)\s*:\s*\w+\s+is\s+/.test(lineContext)) {
@@ -393,15 +401,12 @@ export function categorizarUnknown(code, fileCaminho, lineContext) {
393
401
  };
394
402
  }
395
403
  // Função de análise com validação interna - 90% legítimo
396
- if (/(analise|result|data|value)\s*:\s*unknown/.test(lineContext)) {
397
- const beforeFunc = code.substring(Math.max(0, lineContext.length - 200), lineContext.length + 100);
398
- if (/if\s*\(/.test(beforeFunc) || /typeof\s+\w+\s*===/.test(beforeFunc)) {
399
- return {
400
- categoria: 'legitimo',
401
- confianca: 90,
402
- motivo: 'Parâmetro com validação/narrowing interna - unknown é seguro quando verificado'
403
- };
404
- }
404
+ if (hasInternalValidation(code, lineContext)) {
405
+ return {
406
+ categoria: 'legitimo',
407
+ confianca: 90,
408
+ motivo: 'Parâmetro com validação/narrowing interna - unknown é seguro quando verificado'
409
+ };
405
410
  }
406
411
  // Getter de keys com validação - 95% legítimo
407
412
  if (/value\s*:\s*unknown/.test(lineContext) && /Object\.keys/.test(contextoAmplo)) {
@@ -422,7 +427,7 @@ export function categorizarUnknown(code, fileCaminho, lineContext) {
422
427
  // Default: melhorável com análise incerta
423
428
  return {
424
429
  categoria: 'melhoravel',
425
- confianca: 60,
430
+ confianca: CONFIANCA_PADRAO,
426
431
  motivo: 'Tipo unknown genérico - análise contextual limitada',
427
432
  sugestao: 'Analisar fluxo de dados para inferir tipo correto',
428
433
  variantes: ['Se vem de API externa: definir interface baseada na resposta esperada', 'Se é callback: especificar assinatura da função', 'Se é config/options: criar interface com campos opcionais', 'Se é polimórfico: considerar discriminated union ou generics']
@@ -62,14 +62,14 @@ export function analyzeTypeUsage(match, fullCode, fileCaminho, ast) {
62
62
  /**
63
63
  * Analisa uso de unknown com foco em type guards
64
64
  */
65
- export async function analyzeUnknownUsage(match, fullCode, fileCaminho, ast) {
65
+ export function analyzeUnknownUsage(match, fullCode, fileCaminho, ast) {
66
66
  // Mesma lógica de analyzeTypeUsage, mas mais conservador
67
67
  const analysis = analyzeTypeUsage(match, fullCode, fileCaminho, ast);
68
68
  // Penalizar confiança em 10% para unknown (mais conservador)
69
69
  analysis.confidence = Math.max(0, analysis.confidence - 10);
70
70
  // Se confiança ainda é baixa, sugerir manter unknown
71
71
  if (analysis.confidence < 70) {
72
- analysis.suggestion = 'Confiança baixa para substituir unknown. ' + `Considere adicionar type guards ou criar tipo dedicado em ${getTypesDirectoryDisplay()}`;
72
+ analysis.suggestion = `Confiança baixa para substituir unknown. Considere adicionar type guards ou criar tipo dedicado em ${getTypesDirectoryDisplay()}`;
73
73
  }
74
- return analysis;
74
+ return Promise.resolve(analysis);
75
75
  }
@@ -4,6 +4,7 @@
4
4
  * Verifica compatibilidade e compilação TypeScript
5
5
  */
6
6
  import { findExistingType, isSameType } from './type-creator.js';
7
+ const CONFIANCA_MINIMA = 60;
7
8
  /**
8
9
  * Valida substituição de tipo (any/unknown → specific)
9
10
  */
@@ -18,13 +19,13 @@ export async function validateTypeReplacement(originalCode, fixedCodigo, typeAna
18
19
  if (typeAnalise.createdNewType) {
19
20
  const existingTipo = await findExistingType(typeAnalise.typeName);
20
21
  if (existingTipo && !isSameType(existingTipo, typeAnalise.typeDefinition)) {
21
- result.warnings.push(`Tipo ${typeAnalise.typeName} já existe com definição diferente. ` + `Verifique conflito em ${existingTipo.path}`);
22
+ result.warnings.push(`Tipo ${typeAnalise.typeName} já existe com definição diferente. Verifique conflito em ${existingTipo.path}`);
22
23
  }
23
24
  }
24
25
  // 2. Verificar se tipo inferido é compatível com uso
25
26
  const usageValidation = validateTypeUsageCompatibility(fixedCodigo, typeAnalise);
26
27
  if (!usageValidation.isCompatible) {
27
- result.errors.push(`Tipo inferido ${typeAnalise.inferredTipo} incompatível com uso detectado. ` + `Esperado: ${usageValidation.expectedType}`);
28
+ result.errors.push(`Tipo inferido ${typeAnalise.inferredTipo} incompatível com uso detectado. Esperado: ${usageValidation.expectedType}`);
28
29
  result.isCompatible = false;
29
30
  }
30
31
  // 3. Verificar se import foi adicionado corretamente
@@ -36,7 +37,7 @@ export async function validateTypeReplacement(originalCode, fixedCodigo, typeAna
36
37
  }
37
38
  }
38
39
  // 4. Verificar confiança mínima
39
- if (typeAnalise.confidence < 60) {
40
+ if (typeAnalise.confidence < CONFIANCA_MINIMA) {
40
41
  result.warnings.push(`Confiança muito baixa (${typeAnalise.confidence}%). Considere revisão manual.`);
41
42
  }
42
43
  // 5. Validar sintaxe básica do código modificado
@@ -128,49 +128,46 @@ function extractObjectProperties(usages) {
128
128
  }
129
129
  return Array.from(propertiesMap.values());
130
130
  }
131
- /**
132
- * Detecta type guards no código
133
- */
131
+ function detectTypeofGuard(usage, context, guards) {
132
+ const match = context.match(/typeof\s+\w+\s*===\s*['"](\w+)['"]/);
133
+ if (match) {
134
+ guards.push({
135
+ type: 'typeof',
136
+ expression: usage.context,
137
+ inferredTipo: match[1],
138
+ confidence: 95
139
+ });
140
+ }
141
+ }
142
+ function detectInstanceofGuard(usage, context, guards) {
143
+ const match = context.match(/\w+\s+instanceof\s+(\w+)/);
144
+ if (match) {
145
+ guards.push({
146
+ type: 'instanceof',
147
+ expression: usage.context,
148
+ inferredTipo: match[1],
149
+ confidence: 95
150
+ });
151
+ }
152
+ }
153
+ function detectInGuard(usage, context, guards) {
154
+ const match = context.match(/['"](\w+)['"]\s+in\s+\w+/);
155
+ if (match) {
156
+ guards.push({
157
+ type: 'in',
158
+ expression: usage.context,
159
+ inferredTipo: `{ ${match[1]}: unknown }`,
160
+ confidence: 80
161
+ });
162
+ }
163
+ }
134
164
  function detectTypeGuards(usages) {
135
165
  const guards = [];
136
166
  for (const usage of usages) {
137
167
  const context = usage.context.toLowerCase();
138
- // typeof guards
139
- if (context.includes('typeof')) {
140
- const match = context.match(/typeof\s+\w+\s*===\s*['"](\w+)['"]/);
141
- if (match) {
142
- guards.push({
143
- type: 'typeof',
144
- expression: usage.context,
145
- inferredTipo: match[1],
146
- confidence: 95
147
- });
148
- }
149
- }
150
- // instanceof guards
151
- if (context.includes('instanceof')) {
152
- const match = context.match(/\w+\s+instanceof\s+(\w+)/);
153
- if (match) {
154
- guards.push({
155
- type: 'instanceof',
156
- expression: usage.context,
157
- inferredTipo: match[1],
158
- confidence: 95
159
- });
160
- }
161
- }
162
- // 'in' operator guards
163
- if (context.includes(' in ')) {
164
- const match = context.match(/['"](\w+)['"]\s+in\s+\w+/);
165
- if (match) {
166
- guards.push({
167
- type: 'in',
168
- expression: usage.context,
169
- inferredTipo: `{ ${match[1]}: unknown }`,
170
- confidence: 80
171
- });
172
- }
173
- }
168
+ detectTypeofGuard(usage, context, guards);
169
+ detectInstanceofGuard(usage, context, guards);
170
+ detectInGuard(usage, context, guards);
174
171
  }
175
172
  return guards;
176
173
  }
@@ -214,7 +211,7 @@ function extractUsageFromNode(node, varNome) {
214
211
  * Extrai informações de MemberExpression
215
212
  */
216
213
  function extractMemberExpressionUsage(node, varNome) {
217
- const property = node.property?.name ?? node.property.value;
214
+ const property = node.property?.name ?? String(node.property.value);
218
215
  return {
219
216
  name: varNome,
220
217
  nodeType: 'MemberExpression',
@@ -222,7 +219,7 @@ function extractMemberExpressionUsage(node, varNome) {
222
219
  column: node.loc?.start?.column ?? 0,
223
220
  context: extractNodeContext(node),
224
221
  operation: 'access',
225
- property: property ? String(property) : undefined
222
+ property: property || undefined
226
223
  };
227
224
  }
228
225
  /**
@@ -250,7 +247,7 @@ function extractNodeContext(node) {
250
247
  }
251
248
  if (node.type === 'MemberExpression') {
252
249
  const obj = node.object?.name ?? extractNodeContext(node.object);
253
- const prop = node.property?.name ?? node.property.value;
250
+ const prop = node.property?.name ?? String(node.property.value);
254
251
  return `${obj}.${prop}`;
255
252
  }
256
253
  if (node.type === 'CallExpression') {