@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.
- package/README.md +0 -34
- package/dist/analysts/architects/analyst-structure.js +20 -20
- package/dist/analysts/architects/archetypes-custom.js +16 -19
- package/dist/analysts/architects/detector-archetypes.js +43 -36
- package/dist/analysts/architects/orchestrator-archetypes.js +3 -3
- package/dist/analysts/architects/signals-project-advanced.js +26 -28
- package/dist/analysts/architects/signals-project.js +2 -2
- package/dist/analysts/architects/strategist-structure.js +47 -66
- package/dist/analysts/azure-pipelines/analysts/analyst-azure.js +41 -35
- package/dist/analysts/azure-pipelines/corrections/correction-azure.js +22 -19
- package/dist/analysts/azure-pipelines/detectors/detector-azure-performance.js +21 -18
- package/dist/analysts/azure-pipelines/detectors/detector-azure-security.js +25 -20
- package/dist/analysts/azure-pipelines/detectors/detector-azure-structure.js +39 -40
- package/dist/analysts/azure-pipelines/scorers/scorer-azure.js +10 -7
- package/dist/analysts/circleci/analysts/analyst-circleci.js +33 -27
- package/dist/analysts/circleci/corrections/correction-circleci.js +22 -20
- package/dist/analysts/circleci/detectors/detector-circleci-performance.js +23 -19
- package/dist/analysts/circleci/detectors/detector-circleci-security.js +78 -82
- package/dist/analysts/circleci/detectors/detector-circleci-structure.js +22 -22
- package/dist/analysts/converters/convert-registry.js +1 -1
- package/dist/analysts/converters/engines/converter-gha-to-gitlab.js +17 -15
- package/dist/analysts/converters/index.js +1 -1
- package/dist/analysts/corrections/analyst-quick-fixes.js +25 -28
- package/dist/analysts/corrections/analyst-scoring.js +24 -21
- package/dist/analysts/corrections/auto-fix-engine.js +1 -1
- package/dist/analysts/corrections/corrector-structure.js +43 -42
- package/dist/analysts/corrections/fix-alias-imports.js +10 -6
- package/dist/analysts/corrections/fix-md-fences.js +23 -23
- package/dist/analysts/corrections/map-reversion.js +56 -53
- package/dist/analysts/corrections/pruning.js +19 -16
- package/dist/analysts/corrections/quick-fixes/fix-any-to-proper-type.js +57 -61
- package/dist/analysts/corrections/quick-fixes/fix-unknown-to-specific-type.js +30 -30
- package/dist/analysts/corrections/reorganize-barrels.js +13 -13
- package/dist/analysts/corrections/rewrite-testes-aliases.js +23 -22
- package/dist/analysts/corrections/scoring-shared.js +19 -18
- package/dist/analysts/corrections/type-safety/context-analyzer.js +15 -10
- package/dist/analysts/corrections/type-safety/type-analyzer.js +3 -3
- package/dist/analysts/corrections/type-safety/type-validator.js +4 -3
- package/dist/analysts/corrections/type-safety/usage-analyzer.js +39 -42
- package/dist/analysts/css/analysts/analyst-css.js +42 -42
- package/dist/analysts/css/corrections/correction-css.js +19 -11
- package/dist/analysts/css/detectors/detector-css-best-practices.js +129 -118
- package/dist/analysts/css/scorers/scorer-css.js +23 -18
- package/dist/analysts/css-in-js/analysts/analyst-css-in-js.js +24 -17
- package/dist/analysts/css-in-js/corrections/correction-css-in-js.js +31 -16
- package/dist/analysts/css-in-js/detectors/detector-css-in-js-best-practices.js +28 -30
- package/dist/analysts/css-in-js/scorers/scorer-css-in-js.js +79 -54
- package/dist/analysts/css-in-js/shared.js +7 -0
- package/dist/analysts/detectors/detector-architecture.js +91 -85
- package/dist/analysts/detectors/detector-bugs-ml.js +29 -27
- package/dist/analysts/detectors/detector-code-fragile.js +41 -36
- package/dist/analysts/detectors/detector-dependencies.js +5 -5
- package/dist/analysts/detectors/detector-duplications.js +26 -26
- package/dist/analysts/detectors/detector-monorepo.js +51 -45
- package/dist/analysts/detectors/detector-performance.js +24 -17
- package/dist/analysts/detectors/detector-recommendation-architecture.js +40 -36
- package/dist/analysts/detectors/detector-security.js +43 -42
- package/dist/analysts/detectors/detector-structure.js +31 -28
- package/dist/analysts/github-actions/analysts/analyst-github-actions.js +5 -8
- package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js +1 -9
- package/dist/analysts/github-actions/detectors/detector-workflow-structure.js +1 -4
- package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js +6 -5
- package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js +2 -2
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js +0 -3
- package/dist/analysts/go/analysts/analyst-best-practices.js +2 -2
- package/dist/analysts/go/analysts/analyst-concurrency.js +1 -1
- package/dist/analysts/go/analysts/analyst-security.js +1 -1
- package/dist/analysts/go/detectors/detector-conventions.js +1 -1
- package/dist/analysts/html/analysts/analyst-html.js +10 -12
- package/dist/analysts/html/detectors/detector-html.js +3 -3
- package/dist/analysts/js-ts/analysts/analyst-commands-cli.js +22 -22
- package/dist/analysts/js-ts/analysts/analyst-functions-long.js +5 -5
- package/dist/analysts/js-ts/analysts/analyst-patterns-usage.js +6 -2
- package/dist/analysts/js-ts/detectors/detector-anti-patterns-async.js +84 -9
- package/dist/analysts/js-ts/detectors/detector-constructions-syntactic.js +33 -10
- package/dist/analysts/js-ts/detectors/detector-context-smart.js +6 -6
- package/dist/analysts/js-ts/detectors/detector-leaks-memory.js +1 -1
- package/dist/analysts/js-ts/detectors/detector-types-unsafe.js +33 -2
- package/dist/analysts/php/analysts/analyst-php.js +3 -3
- package/dist/analysts/php/detectors/detector-php-best-practices.js +5 -5
- package/dist/analysts/php/detectors/detector-php-security.js +5 -5
- package/dist/analysts/php/scorers/scorer-php.js +2 -2
- package/dist/analysts/plugins/detector-documentation.js +6 -6
- package/dist/analysts/plugins/detector-markdown.js +7 -7
- package/dist/analysts/python/analysts/analyst-python.js +2 -5
- package/dist/analysts/react/analysts/analyst-react-hooks.js +66 -9
- package/dist/analysts/react/analysts/analyst-react.js +46 -2
- package/dist/analysts/react/corrections/correction-react.js +41 -1
- package/dist/analysts/react/detectors/detector-react-best-practices.js +5 -5
- package/dist/analysts/react/scorers/scorer-react.js +36 -1
- package/dist/analysts/registry/autodiscovery.js +2 -2
- package/dist/analysts/rust/analysts/analyst-best-practices.js +42 -3
- package/dist/analysts/rust/analysts/analyst-memory.js +2 -2
- package/dist/analysts/rust/analysts/analyst-rust.js +52 -5
- package/dist/analysts/rust/analysts/analyst-security.js +29 -1
- package/dist/analysts/scorers/scorer.js +5 -5
- package/dist/analysts/shell/analysts/analyst-shell.js +81 -5
- package/dist/analysts/shell/corrections/correction-shell.js +34 -1
- package/dist/analysts/shell/detectors/detector-shell-security.js +88 -0
- package/dist/analysts/shell/scorers/scorer-shell.js +58 -1
- package/dist/analysts/strategists/operator-structure.js +5 -7
- package/dist/analysts/strategists/suggestions-contextuais.js +5 -2
- package/dist/analysts/svg/analysts/analyst-svg.js +1 -0
- package/dist/analysts/tailwind/analysts/analyst-tailwind.js +79 -55
- package/dist/analysts/tailwind/corrections/correction-tailwind.js +108 -9
- package/dist/analysts/tailwind/detectors/detector-tailwind-best-practices.js +122 -7
- package/dist/analysts/tailwind/scorers/scorer-tailwind.js +62 -11
- package/dist/analysts/xml/analysts/analyst-xml.js +2 -2
- package/dist/app/index.js +1 -0
- package/dist/bin/cli-bootstrap.js +6 -4
- package/dist/bin/index.js +6 -4
- package/dist/caretakers/scoring.js +1 -0
- package/dist/cli/commands/command-analysts.js +4 -3
- package/dist/cli/commands/command-azure.js +1 -1
- package/dist/cli/commands/command-circleci.js +1 -1
- package/dist/cli/commands/command-compliance.js +1 -1
- package/dist/cli/commands/command-diagnose.js +10 -13
- package/dist/cli/commands/command-fix-types.js +9 -32
- package/dist/cli/commands/command-formatters.js +2 -2
- package/dist/cli/commands/command-github-actions.js +1 -1
- package/dist/cli/commands/command-gitlab-ci.js +1 -1
- package/dist/cli/commands/command-guardian.js +1 -1
- package/dist/cli/commands/command-imports.js +6 -6
- package/dist/cli/commands/command-jenkins.js +1 -1
- package/dist/cli/commands/command-licenses.js +1 -1
- package/dist/cli/commands/command-marketplace.js +7 -7
- package/dist/cli/commands/command-names.js +3 -8
- package/dist/cli/commands/command-perf.js +7 -9
- package/dist/cli/commands/command-plugins.js +4 -4
- package/dist/cli/diagnostic/auto-fix.js +2 -2
- package/dist/cli/diagnostic/exporters/json-exporter.js +1 -1
- package/dist/cli/diagnostic/exporters/sharded-exporter.js +0 -3
- package/dist/cli/diagnostic/exporters/svg-optimization-exporter.js +1 -1
- package/dist/cli/diagnostic/filters.js +9 -9
- package/dist/cli/diagnostic/handlers/archetype-handler.js +3 -6
- package/dist/cli/diagnostic/handlers/auto-fix-handler.js +4 -4
- package/dist/cli/diagnostic/handlers/guardian-handler.js +1 -1
- package/dist/cli/diagnostic/processing-diagnostic.js +31 -35
- package/dist/cli/diagnostic/processing-helpers.js +2 -2
- package/dist/cli/handlers/fix-types-exporter.js +1 -4
- package/dist/cli/helpers/display-frame.js +5 -5
- package/dist/core/config/auto/auto-fix-config.js +0 -6
- package/dist/core/config/chalk-safe.js +6 -6
- package/dist/core/config/config.js +11 -13
- package/dist/core/config/conventions.js +1 -1
- package/dist/core/config/security.js +2 -2
- package/dist/core/execution/analysis-cache.js +5 -8
- package/dist/core/execution/ast-cache.js +1 -3
- package/dist/core/execution/executor.js +8 -21
- package/dist/core/execution/inquisitor.js +24 -21
- package/dist/core/execution/results.js +1 -0
- package/dist/core/execution/scanner.js +4 -4
- package/dist/core/messages/en/analysts/analyst-github-actions-messages.js +1 -1
- package/dist/core/messages/en/analysts/analyst-patterns-usage-messages.js +1 -0
- package/dist/core/messages/en/analysts/analyst-shell-messages.js +15 -0
- package/dist/core/messages/en/analysts/detector-constructions-syntactic-messages.js +6 -0
- package/dist/core/messages/en/analysts/detector-js-ts-messages.js +27 -0
- package/dist/core/messages/en/analysts/detector-react-messages.js +8 -0
- package/dist/core/messages/en/analysts/detector-shell-messages.js +17 -0
- package/dist/core/messages/en/analysts/detector-tailwind-messages.js +3 -3
- package/dist/core/messages/en/analysts/report-circleci-messages.js +7 -7
- package/dist/core/messages/en/caretakers/caretaker-messages.js +1 -7
- package/dist/core/messages/en/core/plugin-messages.js +31 -3
- package/dist/core/messages/en/log/log.js +4 -4
- package/dist/core/messages/en/ui/filter-config.js +1 -5
- package/dist/core/messages/i18n-system.js +3 -3
- package/dist/core/messages/index.js +3 -3
- package/dist/core/messages/ja/analysts/analyst-github-actions-messages.js +1 -1
- package/dist/core/messages/ja/analysts/analyst-patterns-usage-messages.js +1 -0
- package/dist/core/messages/ja/analysts/analyst-shell-messages.js +15 -0
- package/dist/core/messages/ja/analysts/detector-constructions-syntactic-messages.js +6 -0
- package/dist/core/messages/ja/analysts/detector-js-ts-messages.js +27 -0
- package/dist/core/messages/ja/analysts/detector-react-messages.js +8 -0
- package/dist/core/messages/ja/analysts/detector-shell-messages.js +17 -0
- package/dist/core/messages/ja/analysts/detector-tailwind-messages.js +3 -3
- package/dist/core/messages/ja/analysts/report-circleci-messages.js +7 -7
- package/dist/core/messages/ja/caretakers/caretaker-messages.js +1 -7
- package/dist/core/messages/ja/core/plugin-messages.js +31 -3
- package/dist/core/messages/ja/log/log.js +4 -4
- package/dist/core/messages/ja/ui/filter-config.js +1 -1
- package/dist/core/messages/pt/analysts/analyst-github-actions-messages.js +1 -1
- package/dist/core/messages/pt/analysts/analyst-patterns-usage-messages.js +1 -0
- package/dist/core/messages/pt/analysts/analyst-shell-messages.js +15 -0
- package/dist/core/messages/pt/analysts/detector-constructions-syntactic-messages.js +6 -0
- package/dist/core/messages/pt/analysts/detector-js-ts-messages.js +27 -0
- package/dist/core/messages/pt/analysts/detector-react-messages.js +8 -0
- package/dist/core/messages/pt/analysts/detector-shell-messages.js +17 -0
- package/dist/core/messages/pt/analysts/detector-tailwind-messages.js +3 -3
- package/dist/core/messages/pt/analysts/report-circleci-messages.js +7 -7
- package/dist/core/messages/pt/caretakers/caretaker-messages.js +1 -7
- package/dist/core/messages/pt/core/plugin-messages.js +31 -3
- package/dist/core/messages/pt/log/log-engine.js +6 -6
- package/dist/core/messages/pt/log/log.js +3 -3
- package/dist/core/messages/pt/ui/filter-config.js +1 -1
- package/dist/core/messages/shared/icons.js +3 -3
- package/dist/core/messages/zh/analysts/analyst-github-actions-messages.js +1 -1
- package/dist/core/messages/zh/analysts/analyst-patterns-usage-messages.js +1 -0
- package/dist/core/messages/zh/analysts/analyst-shell-messages.js +15 -0
- package/dist/core/messages/zh/analysts/detector-constructions-syntactic-messages.js +6 -0
- package/dist/core/messages/zh/analysts/detector-js-ts-messages.js +27 -0
- package/dist/core/messages/zh/analysts/detector-react-messages.js +8 -0
- package/dist/core/messages/zh/analysts/detector-shell-messages.js +17 -0
- package/dist/core/messages/zh/analysts/detector-tailwind-messages.js +3 -3
- package/dist/core/messages/zh/analysts/report-circleci-messages.js +7 -7
- package/dist/core/messages/zh/caretakers/caretaker-messages.js +1 -7
- package/dist/core/messages/zh/core/plugin-messages.js +31 -3
- package/dist/core/messages/zh/log/log.js +3 -3
- package/dist/core/messages/zh/ui/filter-config.js +1 -5
- package/dist/core/parsing/filters.js +3 -3
- package/dist/core/parsing/langs/json.js +1 -1
- package/dist/core/parsing/langs/python.js +1 -1
- package/dist/core/parsing/langs/typescript.js +1 -1
- package/dist/core/parsing/parser.js +3 -4
- package/dist/core/parsing/utils.js +1 -0
- package/dist/core/registry/file-registry.js +3 -2
- package/dist/core/registry/paths.js +3 -3
- package/dist/core/reporting/default-reporter.js +2 -2
- package/dist/core/schema/version.js +6 -6
- package/dist/core/workers/worker-executor.js +3 -3
- package/dist/core/workers/worker-pool.js +0 -0
- package/dist/guardian/baseline.js +1 -1
- package/dist/guardian/gpg.js +3 -1
- package/dist/guardian/integrity.js +2 -7
- package/dist/guardian/records.js +7 -1
- package/dist/guardian/result.js +1 -1
- package/dist/guardian/sentinel.js +7 -1
- package/dist/guardian/watcher-hidden.js +6 -1
- package/dist/licenses/fs-utils.js +5 -1
- package/dist/licenses/generate-notices.js +1 -1
- package/dist/licenses/index.js +1 -0
- package/dist/licenses/normalizer.js +10 -9
- package/dist/node.loader.js +224 -4
- package/dist/reports/analise-async-patterns.js +1 -1
- package/dist/reports/filter-smart.js +2 -5
- package/dist/reports/generator-report.js +7 -7
- package/dist/reports/report-archetypes.js +10 -10
- package/dist/reports/report-caretaker-health.js +2 -1
- package/dist/reports/report-patterns-usage.js +1 -1
- package/dist/sdk/analyzer.js +1 -1
- package/dist/shared/data-processing/fragment-report.js +11 -11
- package/dist/shared/data-processing/json.js +1 -1
- package/dist/shared/data-processing/occurrences.js +3 -2
- package/dist/shared/formatters/code-min-formatter.js +1 -1
- package/dist/shared/formatters/engines/prettier.js +1 -1
- package/dist/shared/formatters/engines/stylelint.js +43 -40
- package/dist/shared/formatters/formatter.js +8 -8
- package/dist/shared/formatters/formatters/code.js +3 -3
- package/dist/shared/formatters/formatters/css.js +2 -10
- package/dist/shared/formatters/formatters/dotfiles.js +1 -1
- package/dist/shared/formatters/formatters/html.js +1 -5
- package/dist/shared/formatters/formatters/json.js +0 -3
- package/dist/shared/formatters/formatters/markdown.js +19 -24
- package/dist/shared/formatters/formatters/properties.js +2 -2
- package/dist/shared/formatters/formatters/shell.js +1 -4
- package/dist/shared/formatters/formatters/sql.js +0 -3
- package/dist/shared/formatters/formatters/xml.js +5 -7
- package/dist/shared/formatters/formatters/yaml.js +2 -7
- package/dist/shared/formatters/index.js +1 -1
- package/dist/shared/helpers/framework-detector.js +6 -2
- package/dist/shared/helpers/json.js +1 -1
- package/dist/shared/helpers/magic-constants-whitelist.js +1 -1
- package/dist/shared/helpers/masking.js +17 -17
- package/dist/shared/helpers/reader-report.js +0 -12
- package/dist/shared/helpers/structural-hash.js +3 -2
- package/dist/shared/helpers/structure.js +1 -1
- package/dist/shared/marketplace/registry.js +1 -1
- package/dist/shared/marketplace/remote.js +4 -4
- package/dist/shared/persistence/persistence.js +13 -6
- package/dist/shared/plugins/core-plugin.js +5 -1
- package/dist/shared/plugins/registry.js +3 -2
- package/dist/types/analysts/tailwind-correction.js +2 -0
- package/dist/types/caretakers/imports-barrel.js +1 -0
- package/dist/types/caretakers/index.js +4 -0
- package/dist/types/caretakers/map-reversion.js +1 -0
- package/dist/types/caretakers/pruning.js +1 -0
- package/dist/types/caretakers/scoring.js +1 -0
- package/dist/types/common/analysts.js +1 -1
- package/dist/types/core/config/filters.js +1 -0
- package/dist/types/core/config/index.js +2 -0
- package/dist/types/core/execution/ambiente.js +1 -0
- package/dist/types/core/execution/linguagens.js +1 -0
- package/dist/types/core/execution/parse-errors.js +1 -0
- package/dist/types/core/execution/results.js +1 -0
- package/dist/types/core/execution/structure-json.js +1 -0
- package/dist/types/core/index.js +1 -0
- package/dist/types/core/messages/index.js +1 -0
- package/dist/types/core/messages/log.js +1 -0
- package/dist/types/core/parsing/babel-narrow.js +1 -0
- package/dist/types/core/parsing/index.js +1 -0
- package/dist/types/core/runtime.js +1 -0
- package/dist/types/guardian/index.js +2 -0
- package/dist/types/guardian/integrity.js +7 -0
- package/dist/types/guardian/snapshot.js +1 -0
- package/dist/types/index.js +4 -4
- package/dist/types/licenses/index.js +2 -0
- package/dist/types/processing/display.js +16 -13
- package/dist/types/processing/filters.js +8 -11
- package/dist/types/reports/compliance.js +1 -0
- package/dist/types/reports/streaming.js +1 -0
- package/dist/types/scripts/index.js +1 -0
- package/dist/types/scripts/migrar-aliases.js +1 -0
- package/dist/types/sdk/index.js +1 -0
- package/dist/types/shared/index.js +2 -0
- package/dist/types/vulnerabilities/index.js +2 -0
- package/dist/vulnerabilities/scanner.js +3 -2
- package/package.json +14 -20
|
@@ -4,11 +4,28 @@
|
|
|
4
4
|
// em expressões regulares de detecção, gerando falso positivo em auto-análise.
|
|
5
5
|
import { getMessages } from '../../../core/messages/index.js';
|
|
6
6
|
import { splitLines } from '../../../shared/helpers/index.js';
|
|
7
|
+
import { IMPORTANT_PATTERN } from '../shared.js';
|
|
7
8
|
import { criarOcorrencia } from '../../../types/index.js';
|
|
8
9
|
const STYLED_PATTERN = /styled\s*(\.|\()`|css\s*`|css\(|StyleSheet\.create|makeStyles|useStyles|createStyles|withStyles/;
|
|
9
|
-
const THEME_PATTERN = /useTheme|ThemeProvider|withTheme|theme\s*\.|createTheme/;
|
|
10
10
|
const PSEUDO_CLASSES = [':hover', ':focus', ':active', ':visited', ':disabled', ':checked', ':focus-within', ':focus-visible'];
|
|
11
11
|
const BREAKPOINT_PATTERN = /\b(768|1024|1280|480|320)\s*px\b/;
|
|
12
|
+
function detectarMissingPseudoClasses(linha, numeroLinha, ocorrencias, relPath, m) {
|
|
13
|
+
if (!/styled\s*\.\s*\w+\s*`[^`]*`/i.test(linha) && !/css\s*`[^`]*`/i.test(linha)) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const hasPseudo = PSEUDO_CLASSES.some(pc => linha.includes(pc));
|
|
17
|
+
const isInteractive = /button|input|a\s*\(|link|click|onClick|onChange|onSubmit|role\s*=\s*["']button/i.test(linha);
|
|
18
|
+
if (isInteractive && !hasPseudo) {
|
|
19
|
+
ocorrencias.push(criarOcorrencia({
|
|
20
|
+
tipo: 'css-in-js-missing-pseudo-classes',
|
|
21
|
+
nivel: 'info',
|
|
22
|
+
mensagem: m.CssInJsMensagens.missingPseudoClasses,
|
|
23
|
+
relPath,
|
|
24
|
+
linha: numeroLinha,
|
|
25
|
+
sugestao: m.CssInJsMensagens.missingPseudoClassesSugestao
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
12
29
|
export const detectorCssInJsBestPractices = {
|
|
13
30
|
nome: 'detector-css-in-js-best-practices',
|
|
14
31
|
categoria: 'estilo',
|
|
@@ -24,12 +41,8 @@ export const detectorCssInJsBestPractices = {
|
|
|
24
41
|
if (!/styled-components|styled-jsx|emotion|@emotion|css\s*`|css\(/i.test(src)) {
|
|
25
42
|
return ocorrencias;
|
|
26
43
|
}
|
|
27
|
-
let hasThemeAccess = false;
|
|
28
44
|
linhas.forEach((linha, index) => {
|
|
29
45
|
const numeroLinha = index + 1;
|
|
30
|
-
if (THEME_PATTERN.test(linha)) {
|
|
31
|
-
hasThemeAccess = true;
|
|
32
|
-
}
|
|
33
46
|
if (/createGlobalStyle|<style[^>]*global/i.test(linha)) {
|
|
34
47
|
ocorrencias.push(criarOcorrencia({
|
|
35
48
|
tipo: 'css-in-js-global-styles',
|
|
@@ -40,7 +53,7 @@ export const detectorCssInJsBestPractices = {
|
|
|
40
53
|
sugestao: m.CssInJsMensagens.sugestaoEvitarGlobalStyles
|
|
41
54
|
}));
|
|
42
55
|
}
|
|
43
|
-
if (
|
|
56
|
+
if (IMPORTANT_PATTERN.test(linha) && /styled|css\s*`|css\(/i.test(linha)) {
|
|
44
57
|
ocorrencias.push(criarOcorrencia({
|
|
45
58
|
tipo: 'css-in-js-important',
|
|
46
59
|
nivel: 'info',
|
|
@@ -90,20 +103,7 @@ export const detectorCssInJsBestPractices = {
|
|
|
90
103
|
sugestao: m.CssInJsMensagens.hardcodedBreakpointSugestao
|
|
91
104
|
}));
|
|
92
105
|
}
|
|
93
|
-
|
|
94
|
-
const hasPseudo = PSEUDO_CLASSES.some(pc => linha.includes(pc));
|
|
95
|
-
const isInteractive = /button|input|a\s*\(|link|click|onClick|onChange|onSubmit|role\s*=\s*["']button/i.test(linha);
|
|
96
|
-
if (isInteractive && !hasPseudo) {
|
|
97
|
-
ocorrencias.push(criarOcorrencia({
|
|
98
|
-
tipo: 'css-in-js-missing-pseudo-classes',
|
|
99
|
-
nivel: 'info',
|
|
100
|
-
mensagem: m.CssInJsMensagens.missingPseudoClasses,
|
|
101
|
-
relPath,
|
|
102
|
-
linha: numeroLinha,
|
|
103
|
-
sugestao: m.CssInJsMensagens.missingPseudoClassesSugestao
|
|
104
|
-
}));
|
|
105
|
-
}
|
|
106
|
-
}
|
|
106
|
+
detectarMissingPseudoClasses(linha, numeroLinha, ocorrencias, relPath, m);
|
|
107
107
|
if (/css\s*`[^$]*`/.test(linha) || /css`[^$]*`/.test(linha)) {
|
|
108
108
|
ocorrencias.push(criarOcorrencia({
|
|
109
109
|
tipo: 'css-in-js-tagged-template-no-expr',
|
|
@@ -126,16 +126,14 @@ export const detectorCssInJsBestPractices = {
|
|
|
126
126
|
}));
|
|
127
127
|
}
|
|
128
128
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}));
|
|
138
|
-
}
|
|
129
|
+
ocorrencias.push(criarOcorrencia({
|
|
130
|
+
tipo: 'css-in-js-missing-theme-access',
|
|
131
|
+
nivel: 'info',
|
|
132
|
+
mensagem: m.CssInJsMensagens.missingThemeAccess,
|
|
133
|
+
relPath,
|
|
134
|
+
linha: 1,
|
|
135
|
+
sugestao: m.CssInJsMensagens.missingThemeAccessSugestao
|
|
136
|
+
}));
|
|
139
137
|
const dynamicStyleCount = (src.match(/\$\{.*\}/g) ?? []).length;
|
|
140
138
|
if (dynamicStyleCount > 10) {
|
|
141
139
|
ocorrencias.push(criarOcorrencia({
|
|
@@ -4,107 +4,132 @@
|
|
|
4
4
|
// em expressões regulares de detecção, gerando falso positivo em auto-análise.
|
|
5
5
|
import { getMessages } from '../../../core/messages/index.js';
|
|
6
6
|
import { splitLines } from '../../../shared/helpers/index.js';
|
|
7
|
+
import { IMPORTANT_GLOBAL } from '../shared.js';
|
|
7
8
|
const STYLED_PATTERN = /styled\s*(\.|\()`|css\s*`|css\(|StyleSheet\.create|makeStyles|useStyles|createStyles|withStyles/;
|
|
8
|
-
|
|
9
|
-
const m = getMessages().CssInJsPontuacaoMensagens;
|
|
10
|
-
let score = 0;
|
|
11
|
-
const maxScore = 100;
|
|
12
|
-
const issues = [];
|
|
13
|
-
const strengths = [];
|
|
14
|
-
const _linhas = splitLines(src);
|
|
15
|
-
const srcCompleto = src;
|
|
16
|
-
if (!STYLED_PATTERN.test(srcCompleto)) {
|
|
17
|
-
return { score: 0, maxScore, percentage: 0, issues: [m.notDetected], strengths: [] };
|
|
18
|
-
}
|
|
19
|
-
strengths.push(m.detected);
|
|
9
|
+
function avaliarGlobalStyles(srcCompleto, m, strengths, issues) {
|
|
20
10
|
if (!/createGlobalStyle|<style[^>]*global/i.test(srcCompleto)) {
|
|
21
|
-
score += 15;
|
|
22
11
|
strengths.push(m.noGlobalStyles);
|
|
12
|
+
return 15;
|
|
23
13
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
issues.push(m.globalStylesIssue);
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
function avaliarImportantUsage(srcCompleto, m, strengths, issues) {
|
|
18
|
+
const importantCount = (srcCompleto.match(IMPORTANT_GLOBAL) ?? []).length;
|
|
28
19
|
if (importantCount === 0) {
|
|
29
|
-
score += 10;
|
|
30
20
|
strengths.push(m.noImportant);
|
|
21
|
+
return 10;
|
|
31
22
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
issues.push(m.importantUsageCount(importantCount));
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
function avaliarHttpUrls(srcCompleto, m, strengths, issues) {
|
|
35
27
|
const httpUrls = (srcCompleto.match(/url\(\s*['"]?http:\/\//gi) ?? []).length;
|
|
36
28
|
if (httpUrls === 0) {
|
|
37
|
-
score += 8;
|
|
38
29
|
strengths.push(m.noHttpUrls);
|
|
30
|
+
return 8;
|
|
39
31
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
32
|
+
issues.push(m.httpUrlCount(httpUrls));
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
function avaliarMixedStyling(srcCompleto, m, strengths, issues) {
|
|
43
36
|
const hasMixed = /className=.*style=\{/.test(srcCompleto);
|
|
44
37
|
if (!hasMixed) {
|
|
45
|
-
score += 10;
|
|
46
38
|
strengths.push(m.consistentStyling);
|
|
39
|
+
return 10;
|
|
47
40
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
issues.push(m.mixedStylingIssue);
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
function avaliarThemeUsage(srcCompleto, m, strengths, issues) {
|
|
51
45
|
const hasTheme = /useTheme|theme\.|ThemeProvider/i.test(srcCompleto);
|
|
52
46
|
if (hasTheme) {
|
|
53
|
-
score += 12;
|
|
54
47
|
strengths.push(m.themeUsage);
|
|
48
|
+
return 12;
|
|
55
49
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
50
|
+
issues.push(m.noThemeSystem);
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
function avaliarInlineStyles(srcCompleto, strengths, issues) {
|
|
59
54
|
const hasInlineStyles = /style\s*=\s*\{\s*\{/.test(srcCompleto);
|
|
60
55
|
if (!hasInlineStyles) {
|
|
61
|
-
score += 8;
|
|
62
56
|
strengths.push('Sem estilos inline excessivos');
|
|
57
|
+
return 8;
|
|
63
58
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
issues.push('Estilos inline detectados - prefira styled components');
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
function avaliarBreakpoints(srcCompleto, strengths, issues) {
|
|
67
63
|
const hasHardcodedBreakpoints = (srcCompleto.match(/\b(768|1024|1280|480|320)\s*px\b/g) ?? []).length;
|
|
68
64
|
if (hasHardcodedBreakpoints === 0) {
|
|
69
|
-
score += 7;
|
|
70
65
|
strengths.push('Breakpoints consistentes');
|
|
66
|
+
return 7;
|
|
71
67
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
issues.push(`${hasHardcodedBreakpoints} breakpoint(s) hardcoded`);
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
function avaliarPseudoClasses(srcCompleto, strengths, issues) {
|
|
75
72
|
const pseudoInteractive = /:hover|:focus|:active/.test(srcCompleto);
|
|
76
73
|
const hasInteractive = /button|input|a\s*\(|link|click|onClick/i.test(srcCompleto);
|
|
77
74
|
if (!hasInteractive || pseudoInteractive) {
|
|
78
|
-
score += 7;
|
|
79
75
|
strengths.push('Pseudo-classes para estados interativos');
|
|
76
|
+
return 7;
|
|
80
77
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
issues.push('Elementos interativos sem pseudo-classes');
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
function avaliarDynamicStyles(srcCompleto, strengths, issues) {
|
|
84
82
|
const dynamicStyles = (srcCompleto.match(/\$\{.*\}/g) ?? []).length;
|
|
85
83
|
if (dynamicStyles <= 5) {
|
|
86
|
-
score += 8;
|
|
87
84
|
strengths.push('Estilos dinâmicos controlados');
|
|
85
|
+
return 8;
|
|
88
86
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
issues.push(`${dynamicStyles} expressões dinâmicas - considere extração estática`);
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
function avaliarExtraction(srcCompleto, strengths, issues) {
|
|
92
91
|
const hasExtraction = /extract|linaria|vanilla-extract|compiled|griffel/i.test(srcCompleto);
|
|
93
92
|
if (hasExtraction) {
|
|
94
|
-
score += 10;
|
|
95
93
|
strengths.push('Extração de CSS estático ativa');
|
|
94
|
+
return 10;
|
|
96
95
|
}
|
|
97
|
-
|
|
96
|
+
if (STYLED_PATTERN.test(srcCompleto)) {
|
|
98
97
|
issues.push('Sem extração de CSS estático - considere ferramentas como linaria');
|
|
99
98
|
}
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
function avaliarConditionalComplexity(srcCompleto, strengths, issues) {
|
|
100
102
|
const conditionalComplex = (srcCompleto.match(/\$\{.*\?.*:.*\}/g) ?? []).length;
|
|
101
103
|
if (conditionalComplex <= 3) {
|
|
102
|
-
score += 5;
|
|
103
104
|
strengths.push('Estilos condicionais simplificados');
|
|
105
|
+
return 5;
|
|
104
106
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
issues.push(`${conditionalComplex} estilos condicionais complexos`);
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
export function pontuarCssInJs(src, _relPath) {
|
|
111
|
+
const m = getMessages().CssInJsPontuacaoMensagens;
|
|
112
|
+
let score = 0;
|
|
113
|
+
const maxScore = 100;
|
|
114
|
+
const issues = [];
|
|
115
|
+
const strengths = [];
|
|
116
|
+
const _linhas = splitLines(src);
|
|
117
|
+
const srcCompleto = src;
|
|
118
|
+
if (!STYLED_PATTERN.test(srcCompleto)) {
|
|
119
|
+
return { score: 0, maxScore, percentage: 0, issues: [m.notDetected], strengths: [] };
|
|
107
120
|
}
|
|
121
|
+
strengths.push(m.detected);
|
|
122
|
+
score += avaliarGlobalStyles(srcCompleto, m, strengths, issues);
|
|
123
|
+
score += avaliarImportantUsage(srcCompleto, m, strengths, issues);
|
|
124
|
+
score += avaliarHttpUrls(srcCompleto, m, strengths, issues);
|
|
125
|
+
score += avaliarMixedStyling(srcCompleto, m, strengths, issues);
|
|
126
|
+
score += avaliarThemeUsage(srcCompleto, m, strengths, issues);
|
|
127
|
+
score += avaliarInlineStyles(srcCompleto, strengths, issues);
|
|
128
|
+
score += avaliarBreakpoints(srcCompleto, strengths, issues);
|
|
129
|
+
score += avaliarPseudoClasses(srcCompleto, strengths, issues);
|
|
130
|
+
score += avaliarDynamicStyles(srcCompleto, strengths, issues);
|
|
131
|
+
score += avaliarExtraction(srcCompleto, strengths, issues);
|
|
132
|
+
score += avaliarConditionalComplexity(srcCompleto, strengths, issues);
|
|
108
133
|
return {
|
|
109
134
|
score: Math.min(score, maxScore),
|
|
110
135
|
maxScore,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Padrões compartilhados para detecção CSS-in-JS
|
|
3
|
+
// Usa construção dinâmica para evitar falso positivo em auto-análise
|
|
4
|
+
const IMPORTANT_CHAR = String.fromCharCode(33);
|
|
5
|
+
export const IMPORTANT_PATTERN = new RegExp(`${IMPORTANT_CHAR}important`);
|
|
6
|
+
export const IMPORTANT_GLOBAL = new RegExp(`${IMPORTANT_CHAR}important`, 'g');
|
|
7
|
+
export const IMPORTANT_WS_GLOBAL = new RegExp(`\\s*${IMPORTANT_CHAR}important`, 'g');
|
|
@@ -2,6 +2,91 @@ import * as path from 'path';
|
|
|
2
2
|
import { traverse } from '../../core/config/index.js';
|
|
3
3
|
import { messages } from '../../core/messages/index.js';
|
|
4
4
|
import { criarOcorrencia } from '../../types/index.js';
|
|
5
|
+
const CONFIANCA_ACOPLAMENTO = 60;
|
|
6
|
+
async function reportarCaracteristicas(analiseCompleta, contexto, ocorrencias, relPath) {
|
|
7
|
+
if ((analiseCompleta.caracteristicas?.length ?? 0) === 0) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (typeof contexto.report === 'function') {
|
|
11
|
+
contexto.report({
|
|
12
|
+
code: 'ARQ_CARACTERISTICAS',
|
|
13
|
+
tipo: 'caracteristicas-arquitetura',
|
|
14
|
+
nivel: 'info',
|
|
15
|
+
relPath,
|
|
16
|
+
linha: 1,
|
|
17
|
+
data: {
|
|
18
|
+
caracteristicas: analiseCompleta.caracteristicas ?? []
|
|
19
|
+
},
|
|
20
|
+
origem: 'arquitetura'
|
|
21
|
+
});
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const { DetectorArquiteturaMensagens } = await import('../../core/messages/pt/analysts/detector-architecture-messages.js');
|
|
25
|
+
ocorrencias.push(criarOcorrencia({
|
|
26
|
+
tipo: 'caracteristicas-arquitetura',
|
|
27
|
+
nivel: 'info',
|
|
28
|
+
mensagem: DetectorArquiteturaMensagens.caracteristicas(analiseCompleta.caracteristicas ?? []),
|
|
29
|
+
relPath,
|
|
30
|
+
linha: 1
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
33
|
+
async function reportarViolacoes(analiseCompleta, contexto, ocorrencias, relPath) {
|
|
34
|
+
for (const violacao of (analiseCompleta.violacoes ?? []).slice(0, 3)) {
|
|
35
|
+
if (typeof contexto.report === 'function') {
|
|
36
|
+
contexto.report({
|
|
37
|
+
code: 'ARQ_VIOLACAO',
|
|
38
|
+
tipo: 'violacao-arquitetura',
|
|
39
|
+
nivel: 'aviso',
|
|
40
|
+
relPath,
|
|
41
|
+
linha: 1,
|
|
42
|
+
data: { violacao },
|
|
43
|
+
origem: 'arquitetura'
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const { DetectorArquiteturaMensagens } = await import('../../core/messages/pt/analysts/detector-architecture-messages.js');
|
|
48
|
+
ocorrencias.push(criarOcorrencia({
|
|
49
|
+
tipo: 'violacao-arquitetura',
|
|
50
|
+
nivel: 'aviso',
|
|
51
|
+
mensagem: DetectorArquiteturaMensagens.violacao(violacao),
|
|
52
|
+
relPath,
|
|
53
|
+
linha: 1
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function reportarMetricas(analiseCompleta, contexto, ocorrencias, relPath) {
|
|
59
|
+
const metricas = analiseCompleta.metricas;
|
|
60
|
+
if (!metricas || typeof metricas !== 'object' || !('acoplamento' in metricas) || !('coesao' in metricas)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if ((metricas.acoplamento ?? 0) <= 0.7 && (metricas.coesao ?? 1) >= 0.3) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (typeof contexto.report === 'function') {
|
|
67
|
+
contexto.report({
|
|
68
|
+
code: 'ARQ_METRICAS',
|
|
69
|
+
tipo: 'metricas-arquitetura',
|
|
70
|
+
nivel: 'aviso',
|
|
71
|
+
relPath,
|
|
72
|
+
linha: 1,
|
|
73
|
+
data: {
|
|
74
|
+
acoplamento: metricas.acoplamento ?? 0,
|
|
75
|
+
coesao: metricas.coesao ?? 0
|
|
76
|
+
},
|
|
77
|
+
origem: 'arquitetura'
|
|
78
|
+
});
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const { DetectorArquiteturaMensagens } = await import('../../core/messages/pt/analysts/detector-architecture-messages.js');
|
|
82
|
+
ocorrencias.push(criarOcorrencia({
|
|
83
|
+
tipo: 'metricas-arquitetura',
|
|
84
|
+
nivel: 'aviso',
|
|
85
|
+
mensagem: DetectorArquiteturaMensagens.metricas(metricas.acoplamento ?? 0, metricas.coesao ?? 0),
|
|
86
|
+
relPath,
|
|
87
|
+
linha: 1
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
5
90
|
export const analistaArquitetura = {
|
|
6
91
|
nome: 'arquitetura',
|
|
7
92
|
categoria: 'estrutura',
|
|
@@ -72,88 +157,9 @@ export const analistaArquitetura = {
|
|
|
72
157
|
linha: 1
|
|
73
158
|
}));
|
|
74
159
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
contexto.report({
|
|
79
|
-
code: 'ARQ_CARACTERISTICAS',
|
|
80
|
-
tipo: 'caracteristicas-arquitetura',
|
|
81
|
-
nivel: 'info',
|
|
82
|
-
relPath,
|
|
83
|
-
linha: 1,
|
|
84
|
-
data: {
|
|
85
|
-
caracteristicas: analiseCompleta.caracteristicas ?? []
|
|
86
|
-
},
|
|
87
|
-
origem: 'arquitetura'
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
const { DetectorArquiteturaMensagens } = await import('../../core/messages/pt/analysts/detector-architecture-messages.js');
|
|
92
|
-
ocorrencias.push(criarOcorrencia({
|
|
93
|
-
tipo: 'caracteristicas-arquitetura',
|
|
94
|
-
nivel: 'info',
|
|
95
|
-
mensagem: DetectorArquiteturaMensagens.caracteristicas(analiseCompleta.caracteristicas ?? []),
|
|
96
|
-
relPath,
|
|
97
|
-
linha: 1
|
|
98
|
-
}));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// Relatório de violações
|
|
102
|
-
for (const violacao of (analiseCompleta.violacoes ?? []).slice(0, 3)) {
|
|
103
|
-
if (typeof contexto.report === 'function') {
|
|
104
|
-
contexto.report({
|
|
105
|
-
code: 'ARQ_VIOLACAO',
|
|
106
|
-
tipo: 'violacao-arquitetura',
|
|
107
|
-
nivel: 'aviso',
|
|
108
|
-
relPath,
|
|
109
|
-
linha: 1,
|
|
110
|
-
data: {
|
|
111
|
-
violacao
|
|
112
|
-
},
|
|
113
|
-
origem: 'arquitetura'
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
const { DetectorArquiteturaMensagens } = await import('../../core/messages/pt/analysts/detector-architecture-messages.js');
|
|
118
|
-
ocorrencias.push(criarOcorrencia({
|
|
119
|
-
tipo: 'violacao-arquitetura',
|
|
120
|
-
nivel: 'aviso',
|
|
121
|
-
mensagem: DetectorArquiteturaMensagens.violacao(violacao),
|
|
122
|
-
relPath,
|
|
123
|
-
linha: 1
|
|
124
|
-
}));
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Métricas de qualidade
|
|
128
|
-
const metricas = analiseCompleta.metricas;
|
|
129
|
-
if (metricas && typeof metricas === 'object' && 'acoplamento' in metricas && 'coesao' in metricas) {
|
|
130
|
-
if ((metricas.acoplamento ?? 0) > 0.7 || (metricas.coesao ?? 1) < 0.3) {
|
|
131
|
-
if (typeof contexto.report === 'function') {
|
|
132
|
-
contexto.report({
|
|
133
|
-
code: 'ARQ_METRICAS',
|
|
134
|
-
tipo: 'metricas-arquitetura',
|
|
135
|
-
nivel: 'aviso',
|
|
136
|
-
relPath,
|
|
137
|
-
linha: 1,
|
|
138
|
-
data: {
|
|
139
|
-
acoplamento: metricas.acoplamento ?? 0,
|
|
140
|
-
coesao: metricas.coesao ?? 0
|
|
141
|
-
},
|
|
142
|
-
origem: 'arquitetura'
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
const { DetectorArquiteturaMensagens } = await import('../../core/messages/pt/analysts/detector-architecture-messages.js');
|
|
147
|
-
ocorrencias.push(criarOcorrencia({
|
|
148
|
-
tipo: 'metricas-arquitetura',
|
|
149
|
-
nivel: 'aviso',
|
|
150
|
-
mensagem: DetectorArquiteturaMensagens.metricas(metricas.acoplamento ?? 0, metricas.coesao ?? 0),
|
|
151
|
-
relPath,
|
|
152
|
-
linha: 1
|
|
153
|
-
}));
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
160
|
+
await reportarCaracteristicas(analiseCompleta, contexto, ocorrencias, relPath);
|
|
161
|
+
await reportarViolacoes(analiseCompleta, contexto, ocorrencias, relPath);
|
|
162
|
+
await reportarMetricas(analiseCompleta, contexto, ocorrencias, relPath);
|
|
157
163
|
return ocorrencias;
|
|
158
164
|
}
|
|
159
165
|
catch (erro) {
|
|
@@ -232,10 +238,10 @@ function analisarArquivo(ast, relPath, _src) {
|
|
|
232
238
|
tipo: 'named'
|
|
233
239
|
});
|
|
234
240
|
}
|
|
235
|
-
else if ('declarations' in decl
|
|
241
|
+
else if ('declarations' in decl) {
|
|
236
242
|
// export const a = ..., b = ...
|
|
237
243
|
for (const declarator of decl.declarations) {
|
|
238
|
-
if (
|
|
244
|
+
if ('name' in declarator.id) {
|
|
239
245
|
exports.push({
|
|
240
246
|
nome: declarator.id.name,
|
|
241
247
|
tipo: 'named'
|
|
@@ -390,7 +396,7 @@ function detectarPadraoArquitetural(estatisticas) {
|
|
|
390
396
|
if (temDependenciasCirculares) {
|
|
391
397
|
return {
|
|
392
398
|
tipo: 'Arquitetura com Problemas de Acoplamento',
|
|
393
|
-
confianca:
|
|
399
|
+
confianca: CONFIANCA_ACOPLAMENTO
|
|
394
400
|
};
|
|
395
401
|
}
|
|
396
402
|
return {
|
|
@@ -21,7 +21,7 @@ const BUG_PATTERNS = [
|
|
|
21
21
|
for (const m of matches) {
|
|
22
22
|
return {
|
|
23
23
|
confidence: 0.85,
|
|
24
|
-
line: contarLinhasAtePos(content, m.index
|
|
24
|
+
line: contarLinhasAtePos(content, m.index),
|
|
25
25
|
message: `Possível null pointer dereference: ${m[0].slice(0, MAX_MESSAGE_PREVIEW_LENGTH)}`,
|
|
26
26
|
suggestion: 'Verificar se o resultado é null/undefined antes de encadear métodos',
|
|
27
27
|
};
|
|
@@ -31,12 +31,12 @@ const BUG_PATTERNS = [
|
|
|
31
31
|
let match;
|
|
32
32
|
while ((match = optionalChainPattern.exec(content)) !== null) {
|
|
33
33
|
const [, varName, funcName] = match;
|
|
34
|
-
const line = contarLinhasAtePos(content, match.index);
|
|
35
34
|
const beforeContent = content.slice(Math.max(0, match.index - 120), match.index);
|
|
36
35
|
// pop() é seguro em qualquer array - retorna undefined se vazio, nunca lança
|
|
37
36
|
if (funcName === 'pop') {
|
|
38
37
|
continue;
|
|
39
38
|
}
|
|
39
|
+
const line = contarLinhasAtePos(content, match.index);
|
|
40
40
|
// Verificar se a variável é garantidamente um array (const = [] ou const = [...])
|
|
41
41
|
const varDeclaration = content.slice(Math.max(0, match.index - 200), match.index);
|
|
42
42
|
if (new RegExp(`(const|let|var)\\s+${varName}\\s*=\\s*\\[`).test(varDeclaration)) {
|
|
@@ -75,7 +75,7 @@ const BUG_PATTERNS = [
|
|
|
75
75
|
for (const pattern of patterns) {
|
|
76
76
|
const matches = content.matchAll(pattern);
|
|
77
77
|
for (const m of matches) {
|
|
78
|
-
const line = contarLinhasAtePos(content, m.index
|
|
78
|
+
const line = contarLinhasAtePos(content, m.index);
|
|
79
79
|
if (!hasCleanup(content, line)) {
|
|
80
80
|
return {
|
|
81
81
|
confidence: 0.82,
|
|
@@ -104,7 +104,7 @@ const BUG_PATTERNS = [
|
|
|
104
104
|
for (const pattern of asyncPatterns) {
|
|
105
105
|
const matches = content.matchAll(pattern);
|
|
106
106
|
for (const m of matches) {
|
|
107
|
-
const line = contarLinhasAtePos(content, m.index
|
|
107
|
+
const line = contarLinhasAtePos(content, m.index);
|
|
108
108
|
if (hasSharedState(content, line)) {
|
|
109
109
|
return {
|
|
110
110
|
confidence: 0.78,
|
|
@@ -133,7 +133,7 @@ const BUG_PATTERNS = [
|
|
|
133
133
|
for (const pattern of patterns) {
|
|
134
134
|
const matches = content.matchAll(pattern);
|
|
135
135
|
for (const m of matches) {
|
|
136
|
-
const line = contarLinhasAtePos(content, m.index
|
|
136
|
+
const line = contarLinhasAtePos(content, m.index);
|
|
137
137
|
if (!hasValidation(content, line)) {
|
|
138
138
|
return {
|
|
139
139
|
confidence: 0.72,
|
|
@@ -157,7 +157,7 @@ const BUG_PATTERNS = [
|
|
|
157
157
|
const pattern = /(?<![.\w])new\s+Promise\s*\([^)]*\)(?![^]*\.(then|catch|finally)\s*\()/g;
|
|
158
158
|
const matches = content.matchAll(pattern);
|
|
159
159
|
for (const m of matches) {
|
|
160
|
-
const line = contarLinhasAtePos(content, m.index
|
|
160
|
+
const line = contarLinhasAtePos(content, m.index);
|
|
161
161
|
const beforeContent = content.slice(Math.max(0, m.index - 20), m.index);
|
|
162
162
|
if (/\b(await|return)\s+/.test(beforeContent)) {
|
|
163
163
|
continue;
|
|
@@ -220,7 +220,7 @@ const BUG_PATTERNS = [
|
|
|
220
220
|
const matches = content.matchAll(magicNumPattern);
|
|
221
221
|
const results = [];
|
|
222
222
|
for (const m of matches) {
|
|
223
|
-
const line = contarLinhasAtePos(content, m.index
|
|
223
|
+
const line = contarLinhasAtePos(content, m.index);
|
|
224
224
|
const lineContent = content.split('\n')[line - 1] || '';
|
|
225
225
|
if (!lineContent.includes('const') && !lineContent.includes('let') && !lineContent.includes('var') && !lineContent.includes('//') && !lineContent.includes('/*')) {
|
|
226
226
|
results.push({
|
|
@@ -252,7 +252,7 @@ const BUG_PATTERNS = [
|
|
|
252
252
|
for (const pattern of patterns) {
|
|
253
253
|
const matches = content.matchAll(pattern);
|
|
254
254
|
for (const m of matches) {
|
|
255
|
-
const line = contarLinhasAtePos(content, m.index
|
|
255
|
+
const line = contarLinhasAtePos(content, m.index);
|
|
256
256
|
return {
|
|
257
257
|
confidence: 0.88,
|
|
258
258
|
line,
|
|
@@ -445,6 +445,26 @@ function hasValidation(content, _line) {
|
|
|
445
445
|
function contarLinhasAtePos(content, pos) {
|
|
446
446
|
return content.slice(0, pos).split('\n').length;
|
|
447
447
|
}
|
|
448
|
+
function detectarPadroesBug(src, relPath, ocorrencias) {
|
|
449
|
+
for (const pattern of BUG_PATTERNS) {
|
|
450
|
+
try {
|
|
451
|
+
const match = pattern.detect(src, relPath);
|
|
452
|
+
if (match && match.confidence > 0.5) {
|
|
453
|
+
const nivel = pattern.severity === 'erro' && match.confidence > 0.8 ? 'erro' : pattern.severity;
|
|
454
|
+
ocorrencias.push({
|
|
455
|
+
tipo: `ml-${pattern.id}`,
|
|
456
|
+
nivel,
|
|
457
|
+
mensagem: getMessages().BugMlMensagens.mlPattern((match.confidence * 100).toFixed(0), match.message),
|
|
458
|
+
origem: 'detector-bugs-ml',
|
|
459
|
+
relPath,
|
|
460
|
+
linha: match.line ?? 0,
|
|
461
|
+
sugestao: match.suggestion,
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
catch { }
|
|
466
|
+
}
|
|
467
|
+
}
|
|
448
468
|
export const detectorBugsMl = {
|
|
449
469
|
nome: 'detector-bugs-ml',
|
|
450
470
|
global: false,
|
|
@@ -473,25 +493,7 @@ export const detectorBugsMl = {
|
|
|
473
493
|
linha: 0,
|
|
474
494
|
});
|
|
475
495
|
}
|
|
476
|
-
|
|
477
|
-
for (const pattern of BUG_PATTERNS) {
|
|
478
|
-
try {
|
|
479
|
-
const match = pattern.detect(src, relPath);
|
|
480
|
-
if (match && match.confidence > 0.5) {
|
|
481
|
-
const nivel = pattern.severity === 'erro' && match.confidence > 0.8 ? 'erro' : pattern.severity;
|
|
482
|
-
ocorrencias.push({
|
|
483
|
-
tipo: `ml-${pattern.id}`,
|
|
484
|
-
nivel,
|
|
485
|
-
mensagem: getMessages().BugMlMensagens.mlPattern((match.confidence * 100).toFixed(0), match.message),
|
|
486
|
-
origem: 'detector-bugs-ml',
|
|
487
|
-
relPath,
|
|
488
|
-
linha: match.line ?? 0,
|
|
489
|
-
sugestao: match.suggestion,
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
catch { }
|
|
494
|
-
}
|
|
496
|
+
detectarPadroesBug(src, relPath, ocorrencias);
|
|
495
497
|
return ocorrencias;
|
|
496
498
|
},
|
|
497
499
|
};
|